OS X El Capitan port forwarding to Parallels VM using pfctl

I have Parallels Desktop 11, which does not have support port forwarding to VMs (just the Pro version supports it). So I am trying to use pfctl to forward ports to my Parallels VM.

I have followed this answer to setup the port forwarding. Forwarding is enabled with sysctl net.inet.ip.forwarding=1

I have specified this rule.

rdr pass inet proto tcp from any to any port 51414 -> 10.211.55.9 port 51414

10.211.55.9 is the static IP of the Parallels VM.

However the port forwarding does not work for VM. It can successfully forward port x to port y on 127.0.0.1 but can not forward port x from Mac to port x on Parallels VM.

What could be going wrong? Is it Parallels which is dropping packets etc?


Solution 1:

There are two solutions for your problem with Parallels Desktop 11 (this doesn't apply to Parallels Desktop Pro/Enterprise 11, which both provide a convenient interface to configure port forwarding - nonetheless the solutions should work also in those enhanced versions):

Instead of attaching the VM's network interface to the "Shared Network" use a bridged interface (e.g. en0 or en1) and configure it with a IP/netmask in the respective network. Then you don't need NAT/port forwarding.


If you insist on a NAT'ed network do the following:

In the example below I use nc as server. To run a server enter nc -l -4 port and to connect to this server use nc server-IP port. You may also specify a source port: nc -p source-port server-IP port.

Here I use nc -l -4 11111 on the VM. To connect to this server I would run nc server-IP 11111 from a host in the same network. After starting the server and connecting the client you can simply enter some text, which is sent to the other console. To connect from a third host in a different network to the VM nc-server I want to use nc NAT-host-IP 22222. So I have to forward NAT-host-IP:22222 to VM-IP:11111. NAT-host in this case is the Mac hosting the Parallels VM.

  1. attach the VM guest's network interface to the "Host-only Network". Usually Parallels' host-only network has the following host configuration (check this by entering ifconfig on the host machine):

    vnic1: ...
    ...
    inet 10.37.129.2 netmask 255.255.255.0 broadcast 10.37.129.255
    

    So configure the VM guest as following:

    • IP: 10.37.129.x (with x ≠ 0,1,2,255) - below I assume it's 10.37.129.10
    • Netmask: 255.255.255.0
    • Gateway: 10.37.129.2
    • DNS: a real DNS server like 8.8.8.8
  2. On the NAT-host machine enable forwarding in /etc/sysctl.conf:

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

    and reboot the host.

  3. On the NAT-host machine (with an example IP of en0: 192.168.0.2) create an anchor file org.user.forwarding in /private/etc/pf.anchors

    sudo touch /private/etc/pf.anchors/org.user.forwarding
    

    with the following content and a trailing empty line:

    rdr pass on en0 inet proto tcp from any to any port 22222 -> 10.37.129.10 port 11111
    
  4. On the NAT-host machine modify the file /private/etc/pf.conf but keep a trailing empty line

    original file:

    ...
    scrub-anchor "com.apple/*"
    nat-anchor "com.apple/*"
    rdr-anchor "com.apple/*"
    dummynet-anchor "com.apple/*"
    anchor "com.apple/*"
    load anchor "com.apple" from "/etc/pf.anchors/com.apple"
    

    to

    ...
    scrub-anchor "com.apple/*"
    nat-anchor "com.apple/*"
    rdr-anchor "com.apple/*"
    rdr-anchor "org.user.forwarding"
    nat on en0 proto {tcp, udp, icmp} from 10.37.129.0/24 to any -> en0
    pass from {lo0, 10.37.129.0/24} to any keep state
    dummynet-anchor "com.apple/*"
    anchor "com.apple/*"
    load anchor "com.apple" from "/etc/pf.anchors/com.apple"
    load anchor "org.user.forwarding" from "/etc/pf.anchors/org.user.forwarding"
    
  5. Parse and test your anchor and your pf.conf file to make sure that there are no errors:

    sudo pfctl -vnf /etc/pf.anchors/org.user.forwarding
    sudo pfctl -vnf /etc/pf.conf
    
  6. Enable pf with:

    sudo pfctl -e -f /etc/pf.conf
    
  7. To test this start the nc server on the VM with nc -l -4 11111. Now on a third host in your physical network enter nc 192.168.0.2 22222.

After a reboot you have to start pf again. If you want to enable pf permanently check my other pf related answers.

After a system update or upgrade some of the original files above may have been replaced and you have to reapply all changes.