mirror of
https://github.com/tailscale/tailscale.git
synced 2025-08-11 21:27:31 +00:00
util/linuxfw,go.{mod,sum}: don't log errors when deleting non-existant chains and rules (#11852)
This PR bumps iptables to a newer version that has a function to detect 'NotExists' errors and uses that function to determine whether errors received on iptables rule and chain clean up are because the rule/chain does not exist- if so don't log the error. Updates corp#19336 Signed-off-by: Irbe Krumina <irbe@tailscale.com>
This commit is contained in:
@@ -7,6 +7,7 @@ package linuxfw
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/netip"
|
||||
"os"
|
||||
@@ -20,6 +21,14 @@ import (
|
||||
"tailscale.com/util/multierr"
|
||||
)
|
||||
|
||||
// isNotExistError needs to be overridden in tests that rely on distinguishing
|
||||
// this error, because we don't have a good way how to create a new
|
||||
// iptables.Error of that type.
|
||||
var isNotExistError = func(err error) bool {
|
||||
var e *iptables.Error
|
||||
return errors.As(err, &e) && e.IsNotExist()
|
||||
}
|
||||
|
||||
type iptablesInterface interface {
|
||||
// Adding this interface for testing purposes so we can mock out
|
||||
// the iptables library, in reality this is a wrapper to *iptables.IPTables.
|
||||
@@ -156,10 +165,6 @@ func (i *iptablesRunner) HasIPV6NAT() bool {
|
||||
return i.v6NATAvailable
|
||||
}
|
||||
|
||||
func isErrChainNotExist(err error) bool {
|
||||
return errCode(err) == 1
|
||||
}
|
||||
|
||||
// getIPTByAddr returns the iptablesInterface with correct IP family
|
||||
// that we will be using for the given address.
|
||||
func (i *iptablesRunner) getIPTByAddr(addr netip.Addr) iptablesInterface {
|
||||
@@ -261,7 +266,7 @@ func (i *iptablesRunner) AddChains() error {
|
||||
// If the chain already exists, it is a no-op.
|
||||
create := func(ipt iptablesInterface, table, chain string) error {
|
||||
err := ipt.ClearChain(table, chain)
|
||||
if isErrChainNotExist(err) {
|
||||
if isNotExistError(err) {
|
||||
// nonexistent chain. let's create it!
|
||||
return ipt.NewChain(table, chain)
|
||||
}
|
||||
@@ -377,7 +382,7 @@ func (i *iptablesRunner) DNATNonTailscaleTraffic(tun string, dst netip.Addr) err
|
||||
// originDst to the backend dsts. Traffic will be load balanced using round robin.
|
||||
func (i *iptablesRunner) DNATWithLoadBalancer(origDst netip.Addr, dsts []netip.Addr) error {
|
||||
table := i.getIPTByAddr(dsts[0])
|
||||
if err := table.ClearChain("nat", "PREROUTING"); err != nil && !isErrChainNotExist(err) {
|
||||
if err := table.ClearChain("nat", "PREROUTING"); err != nil && !isNotExistError(err) {
|
||||
// If clearing the PREROUTING chain fails, fail the whole operation. This
|
||||
// rule is currently only used in Kubernetes containers where a
|
||||
// failed container gets restarted which should hopefully fix things.
|
||||
@@ -454,7 +459,7 @@ func (i *iptablesRunner) DelChains() error {
|
||||
func (i *iptablesRunner) DelBase() error {
|
||||
del := func(ipt iptablesInterface, table, chain string) error {
|
||||
if err := ipt.ClearChain(table, chain); err != nil {
|
||||
if isErrChainNotExist(err) {
|
||||
if isNotExistError(err) {
|
||||
// nonexistent chain. That's fine, since it's
|
||||
// the desired state anyway.
|
||||
return nil
|
||||
@@ -602,14 +607,8 @@ func IPTablesCleanUp(logf logger.Logf) {
|
||||
func delTSHook(ipt iptablesInterface, table, chain string, logf logger.Logf) error {
|
||||
tsChain := tsChain(chain)
|
||||
args := []string{"-j", tsChain}
|
||||
if err := ipt.Delete(table, chain, args...); err != nil {
|
||||
// TODO(apenwarr): check for errCode(1) here.
|
||||
// Unfortunately the error code from the iptables
|
||||
// module resists unwrapping, unlike with other
|
||||
// calls. So we have to assume if Delete fails,
|
||||
// it's because there is no such rule.
|
||||
logf("deleting %v in %s/%s: %v", args, table, chain, err)
|
||||
return nil
|
||||
if err := ipt.Delete(table, chain, args...); err != nil && !isNotExistError(err) {
|
||||
return fmt.Errorf("deleting %v in %s/%s: %v", args, table, chain, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -618,7 +617,7 @@ func delTSHook(ipt iptablesInterface, table, chain string, logf logger.Logf) err
|
||||
// since the desired state is already achieved. otherwise, it returns an error.
|
||||
func delChain(ipt iptablesInterface, table, chain string) error {
|
||||
if err := ipt.ClearChain(table, chain); err != nil {
|
||||
if isErrChainNotExist(err) {
|
||||
if isNotExistError(err) {
|
||||
// nonexistent chain. nothing to do.
|
||||
return nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user