• Skip to primary navigation
  • Skip to main content
Sal Ferrarello
  • About Sal Ferrarello
  • Speaking
  • Connect
    Mastodon GitHub Twitter (inactive)
You are here: Home / Dev Tips / Mac pfctl Port Forwarding

Mac pfctl Port Forwarding

Last updated on March 31, 2015 by Sal Ferrarello

Historically, I used ipfw from the command line to do port forwarding on my Mac. Unfortunately, as of Yosemite OS X 10.10 ipfw has been removed. (In all fairness, ipfw has been deprecated for some time but I continued using it because it was way easier than pfctl on the command line).

Command Line pfctl

pfctl seems to prefer configuration files to command line parameters, which I find frustrating. Fortunately, we can use command line pipes to work around this limitation.

Forward Port 80 and 443 with Mac pfctl Port Forwarding

You can copy and paste the following onto the command line.

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

Remove Port Forwarding

sudo pfctl -F all -f /etc/pf.conf

Display Your Current Port Forwarding Rules

sudo pfctl -s nat

Vagrant Port Forwarding with pfctl

As a WordPress developer, I use VVV for my virtual environment. By default, VVV does not expose the guest environment to other computers on your network. I address the general setup in Vagrant VVV Setup for WordPress Development. The port forwarding in Vagrant is accomplished using Vagrant triggers and these lines in my Customfile (or in your Vagrantfile if you’re not using VVV).

config.trigger.after [:up, :reload, :provision], :stdout => true do

