mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-16 15:26:40 +00:00
Share kernel Wireguard port with raw socket (#826)
This PR brings support of a shared port between stun (ICE agent) and the kernel WireGuard It implements a single port mode for execution with kernel WireGuard interface using a raw socket listener. BPF filters ensure that only STUN packets hit the NetBird userspace app Removed a lot of the proxy logic and direct mode exchange. Now we are doing an extra hole punch to the remote WireGuard port for best-effort cases and support to old client's direct mode.
This commit is contained in:
47
sharedsock/filter_linux.go
Normal file
47
sharedsock/filter_linux.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package sharedsock
|
||||
|
||||
import "golang.org/x/net/bpf"
|
||||
|
||||
// STUNFilter implements BPFFilter by filtering on STUN packets.
|
||||
// Other packets (non STUN) will be forwarded to the process that own the port (e.g., WireGuard).
|
||||
type STUNFilter struct {
|
||||
}
|
||||
|
||||
// NewSTUNFilter creates an instance of a STUNFilter
|
||||
func NewSTUNFilter() BPFFilter {
|
||||
return &STUNFilter{}
|
||||
}
|
||||
|
||||
// GetInstructions returns raw BPF instructions for ipv4 and ipv6 that filter out anything but STUN packets
|
||||
func (sf STUNFilter) GetInstructions(port uint32) (raw4 []bpf.RawInstruction, raw6 []bpf.RawInstruction, err error) {
|
||||
raw4, err = rawInstructions(22, 32, port)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
raw6, err = rawInstructions(2, 12, port)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return raw4, raw6, nil
|
||||
}
|
||||
|
||||
func rawInstructions(portOff, cookieOff, port uint32) ([]bpf.RawInstruction, error) {
|
||||
// UDP raw socket for ipv4 receives the rcvdPacket with IP headers
|
||||
// UDP raw socket for ipv6 receives the rcvdPacket with UDP headers
|
||||
instructions := []bpf.Instruction{
|
||||
// Load the source port from the UDP header (offset 22 for ipv4 and 2 for ipv6)
|
||||
bpf.LoadAbsolute{Off: portOff, Size: 2},
|
||||
// Check if the source port is equal to the specified `port`. If not, skip the next 3 instructions.
|
||||
bpf.JumpIf{Cond: bpf.JumpNotEqual, Val: port, SkipTrue: 3},
|
||||
// Load the 4-byte value (magic cookie) from the UDP payload (offset 32 for ipv4 and 12 for ipv6)
|
||||
bpf.LoadAbsolute{Off: cookieOff, Size: 4},
|
||||
// Check if the loaded value is equal to the `magicCookie`. If not, skip the next instruction.
|
||||
bpf.JumpIf{Cond: bpf.JumpNotEqual, Val: magicCookie, SkipTrue: 1},
|
||||
// If both the port and the magic cookie match, return a positive value (0xffffffff)
|
||||
bpf.RetConstant{Val: 0xffffffff},
|
||||
// If either the port or the magic cookie doesn't match, return 0
|
||||
bpf.RetConstant{Val: 0},
|
||||
}
|
||||
|
||||
return bpf.Assemble(instructions)
|
||||
}
|
||||
Reference in New Issue
Block a user