I use a Mac and I’ve been working in virtual machines (VirtualBox) to learn more about Linux as a server environment. It’s great, to say the least. Knowing you can revert back to a previous “system snapshot” is a wonderful assurance for when you know you’re going to mess thing up.
With all this greatness, I was unfortunately having a lot of trouble getting the VM server to connect to other computers. Actually, it was very easy with using a bridged ethernet connection, with the Ubuntu server getting a unique IP address. However, a bridged connection is not always available, so I was determined to get it to work with a NAT connection with port forwarding. I needed port 80 to be forwarded to port 8080, and it was a pain but I finally got port forwarding to work. Here’s how:
Dirty But Easy
For a Mac, the easy but deprecated method for port forwarding is to use ipfw. To forward your ports you can use this terminal command:
sudo ipfw add 100 fwd 127.0.0.1, 8080 tcp from any to any 80 in
In this case we’re forwarding all HTTP requests (port 80) to port 8080
To erase your rules you can use:
sudo ipfw flush
Easy, right? I call ipfw ‘dirty’ because it’s deprecated, although it still remains in Mac OS X 10.9 and below, so it will be removed in a future release or software update. Beware.
Trying to Play Nice
The more ‘correct’ method for port forwarding is by using pfctl. Its capabilities are much greater than ipfw but working with it is more complicated. It took me many trials and hair-pulling hours getting a grasp on how it worked.
Unlike ipfw, we’ll first need to make a file that will be used to add the rules to our firewall. Here’s the code I used to forward port 80 to port 8080, in a file called pf.conf saved on my desktop:
# Custom pf Rules # ################ Variables #################################################### ex_ethernet = "en0" int_localhost = "lo0" vm_web_http_port = "8080" vm_web_https_port = "8443" ################ Port Forwarding to VM ######################################## ## External Requests for VM Web Server rdr on $ex_ethernet inet proto tcp from any to $ex_ethernet port http -> $int_localhost port $vm_web_http_port rdr on $ex_ethernet inet proto tcp from any to $ex_ethernet port https -> $int_localhost port $vm_web_https_port ## Internal Localhost Requests for VM Web Server rdr on $int_localhost inet proto tcp from $int_localhost to $int_localhost port http -> $int_localhost port $vm_web_http_port rdr on $int_localhost inet proto tcp from $int_localhost to $int_localhost port https -> $int_localhost port $vm_web_https_port # End
Notice the blank line after the last filtering rule? That needs to be there for some reason or else there will be a syntax error. Speaking about syntax, next should check the code for syntax errors. For this we can also use Terminal:
pfctl -v -n -f ~/Desktop/pf.conf
If you’re using the code above you’ll get to see the resulting firewall rules that will be created. They should look something like this:
ex_ethernet = "en0" int_localhost = "lo0" vm_web_http_port = "8080" vm_web_https_port = "8443" rdr on en0 inet proto tcp from any to 192.168.1.130 port = 80 -> 127.0.0.1 port 8080 rdr on en0 inet proto tcp from any to 192.168.1.130 port = 443 -> 127.0.0.1 port 8443 rdr on lo0 inet proto tcp from 127.0.0.1 to 127.0.0.1 port = 80 -> 127.0.0.1 port 8080 rdr on lo0 inet proto tcp from 127.0.0.1 to 127.0.0.1 port = 443 -> 127.0.0.1 port 8443
So finally, we can apply these rules by using this command:
sudo pfctl -f ~/Desktop/pf.conf
You can also remove these custom rules by using this:
udo pfctl -Fa -f ~/Desktop/pf.conf
That’s a lot more code to do basically the same thing! However, you’ll find that using pfctl will give you more control over which devices can communicate with which applications and ports.
That’s it? Well if you really want to have these rules be permanent, you’ll need to save them somewhere safe (like the “/etc/” folder) and apply it as an anchor to the rest of the rules. I’ll write about how to do that if I have the time.
Thanks! This also worked for me after I updated to Yosemite (used IPFW before)
Awesome, got this working for my Vagrant machine for WordPress dev (using VVV).
Neither of these methods worked for me, but yours did:
http://www.abetobing.com/node/81
https://github.com/Varying-Vagrant-Vagrants/VVV/issues/442
Thanks for putting this together!