mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-25 19:15:34 +00:00
4d6a8224d5
When the desired netfilter mode was unset, we would always try to use the `iptables` binary. In such cases if iptables was not found, tailscaled would just crash as seen in #13440. To work around this, in those cases check if the `iptables` binary even exists and if it doesn't fall back to the nftables implementation. Verified that it works on stock Ubuntu 24.04. Updates #5621 Updates #8555 Updates #8762 Fixes #13440 Signed-off-by: Maisem Ali <maisem@tailscale.com>
74 lines
2.1 KiB
Go
74 lines
2.1 KiB
Go
// Copyright (c) Tailscale Inc & AUTHORS
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
// TODO(#8502): add support for more architectures
|
|
//go:build linux && (arm64 || amd64)
|
|
|
|
package linuxfw
|
|
|
|
import (
|
|
"fmt"
|
|
"os/exec"
|
|
"strings"
|
|
"unicode"
|
|
|
|
"tailscale.com/types/logger"
|
|
"tailscale.com/util/multierr"
|
|
)
|
|
|
|
// DebugNetfilter prints debug information about iptables rules to the
|
|
// provided log function.
|
|
func DebugIptables(logf logger.Logf) error {
|
|
// unused.
|
|
return nil
|
|
}
|
|
|
|
// detectIptables returns the number of iptables rules that are present in the
|
|
// system, ignoring the default "ACCEPT" rule present in the standard iptables
|
|
// chains.
|
|
//
|
|
// It only returns an error when there is no iptables binary, or when iptables -S
|
|
// fails. In all other cases, it returns the number of non-default rules.
|
|
//
|
|
// If the iptables binary is not found, it returns an underlying exec.ErrNotFound
|
|
// error.
|
|
func detectIptables() (int, error) {
|
|
// run "iptables -S" to get the list of rules using iptables
|
|
// exec.Command returns an error if the binary is not found
|
|
cmd := exec.Command("iptables", "-S")
|
|
output, err := cmd.Output()
|
|
ip6cmd := exec.Command("ip6tables", "-S")
|
|
ip6output, ip6err := ip6cmd.Output()
|
|
var allLines []string
|
|
outputStr := string(output)
|
|
lines := strings.Split(outputStr, "\n")
|
|
ip6outputStr := string(ip6output)
|
|
ip6lines := strings.Split(ip6outputStr, "\n")
|
|
switch {
|
|
case err == nil && ip6err == nil:
|
|
allLines = append(lines, ip6lines...)
|
|
case err == nil && ip6err != nil:
|
|
allLines = lines
|
|
case err != nil && ip6err == nil:
|
|
allLines = ip6lines
|
|
default:
|
|
return 0, FWModeNotSupportedError{
|
|
Mode: FirewallModeIPTables,
|
|
Err: fmt.Errorf("iptables command run fail: %w", multierr.New(err, ip6err)),
|
|
}
|
|
}
|
|
|
|
// count the number of non-default rules
|
|
count := 0
|
|
for _, line := range allLines {
|
|
trimmedLine := strings.TrimLeftFunc(line, unicode.IsSpace)
|
|
if line != "" && strings.HasPrefix(trimmedLine, "-A") {
|
|
// if the line is not empty and starts with "-A", it is a rule appended not default
|
|
count++
|
|
}
|
|
}
|
|
|
|
// return the count of non-default rules
|
|
return count, nil
|
|
}
|