tstest/natlab: add dual stack with blackholed IPv4

This reproduces the bug report from
https://github.com/tailscale/tailscale/issues/13346

It does not yet fix it.

Updates #13346

Change-Id: Ia5af7b0481a64a37efe259c798facdda6d9da618
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick
2024-09-03 15:00:18 -07:00
committed by Brad Fitzpatrick
parent aeb15dea30
commit c4d0237e5c
3 changed files with 49 additions and 3 deletions

View File

@@ -272,9 +272,10 @@ type Network struct {
wanIP6 netip.Prefix // global unicast router in host bits; CIDR is /64 delegated to LAN
wanIP4 netip.Addr // IPv4 WAN IP, if any
lanIP4 netip.Prefix
nodes []*Node
wanIP4 netip.Addr // IPv4 WAN IP, if any
lanIP4 netip.Prefix
nodes []*Node
breakWAN4 bool // whether to break WAN IPv4 connectivity
svcs set.Set[NetworkService]
@@ -282,6 +283,12 @@ type Network struct {
err error // carried error
}
// SetBlackholedIPv4 sets whether the network should blackhole all IPv4 traffic
// out to the Internet. (DHCP etc continues to work on the LAN.)
func (n *Network) SetBlackholedIPv4(v bool) {
n.breakWAN4 = v
}
func (n *Network) CanV4() bool {
return n.lanIP4.IsValid() || n.wanIP4.IsValid()
}
@@ -353,6 +360,7 @@ func (s *Server) initFromConfig(c *Config) error {
v6: conf.wanIP6.IsValid(),
wanIP4: conf.wanIP4,
lanIP4: conf.lanIP4,
breakWAN4: conf.breakWAN4,
nodesByIP4: map[netip.Addr]*node{},
nodesByMAC: map[MAC]*node{},
logf: logger.WithPrefix(s.logf, fmt.Sprintf("[net-%v] ", conf.mac)),

View File

@@ -514,6 +514,7 @@ type network struct {
wanIP6 netip.Prefix // router's WAN IPv6, if any, as a /64.
wanIP4 netip.Addr // router's LAN IPv4, if any
lanIP4 netip.Prefix // router's LAN IP + CIDR (e.g. 192.168.2.1/24)
breakWAN4 bool // break WAN IPv4 connectivity
nodesByIP4 map[netip.Addr]*node // by LAN IPv4
nodesByMAC map[MAC]*node
logf func(format string, args ...any)
@@ -1104,6 +1105,10 @@ func (n *network) HandleUDPPacket(p UDPPacket) {
Length: len(buf),
InterfaceIndex: n.wanInterfaceID,
}, buf)
if p.Dst.Addr().Is4() && n.breakWAN4 {
// Blackhole the packet.
return
}
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)
@@ -1239,6 +1244,10 @@ func (n *network) HandleEthernetPacketForRouter(ep EthernetPacket) {
}
if toForward && n.s.shouldInterceptTCP(packet) {
if flow.dst.Is4() && n.breakWAN4 {
// Blackhole the packet.
return
}
var base *layers.BaseLayer
proto := header.IPv4ProtocolNumber
if v4, ok := packet.Layer(layers.LayerTypeIPv4).(*layers.IPv4); ok {
@@ -1324,6 +1333,10 @@ func (n *network) handleUDPPacketForRouter(ep EthernetPacket, udp *layers.UDP, t
}
if toForward {
if dstIP.Is4() && n.breakWAN4 {
// Blackhole the packet.
return
}
src := netip.AddrPortFrom(srcIP, uint16(udp.SrcPort))
dst := netip.AddrPortFrom(dstIP, uint16(udp.DstPort))
buf, err := n.serializedUDPPacket(src, dst, udp.Payload, nil)