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.
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)”‘)
Thanks Speakus, you’re right. I love when code improvements involving removing lines. The page is now updated.
Thanks.
now code could be written to one line 😉
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.
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
Thanks Serkan, it is always nice to save some keystrokes.
So handy! Thanks a bunch for the heads up! All the other instructions I found were for ipfw and wouldn’t work on Yosemite.
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?
Hi Aaron,
Adding port 443 forwarding is an excellent suggestion. I’ve updated this article to forward both
80 -> 8080
and
443 -> 8443
I’m glad I asked! It worked perfectly, thanks!
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
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.
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?
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.
Hi Sal,
I found an answer to this on StackExchange https://apple.stackexchange.com/a/332603
That’s great – thanks for sharing Stephen.
I also have this same issue. It’d really help me to get access from the local machine right to the forwarded port
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: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.
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.
How would I go about making the forward more permanent? Every time I restart my machine it needs to be setup again.
Thanks!
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
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?
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.
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 😉
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). Thepfctl
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.
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.
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
, where192.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.
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.
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.
Hi Sal,
I want to visit my virtual box on port 8080, how is the pfctl setting? like the following?
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.
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:
Thank you very much!
I there a way to make this permanent?
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
你好,在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?
Hi Mr. Ferrarello,
Thank you for sharing the local port forwarding commands. I would like to know, how can you make your laptop a webserver by forwarding the URL DNS requests from client machines to your localhost:80?