Source: Quora.com
A forward proxy brokerages the request of the client and forwards the request to the destination of the client's choice contingent on the configuration of the forward proxy.
Most common uses are to
A reverse proxy brokerages the request of the client and forwards the request to the destination purely based on the configuration of the reverse proxy.
Most common uses of a reverse proxy are to
Warning: Enabling proxies, either forward or reverse, could pose a huge security risk. It is highly recommended that you harden the server and take the necessary security precautions required before enabling proxies in your network.
The following article is just to demo how the Apache HTTP Server could act as a forward and reverse proxy. The machines used in the demo were entirely run on a private isolated network.
Okay, now that we have the disclaimers out of the way, let's see how our environment setup will be like. We will use four machines - 2 proxies, 1 web server and a client.
192.168.33.11
192.168.33.1
192.168.33.10
192.168.33.12
(This will be rarely used - only to demo proxy chains)Our Web Server also runs the Apache HTTP Server with mod_php5
and so has support for PHP5. We have a PHP script on it called test.php
which echoes back the Request Headers of any incoming requests.
## test.php
<?php
print_r(apache_request_headers());
?>
On the Proxy Server machines we enable the mod_proxy
and mod_proxy_http
modules for Proxying support. This is done with the following commands on Ubuntu or other Debian-based machines:
$ sudo a2enmod proxy
$ sudo a2enmod proxy_http
A server restart is required on addition of the two modules - $ sudo service apache2 restart
Adding the following Directives in the VirtualHost configuration of our Proxy Server 1 (192.168.33.10) allows for any incoming traffic on that particular VirtualHost to be forwarded to our Web Server (192.168.33.11).
## Proxy Server 1 -> Web Server
ProxyPass / http://192.168.33.11/
ProxyPassReverse / http://192.168.33.11/
A configuration reload is required after adding the two lines - $ sudo service apache2 restart
A request made to 192.168.33.10/test.php
from our Client machine (192.168.33.1) looks so,
$ curl http://192.168.33.10/test.php
Array
(
[Host] => 192.168.33.11
[User-Agent] => curl/7.47.0
[Accept] => */*
[X-Forwarded-For] => 192.168.33.1
[X-Forwarded-Host] => 192.168.33.10
[X-Forwarded-Server] => 10.0.2.15
[Connection] => Keep-Alive
)
Let's configure the Proxy Server 2 to act as a reverse proxy, forwarding all traffic to Proxy Server 1 and then study the effect. So add the following lines to the VirtualHost configuration of Proxy Server 2 (192.168.33.12)
## Proxy Server 2 -> Proxy Server 1
ProxyPass / http://192.168.33.10/
ProxyPassReverse / http://192.168.33.10/
So now, let's make a request from the client to Proxy Server 2. The route would be as follows: Client -> Proxy Server 2 -> Proxy Server 1 -> Web Server
$ curl http://192.168.33.12/test.php
Array
(
[Host] => 192.168.33.11
[User-Agent] => curl/7.47.0
[Accept] => */*
[X-Forwarded-For] => 192.168.33.1, 192.168.33.12
[X-Forwarded-Host] => 192.168.33.12, 192.168.33.10
[X-Forwarded-Server] => 10.0.2.15, 10.0.2.15
[Connection] => Keep-Alive
)
ProxyPreserveHost
You could add an additional directive to the VirtualHost config of Proxy Server 1, so that it now looks like
ProxyPass / http://192.168.33.11/
ProxyPassReverse / http://192.168.33.11/
ProxyPreserveHost On
Now, when the same request is made from our client machine, it looks like so,
$ curl http://192.168.33.10/test.php
Array
(
[Host] => 192.168.33.10
[User-Agent] => curl/7.47.0
[Accept] => */*
[X-Forwarded-For] => 192.168.33.1
[X-Forwarded-Host] => 192.168.33.10
[X-Forwarded-Server] => 10.0.2.15
[Connection] => Keep-Alive
)
The Host
header gets preserved from the original request instead of being overwritten by Proxy Server 1.
ProxyPreserveHost
With ProxyPreserveHost On
on both Proxy Server 1 and Proxy Server 2,
# Client -> Proxy Server 2 -> Proxy Server 1 -> Web Server
$ curl http://192.168.33.12/test.php
Array
(
[Host] => 192.168.33.12
[User-Agent] => curl/7.47.0
[Accept] => */*
[X-Forwarded-For] => 192.168.33.1, 192.168.33.12
[X-Forwarded-Host] => 192.168.33.12, 192.168.33.12
[X-Forwarded-Server] => 10.0.2.15, 10.0.2.15
[Connection] => Keep-Alive
)
With ProxyPreserveHost On
on Proxy Server 1 and ProxyPreserveHost Off
on Proxy Server 2,
# Client -> Proxy Server 2 -> Proxy Server 1 -> Web Server
$ curl http://192.168.33.12/test.php
Array
(
[Host] => 192.168.33.10
[User-Agent] => curl/7.47.0
[Accept] => */*
[X-Forwarded-For] => 192.168.33.1, 192.168.33.12
[X-Forwarded-Host] => 192.168.33.12, 192.168.33.10
[X-Forwarded-Server] => 10.0.2.15, 10.0.2.15
[Connection] => Keep-Alive
)
To configure my Proxy Server 1 (192.168.33.10) as my Forward Proxy, I add the following two Directives to my VirtualHost configuration of Proxy Server 1.
ProxyRequests On
ProxyVia On
Here's the client trying to access http://google.com
using Proxy Server 1,
Using HTTP 1.0:
$ netcat 192.168.33.10 80
GET http://google.com HTTP/1.0
HTTP/1.1 302 Found
Date: Mon, 05 Sep 2016 19:30:15 GMT
Server: Apache/2.4.7 (Ubuntu)
Cache-Control: private
Content-Type: text/html; charset=UTF-8
Location: http://www.google.co.in/?gfe_rd=cr&ei=x8fNV-OIBcWL8QfHwoDYAQ
Content-Length: 261
Via: 1.0 10.0.2.15
Connection: close
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>302 Moved</TITLE></HEAD><BODY>
<H1>302 Moved</H1>
The document has moved
<A HREF="http://www.google.co.in/?gfe_rd=cr&ei=x8fNV-OIBcWL8QfHwoDYAQ">here</A>.
</BODY></HTML>
Using HTTP 1.1:
$ netcat 192.168.33.10 80
GET http://google.com HTTP/1.1
Host: google.com
HTTP/1.1 302 Found
Date: Mon, 05 Sep 2016 19:28:44 GMT
Server: Apache/2.4.7 (Ubuntu)
Cache-Control: private
Content-Type: text/html; charset=UTF-8
Location: http://www.google.co.in/?gfe_rd=cr&ei=bMfNV9DkKK_v8wervYu4Bw
Content-Length: 261
Via: 1.1 10.0.2.15
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>302 Moved</TITLE></HEAD><BODY>
<H1>302 Moved</H1>
The document has moved
<A HREF="http://www.google.co.in/?gfe_rd=cr&ei=bMfNV9DkKK_v8wervYu4Bw">here</A>.
</BODY></HTML>
Another way using HTTP 1.1: (note the Host header)
$ netcat 192.168.33.10 80
GET http://google.com HTTP/1.1
Host: 192.168.33.10
HTTP/1.1 302 Found
Date: Mon, 05 Sep 2016 19:30:55 GMT
Server: Apache/2.4.7 (Ubuntu)
Cache-Control: private
Content-Type: text/html; charset=UTF-8
Location: http://www.google.co.in/?gfe_rd=cr&ei=78fNV9KIF9jpugTU0oWwAw
Content-Length: 261
Via: 1.1 10.0.2.15
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>302 Moved</TITLE></HEAD><BODY>
<H1>302 Moved</H1>
The document has moved
<A HREF="http://www.google.co.in/?gfe_rd=cr&ei=78fNV9KIF9jpugTU0oWwAw">here</A>.
</BODY></HTML>
And now, back to our test.php
script sitting on our Web Server (192.168.33.11),
$ netcat 192.168.33.10 80
GET http://192.168.33.11/test.php HTTP/1.0
HTTP/1.1 200 OK
Date: Mon, 05 Sep 2016 19:33:19 GMT
Server: Apache/2.4.7 (Ubuntu)
X-Powered-By: PHP/5.5.9-1ubuntu4.19
Vary: Accept-Encoding
Content-Length: 91
Content-Type: text/html
Via: 1.0 10.0.2.15
Connection: close
Array
(
[Host] => 192.168.33.11
[Via] => 1.0 10.0.2.15
[Connection] => close
)
And now for a twist, Proxy Server 1 (192.168.33.10) acting as a reverse proxy to Web Server (192.168.33.11) and Proxy Server 2 (192.168.33.12) acting as a Forward Proxy.
$ netcat 192.168.33.12 80
GET http://192.168.33.10/test.php
Array
(
[Host] => 192.168.33.10
[Via] => 0.9 10.0.2.15
[X-Forwarded-For] => 192.168.33.12
[X-Forwarded-Host] => 192.168.33.10
[X-Forwarded-Server] => 10.0.2.15
[Connection] => Keep-Alive
)
For this section, you're going to need mod_authz_host
which comes enabled by default.
So, in this scenario, we will be using our client machine (192.168.33.1) as the one authorized to use the Forward Proxy, and our 192.168.33.12 as another client but one that is not authorized to use the Forward Proxy.
Now we add the following lines to our VirtualHost configuration on our Proxy Server 1 (192.168.33.10) that is acting as our Forward Proxy. This will allow only 192.168.33.1 to access our Forward Proxy and anyone else trying to access it will be blocked.
<Proxy "*">
Require ip 192.168.33.1
</Proxy>
And reload for the configuration to take effect - $ sudo service apache2 reload
And now, accessing from our authorized client (192.168.33.1),
$ netcat 192.168.33.10 80
GET http://google.com HTTP/1.0
HTTP/1.1 302 Found
Date: Sat, 10 Sep 2016 16:24:14 GMT
Server: Apache/2.4.7 (Ubuntu)
Cache-Control: private
Content-Type: text/html; charset=UTF-8
Location: http://www.google.co.in/?gfe_rd=cr&ei=rjPUV8f3MseL8QfxsZq4DA
Content-Length: 261
Via: 1.0 10.0.2.15
Connection: close
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>302 Moved</TITLE></HEAD><BODY>
<H1>302 Moved</H1>
The document has moved
<A HREF="http://www.google.co.in/?gfe_rd=cr&ei=rjPUV8f3MseL8QfxsZq4DA">here</A>.
</BODY></HTML>
But whereas, trying to access from an unauthorized client,
$ netcat 192.168.33.10 80
GET http://google.com HTTP/1.0
HTTP/1.1 403 Forbidden
Date: Sat, 10 Sep 2016 16:25:48 GMT
Server: Apache/2.4.7 (Ubuntu)
Content-Length: 293
Connection: close
Content-Type: text/html; charset=iso-8859-1
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><body>
<h1>Forbidden</h1>
<p>You don't have permission to access http://google.com
on this server.</p>
<hr>
<address>Apache/2.4.7 (Ubuntu) Server at google.com Port 80</address>
</body></html>
And there you have it, restricted access to your Forward Proxy based on IP addresses.
Again, as a reminder, please do go through the official documentation and harden your server before using it as a Forward / Reverse Proxy.
Download the official 2buntu app for both Android and Ubuntu Touch.