From 69fe86edf0ba371b9b0a54e522ec20d33e0ae129 Mon Sep 17 00:00:00 2001 From: Mathias Hall-Andersen Date: Tue, 14 Nov 2017 16:27:53 +0100 Subject: [PATCH] Initial working source caching --- src/conn.go | 9 +++++-- src/device.go | 12 +++------ src/main.go | 1 + src/receive.go | 61 +++++++++++++++++++++++++--------------------- src/tests/netns.sh | 33 ++++++++++++++----------- src/uapi.go | 1 - 6 files changed, 63 insertions(+), 54 deletions(-) diff --git a/src/conn.go b/src/conn.go index 0347262..a047bb6 100644 --- a/src/conn.go +++ b/src/conn.go @@ -2,6 +2,8 @@ package main import ( "errors" + "golang.org/x/net/ipv4" + "golang.org/x/net/ipv6" "net" ) @@ -42,7 +44,6 @@ func unsafeCloseUDPListener(device *Device) error { if netc.bind != nil { err = netc.bind.Close() netc.bind = nil - netc.update.Add(1) } return err } @@ -68,6 +69,8 @@ func UpdateUDPListener(device *Device) error { if device.tun.isUp.Get() { + device.log.Debug.Println("UDP bind updating") + // bind to new port var err error @@ -94,8 +97,10 @@ func UpdateUDPListener(device *Device) error { // decrease waitgroup to 0 + go device.RoutineReceiveIncomming(ipv4.Version, netc.bind) + go device.RoutineReceiveIncomming(ipv6.Version, netc.bind) + device.log.Debug.Println("UDP bind has been updated") - netc.update.Done() } return nil diff --git a/src/device.go b/src/device.go index 033a387..9422d49 100644 --- a/src/device.go +++ b/src/device.go @@ -1,8 +1,6 @@ package main import ( - "golang.org/x/net/ipv4" - "golang.org/x/net/ipv6" "runtime" "sync" "sync/atomic" @@ -23,10 +21,9 @@ type Device struct { } net struct { mutex sync.RWMutex - bind UDPBind // bind interface - port uint16 // listening port - fwmark uint32 // mark value (0 = disabled) - update sync.WaitGroup // the bind was updated (acting as a barrier) + bind UDPBind // bind interface + port uint16 // listening port + fwmark uint32 // mark value (0 = disabled) } mutex sync.RWMutex privateKey NoisePrivateKey @@ -167,7 +164,6 @@ func NewDevice(tun TUNDevice, logLevel int) *Device { device.net.port = 0 device.net.bind = nil - device.net.update.Add(1) // start workers @@ -179,8 +175,6 @@ func NewDevice(tun TUNDevice, logLevel int) *Device { go device.RoutineReadFromTUN() go device.RoutineTUNEventReader() go device.ratelimiter.RoutineGarbageCollector(device.signal.stop) - go device.RoutineReceiveIncomming(ipv4.Version) - go device.RoutineReceiveIncomming(ipv6.Version) return device } diff --git a/src/main.go b/src/main.go index 05d56eb..eb3c67f 100644 --- a/src/main.go +++ b/src/main.go @@ -14,6 +14,7 @@ func printUsage() { } func main() { + // parse arguments var foreground bool diff --git a/src/receive.go b/src/receive.go index 3e88be3..ff3b7bd 100644 --- a/src/receive.go +++ b/src/receive.go @@ -20,12 +20,13 @@ type QueueHandshakeElement struct { } type QueueInboundElement struct { - dropped int32 - mutex sync.Mutex - buffer *[MaxMessageSize]byte - packet []byte - counter uint64 - keyPair *KeyPair + dropped int32 + mutex sync.Mutex + buffer *[MaxMessageSize]byte + packet []byte + counter uint64 + keyPair *KeyPair + endpoint Endpoint } func (elem *QueueInboundElement) Drop() { @@ -92,25 +93,13 @@ func (device *Device) addToHandshakeQueue( } } -func (device *Device) RoutineReceiveIncomming(IPVersion int) { +func (device *Device) RoutineReceiveIncomming(IP int, bind UDPBind) { logDebug := device.log.Debug - logDebug.Println("Routine, receive incomming, IP version:", IPVersion) + logDebug.Println("Routine, receive incomming, IP version:", IP) for { - // wait for bind - - logDebug.Println("Waiting for UDP socket, IP version:", IPVersion) - - device.net.update.Wait() - device.net.mutex.RLock() - bind := device.net.bind - device.net.mutex.RUnlock() - if bind == nil { - continue - } - // receive datagrams until conn is closed buffer := device.GetMessageBuffer() @@ -124,7 +113,7 @@ func (device *Device) RoutineReceiveIncomming(IPVersion int) { var endpoint Endpoint - switch IPVersion { + switch IP { case ipv4.Version: size, err = bind.ReceiveIPv4(buffer[:], &endpoint) case ipv6.Version: @@ -181,10 +170,11 @@ func (device *Device) RoutineReceiveIncomming(IPVersion int) { peer := value.peer elem := &QueueInboundElement{ - packet: packet, - buffer: buffer, - keyPair: keyPair, - dropped: AtomicFalse, + packet: packet, + buffer: buffer, + keyPair: keyPair, + dropped: AtomicFalse, + endpoint: endpoint, } elem.mutex.Lock() @@ -396,7 +386,6 @@ func (device *Device) RoutineHandshake() { peer.TimerAnyAuthenticatedPacketReceived() // update endpoint - // TODO: Discover destination address also, only update on change peer.mutex.Lock() peer.endpoint.set = true @@ -453,6 +442,13 @@ func (device *Device) RoutineHandshake() { continue } + // update endpoint + + peer.mutex.Lock() + peer.endpoint.set = true + peer.endpoint.value = elem.endpoint + peer.mutex.Unlock() + logDebug.Println("Received handshake initation from", peer) peer.TimerEphemeralKeyCreated() @@ -521,6 +517,13 @@ func (peer *Peer) RoutineSequentialReceiver() { } kp.mutex.Unlock() + // update endpoint + + peer.mutex.Lock() + peer.endpoint.set = true + peer.endpoint.value = elem.endpoint + peer.mutex.Unlock() + // check for keep-alive if len(elem.packet) == 0 { @@ -552,7 +555,8 @@ func (peer *Peer) RoutineSequentialReceiver() { src := elem.packet[IPv4offsetSrc : IPv4offsetSrc+net.IPv4len] if device.routingTable.LookupIPv4(src) != peer { - logInfo.Println("Packet with unallowed source IP from", peer.String()) + logInfo.Println(src) + logInfo.Println("Packet with unallowed source IPv4 from", peer.String()) continue } @@ -577,7 +581,8 @@ func (peer *Peer) RoutineSequentialReceiver() { src := elem.packet[IPv6offsetSrc : IPv6offsetSrc+net.IPv6len] if device.routingTable.LookupIPv6(src) != peer { - logInfo.Println("Packet with unallowed source IP from", peer.String()) + logInfo.Println(src) + logInfo.Println("Packet with unallowed source IPv6 from", peer.String()) continue } diff --git a/src/tests/netns.sh b/src/tests/netns.sh index 043da3e..9124b80 100755 --- a/src/tests/netns.sh +++ b/src/tests/netns.sh @@ -28,7 +28,7 @@ netns0="wg-test-$$-0" netns1="wg-test-$$-1" netns2="wg-test-$$-2" program="../wireguard-go" -export LOG_LEVEL="error" +export LOG_LEVEL="debug" pretty() { echo -e "\x1b[32m\x1b[1m[+] ${1:+NS$1: }${2}\x1b[0m" >&3; } pp() { pretty "" "$*"; "$@"; } @@ -147,6 +147,8 @@ tests() { n1 iperf3 -Z -n 1G -b 0 -u -c fd00::2 } +echo "4" + [[ $(ip1 link show dev wg1) =~ mtu\ ([0-9]+) ]] && orig_mtu="${BASH_REMATCH[1]}" big_mtu=$(( 34816 - 1500 + $orig_mtu )) @@ -185,14 +187,14 @@ ip0 -4 addr del 127.0.0.1/8 dev lo ip0 -4 addr add 127.212.121.99/8 dev lo n0 wg set wg1 listen-port 9999 n0 wg set wg1 peer "$pub2" endpoint 127.0.0.1:20000 -n1 ping6 -W 1 -c 1 fd00::20000 -[[ $(n2 wg show wg2 endpoints) == "$pub1 127.212.121.99:9999" ]] +n1 ping6 -W 1 -c 1 fd00::2 +[[ $(n2 wg show wg2 endpoints) == "$pub1 127.212.121.99:9999" ]] # Test using IPv6 that roaming works n1 wg set wg1 listen-port 9998 n1 wg set wg1 peer "$pub2" endpoint [::1]:20000 n1 ping -W 1 -c 1 192.168.241.2 -[[ $(n2 wg show wg2 endpoints) == "$pub1 [::1]:9998" ]] +[[ $(n2 wg show wg2 endpoints) == "$pub1 [::1]:9998" ]] # Test that crypto-RP filter works n1 wg set wg1 peer "$pub2" allowed-ips 192.168.241.0/24 @@ -212,7 +214,7 @@ n2 ncat -u 192.168.241.1 1111 <<<"X" ! read -r -N 1 -t 1 out <&4 kill $nmap_pid n0 wg set wg1 peer "$more_specific_key" remove -[[ $(n1 wg show wg1 endpoints) == "$pub2 [::1]:9997" ]] +[[ $(n1 wg show wg1 endpoints) == "$pub2 [::1]:9997" ]] ip1 link del wg1 ip2 link del wg2 @@ -232,8 +234,9 @@ ip2 link del wg2 # ip1 link add dev wg1 type wireguard # ip2 link add dev wg1 type wireguard -n1 $program wg1 -n2 $program wg2 +n1 $program -f wg1 & +n2 $program -f wg2 & +sleep 5 configure_peers @@ -263,7 +266,7 @@ n0 iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -d 10.0.0.0/24 -j SNAT --to n0 wg set wg1 peer "$pub2" endpoint 10.0.0.100:20000 persistent-keepalive 1 n1 ping -W 1 -c 1 192.168.241.2 n2 ping -W 1 -c 1 192.168.241.1 -[[ $(n2 wg show wg2 endpoints) == "$pub1 10.0.0.1:10000" ]] +[[ $(n2 wg show wg2 endpoints) == "$pub1 10.0.0.1:10000" ]] # Demonstrate n2 can still send packets to n1, since persistent-keepalive will prevent connection tracking entry from expiring (to see entries: `n0 conntrack -L`). pp sleep 3 n2 ping -W 1 -c 1 192.168.241.1 @@ -288,8 +291,9 @@ ip2 link del wg2 # ip1 link add dev wg1 type wireguard # ip2 link add dev wg1 type wireguard -n1 $program wg1 -n2 $program wg1 +n1 $program -f wg1 & +n2 $program -f wg2 & +sleep 5 configure_peers @@ -336,17 +340,18 @@ waitiface $netns1 veth1 waitiface $netns2 veth2 n0 wg set wg2 peer "$pub1" endpoint 10.0.0.1:10000 n2 ping -W 1 -c 1 192.168.241.1 -[[ $(n0 wg show wg2 endpoints) == "$pub1 10.0.0.1:10000" ]] +[[ $(n0 wg show wg2 endpoints) == "$pub1 10.0.0.1:10000" ]] n0 wg set wg2 peer "$pub1" endpoint [fd00:aa::1]:10000 n2 ping -W 1 -c 1 192.168.241.1 -[[ $(n0 wg show wg2 endpoints) == "$pub1 [fd00:aa::1]:10000" ]] +[[ $(n0 wg show wg2 endpoints) == "$pub1 [fd00:aa::1]:10000" ]] n0 wg set wg2 peer "$pub1" endpoint 10.0.0.2:10000 n2 ping -W 1 -c 1 192.168.241.1 -[[ $(n0 wg show wg2 endpoints) == "$pub1 10.0.0.2:10000" ]] +[[ $(n0 wg show wg2 endpoints) == "$pub1 10.0.0.2:10000" ]] n0 wg set wg2 peer "$pub1" endpoint [fd00:aa::2]:10000 n2 ping -W 1 -c 1 192.168.241.1 -[[ $(n0 wg show wg2 endpoints) == "$pub1 [fd00:aa::2]:10000" ]] +[[ $(n0 wg show wg2 endpoints) == "$pub1 [fd00:aa::2]:10000" ]] ip1 link del veth1 ip1 link del wg1 ip2 link del wg2 +echo "done" diff --git a/src/uapi.go b/src/uapi.go index 5098e3d..5e40939 100644 --- a/src/uapi.go +++ b/src/uapi.go @@ -248,7 +248,6 @@ func ipcSetOperation(device *Device, socket *bufio.ReadWriter) *IPCError { peer.mutex.Lock() err := peer.endpoint.value.SetDst(value) - fmt.Println(peer.endpoint.value.DstToString(), err) peer.endpoint.set = (err == nil) peer.mutex.Unlock() if err != nil {