@ -25,6 +25,8 @@ var (
linkLocalMulticastIPv4Range = netip . MustParsePrefix ( "224.0.0.0/24" )
linkLocalMulticastIPv6Range = netip . MustParsePrefix ( "ff02::/16" )
limitedBroadcast = netip . MustParsePrefix ( "255.255.255.255/32" )
)
type direction int
@ -233,26 +235,41 @@ func (f *Firewall) UpdatePermittedRoutes(newRoutes []netip.Prefix) error {
return err
}
name = "link-local multicast - " + r . String ( )
conditions = matchLinkLocalMulticast ( r , false )
multicastRules , err := f . addRules ( name , weightKnownTraffic , conditions , wf . ActionPermit , p , directionOutbound )
multicastRules , err := f . addLinkLocalMulticastRules ( p , r )
if err != nil {
return err
}
rules = append ( rules , multicastRules ... )
conditions = matchLinkLocalMulticast ( r , true )
multicastRules , err = f . addRules ( name , weightKnownTraffic , conditions , wf . ActionPermit , p , directionInbound )
broadcastRules , err := f . addLimitedBroadcastRules ( p , r )
if err != nil {
return err
}
rules = append ( rules , multi castRules... )
rules = append ( rules , broad castRules... )
f . permittedRoutes [ r ] = rules
}
return nil
}
// addLinkLocalMulticastRules adds rules to allow inbound and outbound
// link-local multicast traffic to or from the specified network.
// It returns the added rules, or an error.
func ( f * Firewall ) addLinkLocalMulticastRules ( p protocol , r netip . Prefix ) ( [ ] * wf . Rule , error ) {
name := "link-local multicast - " + r . String ( )
conditions := matchLinkLocalMulticast ( r , false )
outboundRules , err := f . addRules ( name , weightKnownTraffic , conditions , wf . ActionPermit , p , directionOutbound )
if err != nil {
return nil , err
}
conditions = matchLinkLocalMulticast ( r , true )
inboundRules , err := f . addRules ( name , weightKnownTraffic , conditions , wf . ActionPermit , p , directionInbound )
if err != nil {
return nil , err
}
return append ( outboundRules , inboundRules ... ) , nil
}
// matchLinkLocalMulticast returns a list of conditions that match
// outbound or inbound link-local multicast traffic to or from the
// specified network.
@ -288,6 +305,59 @@ func matchLinkLocalMulticast(pfx netip.Prefix, inbound bool) []*wf.Match {
}
}
// addLimitedBroadcastRules adds rules to allow inbound and outbound
// limited broadcast traffic to or from the specified network,
// if the network is IPv4. It returns the added rules, or an error.
func ( f * Firewall ) addLimitedBroadcastRules ( p protocol , r netip . Prefix ) ( [ ] * wf . Rule , error ) {
if ! r . Addr ( ) . Is4 ( ) {
return nil , nil
}
name := "broadcast - " + r . String ( )
conditions := matchLimitedBroadcast ( r , false )
outboundRules , err := f . addRules ( name , weightKnownTraffic , conditions , wf . ActionPermit , p , directionOutbound )
if err != nil {
return nil , err
}
conditions = matchLimitedBroadcast ( r , true )
inboundRules , err := f . addRules ( name , weightKnownTraffic , conditions , wf . ActionPermit , p , directionInbound )
if err != nil {
return nil , err
}
return append ( outboundRules , inboundRules ... ) , nil
}
// matchLimitedBroadcast returns a list of conditions that match
// outbound or inbound limited broadcast traffic to or from the
// specified network. It panics if the pfx is not IPv4.
func matchLimitedBroadcast ( pfx netip . Prefix , inbound bool ) [ ] * wf . Match {
if ! pfx . Addr ( ) . Is4 ( ) {
panic ( "limited broadcast is only applicable to IPv4" )
}
var localAddr , remoteAddr netip . Prefix
if inbound {
localAddr , remoteAddr = limitedBroadcast , pfx
} else {
localAddr , remoteAddr = pfx , limitedBroadcast
}
return [ ] * wf . Match {
{
Field : wf . FieldIPProtocol ,
Op : wf . MatchTypeEqual ,
Value : wf . IPProtoUDP ,
} ,
{
Field : wf . FieldIPLocalAddress ,
Op : wf . MatchTypeEqual ,
Value : localAddr ,
} ,
{
Field : wf . FieldIPRemoteAddress ,
Op : wf . MatchTypeEqual ,
Value : remoteAddr ,
} ,
}
}
func ( f * Firewall ) newRule ( name string , w weight , layer wf . LayerID , conditions [ ] * wf . Match , action wf . Action ) ( * wf . Rule , error ) {
id , err := windows . GenerateGUID ( )
if err != nil {