Mac DHCP Server

ethernetinternet-sharingNetworkwifi

I often have the need to connect to devices directly through the ethernet port on my MacBook.

  • When I am connected to a wireless network, I can share my connection to ethernet. However, the second, I loose the wireless connection, I loose connectivity to the devices.

  • I can set up a static IP on both the MacBook and the Device, but this is not very easy because I still have to make an initial connection to setup the static IP.

Is there any way to setup a DHCP server on the ethernet port that works even if I am not connected to a network?

Best Answer

Based on my answer here: Using Server 5.0.15 to share internet WITHOUT internet sharing I provide a possibility to share internet with PF and dnsmasq (i.e. without Apple's OS X Server):

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. Additionally you have to set up a DNS/DHCP server: dnsmasq.

Below I assume en0: the interface connected to the internet or a router and en1: the interface connected to the LAN. The router has the IP 192.168.0.1 and the netmask 255.255.255.0.

Use ifconfig to get the device names.

Prepare the Mac gateway:

  • Set up the two interfaces en0 and en1 with fixed IPs and netmasks

    Example:

    en0: IP: 192.168.0.2 Netmask: 255.255.255.0 Gateway: 192.168.0.1 DNS: 8.8.8.8 and 127.0.0.1 Search Domains: home.org
    en1: IP: 192.168.1.1 Netmask: 255.255.255.0

  • Disable System Integrity Protection if El Capitan is installed

  • Install Xcode Command Line tools/Xcode
  • Install, set up and doctor brew
  • Install dnsmasq:

    brew install dnsmasq
    
  • Set up and configure dnsmasq

    cp /usr/local/opt/dnsmasq/dnsmasq.conf.example /usr/local/etc/dnsmasq.conf
    sudo mkdir -p /usr/local/var/lib/misc
    sudo touch /usr/local/var/lib/misc/dnsmasq.leases
    

    open /usr/local/etc/dnsmasq.conf with an editor and modify at least the following lines:

    ~ line 144
    # 3) Provides the domain part for "expand-hosts"
    domain=home.org
    
    ~ line 163
    # don't need to worry about this.
    dhcp-range=192.168.1.50,192.168.1.100,255.255.255.0,12h
    
    ~ line 243
    # Always give the host with Ethernet address 11:22:33:44:55:66
    # the name fred and IP address 192.168.0.60 and lease time 45 minutes
    dhcp-host=11:22:33:44:55:66,raspberry,192.168.1.70,12h
    **use the proper MAC of your raspberry here**
    
    ~ line 536
    # This defaults to a sane location, but if you want to change it, use
    # the line below.
    dhcp-leasefile=/usr/local/var/lib/misc/dnsmasq.leases
    

    You may configure much more - just check the config file and its descriptions.

    sudo brew services start dnsmasq
    sudo chmod 644 /Library/LaunchDaemons/homebrew.mxcl.dnsmasq.plist
    sudo chown root:wheel /Library/LaunchDaemons/homebrew.mxcl.dnsmasq.plist
    
  • Create a file named nat-rules in /private/etc/ with the following content

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

    #!/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
    
  • 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/bin/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.

  • Modify ownership and file modes:

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

    sudo launchctl load /Library/LaunchDaemons/org.user.natpf.plist
    
  • Reboot your gateway Mac. If everything works fine enable SIP again.

    The file /tmp/org.user.natpf.stderr contains error messages. You may add a similar key to the file /Library/LaunchDaemons/homebrew.mxcl.dnsmasq.plist to get potential error messages:

        ...
        <key>StandardErrorPath</key>
        <string>/tmp/homebrew.mxcl.dnsmasq</string>
        <key>StandardOutPath</key>
        <string>/tmp/homebrew.mxcl.dnsmasq</string>
        ...
    

Prepare your Internet Router (if you have one)

  • Add a static route: Network: 192.168.1.0 Netmask: 255.255.255.0 Gateway: 192.168.0.2

Prepare your Raspberry

  • You may have to reboot it.

After setting all things up successfully you should have a reliable LAN with NAT, DHCP and DNS. You may even enter ping raspberry with a proper result.

If you run into problems leave acomment.