MacOS – Port Forwarding on macOS Sierra

macos

I've switched to macOS Sierra and am not able to get port forwarding working for localhost (http and https) using the loopback interface lo0. I'm using pf and following the existing instructions for El Capitan but without success:

https://apple.stackexchange.com/a/230331/81267, http://blog.brianjohn.com/forwarding-ports-in-os-x-el-capitan.html

Basically, I setup ifconfig:

sudo ifconfig lo0 10.0.0.1 alias

Then I create a pf anchors file: /etc/pf.anchors/myorganization

rdr pass on lo0 inet proto tcp from any to 10.0.0.1 port = 80 -> 127.0.0.1 port 3000
rdr pass on lo0 inet proto tcp from any to 10.0.0.1 port = 443 -> 127.0.0.1 port 7000

Add a reference to it in pf.conf (had to disable and then re-enable SIP to do this):

rdr-anchor "myorganization"
...
load anchor "myorganization" from "/etc/pf.anchors/myorganization"

I test the anchors:

sudo pfctl -vnf /etc/pf.anchors/myorganization

and the result looks good:

...
TRANSLATION RULES:
nat-anchor "com.apple/*" all
rdr-anchor "com.apple/*" all
rdr-anchor "myorganization" all
...

I've enabled them:

sudo pfctl -evf /etc/pf.conf

I've added localhost to my /etc/hosts

127.0.0.1   localhost

But when I browse to http://localhost I get ERR_CONNECTION_REFUSED. If I browse to http://localhost:3000 the site is working fine.

Update
I turned on pf logging and tried without the 10.0.0.1 alias:

rdr pass log (all) on lo0 inet proto tcp from any to any port 80 -> 127.0.0.1 port 3000
rdr pass log (all) on lo0 inet proto tcp from any to any port 443 -> 127.0.0.1 port 7000

And the first time I hit http://localhost, I see the log:

00:00:00.000000 rule 4294967295/8(ip-option): pass in on en0: (tos 0x0, ttl 1, id 59674, offset 0, flags [none], proto IGMP (2), length 32, options (RA))
    192.168.0.106 > 224.0.1.60: igmp v2 report 224.0.1.60
00:00:00.204784 rule 4294967295/8(ip-option): pass in on en0: (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto IGMP (2), length 32, options (RA))
    192.168.0.3 > 224.0.0.252: igmp v2 report 224.0.0.252
00:00:00.093232 rule 4294967295/8(ip-option): pass out on en0: (tos 0x0, ttl 1, id 11047, offset 0, flags [none], proto IGMP (2), length 32, options (RA))
    192.168.0.77 > 224.0.0.251: igmp v2 report 224.0.0.251
00:00:00.111608 rule 4294967295/8(ip-option): pass in on en0: (tos 0x0, ttl 1, id 60629, offset 0, flags [none], proto IGMP (2), length 32, options (RA))
    192.168.0.106 > 239.255.255.250: igmp v2 report 239.255.255.250
00:00:00.102426 rule 4294967295/8(ip-option): pass in on en0: (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto IGMP (2), length 32, options (RA))
    192.168.0.3 > 224.0.0.251: igmp v2 report 224.0.0.251
00:00:00.000120 rule 4294967295/8(ip-option): pass in on en0: (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto IGMP (2), length 48, options (RA))
    192.168.0.3 > 224.0.0.22: igmp v3 report, 2 group record(s) [gaddr 224.0.0.251 is_ex, 0 source(s)] [gaddr 224.0.0.252 is_ex, 0 source(s)]

Subsequent hits to localhost add nothing to the logs and I see that the loopback interface lo0 doesn't show in that log, just en0 (Ethernet), so I'm not convinced this log output is relevant to the problem. I also tried adding en0 and en1 to the /etc/pf.anchors/myorganization file but same results.

Best Answer

My answer to the question: What is the modern way to do port-forwarding on El Capitan? (forward port 80 to 8080) is still valid.

You have several frictions/misconfigurations in your setup though:

  • There is no need to establish an additional network address (i.e. 10.0.0.1) for lo0 if you don't have a second http/https host.
  • A redirection:

    rdr pass on lo0 inet proto tcp from any to 10.0.0.1 port = 80 -> 127.0.0.1 port 3000
    

    will only redirect a request for 10.0.0.1:80 to 127.0.0.1:3000.

    A request for localhost:80 (which translates to 127.0.0.1:80 and not to 10.0.0.1:80) won't be redirected because there is no appropriate rdr ... line and you will get a connection error.

  • Even adding the line 10.0.0.1 localhost to /etc/hosts will not salvage your problem because localhost seems to be hard coded to 127.0.0.1.

To get your redirection working unload pf.conf with sudo pfctl -d. Then check your anchor and pf.conf:

rdr pass log (all) on lo0 inet proto tcp from any to any port 80 -> 127.0.0.1 port 3000
rdr pass log (all) on lo0 inet proto tcp from any to any port 443 -> 127.0.0.1 port 7000

and

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

Then parse/check myorganization with sudo pfctl -vnf /etc/pf.anchors/myorganization and load pf.conf with sudo pfctl -evf /etc/pf.conf.

In some rare cases you may have to add an additional line:

::1     127.0.0.1 

to your /etc/hosts file. This doesn't seem logical though and may apply to older Sierra versions only. I haven't been able to confirm this.