On Wed, Apr 16, 2003 at 05:24:44PM -0700, Peter Hicks wrote:
Hi,
I was wondering if someone could help me with setting up https proxying with zorp. I would like zorp to be able to proxy based on domain name, as I have a limited number of external IPs. I figured I could set up unlimited https servers on internalRFC1918 addresses and have zorp reverse proxy them.
https foo1.com(10.1.1.1) -> 192.168.1.5 https foo2.com(10.1.1.1) -> 192.168.1.6 https foo3.com(10.1.1.1) -> 192.168.1.7
Does this make sense?
I am still trying to get a handle on zorp's configuration files, so if you could include some examples, I would be very grateful.
yes, it perfectly does and it can be done without problems for HTTP. The encrypted version has a problem though, you can only show a single server certificate to clients as the certificate is show prior to the client sending the server name it wants to communicate with. An example for HTTP would be something like: class ReverseHostHttpProxy(HttpProxy): host_mapping = { 'foo1.com': '192.168.1.5', 'foo2.com': '192.168.1.6' } default_ip = '192.168.1.5'; def config(self): HttpProxy.config(self) self.request_headers["Host"] = (HTTP_HDR_POLICY, self.checkHostHeader) def checkHostHeader(self, name, value): # check the host header and set destination address # based on the header's value if self.host_mapping.has_key(value): self.session.server_address.ip_s = self.host_mapping[value] else: self.session.server_address.ip_s = self.default_ip # we don't need further hooks del self.request_headers["Host"] return HTTP_HDR_ACCEPT And you could use this class with a service definition like this: # instance definition def reverse_http(): Service("inter_HTTP_farm", ReverseHostHttpProxy, router=DirectedRouter(SockAddrInet('192.168.1.5', 80))) Listener(SockAddrInet('10.1.1.1', 80), "inter_HTTP_farm") For SSL traffic you would have to decide whether you want encrypted communication between the firewall and the server. If you trust the network between your server and the firewall at least as much as you trust the firewall you could transmit the traffic flow in cleartext, thus decreasing the load of both your servers (because they have to do no encryption) and the firewall (because it does not need to reencrypt traffic). Assuming cleartext on the trusted site is OK, you would have to do something like this: class ReverseUnwrapSSL(PsslProxy): def config(self): PsslProxy.config(self) self.client_cert_file = '/etc/zorp/serverfarm.crt' self.client_key_file = '/etc/zorp/serverfarm.key' self.client_need_ssl = TRUE self.server_need_ssl = FALSE def reverse_https(): Service("inter_HTTPS_farm", ReverseUnwrapSSL, chainer=SideStackChainer(ReverseHostHttpProxy), router=DirectedRouter(SockAddrInet('192.168.1.5', 443))) Listener(SockAddrInet('10.1.1.1', 443), "inter_HTTPS_farm") In this case we used a scenario when our proxies were stacked side-by-side, e.g. the server side of the SSL proxy was the HTTP proxy, and its server side was the server itself like this: +-----+ +------+ real client ----+ SSL +----+ HTTP +---- real server +-----+ +------+ This was needed because the HTTP was selecting its destination based on the Host header. If the target address would have been based on other things (like choose it transparently) we could have used the traditional stacking scenario: real client ----+ +---- real server | | +-------+ | SSL | +-+---+-+ | | +-------+ | HTTP | +-------+ Of course neither SSL nor HTTP differentiates between connections to real servers or other proxies. They are communicating with the abstract Stream interface. A funnier scenario that represents the power of stacking even more is when you have a non-transparent HTTP proxy, where clients request CONNECT to cross the firewall: real client ----+ +---- real server | | +-------+ | HTTP | non-transparent HTTP +-+---+-+ | | +-+---+-+ | SSL | SSL proxy started for the CONNECT flow +-+---+-+ | | +-------+ | HTTP | HTTP proxy for the decrypted traffic +-------+ -- Bazsi PGP info: KeyID 9AF8D0A9 Fingerprint CD27 CFB0 802C 0944 9CFD 804E C82C 8EB1