tstest/natlab/vnet: treat network wan/lan interface separately

Signed-off-by: Maisem Ali <maisem@tailscale.com>
This commit is contained in:
Maisem Ali 2024-08-08 21:53:13 -07:00
parent 6c21021fff
commit 7e02481ecd
2 changed files with 59 additions and 39 deletions

View File

@ -229,8 +229,12 @@ func (s *Server) initFromConfig(c *Config) error {
return fmt.Errorf("two networks have the same WAN IP %v; Anycast not (yet?) supported", conf.wanIP) return fmt.Errorf("two networks have the same WAN IP %v; Anycast not (yet?) supported", conf.wanIP)
} }
s.networkByWAN[conf.wanIP] = n s.networkByWAN[conf.wanIP] = n
n.interfaceID = must.Get(s.pcapWriter.AddInterface(pcapgo.NgInterface{ n.lanInterfaceID = must.Get(s.pcapWriter.AddInterface(pcapgo.NgInterface{
Name: fmt.Sprintf("network%d", i+1), Name: fmt.Sprintf("network%d-lan", i+1),
LinkType: layers.LinkTypeIPv4,
}))
n.wanInterfaceID = must.Get(s.pcapWriter.AddInterface(pcapgo.NgInterface{
Name: fmt.Sprintf("network%d-wan", i+1),
LinkType: layers.LinkTypeIPv4, LinkType: layers.LinkTypeIPv4,
})) }))
} }

View File

