Create a gist now

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Port forwarding in Mavericks

Port Forwarding in Mavericks


Since Mavericks stopped using the deprecated ipfw (as of Mountain Lion), we'll be using pf to allow port forwarding.

####1. anchor file Create an anchor file under /etc/pf.anchors/<anchor file> with your redirection rule like:

rdr pass on lo0 inet proto tcp from any to 127.0.0.2 port 80 -> 127.0.0.1 port 40070

####2. Test the anchor file Parse and test your anchor file to make sure there are no errors:

sudo pfctl -vnf <anchor file>

####3. Reference the anchor in pf.conf /etc/pf.conf is the main configuration file that pf loads at boot. We'll need to load the anchor file we previously created:

rdr-anchor "forwarding"
load anchor "forwarding" from "/etc/pf.anchors/<anchor file>"

Make sure to add these entries to the appropriate spot.

####4. Load and enabling pf pf is not enabled by default in Mavericks, few ways to enable this:

  • Manually load and enable from a pf.conf file via sudo pfctl -ef <pf.conf file>

  • Auto enable by creating a launch daemon via this doc to run pfctl -ef <pf.conf file> on boot.

  • Auto enable by adding an -e(enable) to the pfctl ProgramArgument in /System/Library/LaunchDaemons/com.apple.pfctl.plist like this:

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

####5. Forwarding across interfaces By default, pf does not forward between interfaces. Here's a snippet from man for pfctl with help from 2sidedfigure:

The packet filter does not itself forward packets between interfaces.  Forwarding can be enabled by setting the sysctl(8) variables net.inet.ip.forwarding and/or net.inet6.ip6.forwarding to 1.  Set them permanently in sysctl.conf(5).

We'll need to enable this by adding to /etc/sysctl.conf:

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

Caution

There is the possibility that pf.conf will be overriden with updates to the OS. It might be best to create your own pf config file and load them in additon to the main pf.conf to prevent this.

@richie5um

This comment has been minimized.

Show comment
Hide comment
@richie5um

richie5um Dec 4, 2013

It is only minor, but, it is worth mentioning that the last rule in the config file must have a newline after it, otherwise the pfctl command will report Syntax error in config file.

This has taken me about an hour to work out, so, hopefully someone will find this a timesaver :-).

richie5um commented Dec 4, 2013

It is only minor, but, it is worth mentioning that the last rule in the config file must have a newline after it, otherwise the pfctl command will report Syntax error in config file.

This has taken me about an hour to work out, so, hopefully someone will find this a timesaver :-).

@figalex

This comment has been minimized.

Show comment
Hide comment
@figalex

figalex Jan 15, 2014

In step 3 you say "Make sure to add these entries to the appropriate spot." but what's the appropriate spot? I'm getting "Rules must be in order: options, normalization, queueing, translation, filtering" error when I try step 4.

figalex commented Jan 15, 2014

In step 3 you say "Make sure to add these entries to the appropriate spot." but what's the appropriate spot? I'm getting "Rules must be in order: options, normalization, queueing, translation, filtering" error when I try step 4.

@Speakus

This comment has been minimized.

Show comment
Hide comment
@Speakus

Speakus Jan 21, 2014

2alex0807 set 'rdr-anchor' after apple defined 'rdr-anchor' and 'load anchor' after apple defined 'load anchor'.

In my case pf-rules stop working after i use 'internet sharing' setting. Anyone know workaround for this issue?

Speakus commented Jan 21, 2014

2alex0807 set 'rdr-anchor' after apple defined 'rdr-anchor' and 'load anchor' after apple defined 'load anchor'.

In my case pf-rules stop working after i use 'internet sharing' setting. Anyone know workaround for this issue?

@sergiocampama

This comment has been minimized.

Show comment
Hide comment
@sergiocampama

sergiocampama May 1, 2014

also, it should say 127.0.0.1, not 127.0.0.2

sergiocampama commented May 1, 2014

also, it should say 127.0.0.1, not 127.0.0.2

@torgeir

This comment has been minimized.

Show comment
Hide comment
@torgeir

torgeir Jun 10, 2014

Doing this seems to make the port 40070 non responsive when accessed directry - suggestions?

torgeir commented Jun 10, 2014

Doing this seems to make the port 40070 non responsive when accessed directry - suggestions?

@aordway

This comment has been minimized.

Show comment
Hide comment
@aordway

aordway Aug 7, 2014

I can't seem to get this to work. I created a file /etc/pf.anchors/us.ihmc and the contents are
rdr on en1 inet proto tcp from any to 184.182.233.152 port = 4447 -> 184.182.233.152 port 443
I then edited /etc/pf.conf and added rdr-anchor "us.ihmc" after Apple's rdr-anchor and also added load anchor "us.ihmc" from "/etc/pf.anchors/us.ihmc" after Apple's load anchor.
I then executed the following: pfctl -vnf /etc/pf.anchors/us.ihmc which did not give any errors, then pfctl -f /etc/pf.conf and then pfctl -e
I should be able to telnet 184.182.233.152 4447 but I can not. I can telnet 184.182.233.152 443. What am I doing wrong???

aordway commented Aug 7, 2014

I can't seem to get this to work. I created a file /etc/pf.anchors/us.ihmc and the contents are
rdr on en1 inet proto tcp from any to 184.182.233.152 port = 4447 -> 184.182.233.152 port 443
I then edited /etc/pf.conf and added rdr-anchor "us.ihmc" after Apple's rdr-anchor and also added load anchor "us.ihmc" from "/etc/pf.anchors/us.ihmc" after Apple's load anchor.
I then executed the following: pfctl -vnf /etc/pf.anchors/us.ihmc which did not give any errors, then pfctl -f /etc/pf.conf and then pfctl -e
I should be able to telnet 184.182.233.152 4447 but I can not. I can telnet 184.182.233.152 443. What am I doing wrong???

@helderco

This comment has been minimized.

Show comment
Hide comment
@helderco

helderco Sep 2, 2014

Also not working for me... additionally to what @aordway said I've set the sysctl flags.

$ sudo sysctl -a | grep forwarding
net.inet.ip.forwarding: 1
net.inet6.ip6.forwarding: 1

helderco commented Sep 2, 2014

Also not working for me... additionally to what @aordway said I've set the sysctl flags.

$ sudo sysctl -a | grep forwarding
net.inet.ip.forwarding: 1
net.inet6.ip6.forwarding: 1
@jasonhinkle

This comment has been minimized.

Show comment
Hide comment
@jasonhinkle

jasonhinkle Nov 12, 2014

