download
Accepting incoming connections
Introduction
------------
This paper is part of the "Zorp Anatomy" series of articles and as such it
gives some background information about one or more Zorp subsystems. It is
intended for advanced Zorp users, those interested in what behind the scene
is.
Incoming connections
--------------------
Zorp opens one or more ports using its Dispatch subsystem (see the article
about the Dispatch framework for more details). When a new connection is
accepted on one of these open ports the dispatch subsystem decides whether
the connection is expected by one of the running proxies (RELATED
connections), or it is to be processed as a secondary session of one of the
running proxies (SECONDARY connections) or as a last resort a new proxy is
started.
This paper focuses on how new proxies are started, related and secondary
connections are detailed in the article mentioned above.
Listener, the reaction to a new connection
------------------------------------------
When the Zorp core accepts a new connection, it indicates this fact by
calling the 'accepted' method of the Listener which opened the port. This
accepted method is implemented in Python and can be found in the file
Dispatch.py in the class named Dispatcher (all Listeners and Receivers have
this Dispatcher class in their inheritance).
This accepted method gets the following information about the new connection
as arguments:
- stream: an object representing a duplex data pipe (a TCP/UDP connection in
this case), will be passed to the proxy as its client side
- client_address: the socket address representing the client (for IPv4 a
socket address is an IP/port pair)
- client_local: the socket address the client was trying to connect to (for
transparent services it is the transparent destination)
- client_listen: the socket address where this listener was bound to
The accepted method then creates a new session object, looks up the client
zone, decides which service to start (simple listeners always start the same
service, more complex ones like CSZoneListener look up the service based on
client/server address), then continues processing using the chosen service:
1) calls the associated Router to decide the method used for routing
(Transparent, Directed, etc)
2) checks access control whether the connection is permitted to leave the
zone of the client (the outbound_services set for the zone)
3) starts a new service instance by calling Service.startInstance()
Service classes
---------------
The service class is one of the most seen classes in Zorp configuration as
the administrator defines each service by setting various arguments to the
Service constructor. The role of the service class is exactly this: keeping
all service related information (name, proxy, NAT, authentication, routing,
chaining etc) at one single place.
Session classes
---------------
While Service objects keep all parameters related to a given service in
general, Session objects more exactly the Session object hierarchy keeps all
session related information like: client address/port/zone, server
address/port/zone etc.
Sessions are structured in a similar way how proxies can be structured: in a
hierarchy. On the top of the hierarchy a MasterSession object is present
which is created immediately as an incoming connection is established, it is
filled with information about the client connection. When a proxy is added
to the stack (this includes the topmost proxy as well) a StackedSession
instance is added to the session hierarchy.
The information stored in the Session hierarchy is inherited, e.g.
client_address stored in the topmost session object can be 'seen' when
referring it as the attribute of the session object at the bottom. Writes to
the session objects at a specific level however does not propagate upwards,
when an attribute is changed in the middle upper levels are not changed,
lower levels however can 'see' the changes.
This property makes session a good place for data exchange. Additional
attributes can be added to make inter-proxy communication possible.
NOTE: Zorp 2.1 introduced callback based communication in the C layer, thus
it is not absolutely necessary to use Session as the communication medium.
However it is still very useful when we create customized cooperating proxy
classes.
Router classes
--------------
The routing decision is made by instances of classes derived from the
AbstractRouter class. The role of the routing decision is to define the
parameters of the server side connection:
* The server side local address, e.g. the address used by the firewall as a source
* The server side remote address, e.g. the address of the server
The following router classes are available:
* TransparentRouter specifies that the original destination is to be used as
server address.
* DirectedRouter specifies a given destination, the proxy will be
connected to this destination regardless of what the original destination was
* InbandRouter specifies that the proxy will decide the real destination
The decision of the Router can be modified by the NAT mechanisms later, as
described in the "Establishing server connections" article.
The role of the Service object in connection startup
----------------------------------------------------
In connection startup startInstance method of the Service object is used to
start a new proxy after checking various parameters (like parallel
connection limit). Starting a new proxy is easy: a new instance of the class
representing the proxy must be created. This implicitly results in the proxy
being loaded from the external shared object if needed, a new proxy thread
being started and the proxy to start processing, based on the incoming
parameters.
|