@ -404,14 +404,15 @@ type portMapping struct {
} }
type network struct { type network struct {
s *Server s *Server
mac MAC mac MAC
portmap bool portmap bool
interfaceID int lanInterfaceID int
wanIP netip.Addr wanInterfaceID int
lanIP netip.Prefix // with host bits set (e.g. 192.168.2.1/24) wanIP netip.Addr
nodesByIP map[netip.Addr]*node lanIP netip.Prefix // with host bits set (e.g. 192.168.2.1/24)
logf func(format string, args ...any) nodesByIP map[netip.Addr]*node
logf func(format string, args ...any)
ns *stack.Stack ns *stack.Stack
linkEP *channel.Endpoint linkEP *channel.Endpoint
@ -646,15 +647,12 @@ func (s *Server) ServeUnixConn(uc *net.UnixConn, proto Protocol) {
if err := bw.Flush(); err != nil { if err := bw.Flush(); err != nil {
log.Printf("Flush: %v", err) log.Printf("Flush: %v", err)
} }
ci := gopacket.CaptureInfo{ must.Do(s.pcapWriter.WritePacket(gopacket.CaptureInfo{
Timestamp: time.Now(), Timestamp: time.Now(),
CaptureLength: len(pkt), CaptureLength: len(pkt),
Length: len(pkt), Length: len(pkt),
} InterfaceIndex: srcNode.interfaceID,
if srcNode != nil { }, pkt))
ci.InterfaceIndex = srcNode.interfaceID
}
must.Do(s.pcapWriter.WritePacket(ci, pkt))
} }
buf := make([]byte, 16<<10) buf := make([]byte, 16<<10)
@ -714,13 +712,12 @@ func (s *Server) ServeUnixConn(uc *net.UnixConn, proto Protocol) {
continue continue
} }
} }
ci := gopacket.CaptureInfo{ must.Do(s.pcapWriter.WritePacket(gopacket.CaptureInfo{
Timestamp: time.Now(), Timestamp: time.Now(),
CaptureLength: len(packetRaw), CaptureLength: len(packetRaw),
Length: len(packetRaw), Length: len(packetRaw),
InterfaceIndex: srcNode.interfaceID, InterfaceIndex: srcNode.interfaceID,
} }, packetRaw))
must.Do(s.pcapWriter.WritePacket(ci, packetRaw))
netw.HandleEthernetPacket(ep) netw.HandleEthernetPacket(ep)
} }
} }
@ -818,23 +815,34 @@ func (n *network) HandleEthernetPacket(ep EthernetPacket) {
// LAN IP here and wrapped in an ethernet layer and delivered // LAN IP here and wrapped in an ethernet layer and delivered
// to the network. // to the network.
func (n *network) HandleUDPPacket(p UDPPacket) { func (n *network) HandleUDPPacket(p UDPPacket) {
dst := n.doNATIn(p.Src, p.Dst) buf, err := n.serializedUDPPacket(p.Src, p.Dst, p.Payload, nil)
if !dst.IsValid() {
n.logf("Warning: NAT dropped packet; no mapping for %v=>%v", p.Src, p.Dst)
return
}
p.Dst = dst
buff, err := n.serializedUDPPacket(p.Src, p.Dst, p.Payload, nil)
if err != nil { if err != nil {
n.logf("serializing UDP packet: %v", err) n.logf("serializing UDP packet: %v", err)
return return
} }
n.s.pcapWriter.WritePacket(gopacket.CaptureInfo{ n.s.pcapWriter.WritePacket(gopacket.CaptureInfo{
Timestamp: time.Now(), Timestamp: time.Now(),
CaptureLength: len(buff), CaptureLength: len(buf),
Length: len(buff), Length: len(buf),
InterfaceIndex: n.interfaceID, InterfaceIndex: n.wanInterfaceID,
}, buff) }, buf)
dst := n.doNATIn(p.Src, p.Dst)
if !dst.IsValid() {
n.logf("Warning: NAT dropped packet; no mapping for %v=>%v", p.Src, p.Dst)
return
}
p.Dst = dst
buf, err = n.serializedUDPPacket(p.Src, p.Dst, p.Payload, nil)
if err != nil {
n.logf("serializing UDP packet: %v", err)
return
}
n.s.pcapWriter.WritePacket(gopacket.CaptureInfo{
Timestamp: time.Now(),
CaptureLength: len(buf),
Length: len(buf),
InterfaceIndex: n.lanInterfaceID,
}, buf)
n.WriteUDPPacketNoNAT(p) n.WriteUDPPacketNoNAT(p)
} }
@ -946,11 +954,6 @@ func (n *network) HandleEthernetIPv4PacketForRouter(ep EthernetPacket) {
if toForward && isUDP { if toForward && isUDP {
src := netip.AddrPortFrom(srcIP, uint16(udp.SrcPort)) src := netip.AddrPortFrom(srcIP, uint16(udp.SrcPort))
dst := netip.AddrPortFrom(dstIP, uint16(udp.DstPort)) dst := netip.AddrPortFrom(dstIP, uint16(udp.DstPort))
src0 := src
src = n.doNATOut(src, dst)
_ = src0
//log.Printf("XXX UDP out %v=>%v to %v", src0, src, dst)
buf, err := n.serializedUDPPacket(src, dst, udp.Payload, nil) buf, err := n.serializedUDPPacket(src, dst, udp.Payload, nil)
if err != nil { if err != nil {
n.logf("serializing UDP packet: %v", err) n.logf("serializing UDP packet: %v", err)
@ -960,7 +963,20 @@ func (n *network) HandleEthernetIPv4PacketForRouter(ep EthernetPacket) {
Timestamp: time.Now(), Timestamp: time.Now(),
CaptureLength: len(buf), CaptureLength: len(buf),
Length: len(buf), Length: len(buf),
InterfaceIndex: n.interfaceID, InterfaceIndex: n.lanInterfaceID,
}, buf)
src = n.doNATOut(src, dst)
buf, err = n.serializedUDPPacket(src, dst, udp.Payload, nil)
if err != nil {
n.logf("serializing UDP packet: %v", err)
return
}
n.s.pcapWriter.WritePacket(gopacket.CaptureInfo{
Timestamp: time.Now(),
CaptureLength: len(buf),
Length: len(buf),
InterfaceIndex: n.wanInterfaceID,
}, buf) }, buf)
n.s.routeUDPPacket(UDPPacket{ n.s.routeUDPPacket(UDPPacket{