HttpProxy is a wrapper class for the built in Http proxy implemented
in Zorp. It features both transparent and non-transparent modes
of operation, advanced filtering and more.
Setting policy for requests:
Changing the default behaviour of requests can be done using the
hash named "request". This hash is indexed by the method name
(e.g: GET or POST), and each item in this hash is a tuple, whose
first item is an integer value, determining the action to be
done with the request, and also the interpretation of the
remaining items in the tuple. All requests are denied by default in the low level proxy
implementation. The most common methods (GET, POST and HEAD)
are enabled from Python code.
Possible values for the first item:
-
HTTP_PASS
- allow request without modification
-
HTTP_DROP
- deny request (default)
-
HTTP_POLICY
- call the given function to decide what to do
this value uses an additional tuple item,
which must be a callable Python function.
The function must take four parameters:
self, method, url, version
Example:
class DmzHTTP(HttpProxy):
def config(self):
HttpProxy.config(self)
self.request["GET"] = (HTTP_POLICY, self.filterURL)
def self.filterURL(self, method, url, version):
if (url == "http://www.balabit.hu")
return Z_ACCEPT
return Z_DENY
Changing headers in requests or responses:
Both request headers and response headers can be modified
during transit. New header lines can be inserted, entries
can be modified or deleted. To change headers in the
request use the request_headers hash, for response headers
you need the response_headers hash. Similarly to the request hash, these hashes contain a
variable-length tuple, where the first item determines
the interpretation of the remaining items. The hash index
is the name of the header to be modified. Headers are not touched by default, except the "Host:",
"Connection:" and "Proxy-Connection" headers. However
the way these are modified can be changed here.
Possible values for the first item:
-
HTTP_PASS
- pass header without change, default for all headers
-
HTTP_DROP
- remove this header
-
HTTP_POLICY
- call the next tuple item, which must be
a Python function taking 3 parameters:
self, hdr_name, hdr_value
-
HTTP_CHANGE_NAME
- set header name to the next tuple item
-
HTTP_CHANGE_VALUE
- set header value to the next tuple item
-
HTTP_CHANGE_BOTH
- set header name and value to the next tuple items
-
HTTP_CHANGE_REGEXP
- FIXME: Not yet implemented.
-
HTTP_INSERT
- insert a new header defined by the next two
tuple items (name, value)
-
HTTP_REPLACE
- remove all existing occurences of this header
and insert this one instead.
Example:
class MyHttp(HttpProxy):
def config(self):
HttpProxy.config(self)
self.request_headers["User-Agent"] = (HTTP_CHANGE_VALUE, "Lynx 2.4.1")
self.request_headers["Cookie"] = (HTTP_POLICY, self.processCookies)
self.response_headers["Set-Cookie"] = (HTTP_DROP,)
def processCookies(self, name, value):
log("http.message", 7, "cookie: value=%s" % value,)
# you could change the current header in self.current_header_name
# or self.current_header_value, the current request url
# in self.request_url
return Z_DROP
Redirecting urls:
You can choose to either reject a set of urls, or redirect them to a local
mirror by changing some attributes during request processing. As a HTTP request comes in, normative policy chains are
processed (self.request, self.request_headers), where you
can install policy callbacks for certain events with the HTTP_POLICY
directive. Any of these callbacks may change the request_url attribute
which may result in a completely different url to be fetched.
Example:
class MyHttp(HttpProxy):
def config(self):
HttpProxy.config(self)
self.request["GET"] = (HTTP_POLICY, self.filterURL)
def filterURL(self, method, url, version):
self.request_url = "http://www.balabit.hu/"
Using parent proxies:
There are two things to checked to use parent proxies. First you have
to pick a chainer which makes the proxy connect to the parent proxy. The
two possibilities are InbandChainer(), or DirectedChainer(). The second thing to set is the parent_proxy and
parent_proxy_port attribute in the HttpProxy instance. Setting
these attributes results in proxy requests to be emitted to the
target server in either transparent or non-transparent mode. The parent proxy attributes can be set in both the
configuration phase (e.g. config() event), and later on a
per-request basis.
Example:
class MyHttp(HttpProxy):
def config(self):
HttpProxy.config(self)
self.parent_proxy = "proxy.balabit.hu"
self.parent_proxy_port = 3128