github.com/slackhq/nebula@v1.9.0/control_tester.go (about)

     1  //go:build e2e_testing
     2  // +build e2e_testing
     3  
     4  package nebula
     5  
     6  import (
     7  	"net"
     8  
     9  	"github.com/slackhq/nebula/cert"
    10  
    11  	"github.com/google/gopacket"
    12  	"github.com/google/gopacket/layers"
    13  	"github.com/slackhq/nebula/header"
    14  	"github.com/slackhq/nebula/iputil"
    15  	"github.com/slackhq/nebula/overlay"
    16  	"github.com/slackhq/nebula/udp"
    17  )
    18  
    19  // WaitForType will pipe all messages from this control device into the pipeTo control device
    20  // returning after a message matching the criteria has been piped
    21  func (c *Control) WaitForType(msgType header.MessageType, subType header.MessageSubType, pipeTo *Control) {
    22  	h := &header.H{}
    23  	for {
    24  		p := c.f.outside.(*udp.TesterConn).Get(true)
    25  		if err := h.Parse(p.Data); err != nil {
    26  			panic(err)
    27  		}
    28  		pipeTo.InjectUDPPacket(p)
    29  		if h.Type == msgType && h.Subtype == subType {
    30  			return
    31  		}
    32  	}
    33  }
    34  
    35  // WaitForTypeByIndex is similar to WaitForType except it adds an index check
    36  // Useful if you have many nodes communicating and want to wait to find a specific nodes packet
    37  func (c *Control) WaitForTypeByIndex(toIndex uint32, msgType header.MessageType, subType header.MessageSubType, pipeTo *Control) {
    38  	h := &header.H{}
    39  	for {
    40  		p := c.f.outside.(*udp.TesterConn).Get(true)
    41  		if err := h.Parse(p.Data); err != nil {
    42  			panic(err)
    43  		}
    44  		pipeTo.InjectUDPPacket(p)
    45  		if h.RemoteIndex == toIndex && h.Type == msgType && h.Subtype == subType {
    46  			return
    47  		}
    48  	}
    49  }
    50  
    51  // InjectLightHouseAddr will push toAddr into the local lighthouse cache for the vpnIp
    52  // This is necessary if you did not configure static hosts or are not running a lighthouse
    53  func (c *Control) InjectLightHouseAddr(vpnIp net.IP, toAddr *net.UDPAddr) {
    54  	c.f.lightHouse.Lock()
    55  	remoteList := c.f.lightHouse.unlockedGetRemoteList(iputil.Ip2VpnIp(vpnIp))
    56  	remoteList.Lock()
    57  	defer remoteList.Unlock()
    58  	c.f.lightHouse.Unlock()
    59  
    60  	iVpnIp := iputil.Ip2VpnIp(vpnIp)
    61  	if v4 := toAddr.IP.To4(); v4 != nil {
    62  		remoteList.unlockedPrependV4(iVpnIp, NewIp4AndPort(v4, uint32(toAddr.Port)))
    63  	} else {
    64  		remoteList.unlockedPrependV6(iVpnIp, NewIp6AndPort(toAddr.IP, uint32(toAddr.Port)))
    65  	}
    66  }
    67  
    68  // InjectRelays will push relayVpnIps into the local lighthouse cache for the vpnIp
    69  // This is necessary to inform an initiator of possible relays for communicating with a responder
    70  func (c *Control) InjectRelays(vpnIp net.IP, relayVpnIps []net.IP) {
    71  	c.f.lightHouse.Lock()
    72  	remoteList := c.f.lightHouse.unlockedGetRemoteList(iputil.Ip2VpnIp(vpnIp))
    73  	remoteList.Lock()
    74  	defer remoteList.Unlock()
    75  	c.f.lightHouse.Unlock()
    76  
    77  	iVpnIp := iputil.Ip2VpnIp(vpnIp)
    78  	uVpnIp := []uint32{}
    79  	for _, rVPnIp := range relayVpnIps {
    80  		uVpnIp = append(uVpnIp, uint32(iputil.Ip2VpnIp(rVPnIp)))
    81  	}
    82  
    83  	remoteList.unlockedSetRelay(iVpnIp, iVpnIp, uVpnIp)
    84  }
    85  
    86  // GetFromTun will pull a packet off the tun side of nebula
    87  func (c *Control) GetFromTun(block bool) []byte {
    88  	return c.f.inside.(*overlay.TestTun).Get(block)
    89  }
    90  
    91  // GetFromUDP will pull a udp packet off the udp side of nebula
    92  func (c *Control) GetFromUDP(block bool) *udp.Packet {
    93  	return c.f.outside.(*udp.TesterConn).Get(block)
    94  }
    95  
    96  func (c *Control) GetUDPTxChan() <-chan *udp.Packet {
    97  	return c.f.outside.(*udp.TesterConn).TxPackets
    98  }
    99  
   100  func (c *Control) GetTunTxChan() <-chan []byte {
   101  	return c.f.inside.(*overlay.TestTun).TxPackets
   102  }
   103  
   104  // InjectUDPPacket will inject a packet into the udp side of nebula
   105  func (c *Control) InjectUDPPacket(p *udp.Packet) {
   106  	c.f.outside.(*udp.TesterConn).Send(p)
   107  }
   108  
   109  // InjectTunUDPPacket puts a udp packet on the tun interface. Using UDP here because it's a simpler protocol
   110  func (c *Control) InjectTunUDPPacket(toIp net.IP, toPort uint16, fromPort uint16, data []byte) {
   111  	ip := layers.IPv4{
   112  		Version:  4,
   113  		TTL:      64,
   114  		Protocol: layers.IPProtocolUDP,
   115  		SrcIP:    c.f.inside.Cidr().IP,
   116  		DstIP:    toIp,
   117  	}
   118  
   119  	udp := layers.UDP{
   120  		SrcPort: layers.UDPPort(fromPort),
   121  		DstPort: layers.UDPPort(toPort),
   122  	}
   123  	err := udp.SetNetworkLayerForChecksum(&ip)
   124  	if err != nil {
   125  		panic(err)
   126  	}
   127  
   128  	buffer := gopacket.NewSerializeBuffer()
   129  	opt := gopacket.SerializeOptions{
   130  		ComputeChecksums: true,
   131  		FixLengths:       true,
   132  	}
   133  	err = gopacket.SerializeLayers(buffer, opt, &ip, &udp, gopacket.Payload(data))
   134  	if err != nil {
   135  		panic(err)
   136  	}
   137  
   138  	c.f.inside.(*overlay.TestTun).Send(buffer.Bytes())
   139  }
   140  
   141  func (c *Control) GetVpnIp() iputil.VpnIp {
   142  	return c.f.myVpnIp
   143  }
   144  
   145  func (c *Control) GetUDPAddr() string {
   146  	return c.f.outside.(*udp.TesterConn).Addr.String()
   147  }
   148  
   149  func (c *Control) KillPendingTunnel(vpnIp net.IP) bool {
   150  	hostinfo := c.f.handshakeManager.QueryVpnIp(iputil.Ip2VpnIp(vpnIp))
   151  	if hostinfo == nil {
   152  		return false
   153  	}
   154  
   155  	c.f.handshakeManager.DeleteHostInfo(hostinfo)
   156  	return true
   157  }
   158  
   159  func (c *Control) GetHostmap() *HostMap {
   160  	return c.f.hostMap
   161  }
   162  
   163  func (c *Control) GetCert() *cert.NebulaCertificate {
   164  	return c.f.pki.GetCertState().Certificate
   165  }
   166  
   167  func (c *Control) ReHandshake(vpnIp iputil.VpnIp) {
   168  	c.f.handshakeManager.StartHandshake(vpnIp, nil)
   169  }