Using Server 5.0.15 to share internet WITHOUT internet sharing

The newest OS X Server versions don't provide any tools to enable NAT/Routing in OS X.

To get NAT working without using Internet Sharing you have to use a pf rule and create a plist to enable forwarding and load the pf rule:

Below I assume en0: the interface connected to the cable modem and en1: the interface connected to the LAN. DHCP and DNS are set up properly in the internal LAN.

  1. Create a pf NAT rule:

    Create a file named nat-rules in /private/etc/ with the following content

    nat on en0 from en1 to any -> (en0)
    
  2. Create a shell script named nat-pf.sh enabling forwarding and loading the pf rule. I saved it in /usr/local/:

    #!/bin/sh
    
    sysctl -w net.inet.ip.forwarding=1
    sysctl -w net.inet.ip.fw.enable=1
    
    #disables pfctl
    pfctl -d
    
    sleep 1
    
    #flushes all pfctl rules
    pfctl -F all
    
    sleep 1
    
    #starts pfctl and loads the rules from the nat-rules file
    pfctl -f /private/etc/nat-rules -e
    
  3. Create a plist named org.user.natpf.plist with the following content and save it in /Library/LaunchDaemons/ to execute the above shell script at start-up:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <key>Disabled</key>
        <false/>
        <key>KeepAlive</key>
        <dict>
            <key>SuccessfulExit</key>
            <false/>
        </dict>
        <key>Label</key>
        <string>org.user.natpf</string>
        <key>ProgramArguments</key>
        <array>
            <string>/usr/local/nat-pf.sh</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
        <key>StandardErrorPath</key>
        <string>/tmp/org.user.natpf.stderr</string>
        <key>StandardOutPath</key>
        <string>/tmp/org.user.natpf.stdout</string>
    </dict>
    </plist>
    

    All three files need a trailing empty line so don't simply copy the above code/lines.

  4. Modify ownership and file modes:

    sudo chown root:wheel /private/etc/nat-rules
    sudo chown root:wheel /usr/local/nat-pf.sh
    sudo chmod 755 /usr/local/nat-pf.sh
    sudo chown root:wheel /Library/LaunchDaemons/org.user.natpf.plist
    
  5. Load the launch daemon:

    sudo launchctl load /Library/LaunchDaemons/org.user.natpf.plist
    
  6. After testing everything you can delete the following part in the plist:

        <key>StandardErrorPath</key>
        <string>/tmp/org.user.natpf.stderr</string>
        <key>StandardOutPath</key>
        <string>/tmp/org.user.natpf.stdout</string>
    

    org.user.natpf.stderr provides error messages to debug your plist.

  7. On my local router I had to add a static route:

    192.168.3.0/24 (the internal network) -> 192.168.0.2 (Mac mini IP-address of the external interface connected to the router)

    This last step may not apply to your network environment!