Apache Proxy Server on FreeBSD
In this article we will see how you can configure Apache to as a reverse proxy server.
You might want to use Apache proxy server for many different reasons. One of it is to is to provide web access to internal private web server from the outside.
Suppose you have a private network that is serving your intranet pages.You may even have more than one web server in your private network, that is not visible from the Internet. You may not want to directly expose these systems to the big bad Internet, and this is where an Apache proxy server comes in hand.
Instead of exposing your web servers directly to the Internet you would have one publicly accessible IP address, where your proxy server is accepting connections on.
The proxy server itself will be redirecting all those web requests from the external clients to the internal web servers. You may have as many as you want Apache vhosts configured on the proxy server forwarding all those external requests to the internal servers.
Requirements
- root access or sudo rights
- You have already installed Apache. If you still do not have Apache installed, please have a look at this handbook, which explains how you can install Apache web server.
Installation
In order to get Apache proxy server running, please refer to the following document, which explains how you can get Apache installed and configured for you.
Following the above documentation you can safely skip all those steps where you need to install and configure PHP support for Apache.
Please also note, that before you start building Apache, make sure you select the following modules, so we can have proxy capabilities within Apache.
[X] PROXY Enable mod_proxy
[X] PROXY_CONNECT Enable mod_proxy_connect
[X] PATCH_PROXY_CONNECT Patch proxy_connect SSL support
[X] PROXY_FTP Enable mod_proxy_ftp
[X] PROXY_HTTP Enable mod_proxy_http
Note, that PROXY_FTP is needed only if intend on proxying FTP connection, otherwise you may uncheck this module.
Now go ahead and install Apache according to this handbook, where you skip all those steps for enabling PHP support in your Apache server. Go through the configuration as well, and once you are ready, come back here so we can configure Apache as a proxy server.
After you’ve installed and configured Apache we need to install one more module from the FreeBSD Ports Collection
- www/mod_proxy_html. This module will let us replace all those hyperlinks received by the internal web server to something that the external clients can use.
Suppose that your internal web server is named intranet.my-private-network.org, and your your external publically accessible domain, where your proxy server will be running on is named example.org.
Now when the proxy server at example.org receives HTTP/HTTPS requests it will forward them to the internal web server at intranet.my-private-network.org, but if somewhere in the content we have links to other documents located on intranet.my-private-network.org, external clients will not be able to follow these links, since intranet.my-private-network.org is not visible from the outside.
So what we need to do is to make in some way all those for example http://intranet.my-private-network.org/index.php links to something like http://example.org/index.php. And this is where we are going to use the www/mod_proxy_html Apache module. So now, go ahead and install it:
$ cd /usr/ports/www/mod_proxy_html && sudo make install
Now that we have everything installed, we can continue with the configuration in the next step.
Configuration of
Assuming you have followed the handbook for installing and configuring Apache as web server, we will do some changes to our configuration files, so we make Apache work as a proxy server.
Make sure you have these lines in your Dynamic Shared Object (DSO) Support section of /usr/local/etc/apache22/httpd.conf file
LoadModule proxy_module libexec/apache22/mod_proxy.so
LoadModule proxy_connect_module libexec/apache22/mod_proxy_connect.so
LoadModule proxy_ftp_module libexec/apache22/mod_proxy_ftp.so
LoadModule proxy_http_module libexec/apache22/mod_proxy_http.so
LoadModule proxy_html_module libexec/apache22/mod_proxy_html.so
Please, note that you need the proxy_ftp_module entry only if you have chosen to have proxy_ftp installed in Apache.
We also need to configure the mod_proxy_html Apache module, so let’s do this. Either create a new file in /usr/local/etc/apache22/Includes directory called mod_proxy_html.conf or add these lines directly at the end of your /usr/local/etc/apache22/httpd.conf file:
# Configure the Apache mod_proxy_html module
ProxyHTMLLinks a href
ProxyHTMLLinks area href
ProxyHTMLLinks link href
ProxyHTMLLinks img src longdesc usemap
ProxyHTMLLinks object classid codebase data usemap
ProxyHTMLLinks q cite
ProxyHTMLLinks blockquote cite
ProxyHTMLLinks ins cite
ProxyHTMLLinks del cite
ProxyHTMLLinks form action
ProxyHTMLLinks input src usemap
ProxyHTMLLinks head profile
ProxyHTMLLinks base href
ProxyHTMLLinks script src for
ProxyHTMLEvents onclick ondblclick onmousedown onmouseup \
onmouseover onmousemove onmouseout onkeypress \
onkeydown onkeyup onfocus onblur onload \
onunload onsubmit onreset onselect onchange
Now, let’s configure a default HTTP vhost that all proxy requests will be received by. Open httpd-vhosts.conf file and edit it.
This default vhost will pass all requests from the externally accessible domain example.org to the internal web server at intranet.my-private-network.org.
Here’s mine httpd-vhosts.conf file, feel free to suit it for your needs:
#
# Virtual Hosts
#
# If you want to maintain multiple domains/hostnames on your
# machine you can setup VirtualHost containers for them. Most configurations
# use only name-based virtual hosts so the server doesn't need to worry about
# IP addresses. This is indicated by the asterisks in the directives below.
#
# Please see the documentation at
# <URL:http://httpd.apache.org/docs/2.2/vhosts/>
# for further details before you try to setup virtual hosts.
#
# You may use the command line option '-S' to verify your virtual host
# configuration.
#
# Use name-based virtual hosting.
#
NameVirtualHost *:80
#
# VirtualHost example:
# Almost any Apache directive may go into a VirtualHost container.
# The first VirtualHost section is used for all requests that do not
# match a ServerName or ServerAlias in any <VirtualHost> block.
#
<VirtualHost *:80>
ServerAdmin admin@example.org
ServerName example.org
ServerAlias www.example.org
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\.example\.org [NC]
RewriteCond %{HTTP_HOST} !^$
RewriteRule ^/(.*) http://www.example.org/$1 [L,R]
ProxyRequests Off
ProxyHTMLEnable On
ProxyPass / http://intranet.my-private-network.org/
ProxyPassReverse / http://intranet.my-private-network.org/
ProxyHTMLURLMap http://intranet.my-private-network.org/ http://www.example.org/
ErrorLog "/var/log/apache/httpd-example.org-error.log"
CustomLog "/var/log/apache/httpd-example.org-access.log" common
</VirtualHost>
Now, let’s configure the default HTTPS vhost. All SSL requests will have a default vhost. Feel free to suit the settings for your needs.
Most of the settings are already there in the default configuration, so just add the needed lines to your configuration (comments were removed to make the file smaller).
Here’s mine httpd-ssl.conf file:
Listen 443
AddType application/x-x509-ca-cert .crt
AddType application/x-pkcs7-crl .crl
SSLPassPhraseDialog builtin
SSLSessionCache "shmcb:/var/run/ssl_scache(512000)"
SSLSessionCacheTimeout 300
SSLMutex "file:/var/run/ssl_mutex"
##
## SSL Virtual Host Context
##
<VirtualHost *:443>
# General setup for the virtual host
ServerAdmin admin@example.org
ServerName example.org:443
ServerAlias www.example.org
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\.example\.org [NC]
RewriteCond %{HTTP_HOST} !^$
RewriteRule ^/(.*) https://www.example.org/$1 [L,R]
SSLProxyEngine On
ProxyRequests Off
ProxyHTMLEnable On
ProxyPass / https://intranet.my-private-network.org/
ProxyPassReverse / https://intranet.my-private-network.org/
ProxyHTMLURLMap https://intranet.my-private-network.org/ https://www.example.org/
ErrorLog "/var/log/apache/httpd-example.org-ssl-error.log"
TransferLog "/var/log/apache/httpd-example.org-ssl-access.log"
SSLEngine on
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
# Server Certificate
SSLCertificateFile "/etc/ssl/apache/server.crt"
# Server Private Key
SSLCertificateKeyFile "/etc/ssl/apache/server.key"
<FilesMatch "\.(cgi|shtml|phtml|php)$">
SSLOptions +StdEnvVars
</FilesMatch>
<Directory "/usr/local/www/apache22/cgi-bin">
SSLOptions +StdEnvVars
</Directory>
BrowserMatch ".*MSIE.*" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
# Per-Server Logging:
# The home of a custom SSL log file. Use this when you want a
# compact non-error SSL logfile on a virtual host basis.
CustomLog "/var/log/httpd-ssl_request.log" \
"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
</VirtualHost>
Starting Apache
Before starting Apache for the first time, it is a good thing to test the configuration for errors.
To do so, just execute the command below
$ sudo apachectl configtest
If the output says Syntax OK, then we can start our Apache proxy server, otherwise please double check the configuration for errors.
So, let’s start Apache now:
$ sudo apachectl start
In order to start Apache during boot-time add the following line to your /etc/rc.conf file:
apache22_enable="YES"
In the next chapter of this handbook you will find examples on how to add more vhosts to your Apache Proxy server.
Adding more Apache vhosts
Now let’s have a look at some examples, where we add more vhosts to our Apache Proxy configuration.
Suppose that you have a mail server in your internal network named mail.my-private-network.org, and you want to allow web access to the mail server using some web interface from webmail.example.org. In this example the mail server should be accessed only via HTTPS.
We will also add one more vhost to our configuration called lists.example.org, which we will use to access the mailing lists which are also located on internal web server at lists.my-private-network.org.
Below is a sample configuration covering these two examples. Feel free to suit the configuration for your needs. So, open httpd-vhosts.conf and update the file as follows:
#
# Virtual Hosts
#
# If you want to maintain multiple domains/hostnames on your
# machine you can setup VirtualHost containers for them. Most configurations
# use only name-based virtual hosts so the server doesn't need to worry about
# IP addresses. This is indicated by the asterisks in the directives below.
#
# Please see the documentation at
# <URL:http://httpd.apache.org/docs/2.2/vhosts/>
# for further details before you try to setup virtual hosts.
#
# You may use the command line option '-S' to verify your virtual host
# configuration.
#
# Use name-based virtual hosting.
#
NameVirtualHost *:80
NameVirtualHost *:443
#
# VirtualHost example:
# Almost any Apache directive may go into a VirtualHost container.
# The first VirtualHost section is used for all requests that do not
# match a ServerName or ServerAlias in any <VirtualHost> block.
#
# Default vhost
<VirtualHost *:80>
ServerAdmin admin@example.org
ServerName example.org
ServerAlias www.example.org
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\.example\.org [NC]
RewriteCond %{HTTP_HOST} !^$
RewriteRule ^/(.*) http://www.example.org/$1 [L,R]
ProxyRequests Off
ProxyHTMLEnable On
ProxyPass / http://intranet.my-private-network.org/
ProxyPassReverse / http://intranet.my-private-network.org/
ProxyHTMLURLMap http://intranet.my-private-network.org/ http://www.example.org/
ErrorLog "/var/log/apache/httpd-example.org-error.log"
CustomLog "/var/log/apache/httpd-example.org-access.log" common
</VirtualHost>
# lists.example.org vhost
<VirtualHost *:80>
ServerAdmin admin@example.org
ServerName lists.example.org
ServerAlias lists.example.org
ProxyRequests Off
ProxyHTMLEnable On
ProxyPass / http://lists.my-private-network.org/
ProxyPassReverse / http://lists.my-private-network.org/
ProxyHTMLURLMap http://lists.my-private-network.org/ http://lists.example.org/
ErrorLog "/var/log/apache/httpd-lists.example.org-error.log"
CustomLog "/var/log/apache/httpd-lists.example.org-access.log" common
</VirtualHost>
# webmail.example.org vhost
<VirtualHost *:80>
ServerName webmail.example.org:80
Redirect permanent / https://webmail.example.org/
</VirtualHost>
<VirtualHost *:443>
ServerAdmin admin@example.org
ServerName webmail.example.org:443
ServerAlias webmail.example.org
SSLEngine On
SSLProxyEngine On
ProxyRequests Off
ProxyHTMLEnable On
ProxyPass / https://mail.my-private-network.org/
ProxyPassReverse / https://mail.my-private-network.org/
ProxyHTMLURLMap https://mail.my-private-network.org/ https://webmail.example.org/
SSLCertificateFile "/etc/ssl/apache/server.crt"
SSLCertificateKeyFile "/etc/ssl/apache/server.key"
ErrorLog "/var/log/apache/httpd-webmail.example.org-error.log"
CustomLog "/var/log/apache/httpd-webmail.example.org-access.log" common
</VirtualHost>
Now tell Apache to re-read it’s configuration, so the changes are applied.
$ sudo apachectl graceful
And that was it!