A couple of days ago, my friend Jeffery registered a new domain name, and he pointed that domain to his server located in his apartment. But his ISP, Cox Communications, blocked some common ports, namely 80, 443. Basically, with these ports being blocked, one could not easily run an Internet-accessible website. As a result, Jeffery had to append the port number explicitly, which is not only a pain in life but also a significant impact on SEO. So he came to see if I can help him out.
My first thought was to use some kind of third-party redirecting services that allow users to redirect to port 8888. But Jeffery said that he wants his visitors to stay with his own domain, and always stay on port 80. He wants some kind of DNS service that allows binding to ports or port-forwarding.
But there is no such service. DNS simply resolves a domain name to an IP, without providing any information about the port. It is up to the client to choose a port to use. Browsers are configured to use ports 80 for HTTP and 443 for HTTPS. Since Jeffery’s ISP is restricting all incoming traffic on ports 80 and 443, there is no way to visit his server without explicitly specifying the port. Hence, a port 80 proxy server running outside the Cox firewall is needed.
I have a private server as well (the LAMP server which this blog runs on.) I am using Charters Communications, which does not restrict incoming traffics on any port. Thumb up Charters!
I thought, my server can act as a proxy server for Jeffery. So I instructed him to point his domain name to my server IP address, I will then forward all web requests to his server on port 8888.
Set Up DNS Record
Depending on whether he wants to park his root domain or some sub-domain on my server, he can choose to set an A record on his root domain (using @.root.domain) or set an A record on his sub-domain (using sub.root.domain.) Jeffery opted for parking the root domain on my server so that visitors who visit his root domain will get proxied as well.
NAME TYPE TTL DATA @.liyinxue.com A 1h 188.8.131.52
All incoming traffics will now be sent to my server.
Set Up Apache Virtual Host
By default, Apache provides a single host configuration. I have enabled virtual hosts since I have been running multiple websites on this LAMP server.
To enable virtual hosts on a newly installed Apache server, create a new file in
/etc/apache2/sites-available/[SITENAME].conf. In my case, it is
The file content should be as following:
<virtualhost *:80> ServerName liyinxue.com ServerAlias *.liyinxue.com ServerAdmin firstname.lastname@example.org </virtualhost>
ServerName tells Apache that, this configuration is for requests to the domain liyinxue.com, so settings here will apply to liyinxue.com and won’t affect any other virtual hosts.
ServerAlias tells Apache that, all subdomains under liyinxue.com belong to this virtual host.
ServerAdmin provides an admin email. It will be shown on Apache default error pages like 404 page.
Save the file and enable the virtual host with
a2ensite liyinxue.com. Then restart Apache server with
Now Apache should be configured to respond to requests to liyinxue.com. A 403 error will yield because we did not specify any
DocumentRoot for this virtual host as it is not needed.
Set Up Apache Proxy Server
The next step is to configure my server to get content from his server on port 8888 and returns content to the client.
Reopen the virtual host configuration file and add some lines to make it look like this:
<VirtualHost *:80> ServerName liyinxue.com ServerAlias *.liyinxue.com ServerAdmin email@example.com ProxyPreserveHost On ProxyRequests Off ProxyPass / http://liyinxue.ddns.net:8888/ ProxyPassReverse / http://liyinxue.ddns.net:8888/ </VirtualHost>
ProxyPreserveHost is set to On. When enabled, this option will pass the
Host: line from the incoming request to the proxied host. Note that on Apache website, it is said that this option should normally be turned Off. But since I am proxying all traffic to another fully functional server, I set it to On. Thus, Jeffery may make use of the original Host header information.
ProxyRequest is set to Off to prevent Apache httpd from functioning as a forward proxy server. Do not enable proxying with ProxyRequests unless you have secured your server. Open proxy servers are dangerous both to your network.
ProxyPass line redirects everything on
http://liyinxue.ddns.net:8888/ which is Jeffery’s server on port 8888, while
ProxyPassReverse lets Apache httpd adjust the URL in the
Location, Content-Location and
URI headers on HTTP redirect responses. This is essential when Apache httpd is used as a reverse proxy (or gateway) to avoid bypassing the reverse proxy because of HTTP redirects on the backend servers which stay behind the reverse proxy.
Then save the file and restart Apache to apply the configuration.
Now the Apache server should be configured to proxy all incoming requests.
By doing this, the client will be always visiting with Jeffery’s domain, on port 80.
The proxy process is invisible to the client, but the client will notice a significant delay, because under the hood, upon receiving a request, my server is sending another request to Jeffery’s server (:8888), wait for the content, and then send it back to the client. This extra data flow will slow down the connection to Jeffery’s server. But since Jeffery and I are physically close to each other, the delay should not make a real-life difference.
There is a potential risk for providing the proxy server though.
As far as the client can see, the server IP associated with Jeffery’s domain name is my IP. This means that any content served in his domain name is publically served from my server. If he provides any illegal materials, I will be the one in charge. So do this at your own risk. Only do this for someone you really trust.