Always use iptables -C to look for rules
iptables -C flag was introduced in v1.4.11, which was released ten years ago. Thus, there're no more Linux distributions supported by Docker using this version. As such, this commit removes the old way of checking if an iptables rule exists (by using substring matching). Signed-off-by: Albin Kerouanton <albinker@gmail.com>
This commit is contained in:
parent
205e5278c6
commit
799cc143c9
2 changed files with 7 additions and 82 deletions
|
@ -8,7 +8,6 @@ import (
|
|||
"fmt"
|
||||
"net"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
@ -56,7 +55,6 @@ var (
|
|||
iptablesPath string
|
||||
ip6tablesPath string
|
||||
supportsXlock = false
|
||||
supportsCOpt = false
|
||||
xLockWaitMsg = "Another app is currently holding the xtables lock"
|
||||
// used to lock iptables commands if xtables lock is not supported
|
||||
bestEffortLock sync.Mutex
|
||||
|
@ -96,19 +94,14 @@ func detectIptables() {
|
|||
}
|
||||
iptablesPath = path
|
||||
|
||||
// The --wait flag was added in iptables v1.6.0.
|
||||
// TODO remove this check once we drop support for CentOS/RHEL 7, which uses an older version of iptables
|
||||
if out, err := exec.Command(path, "--wait", "-L", "-n").CombinedOutput(); err != nil {
|
||||
logrus.WithError(err).Infof("unable to detect if iptables supports xlock: 'iptables --wait -L -n': `%s`", strings.TrimSpace(string(out)))
|
||||
} else {
|
||||
supportsXlock = true
|
||||
}
|
||||
|
||||
mj, mn, mc, err := GetVersion()
|
||||
if err != nil {
|
||||
logrus.Warnf("Failed to read iptables version: %v", err)
|
||||
} else {
|
||||
supportsCOpt = supportsCOption(mj, mn, mc)
|
||||
}
|
||||
|
||||
path, err = exec.LookPath("ip6tables")
|
||||
if err != nil {
|
||||
logrus.WithError(err).Warnf("unable to find ip6tables")
|
||||
|
@ -463,26 +456,9 @@ func (iptable IPTable) exists(native bool, table Table, chain string, rule ...st
|
|||
return false
|
||||
}
|
||||
|
||||
if supportsCOpt {
|
||||
// if exit status is 0 then return true, the rule exists
|
||||
_, err := f(append([]string{"-t", string(table), "-C", chain}, rule...)...)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// parse "iptables -S" for the rule (it checks rules in a specific chain
|
||||
// in a specific table and it is very unreliable)
|
||||
return iptable.existsRaw(table, chain, rule...)
|
||||
}
|
||||
|
||||
func (iptable IPTable) existsRaw(table Table, chain string, rule ...string) bool {
|
||||
path := iptablesPath
|
||||
if iptable.Version == IPv6 {
|
||||
path = ip6tablesPath
|
||||
}
|
||||
ruleString := fmt.Sprintf("%s %s\n", chain, strings.Join(rule, " "))
|
||||
existingRules, _ := exec.Command(path, "-t", string(table), "-S", chain).Output()
|
||||
|
||||
return strings.Contains(string(existingRules), ruleString)
|
||||
// if exit status is 0 then return true, the rule exists
|
||||
_, err := f(append([]string{"-t", string(table), "-C", chain}, rule...)...)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// Maximum duration that an iptables operation can take
|
||||
|
@ -580,15 +556,6 @@ func (iptable IPTable) ExistChain(chain string, table Table) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// GetVersion reads the iptables version numbers during initialization
|
||||
func GetVersion() (major, minor, micro int, err error) {
|
||||
out, err := exec.Command(iptablesPath, "--version").CombinedOutput()
|
||||
if err == nil {
|
||||
major, minor, micro = parseVersionNumbers(string(out))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// SetDefaultPolicy sets the passed default policy for the table/chain
|
||||
func (iptable IPTable) SetDefaultPolicy(table Table, chain string, policy Policy) error {
|
||||
if err := iptable.RawCombinedOutput("-t", string(table), "-P", chain, string(policy)); err != nil {
|
||||
|
@ -597,19 +564,6 @@ func (iptable IPTable) SetDefaultPolicy(table Table, chain string, policy Policy
|
|||
return nil
|
||||
}
|
||||
|
||||
func parseVersionNumbers(input string) (major, minor, micro int) {
|
||||
re := regexp.MustCompile(`v\d*.\d*.\d*`)
|
||||
line := re.FindString(input)
|
||||
fmt.Sscanf(line, "v%d.%d.%d", &major, &minor, µ)
|
||||
return
|
||||
}
|
||||
|
||||
// iptables -C, --check option was added in v.1.4.11
|
||||
// http://ftp.netfilter.org/pub/iptables/changes-iptables-1.4.11.txt
|
||||
func supportsCOption(mj, mn, mc int) bool {
|
||||
return mj > 1 || (mj == 1 && (mn > 4 || (mn == 4 && mc >= 11)))
|
||||
}
|
||||
|
||||
// AddReturnRule adds a return rule for the chain in the filter table
|
||||
func (iptable IPTable) AddReturnRule(chain string) error {
|
||||
var (
|
||||
|
|
|
@ -284,44 +284,15 @@ func TestExistsRaw(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("i=%d, err: %v", i, err)
|
||||
}
|
||||
if !iptable.existsRaw(Filter, testChain1, r.rule...) {
|
||||
if !iptable.exists(true, Filter, testChain1, r.rule...) {
|
||||
t.Fatalf("Failed to detect rule. i=%d", i)
|
||||
}
|
||||
// Truncate the rule
|
||||
trg := r.rule[len(r.rule)-1]
|
||||
trg = trg[:len(trg)-2]
|
||||
r.rule[len(r.rule)-1] = trg
|
||||
if iptable.existsRaw(Filter, testChain1, r.rule...) {
|
||||
if iptable.exists(true, Filter, testChain1, r.rule...) {
|
||||
t.Fatalf("Invalid detection. i=%d", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetVersion(t *testing.T) {
|
||||
mj, mn, mc := parseVersionNumbers("iptables v1.4.19.1-alpha")
|
||||
if mj != 1 || mn != 4 || mc != 19 {
|
||||
t.Fatal("Failed to parse version numbers")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSupportsCOption(t *testing.T) {
|
||||
input := []struct {
|
||||
mj int
|
||||
mn int
|
||||
mc int
|
||||
ok bool
|
||||
}{
|
||||
{1, 4, 11, true},
|
||||
{1, 4, 12, true},
|
||||
{1, 5, 0, true},
|
||||
{0, 4, 11, false},
|
||||
{0, 5, 12, false},
|
||||
{1, 3, 12, false},
|
||||
{1, 4, 10, false},
|
||||
}
|
||||
for ind, inp := range input {
|
||||
if inp.ok != supportsCOption(inp.mj, inp.mn, inp.mc) {
|
||||
t.Fatalf("Incorrect check: %d", ind)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue