raw code

Even if Mac-OSX has a Unix core, Apple put some layers on top of it, which makes it rather hard to freely hack around. That's why I wrote an own small DHCP server recently. Configuring a Mac (Macbook Pro in my case) to act as a NAT router is hairy as well. Sure, there are the sharing options, but they're quite limited and bring their own DHCP server, with no control over it anymore.

Setting up NAT by appealing to the core of OSX is not that hard. I assume your Mac (=router) has a Wifi connection to the internet (en0, configured with upstream DHCP). A network interface (en4), connected to the network which needs to be connected to the internet has a static IP address 192.168.3.1. You can set this static IP address either via the network settings or via the Terminal:

$ networksetup -setmanual "Ethernet" 192.168.3.1 255.255.0.0

Note: ifconfig would work as well, but can be overwritten by the network settings. So using networksetup is the better option.

Enable IP forwarding on OSX

Now we need to enable packet forwarding. This can be accomplished with the following command:

$ sudo sysctl -w net.inet.ip.forwarding=1

Now the interesting part. Apple changed the way NAT works quite often over the last versions of OSX. The most recent way is to use pfctl. To do this, add the following line to /etc/pf.conf:

nat on en0 from en4:network to any -> (en0)

Remember: en0 is the Wifi network with internet connection, en4 is the local network connection. To activate the change run the following commands:

# Disable PF if it was enabled before
sudo pfctl -d
# Enable PF and load the config
sudo pfctl -e -f /etc/pf.conf

Configure the clients

Either you use an own DHCP server or configure the other devices statically. In my case, it's just a Raspberry PI, which needs to be connected to the internet, so setting it statically can be done with:

# Set up the IP address
sudo ip addr add 192.168.3.3 dev eth0
# Set the default Gateway
sudo ip route add default via 192.168.3.1

To make this change permanent, edit /etc/network/interfaces and set the following attributes:

auto eth0
iface eth0 inet static
address 192.168.3.3
netmask 255.255.255.0
gateway 192.168.3.1
dns-nameservers 8.8.8.8 8.8.4.4

To make the change work, run

sudo /etc/init.d/networking restart