aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Crawshaw <crawshaw@tailscale.io>2019-10-15 15:24:46 +0200
committerDavid Crawshaw <crawshaw@tailscale.io>2019-10-15 15:27:13 +0200
commit0ac90870629a3f6b1744ca5cdb1b60407d3890f4 (patch)
treeeef91e2b6437edb46f3fa1b7a4d6cdd109dbeaef
parentdevice: use tokenbucket package for handshake initiation (diff)
downloadwireguard-go-dc/manualmerge.tar.xz
wireguard-go-dc/manualmerge.zip
device: add a test that demonstrates handshakes racingdc/manualmerge
Each side attempts to establish a tunnel at the same time. The result is the handshakes cross in-flight, both sides get confused, and we have to wait for the multi-second timeout to get a tunnel established. Without a handshake race, it is possible to set const maxWait = 300 * time.Millisecond to get the test passing reliably even on slow machines.
-rw-r--r--device/device_test.go82
1 files changed, 71 insertions, 11 deletions
diff --git a/device/device_test.go b/device/device_test.go
index 14cc605..cead816 100644
--- a/device/device_test.go
+++ b/device/device_test.go
@@ -13,15 +13,15 @@ import (
"net"
"os"
"strings"
+ "sync"
"testing"
"time"
"golang.zx2c4.com/wireguard/tun"
)
-func TestTwoDevicePing(t *testing.T) {
- // TODO(crawshaw): pick unused ports on localhost
- cfg1 := `private_key=481eb0d8113a4a5da532d2c3e9c14b53c8454b34ab109676f6b58c2245e37b58
+// TODO(crawshaw): pick unused ports on localhost
+var cfg1 = `private_key=481eb0d8113a4a5da532d2c3e9c14b53c8454b34ab109676f6b58c2245e37b58
listen_port=53511
replace_peers=true
public_key=f70dbb6b1b92a1dde1c783b297016af3f572fef13b0abb16a2623d89a58e9725
@@ -29,15 +29,8 @@ protocol_version=1
replace_allowed_ips=true
allowed_ip=1.0.0.2/32
endpoint=127.0.0.1:53512`
- tun1 := NewChannelTUN()
- dev1 := NewDevice(tun1.TUN(), NewLogger(LogLevelDebug, "dev1: "))
- dev1.Up()
- defer dev1.Close()
- if err := dev1.IpcSetOperation(bufio.NewReader(strings.NewReader(cfg1))); err != nil {
- t.Fatal(err)
- }
- cfg2 := `private_key=98c7989b1661a0d64fd6af3502000f87716b7c4bbcf00d04fc6073aa7b539768
+var cfg2 = `private_key=98c7989b1661a0d64fd6af3502000f87716b7c4bbcf00d04fc6073aa7b539768
listen_port=53512
replace_peers=true
public_key=49e80929259cebdda4f322d6d2b1a6fad819d603acd26fd5d845e7a123036427
@@ -45,6 +38,16 @@ protocol_version=1
replace_allowed_ips=true
allowed_ip=1.0.0.1/32
endpoint=127.0.0.1:53511`
+
+func TestTwoDevicePing(t *testing.T) {
+ tun1 := NewChannelTUN()
+ dev1 := NewDevice(tun1.TUN(), NewLogger(LogLevelDebug, "dev1: "))
+ dev1.Up()
+ defer dev1.Close()
+ if err := dev1.IpcSetOperation(bufio.NewReader(strings.NewReader(cfg1))); err != nil {
+ t.Fatal(err)
+ }
+
tun2 := NewChannelTUN()
dev2 := NewDevice(tun2.TUN(), NewLogger(LogLevelDebug, "dev2: "))
dev2.Up()
@@ -80,6 +83,63 @@ endpoint=127.0.0.1:53511`
})
}
+func TestSimultaneousHandshake(t *testing.T) {
+ // TODO(crawshaw): this is a handshake race between the peers.
+ // The value for maxWait should be safely 300 milliseconds, but
+ // it takes multiple seconds for the simultaneous handshakes
+ // to resolve a session key.
+ const maxWait = 6000 * time.Second
+
+ tun1 := NewChannelTUN()
+ dev1 := NewDevice(tun1.TUN(), NewLogger(LogLevelDebug, "dev1: "))
+ dev1.Up()
+ defer dev1.Close()
+ if err := dev1.IpcSetOperation(bufio.NewReader(strings.NewReader(cfg1))); err != nil {
+ t.Fatal(err)
+ }
+
+ tun2 := NewChannelTUN()
+ dev2 := NewDevice(tun2.TUN(), NewLogger(LogLevelDebug, "dev2: "))
+ dev2.Up()
+ defer dev2.Close()
+ if err := dev2.IpcSetOperation(bufio.NewReader(strings.NewReader(cfg2))); err != nil {
+ t.Fatal(err)
+ }
+
+ msg2to1 := ping(net.ParseIP("1.0.0.1"), net.ParseIP("1.0.0.2"))
+ msg1to2 := ping(net.ParseIP("1.0.0.2"), net.ParseIP("1.0.0.1"))
+
+ var wg sync.WaitGroup
+ wg.Add(2)
+ go func() {
+ tun1.Outbound <- msg1to2
+ wg.Done()
+ }()
+ go func() {
+ tun2.Outbound <- msg2to1
+ wg.Done()
+ }()
+ wg.Wait()
+
+ select {
+ case msgRecv := <-tun1.Inbound:
+ if !bytes.Equal(msg2to1, msgRecv) {
+ t.Error("ping did not transit correctly")
+ }
+ case <-time.After(maxWait):
+ t.Error("ping 1.0.0.1 did not transit")
+ }
+
+ select {
+ case msgRecv := <-tun2.Inbound:
+ if !bytes.Equal(msg1to2, msgRecv) {
+ t.Error("return ping did not transit correctly")
+ }
+ case <-time.After(maxWait):
+ t.Error("ping 1.0.0.2 did not transit")
+ }
+}
+
func ping(dst, src net.IP) []byte {
localPort := uint16(1337)
seq := uint16(0)