@figalex and anybody else who gets "Rules must be in order" error on a default Yosemite setup, the two lines can be placed immediately after the line: "rdr-anchor "com.apple/*" (note rdr-anchor, not anchor) You can't just append them to the end of the file.

jasonhinkle commented Nov 12, 2014

@figalex and anybody else who gets "Rules must be in order" error on a default Yosemite setup, the two lines can be placed immediately after the line: "rdr-anchor "com.apple/*" (note rdr-anchor, not anchor) You can't just append them to the end of the file.

@leovaz

This comment has been minimized.

Show comment
Hide comment
@leovaz

leovaz Dec 6, 2014

I didn't find this file /etc/sysctl.conf so i created it, but still does not work, when i execute this command it gives me something that i don't really know if is ok or not.

sh-3.2# sudo pfctl -ef pf.conf
pfctl: Use of -f option, could result in flushing of rules
present in the main ruleset added by the system at startup.
See /etc/pf.conf for further details.

No ALTQ support in kernel
ALTQ related functions disabled
pfctl: pf already enabled

leovaz commented Dec 6, 2014

I didn't find this file /etc/sysctl.conf so i created it, but still does not work, when i execute this command it gives me something that i don't really know if is ok or not.

sh-3.2# sudo pfctl -ef pf.conf
pfctl: Use of -f option, could result in flushing of rules
present in the main ruleset added by the system at startup.
See /etc/pf.conf for further details.

No ALTQ support in kernel
ALTQ related functions disabled
pfctl: pf already enabled

@Speakus

This comment has been minimized.

Show comment
Hide comment
@Speakus

Speakus Mar 19, 2015

Forwarding between interfaces stops to work for me since Yosemite, even when net.inet.ip.forwarding=1
Is anybody know how to fix this?

Speakus commented Mar 19, 2015

Forwarding between interfaces stops to work for me since Yosemite, even when net.inet.ip.forwarding=1
Is anybody know how to fix this?

@Speakus

This comment has been minimized.

Show comment
Hide comment
@Speakus

Speakus Mar 19, 2015

Can't update myself comment for some reason...
I have find solution. Just remove 'on lo0' from rdr rules and it works between interfaces even when net.inet.ip.forwarding == 0

Speakus commented Mar 19, 2015

Can't update myself comment for some reason...
I have find solution. Just remove 'on lo0' from rdr rules and it works between interfaces even when net.inet.ip.forwarding == 0

@ctgreybeard

This comment has been minimized.

Show comment
Hide comment
@ctgreybeard

ctgreybeard Jun 21, 2015

I am trying to forward from my Mavericks server to another machine, from port 23828 to port 8080 on the other machine. The file I have is:

rdr pass inet proto tcp from any to any port 23828 -> 192.168.2.62 port 8080

I set the rdr-anchor and load it as shown above. There are no errors shown.

net.inet.ip.forwarding=1

But when I have that loaded port 23828 is completely unresponsive on the server. Without that loaded the port refuses. So, apparently, "something" is happening, just not what I want.

Any ideas?

ctgreybeard commented Jun 21, 2015

I am trying to forward from my Mavericks server to another machine, from port 23828 to port 8080 on the other machine. The file I have is:

rdr pass inet proto tcp from any to any port 23828 -> 192.168.2.62 port 8080

I set the rdr-anchor and load it as shown above. There are no errors shown.

net.inet.ip.forwarding=1

But when I have that loaded port 23828 is completely unresponsive on the server. Without that loaded the port refuses. So, apparently, "something" is happening, just not what I want.

Any ideas?

@objectuser

This comment has been minimized.

Show comment
Hide comment
@objectuser

objectuser Mar 16, 2016

This works for me. I'm redirecting port 80 to 8080 and it does disable my use of 8080.

objectuser commented Mar 16, 2016

This works for me. I'm redirecting port 80 to 8080 and it does disable my use of 8080.

@bluebinary

This comment has been minimized.

Show comment
Hide comment
@bluebinary

bluebinary Jun 25, 2016

For others trying to use pf on OS X 10.11 El Capitan, while /etc/sysctl.conf does not appear to exist, you can use the sysctl command instead to set the relevant forwarding options (set the flags to 1 to enable, 0 to disable):

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

Once set these can be confirmed by running:

sudo sysctl -a | grep forwarding

bluebinary commented Jun 25, 2016

For others trying to use pf on OS X 10.11 El Capitan, while /etc/sysctl.conf does not appear to exist, you can use the sysctl command instead to set the relevant forwarding options (set the flags to 1 to enable, 0 to disable):

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

Once set these can be confirmed by running:

sudo sysctl -a | grep forwarding

@ekkis

This comment has been minimized.

Show comment
Hide comment
@ekkis

ekkis Nov 8, 2016

it should also be mentioned in the document that modifying the /System/Library/LaunchDaemons/com.apple.pfctl.plist requires disabling SIP (System Integrity Protection), which is a bit complicated

ekkis commented Nov 8, 2016

it should also be mentioned in the document that modifying the /System/Library/LaunchDaemons/com.apple.pfctl.plist requires disabling SIP (System Integrity Protection), which is a bit complicated

@rjjakes

This comment has been minimized.

Show comment
Hide comment
@rjjakes

rjjakes Nov 9, 2016

This helped me out a bunch today. Thank you!

rjjakes commented Nov 9, 2016

This helped me out a bunch today. Thank you!

@dandriana

This comment has been minimized.

Show comment
Hide comment
@dandriana

dandriana Nov 13, 2016

Works for me only when port forwarding is set to the same machine.
That is, this works :
rdr pass inet proto tcp from any to 192.168.1.12 port 5080 -> 192.168.1.12 port 9080

But, even though sysctl net.inet.ip.forwarding returns 1, this one doesn’t work (when another machine, 192.168.1.37, connects to 192.168.1.12:5080, it waits for 10 sec, then drops the connecion) :
rdr pass inet proto tcp from any to 192.168.1.12 port 5080 -> 192.168.56.2 port 80

With the latter, 192.168.56.2 seems to be receiving packets but not sending any packet back.

dandriana commented Nov 13, 2016

Works for me only when port forwarding is set to the same machine.
That is, this works :
rdr pass inet proto tcp from any to 192.168.1.12 port 5080 -> 192.168.1.12 port 9080

But, even though sysctl net.inet.ip.forwarding returns 1, this one doesn’t work (when another machine, 192.168.1.37, connects to 192.168.1.12:5080, it waits for 10 sec, then drops the connecion) :
rdr pass inet proto tcp from any to 192.168.1.12 port 5080 -> 192.168.56.2 port 80

With the latter, 192.168.56.2 seems to be receiving packets but not sending any packet back.

@snimavat

This comment has been minimized.

Show comment
Hide comment
@snimavat

snimavat Nov 19, 2016

I have the same problem as @dandriana -- has any one been able to forward to different ip ?

snimavat commented Nov 19, 2016

I have the same problem as @dandriana -- has any one been able to forward to different ip ?

@dohpaz42

This comment has been minimized.

Show comment
Hide comment
@dohpaz42

dohpaz42 Apr 18, 2017

Regarding SIP: Do not disable SIP. Instead, do the following for editing the com.apple.pfctl service:

  1. sudo launchctl unload -w /System/Library/LaunchDaemon/com.apple.pfctl.plist
  2. sudo cp /System/Library/LaunchDaemon/com.apple.pfctl.plist /Library/LaunchDaemon/com.apple.pfctl-override.plist
    (You must give the service a different name due to the directory search order)
  3. # Edit /Library/LaunchDaemon/com.apple.pfctl-override.plist to your heart's content
  4. # Don't forget to edit the <Label> to match the filename
  5. sudo launchctl load -w /Library/LaunchDaemon/com.apple.pfctl-override.plist
  6. Profit $$$

I cannot stress this enough: never, ever, ever, ever disable SIP. If you find yourself faced with a situation where you think disabling SIP is the solution: STOP! SIP is there for a very good reason. There is always a better solution. :)

dohpaz42 commented Apr 18, 2017

Regarding SIP: Do not disable SIP. Instead, do the following for editing the com.apple.pfctl service:

  1. sudo launchctl unload -w /System/Library/LaunchDaemon/com.apple.pfctl.plist
  2. sudo cp /System/Library/LaunchDaemon/com.apple.pfctl.plist /Library/LaunchDaemon/com.apple.pfctl-override.plist
    (You must give the service a different name due to the directory search order)
  3. # Edit /Library/LaunchDaemon/com.apple.pfctl-override.plist to your heart's content
  4. # Don't forget to edit the <Label> to match the filename
  5. sudo launchctl load -w /Library/LaunchDaemon/com.apple.pfctl-override.plist
  6. Profit $$$

I cannot stress this enough: never, ever, ever, ever disable SIP. If you find yourself faced with a situation where you think disabling SIP is the solution: STOP! SIP is there for a very good reason. There is always a better solution. :)

@yi-ji

This comment has been minimized.

Show comment
Hide comment
@yi-ji

yi-ji Jun 22, 2017

Not working at all, exact same situation with @helderco . My rule is:
rdr pass on {lo0,en0} inet proto tcp from any to 103.211.228.142 port {http,https} -> 127.0.0.1 port 32794

running pfctl -s info gives the result:

State Table                          Total             Rate
  current entries                        0
  searches                             707           23.6/s
  inserts                                0            0.0/s
  removals                               0            0.0/s
Counters
  match                                581           19.4/s
  bad-offset                             0            0.0/s
  fragment                               0            0.0/s
  short                                  0            0.0/s
  normalize                              0            0.0/s
  memory                                 0            0.0/s
  bad-timestamp                          0            0.0/s
  congestion                             0            0.0/s
  ip-option                              0            0.0/s
  proto-cksum                            0            0.0/s
  state-mismatch                         0            0.0/s
  state-insert                           0            0.0/s
  state-limit                            0            0.0/s
  src-limit                              0            0.0/s
  synproxy                               0            0.0/s
  dummynet                               0            0.0/s

only the match counter and searches are increasing. but I receive nothing at localhost port 32794.

Also, I tested what @dandriana said, and it is true, it works only when port forwarding is set to the same machine.

yi-ji commented Jun 22, 2017

Not working at all, exact same situation with @helderco . My rule is:
rdr pass on {lo0,en0} inet proto tcp from any to 103.211.228.142 port {http,https} -> 127.0.0.1 port 32794

running pfctl -s info gives the result:

State Table                          Total             Rate
  current entries                        0
  searches                             707           23.6/s
  inserts                                0            0.0/s
  removals                               0            0.0/s
Counters
  match                                581           19.4/s
  bad-offset                             0            0.0/s
  fragment                               0            0.0/s
  short                                  0            0.0/s
  normalize                              0            0.0/s
  memory                                 0            0.0/s
  bad-timestamp                          0            0.0/s
  congestion                             0            0.0/s
  ip-option                              0            0.0/s
  proto-cksum                            0            0.0/s
  state-mismatch                         0            0.0/s
  state-insert                           0            0.0/s
  state-limit                            0            0.0/s
  src-limit                              0            0.0/s
  synproxy                               0            0.0/s
  dummynet                               0            0.0/s

only the match counter and searches are increasing. but I receive nothing at localhost port 32794.

Also, I tested what @dandriana said, and it is true, it works only when port forwarding is set to the same machine.

@rdoust

This comment has been minimized.

Show comment
Hide comment
@rdoust

rdoust Jun 23, 2017

This was the only blog or entry anywhere on the web that worked for me. I'm running Sierra, developing a website that must get to a backend with CORS rules that make testing difficult. (I don't own the CORS filter. I have to somehow conform to it.) I develop in Eclipse, and deploy to Tomcat locally (from within Eclipse). Eclipse fails to start Tomcat on port 80, so I have to start it on 8080, but that won't allow me to get past the CORS filter. So, I had to set up a redirect from 10.0.0.1 port 80 to 127.0.0.1 port 8080, then set up a host in hosts file naming 10.0.0.1 in such a way that my requests pass the filter.

rdoust commented Jun 23, 2017

This was the only blog or entry anywhere on the web that worked for me. I'm running Sierra, developing a website that must get to a backend with CORS rules that make testing difficult. (I don't own the CORS filter. I have to somehow conform to it.) I develop in Eclipse, and deploy to Tomcat locally (from within Eclipse). Eclipse fails to start Tomcat on port 80, so I have to start it on 8080, but that won't allow me to get past the CORS filter. So, I had to set up a redirect from 10.0.0.1 port 80 to 127.0.0.1 port 8080, then set up a host in hosts file naming 10.0.0.1 in such a way that my requests pass the filter.

@inoicouldalwaysturn2u

This comment has been minimized.

Show comment
Hide comment
@inoicouldalwaysturn2u

inoicouldalwaysturn2u Aug 15, 2017

Would be nice to show how to do this temporarily as well. something like:

echo "
rdr pass on lo0 inet proto tcp from any to 127.0.0.2 port 80 -> 127.0.0.1 port 40070
" | sudo pfctl -ef -

not exactly sure what the code would be like. But something like that. it won't persist a restart, but i don't want mine to.

inoicouldalwaysturn2u commented Aug 15, 2017

Would be nice to show how to do this temporarily as well. something like:

echo "
rdr pass on lo0 inet proto tcp from any to 127.0.0.2 port 80 -> 127.0.0.1 port 40070
" | sudo pfctl -ef -

not exactly sure what the code would be like. But something like that. it won't persist a restart, but i don't want mine to.

@dlo

This comment has been minimized.

Show comment
Hide comment
@dlo

dlo May 23, 2018

@inoicouldalwaysturn2u - what you have is close to what works for me (on macOS 10.13.4):

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

dlo commented May 23, 2018

@inoicouldalwaysturn2u - what you have is close to what works for me (on macOS 10.13.4):

echo "rdr pass inet proto tcp from any to any port 80 -> 127.0.0.1 port 8000" | sudo pfctl -ef -
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment