What is the modern way to do port-forwarding on El Capitan? (forward port 80 to 8080)

Solution 1:

To forward all port 80 traffic to port 8080, you can enter the following from the Terminal command line.

echo "
rdr pass inet proto tcp from any to any port 80 -> 127.0.0.1 port 8080
" | sudo pfctl -ef -

Taken from https://salferrarello.com/mac-pfctl-port-forwarding/

Solution 2:

The modern way to forward ports in El Capitan is using pf. In the example below all port 80 requests are forwarded to port 8080 on the same host. Please adjust the redirections to your needs.

  1. Create an anchor file org.user.forwarding in /private/etc/pf.anchors

    sudo touch /private/etc/pf.anchors/org.user.forwarding
    

    with the following content and a trailing empty line

    rdr pass on lo0 inet proto tcp from any to any port 80 -> 127.0.0.1 port 8080
    rdr pass on en0 inet proto tcp from any to any port 80 -> 127.0.0.1 port 8080
    rdr pass on en1 inet proto tcp from any to any port 80 -> 127.0.0.1 port 8080
    

    or

    rdr pass inet proto tcp from any to any port 80 -> 127.0.0.1 port 8080
    
  2. Modify the file /private/etc/pf.conf but keep a trailing empty line

    original file:

    scrub-anchor "com.apple/*"
    nat-anchor "com.apple/*"
    rdr-anchor "com.apple/*"
    dummynet-anchor "com.apple/*"
    anchor "com.apple/*"
    load anchor "com.apple" from "/etc/pf.anchors/com.apple"
    

    to

    scrub-anchor "com.apple/*"
    nat-anchor "com.apple/*"
    rdr-anchor "com.apple/*"
    rdr-anchor "org.user.forwarding"
    dummynet-anchor "com.apple/*"
    anchor "com.apple/*"
    load anchor "com.apple" from "/etc/pf.anchors/com.apple"
    load anchor "org.user.forwarding" from "/etc/pf.anchors/org.user.forwarding"
    
  3. Parse and test your anchor file to make sure there are no errors:

    sudo pfctl -vnf /etc/pf.anchors/org.user.forwarding
    
  4. Now modify /System/Library/LaunchDaemons/com.apple.pfctl.plist from

    <array>
        <string>pfctl</string>
        <string>-f</string>
        <string>/etc/pf.conf</string>
    </array>
    

    to

    <array>
        <string>pfctl</string>
        <string>-e</string>
        <string>-f</string>
        <string>/etc/pf.conf</string>
    </array>
    

    You have to disable System Integrity Protection to accomplish this. After editing the file reenable SIP. After rebooting your Mac pf will be enabled (that's the -e option).

    In macOS 10.15 Catalina (and its read-only system volume) you have to edit the launch daemon in Recovery Mode. SIP is disabled by default in Recovery Mode - so no need to execute csrutil:

    /Volumes/Name_of_boot_volume/usr/bin/nano /Volumes/Name_of_boot_volume/System/Library/LaunchDaemons/com.apple.pfctl.plist
    

    with the default boot volume name Macintosh HD this is:

    /Volumes/Macintosh\ HD/usr/bin/nano /Volumes/Macintosh\ HD/System/Library/LaunchDaemons/com.apple.pfctl.plist
    

    Alternatively you may create your own launch daemon similar to the answer here: Using Server 5.0.15 to share internet WITHOUT internet sharing.

After a system update or upgrade some of the original files above may have been replaced and you have to reapply all changes.

If you want to forward across different interfaces you have to enable this in /etc/sysctl.conf:

net.inet.ip.forwarding=1
net.inet6.ip6.forwarding=1

Solution 3:

To extend solution from @sal-ferrarello answer, I created two super-basic Shell Scripts to enable or disable redirecting without compromising already existing entries in pf.

I. First find what entries do you already have with:

sudo pfctl -s nat

My output was like:

No ALTQ support in kernel
ALTQ related functions disabled
nat-anchor "com.apple/*" all
rdr-anchor "com.apple/*" all

What interests us is actual entries so ommit first two info lines.

II. Create enable.sh script:

#!/bin/sh
echo "
nat-anchor \"com.apple/*\" all
rdr-anchor \"com.apple/*\" all
rdr pass inet proto tcp from any to any port 80 -> 127.0.0.1 port 8080
" | sudo pfctl -ef -
sudo pfctl -s nat

First two lines after echo are the entries that were already there. Third line is with new redirect – in this case 80 to 8080. At the end we call sudo pfctl -s nat to see if changes were applied.

III. Create disable.sh script:

Similar to enable.sh we create script, but without 80->8080 redirect, but with previous already existing entries:

#!/bin/sh
echo "
nat-anchor \"com.apple/*\" all
rdr-anchor \"com.apple/*\" all
" | sudo pfctl -ef -
sudo pfctl -s nat