Exposing multiple servers behind NAT using a single public IP address
This is a Canonical Question about NAT and DNS
I'm currently trying to set up a network with a DMZ containing a web server and an e-mail server separated from the Internet by a network address translating (NAT) firewall.
I have installed the NAT firewall with the following interfaces:
WAN - x.x.x.x (redacted public IP address)
DMZ - 192.168.124.5/24
LAN - 192.168.123.5/24
On my DMZ I have my two hosts:
Web server - 192.168.124.30
E-mail server - 192.168.124.32
I know that I will need to configure the DNS for the example.com
domain to resolve both example.com
and mail.example.com
to my public IP address.
I would like my NAT firewall to forward all incoming requests to example.com
to the web server at 192.168.124.30, and all incoming requests to mail.example.com
to the e-mail server at 192.168.124.32. I see a "port forwarding" feature in my NAT firewall's configuration but can't seem to achieve what I'm looking for.
Solution 1:
You're getting muddled in your thinking about how information flows between the layers of the TCP/IP protocol stack-- between DNS and application layer protocols, specifically.
You have one public IP address. Your DNS can certainly resolve both mail.example.com
and example.com
to the same public IP address.
In general, the IP datagrams containing requests to your public IP address, which will be received by the external interface of your firewall, don't contain the name of the host the remote client is attempting to access. Your firewall can't magically "know" which hostname the remote client resolved, since both hostnames resolve to the same IP address. The IP layer isn't aware of the hostname used at the application layer.
The TCP and UDP protocols differentiate specific services offered by a host using port numbers. In the case of your example it may be possible to use the port forwarding (also called port address translation, or PAT) feature of your NAT firewall to send incoming requests to TCP port 80 (HTTP) to the web server while sending inbound TCP port 25 (SMTP) to your email server.
If, however, you plan to host the same service on both machines then this strategy becomes problematic. Suppose you are going to host both a secure web site on your web server (for Customer access) and a secure web site on your email server (for webmail). Requests coming to your NAT firewall's public IP address to TCP port 443 (HTTPS) can only be routed to one server or the other.
The generalized solution to this situation is to have more public IP addresses. Because IPv4 addresses are becoming scarce that can also be problematic.
We end up working around the scarcity of public IP addresses in some protocols at the application layer. For example, HTTP/1.1 added the Host:
header specifically to allow a web server to host multiple websites on the same public IP address. TLS adds the Server Name Indication (SNI) extension to allow selection of the appropriate certificate based on the hostname entered by the remote client.
Doing this kind of workaround in the application layer means that every application layer protocol would need its own "fix" (and then all the server and client software would have to implement that "fix"). That's a tall order.
In lieu of modifying the application layer protocol some protocols are easily amenable to being "multiplexed" between multiple hosts using software that can "route" requests. This likely goes beyond what a simple NAT firewall is capable of because the packets need to be inspected at the application layer. Using a reverse-proxy like nginx is a good example of this kind of "multiplexing" (or Web publishing rules on Forefront TMG or ISA Server in a Microsoft environment) for the HTTP protocol. In theory any protocol could be multiplexed via a reverse proxy but the more esoteric the protocol the more likely you'd be talking about having custom code written.
When you need to offer the same service from two different hosts on a single public IP address you always have the option to move one of the hosts to a non-standard port. This will require that clients be aware of the non-standard port, however. In the case of HTTP(S) this results in URLs with the http://example.com:XXX
notation (where XXX
is the non-standard port number). Whether this would be problematic in your situation is something that only you can decide. (My experience has shown that virtually no end users are capable of handling :XXX
port notation in any URL they have to hand-enter.)
Solution 2:
Your "Port Forwarding" feature may let you send traffic destined for :80 and :443 to 192.168.124.30 and the remaining ports (or just those your email server is configured to use) to 192.168.124.32. If for some reason you need either of those two ports for the email server as well as for the web server, you're in trouble. For this method to work, any web access to your email server would have to be on a different (most likely non-standard) port. You would probably also set up the web server to redirect anything that says "mail.example.com
" to use https://mail.example.com:other_port
instead, for the users who don't know how to append the port number and/or specify secure connection. (You are going to use only secure web connections to the mail server, right?)
This is at the Transport layer rather than the Application layer, which means it doesn't have to rely on deep packet inspection. Instead it can look at an easy-to-find location in the TCP header for the port.