diff --git a/wgengine/filter/filter.go b/wgengine/filter/filter.go index 4cb509b28..8821bcbbf 100644 --- a/wgengine/filter/filter.go +++ b/wgengine/filter/filter.go @@ -367,6 +367,11 @@ func (f *Filter) pre(q *packet.ParsedPacket, rf RunFlags, dir direction) Respons f.logRateLimit(rf, q, dir, Drop, "ipv6") return Drop } + if q.DstIP.IsMulticast() { + f.logRateLimit(rf, q, dir, Drop, "multicast") + return Drop + } + switch q.IPProto { case packet.Unknown: // Unknown packets are dangerous; always drop them. @@ -409,6 +414,9 @@ func omitDropLogging(p *packet.ParsedPacket, dir direction) bool { if ipProto == packet.IGMP { return true } + if p.DstIP.IsMulticast() { + return true + } case 6: if len(b) < 40 { return false diff --git a/wgengine/filter/filter_test.go b/wgengine/filter/filter_test.go index ce1e46cac..dfab282b2 100644 --- a/wgengine/filter/filter_test.go +++ b/wgengine/filter/filter_test.go @@ -379,6 +379,18 @@ func TestOmitDropLogging(t *testing.T) { dir: out, want: true, }, + { + name: "v6_multicast_out_low", + pkt: &packet.ParsedPacket{IPVersion: 4, DstIP: packet.NewIP(net.ParseIP("224.0.0.0"))}, + dir: out, + want: true, + }, + { + name: "v6_multicast_out_high", + pkt: &packet.ParsedPacket{IPVersion: 4, DstIP: packet.NewIP(net.ParseIP("239.255.255.255"))}, + dir: out, + want: true, + }, } for _, tt := range tests { diff --git a/wgengine/packet/ip.go b/wgengine/packet/ip.go index 5620f4531..7ab3c90e8 100644 --- a/wgengine/packet/ip.go +++ b/wgengine/packet/ip.go @@ -39,6 +39,10 @@ func (ip IP) String() string { return fmt.Sprintf("%d.%d.%d.%d", byte(ip>>24), byte(ip>>16), byte(ip>>8), byte(ip)) } +func (ip IP) IsMulticast() bool { + return byte(ip>>24)&0xf0 == 0xe0 +} + // IPProto is either a real IP protocol (ITCP, UDP, ...) or an special value like Unknown. // If it is a real IP protocol, its value corresponds to its IP protocol number. type IPProto uint8