system('echo "
rdr pass inet proto tcp from any to any port 80 -> 127.0.0.1 port 8080
rdr pass inet proto tcp from any to any port 443 -> 127.0.0.1 port 8443
" | sudo pfctl -ef - >/dev/null 2>&1; echo "Add Port Forwarding (80 => 8080)\nAdd Port Forwarding (443 => 8443)"')
end

Feel free to view and download my full VVV Custom file for port forwarding.

Sal Ferrarello
Sal Ferrarello (@salcode)
Sal is a PHP developer with a focus on the WordPress platform. He is a conference speaker with a background including Piano Player, Radio DJ, Magician/Juggler, Beach Photographer, and High School Math Teacher. Sal can be found professionally at WebDevStudios, where he works as a senior backend engineer.

Share this post:

Share on TwitterShare on FacebookShare on LinkedInShare on EmailShare on Reddit

Filed Under: Dev Tips, Programming Tagged With: network, vagrant, VVV

Reader Interactions

Comments

  1. Speakus says

    March 19, 2015 at 4:38 am

    it could be easier – remove ‘on en1’ from rule to apply to all interfaces:

    system(‘echo ”
    rdr pass inet proto tcp from any to any port 80 -> 127.0.0.1 port 8080
    ” | sudo pfctl -ef – >/dev/null 2>&1; echo “Add Port Forwarding (80 => 8080)”‘)

    Reply
    • Sal Ferrarello says

      March 19, 2015 at 6:28 am

      Thanks Speakus, you’re right. I love when code improvements involving removing lines. The page is now updated.

      Thanks.

      Reply
  2. Speakus says

    March 19, 2015 at 7:14 am

    now code could be written to one line 😉

    Reply
    • Sal Ferrarello says

      March 19, 2015 at 2:31 pm

      Thanks Speakus, this is great. I’ve updated the command line version at the top of this page but left the Vagrant version split across multiple lines for readability.

      Thanks again.

      Reply
  3. Serkan Yersen says

    March 25, 2015 at 8:41 pm

    Thanks for this, it’s very useful. I’ve created aliases for these to simplify and remember the commands :).

    Just put it in the `~/.basrc` or `~/.zshrc` and source it.
    http://d.pr/n/15y8J/4T2kXiqs

    Reply
    • Sal Ferrarello says

      March 27, 2015 at 6:28 am

      Thanks Serkan, it is always nice to save some keystrokes.

      Reply
  4. Naresh Chandranatha says

    March 30, 2015 at 10:38 pm

    So handy! Thanks a bunch for the heads up! All the other instructions I found were for ipfw and wouldn’t work on Yosemite.

    Reply
  5. Aaron Foster says

    March 30, 2015 at 10:59 pm

    Thanks Sal, this works great! I forwarded port 80 to 8080 exactly as you’ve shown. I also tried to forward port 443 to 8443, and that worked as well. However, after doing that, port 80 was no longer forwarding to 8080. Is this command able to forward more than one port at a time?

    Reply
    • Sal Ferrarello says

      March 31, 2015 at 9:41 am

      Hi Aaron,
      Adding port 443 forwarding is an excellent suggestion. I’ve updated this article to forward both
      80 -> 8080
      and
      443 -> 8443

      Reply
      • Aaron Foster says

        April 2, 2015 at 3:10 pm

        I’m glad I asked! It worked perfectly, thanks!

        Reply
  6. Gonzalo says

    April 22, 2015 at 9:55 am

    I am trying to forward outgoing traffic to 192.168.64.1 on port 8161 to localhost on the same port (that is, redirect it back to my computer). How can I achieve this?

    Thanks

    Reply
    • Sal Ferrarello says

      April 22, 2015 at 2:47 pm

      Hi Gonzalo, that is not something I’m familiar with setting up. If you find a solution, I’d certainly be interested to hear how you do it.

      Best of luck.

      Reply
  7. Ruchir Godura says

    May 12, 2015 at 3:25 pm

    Hi Sal.
    After redirecting port 80 to 9080, I find that on my local machine (i.e. the one on which the server is running) I am able to connect via port 80 but not directly via 9080.
    i.e., http://127.0.0.1 works, but not
    http://127.0.0.1:9080

    From external computers both ports are reachable.. any ideas?

    Reply
    • Sal Ferrarello says

      May 13, 2015 at 1:01 pm

      Hi Ruchir,

      I get the same behavior you’ve described. My host machine is http://10.0.1.6/.

      Using the port forwarding rules defined in this blog post.

      Local Machine
      http://10.0.1.6/ (works)
      http://10.0.1.6:8080 (does NOT works)

      From Another Machine on the Network
      http://10.0.1.6/ (works)
      http://10.0.1.6:8080 (works)

      I honestly don’t know why this behavior occurs.

      I’m guessing it has something to do with accessing the network interfaces on the same machine versus over the network. You could copy and modify an outdated version of my Vagrant Custom File where interfaces lo0, en0, en1 are defined separately. That would be where I would start in trying to understand what is going on. https://gist.github.com/salcode/da45f09ca0c319a108db/c239cd1eb9885c123686ef6d71e5b4abbe8b7625

      If you determine a solution and/or explanation, I’d be very interested in hearing it. Thanks for your comment.

      Reply
      • Stephen James says

        March 6, 2019 at 2:03 am

        Hi Sal,

        I found an answer to this on StackExchange https://apple.stackexchange.com/a/332603

        
        echo 'no rdr inet proto tcp from 127.0.0.1 port 8080
        rdr inet proto tcp from any to 127.0.0.1 port 80 -> 127.0.0.1 port 8080
        ' | sudo pfctl -ef -
        
        Reply
        • Sal Ferrarello says

          March 7, 2019 at 2:51 pm

          That’s great – thanks for sharing Stephen.

          Reply
    • Jordan Alperin says

      June 17, 2015 at 7:38 pm

      I also have this same issue. It’d really help me to get access from the local machine right to the forwarded port

      Reply
    • jaume says

      August 1, 2018 at 8:49 am

      Hi Sal, Ruchir and Jordan

      This worked for me: add another rule to exclude the address and port the web server is listening on (in Ruchir’s comment that would be 127.0.0.1:9080) from being redirected, like this:

      no rdr inet proto tcp from 127.0.0.1 port 9080 #  127.0.0.1 port 9080

      After enabling both rules I was able to access both the port the web server was bound to (127.0.0.1:9080) and the redirected port (127.0.0.1:80). See my answer at StackExchange for more information:
      https://apple.stackexchange.com/a/332603/32815
      and thank you all for the useful article and comments.

      Reply
      • Sal Ferrarello says

        August 1, 2018 at 9:55 am

        Thanks jaume.

        Anyone looking to learn more about port forwarding on a Mac should definitely read jaume’s StackExchange answer. It is well written with supporting links – good stuff.

        Reply
  8. Austin says

    May 18, 2015 at 7:24 pm

    How would I go about making the forward more permanent? Every time I restart my machine it needs to be setup again.
    Thanks!

    Reply
    • Sal Ferrarello says

      May 19, 2015 at 2:38 pm

      Hi Austin,

      I’ve not done this. I apply the rules when my vagrant box comes up and remove them when the box goes down (see my VVV Customfile for port forwarding).

      For what you are describing, I’d start by checking out http://stackoverflow.com/questions/6442364/running-script-upon-login-mac#answer-13372744

      Reply
  9. Andrew says

    June 12, 2015 at 2:41 pm

    Hi guys! Do you actually know how to just open port 9 for UDP packets with pf on mac os x? I’m trying to set up wake on lan and It doesn’t work. when I scan with `sudo nmap -sU -p 9 localhost`, I’m getting: `port closed`. Could anyone help?

    Reply
    • Sal Ferrarello says

      June 12, 2015 at 3:39 pm

      Hi Andrew,

      Unfortunately, I don’t know how to create the setup you are describing. Perhaps someone else can comment and answer your question. Best of luck.

      Reply
  10. Andres says

    July 27, 2015 at 6:27 pm

    Hi, i’m having problems accessing other pages from my smartphone when i run this script:

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

    I’m running a Weblogic server that needs the port 7101, i can access the applications in it, like 192.168.2.1:7101/myapplication from my smartphone, but i lost total access to other pages like http://www.google.com or wherever.

    I think that is maybe because all requests that use port 80 are changed to 7101, but that is not the idea, i only want that requests to the ip 192.168.2.1 (Weblogic server in my Mac computer) are changed.

    Do you know how can i fix this? should i buy a router?

    thanks for your time, and sorry for my bad english 😉

    Reply
    • Sal Ferrarello says

      July 28, 2015 at 8:04 am

      Hi Andres,

      In my experience, running pfctl on my Mac has no affect on accessing other URLs from my smartphone. My smartphone connects to my router directly (as if my Mac were not even on the network). The pfctl port forwarding code only has an affect when my smartphone connects to my Mac by going to its IP address (e.g. 192.168.1.5 as determined by my notes in my Find My Local IP Address instructions).

      Perhaps your smartphone is accessing the Internet through your Mac as a proxy, in which case I don’t know how you would need to modify the pfctl settings.

      If you do determine how to make this work, I’d be interested in hearing about your solution. Best of luck.

      Reply
  11. Shreya Dahal says

    June 8, 2016 at 12:19 am

    Hey,
    I have a mac that has an rdr rule that redirects all the requests to port 80 to a different port on this computer itself:

    rdr pass inet proto tcp from 192.168.0.102 to any port = 80 -> 127.0.0.1 port 9882

    where 192.168.0.102 is my current ip address. Am I understanding the rule correct?

    The effect this has is that any http connection I try on a browser gives me a connection refused error. HTTPS works alright though.

    I have tried to remove this rule using different methods. If I do a sudo pfctl -F all and open a http webpage quickly (like withing a second), the page opens. But after that the rule is back and http is blocked again.

    I tried to disable pf with sudo pfctl -d, but the rule is still in effect.

    I have tried to look for the rule in the default places (/etc/pf.conf and its anchors), and didn’t find anything. I am guessing this is a malware issue.

    How can I go about solving this?

    PS: I am not used to OS X, but I have experience with Linux.

    Reply
    • Sal Ferrarello says

      June 8, 2016 at 11:28 am

      Hi Shreya,

      If I understand correctly, whenever you run
      sudo pfctl -s nat
      the output is
      rdr pass inet proto tcp from 192.168.0.102 to any port = 80 -> 127.0.0.1 port 9882, where 192.168.0.102 is whatever you current IP address is.

      Furthermore, if you run
      sudo pfctl -F all -f /etc/pf.conf
      and then run
      sudo pfctl -s nat
      the rule still appears (i.e. it is not deleted).

      Unfortunately, I’m not familiar with this issue or what could cause it but malware does seem to be one possibility. Best of luck of with it.

      Reply
    • Ricardo Mesquuita says

      August 29, 2016 at 12:39 pm

      Hi guys, I have exactly the same issue. I am getting crazy trying to solve it. Nothing works.
      No traffic destined to port 80 exits my Wireless adapter (verified using Wireshark). All other traffic works fine. Issue only happens in Wireless adapter.
      Troubleshooting this issue I have found the following PF rule:
      pass out on en0 route-to lo0 inet proto tcp from 192.168.1.8 to any port = 80 flags S/SA keep state
      And the rule’s source IP changes whenever my IP address changes.
      As Shreya comment, I did everything but nothing disables/deletes this rule.
      Any idea?
      Thanks.

      Reply
  12. Mark Farber says

    July 1, 2016 at 12:03 pm

    Hello. I have the following setup and need some help. Primary computer has a staic IP address ox 152.xx.xx.xx and I have a NAS commected to its second ethernet port and I share my ethernet connection to it. The NAS therefore has a private IP address of 192.168.2.3. The NAS can connect to the internet. I can connect to the NAS from the local machine. I CANNOT connect to the NAS from outside th network. How do I port forward 152.xx.xx.xx:7777 to 192.168.2.3 so that I can access my NAS from outside the network.

    Reply
  13. Ricky says

    May 2, 2017 at 5:08 am

    Hi Sal,

    I want to visit my virtual box on port 8080, how is the pfctl setting? like the following?

    rdr pass inet proto tcp from any to any port = 80 -> 192.168.56.101 port 8080
    Reply
    • Sal Ferrarello says

      May 2, 2017 at 2:53 pm

      Hi Ricky,

      I don’t think you need to use pfctl to access you machine on port 8080.

      The reason I’m using port forwarding is I want to access port 80 on my virtual machine but I’m creating the virtual machine with vagrant and vagrant will not allow one to use a host port less than 1025. To work around this, I’m setting up my virtual machine to use port 8080 and then using pfctl to forward port 80 to port 8080.

      I hope this helps.

      Reply
  14. Rusty says

    May 5, 2017 at 6:28 am

    Very helpful. I think another clean-up command to stop the forward of IP traffic from the mac would be a good addition. I can turn off Port Forwarding but you should also turn off forwarding of all traffic.

    The opposite of:

    sudo sysctl -w net.inet.ip.forwarding=1
    Reply
  15. Blake W says

    October 26, 2017 at 4:40 pm

    Thank you very much!

    Reply
  16. Fred Rodrigues says

    November 13, 2018 at 4:35 pm

    I there a way to make this permanent?

    Reply
  17. Riting LIU says

    October 12, 2020 at 11:09 pm

    Hi Sal,

    Many thanks for your solution.
    I googled tons of results to find only yours gets the point.

    It is over five years since you post this thread.
    Feel lucky it is still alive 🙂

    Riting

    Reply
  18. 一粒麦子 says

    June 25, 2022 at 7:00 am

    你好,在macos中,我需要将一个外部公网端口号转发到本地,比如说:将windows的公网123.34.345.345:8080 和 localhsot:8080,在访问 localhsot:8080可以重定向到123.34.345.345:8080(windows) ,我需要怎么做?

    Hello, in MacOS, I need to forward an external public network port number to the local. For example, I need to redirect the public network 123.34.345.345:8080 and localhsot:8080 of windows to 123.34.345.345:8080 (Windows) when accessing localhsot:8080. What should I do?

    Reply

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Copyright © 2023 · Bootstrap4 Genesis on Genesis Framework · WordPress · Log in