barrowclift / barrowclift.github.io

Where humanity and computing meet
https://barrowclift.me
4 stars 2 forks source link

A suggestion about “Wireguard Server on macOS” #1

Open lifepillar opened 4 years ago

lifepillar commented 4 years ago

Hi, I'm among the dozen people who run a Wireguard server on macOS. I have a couple of remarks about setting up the firewall rules.

  1. I think that the two NAT rules you suggest are conflicting with each other. I was noticing dropped pings (first ping ok, then the rest times out)—usually a symptom of different devices using the same IP—which I resolved by removing the utun NAT rule. The following rule is enough to let me access my LAN through Wireguard:
nat on en0 from 10.0.10.0/24 to any -> (en0)

(where en0 is the active interface on my computer, of course, and 10.0.10.0/24 is Wireguard's subnet).

  1. Modifying /etc/pf.conf (or any other system's file in macOS) is never a good idea. It will be most likely overwritten on updates. I use Wireguard's PostUp and PostDown to dynamically add/remove the above firewall rule. Specifically:
#!/bin/sh
mkdir -p /usr/local/var/run/wireguard
chmod 700 /usr/local/var/run/wireguard
echo 'nat on en0 from 10.0.10.0/24 to any -> (en0)' | \
  pfctl -a com.apple/wireguard -Ef - 2>&1 | \
  grep 'Token' | \
  sed 's%Token : \(.*\)%\1%' >/usr/local/var/run/wireguard/pf_wireguard_token.txt

This will create a directory to store the token generated by pfctl; set its permissions so that it will be accessible only by root; dynamically add the NAT rule to the com.apple/wireguard anchor; enable the firewall and increase its reference count (-E); filter pfctl output to extract the reference token and store it into pf_wireguard_token.txt.

#!/bin/sh
TOKEN=`cat /usr/local/var/run/wireguard/pf_wireguard_token.txt`
pfctl -X ${TOKEN} || exit 1
rm -f /usr/local/var/run/wireguard/pf_wireguard_token.txt

This will get the reference from the file created before and it will release it (-X), disabling the firewall if there are no other references (otherwise the firewall will remain enabled).

[Interface]
Address = 10.0.10.0/24
PrivateKey = XXX
ListenPort = 51820
DNS = 1.1.1.1, 1.0.0.1, 2606:4700:4700::1111
PostUp = /usr/sbin/sysctl -w net.inet.ip.forwarding=1
PostUp = /usr/sbin/sysctl -w net.inet6.ip6.forwarding=1
PostUp = /usr/local/etc/wireguard/postup.sh
PostDown = /usr/local/etc/wireguard/postdown.sh

You don't need a launchd plist to start the firewall any longer. Rather, you should define a launchd plist to bring up Wireguard at boot time:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd";>
<plist version="1.0">
  <dict>
    <key>Label</key>
    <string>com.wireguard.server</string>
    <key>ProgramArguments</key>
    <array>
      <string>/usr/local/bin/wg-quick</string>
      <string>up</string>
      <string>/usr/local/etc/wireguard/server.conf</string>
    </array>
    <key>KeepAlive</key>
    <true/>
    <key>RunAtLoad</key>
    <true/>
    <key>LaunchOnlyOnce</key>
    <true/>
    <key>StandardErrorPath</key>
    <string>/usr/local/var/log/wireguard.err</string>
    <key>EnvironmentVariables</key>
    <dict>
      <key>PATH</key>
      <string>/usr/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
    </dict>
  </dict>
</plist>

(The above assumes that Wireguard configuration is saved at /usr/local/etc/wireguard/server.conf; also, make sure that /usr/local/var/log/ exists). Enable with:

sudo launchctl enable system/com.wireguard.server
sudo launchctl bootstrap system /Library/LaunchDaemons/com.wireguard.server.plist

You may want to test this and update your nice blog post accordingly ;-)

barrowclift commented 4 years ago

@lifepillar, thank you so much for taking the time to write in such fantastic and comprehensive feedback, I really appreciate it! Learned a lot of new things from this.

I'm working through integrating your improvements to my own setup now and hope to get an update to the post out within the week. I promise to include proper credit and a link to your site in the update.

Thanks again! 😁🙏

lifepillar commented 4 years ago

Thank you. One caveat is that I am using an old iMac with High Sierra. Tightened security and fresh bugs in more recent macOS releases might break something. Catalina, in particular, is not known for being a… cough cough… an especially good release: “no route to host” errors have been reported; also, there seems to be a bug related to interfaces visibility when wifi is off.

barrowclift commented 4 years ago

Noted; I'm running Catalina over here, so I'll keep an eye out for packet losses and other strange behavior going forward. However, things seem to be thankfully working fine so far on my end with the suggested changes, so it's possible I either haven't noticed or there's unknown, additional criteria required to expose those bugs.

Also, I'm happy to report the new and improved guide is now live at the original address. Thanks so much again for your feedback!

lifepillar commented 4 years ago

Great, thanks!

The only issue I have had with this setup is with my laptop (on Catalina) in my working environment, where both wireless and wired connections are available. Using wi-fi everything works perfectly (as a Wireguard client), but the wired connection doesn't work most of the times, and I haven't been able to debug it yet. I don't think it's an OS problem with utun interfaces, though, because I also use OpenVPN in the same environment without any issue. I doubt it's firewall problem, for the same reason (and also because I have tried Wireguard with different ports, including OpenVPN's).

