Honour hosts routeback for same-interface intra-zone pairs
This commit is contained in:
@@ -953,10 +953,10 @@ func (c *Compiler) compileImplicitIntraZone(state *FirewallState, overridden map
|
||||
return nil
|
||||
}
|
||||
|
||||
// intraZoneSkip drops intra-zone pairs on one interface (routeback's job) and pairs whose address
|
||||
// families can never both match.
|
||||
// intraZoneSkip drops intra-zone pairs on one interface unless both are routeback hosts entries
|
||||
// (interface routeback is compileIntraZone's job), and pairs whose address families can never both match.
|
||||
func intraZoneSkip(si, di zoneMatch) bool {
|
||||
if si.iface != "" && si.iface == di.iface {
|
||||
if si.iface != "" && si.iface == di.iface && !(si.routeback && di.routeback) {
|
||||
return true
|
||||
}
|
||||
a, b := matchFamily(si), matchFamily(di)
|
||||
@@ -1278,11 +1278,12 @@ func (c *Compiler) selectChain(srcZone, dstZone, fwZone string) string {
|
||||
// zoneMatch classifies a packet into a zone: an interface (empty: any) and, for a hosts entry, one host
|
||||
// address; excl carves out hosts exclusions and the hosts of sub-zones, which shorewall matches first.
|
||||
// fam (an NFPROTO; addr's family when set, else 0: any) guards addr and excl so IPv4 offsets are
|
||||
// never compared against IPv6 bytes.
|
||||
// never compared against IPv6 bytes. routeback marks a hosts entry with the routeback option.
|
||||
type zoneMatch struct {
|
||||
iface, addr string
|
||||
excl []string
|
||||
fam byte
|
||||
routeback bool
|
||||
}
|
||||
|
||||
// resolveZone returns nil (fail closed) for an unknown zone, or one with neither interfaces nor hosts
|
||||
@@ -1326,7 +1327,7 @@ func (c *Compiler) resolveZone(zone, addr string) []zoneMatch {
|
||||
v4, v6 := splitFamily(slices.Concat(h.Exclusions, sub))
|
||||
for _, a := range h.Addresses {
|
||||
if addrsOverlap(a, addr) {
|
||||
m := zoneMatch{iface: h.Interface, addr: a, excl: v6}
|
||||
m := zoneMatch{iface: h.Interface, addr: a, excl: v6, routeback: h.Options.RouteBack}
|
||||
if p, err := parsePrefix(a); err == nil && p.Addr().Is4() {
|
||||
m.excl = v4
|
||||
}
|
||||
|
||||
@@ -3637,3 +3637,29 @@ func TestCompile_HostsIntraZone(t *testing.T) {
|
||||
t.Errorf("lan lan policy = %q, want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompile_HostsRouteBack(t *testing.T) {
|
||||
sameIface := func(routeback bool) func(*config.Config) {
|
||||
return func(c *config.Config) {
|
||||
c.Hosts = []config.Host{
|
||||
{Zone: "lan", Interface: "wlo1", Addresses: []string{"192.0.2.0/24"}, Options: config.HostOptions{RouteBack: routeback}},
|
||||
{Zone: "lan", Interface: "wlo1", Addresses: []string{"198.51.100.0/24"}},
|
||||
}
|
||||
}
|
||||
}
|
||||
if got := describeTagged(mustCompile(t, hostsCfg(sameIface(false))), "forward", "intra:lan"); len(got) != 0 {
|
||||
t.Errorf("same-interface hosts without routeback = %q, want none", got)
|
||||
}
|
||||
want := []string{"iif=wlo1 ip4 saddr=192.0.2.0/24 oif=wlo1 ip4 daddr=192.0.2.0/24"}
|
||||
if got := describeTagged(mustCompile(t, hostsCfg(sameIface(true))), "forward", "intra:lan"); !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("routeback hosts intra = %q, want %q", got, want)
|
||||
}
|
||||
|
||||
state := mustCompile(t, hostsCfg(func(c *config.Config) {
|
||||
sameIface(true)(c)
|
||||
c.Policy = append([]config.Policy{{Source: "lan", Dest: "lan", Action: config.PolicyDrop}}, c.Policy...)
|
||||
}))
|
||||
if got := describeTagged(state, "forward", "policy:0"); !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("routeback hosts lan lan policy = %q, want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user