Problem/ IssueI recently had the opportunity to look into the following issue:
- the organisation, like most others, have segregated the network into at least 2 zones (DMZ and internal)
- the DMZ hosts the web servers while the internal zone hosts the application and database servers
- a requirement is that an application in the internal zone needs to access a web service in the public internet
- allowing direct HTTP traffic from the internal zone to the public network is not an option
With the above constraints, a forward proxy could have been an option. However, the internal-zoned application may not be able to support a forward proxy. As such, a reverse proxy would be the solution.
Existing SolutionThe existing in-place solution follows:
- host a custom-written web service (acting as a proxy) in the DMZ to connect to the public network.
- The application in the internal zone will connect to the DMZ-hosted web service
- This custom-written web service will then connect to the public network
- any changes (especially schema changes) to the public web service will result in changes to the custom-written web service
- any new services in the future will incur writing more custom web services to be deployed in the DMZ
- performance is highly dependent on whether the custom-written web service was well-written or not
Forward or Reverse Proxy?
Take this scenario: Client –> Proxy –> Server
|Forward Proxy||Reverse Proxy|
|Supportability||requires web client to be configured (unless proxy is in transparent mode)||transparent to web client|
|Client’s target end-point||Server||Proxy|
|TLS/ SSL||Transparent (pass-through)||Terminates the connection to Server|
|Uses cases|| || |
Proposed SolutionA more elegant solution is to create a web service gateway otherwise known as a reverse proxy:
- this can be a generic solution as a common gateway for all web services
- requests/ responses will not be manipulated but may be logged as necessary
- no development work is required; only configuration of the Apache server
- We need to load mod_proxy & mod_proxy_http.
- Both mod_proxy_connect & mod_ssl are required if SSL is required.
- As I use virtual hosting, I’ve also included mod_vhost_alias.
I run the proxy on port 8888 and mapping is as follows:LoadModule proxy_module modules/mod_proxy.soLoadModule proxy_connect_module modules/mod_proxy_connect.soLoadModule proxy_http_module modules/mod_proxy_http.soLoadModule vhost_alias_module modules/mod_vhost_alias.soLoadModule ssl_module modules/mod_ssl.soInclude conf/extra/httpd-vhosts.conf<IfModule ssl_module>SSLRandomSeed startup builtinSSLRandomSeed connect builtin</IfModule>
- http://myproxy:8888/url_parturl_part always maps to https://webservice.end.pt/url_part
- The request will then timeout in 30 seconds
- in order to log the time taken for the proxied request, you need to add %D to the log parameter to capture the time in milliseconds
NameVirtualHost *:8888<VirtualHost *:8888>DocumentRoot "../htdocs"ServerName myproxyErrorLog "logs/proxy-error.log"CustomLog "logs/proxy-access.log" combinedio<Directory />Options NoneAllowOverride None</Directory><IfModule ssl_module>SSLProxyEngine on</IfModule><IfModule proxy_module>ProxyRequests OffProxyPassMatch ^/(.*)$ https ://webservice.end.pt/$1timeout=30 keepalive=On</IfModule></VirtualHost>