What I find puzzling is that the handshake appears to succeed when I am on Ethernet, but I cannot establish any connection through Wireguard. I have to take a closer look at the routing tables…

ericbf commented 4 years ago

@lifepillar I was following this guide, and the wg-quick up command failed every time for me. Come to find, macOS may have some bug where the interfaces/tunnels don't work right when wifi is disabled. Perhaps that has something to do with what's going on with you? Once I enabled the wifi interface on my machine (though I kept it off) it seems to be working consistently for me now.

lifepillar commented 4 years ago

Due to the current restraints on movements, I have not had access for a while to the environment where I have experienced some issues, so I don’t know for sure. I recall that they were not easily reproducible, as I was switching from Ethernet to wifi and back, and sometimes Wireguard worked, but most of the times it didn’t. I had not been able to pinpoint the wifi interface as the culprit, despite my attempts.

What I can tell you is that my home server, set up as above, works flawlessly, as do my mobile clients (iOS).

barrowclift commented 4 years ago

While a bit late to the discussion, I can add another data point to the conversation; I don't believe I've ever disabled the WiFi on my server, both the Ethernet (which I have Wireguard set up to use) and WiFi networks are always on and connected, so that might explain why I've never come across this.

I did briefly play around with disabling the WiFi when restarting Wireguard, but things continued to work as expected. I am running the latest public macOS version (10.15.5, at time of writing), are both of you on the latest Catalina and still seeing this?

ericbf commented 4 years ago

Idk if it is what you did, but I wasn't expressly clear the first time. I had the Wi-Fi interface completely disabled in system preferences, not just turned off. When I enabled it, it worked with Wi-Fi either turned on or off both.

suxus-zz commented 2 years ago

@lifepillar Hello i do that on my MacMini (Intel with 10.15.7) but when i try it on my iPhone then no response from websites or emails. When i start my server then i see this (my MacMini is connected over ethernet).

