Proxy Server

advertisement
Abstract
This document presents the concepts of frameworks and proxies and the work done during the
mini-project involving development of a framework for proxy servers.
The objective of this project is to develop a framework for creating proxy servers. After
analyzing several different proxy servers, our group found HTTP/TCP port-forwarding the most
interesting kind of proxy application for this project. For port-forwarding proxies, we were able
to find enough resources in terms of Java code without existing frameworks and an
understandable reusable design.
We achieved the white-box framework in the first iteration by synthesizing abstract classes from
the code. In the second iteration we converted the abstract classes into interfaces, resulting in a
black-box framework. The third iteration required no modification of the framework and served
as a validation of the black-box framework that was built at the end of the second iteration.
This project helped us understand the steps involved in developing frameworks from existing
reusable code and progressing from white-box to gray-box to black-box level. We were also able
to extend our knowledge of design patterns by using patterns such as Factory, Singleton,
Mediator, Adapter, Bridge and Observer. Fault tolerance techniques were applied to the code
through recoverable exception handling and error checking.
Abstract .......................................................................................................................................................... 1
Introduction ................................................................................................................................................... 3
Frameworks: ............................................................................................................................................. 3
Proxy Server: ............................................................................................................................................ 4
Proxy-Server-to-Proxy-Server Linking: Port-Forwarding Proxy servers ................................................ 5
Design Patterns ......................................................................................................................................... 7
Fault-tolerance: ........................................................................................................................................ 7
Original Port-forwarding proxies ................................................................................................................. 9
ProxyServerJ Proxy application ............................................................................................................. 9
TCP Reflector Proxy application .......................................................................................................... 10
Dodgy TCP Port forwarding proxy ...................................................................................................... 11
Frameworks and their UML diagrams ....................................................................................................... 12
Development of Framework 1 ............................................................................................................... 12
Development of Framework 2 ............................................................................................................... 13
Development of Framework 3: .............................................................................................................. 15
UML Diagrams for applications with their frameworks: ........................................................................... 16
Conclusion ................................................................................................................................................... 22
Sources of the original proxy code .............................................................................................................. 23
Introduction
Our goal was to create a framework that would enable reuse of domain-specific design and code
for proxy servers. Three port-forwarding proxy servers were chosen and the entire development
involved three iterations, going progressively from white-box to black-box framework. We also
applied design patterns and fault-tolerance techniques to our frameworks. This document also
contains the Unified Modeling Language (UML) diagrams from each stage of development.
Frameworks:
A framework is a set of classes that embodies an abstract design for solutions to a family of
related domain-specific problems and supports reuse at a larger level of granularity than classes.
Frameworks allow a collection of objects to serve as a template solution or a semi-complete
application.
The application specific logic “plugs” into the framework through a set of interfaces. A
framework provides inversion of control, implying that the framework calls the application
specific code.
Frameworks are ideally suited for capturing the common features in a product family. The
abstraction is at such a high level that bulk of the functionality is captured in the framework and
each application is an extension of the framework.
A framework provides a reusable architecture for a family of applications from a particular
domain. With frameworks, the principle of reuse is applied to whole applications or sub-systems,
so that the effort required to develop a new application is limited to the difference in
functionality between the particular application and the rest of the family.
A good framework captures a good underlying design and it can reduce the cost of developing an
application by an order of magnitude because it lets you reuse both design and code. However,
developing a good framework could be expensive. Hence a framework must be simple enough to
be learned and yet must provide enough features so that it can be used quickly.
Frameworks evolve from "white-box" to "black-box." An intermediate stage between the two is
referred to as the gray-box framework.
A white-box framework permits creation of new classes by changing the abstract classes that
form the core of the framework. A thorough understanding of the hierarchical structure and
source code is important for implementing application specific logic with a white-box
framework.
A black-box framework permits plugging in the application specific logic that confirms to the
pre-defined interface or protocol. The application specific logic does not change the framework
and it does not make any new concrete subclasses to utilize the framework.
The gray-box framework is between the two extremes. To use a gray-box framework, new
concrete sub-classes must be defined and used to build the application. The subclasses are rightly
coupled to super-classes and the sub-classes must meet the interface specified by the superclasses. The programmer must understand the framework’s interfaces in detail.
Initial framework designs may be acceptable for single applications. However, the ability to
generalize for a family of applications can only come by actually building the applications and
determining which abstractions are being reused across the applications. Generalizing from a
single application rarely happens. This is the reason we could achieve only a white-box
framework in the first iteration.
It is much easier to generalize from two applications, but it is still difficult. Provided that all of
the applications fall within the problem domain, common abstractions will become apparent in a
few iterations.
We were able to extract common functionalities from the first two applications and define a
tentative standard interface for port-forwarding proxies. Fortunately, the third port-forwarding
proxy server application had features very similar to the first two applications. Thus the third
iteration validated our interface, leading to the success of our black-box framework for the given
set of three applications.
A framework can be expected to evolve, especially if the application domain is not as specific as
“port-forwarding proxy servers”. If the problem domain has an infinite horizon, the framework
development might continue to evolve until all potential applications have been analyzed and
their features incorporated into the framework.
Proxy Server:
A proxy server is a specialized server that listens for requests from clients and forwards these
requests to remote Internet servers. The proxy server reads responses from the external servers
and then sends them to internal clients. Clients using a proxy server feel as if they are getting
responses directly from remote servers.
For a client application (such as a browser) to use a proxy server, it must channel Internet
requests through the proxy server. Most browsers allow configuration, so that they direct
requests through a proxy server. Depending on the browser, you can identify a proxy server by
identifying the server’s domain name or IP address. However, browsers must be individually
configured on the subnet to look for the proxy server and send their requests to it.
The proxy server acts as both a server system and a client system. It is a server when accepting
HTTP requests from browsers and it acts as a client system when the browser connects to remote
servers to retrieve documents.
Proxy-Server-to-Proxy-Server Linking: Port-Forwarding Proxy servers
Chaining proxy servers provides an extra level of indirection and is particularly applicable when
groups of clients need to be configured as per different policies. This involves setting up an outer
level proxy that connects directly to the Internet and several inner level proxies that form the link
between the clients and the outer-level proxy. Any access restrictions set for the external
(organizational) proxy server take precedence over access restrictions set for the internal
(departmental) proxy servers.
Port forwarding works by creating a proxy server for a source port that a TCP service uses. The
proxy server waits on the local machine for a connection from a client program to the source
port.
Design Patterns
Design patterns systematically names, motivates and explains a general design that addresses a
recurring design problem in object-oriented systems. It describes the problem, the solution, when
to apply the solution, and its consequences. It also gives implementation hints and examples. The
solution is a general arrangement of objects and classes that solve the problem. The solution is
customized and implemented to solve the problem in a particular context.
We implemented a few of the design patterns –
Factory Method: Defines and interface for creating an object, but let subclasses decide which
class to instantiate. The Factory Method lets a class defer instantiation to subclasses.
Singleton: Ensures that a class has only one instance and it provides a global point of access to it.
Adapter: Converts the interface of a class into another interface that clients expect. It lets the
classes work together that couldn’t otherwise because of incompatible interfaces.
Bridge: It decouples the abstraction from its implementation so that the two can vary
independently.
Mediator: It defines an object that encapsulates how a set of objects interacts. It promotes loose
coupling by keeping objects from referring to each other explicitly and it lets you vary their
interaction independently.
Observer: It defines a one-to-many dependency between objects so that when one object changes
its state, all its dependents are notified and updated automatically.
Fault-tolerance:
A fault is defined as a condition that might lead to a failure.
Failure is a malfunction in the system.
An error is an incorrect or undesired response from the system that indicates a fault is present.
Fault tolerance involves fault detection, confinement, diagnosis and recovery.
The third framework and any plugged proxy application have been made fault-tolerant to the
level of minimal performance.
Faults in the system are enclosed within exception handling code that detects and recovers from
errors, thereby preventing the system from complete failure.
The proxy applications are all port-forwarding, but the client applications such as browsers may
request documents through different protocols such as HTTP, FTP, telnet, etc that connect
through different ports. The framework takes care of wrong port numbers and restricts the proxy
applications to the desired operation.
UML Diagrams
The Unified Modeling Language (UML) defines a set of diagrams that represent different aspects
of the software system under design. The UML notation is defined for both static and dynamic
views of the system.
A Class diagrams is a collection of static declarative model elements that represent the objectoriented classes and the relationships (such as associations, generalizations and aggregations)
between the classes.
Original Port-forwarding proxies
ProxyServerJ Proxy application
This is a Java based HTTP proxy server. It allows multiple users to share single Internet
connection. It performs generic port forwarding to another server.
UML diagram for ProxyServerJ application
The proxy saves the current configuration to a disk file, so it does not have to request the user to
re-enter the data on the next run.
We analyzed the classes in this application and found it suited to our requirement. We started
work on our first proxy by identifying the common operation shown by this proxy application.
To run this proxy, we need to provide the hostname, the remote port and the local port. The
proxy application provides a graphical user interface to accept the configuration from the user. It
saves this configuration to the persistent storage so the user does not require to re-enter the
configuration information on each run. In short, this application has a user-oriented interface
design.
TCP Reflector Proxy application
A multithreaded java class that allows you to redirect all connections to a particular machine and
port to another machine and port.
UML diagram for TCP Reflector proxy application
This proxy application is used to talk to a socket not located on the host from which it is served.
The TCPReflector must be run on a known port and it must be set up to connect the host and port
required by the application. The TCPReflector will behave as if the application has a direct
connection to that remote host and port.
This proxy requires the user to provide the local and remote port numbers and the host IP address
on the command line as switches. It is capable of accepting a few more advanced parameters, but
can work with the minimal switches such as –port and –server.
Dodgy TCP Port forwarding proxy
This is a port forwarding proxy that works at the TCP level. It forwards the data to the external
proxy over the same TCP connection.
The original proxy does not work correctly with Windows 95 systems. The forwarded telnet or
ssh sessions will just lock up randomly, although the underlying session is actually still open.
The terminal just stops redrawing.
UML diagram for Dodgy TCP port-forwarding proxy
This proxy application requires the user to provide the local and remote port information on the
command line. However the application relies on the sequence of the command line parameters
rather than switches.
Frameworks and their UML diagrams
Development of Framework 1
This is a white box framework.
The application class inherits from the FWProxy, which is an abstract class providing a skeleton
implementation of a proxy. The application needs to provide two things - the configuration
information and the connection handler.
The configuration information is obtained using a graphical user interface for the first proxy
application called ProxyServerJ. The user provides the configuration.
The proxy provides a base connection handler that can be used by the application.
We extracted the common classes, the server classes and the connection handling classes from
the original proxy application and incorporated them into the set of abstract classes forming the
framework. The application is responsible for collecting the connection information.
UML diagram for Framework 1
(whitebox)
Development of Framework 2
This is a black box framework and unlike Framework 1, this one uses interfaces.
We derived most of the interfaces after analyzing the TCP reflector proxy. This is because TCP
reflector provides a better implementation of the connection handling and proxy server than the
previous application.
UML diagram for Framework 2
(blackbox)
The FWProxy contains an implementation of the Mediator design pattern since it encapsulates
how the set of applications interact. It promotes loose coupling certain components of the
framework interface and lets the interaction of the proxies vary independent of each other.
FWProxy also provides a Factory design pattern that automatically identifies the application
proxy in the current folder and instantiates the corresponding object. The proxy uses reflection
mechanism to find out which class corresponding to the application uses the FWProxyInterface.
This is necessary to keep the main function within the framework, which is one of the important
properties of the framework. This is an implementation similar to the Adapter design pattern
because it lets classes having different interfaces to work with the framework.
Any proxy application being used by this framework needs to know two interfaces to make use
of this framework. These interfaces are FWProxyInterface and FWConnectionMonitorInterface.
This set of two interfaces are implemented using the Bridge design pattern. It decouples the
abstraction from its implementation so that the two can vary independently.
FWProxyInterface is used to provide the proxy with information such as the connection
configuration and FWConnectionMonitorInterface is used to receive and send events.
Implementing the FWConnectionMonitorInterface is optional. The application may choose to
implement this interface if it is required to perform tasks such as opening a connection, cleaning
a connection and closing the connection.
The FWConfig class contains the proxy configuration. This class implements the Singleton
design pattern.
Part of the configuration such as the localhost, port and server information is provided by the
application.
FWAgent handles the data transfer from the client to the server and from the server to the client.
Each of these agents is an independent thread. Whenever the connection is terminated, the
FWAgent informs the corresponding FWProxyServer which closes the socket and stream.
FWAgent contains an implementation of the Observer design pattern. It defines a dependency so
that when one object changes state, it notifies the dependents automatically.
Development of Framework 3:
This is also a black-box framework with very little change from the second framework.
UML diagram for Framework 3
(blackbox)
Additional fault tolerance techniques have been implemented. It involves a few load-balancing
features. It also prints the usage information and error messages.
This framework prevents the proxies from disrupting the working of the system and provides
recoverable error checking so that the system can continue to work with degraded level of
service.
UML Diagrams for applications with their frameworks:
UML Diagram for ProxyServerJ application with Framework 1 (white-box)
We found that the first iteration consumed a lot of resources. It involved extracting what looked
like the universal features of the application domain and gathering these features in an
abstraction. The second stage required lesser time than the first and the third iteration required
very little time. We came to the conclusion that frameworks should be developed only when
many applications are going to be developed within a specific problem domain, allowing the time
savings of reuse to recover the time invested to develop them.
UML Diagram for ProxyServerJ application with Framework 2 (black-box)
UML Diagram for TCP Reflector proxy application with Framework 2 (black-box)
UML Diagram for ProxyServerJ application with Framework 3
(black-box framework with fault-tolerance features)
UML Diagram for TCPReflector application with Framework 3
(black-box framework with fault-tolerance features)
UML Diagram for Dodgy TCP port-forwarding proxy application with Framework 3
(black-box framework with fault-tolerance features)
Conclusion
We found that the first iteration consumed a lot of resources. It involved extracting what looked
like the universal features of the application domain and gathering these features in an
abstraction. The second stage required lesser time than the first and the third iteration required
very little time.
We came to the conclusion that frameworks should be developed only when many applications
are going to be developed within a specific problem domain, allowing the time-saving from reuse
to recover the time invested to develop them. We also realized that the current black-box
framework might not suit some other proxy implementations. Hence this framework must be
flexible enough to accommodate more proxies. We provided hooks within our framework for
future extensions.
This project also helped us understand a few more design patterns not done as part of the class
exercises. We incorporated fault-tolerance and recoverable exception handling into our final
framework.
Sources of the original proxy code
ProxyServerJ proxy code
http://members.home.net/vladimirl/ProxyServerJ.html
TCP Reflector proxy code
http://208.223.9.21/jfd/java/tcp/tcp/html
Dodgy TCP port-forwarding proxy code
http://www.mooh.org/public/proxy
Download