Keep rule extras off the DNAT implied accept, expand all/any DNAT sources and match SPORT
This commit is contained in:
@@ -467,19 +467,24 @@ func (c *Compiler) compileOneRule(state *FirewallState, tag, srcSpec, dstSpec, p
|
||||
dports, sports config.PortSpec, action config.RuleAction, logLevel string,
|
||||
dnatDest, origDest string, fwZone string, section config.RuleSection) error {
|
||||
|
||||
for _, src := range c.zoneSpecs(srcSpec) {
|
||||
isDNAT := action == config.RuleDNAT || action == config.RuleRedirect
|
||||
srcs := c.zoneSpecs(srcSpec)
|
||||
if isDNAT {
|
||||
srcs = c.dnatSourceSpecs(srcSpec, fwZone)
|
||||
}
|
||||
for _, src := range srcs {
|
||||
for _, srcAddr := range splitAddrs(src.Addr) {
|
||||
if action == config.RuleDNAT || action == config.RuleRedirect {
|
||||
if isDNAT {
|
||||
if dnatSkipsIntrazone(srcSpec, src.Zone, dstSpec) {
|
||||
continue
|
||||
}
|
||||
if err := c.compileDNATAccept(state, tag, src.Zone, srcAddr, dstSpec, proto, dports, sports, action, fwZone, section); err != nil {
|
||||
if err := c.compileDNATAccept(state, tag+":accept", src.Zone, srcAddr, dstSpec, proto, dports, sports, action, fwZone, section); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for _, od := range splitAddrs(origDest) {
|
||||
if action == config.RuleDNAT || action == config.RuleRedirect {
|
||||
if err := c.compileDNATRule(state, tag, src.Zone, srcAddr, od, dstSpec, proto, dports, action, logLevel); err != nil {
|
||||
if isDNAT {
|
||||
if err := c.compileDNATRule(state, tag, src.Zone, srcAddr, od, dstSpec, proto, dports, sports, action, logLevel); err != nil {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
@@ -503,12 +508,29 @@ func (c *Compiler) compileOneRule(state *FirewallState, tag, srcSpec, dstSpec, p
|
||||
return nil
|
||||
}
|
||||
|
||||
// dnatSkipsIntrazone mirrors shorewall: a zone list or all!x source never pairs a zone with itself unless marked "+".
|
||||
// dnatSourceSpecs hooks DNAT per source zone like shorewall: all/any expand to every zone but fw (prerouting never sees fw traffic).
|
||||
func (c *Compiler) dnatSourceSpecs(spec, fwZone string) []config.ZoneSpec {
|
||||
zone, addr := splitZoneSpec(spec)
|
||||
base, _, _ := strings.Cut(zone, "!")
|
||||
if base = strings.TrimSuffix(base, "+"); base != "all" && base != "any" {
|
||||
return c.zoneSpecs(spec)
|
||||
}
|
||||
var out []config.ZoneSpec
|
||||
for _, z := range c.expandZoneRef(zone) {
|
||||
if z != fwZone {
|
||||
out = append(out, config.ZoneSpec{Zone: z, Addr: addr})
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// dnatSkipsIntrazone mirrors shorewall: a zone list or all/any source never pairs a zone with itself unless marked "+".
|
||||
func dnatSkipsIntrazone(srcSpec, srcZone, dstSpec string) bool {
|
||||
zones, _, _ := strings.Cut(srcSpec, ":")
|
||||
wild := isZoneExclusion(srcSpec) || strings.Contains(zones, ",")
|
||||
base, _, _ := strings.Cut(zones, "!")
|
||||
wild := base == "all" || base == "any" || strings.Contains(base, ",")
|
||||
dstZone, _, _ := strings.Cut(dstSpec, ":")
|
||||
return wild && !strings.Contains(zones, "+!") && srcZone == dstZone
|
||||
return wild && srcZone == dstZone
|
||||
}
|
||||
|
||||
// compileDNATAccept emits the filter ACCEPT implied by DNAT/REDIRECT (shorewall's DNAT-/REDIRECT- omit it) for the translated flow.
|
||||
@@ -639,7 +661,7 @@ func (c *Compiler) compileZonePair(state *FirewallState, tag, srcZone, srcAddr,
|
||||
}
|
||||
|
||||
func (c *Compiler) compileDNATRule(state *FirewallState, tag, srcZone, srcAddr, origDest, dstSpec, proto string,
|
||||
dports config.PortSpec, action config.RuleAction, logLevel string) error {
|
||||
dports, sports config.PortSpec, action config.RuleAction, logLevel string) error {
|
||||
chain := "prerouting"
|
||||
|
||||
parts := strings.SplitN(dstSpec, ":", 3)
|
||||
@@ -667,7 +689,7 @@ func (c *Compiler) compileDNATRule(state *FirewallState, tag, srcZone, srcAddr,
|
||||
}
|
||||
}
|
||||
|
||||
matches, err := l4Matches(proto, dports, nil)
|
||||
matches, err := l4Matches(proto, dports, sports)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user