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:
-
Proxy Server Configurations(CentOS7)
-
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
Log 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 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 !
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"
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