sh-3.2# wg-quick up /usr/local/etc/wireguard/coordinates.conf
Warning: `/usr/local/etc/wireguard/coordinates.conf' is world accessible
[#] wireguard-go utun
[+] Interface for coordinates is utun2
[#] wg setconf utun2 /dev/fd/63
[#] ifconfig utun2 inet 10.0.10.0/24 10.0.10.0 alias
[#] ifconfig utun2 up
[#] route -q -n add -inet 10.0.10.10/32 -interface utun2
[+] Backgrounding route monitor
[#] /usr/sbin/sysctl -w net.inet.ip.forwarding=1
net.inet.ip.forwarding: 1 -> 1
[#] /usr/sbin/sysctl -w net.inet6.ip6.forwarding=1
net.inet6.ip6.forwarding: 1 -> 1
[#] /usr/local/etc/wireguard/postup.sh

Is this right?

I hope you can help me.

regrads

postup.sh

#!/bin/sh
mkdir -p /usr/local/var/run/wireguard
chmod 700 /usr/local/var/run/wireguard
echo 'nat on en0 from 10.0.10.0/24 to any -> (en0)' | \
  pfctl -a com.apple/wireguard -Ef - 2>&1 | \
  grep 'Token' | \
  sed 's%Token : \(.*\)%\1%' >/usr/local/var/run/wireguard/pf_wireguard_token.txt

postdown.sh

#!/bin/sh
TOKEN=`cat /usr/local/var/run/wireguard/pf_wireguard_token.txt`
pfctl -X ${TOKEN} || exit 1
rm -f /usr/local/var/run/wireguard/pf_wireguard_token.txt

coordinates.conf

[Interface]
Address = 10.0.10.0/24
PrivateKey = XYZ
ListenPort = 41195

#DNS = 1.1.1.1, 1.0.0.1, 2606:4700:4700::1111

PostUp = /usr/sbin/sysctl -w net.inet.ip.forwarding=1
PostUp = /usr/sbin/sysctl -w net.inet6.ip6.forwarding=1
PostUp = /usr/local/etc/wireguard/postup.sh
PostDown = /usr/local/etc/wireguard/postdown.sh

[Peer]
PublicKey = o...U=
AllowedIPs = 10.0.10.10/32
lifepillar commented 2 years ago

I have since moved my Wireguard server to my router, so I am not running it in macOS any longer. At a glance, I don't see anything obviously wrong with your configuration. However:

when i try it on my iPhone then no response from websites or emails.

That might be an issue with DNS. I suggest that you check the logs in your iPhone's Wireguard (Settings > View Log): if you see a message like “…connection status changed to 'connected'’ then your VPN is set up fine. In this case, you should double-check your DNS settings. Is Wireguard in your phone configured with allowed IPs set to 0.0.0.0/0? If that is the case, then all the traffic, including DNS requests, pass through Wireguard. So, you should set a DNS server that is reachable via the VPN.

If, instead, you (repeatedly) see a log message like “Handshake did not complete after 5 seconds”, then most likely your client cannot reach the Wireguard server. Double-check everything, (IPs, port, etc.) especially your firewall settings (if the server is in your Mac Mini, go to System Preferences > Security and Privacy > Firewall and try to disable the firewall or make sure in Firewall Options that Wireguard is allowed to receive connections).

suxus-zz commented 2 years ago

Hello

Wireguard Settings on iPhone and for the testing i switch Wlan off, only cellular (4G).

[Interface]
Address = 10.0.10.10/32
PrivateKey = XXX
DNS = 192.168.99.45 (my Pi-Hole with Cloudflare DNS)

[Peer]
PublicKey = XXX
Endpoint = My_DynDNS: 41195
AllowedIPs = 0.0.0.0/0, ::/0
Address = 10.0.10.10/32

On my MacMini is the Firewall OFF, not activated.

Log from iPhone

2021-11-05 10:00:19.555729: [APP] startActivation: Entering (tunnel: Test)
2021-11-05 10:00:19.560217: [APP] startActivation: Starting tunnel
2021-11-05 10:00:19.560577: [APP] startActivation: Success
2021-11-05 10:00:19.567343: [APP] Tunnel 'Test' connection status changed to 'connecting'
2021-11-05 10:00:19.619057: [NET] App version: 1.0.15 (26)
2021-11-05 10:00:19.619237: [NET] Starting tunnel from the app
2021-11-05 10:00:19.810496: [NET] DNS64: mapped 77.56.250.54 to itself.
2021-11-05 10:00:19.811725: [NET] Attaching to interface
2021-11-05 10:00:19.812370: [NET] UAPI: Updating private key
2021-11-05 10:00:19.812697: [NET] Routine: encryption worker 1 - started
2021-11-05 10:00:19.813022: [NET] UAPI: Removing all peers
2021-11-05 10:00:19.813175: [NET] Routine: encryption worker 4 - started
2021-11-05 10:00:19.813334: [NET] Routine: decryption worker 1 - started
2021-11-05 10:00:19.813700: [NET] Routine: handshake worker 1 - started
2021-11-05 10:00:19.813714: [NET] peer(ysg5…rqDQ) - UAPI: Created
2021-11-05 10:00:19.813875: [NET] peer(ysg5…rqDQ) - UAPI: Updating endpoint
2021-11-05 10:00:19.813920: [NET] Routine: handshake worker 5 - started
2021-11-05 10:00:19.813964: [NET] Routine: encryption worker 2 - started
2021-11-05 10:00:19.814084: [NET] peer(ysg5…rqDQ) - UAPI: Updating persistent keepalive interval
2021-11-05 10:00:19.814334: [NET] peer(ysg5…rqDQ) - UAPI: Removing all allowedips
2021-11-05 10:00:19.814454: [NET] Routine: decryption worker 3 - started
2021-11-05 10:00:19.814478: [NET] peer(ysg5…rqDQ) - UAPI: Adding allowedip
2021-11-05 10:00:19.814554: [NET] peer(ysg5…rqDQ) - UAPI: Adding allowedip
2021-11-05 10:00:19.814578: [NET] Routine: encryption worker 3 - started
2021-11-05 10:00:19.814583: [NET] Routine: decryption worker 4 - started
2021-11-05 10:00:19.814632: [NET] Routine: handshake worker 3 - started
2021-11-05 10:00:19.814717: [NET] Routine: decryption worker 2 - started
2021-11-05 10:00:19.814802: [NET] Routine: decryption worker 5 - started
2021-11-05 10:00:19.814859: [NET] Routine: handshake worker 2 - started
2021-11-05 10:00:19.814876: [NET] Routine: encryption worker 5 - started
2021-11-05 10:00:19.814917: [NET] Routine: decryption worker 6 - started
2021-11-05 10:00:19.814970: [NET] Routine: handshake worker 4 - started
2021-11-05 10:00:19.815013: [NET] Routine: handshake worker 6 - started
2021-11-05 10:00:19.815017: [NET] Routine: TUN reader - started
2021-11-05 10:00:19.815037: [NET] Routine: encryption worker 6 - started
2021-11-05 10:00:19.815212: [NET] Routine: event worker - started
2021-11-05 10:00:19.815279: [NET] UDP bind has been updated
2021-11-05 10:00:19.815323: [NET] Routine: receive incoming v4 - started
2021-11-05 10:00:19.815345: [NET] Routine: receive incoming v6 - started
2021-11-05 10:00:19.815504: [NET] peer(ysg5…rqDQ) - Starting
2021-11-05 10:00:19.815632: [NET] Interface state was Down, requested Up, now Up
2021-11-05 10:00:19.815724: [NET] Device started
2021-11-05 10:00:19.815848: [NET] peer(ysg5…rqDQ) - Routine: sequential receiver - started
2021-11-05 10:00:19.815989: [NET] Tunnel interface is utun7
2021-11-05 10:00:19.815999: [NET] peer(ysg5…rqDQ) - Routine: sequential sender - started
2021-11-05 10:00:19.816596: [NET] Network change detected with satisfied route and interface order [pdp_ip0]
2021-11-05 10:00:19.817057: [NET] DNS64: mapped 77.56.250.54 to itself.
2021-11-05 10:00:19.817215: [NET] peer(ysg5…rqDQ) - UAPI: Updating endpoint
2021-11-05 10:00:19.817551: [NET] Routine: receive incoming v4 - stopped
2021-11-05 10:00:19.817575: [NET] Routine: receive incoming v6 - stopped
2021-11-05 10:00:19.817919: [APP] Tunnel 'Test' connection status changed to 'connected'
2021-11-05 10:00:19.818117: [NET] UDP bind has been updated
2021-11-05 10:00:19.818130: [NET] Routine: receive incoming v4 - started
2021-11-05 10:00:19.818155: [NET] Routine: receive incoming v6 - started
2021-11-05 10:00:20.385783: [NET] Network change detected with satisfied route and interface order [pdp_ip0, utun7]
2021-11-05 10:00:20.386600: [NET] DNS64: mapped 77.56.250.54 to itself.
2021-11-05 10:00:20.386939: [NET] peer(ysg5…rqDQ) - UAPI: Updating endpoint
2021-11-05 10:00:20.387241: [NET] Routine: receive incoming v4 - stopped
2021-11-05 10:00:20.387377: [NET] Routine: receive incoming v6 - stopped
2021-11-05 10:00:20.388005: [NET] UDP bind has been updated
2021-11-05 10:00:20.388074: [NET] Routine: receive incoming v4 - started
2021-11-05 10:00:20.388136: [NET] Routine: receive incoming v6 - started
2021-11-05 10:00:24.560704: [APP] Status update notification timeout for tunnel 'Test'. Tunnel status is now 'connected'.
2021-11-05 10:00:29.980384: [NET] peer(ysg5…rqDQ) - Sending handshake initiation
2021-11-05 10:00:35.251925: [NET] peer(ysg5…rqDQ) - Handshake did not complete after 5 seconds, retrying (try 2)
2021-11-05 10:00:35.252278: [NET] peer(ysg5…rqDQ) - Sending handshake initiation
2021-11-05 10:00:40.416725: [NET] peer(ysg5…rqDQ) - Handshake did not complete after 5 seconds, retrying (try 2)
2021-11-05 10:00:40.416901: [NET] peer(ysg5…rqDQ) - Sending handshake initiation
2021-11-05 10:00:44.081358: [APP] startDeactivation: Tunnel: Test
2021-11-05 10:00:44.086265: [APP] Tunnel 'Test' connection status changed to 'disconnecting'
2021-11-05 10:00:44.460018: [NET] Stopping tunnel
2021-11-05 10:00:44.460391: [NET] Device closing
2021-11-05 10:00:44.461063: [NET] Routine: TUN reader - stopped
2021-11-05 10:00:44.461218: [NET] Routine: event worker - stopped
2021-11-05 10:00:44.461412: [NET] Routine: receive incoming v4 - stopped
2021-11-05 10:00:44.461532: [NET] Routine: receive incoming v6 - stopped
2021-11-05 10:00:44.461742: [NET] peer(ysg5…rqDQ) - Stopping
2021-11-05 10:00:44.461921: [NET] peer(ysg5…rqDQ) - Routine: sequential receiver - stopped
2021-11-05 10:00:44.461914: [NET] peer(ysg5…rqDQ) - Routine: sequential sender - stopped
2021-11-05 10:00:44.462150: [NET] Device closed
2021-11-05 10:00:44.462182: [NET] Routine: handshake worker 1 - stopped
2021-11-05 10:00:44.462190: [NET] Routine: decryption worker 1 - stopped
2021-11-05 10:00:44.462206: [NET] Routine: handshake worker 4 - stopped
2021-11-05 10:00:44.462230: [NET] Routine: decryption worker 4 - stopped
2021-11-05 10:00:44.462243: [NET] Routine: handshake worker 3 - stopped
2021-11-05 10:00:44.462252: [NET] Routine: decryption worker 2 - stopped
2021-11-05 10:00:44.462290: [NET] Routine: handshake worker 5 - stopped
2021-11-05 10:00:44.462359: [NET] Routine: decryption worker 3 - stopped
2021-11-05 10:00:44.462411: [NET] Routine: handshake worker 6 - stopped
2021-11-05 10:00:44.462436: [NET] Routine: handshake worker 2 - stopped
2021-11-05 10:00:44.462505: [NET] Routine: decryption worker 5 - stopped
2021-11-05 10:00:44.462514: [NET] Routine: decryption worker 6 - stopped
2021-11-05 10:00:44.462820: [NET] Routine: encryption worker 3 - stopped
2021-11-05 10:00:44.462813: [NET] Routine: encryption worker 1 - stopped
2021-11-05 10:00:44.462835: [NET] Routine: encryption worker 5 - stopped
2021-11-05 10:00:44.462852: [NET] Routine: encryption worker 2 - stopped
2021-11-05 10:00:44.462872: [NET] Routine: encryption worker 4 - stopped
2021-11-05 10:00:44.462897: [NET] Routine: encryption worker 6 - stopped
2021-11-05 10:00:44.470806: [APP] Tunnel 'Test' connection status changed to 'disconnected'

On my Unifi DreamMachine Pro i make a port forwarding from Port 41195 to 41195 on my MacMini (192.168.99.25)

On my Router is running a VPN Server L2TP on subnet 10.1.88.0/27 and on my NAS running a Wireguard Server on subnet 10.0.1.1/32 (i will replace Wireguard Server to the MacMini)

Is it purhaps a problem with my other VPN-Wireguard Server on my NAS?

Subnet NAS: 10.0.1.1/32 Subnet MacMini: 10.0.10.0/24

A test router running under 10.220.0.1/32

Purhaps you see more

regards

lifepillar commented 2 years ago

I believe that your 192… network is not reachable from the VPN. Is it en0? If not, you may try adding another nat rule.

suxus-zz commented 2 years ago

I think it's reachable

macmini:~ suxus$ ifconfig
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
    options=1203<RXCSUM,TXCSUM,TXSTATUS,SW_TIMESTAMP>
    inet 127.0.0.1 netmask 0xff000000 
    inet6 ::1 prefixlen 128 
    inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1 
    nd6 options=201<PERFORMNUD,DAD>
gif0: flags=8010<POINTOPOINT,MULTICAST> mtu 1280
stf0: flags=0<> mtu 1280
en1: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
    options=400<CHANNEL_IO>
    ether 20:c9:d0:92:32:71 
    inet6 fe80::c00:dc64:7c76:112e%en1 prefixlen 64 secured scopeid 0x4 
    inet6 fd1a:9d61:63b2:1:d0:5dda:5a5d:edee prefixlen 64 autoconf secured 
    inet6 fd1a:9d61:63b2:1:54b2:a653:1662:5bf prefixlen 64 autoconf temporary 
    inet 192.168.99.245 netmask 0xffffff00 broadcast 192.168.99.255
    nd6 options=201<PERFORMNUD,DAD>
    media: autoselect
    status: active
en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
    options=50b<RXCSUM,TXCSUM,VLAN_HWTAGGING,AV,CHANNEL_IO>
    ether a8:20:66:11:c2:14 
    inet6 fe80::f1:5acd:9789:1148%en0 prefixlen 64 secured scopeid 0x5 
    inet 192.168.99.25 netmask 0xffffff00 broadcast 192.168.99.255
    inet6 fd1a:9d61:63b2:1:892:39eb:f032:b33c prefixlen 64 autoconf secured 
    inet6 fd1a:9d61:63b2:1:c404:b2c6:21d7:fb8 prefixlen 64 autoconf temporary 
    nd6 options=201<PERFORMNUD,DAD>
    media: autoselect (1000baseT <full-duplex>)
    status: active

Where and how is it then determined whether VPN is allowed on the 192.168 network? Will my log from the iPhone then look correct?

lifepillar commented 2 years ago

The log looks fine to me. You may use an app such as Fing to test connectivity in your iPhone, e.g., to test whether the IP address of your DNS is reachable.

When your traffic is tunnelled through your VPN, you are inside a LAN with network id 10.0.10.0. Whether you can reach other local networks from there depends on the routing and firewall rules on your server, as is the case for any other network. As I said, I have not run Wireguard in my Mac for a while, so I can't help much more than that. If you plan to use your NAS eventually, perhaps it is worth to set up Wireguard there to begin with. In case of issues, you may then look for support in the forums of your NAS's operating system.

alessionossa commented 2 years ago

Hello, in https://github.com/barrowclift/barrowclift.github.io/issues/1#issue-577317050 you use the following commands in postdown.sh script

#!/bin/sh
TOKEN=`cat /usr/local/var/run/wireguard/pf_wireguard_token.txt`
pfctl -X ${TOKEN} || exit 1
rm -f /usr/local/var/run/wireguard/pf_wireguard_token.txt

However, it looks like pfctl -X only "release the pf enable reference represented by the token passed" (see https://www.manpagez.com/man/8/pfctl/ ), but it doesn’t actually remove the rule if there is any other rule for pf Therefore, when @barrowclift says in the guide

Adding and removing rules by references like this will automatically disable the packet filter firewall if there are no other references left, but will leave it up and intact if there are. It’s not exact because it’s removing rules by references, it’s actually removing references to pf enable.

Anyway, thank you both for the great detailed article and contribution, I noticed this behavior because I am using the same instructions to use macOS as a gateway to Internet for just a device on my local LAN with no Internet (the Mac is the only device connected to both) and so I was dealing with two different NAT rules.

To actually remove the rule from pf, the postdown.sh script can be:

#!/bin/sh

# 1) Fetch the pf reference token that was generated on
#    Wireguard startup with postup.sh
TOKEN=`cat /usr/local/var/run/wireguard/pf_wireguard_token.txt`

# 2) Remove the reference (and by extension, the pf rule that
#    generated it). Adding and removing rules by references
#    like this will automatically disable the packet filter
#    firewall if there are no other references left, but will
#    leave it up and intact if there are.
ANCHOR='com.apple/wireguard'
pfctl -a $ANCHOR -F all || exit 1
echo "Removed rule with anchor: $ANCHOR"

pfctl -X $TOKEN || exit 1
echo "Removed reference for token: $TOKEN"

rm -f /usr/local/var/run/wireguard/pf_wireguard_token.txt
echo "Deleted token file"

In fact, -F all flush all the information and -a com.apple/wireguard restrict this action to the specified anchor.

barrowclift commented 2 years ago

Oh wow, thanks @alessionossa for the catch and detailed report! That was a miss on my part, should have given the man page a quick look before writing that comment. The article has been updated to reflect your suggestions, and you're now included in a shout-out at the bottom. Thanks again!

Disuissi commented 11 months ago

Hi, sorry for entering this discussion with nothing to contribute, but I do need your help to understand the NAT rule. I am one of the crazy people who run wirguard server on Mac OS, and my knowledge in networking is minimal, but I am a self learner, specially if something is interesting (Yes, for me this is interesting, as my wife thinks I m crazy ahah). My question is: why nat on en0 from 10.0.10.0/24 to any -> (en0) and not: nat on utun0 from 10.0.10.0/24 to any -> (en0)? Everything works fine, but I do like to know how things work and why. And I searched everything and no clear explanation :/

Thanks everyone for the help that you already gave. I have a free VPN to access all my files on the go!!!!!!

barrowclift commented 11 months ago

Hi @Disuissi 👋🏻

why nat on en0 from 10.0.10.0/24 to any -> (en0) and not: nat on utun0 from 10.0.10.0/24 to any -> (en0)?

(asterisk: as this thread has indicated, I'm by no means a pfsense expert, so please take my attempt at answering this with a grain of salt.)

To set the groundwork, when building the WireGuard server config, we assigned both a local subnet which the WireGuard server will use and then assigned IPs your clients will use when they connect. In the guide, the example subnet of 10.0.10.0/24 was used with clients assigned 10.0.10.1, 10.0.10.2, etc. This means when a client is connected to the Wireguard VPN, its network activity will be through its pre-assigned IP.

So with that understood, let's turn our attention to the PF sense rule, nat on en0 from 10.0.10.0/24 to any -> (en0). To (roughly) describing what this is saying, this means...

When networking requests from any of the IPs in the special WireGuard subnet attempt using the Ethernet network interface (which is how your macOS Server "talks" to other devices on your LAN and to the broader internet), grant those requests access/let those requests through.

Without that declaration above, macOS's Firewall (correctly!) blocks those requests.

If it's helpful, you can kind of think of this as a text version of the macOS Firewall panel in System Settings where you have control over allowing/rejecting incoming connections, but in this case it's for the other way (i.e. to allow/reject outgoing connections to your LAN & the broader internet for IPs in your special WireGuard subnet).

Hope that helps clear things up!