Apache as a Forward Proxy

Proxy Server is a intermediary server that resides between client and  server. All requests originated by client send to the web server through  proxy server.  You can see below diagram with tcpdump analysis.

 

 

 

 

 

 

 

 

 

Configurations:

  1. Proxy Server Configurations(CentOS7)
  2. Install apache for using Proxy server.
[root@rhce ~]# yum install -y httpd

Create a file forward_proxy.conf under the /etc/httpd/conf.d and put the below lines into the configuration file.

Listen 7777
<VirtualHost 192.168.59.20:7777>
ProxyRequests On
ProxyVia On
ErrorLog logs/ex_error.log
CustomLog logs/ex_access.log combined
<ProxyMatch "http://example.com:8090/*">
Require ip 192.168.59.40
Require all denied
</ProxyMatch>
<ProxyMatch "http://example2.com:8090">
Require all denied
</ProxyMatch>
</VirtualHost>

Allow port 7777/tcp on the proxy server to the client make connections.

[root@rhce ~]#firewal-cmd --add-port=7777/tcp --permanent
[root@rhce ~]#firewal-cmd --reload

Restart httpd

[root@rhce ~]#systemctl restart httpd.service

2. Client Configurations

Setup the client to make request through proxy server to the 7777/tcp.

ansible@lubuntu:~$ export http_proxy=192.168.59.20:7777

Experiments:

Requst to example.com:8090. As you see in the debug message, request firstly goes to the proxy server.

