mirror of
https://github.com/amnezia-vpn/amneziawg-go.git
synced 2026-10-13 21:34:25 +00:00
[PR #180] feat: implement sticky sockets on FreeBSD #188
Labels
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
amnezia-vpn/amneziawg-go#188
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/amnezia-vpn/amneziawg-go/pull/180
Author: @MarceloMayo74
Created: 8/14/2026
Status: 🔄 Open
Base:
master← Head:freebsd-sticky-sockets📝 Commits (1)
ec5368econn: implement sticky sockets on FreeBSD📊 Changes
4 files changed (+456 additions, -3 deletions)
View changed files
➕
conn/controlfns_freebsd.go(+38 -0)📝
conn/sticky_default.go(+3 -3)➕
conn/sticky_freebsd.go(+121 -0)➕
conn/sticky_freebsd_test.go(+294 -0)📄 Description
What this does
Fills in
getSrcFromControl()/setSrcControl()for FreeBSD, so a socket answers from the address the packet arrived on instead of whatever routing picks. This is the openTODOinconn/sticky_default.go.The generic transport already does the work on every platform — the non-Linux path in
bind_std.gousesReadMsgUDP/WriteMsgUDPwith OOB — only the implementations were empty outside Linux.Why FreeBSD is easy
It has the whole API:
IP_RECVDSTADDRIPV6_RECVPKTINFOin_addrin6_pktinfoIP_SENDSRCADDRIPV6_PKTINFOAnd
IP_SENDSRCADDR == IP_RECVDSTADDR(both 7), so the control message that came in can be handed straight back tosendmsg— the same trick the Linux code uses by keeping the raw cmsg inep.src. IPv6 is symmetric on its own.Why it matters
On a multi-homed host without sticky sockets, a handshake arriving on a secondary WAN gets answered out of the default gateway's interface with the wrong source address; the client discards it and the handshake never completes.
Concretely, on a pfSense firewall with two WANs, before and after:
That is the behaviour
if_wgalready has in kernel, so this closes the gap for the userspace implementation.Verification
go test ./conn/on FreeBSD 16 (pfSense 2.9.0), including a round trip that exerciseslistenConfig(), the cmsg parse, and asendmsgwith the source pinned against the real kernel.go build ./conn/andgo vet ./conn/forfreebsd,linux,windows,darwinandopenbsd— the build tag change (!linux || android→(!linux && !freebsd) || android) leaves every other platform on the stub.Two notes
Anyone extending
sticky_freebsd_test.goshould know thatIP_SENDSRCADDRreturnsEINVALon a socket bound to a specific address — it only works with a wildcard bind, which is whatStdNetBind.Open()does. The code is unaffected, but a test binding127.0.0.1fails for that reason alone.Unrelated to this change:
GOOS=freebsd go build ./...on currentmasterfails ingolang.getoutline.org/sdk/x/smart(undefined: lookupCNAME), so the repo does not build for FreeBSD today. Theconnpackage itself is fine, which is what this patch touches.The change applies identically to
wireguard-go, which is where these files come from.🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.