IKEv2 relies on fixed port numbers (500 and 4500) and most implementations (macOS and Windows built-in VPN clients) don't allow to specify a custom port number. Additionally, IKEv2 uses fixed ports on the client side as well.
This means that running on localhost (127.0.0.1 or ::1) will connect from 127.0.0.1:500
to 127.0.0.1:500
, and fail if pterodapter is already using port 500.
Using another localhost destination IP address (e.g. 127.0.0.2, 127.0.1.1 or ::1) will also change the source IP address - it's not possible to connect from 127.0.0.1 to 127.0.0.2.
The macOS IKEv2 client also seems to prefer real network cards (en0), even with route add
or networksetup -setadditionalroutes
route traffic through lo0.
The solution is using the built-in pf filter to set up a fake IP address (e.g. 192.0.2.40, an IPv4 reserved address from TEST-NET-1) and redirect all packets to a custom port used by pterodapter.
This document explains how to set up a rule so that 192.0.2.40:500
is redirected to 192.0.2.40:9500
, and 192.0.2.40:4500
is redirected to 127.0.0.1:9501
; this way, a local copy of pterodapter will look like it's running at 192.0.2.40
.
Run pterodapter on ports 9500 + 9501 - and specify 192.0.2.40 as the destination host.
cat << EOF | sudo pfctl -e -f -
rdr pass proto udp from any to 192.0.2.40 port 500 tag MAC_TO_VPN -> 127.0.0.1 port 9500
rdr pass proto udp from any to 192.0.2.40 port 4500 tag MAC_TO_VPN -> 127.0.0.1 port 9501
pass out quick route-to (lo0 127.0.0.1) proto udp from any to 192.0.2.40 port {500, 4500}
EOF
Technically, this is not needed, but might help:
sudo sysctl net.inet.ip.forwarding=1
Instead of completely replacing all pf rules, add a custom anchor (using the predefined com.apple
prefix):
Enable the firewall:
sudo pfctl -ef /etc/pf.conf
and add an achor:
cat << EOF | sudo pfctl -a com.apple/pterodapter -f -
rdr pass proto udp from any to 192.0.2.40 port 500 tag MAC_TO_VPN -> 127.0.0.1 port 9500
rdr pass proto udp from any to 192.0.2.40 port 4500 tag MAC_TO_VPN -> 127.0.0.1 port 9501
pass out quick route-to (lo0 127.0.0.1) proto udp from any to 192.0.2.40 port {500, 4500}
EOF
Check status with
sudo pfctl -s all
Show all anchors with
sudo pfctl -vsA
Reset to default rules with
sudo pfctl -ef /etc/pf.conf
Disable packet filter with
sudo pfctl -d
- Automatically load PF rules using launchd
- VM-based virtual net using socket_vmnet, requires root permissions
- Run lightweight VM using vfkit
- Reuse parts of SimpleTunnel example project