There are a few limitations of the WireGuard implementation in FreeBSD which must be taken into consideration when deciding if WireGuard fits the needs of a use case.
WireGuard does not bind itself to an interface or a specific address on the firewall, but instead can accept traffic on any local IP address. This makes it very flexible, but can cause problems with functionality which requires traffic to use a specific address. When a WireGuard peer contacts the firewall, the firewall will respond from the address the peer used to contact it, if possible.
There are certain cases where this may not function as expected, such as when a peer was communicating with a CARP VIP which changed status.
Remote Peer Endpoint Requirements¶
When this firewall initiates a packet to a remote WireGuard endpoint, the source will be based on the main IP address on the WAN interface with the default gateway. If a remote endpoint expects to communicate with a different address, it is unlikely to work.
In this case, the problem can be worked around by updating the remote peer to use the correct endpoint address.
If this firewall is the only peer to initiate traffic in the tunnel, an outbound NAT rule could be crafted which matches the incorrect source address and translates it to the expected address.
Another alternative is to remove the remote endpoint from the peer configuration on this firewall, and set the remote endpoint to use the expected peer address for this firewall. If the remote peer always initiates traffic and sends to the expected address, replies will use that address.
The address selection behavior mentioned earlier can cause some unexpected behavior with CARP.
For example, if a CARP node goes into maintenance mode during ongoing communication with a peer, the CARP VIP will no longer be available for use by WireGuard and the CARP node may respond to the client using its interface address instead. This can cause the remote peer to continue attempting communication with that specific node, and not the node holding MASTER status for the CARP VIP. This isn’t a problem when a CARP node is powered off or reboots, as in those cases the CARP node cannot issue the unexpected responses.
When initiating traffic to a remote endpoint it can’t be properly sourced from a CARP VIP. Outbound NAT cannot work around this limitation as the state created by outbound NAT is tied to a specific HA node. If that node fails, the other node cannot utilize the same state as it doesn’t match its own local address. Allowing the remote peer to always initiate can work around this limitation.
If a client contacts the firewall via its WAN2 address, the firewall will respond from its WAN2 address as expected. However, if this firewall initiates, the traffic will always leave via the interface with the default route unless the routing table sends the traffic by another path.
If the only concern is connectivity, this may be acceptable. However, it is not acceptable if the intent is to cause WireGuard to use WAN2 for its initiated traffic.
For remote peers with static addresses, this can be worked around by adding a static route for the remote endpoint address using the correct WAN gateway.