Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 29 additions & 12 deletions client/firewall/iptables/acl_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ type aclManager struct {
entries aclEntries
optionalEntries map[string][]entry
ipsetStore *ipsetStore
ipsetSupported bool
Comment thread
coderabbitai[bot] marked this conversation as resolved.

stateManager *statemanager.Manager
}
Expand All @@ -51,6 +52,7 @@ func newAclManager(iptablesClient *iptables.IPTables, wgIface iFaceMapper) (*acl
entries: make(map[string][][]string),
optionalEntries: make(map[string][]entry),
ipsetStore: newIpsetStore(),
ipsetSupported: true,
}, nil
}

Expand Down Expand Up @@ -84,6 +86,12 @@ func (m *aclManager) AddPeerFiltering(
) ([]firewall.Rule, error) {
chain := chainNameInputRules

// If ipset is not supported on this system (e.g. missing ip_set kernel module),
// clear the ipset name so rules fall back to individual IP matching (-s ip).
if !m.ipsetSupported {
ipsetName = ""
}

ipsetName = transformIPsetName(ipsetName, sPort, dPort, action)
specs := filterRuleSpecs(ip, string(protocol), sPort, dPort, action, ipsetName)

Expand Down Expand Up @@ -113,21 +121,30 @@ func (m *aclManager) AddPeerFiltering(
}

if err := m.flushIPSet(ipsetName); err != nil {
if errors.Is(err, ipset.ErrSetNotExist) {
log.Debugf("flush ipset %s before use: %v", ipsetName, err)
} else {
log.Errorf("flush ipset %s before use: %v", ipsetName, err)
}
log.Debugf("flush ipset %s before use: %v", ipsetName, err)
}
if err := m.createIPSet(ipsetName); err != nil {
return nil, fmt.Errorf("create ipset: %w", err)
}
if err := m.addToIPSet(ipsetName, ip); err != nil {
return nil, fmt.Errorf("add IP to ipset: %w", err)
}
log.Warnf("ipset not supported, falling back to individual IP rules: %v", err)
m.ipsetSupported = false
ipsetName = ""

// Regenerate specs without ipset
specs = filterRuleSpecs(ip, string(protocol), sPort, dPort, action, "")
mangleSpecs = slices.Clone(specs)
mangleSpecs = append(mangleSpecs,
"-i", m.wgIface.Name(),
"-m", "addrtype", "--dst-type", "LOCAL",
"-j", "MARK", "--set-xmark", fmt.Sprintf("%#x", nbnet.PreroutingFwmarkRedirected),
)
specs = append(specs, "-j", actionToStr(action))
} else {
if err := m.addToIPSet(ipsetName, ip); err != nil {
return nil, fmt.Errorf("add IP to ipset: %w", err)
}

ipList := newIpList(ip.String())
m.ipsetStore.addIpList(ipsetName, ipList)
ipList := newIpList(ip.String())
m.ipsetStore.addIpList(ipsetName, ipList)
}
}

ok, err := m.iptablesClient.Exists(tableFilter, chain, specs...)
Expand Down