ansible@lubuntu:~$ curl -v example.com:8090
* Rebuilt URL to: example.com:8090/
*   Trying 192.168.59.20...
* TCP_NODELAY set
* Connected to (nil) (192.168.59.20) port 7777 (#0)
> GET http://example.com:8090/ HTTP/1.1
> Host: example.com:8090
> User-Agent: curl/7.52.1
> Accept: */*
> Proxy-Connection: Keep-Alive
>
< HTTP/1.1 200 OK
< Date: Sat, 19 Aug 2017 08:11:51 GMT
< Server: Apache/2.4.25 (Ubuntu)
< Last-Modified: Fri, 18 Aug 2017 08:36:39 GMT
< ETag: "19-55703071fac7d"
< Accept-Ranges: bytes
< Content-Length: 25
< Content-Type: text/html; charset=UTF-8
< Via: 1.1 rhce:8090
<
<h1>Hello example.com</>
* Curl_http_done: called premature == 0
* Connection #0 to host (nil) left intact

Request to example2.com

root@lubuntu:~# curl -v example2.com:8090
* Rebuilt URL to: example2.com:8090/
*   Trying 192.168.59.20...
* TCP_NODELAY set
* Connected to (nil) (192.168.59.20) port 7777 (#0)
> GET http://example2.com:8090/ HTTP/1.1
> Host: example2.com:8090
> User-Agent: curl/7.52.1
> Accept: */*
> Proxy-Connection: Keep-Alive
>
< HTTP/1.1 403 Forbidden
< Date: Sat, 19 Aug 2017 08:34:26 GMT
< Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.1e-fips PHP/5.4.16
< Content-Length: 226
< 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://example2.com:8090/
on this server.</p>
</body></html>
* Curl_http_done: called premature == 0
* Connection #0 to host (nil) left intact

Logs on the Proxy Server.

192.168.59.40 - - [19/Aug/2017:10:30:42 +0200] "GET http://example.com:8090/ HTTP/1.1" 200 25 "-" "curl/7.52.1"
192.168.59.40 - - [19/Aug/2017:10:30:52 +0200] "GET http://example2.com:8090/ HTTP/1.1" 403 226 "-" "curl/7.52.1"
192.168.59.40 - - [19/Aug/2017:10:34:21 +0200] "GET http://example.com:8090/ HTTP/1.1" 200 25 "-" "curl/7.52.1"
192.168.59.40 - - [19/Aug/2017:10:34:26 +0200] "GET http://example2.com:8090/ HTTP/1.1" 403 226 "-" "curl/7.52.1"

SSH connection via Proxy Server:

I tried to connect to the host which is Web Server, using ssh protocol through the proxy server. But I got some errors. You can see below debug log, which was captured by ssh client. After some googling, I have found the solution to connect to the host via ssh. You can see below debug message before the proper solution.

...
debug1: key_load_public: No such file or directory
debug1: identity file /home/ansible/.ssh/id_ed25519-cert type -1
debug1: Enabling compatibility mode for protocol 2.0
debug1: Local version string SSH-2.0-OpenSSH_7.4p1 Ubuntu-10https://manintheit.org/wp-admin/post.php?post=402&action=edit#
debug1: permanently_drop_suid: 1000
Proxy could not open connection to 192.168.59.50:  Proxy Error
ssh_exchange_identification: Connection closed by remote host

SSH Client Configuration to Connect Web Server Through Proxy Server.

Client Configuration:

You have two options for the client configuration to establish ssh connection through proxy.

Create file with the name config under the  ~/.ssh

Put the one of below configuration into the config file.
To use corkscrew you have to install this package.

Host *
    ProxyCommand corkscrew 192.168.59.20 7777 %h %p

OR

You can use nc tool.

Host *
    ProxyCommand nc -X connect -x 192.168.59.20:7777 %h %p

Proxy Server Configuration to allow SSH connection:

Proxy server by default allow http methods such as  GET, POST, HEAD. But for ssh connection we need to allow CONNECT request on the proxy server. To do that We put AllowCONNECT <port>  directive into the forward_proxy.conf file and restart the proxy server.

Listen 7777
<VirtualHost 192.168.59.20:7777>
  ProxyRequests On
  ProxyVia On
  AllowCONNECT 22           #Add this line to allow ssh connection.
  ErrorLog logs/ex_error.log
  CustomLog logs/ex_access.log combined
<ProxyMatch "http://example.com:8090/*">
        Require ip 192.168.59.40
        Require all denied
</ProxyMatch>
<ProxyMatch "http://example2.com:8090">
        Require all denied
</ProxyMatch>
</VirtualHost>

Experiments:

Gotcha !

We can able to connect through proxy.

debug1: Host '192.168.59.50' is known and matches the ECDSA host key.
debug1: Found key in /home/ansible/.ssh/known_hosts:2
debug1: rekey after 134217728 blocks
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug1: SSH2_MSG_NEWKEYS received
debug1: rekey after 134217728 blocks
debug1: SSH2_MSG_EXT_INFO received
debug1: kex_input_ext_info: server-sig-algs=<ssh-ed25519,ssh-rsa,ssh-dss,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521>
debug1: SSH2_MSG_SERVICE_ACCEPT received
debug1: Authentications that can continue: publickey,password
debug1: Next authentication method: publickey
debug1: Trying private key: /home/ansible/.ssh/id_rsa
debug1: Trying private key: /home/ansible/.ssh/id_dsa
debug1: Trying private key: /home/ansible/.ssh/id_ecdsa
debug1: Trying private key: /home/ansible/.ssh/id_ed25519
debug1: Next authentication method: password
ansible@192.168.59.50's password:

Logs on the Proxy Server.[CONNECT] requests

192.168.59.40 - - [19/Aug/2017:11:29:36 +0200] "CONNECT 192.168.59.50:22 HTTP/1.0" 200 - "-" "-"
192.168.59.40 - - [19/Aug/2017:11:29:44 +0200] "CONNECT 192.168.59.50:22 HTTP/1.0" 200 - "-" "-"
192.168.59.40 - - [19/Aug/2017:11:31:25 +0200] "CONNECT 192.168.59.50:22 HTTP/1.0" 200 - "-" "-"

You can see iptables rule on the Web Server(192.168.59.50) below. It only allows connection from 192.168.59.20 which is proxy server. But we make actual requests from 192.168.59.40

target     prot opt source               destination
ACCEPT     tcp  --  192.168.59.20        anywhere             tcp dpt:8090
ACCEPT     tcp  --  192.168.59.20        anywhere             tcp dpt:ssh
REJECT     tcp  --  anywhere             anywhere             reject-with icmp-port-unreachable

 

 

 

 

 

 

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.