Gate IPv6 forwarding on overlay v6 capability and preserve host RA acceptance

This commit is contained in:
Viktor Liu
2026-05-20 12:21:51 +02:00
parent af24fd7796
commit c46dee4e6b
10 changed files with 236 additions and 58 deletions

View File

@@ -89,7 +89,7 @@ func (m *Manager) createIPv6Components(wgIface iFaceMapper, mtu uint16) error {
}
// Share the same IP forwarding state with the v4 router, since
// EnableIPForwarding controls both v4 and v6 sysctls.
// Forwarding refcounter is per-family but shared between v4 and v6 routers.
m.router6.ipFwdState = m.router.ipFwdState
m.aclMgr6, err = newAclManager(ip6Client, wgIface)
@@ -402,15 +402,27 @@ func (m *Manager) SetLogLevel(log.Level) {
}
func (m *Manager) EnableRouting() error {
if err := m.router.ipFwdState.RequestForwarding(); err != nil {
return fmt.Errorf("enable IP forwarding: %w", err)
if err := m.router.ipFwdState.RequestForwarding(false); err != nil {
return fmt.Errorf("enable IPv4 forwarding: %w", err)
}
// Only flip v6 forwarding when the WG interface actually has v6, so that
// v4-only routing setups don't disable RA acceptance on the host.
if m.router6 != nil {
if err := m.router.ipFwdState.RequestForwarding(true); err != nil {
return fmt.Errorf("enable IPv6 forwarding: %w", err)
}
}
return nil
}
func (m *Manager) DisableRouting() error {
if err := m.router.ipFwdState.ReleaseForwarding(); err != nil {
return fmt.Errorf("disable IP forwarding: %w", err)
if err := m.router.ipFwdState.ReleaseForwarding(false); err != nil {
return fmt.Errorf("disable IPv4 forwarding: %w", err)
}
if m.router6 != nil {
if err := m.router.ipFwdState.ReleaseForwarding(true); err != nil {
return fmt.Errorf("disable IPv6 forwarding: %w", err)
}
}
return nil
}

View File

@@ -101,7 +101,7 @@ func newRouter(iptablesClient *iptables.IPTables, wgIface iFaceMapper, mtu uint1
wgIface: wgIface,
mtu: mtu,
v6: iptablesClient.Proto() == iptables.ProtocolIPv6,
ipFwdState: ipfwdstate.NewIPForwardingState(),
ipFwdState: ipfwdstate.NewIPForwardingState(wgIface.Name()),
}
r.ipsetCounter = refcounter.New(
@@ -763,7 +763,7 @@ func (r *router) updateState() {
}
func (r *router) AddDNATRule(rule firewall.ForwardRule) (firewall.Rule, error) {
if err := r.ipFwdState.RequestForwarding(); err != nil {
if err := r.ipFwdState.RequestForwarding(r.v6); err != nil {
return nil, err
}
@@ -861,7 +861,7 @@ func (r *router) rollbackRules(rules map[string]ruleInfo) error {
}
func (r *router) DeleteDNATRule(rule firewall.Rule) error {
if err := r.ipFwdState.ReleaseForwarding(); err != nil {
if err := r.ipFwdState.ReleaseForwarding(r.v6); err != nil {
log.Errorf("%v", err)
}

View File

@@ -105,8 +105,8 @@ func (m *Manager) createIPv6Components(tableName string, wgIface iFaceMapper, mt
return fmt.Errorf("create v6 router: %w", err)
}
// Share the same IP forwarding state with the v4 router, since
// EnableIPForwarding controls both v4 and v6 sysctls.
// Share the per-family forwarding refcounter with the v4 router so a v4
// rule and a v6 rule against the same state machine cooperate cleanly.
m.router6.ipFwdState = m.router.ipFwdState
m.aclManager6, err = newAclManager(workTable6, wgIface, chainNameRoutingFw)
@@ -530,15 +530,27 @@ func (m *Manager) SetLogLevel(log.Level) {
}
func (m *Manager) EnableRouting() error {
if err := m.router.ipFwdState.RequestForwarding(); err != nil {
return fmt.Errorf("enable IP forwarding: %w", err)
if err := m.router.ipFwdState.RequestForwarding(false); err != nil {
return fmt.Errorf("enable IPv4 forwarding: %w", err)
}
// Only flip v6 forwarding when the WG interface actually has v6, so that
// v4-only routing setups don't disable RA acceptance on the host.
if m.router6 != nil {
if err := m.router.ipFwdState.RequestForwarding(true); err != nil {
return fmt.Errorf("enable IPv6 forwarding: %w", err)
}
}
return nil
}
func (m *Manager) DisableRouting() error {
if err := m.router.ipFwdState.ReleaseForwarding(); err != nil {
return fmt.Errorf("disable IP forwarding: %w", err)
if err := m.router.ipFwdState.ReleaseForwarding(false); err != nil {
return fmt.Errorf("disable IPv4 forwarding: %w", err)
}
if m.router6 != nil {
if err := m.router.ipFwdState.ReleaseForwarding(true); err != nil {
return fmt.Errorf("disable IPv6 forwarding: %w", err)
}
}
return nil
}

View File

@@ -93,7 +93,7 @@ func newRouter(workTable *nftables.Table, wgIface iFaceMapper, mtu uint16) (*rou
rules: make(map[string]*nftables.Rule),
af: familyForAddr(workTable.Family == nftables.TableFamilyIPv4),
wgIface: wgIface,
ipFwdState: ipfwdstate.NewIPForwardingState(),
ipFwdState: ipfwdstate.NewIPForwardingState(wgIface.Name()),
mtu: mtu,
}
@@ -1550,7 +1550,7 @@ func (r *router) refreshRulesMap() error {
}
func (r *router) AddDNATRule(rule firewall.ForwardRule) (firewall.Rule, error) {
if err := r.ipFwdState.RequestForwarding(); err != nil {
if err := r.ipFwdState.RequestForwarding(r.af.tableFamily == nftables.TableFamilyIPv6); err != nil {
return nil, err
}
@@ -1778,7 +1778,7 @@ func (r *router) addDnatMasq(rule firewall.ForwardRule, protoNum uint8, ruleKey
}
func (r *router) DeleteDNATRule(rule firewall.Rule) error {
if err := r.ipFwdState.ReleaseForwarding(); err != nil {
if err := r.ipFwdState.ReleaseForwarding(r.af.tableFamily == nftables.TableFamilyIPv6); err != nil {
log.Errorf("%v", err)
}