We all know the trouble: today's stupid ISPs will only give you one IP-address so to connect more than one computer, we need to use RFC 1918 IP-addresses, also known as private IP-addresses. This is all nice and dandy when all you're doing is accessing servers on the internet from behind your router, which will inevitably use Network Address Translation (NAT) to allow you to do so. It's an incredible headache if you want to go the other way around: set up a service on one of your machines that people on the internet will be able to access.

Luckily, we can forward ports. You can only forward a single port once though, so take into consideration what machine you're forwarding to. You can't have two forwards for port 25, for instance, unless they are on different IP addresses. (On a side note, if you're forwarding webservers, use apache's reverse proxy feature for that to allow multiple servers based on the URL).

In Linux, I would use iptables for this. Unfortunately the machine I want to forward a port on doesn't run linux. It runs Mac OS X server. Given my knowledge of how this is done with the same tool as setting up a firewall in linux, I set out to do the same on osx and found that ipfw (the tool that manipulates firewall rules in BSDs and OSX) knows an action called 'forward'. Hold it, that's not it. That does forward, like it says. But it doesn't do NAT. Which we want, because otherwise.. Well it just won't work properly.

Connection sharing in BSD is handled using a userland process called 'natd'. Incidentally, natd is also capable of properly forwarding ports to other machines. Great. Now let's find out how. There isn't much documentation on this, but I did figure it out eventually. This is OSX-specific, I must add.

Apple stores the configuration for natd in /etc/nat/natd.conf.apple. Don't change that though, it's generated every time natd starts. The basis for the generated file is in /etc/natd/natd.plist. Open that up. It's a fairly standard XML file with some settings in it. Add the following to the end of it, just before the two last closing tags:

        <key>redirect_port</key>
        <array>
                <dict>
                        <key>aliasIP</key>
                        <string>INCOMING IP</string>
                        <key>aliasPortRange</key>
                        <string>INCOMING PORT</string>
                        <key>proto</key>
                        <string>tcp</string>
                        <key>targetIP</key>
                        <string>OUTGOING IP</string>
                        <key>targetPortRange</key>
                        <string>OUTGOING PORT</string>
                </dict>
        </array>

Replace the incoming and outgoing ips and ports with whatever your network requires. Incoming is the ip address on your server, target is the ip address of the machine you're forwarding to.

You can now restart natd, for example by stopping and starting internet sharing. If all went well, your machine now forwards the port(s) you listed. Don't forget to allow it in your firewall!

As a last note: this was tested and verified to work on MacOS X Server 10.3. It should also work on MacOS X Server 10.4. However, the configuration files do not seem to exist on the non-server version.