Server Fault is a question and answer site for system and network administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I want to forward requests from 192.168.99.100:80 to 127.0.0.1:8000. This is how I'd do it in linux using iptables:

iptables -t nat -A OUTPUT -p tcp --dport 80 -d 192.168.99.100 -j DNAT --to-destination 127.0.0.1:8000

How do I do the same thing in MacOS X? I tried out a combination of ipfw commands without much success:

ipfw add fwd 127.0.0.1,8000 tcp from any to 192.168.99.100 80

(Success for me is pointing a browser at http://192.168.99.100 and getting a response back from a development server that I have running on localhost:8000)

share|improve this question
    
Are we talking OSX Client or Server? – Scott Pack Jan 13 '10 at 21:15
1  
It's snow leopard. – nafe Jan 13 '10 at 21:57
    
Is there some reason you can't just configure your web server to also listen on 192.168.99.100:80? – Zoredache Jan 13 '10 at 23:28
1  
@Zoredache Listening on port 80 needs sudo and some webservers don't drop privileges fast enough to safely run them with sudo. – Navin Dec 21 '15 at 10:33
up vote 24 down vote accepted

So I found out a way to do this. I'm not sure if it's the preferred way but it works! At your favourite shell:

sudo ifconfig lo0 10.0.0.1 alias
sudo ipfw add fwd 127.0.0.1,9090 tcp from me to 10.0.0.1 dst-port 80

(The alias to lo0 seems to be the missing part)

If you'd like a (fake) domain to point to this new alias then make sure /etc/hosts contains the line:

10.0.0.1 www.your-domain.com
share|improve this answer
2  
This is great! What I needed! Thanks a lot! – Yoldar-Zi Feb 4 '13 at 15:41

I was able to get this working using the ifconfig and pfctl commands on Mac 10.10.2. With the following approach I'm successfully mapping 127.0.0.1:3000 to mydomain.com locally on my machine.

In your command line enter the following two commands to forward connections to 127.0.0.1:3000 to 10.0.0.1:

sudo ifconfig lo0 10.0.0.1 alias
echo "rdr pass on lo0 inet proto tcp from any to 10.0.0.1 port 80 -> 127.0.0.1 port 3000" | sudo pfctl -ef -

Then edit your /etc/hosts or /private/etc/hosts file and add the following line to map your domain to 10.0.0.1.

10.0.0.1 mydomain.com

After you save your hosts file flush your local DNS:

sudo discoveryutil udnsflushcaches

Now open mydomain.com in a browser and you'll be seeing the server hosted on your localhost port (i.e. 127.0.0.1:3000). Basically this process maps an <ip>:<port> to a new <ip> so that you can then map a host that IP.

share|improve this answer
1  
Just a tad hacky, but gets the job done. Good show. – Joey Carson Apr 24 '15 at 13:57
    
Well that works. – user974407 Aug 23 '15 at 18:49
1  
Thank you. How would you undo the alias and the forwarding? – Carlos Nuñez Sep 7 '15 at 19:22
    
Hi sudo discoveryutil udnsflushcaches gives me command not found but it still matches the entry correctly. But how can I map a second port? I tried to do steps 1+2 with id: 10.0.0.2 and another port, but it always takes only the last connection. So if I do last 10.0.0.1 & port 3000 it forwards 3000, if I do last 10.0.0.2 and port 4000 it forwards 4000. In my /private/etc/hosts I wrote both entries with the (according) different id. – Andi Giga Feb 3 at 10:18

This worked well for me:

share|improve this answer

From 10.5 on, OS X comes with a new, application-oriented firewall instead of ipfw. But ipfw is still installed. If you have trouble with its syntax, check out graphical frontends like WaterRoof or Flying Buttress.

HTH, PEra

share|improve this answer

order of rules is important, make sure there is no "deny all" before your allow rules, or something like that.

share|improve this answer
    
Thanks for the advice but I don't think I have that particular problem (ipfw list only shows my rule and 65535 allow ip from any to any). – nafe Jan 13 '10 at 22:13

Your command seems to be missing a rule number; try:

ipfw add 100 fwd 127.0.0.1,8000 tcp from any to 192.168.99.100 80

(if you aren't running as root, you'll have to prefix it with sudo). Another thing to check is that the firewall is enabled:

sysctl net.inet.ip.fw.enable

If it comes back with the value 0 (off), turn it on with:

sysctl -w sysctl net.inet.ip.fw.enable=1

... and then arrange for it to get reenabled when the computer reboots. The "proper" way to do this is probably to create a launchd item (Lingon makes this fairly easy). Or just use one of the GUI tools PEra mentioned, and let it take care of the details.

share|improve this answer

I too had to do a similar thing recently, and in searching came upon this answer. Unfortunately, the answer of Nafe uses ipfw which is now deprecated and unavailable in OSX; and the answer of Kevin Leary is indeed a bit hackish. So I had to make something better (cleaner) and decided to share it here for posterity. This answer is largely based on the approach mentioned at this gist.

As OP mentions, pointing a browser at 192.168.99.100 should get a response from a server at localhost:8000. Adding an alias to ifconfig isn't really necessary, pfctl alone is sufficient: to achieve this the pf.conf file at /etc/pf.conf needs to be modified.

First we create (with sudo) a new anchor file (let's call it redirection) at: /etc/pf.anchors/redirection. This is basically a regular text file and contains the following line (just like in the answer of Kevin Leary): rdr pass on lo0 inet proto tcp from any to 192.168.99.100 port = 80 -> 127.0.0.1 port 8000. Once the new anchor file has been created, it needs to be referenced within the pf.conf file. Open the pf.conf file with sudo and add rdr-anchor "redirection" after the last rdr-anchor line (which is rdr-anchor "com.apple/*") and add load anchor "redirection" from "/etc/pf.anchors/redirection" at the end.

Ultimately, this is what the pf.conf file should look like:

scrub-anchor "com.apple/*"
nat-anchor "com.apple/*"
rdr-anchor "com.apple/*"
rdr-anchor "redirection"  #added for redirection/port forwarding
dummynet-anchor "com.apple/*"
anchor "com.apple/*"
load anchor "com.apple" from "/etc/pf.anchors/com.apple"
load anchor "pow" from "/etc/pf.anchors/redirection"  #added for redirection/port forwarding

And that's almost it. Just restart pfctl by issuing sudo pfctl -d to disable it first and then sudo pfctl -fe /etc/pf.conf to start it again.

Now, if you need this happen automatically after every restart, another tiny bit of work needs to be done: the launch daemon for pfctl needs to be updated (the referenced gist mentions that pf is enabled automatically on boot, however this does not seem to be the case from looking at the code). Open (with sudo) System/Library/LaunchDaemons/com.apple.pfctl.plist and look for this:

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

and add the line <string>-e</string> to ultimately make it like this:

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

That should do it.

Caveat: Apple no longer allows to change the launch demon files just like that (not with sudo, nor chmod, nor anything else). The only way is to tinker with the System Integrity Protection settings: boot into recovery mode and launch terminal. Check the SIP status with csrutil status, it should generally be enabled. Disable it with csrutil disable and reboot in normal mode and then do the changes to the plist file as discussed above. Once done, go back to recovery mode and re-enable the protection (it's in place for good reason) by issuing csrutil enable.

Explanation: One can check by issuing the ifconfig command that 127.0.0.1 is already the (default) alias for localhost lo0 - this fact is being used to avoid having to add an extra alias for localhost and to simply use the default address in the pf.conf file.

UPDATE: Unfortunately, it seems as though loading the file at startup does not work. I am still trying to get help to have it sorted. Until then, running sudo -f /etc/pfctl.conf after starting up does the trick.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.