From 634181ba66cb937cea12b2ba29273981459a8aa0 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Wed, 8 Oct 2025 17:02:36 +0100 Subject: [PATCH] Fix incorrect CIDR construction in hostmap (#1493) * Fix incorrect CIDR construction in hostmap * Introduce a regression test for incorrect hostmap CIDR --- firewall_test.go | 44 ++++++++++++++++++++++++++++++++++++++++++++ hostmap.go | 3 ++- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/firewall_test.go b/firewall_test.go index 49f4d73..02eaad9 100644 --- a/firewall_test.go +++ b/firewall_test.go @@ -692,6 +692,50 @@ func TestFirewall_DropConntrackReload(t *testing.T) { assert.Equal(t, fw.Drop(p, false, &h, cp, nil), ErrNoMatchingRule) } +func TestFirewall_DropIPSpoofing(t *testing.T) { + l := test.NewLogger() + ob := &bytes.Buffer{} + l.SetOutput(ob) + + c := cert.CachedCertificate{ + Certificate: &dummyCert{ + name: "host-owner", + networks: []netip.Prefix{netip.MustParsePrefix("192.0.2.1/24")}, + }, + } + + c1 := cert.CachedCertificate{ + Certificate: &dummyCert{ + name: "host", + networks: []netip.Prefix{netip.MustParsePrefix("192.0.2.2/24")}, + unsafeNetworks: []netip.Prefix{netip.MustParsePrefix("198.51.100.0/24")}, + }, + } + h1 := HostInfo{ + ConnectionState: &ConnectionState{ + peerCert: &c1, + }, + vpnAddrs: []netip.Addr{c1.Certificate.Networks()[0].Addr()}, + } + h1.buildNetworks(c1.Certificate.Networks(), c1.Certificate.UnsafeNetworks()) + + fw := NewFirewall(l, time.Second, time.Minute, time.Hour, c.Certificate) + + require.NoError(t, fw.AddRule(true, firewall.ProtoAny, 1, 1, []string{}, "", netip.Prefix{}, netip.Prefix{}, "", "")) + cp := cert.NewCAPool() + + // Packet spoofed by `c1`. Note that the remote addr is not a valid one. + p := firewall.Packet{ + LocalAddr: netip.MustParseAddr("192.0.2.1"), + RemoteAddr: netip.MustParseAddr("192.0.2.3"), + LocalPort: 1, + RemotePort: 1, + Protocol: firewall.ProtoUDP, + Fragment: false, + } + assert.Equal(t, fw.Drop(p, true, &h1, cp, nil), ErrInvalidRemoteIP) +} + func BenchmarkLookup(b *testing.B) { ml := func(m map[string]struct{}, a [][]string) { for n := 0; n < b.N; n++ { diff --git a/hostmap.go b/hostmap.go index cd2e696..66b4851 100644 --- a/hostmap.go +++ b/hostmap.go @@ -738,7 +738,8 @@ func (i *HostInfo) buildNetworks(networks, unsafeNetworks []netip.Prefix) { i.networks = new(bart.Lite) for _, network := range networks { - i.networks.Insert(network) + nprefix := netip.PrefixFrom(network.Addr(), network.Addr().BitLen()) + i.networks.Insert(nprefix) } for _, network := range unsafeNetworks {