feat: add idempotent route checks and container network routes
continuous-integration/drone/push Build is passing

- Make AddRouteInContainer idempotent by checking existing routes and handling "File exists" errors
- Add loop in firewall reconciler to add routes for containers to reach other networks
- Update iptables checks to include port for better rule distinction
This commit is contained in:
gyurix
2026-06-16 09:42:47 +02:00
parent 903bc1a7da
commit 77f80dea1b
3 changed files with 52 additions and 6 deletions
+10 -5
View File
@@ -282,7 +282,8 @@ func (m *Manager) InsertPreroutingRuleOnInterface(iface, proto, sourcePort, targ
iface, proto, sourcePort, targetIP, targetPort, comment)
// Check if rule already exists (idempotent: don't re-apply)
existing := m.getLineNumbers("PREROUTING", "nat", comment, "DNAT", targetIP)
// Must include port in check to distinguish port 80 from port 443 rules with same comment
existing := m.getLineNumbers("PREROUTING", "nat", comment, "DNAT", targetIP, targetPort)
if len(existing) > 0 {
logger.Debug("IPTABLES: PREROUTING DNAT rule already exists on %s (lines=%v), skipping", iface, existing)
return nil
@@ -307,7 +308,8 @@ func (m *Manager) InsertPostroutingMasquerade(destCIDR, proto, destPort, comment
destCIDR, proto, destPort, comment)
// Check if rule already exists (idempotent: don't re-apply)
existing := m.getLineNumbers("POSTROUTING", "nat", comment, "MASQUERADE", destCIDR)
// Must include port in check to distinguish port 80 from port 443 rules with same comment
existing := m.getLineNumbers("POSTROUTING", "nat", comment, "MASQUERADE", destCIDR, destPort)
if len(existing) > 0 {
logger.Debug("IPTABLES: POSTROUTING MASQUERADE rule already exists (lines=%v), skipping", existing)
return nil
@@ -332,7 +334,8 @@ func (m *Manager) InsertPostroutingMasqueradeForTarget(targetCIDR, proto, target
targetCIDR, proto, targetPort, comment)
// Idempotent: check if rule already exists
existing := m.getLineNumbers("POSTROUTING", "nat", comment, "MASQUERADE", targetCIDR)
// Must include port in check to distinguish port 80 from port 443 rules with same comment
existing := m.getLineNumbers("POSTROUTING", "nat", comment, "MASQUERADE", targetCIDR, targetPort)
if len(existing) > 0 {
logger.Debug("IPTABLES: POSTROUTING MASQUERADE for target already exists (lines=%v), skipping", existing)
return nil
@@ -484,17 +487,19 @@ func (m *Manager) InsertPostroutingMasqueradeInContainer(pid int, destCIDR, prot
}
// Idempotent check: scan existing rules for matching patterns
// Must include port to distinguish port 80 from port 443 rules with same comment
ruleExists := false
for _, line := range strings.Split(output, "\n") {
if strings.Contains(line, "MASQUERADE") &&
strings.Contains(line, comment) &&
strings.Contains(line, destCIDR) {
strings.Contains(line, destCIDR) &&
strings.Contains(line, destPort) {
ruleExists = true
break
}
}
if ruleExists {
logger.Info("IPTABLES: POSTROUTING MASQUERADE rule already exists in container PID %d (dst=%s), skipping", pid, destCIDR)
logger.Info("IPTABLES: POSTROUTING MASQUERADE rule already exists in container PID %d (dst=%s dport=%s), skipping", pid, destCIDR, destPort)
return nil
}