Example: I have two URLs
https:// www.abc.net => maps to https://192.168.0.100:5000
https:// www.def.net => maps to https://192.168.0.100:5001
Both servers running on the same Windows 10 PCs.
May I know how can I achieve that?
Port forwarding is forwarding traffic to a host based on specific ports. No additional information is used for this routing (i.e. any "destination" URLs). For routing specific URLs to particular local services, you'll likely want a reverse proxy.
In short, a reverse proxy takes requests from the Internet and forwards them to servers in an internal network. Importantly, it can often do this based on a particular URL received.
Software
For setting up a reverse proxy, two common solutions that would likely suit your needs are Apache and Nginx. Both are open source web servers and both can be configured to act as reverse proxies (via Apache virtual hosts or Nginx server blocks, respectively).
Windows builds of Apache with SSL are available from Apache Lounge and Windows builds of Nginx (which also support SSL) are directly available from Nginx.
Caveats
One thing to consider about a reverse proxy is that communications between a client and a local service may be limited by what the reverse proxy itself can pass.
In some cases, it could be preferable (or may even be necessary) to make a direct link between the client and a local service. For instance, assuming a router was mapping ports 5000
and 5001
to an internal host (e.g. 192.168.0.100
) and that example.com
and example.net
were pointed to that router, those ports/services would likely be externally available as e.g. example.com:5000
and example.net:5001
.
The basic downside to this is approach is that DNS doesn't use port information, so example.net:5000
and example.com:5001
would also map to the same services. However, for some types of communication, this might be the only option.
Reverse Proxy Example (Overview)
Assuming you decide to use Apache or Nginx as reverse proxy, while the individual configuration steps may be different, the basics are roughly the same:
While the example below only covers using Apache as a reverse proxy, for Nginx, the steps outlined above are generally available on the web.
Reverse Proxy Example (Apache)
Assumptions
Below is a bare-bones example of how to setup Apache from scratch as reverse proxy on Windows. Note that it isn't intended to address any of the finer points of general Apache, SSL or reverse proxy configuration beyond sending requests from basic URL A to local service B.
It also assumes that:
The reverse proxy (i.e. Apache) is being installed on the same local server as the current services (ex. 192.168.0.100
), outside of any virtual machine.
There are no services running on port 80
(HTTP) or 443
(HTTPS) on that host.
DNS is already set up correctly for any domains (e.g. example.com
and example.net
already point to the appropriate router/local network).
SSL certificates and keys are available for the domains you wish to proxy.
The local services you wish to proxy to are not using HTTPS (SSL) themselves.
Port forwarding is already set up correctly (i.e. ports 5000
and 5001
are mapped to 192.168.0.100
). Note that for this example, ports 80
and 443
will also need to be mapped to the host with the reverse proxy (again, ex. 192.168.0.100
).
Installation
Download Apache from Apache Lounge and extract it. For this example, place the folder labeled Apache24
into C:\
on your local server (i.e C:\Apache24
on 192.168.0.100
).
Apache being built as 32-bit (ex. httpd-2.4.43-win32-VS16.zip
) or 64-bit (ex. httpd-2.4.43-win64-VS16.zip
) doesn't matter in this instance, so you can choose either one.
Download the matching Microsoft Visual C++ Redistributable for Visual Studio 2015-2019 from the same page (either vc_redist_x86
for httpd-2.4.43-win32-VS16.zip
or vc_redist_x64
for httpd-2.4.43-win64-VS16.zip
). Double-click the executable to install it.
If the installer displays the option to "Repair" an existing redistributable installation, you can safely cancel the installation entirely, as you already have an appropriate version of that redistributable installed.
It is possible to install Apache as a service in Windows by running httpd -k install -n "Apache2.4"
from the command line (httpd.exe
is located under ex. C:\Apache24\bin
). If you decide to do this, use an administrative command prompt and do not use a name for the service other than Apache2.4
.
Configuration (Overview)
When editing any configuration file for Apache, you should use a plain text editor such as Windows Notepad or a third-party editor like Notepad++.
In the context of the steps given below, "uncomment" means to remove any leading #
sign in front of one or more lines in a configuration file and "comment out" means to add a leading #
sign in front of one or more lines in a configuration file:
# This line is commented out
This line is uncommented
In the individual configuration examples below, [...]
is just an place holder intended to indicate "more irrelevant stuff here" (i.e. it doesn't actually go in the configuration file).
The majority of the configuration steps listed below are done in httpd.conf
(ex. C:\Apache24\conf\httpd.conf
), as it is the main configuration file for Apache.
For general SSL support and implementing the virtual hosts needed for a reverse proxy setup, there are changes that need to be made in httpd-ssl.conf
(ex. C:\Apache24\conf\extra\httpd-ssl.conf
) and httpd-vhosts.conf
(ex. C:\Apache24\conf\extra\httpd-vhosts.conf
) as well.
Configuration files need to be saved and Apache restarted (assuming it is running) for any configuration changes to take effect.
HTTP Configuration
Apache is already set up for handling basic HTTP requests out of the box, especially when placed in C:\Apache24
(the default directory the Apache Lounge version of Apache assumes it resides in). However, a warning will be emitted if the default ServerName
directive in httpd.conf
isn't uncommented. So make the following change:
ex. httpd.conf
[...]
# ServerName gives the name and port that the server uses to identify itself.
# This can often be determined automatically, but we recommend you specify
# it explicitly to prevent problems during startup.
#
# If your host doesn't have a registered DNS name, enter its IP address here.
#
ServerName www.example.com:80
For this example, the value of this ServerName
directive doesn't matter, as long as it isn't one of the domains you wish to proxy (i.e. leaving it www.example.com:80
is fine).
Enabling Proxy Modules
Apache comes with a number of optional modules which enable additional features in Apache, such as the ability to proxy incoming requests to local services. These "extra" modules are listed in httpd.conf
but are typically disabled (commented out) by default.
You don't mention the services you are attempting to proxy, but you should probably enable at least mod_proxy
, mod_proxy_html
, mod_proxy_http
and mod_xml2enc
in httpd.conf
by uncommenting them like so:
ex. httpd.conf
[...]
LoadModule proxy_module modules/mod_proxy.so
[...]
LoadModule proxy_html_module modules/mod_proxy_html.so
LoadModule proxy_http_module modules/mod_proxy_http.so
[...]
LoadModule xml2enc_module modules/mod_xml2enc.so
mod_proxy
is a "base" module that other proxy modules rely on, so it should always be uncommented. mod_proxy_html
and mod_proxy_http
should allow most web pages to be proxied successfully and mod_xml2enc
helps ensure non-ASCII characters in proxied pages are displayed correctly.
SSL Certificates (Overview)
Please note that the instruction below assume that you have an existing self-signed SSL certificate and matching key specifically for www.example.com
(as in the actual domain www.example.com
, not merely as a documentation placeholder). These aren't directly used for proxying, but are required when including the default Apache httpd-ssl.conf
file (unless additional configuration is done to that file, which is mostly skipped here).
If you do not have these files, I would suggest using this website to generate them. It only takes a moment and the domain in the link currently defaults to www.example.com
. All you should need to do is click the button marked Generate
and then use the resulting links to download the appropriate .cert
and .key
files (e.g. 12345678-www.example.com.cert
and 12345678-www.example.com.key
).
If you want to generate a self-signed certificate locally, SLProWeb offers Windows builds of OpenSSL that can be used from the command line, but those steps aren't covered here.
If you need free SSL certificates for the domain names you wish to proxy (these certificates are used later in the "virtual hosts" section of this example), I might suggest looking at ZeroSSL to obtain certificates from Let's Encrypt. They only last 3 months, but can be renewed indefinitely at no charge. Plus, ZeroSSL offers a simple, fairly easy-to-use command line client for obtaining/renewing Let's Encrypt certificates.
Be aware that it is important not to use encrypted SSL key files on Windows with Apache. Apache does not support SSL passphrases on Win32. If any of your SSL key files are encrypted with a passphrase, you must use OpenSSL to remove that passphrase before using it with Apache on Windows.
SSL (HTTPS) Configuration
To enable SSL support in Apache, enable the mod_ssl
module in httpd.conf
by uncommenting it. For this example, you will also need to enable (uncomment) mod_socache_shmcb
:
ex. httpd.conf
[...]
LoadModule socache_shmcb_module modules/mod_socache_shmcb.so
#LoadModule speling_module modules/mod_speling.so
LoadModule ssl_module modules/mod_ssl.so
[...]
For expediency, we will also include the default Apache SSL configuration file (httpd-ssl.conf
). To do this, uncomment the following line near the end of httpd.conf
:
ex. httpd.conf
# Secure (SSL/TLS) connections
Include conf/extra/httpd-ssl.conf
Create one (or more) folders to hold your www.example.com
SSL certificate and key file. For this example, these folders should be under C:\Apache24
. Place the appropriate files in the folder(s) you created.
Open httpd-ssl.conf
(ex. C:\Apache24\conf\extra\httpd-ssl.conf
). Look for the line SSLPassPhraseDialog builtin
and disable it (comment it out):
ex. httpd-ssl.conf
[...]
# Pass Phrase Dialog:
# Configure the pass phrase gathering process.
# The filtering dialog program (`builtin' is an internal
# terminal dialog) has to provide the pass phrase on stdout.
#SSLPassPhraseDialog builtin
Further down in httpd-ssl.conf
, look for the SSLCertificateFile
and SSLCertificateKeyFile
directives and change the paths after them to point to your www.example.com
certificate and key files (wherever you placed them in Step 3, above):
ex. httpd-ssl.conf
[...]
SSLCertificateFile "${SRVROOT}/path/to/12345678-www.example.com.cert"
[...]
SSLCertificateKeyFile "${SRVROOT}/path/to/12345678-www.example.com.key"
[...]
Testing (Preliminary)
You should have a working, SSL enabled Apache server at this point (though not a reverse proxy just yet). To test this:
Save any changes you made to httpd.conf
and httpd-ssl.conf
(if you haven't already).
Navigate to your Apache bin
directory (ex. C:\Apache24\bin
).
Open a command window in that directory (ex. Shift + Right-Click a blank area in Explorer and choose the option to Open Command Prompt Here).
Run httpd.exe
:
This command window should remain open without any additional errors or warnings and without returning to the command line (e.g. C:\Apache24\bin>
).
Assuming this is the case, you should be able to enter e.g. http://192.168.0.100
and https://192.168.0.100
into your browser and get a white page that states It works!
.
Assuming your DNS is configured properly and you have port forwarded ports 80
and 443
to ex. http://192.168.0.100
, using the HTTP and HTTPS versions of abc.net
and def.net
should yield the same page.
For SSL connections (ex. https://192.168.0.100
), your browser may warn you that the certificate name doesn't match and/or that the certificate is self-signed. In this instance, it is safe to ignore any warnings and proceed with the connection.
Testing (Issues)
If any errors or warnings are displayed at the command line, fix them before proceeding.
If httpd.exe
immediately stops (goes back to the command line) without any additional output, check the Apache error.log
(ex. C:\Apache24\logs\error.log
) for any issues e.g. with your SSL configuration.
If you cannot reach ex. https://192.168.0.100
, ensure that any firewall on that host isn't blocking web traffic and that ports 80
and 443
are forwarded correctly to that host.
In some rarer cases, using ex. abc.net
and def.net
may not be possible without additional considerations or steps. This could be due to a router not supporting hairpinning (NAT Loopback) or worse, an ISP having Carrier-Grade NAT (CGNAT) or actively blocking ports.
Hairpinning issues can be bypassed by accessing ex. abc.net
and def.net
from a device not connected to your local network (e.g. a smartphone connected to a carrier's network).
CGNAT or similar may require a server completely outside your local network to act as an additional proxy to your network and isn't covered here.
Virtual Host (Reverse Proxy) Configuration
After testing Apache (above), close the command window for httpd.exe
to stop Apache.
Reopen httpd.conf
(ex. C:\Apache24\conf\httpd.conf
) and enable the default Apache virtual hosts configuration file (httpd-vhosts.conf
) by uncommenting the following line:
ex. httpd.conf
# Virtual hosts
Include conf/extra/httpd-vhosts.conf
Next, open httpd-vhosts.conf
(ex. C:\Apache24\conf\extra\httpd-vhosts.conf
) and comment out the existing virtual host example entries:
ex. httpd-vhosts.conf
[...]
#<VirtualHost *:80>
#ServerAdmin [email protected]
#DocumentRoot "${SRVROOT}/docs/dummy-host.example.com"
#ServerName dummy-host.example.com
#ServerAlias www.dummy-host.example.com
#ErrorLog "logs/dummy-host.example.com-error.log"
#CustomLog "logs/dummy-host.example.com-access.log" common
#</VirtualHost>
#<VirtualHost *:80>
#ServerAdmin [email protected]
#DocumentRoot "${SRVROOT}/docs/dummy-host2.example.com"
#ServerName dummy-host2.example.com
#ErrorLog "logs/dummy-host2.example.com-error.log"
#CustomLog "logs/dummy-host2.example.com-access.log" common
#</VirtualHost>
Add the following example virtual hosts to the end of httpd-vhosts.conf
:
ex. httpd-vhosts.conf
# Redirect HTTP to HTTPS for http://example.com
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
Redirect permanent / https://example.com/
</VirtualHost>
# Redirect HTTP to HTTPS for http://example.net
<VirtualHost *:80>
ServerName example.net
ServerAlias www.example.net
Redirect permanent / https://example.net/
</VirtualHost>
# Redirect HTTPS requests for https://example.com to ex. 192.168.0.100:5000
<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com
SSLEngine on
SSLOptions +StrictRequire
SSLCertificateFile "${SRVROOT}/path/to/www.example.com.crt"
SSLCertificateKeyFile "${SRVROOT}/path/to/www.example.com.key"
# Required by first virtual SSL host
#SSLProtocol TLSv1
#ProxyPass / http://192.168.0.100:5000/
#ProxyPassReverse / http://192.168.0.100:5000/
# Localhost
ProxyPass / http://127.0.0.1:5000/
ProxyPassReverse / http://127.0.0.1:5000/
</VirtualHost>
# Redirect HTTPS requests for https://example.net to ex. 192.168.0.100:5001
<VirtualHost *:443>
ServerName example.net
ServerAlias www.example.net
SSLEngine on
SSLOptions +StrictRequire
SSLCertificateFile "${SRVROOT}/path/to/www.example.net.crt"
SSLCertificateKeyFile "${SRVROOT}/path/to/www.example.net.key"
# Required by first virtual SSL host
#SSLProtocol TLSv1
#ProxyPass / http://192.168.0.100:5001/
#ProxyPassReverse / http://192.168.0.100:5001/
# Localhost
ProxyPass / http://127.0.0.1:5001/
ProxyPassReverse / http://127.0.0.1:5001/
#</VirtualHost>
Modify this updated example for your needs. In particular:
Unlike in httpd.conf
and httpd-ssl.conf
, substitute your actual domains (e.g. abc.net
and def.net
) for example.com
and example.net
(e.g. just do a simple search/replace).
Change the SSLCertificateFile
and SSLCertificateKeyFile
directives to point to the appropriate SSL certificate and key files for each of your domains (again, ex. abc.net
and def.net
). This example assumes you are dropping them in roughly the same folder(s) as your actual www.example.com
certificate and key files from the prior "SSL" section (above).
While these examples omit per-host logging for space, you can add logging directives to any of the virtual hosts above if you wish.
Save httpd-vhosts.conf
after making the necessary changes above.
While Apache is running, your services on 192.168.0.100:5000
and 192.168.0.100:5001
should now be returned by either the HTTP or HTTPS versions of abc.net
and def.net
, respectively (with or without the www
prefix, assuming the non-www versions are set in DNS).