Start of end to end testing with a good handshake between two nodes (#425)
This commit is contained in:
		
							
								
								
									
										5
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								Makefile
									
									
									
									
									
								
							| @@ -32,7 +32,8 @@ ALL = $(ALL_LINUX) \ | |||||||
| 	freebsd-amd64 \ | 	freebsd-amd64 \ | ||||||
| 	windows-amd64 | 	windows-amd64 | ||||||
|  |  | ||||||
|  | e2e: | ||||||
|  | 	go test -v -tags=e2e_testing ./e2e | ||||||
|  |  | ||||||
| all: $(ALL:%=build/%/nebula) $(ALL:%=build/%/nebula-cert) | all: $(ALL:%=build/%/nebula) $(ALL:%=build/%/nebula-cert) | ||||||
|  |  | ||||||
| @@ -137,5 +138,5 @@ smoke-docker-race: BUILD_ARGS = -race | |||||||
| smoke-docker-race: smoke-docker | smoke-docker-race: smoke-docker | ||||||
|  |  | ||||||
| .FORCE: | .FORCE: | ||||||
| .PHONY: test test-cov-html bench bench-cpu bench-cpu-long bin proto release service smoke-docker smoke-docker-race | .PHONY: e2e test test-cov-html bench bench-cpu bench-cpu-long bin proto release service smoke-docker smoke-docker-race | ||||||
| .DEFAULT_GOAL := bin | .DEFAULT_GOAL := bin | ||||||
|   | |||||||
							
								
								
									
										92
									
								
								control_tester.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								control_tester.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,92 @@ | |||||||
|  | // +build e2e_testing | ||||||
|  |  | ||||||
|  | package nebula | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"net" | ||||||
|  |  | ||||||
|  | 	"github.com/google/gopacket" | ||||||
|  | 	"github.com/google/gopacket/layers" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // WaitForTypeByIndex will pipe all messages from this control device into the pipeTo control device | ||||||
|  | // returning after a message matching the criteria has been piped | ||||||
|  | func (c *Control) WaitForType(msgType NebulaMessageType, subType NebulaMessageSubType, pipeTo *Control) { | ||||||
|  | 	h := &Header{} | ||||||
|  | 	for { | ||||||
|  | 		p := c.f.outside.Get(true) | ||||||
|  | 		if err := h.Parse(p.Data); err != nil { | ||||||
|  | 			panic(err) | ||||||
|  | 		} | ||||||
|  | 		pipeTo.InjectUDPPacket(p) | ||||||
|  | 		if h.Type == msgType && h.Subtype == subType { | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // WaitForTypeByIndex is similar to WaitForType except it adds an index check | ||||||
|  | // Useful if you have many nodes communicating and want to wait to find a specific nodes packet | ||||||
|  | func (c *Control) WaitForTypeByIndex(toIndex uint32, msgType NebulaMessageType, subType NebulaMessageSubType, pipeTo *Control) { | ||||||
|  | 	h := &Header{} | ||||||
|  | 	for { | ||||||
|  | 		p := c.f.outside.Get(true) | ||||||
|  | 		if err := h.Parse(p.Data); err != nil { | ||||||
|  | 			panic(err) | ||||||
|  | 		} | ||||||
|  | 		pipeTo.InjectUDPPacket(p) | ||||||
|  | 		if h.RemoteIndex == toIndex && h.Type == msgType && h.Subtype == subType { | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // InjectLightHouseAddr will push toAddr into the local lighthouse cache for the vpnIp | ||||||
|  | // This is necessary if you did not configure static hosts or are not running a lighthouse | ||||||
|  | func (c *Control) InjectLightHouseAddr(vpnIp net.IP, toAddr *net.UDPAddr) { | ||||||
|  | 	c.f.lightHouse.AddRemote(ip2int(vpnIp), &udpAddr{IP: toAddr.IP, Port: uint16(toAddr.Port)}, false) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // GetFromTun will pull a packet off the tun side of nebula | ||||||
|  | func (c *Control) GetFromTun(block bool) []byte { | ||||||
|  | 	return c.f.inside.(*Tun).Get(block) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // GetFromUDP will pull a udp packet off the udp side of nebula | ||||||
|  | func (c *Control) GetFromUDP(block bool) *UdpPacket { | ||||||
|  | 	return c.f.outside.Get(block) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // InjectUDPPacket will inject a packet into the udp side of nebula | ||||||
|  | func (c *Control) InjectUDPPacket(p *UdpPacket) { | ||||||
|  | 	c.f.outside.Send(p) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // InjectTunUDPPacket puts a udp packet on the tun interface. Using UDP here because it's a simpler protocol | ||||||
|  | func (c *Control) InjectTunUDPPacket(toIp net.IP, toPort uint16, fromPort uint16, data []byte) { | ||||||
|  | 	ip := layers.IPv4{ | ||||||
|  | 		Version:  4, | ||||||
|  | 		TTL:      64, | ||||||
|  | 		Protocol: layers.IPProtocolUDP, | ||||||
|  | 		SrcIP:    c.f.inside.CidrNet().IP, | ||||||
|  | 		DstIP:    toIp, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	udp := layers.UDP{ | ||||||
|  | 		SrcPort: layers.UDPPort(fromPort), | ||||||
|  | 		DstPort: layers.UDPPort(toPort), | ||||||
|  | 	} | ||||||
|  | 	udp.SetNetworkLayerForChecksum(&ip) | ||||||
|  |  | ||||||
|  | 	buffer := gopacket.NewSerializeBuffer() | ||||||
|  | 	opt := gopacket.SerializeOptions{ | ||||||
|  | 		ComputeChecksums: true, | ||||||
|  | 		FixLengths:       true, | ||||||
|  | 	} | ||||||
|  | 	err := gopacket.SerializeLayers(buffer, opt, &ip, &udp, gopacket.Payload(data)) | ||||||
|  | 	if err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	c.f.inside.(*Tun).Send(buffer.Bytes()) | ||||||
|  | } | ||||||
							
								
								
									
										60
									
								
								e2e/handshakes_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								e2e/handshakes_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | |||||||
|  | // +build e2e_testing | ||||||
|  |  | ||||||
|  | package e2e | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"net" | ||||||
|  | 	"testing" | ||||||
|  | 	"time" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func TestGoodHandshake(t *testing.T) { | ||||||
|  | 	ca, _, caKey, _ := newTestCaCert(time.Now(), time.Now().Add(10*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{}) | ||||||
|  | 	defMask := net.IPMask{0, 0, 0, 0} | ||||||
|  |  | ||||||
|  | 	myUdpAddr := &net.UDPAddr{IP: net.IP{10, 0, 0, 1}, Port: 4242} | ||||||
|  | 	myVpnIpNet := &net.IPNet{IP: net.IP{10, 128, 0, 1}, Mask: defMask} | ||||||
|  | 	myControl := newSimpleServer(ca, caKey, "me", myUdpAddr, myVpnIpNet) | ||||||
|  |  | ||||||
|  | 	theirUdpAddr := &net.UDPAddr{IP: net.IP{10, 0, 0, 2}, Port: 4242} | ||||||
|  | 	theirVpnIpNet := &net.IPNet{IP: net.IP{10, 128, 0, 2}, Mask: defMask} | ||||||
|  | 	theirControl := newSimpleServer(ca, caKey, "them", theirUdpAddr, theirVpnIpNet) | ||||||
|  |  | ||||||
|  | 	// Put their info in our lighthouse | ||||||
|  | 	myControl.InjectLightHouseAddr(theirVpnIpNet.IP, theirUdpAddr) | ||||||
|  |  | ||||||
|  | 	// Start the servers | ||||||
|  | 	myControl.Start() | ||||||
|  | 	theirControl.Start() | ||||||
|  |  | ||||||
|  | 	// Send a udp packet through to begin standing up the tunnel, this should come out the other side | ||||||
|  | 	myControl.InjectTunUDPPacket(theirVpnIpNet.IP, 80, 80, []byte("Hi from me")) | ||||||
|  |  | ||||||
|  | 	// Have them consume my stage 0 packet. They have a tunnel now | ||||||
|  | 	theirControl.InjectUDPPacket(myControl.GetFromUDP(true)) | ||||||
|  |  | ||||||
|  | 	// Have me consume their stage 1 packet. I have a tunnel now | ||||||
|  | 	myControl.InjectUDPPacket(theirControl.GetFromUDP(true)) | ||||||
|  |  | ||||||
|  | 	// Wait until we see my cached packet come through | ||||||
|  | 	myControl.WaitForType(1, 0, theirControl) | ||||||
|  |  | ||||||
|  | 	// Make sure our host infos are correct | ||||||
|  | 	assertHostInfoPair(t, myUdpAddr, theirUdpAddr, myVpnIpNet.IP, theirVpnIpNet.IP, myControl, theirControl) | ||||||
|  |  | ||||||
|  | 	// Get that cached packet and make sure it looks right | ||||||
|  | 	myCachedPacket := theirControl.GetFromTun(true) | ||||||
|  | 	assertUdpPacket(t, []byte("Hi from me"), myCachedPacket, myVpnIpNet.IP, theirVpnIpNet.IP, 80, 80) | ||||||
|  |  | ||||||
|  | 	// Send a packet from them to me | ||||||
|  | 	theirControl.InjectTunUDPPacket(myVpnIpNet.IP, 80, 80, []byte("Hi from them")) | ||||||
|  | 	myControl.InjectUDPPacket(theirControl.GetFromUDP(true)) | ||||||
|  | 	theirPacket := myControl.GetFromTun(true) | ||||||
|  | 	assertUdpPacket(t, []byte("Hi from them"), theirPacket, theirVpnIpNet.IP, myVpnIpNet.IP, 80, 80) | ||||||
|  |  | ||||||
|  | 	// And once more from me to them | ||||||
|  | 	myControl.InjectTunUDPPacket(theirVpnIpNet.IP, 80, 80, []byte("Hello again from me")) | ||||||
|  | 	theirControl.InjectUDPPacket(myControl.GetFromUDP(true)) | ||||||
|  | 	myPacket := theirControl.GetFromTun(true) | ||||||
|  | 	assertUdpPacket(t, []byte("Hello again from me"), myPacket, myVpnIpNet.IP, theirVpnIpNet.IP, 80, 80) | ||||||
|  | } | ||||||
							
								
								
									
										252
									
								
								e2e/helpers_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										252
									
								
								e2e/helpers_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,252 @@ | |||||||
|  | // +build e2e_testing | ||||||
|  |  | ||||||
|  | package e2e | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"crypto/rand" | ||||||
|  | 	"encoding/binary" | ||||||
|  | 	"fmt" | ||||||
|  | 	"io" | ||||||
|  | 	"net" | ||||||
|  | 	"testing" | ||||||
|  | 	"time" | ||||||
|  |  | ||||||
|  | 	"github.com/google/gopacket" | ||||||
|  | 	"github.com/google/gopacket/layers" | ||||||
|  | 	"github.com/sirupsen/logrus" | ||||||
|  | 	"github.com/slackhq/nebula" | ||||||
|  | 	"github.com/slackhq/nebula/cert" | ||||||
|  | 	"github.com/stretchr/testify/assert" | ||||||
|  | 	"golang.org/x/crypto/curve25519" | ||||||
|  | 	"golang.org/x/crypto/ed25519" | ||||||
|  | 	"gopkg.in/yaml.v2" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type m map[string]interface{} | ||||||
|  |  | ||||||
|  | // newSimpleServer creates a nebula instance with many assumptions | ||||||
|  | func newSimpleServer(caCrt *cert.NebulaCertificate, caKey []byte, name string, listenAddr *net.UDPAddr, vpnIp *net.IPNet) *nebula.Control { | ||||||
|  | 	l := logrus.New() | ||||||
|  | 	_, _, myPrivKey, myPEM := newTestCert(caCrt, caKey, name, time.Now(), time.Now().Add(5*time.Minute), vpnIp, nil, []string{}) | ||||||
|  |  | ||||||
|  | 	caB, err := caCrt.MarshalToPEM() | ||||||
|  | 	if err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	mc := m{ | ||||||
|  | 		"pki": m{ | ||||||
|  | 			"ca":   string(caB), | ||||||
|  | 			"cert": string(myPEM), | ||||||
|  | 			"key":  string(myPrivKey), | ||||||
|  | 		}, | ||||||
|  | 		//"tun": m{"disabled": true}, | ||||||
|  | 		"firewall": m{ | ||||||
|  | 			"outbound": []m{{ | ||||||
|  | 				"proto": "any", | ||||||
|  | 				"port":  "any", | ||||||
|  | 				"host":  "any", | ||||||
|  | 			}}, | ||||||
|  | 			"inbound": []m{{ | ||||||
|  | 				"proto": "any", | ||||||
|  | 				"port":  "any", | ||||||
|  | 				"host":  "any", | ||||||
|  | 			}}, | ||||||
|  | 		}, | ||||||
|  | 		"listen": m{ | ||||||
|  | 			"host": listenAddr.IP.String(), | ||||||
|  | 			"port": listenAddr.Port, | ||||||
|  | 		}, | ||||||
|  | 		"logging": m{ | ||||||
|  | 			"timestamp_format": fmt.Sprintf("%v 15:04:05.000000", name), | ||||||
|  | 			"level":            "info", | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 	cb, err := yaml.Marshal(mc) | ||||||
|  | 	if err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	config := nebula.NewConfig(l) | ||||||
|  | 	config.LoadString(string(cb)) | ||||||
|  |  | ||||||
|  | 	control, err := nebula.Main(config, false, "e2e-test", l, nil) | ||||||
|  |  | ||||||
|  | 	if err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return control | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // newTestCaCert will generate a CA cert | ||||||
|  | func newTestCaCert(before, after time.Time, ips, subnets []*net.IPNet, groups []string) (*cert.NebulaCertificate, []byte, []byte, []byte) { | ||||||
|  | 	pub, priv, err := ed25519.GenerateKey(rand.Reader) | ||||||
|  | 	if before.IsZero() { | ||||||
|  | 		before = time.Now().Add(time.Second * -60).Round(time.Second) | ||||||
|  | 	} | ||||||
|  | 	if after.IsZero() { | ||||||
|  | 		after = time.Now().Add(time.Second * 60).Round(time.Second) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	nc := &cert.NebulaCertificate{ | ||||||
|  | 		Details: cert.NebulaCertificateDetails{ | ||||||
|  | 			Name:           "test ca", | ||||||
|  | 			NotBefore:      time.Unix(before.Unix(), 0), | ||||||
|  | 			NotAfter:       time.Unix(after.Unix(), 0), | ||||||
|  | 			PublicKey:      pub, | ||||||
|  | 			IsCA:           true, | ||||||
|  | 			InvertedGroups: make(map[string]struct{}), | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if len(ips) > 0 { | ||||||
|  | 		nc.Details.Ips = ips | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if len(subnets) > 0 { | ||||||
|  | 		nc.Details.Subnets = subnets | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if len(groups) > 0 { | ||||||
|  | 		nc.Details.Groups = groups | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	err = nc.Sign(priv) | ||||||
|  | 	if err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	pem, err := nc.MarshalToPEM() | ||||||
|  | 	if err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return nc, pub, priv, pem | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // newTestCert will generate a signed certificate with the provided details. | ||||||
|  | // Expiry times are defaulted if you do not pass them in | ||||||
|  | func newTestCert(ca *cert.NebulaCertificate, key []byte, name string, before, after time.Time, ip *net.IPNet, subnets []*net.IPNet, groups []string) (*cert.NebulaCertificate, []byte, []byte, []byte) { | ||||||
|  | 	issuer, err := ca.Sha256Sum() | ||||||
|  | 	if err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if before.IsZero() { | ||||||
|  | 		before = time.Now().Add(time.Second * -60).Round(time.Second) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if after.IsZero() { | ||||||
|  | 		after = time.Now().Add(time.Second * 60).Round(time.Second) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	pub, rawPriv := x25519Keypair() | ||||||
|  |  | ||||||
|  | 	nc := &cert.NebulaCertificate{ | ||||||
|  | 		Details: cert.NebulaCertificateDetails{ | ||||||
|  | 			Name:           name, | ||||||
|  | 			Ips:            []*net.IPNet{ip}, | ||||||
|  | 			Subnets:        subnets, | ||||||
|  | 			Groups:         groups, | ||||||
|  | 			NotBefore:      time.Unix(before.Unix(), 0), | ||||||
|  | 			NotAfter:       time.Unix(after.Unix(), 0), | ||||||
|  | 			PublicKey:      pub, | ||||||
|  | 			IsCA:           false, | ||||||
|  | 			Issuer:         issuer, | ||||||
|  | 			InvertedGroups: make(map[string]struct{}), | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	err = nc.Sign(key) | ||||||
|  | 	if err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	pem, err := nc.MarshalToPEM() | ||||||
|  | 	if err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return nc, pub, cert.MarshalX25519PrivateKey(rawPriv), pem | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func x25519Keypair() ([]byte, []byte) { | ||||||
|  | 	var pubkey, privkey [32]byte | ||||||
|  | 	if _, err := io.ReadFull(rand.Reader, privkey[:]); err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  | 	curve25519.ScalarBaseMult(&pubkey, &privkey) | ||||||
|  | 	return pubkey[:], privkey[:] | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func ip2int(ip []byte) uint32 { | ||||||
|  | 	if len(ip) == 16 { | ||||||
|  | 		return binary.BigEndian.Uint32(ip[12:16]) | ||||||
|  | 	} | ||||||
|  | 	return binary.BigEndian.Uint32(ip) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func int2ip(nn uint32) net.IP { | ||||||
|  | 	ip := make(net.IP, 4) | ||||||
|  | 	binary.BigEndian.PutUint32(ip, nn) | ||||||
|  | 	return ip | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func assertHostInfoPair(t *testing.T, addrA, addrB *net.UDPAddr, vpnIpA, vpnIpB net.IP, controlA, controlB *nebula.Control) { | ||||||
|  | 	// Get both host infos | ||||||
|  | 	hBinA := controlA.GetHostInfoByVpnIP(ip2int(vpnIpB), false) | ||||||
|  | 	assert.NotNil(t, hBinA, "Host B was not found by vpnIP in controlA") | ||||||
|  |  | ||||||
|  | 	hAinB := controlB.GetHostInfoByVpnIP(ip2int(vpnIpA), false) | ||||||
|  | 	assert.NotNil(t, hAinB, "Host A was not found by vpnIP in controlB") | ||||||
|  |  | ||||||
|  | 	// Check that both vpn and real addr are correct | ||||||
|  | 	assert.Equal(t, vpnIpB, hBinA.VpnIP, "HostA VpnIp is wrong in controlB") | ||||||
|  | 	assert.Equal(t, vpnIpA, hAinB.VpnIP, "HostB VpnIp is wrong in controlA") | ||||||
|  |  | ||||||
|  | 	assert.Equal(t, addrB.IP.To16(), hBinA.CurrentRemote.IP.To16(), "HostA remote ip is wrong in controlB") | ||||||
|  | 	assert.Equal(t, addrA.IP.To16(), hAinB.CurrentRemote.IP.To16(), "HostB remote ip is wrong in controlA") | ||||||
|  |  | ||||||
|  | 	assert.Equal(t, uint16(addrA.Port), hBinA.CurrentRemote.Port, "HostA remote ip is wrong in controlB") | ||||||
|  | 	assert.Equal(t, uint16(addrB.Port), hAinB.CurrentRemote.Port, "HostB remote ip is wrong in controlA") | ||||||
|  |  | ||||||
|  | 	// Check that our indexes match | ||||||
|  | 	assert.Equal(t, hBinA.LocalIndex, hAinB.RemoteIndex, "Host B local index does not match host A remote index") | ||||||
|  | 	assert.Equal(t, hBinA.RemoteIndex, hAinB.LocalIndex, "Host B remote index does not match host A local index") | ||||||
|  |  | ||||||
|  | 	//TODO: Would be nice to assert this memory | ||||||
|  | 	//checkIndexes := func(name string, hm *HostMap, hi *HostInfo) { | ||||||
|  | 	//	hBbyIndex := hmA.Indexes[hBinA.localIndexId] | ||||||
|  | 	//	assert.NotNil(t, hBbyIndex, "Could not host info by local index in %s", name) | ||||||
|  | 	//	assert.Equal(t, &hBbyIndex, &hBinA, "%s Indexes map did not point to the right host info", name) | ||||||
|  | 	// | ||||||
|  | 	//	//TODO: remote indexes are susceptible to collision | ||||||
|  | 	//	hBbyRemoteIndex := hmA.RemoteIndexes[hBinA.remoteIndexId] | ||||||
|  | 	//	assert.NotNil(t, hBbyIndex, "Could not host info by remote index in %s", name) | ||||||
|  | 	//	assert.Equal(t, &hBbyRemoteIndex, &hBinA, "%s RemoteIndexes did not point to the right host info", name) | ||||||
|  | 	//} | ||||||
|  | 	// | ||||||
|  | 	//// Check hostmap indexes too | ||||||
|  | 	//checkIndexes("hmA", hmA, hBinA) | ||||||
|  | 	//checkIndexes("hmB", hmB, hAinB) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func assertUdpPacket(t *testing.T, expected, b []byte, fromIp, toIp net.IP, fromPort, toPort uint16) { | ||||||
|  | 	packet := gopacket.NewPacket(b, layers.LayerTypeIPv4, gopacket.Lazy) | ||||||
|  | 	v4 := packet.Layer(layers.LayerTypeIPv4).(*layers.IPv4) | ||||||
|  | 	assert.NotNil(t, v4, "No ipv4 data found") | ||||||
|  |  | ||||||
|  | 	assert.Equal(t, fromIp, v4.SrcIP, "Source ip was incorrect") | ||||||
|  | 	assert.Equal(t, toIp, v4.DstIP, "Dest ip was incorrect") | ||||||
|  |  | ||||||
|  | 	udp := packet.Layer(layers.LayerTypeUDP).(*layers.UDP) | ||||||
|  | 	assert.NotNil(t, udp, "No udp data found") | ||||||
|  |  | ||||||
|  | 	assert.Equal(t, fromPort, uint16(udp.SrcPort), "Source port was incorrect") | ||||||
|  | 	assert.Equal(t, toPort, uint16(udp.DstPort), "Dest port was incorrect") | ||||||
|  |  | ||||||
|  | 	data := packet.ApplicationLayer() | ||||||
|  | 	assert.NotNil(t, data) | ||||||
|  | 	assert.Equal(t, expected, data.Payload(), "Data was incorrect") | ||||||
|  | } | ||||||
							
								
								
									
										1
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								go.mod
									
									
									
									
									
								
							| @@ -10,6 +10,7 @@ require ( | |||||||
| 	github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 // indirect | 	github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 // indirect | ||||||
| 	github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6 | 	github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6 | ||||||
| 	github.com/golang/protobuf v1.5.0 | 	github.com/golang/protobuf v1.5.0 | ||||||
|  | 	github.com/google/gopacket v1.1.19 // indirect | ||||||
| 	github.com/imdario/mergo v0.3.8 | 	github.com/imdario/mergo v0.3.8 | ||||||
| 	github.com/kardianos/service v1.1.0 | 	github.com/kardianos/service v1.1.0 | ||||||
| 	github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect | 	github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect | ||||||
|   | |||||||
							
								
								
									
										7
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								go.sum
									
									
									
									
									
								
							| @@ -62,6 +62,8 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ | |||||||
| github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | ||||||
| github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | ||||||
| github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= | ||||||
|  | github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= | ||||||
|  | github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= | ||||||
| github.com/imdario/mergo v0.3.8 h1:CGgOkSJeqMRmt0D9XLWExdT4m4F1vd3FV3VPt+0VxkQ= | github.com/imdario/mergo v0.3.8 h1:CGgOkSJeqMRmt0D9XLWExdT4m4F1vd3FV3VPt+0VxkQ= | ||||||
| github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= | github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= | ||||||
| github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= | github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= | ||||||
| @@ -139,12 +141,15 @@ github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17 | |||||||
| golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= | golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= | ||||||
| golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | ||||||
| golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= | golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= | ||||||
|  | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | ||||||
| golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975 h1:/Tl7pH94bvbAAHBdZJT947M/+gp0+CqQXDtMRC0fseo= | golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975 h1:/Tl7pH94bvbAAHBdZJT947M/+gp0+CqQXDtMRC0fseo= | ||||||
| golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | ||||||
| golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= | ||||||
| golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= | ||||||
| golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= | ||||||
| golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= | ||||||
|  | golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= | ||||||
|  | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= | ||||||
| golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||||||
| golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||||||
| golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||||||
| @@ -184,7 +189,9 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3 | |||||||
| golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= | ||||||
| golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= | ||||||
| golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | ||||||
|  | golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= | ||||||
| golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||||
|  | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||||
| google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= | ||||||
| google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= | ||||||
|   | |||||||
| @@ -1,3 +1,5 @@ | |||||||
|  | // +build !e2e_testing | ||||||
|  |  | ||||||
| package nebula | package nebula | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|   | |||||||
| @@ -1,4 +1,5 @@ | |||||||
| // +build !ios | // +build !ios | ||||||
|  | // +build !e2e_testing | ||||||
|  |  | ||||||
| package nebula | package nebula | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,3 +1,5 @@ | |||||||
|  | // +build !e2e_testing | ||||||
|  |  | ||||||
| package nebula | package nebula | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|   | |||||||
| @@ -1,4 +1,5 @@ | |||||||
| // +build ios | // +build ios | ||||||
|  | // +build !e2e_testing | ||||||
|  |  | ||||||
| package nebula | package nebula | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,4 +1,5 @@ | |||||||
| // +build !android | // +build !android | ||||||
|  | // +build !e2e_testing | ||||||
|  |  | ||||||
| package nebula | package nebula | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,3 +1,5 @@ | |||||||
|  | // +build !e2e_testing | ||||||
|  |  | ||||||
| package nebula | package nebula | ||||||
|  |  | ||||||
| import "testing" | import "testing" | ||||||
|   | |||||||
							
								
								
									
										103
									
								
								tun_tester.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								tun_tester.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,103 @@ | |||||||
|  | // +build e2e_testing | ||||||
|  |  | ||||||
|  | package nebula | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"io" | ||||||
|  | 	"net" | ||||||
|  |  | ||||||
|  | 	"github.com/sirupsen/logrus" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type Tun struct { | ||||||
|  | 	Device       string | ||||||
|  | 	Cidr         *net.IPNet | ||||||
|  | 	MTU          int | ||||||
|  | 	UnsafeRoutes []route | ||||||
|  | 	l            *logrus.Logger | ||||||
|  |  | ||||||
|  | 	rxPackets chan []byte // Packets to receive into nebula | ||||||
|  | 	txPackets chan []byte // Packets transmitted outside by nebula | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func newTun(l *logrus.Logger, deviceName string, cidr *net.IPNet, defaultMTU int, _ []route, unsafeRoutes []route, _ int, _ bool) (ifce *Tun, err error) { | ||||||
|  | 	return &Tun{ | ||||||
|  | 		Device:       deviceName, | ||||||
|  | 		Cidr:         cidr, | ||||||
|  | 		MTU:          defaultMTU, | ||||||
|  | 		UnsafeRoutes: unsafeRoutes, | ||||||
|  | 		l:            l, | ||||||
|  | 		rxPackets:    make(chan []byte, 100), | ||||||
|  | 		txPackets:    make(chan []byte, 100), | ||||||
|  | 	}, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func newTunFromFd(_ *logrus.Logger, _ int, _ *net.IPNet, _ int, _ []route, _ []route, _ int) (ifce *Tun, err error) { | ||||||
|  | 	return nil, fmt.Errorf("newTunFromFd not supported") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Send will place a byte array onto the receive queue for nebula to consume | ||||||
|  | // These are unencrypted ip layer frames destined for another nebula node. | ||||||
|  | // packets should exit the udp side, capture them with udpConn.Get | ||||||
|  | func (c *Tun) Send(packet []byte) { | ||||||
|  | 	c.rxPackets <- packet | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Get will pull an unencrypted ip layer frame from the transmit queue | ||||||
|  | // nebula meant to send this message to some application on the local system | ||||||
|  | // packets were ingested from the udp side, you can send them with udpConn.Send | ||||||
|  | func (c *Tun) Get(block bool) []byte { | ||||||
|  | 	if block { | ||||||
|  | 		return <-c.txPackets | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	select { | ||||||
|  | 	case p := <-c.txPackets: | ||||||
|  | 		return p | ||||||
|  | 	default: | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | //********************************************************************************************************************// | ||||||
|  | // Below this is boilerplate implementation to make nebula actually work | ||||||
|  | //********************************************************************************************************************// | ||||||
|  |  | ||||||
|  | func (c *Tun) Activate() error { | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *Tun) CidrNet() *net.IPNet { | ||||||
|  | 	return c.Cidr | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *Tun) DeviceName() string { | ||||||
|  | 	return c.Device | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *Tun) Write(b []byte) (n int, err error) { | ||||||
|  | 	return len(b), c.WriteRaw(b) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *Tun) Close() error { | ||||||
|  | 	close(c.rxPackets) | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *Tun) WriteRaw(b []byte) error { | ||||||
|  | 	packet := make([]byte, len(b), len(b)) | ||||||
|  | 	copy(packet, b) | ||||||
|  | 	c.txPackets <- packet | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *Tun) Read(b []byte) (int, error) { | ||||||
|  | 	p := <-c.rxPackets | ||||||
|  | 	copy(b, p) | ||||||
|  | 	return len(p), nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *Tun) NewMultiQueueReader() (io.ReadWriteCloser, error) { | ||||||
|  | 	return nil, fmt.Errorf("TODO: multiqueue not implemented") | ||||||
|  | } | ||||||
							
								
								
									
										116
									
								
								udp_tester.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								udp_tester.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,116 @@ | |||||||
|  | // +build e2e_testing | ||||||
|  |  | ||||||
|  | package nebula | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"net" | ||||||
|  |  | ||||||
|  | 	"github.com/sirupsen/logrus" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type UdpPacket struct { | ||||||
|  | 	ToIp     net.IP | ||||||
|  | 	ToPort   uint16 | ||||||
|  | 	FromIp   net.IP | ||||||
|  | 	FromPort uint16 | ||||||
|  | 	Data     []byte | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type udpConn struct { | ||||||
|  | 	addr *udpAddr | ||||||
|  |  | ||||||
|  | 	rxPackets chan *UdpPacket // Packets to receive into nebula | ||||||
|  | 	txPackets chan *UdpPacket // Packets transmitted outside by nebula | ||||||
|  |  | ||||||
|  | 	l *logrus.Logger | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func NewListener(l *logrus.Logger, ip string, port int, _ bool) (*udpConn, error) { | ||||||
|  | 	return &udpConn{ | ||||||
|  | 		addr:      &udpAddr{net.ParseIP(ip), uint16(port)}, | ||||||
|  | 		rxPackets: make(chan *UdpPacket, 1), | ||||||
|  | 		txPackets: make(chan *UdpPacket, 1), | ||||||
|  | 		l:         l, | ||||||
|  | 	}, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Send will place a UdpPacket onto the receive queue for nebula to consume | ||||||
|  | // this is an encrypted packet or a handshake message in most cases | ||||||
|  | // packets were transmitted from another nebula node, you can send them with Tun.Send | ||||||
|  | func (u *udpConn) Send(packet *UdpPacket) { | ||||||
|  | 	u.rxPackets <- packet | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Get will pull a UdpPacket from the transmit queue | ||||||
|  | // nebula meant to send this message on the network, it will be encrypted | ||||||
|  | // packets were ingested from the tun side (in most cases), you can send them with Tun.Send | ||||||
|  | func (u *udpConn) Get(block bool) *UdpPacket { | ||||||
|  | 	if block { | ||||||
|  | 		return <-u.txPackets | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	select { | ||||||
|  | 	case p := <-u.txPackets: | ||||||
|  | 		return p | ||||||
|  | 	default: | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | //********************************************************************************************************************// | ||||||
|  | // Below this is boilerplate implementation to make nebula actually work | ||||||
|  | //********************************************************************************************************************// | ||||||
|  |  | ||||||
|  | func (u *udpConn) WriteTo(b []byte, addr *udpAddr) error { | ||||||
|  | 	p := &UdpPacket{ | ||||||
|  | 		Data:     make([]byte, len(b), len(b)), | ||||||
|  | 		FromIp:   make([]byte, 16), | ||||||
|  | 		FromPort: u.addr.Port, | ||||||
|  | 		ToIp:     make([]byte, 16), | ||||||
|  | 		ToPort:   addr.Port, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	copy(p.Data, b) | ||||||
|  | 	copy(p.ToIp, addr.IP) | ||||||
|  | 	copy(p.FromIp, u.addr.IP) | ||||||
|  |  | ||||||
|  | 	u.txPackets <- p | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (u *udpConn) ListenOut(f *Interface, q int) { | ||||||
|  | 	plaintext := make([]byte, mtu) | ||||||
|  | 	header := &Header{} | ||||||
|  | 	fwPacket := &FirewallPacket{} | ||||||
|  | 	ua := &udpAddr{IP: make([]byte, 16)} | ||||||
|  | 	nb := make([]byte, 12, 12) | ||||||
|  |  | ||||||
|  | 	lhh := f.lightHouse.NewRequestHandler() | ||||||
|  | 	conntrackCache := NewConntrackCacheTicker(f.conntrackCacheTimeout) | ||||||
|  |  | ||||||
|  | 	for { | ||||||
|  | 		p := <-u.rxPackets | ||||||
|  | 		ua.Port = p.FromPort | ||||||
|  | 		copy(ua.IP, p.FromIp.To16()) | ||||||
|  | 		f.readOutsidePackets(ua, plaintext[:0], p.Data, header, fwPacket, lhh, nb, q, conntrackCache.Get(u.l)) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (u *udpConn) reloadConfig(*Config) {} | ||||||
|  |  | ||||||
|  | func NewUDPStatsEmitter(_ []*udpConn) func() { | ||||||
|  | 	// No UDP stats for non-linux | ||||||
|  | 	return func() {} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (u *udpConn) LocalAddr() (*udpAddr, error) { | ||||||
|  | 	return u.addr, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (u *udpConn) Rebind() error { | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func hostDidRoam(addr *udpAddr, newaddr *udpAddr) bool { | ||||||
|  | 	return !addr.Equals(newaddr) | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user
	 Nathan Brown
					Nathan Brown