mirror of
https://github.com/kubernetes/kubernetes.git
synced 2026-08-08 06:00:48 +00:00
Merge pull request #139247 from danwinship/utiliptables-cleanup
remove old workarounds in utiliptables
This commit is contained in:
@@ -307,12 +307,6 @@ func NewProxier(ctx context.Context,
|
||||
go ipt.Monitor(kubeProxyCanaryChain, []utiliptables.Table{utiliptables.TableMangle, utiliptables.TableNAT, utiliptables.TableFilter},
|
||||
proxier.forceSyncProxyRules, syncPeriod, wait.NeverStop)
|
||||
|
||||
if ipt.HasRandomFully() {
|
||||
logger.V(2).Info("Iptables supports --random-fully")
|
||||
} else {
|
||||
logger.V(2).Info("Iptables does not support --random-fully")
|
||||
}
|
||||
|
||||
return proxier, nil
|
||||
}
|
||||
|
||||
@@ -754,15 +748,12 @@ func (proxier *Proxier) syncProxyRules() (retryError error) {
|
||||
"-A", string(kubePostroutingChain),
|
||||
"-j", "MARK", "--xor-mark", proxier.masqueradeMark,
|
||||
)
|
||||
masqRule := []string{
|
||||
proxier.natRules.Write(
|
||||
"-A", string(kubePostroutingChain),
|
||||
"-m", "comment", "--comment", `"kubernetes service traffic requiring SNAT"`,
|
||||
"-j", "MASQUERADE",
|
||||
}
|
||||
if proxier.iptables.HasRandomFully() {
|
||||
masqRule = append(masqRule, "--random-fully")
|
||||
}
|
||||
proxier.natRules.Write(masqRule)
|
||||
"--random-fully",
|
||||
)
|
||||
|
||||
// Install the kubernetes-specific masquerade mark rule. We use a whole chain for
|
||||
// this so that it is easier to flush and change, for example if the mark
|
||||
|
||||
@@ -204,7 +204,7 @@ func TestParseIPTablesData(t *testing.T) {
|
||||
:KUBE-SEP-SXIVWICOYRO3J4NJ - [0:0]
|
||||
-A KUBE-POSTROUTING -m mark ! --mark 0x4000/0x4000 -j RETURN
|
||||
-A KUBE-POSTROUTING -j MARK --xor-mark 0x4000
|
||||
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE
|
||||
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE --random-fully
|
||||
-A KUBE-MARK-MASQ -j MARK --or-mark 0x4000
|
||||
-A KUBE-SERVICES -m comment --comment "ns1/svc1:p80 cluster IP" -m tcp -p tcp -d 10.20.30.41 --dport 80 -j KUBE-SVC-XPGD46QRK7WJZT7O
|
||||
-A KUBE-SVC-XPGD46QRK7WJZT7O -m comment --comment "ns1/svc1:p80 cluster IP" -m tcp -p tcp -d 10.20.30.41 --dport 80 ! -s 10.0.0.0/24 -j KUBE-MARK-MASQ
|
||||
@@ -237,7 +237,7 @@ func TestParseIPTablesData(t *testing.T) {
|
||||
`:KUBE-SEP-SXIVWICOYRO3J4NJ - [0:0]`,
|
||||
`-A KUBE-POSTROUTING -m mark ! --mark 0x4000/0x4000 -j RETURN`,
|
||||
`-A KUBE-POSTROUTING -j MARK --xor-mark 0x4000`,
|
||||
`-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE`,
|
||||
`-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE --random-fully`,
|
||||
`-A KUBE-MARK-MASQ -j MARK --or-mark 0x4000`,
|
||||
`-A KUBE-SERVICES -m comment --comment "ns1/svc1:p80 cluster IP" -m tcp -p tcp -d 10.20.30.41 --dport 80 -j KUBE-SVC-XPGD46QRK7WJZT7O`,
|
||||
`-A KUBE-SVC-XPGD46QRK7WJZT7O -m comment --comment "ns1/svc1:p80 cluster IP" -m tcp -p tcp -d 10.20.30.41 --dport 80 ! -s 10.0.0.0/24 -j KUBE-MARK-MASQ`,
|
||||
@@ -780,7 +780,7 @@ func TestSortIPTablesRules(t *testing.T) {
|
||||
:KUBE-SEP-C6EBXVWJJZMIWKLZ - [0:0]
|
||||
-A KUBE-POSTROUTING -m mark ! --mark 0x4000/0x4000 -j RETURN
|
||||
-A KUBE-POSTROUTING -j MARK --xor-mark 0x4000
|
||||
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE
|
||||
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE --random-fully
|
||||
-A KUBE-MARK-MASQ -j MARK --or-mark 0x4000
|
||||
-A KUBE-SERVICES -m comment --comment "ns1/svc1:p80 cluster IP" -m tcp -p tcp -d 172.30.0.41 --dport 80 -j KUBE-SVC-XPGD46QRK7WJZT7O
|
||||
-A KUBE-SVC-XPGD46QRK7WJZT7O -m comment --comment "ns1/svc1:p80 cluster IP" -m tcp -p tcp -d 172.30.0.41 --dport 80 ! -s 10.0.0.0/8 -j KUBE-MARK-MASQ
|
||||
@@ -876,7 +876,7 @@ func TestSortIPTablesRules(t *testing.T) {
|
||||
-A KUBE-MARK-MASQ -j MARK --or-mark 0x4000
|
||||
-A KUBE-POSTROUTING -m mark ! --mark 0x4000/0x4000 -j RETURN
|
||||
-A KUBE-POSTROUTING -j MARK --xor-mark 0x4000
|
||||
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE
|
||||
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE --random-fully
|
||||
-A KUBE-SEP-C6EBXVWJJZMIWKLZ -m comment --comment ns4/svc4:p80 -s 10.180.0.5 -j KUBE-MARK-MASQ
|
||||
-A KUBE-SEP-C6EBXVWJJZMIWKLZ -m comment --comment ns4/svc4:p80 -m tcp -p tcp -j DNAT --to-destination 10.180.0.5:80
|
||||
-A KUBE-SEP-OYPFS5VJICHGATKP -m comment --comment ns3/svc3:p80 -s 10.180.0.3 -j KUBE-MARK-MASQ
|
||||
@@ -1427,7 +1427,7 @@ func TestTracePacket(t *testing.T) {
|
||||
-A POSTROUTING -m comment --comment kubernetes postrouting rules -j KUBE-POSTROUTING
|
||||
-A KUBE-POSTROUTING -m mark ! --mark 0x4000/0x4000 -j RETURN
|
||||
-A KUBE-POSTROUTING -j MARK --xor-mark 0x4000
|
||||
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE
|
||||
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE --random-fully
|
||||
-A KUBE-MARK-MASQ -j MARK --or-mark 0x4000
|
||||
-A KUBE-NODEPORTS -m comment --comment ns2/svc2:p80 -m tcp -p tcp --dport 3001 -j KUBE-EXT-GNZBNJ2PO5MGZ6GT
|
||||
-A KUBE-NODEPORTS -m comment --comment ns3/svc3:p80 -m tcp -p tcp --dport 3003 -j KUBE-EXT-X27LE4BHSL4DOUIK
|
||||
@@ -1775,7 +1775,7 @@ func TestOverallIPTablesRules(t *testing.T) {
|
||||
-A KUBE-MARK-MASQ -j MARK --or-mark 0x4000
|
||||
-A KUBE-POSTROUTING -m mark ! --mark 0x4000/0x4000 -j RETURN
|
||||
-A KUBE-POSTROUTING -j MARK --xor-mark 0x4000
|
||||
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE
|
||||
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE --random-fully
|
||||
-A KUBE-SEP-C6EBXVWJJZMIWKLZ -m comment --comment ns4/svc4:p80 -s 10.180.0.5 -j KUBE-MARK-MASQ
|
||||
-A KUBE-SEP-C6EBXVWJJZMIWKLZ -m comment --comment ns4/svc4:p80 -m tcp -p tcp -j DNAT --to-destination 10.180.0.5:80
|
||||
-A KUBE-SEP-I77PXRDZVX7PMWMN -m comment --comment ns5/svc5:p80 -s 10.180.0.3 -j KUBE-MARK-MASQ
|
||||
@@ -2595,29 +2595,6 @@ func TestDropInvalidRule(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestMasqueradeRule(t *testing.T) {
|
||||
for _, randomFully := range []bool{false, true} {
|
||||
t.Run(fmt.Sprintf("randomFully %t", randomFully), func(t *testing.T) {
|
||||
ipt := iptablestest.NewFake().SetHasRandomFully(randomFully)
|
||||
fp := NewFakeProxier(ipt)
|
||||
fp.syncProxyRules()
|
||||
|
||||
expectedFmt := dedent.Dedent(`
|
||||
-A KUBE-POSTROUTING -m mark ! --mark 0x4000/0x4000 -j RETURN
|
||||
-A KUBE-POSTROUTING -j MARK --xor-mark 0x4000
|
||||
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE%s
|
||||
`)
|
||||
var expected string
|
||||
if randomFully {
|
||||
expected = fmt.Sprintf(expectedFmt, " --random-fully")
|
||||
} else {
|
||||
expected = fmt.Sprintf(expectedFmt, "")
|
||||
}
|
||||
assertIPTablesChainEqual(t, getLine(), utiliptables.TableNAT, kubePostroutingChain, expected, fp.iptablesData.String())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestExternalTrafficPolicyLocal tests that traffic to externally-facing IPs does not get
|
||||
// masqueraded when using Local traffic policy. For traffic from external sources, that
|
||||
// means it can also only be routed to local endpoints, but for traffic from internal
|
||||
@@ -5823,7 +5800,7 @@ func TestSyncProxyRulesRepeated(t *testing.T) {
|
||||
-A KUBE-MARK-MASQ -j MARK --or-mark 0x4000
|
||||
-A KUBE-POSTROUTING -m mark ! --mark 0x4000/0x4000 -j RETURN
|
||||
-A KUBE-POSTROUTING -j MARK --xor-mark 0x4000
|
||||
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE
|
||||
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE --random-fully
|
||||
-A KUBE-SEP-SNQ3ZNILQDEJNDQO -m comment --comment ns1/svc1:p80 -s 10.0.1.1 -j KUBE-MARK-MASQ
|
||||
-A KUBE-SEP-SNQ3ZNILQDEJNDQO -m comment --comment ns1/svc1:p80 -m tcp -p tcp -j DNAT --to-destination 10.0.1.1:80
|
||||
-A KUBE-SEP-UHEGFW77JX3KXTOV -m comment --comment ns2/svc2:p8080 -s 10.0.2.1 -j KUBE-MARK-MASQ
|
||||
@@ -5905,7 +5882,7 @@ func TestSyncProxyRulesRepeated(t *testing.T) {
|
||||
-A KUBE-MARK-MASQ -j MARK --or-mark 0x4000
|
||||
-A KUBE-POSTROUTING -m mark ! --mark 0x4000/0x4000 -j RETURN
|
||||
-A KUBE-POSTROUTING -j MARK --xor-mark 0x4000
|
||||
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE
|
||||
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE --random-fully
|
||||
-A KUBE-SEP-BSWRHOQ77KEXZLNL -m comment --comment ns3/svc3:p80 -s 10.0.3.1 -j KUBE-MARK-MASQ
|
||||
-A KUBE-SEP-BSWRHOQ77KEXZLNL -m comment --comment ns3/svc3:p80 -m tcp -p tcp -j DNAT --to-destination 10.0.3.1:80
|
||||
-A KUBE-SVC-X27LE4BHSL4DOUIK -m comment --comment "ns3/svc3:p80 cluster IP" -m tcp -p tcp -d 172.30.0.43 --dport 80 ! -s 10.0.0.0/8 -j KUBE-MARK-MASQ
|
||||
@@ -5958,7 +5935,7 @@ func TestSyncProxyRulesRepeated(t *testing.T) {
|
||||
-A KUBE-MARK-MASQ -j MARK --or-mark 0x4000
|
||||
-A KUBE-POSTROUTING -m mark ! --mark 0x4000/0x4000 -j RETURN
|
||||
-A KUBE-POSTROUTING -j MARK --xor-mark 0x4000
|
||||
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE
|
||||
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE --random-fully
|
||||
-X KUBE-SEP-UHEGFW77JX3KXTOV
|
||||
-X KUBE-SVC-2VJB64SDSIJUP5T6
|
||||
COMMIT
|
||||
@@ -6020,7 +5997,7 @@ func TestSyncProxyRulesRepeated(t *testing.T) {
|
||||
-A KUBE-MARK-MASQ -j MARK --or-mark 0x4000
|
||||
-A KUBE-POSTROUTING -m mark ! --mark 0x4000/0x4000 -j RETURN
|
||||
-A KUBE-POSTROUTING -j MARK --xor-mark 0x4000
|
||||
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE
|
||||
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE --random-fully
|
||||
COMMIT
|
||||
`)
|
||||
assertIPTablesRulesEqual(t, getLine(), false, expected, fp.iptablesData.String())
|
||||
@@ -6079,7 +6056,7 @@ func TestSyncProxyRulesRepeated(t *testing.T) {
|
||||
-A KUBE-MARK-MASQ -j MARK --or-mark 0x4000
|
||||
-A KUBE-POSTROUTING -m mark ! --mark 0x4000/0x4000 -j RETURN
|
||||
-A KUBE-POSTROUTING -j MARK --xor-mark 0x4000
|
||||
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE
|
||||
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE --random-fully
|
||||
-A KUBE-SEP-AYCN5HPXMIRJNJXU -m comment --comment ns4/svc4:p80 -s 10.0.4.1 -j KUBE-MARK-MASQ
|
||||
-A KUBE-SEP-AYCN5HPXMIRJNJXU -m comment --comment ns4/svc4:p80 -m tcp -p tcp -j DNAT --to-destination 10.0.4.1:80
|
||||
-A KUBE-SVC-4SW47YFZTEDKD3PK -m comment --comment "ns4/svc4:p80 cluster IP" -m tcp -p tcp -d 172.30.0.44 --dport 80 ! -s 10.0.0.0/8 -j KUBE-MARK-MASQ
|
||||
@@ -6137,7 +6114,7 @@ func TestSyncProxyRulesRepeated(t *testing.T) {
|
||||
-A KUBE-MARK-MASQ -j MARK --or-mark 0x4000
|
||||
-A KUBE-POSTROUTING -m mark ! --mark 0x4000/0x4000 -j RETURN
|
||||
-A KUBE-POSTROUTING -j MARK --xor-mark 0x4000
|
||||
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE
|
||||
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE --random-fully
|
||||
-A KUBE-SEP-DKCFIS26GWF2WLWC -m comment --comment ns3/svc3:p80 -s 10.0.3.2 -j KUBE-MARK-MASQ
|
||||
-A KUBE-SEP-DKCFIS26GWF2WLWC -m comment --comment ns3/svc3:p80 -m tcp -p tcp -j DNAT --to-destination 10.0.3.2:80
|
||||
-A KUBE-SVC-X27LE4BHSL4DOUIK -m comment --comment "ns3/svc3:p80 cluster IP" -m tcp -p tcp -d 172.30.0.43 --dport 80 ! -s 10.0.0.0/8 -j KUBE-MARK-MASQ
|
||||
@@ -6193,7 +6170,7 @@ func TestSyncProxyRulesRepeated(t *testing.T) {
|
||||
-A KUBE-MARK-MASQ -j MARK --or-mark 0x4000
|
||||
-A KUBE-POSTROUTING -m mark ! --mark 0x4000/0x4000 -j RETURN
|
||||
-A KUBE-POSTROUTING -j MARK --xor-mark 0x4000
|
||||
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE
|
||||
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE --random-fully
|
||||
-A KUBE-SEP-DKCFIS26GWF2WLWC -m comment --comment ns3/svc3:p80 -s 10.0.3.2 -j KUBE-MARK-MASQ
|
||||
-A KUBE-SEP-DKCFIS26GWF2WLWC -m comment --comment ns3/svc3:p80 -m tcp -p tcp -j DNAT --to-destination 10.0.3.2:80
|
||||
-A KUBE-SEP-JVVZVJ7BSEPPRNBS -m comment --comment ns3/svc3:p80 -s 10.0.3.3 -j KUBE-MARK-MASQ
|
||||
@@ -6248,7 +6225,7 @@ func TestSyncProxyRulesRepeated(t *testing.T) {
|
||||
-A KUBE-MARK-MASQ -j MARK --or-mark 0x4000
|
||||
-A KUBE-POSTROUTING -m mark ! --mark 0x4000/0x4000 -j RETURN
|
||||
-A KUBE-POSTROUTING -j MARK --xor-mark 0x4000
|
||||
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE
|
||||
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE --random-fully
|
||||
COMMIT
|
||||
`)
|
||||
assertIPTablesRulesEqual(t, getLine(), false, expected, fp.iptablesData.String())
|
||||
@@ -6345,7 +6322,7 @@ func TestSyncProxyRulesRepeated(t *testing.T) {
|
||||
-A KUBE-MARK-MASQ -j MARK --or-mark 0x4000
|
||||
-A KUBE-POSTROUTING -m mark ! --mark 0x4000/0x4000 -j RETURN
|
||||
-A KUBE-POSTROUTING -j MARK --xor-mark 0x4000
|
||||
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE
|
||||
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE --random-fully
|
||||
-A KUBE-SEP-DKCFIS26GWF2WLWC -m comment --comment ns3/svc3:p80 -s 10.0.3.2 -j KUBE-MARK-MASQ
|
||||
-A KUBE-SEP-DKCFIS26GWF2WLWC -m comment --comment ns3/svc3:p80 -m tcp -p tcp -j DNAT --to-destination 10.0.3.2:80
|
||||
-A KUBE-SEP-JVVZVJ7BSEPPRNBS -m comment --comment ns3/svc3:p80 -s 10.0.3.3 -j KUBE-MARK-MASQ
|
||||
@@ -6701,7 +6678,7 @@ func TestBadIPs(t *testing.T) {
|
||||
-A KUBE-MARK-MASQ -j MARK --or-mark 0x4000
|
||||
-A KUBE-POSTROUTING -m mark ! --mark 0x4000/0x4000 -j RETURN
|
||||
-A KUBE-POSTROUTING -j MARK --xor-mark 0x4000
|
||||
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE
|
||||
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE --random-fully
|
||||
-A KUBE-SEP-SXIVWICOYRO3J4NJ -m comment --comment ns1/svc1:p80 -s 10.180.0.1 -j KUBE-MARK-MASQ
|
||||
-A KUBE-SEP-SXIVWICOYRO3J4NJ -m comment --comment ns1/svc1:p80 -m tcp -p tcp -j DNAT --to-destination 10.180.0.1:80
|
||||
-A KUBE-SVC-XPGD46QRK7WJZT7O -m comment --comment "ns1/svc1:p80 cluster IP" -m tcp -p tcp -d 172.30.0.41 --dport 80 ! -s 10.0.0.0/8 -j KUBE-MARK-MASQ
|
||||
|
||||
@@ -1468,15 +1468,12 @@ func (proxier *Proxier) writeIptablesRules() {
|
||||
// XOR proxier.masqueradeMark to unset it
|
||||
"-j", "MARK", "--xor-mark", proxier.masqueradeMark,
|
||||
)
|
||||
masqRule := []string{
|
||||
proxier.natRules.Write(
|
||||
"-A", string(kubePostroutingChain),
|
||||
"-m", "comment", "--comment", `"kubernetes service traffic requiring SNAT"`,
|
||||
"-j", "MASQUERADE",
|
||||
}
|
||||
if proxier.iptables.HasRandomFully() {
|
||||
masqRule = append(masqRule, "--random-fully")
|
||||
}
|
||||
proxier.natRules.Write(masqRule)
|
||||
"--random-fully",
|
||||
)
|
||||
|
||||
// Install the kubernetes-specific masquerade mark rule. We use a whole chain for
|
||||
// this so that it is easier to flush and change, for example if the mark
|
||||
|
||||
@@ -1563,41 +1563,6 @@ func TestIPv6Proxier(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestMasqueradeRule(t *testing.T) {
|
||||
for _, testcase := range []bool{false, true} {
|
||||
_, ctx := ktesting.NewTestContext(t)
|
||||
ipt := iptablestest.NewFake().SetHasRandomFully(testcase)
|
||||
ipvs := ipvstest.NewFake()
|
||||
ipset := ipsettest.NewFake(testIPSetVersion)
|
||||
fp := NewFakeProxier(ctx, ipt, ipvs, ipset, nil, nil, v1.IPv4Protocol)
|
||||
makeServiceMap(fp)
|
||||
fp.syncProxyRules()
|
||||
|
||||
buf := bytes.NewBuffer(nil)
|
||||
_ = ipt.SaveInto(utiliptables.TableNAT, buf)
|
||||
natRules := strings.Split(buf.String(), "\n")
|
||||
var hasMasqueradeJump, hasMasqRandomFully bool
|
||||
for _, line := range natRules {
|
||||
rule, _ := iptablestest.ParseRule(line, false)
|
||||
if rule != nil && rule.Chain == kubePostroutingChain && rule.Jump != nil && rule.Jump.Value == "MASQUERADE" {
|
||||
hasMasqueradeJump = true
|
||||
if rule.RandomFully != nil {
|
||||
hasMasqRandomFully = true
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !hasMasqueradeJump {
|
||||
t.Errorf("Failed to find -j MASQUERADE in %s chain", kubePostroutingChain)
|
||||
}
|
||||
if hasMasqRandomFully != testcase {
|
||||
probs := map[bool]string{false: "found", true: "did not find"}
|
||||
t.Errorf("%s --random-fully in -j MASQUERADE rule in %s chain for HasRandomFully()=%v", probs[testcase], kubePostroutingChain, testcase)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestExternalIPsNoEndpoint(t *testing.T) {
|
||||
_, ctx := ktesting.NewTestContext(t)
|
||||
ipt := iptablestest.NewFake()
|
||||
|
||||
@@ -26,12 +26,9 @@ import (
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
utilversion "k8s.io/apimachinery/pkg/util/version"
|
||||
utilwait "k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/klog/v2"
|
||||
utilexec "k8s.io/utils/exec"
|
||||
@@ -88,12 +85,6 @@ type Interface interface {
|
||||
// a reload) it will log an error and stop monitoring.
|
||||
// (This function should be called from a goroutine.)
|
||||
Monitor(canary Chain, tables []Table, reloadFunc func(), interval time.Duration, stopCh <-chan struct{})
|
||||
// HasRandomFully reveals whether `-j MASQUERADE` takes the
|
||||
// `--random-fully` option. This is helpful to work around a
|
||||
// Linux kernel bug that sometimes causes multiple flows to get
|
||||
// mapped to the same IP:PORT and consequently some suffer packet
|
||||
// drops.
|
||||
HasRandomFully() bool
|
||||
|
||||
// Present checks if the kernel supports the iptable interface
|
||||
Present() error
|
||||
@@ -164,78 +155,25 @@ const FlushTables FlushFlag = true
|
||||
// NoFlushTables a boolean false constant for option flag FlushFlag
|
||||
const NoFlushTables FlushFlag = false
|
||||
|
||||
// MinCheckVersion minimum version to be checked
|
||||
// Versions of iptables less than this do not support the -C / --check flag
|
||||
// (test whether a rule exists).
|
||||
var MinCheckVersion = utilversion.MustParseGeneric("1.4.11")
|
||||
|
||||
// RandomFullyMinVersion is the minimum version from which the --random-fully flag is supported,
|
||||
// used for port mapping to be fully randomized
|
||||
var RandomFullyMinVersion = utilversion.MustParseGeneric("1.6.2")
|
||||
|
||||
// WaitMinVersion a minimum iptables versions supporting the -w and -w<seconds> flags
|
||||
var WaitMinVersion = utilversion.MustParseGeneric("1.4.20")
|
||||
|
||||
// WaitSecondsMinVersion a minimum iptables versions supporting the wait seconds
|
||||
var WaitSecondsMinVersion = utilversion.MustParseGeneric("1.4.22")
|
||||
|
||||
// WaitRestoreMinVersion a minimum iptables versions supporting the wait restore seconds
|
||||
var WaitRestoreMinVersion = utilversion.MustParseGeneric("1.6.2")
|
||||
|
||||
// WaitString a constant for specifying the wait flag
|
||||
const WaitString = "-w"
|
||||
|
||||
// WaitSecondsValue a constant for specifying the default wait seconds
|
||||
const WaitSecondsValue = "5"
|
||||
|
||||
// LockfilePath16x is the iptables 1.6.x lock file acquired by any process that's making any change in the iptable rule
|
||||
const LockfilePath16x = "/run/xtables.lock"
|
||||
|
||||
// LockfilePath14x is the iptables 1.4.x lock file acquired by any process that's making any change in the iptable rule
|
||||
const LockfilePath14x = "@xtables"
|
||||
|
||||
// runner implements Interface in terms of exec("iptables").
|
||||
type runner struct {
|
||||
mu sync.Mutex
|
||||
exec utilexec.Interface
|
||||
protocol Protocol
|
||||
hasCheck bool
|
||||
hasRandomFully bool
|
||||
waitFlag []string
|
||||
restoreWaitFlag []string
|
||||
lockfilePath14x string
|
||||
lockfilePath16x string
|
||||
exec utilexec.Interface
|
||||
protocol Protocol
|
||||
}
|
||||
|
||||
// newInternal returns a new Interface which will exec iptables, and allows the
|
||||
// caller to change the iptables-restore lockfile path
|
||||
func newInternal(exec utilexec.Interface, protocol Protocol, lockfilePath14x, lockfilePath16x string) Interface {
|
||||
if lockfilePath16x == "" {
|
||||
lockfilePath16x = LockfilePath16x
|
||||
}
|
||||
if lockfilePath14x == "" {
|
||||
lockfilePath14x = LockfilePath14x
|
||||
}
|
||||
|
||||
// newInternal returns a new Interface which will exec iptables
|
||||
func newInternal(exec utilexec.Interface, protocol Protocol) Interface {
|
||||
runner := &runner{
|
||||
exec: exec,
|
||||
protocol: protocol,
|
||||
lockfilePath14x: lockfilePath14x,
|
||||
lockfilePath16x: lockfilePath16x,
|
||||
exec: exec,
|
||||
protocol: protocol,
|
||||
}
|
||||
|
||||
version, err := getIPTablesVersion(exec, protocol)
|
||||
if err != nil {
|
||||
// The only likely error is "no such file or directory", in which case any
|
||||
// further commands will fail the same way, so we don't need to do
|
||||
// anything special here.
|
||||
return runner
|
||||
}
|
||||
|
||||
runner.hasCheck = version.AtLeast(MinCheckVersion)
|
||||
runner.hasRandomFully = version.AtLeast(RandomFullyMinVersion)
|
||||
runner.waitFlag = getIPTablesWaitFlag(version)
|
||||
runner.restoreWaitFlag = getIPTablesRestoreWaitFlag(version, exec, protocol)
|
||||
return runner
|
||||
}
|
||||
|
||||
@@ -243,16 +181,16 @@ func newInternal(exec utilexec.Interface, protocol Protocol, lockfilePath14x, lo
|
||||
// Note that this function will return a single iptables Interface *and* an error, if only
|
||||
// a single family is supported.
|
||||
func New(protocol Protocol) Interface {
|
||||
return newInternal(utilexec.New(), protocol, "", "")
|
||||
return newInternal(utilexec.New(), protocol)
|
||||
}
|
||||
|
||||
func newDualStackInternal(exec utilexec.Interface) map[v1.IPFamily]Interface {
|
||||
interfaces := map[v1.IPFamily]Interface{}
|
||||
iptv4 := newInternal(exec, ProtocolIPv4, "", "")
|
||||
iptv4 := newInternal(exec, ProtocolIPv4)
|
||||
if presentErr := iptv4.Present(); presentErr == nil {
|
||||
interfaces[v1.IPv4Protocol] = iptv4
|
||||
}
|
||||
iptv6 := newInternal(exec, ProtocolIPv6, "", "")
|
||||
iptv6 := newInternal(exec, ProtocolIPv6)
|
||||
if presentErr := iptv6.Present(); presentErr == nil {
|
||||
interfaces[v1.IPv6Protocol] = iptv6
|
||||
}
|
||||
@@ -272,9 +210,6 @@ func NewBestEffort() map[v1.IPFamily]Interface {
|
||||
func (runner *runner) EnsureChain(table Table, chain Chain) (bool, error) {
|
||||
fullArgs := makeFullArgs(table, chain)
|
||||
|
||||
runner.mu.Lock()
|
||||
defer runner.mu.Unlock()
|
||||
|
||||
out, err := runner.run(opCreateChain, fullArgs)
|
||||
if err != nil {
|
||||
if ee, ok := err.(utilexec.ExitError); ok {
|
||||
@@ -291,9 +226,6 @@ func (runner *runner) EnsureChain(table Table, chain Chain) (bool, error) {
|
||||
func (runner *runner) FlushChain(table Table, chain Chain) error {
|
||||
fullArgs := makeFullArgs(table, chain)
|
||||
|
||||
runner.mu.Lock()
|
||||
defer runner.mu.Unlock()
|
||||
|
||||
out, err := runner.run(opFlushChain, fullArgs)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error flushing chain %q: %v: %s", chain, err, out)
|
||||
@@ -305,9 +237,6 @@ func (runner *runner) FlushChain(table Table, chain Chain) error {
|
||||
func (runner *runner) DeleteChain(table Table, chain Chain) error {
|
||||
fullArgs := makeFullArgs(table, chain)
|
||||
|
||||
runner.mu.Lock()
|
||||
defer runner.mu.Unlock()
|
||||
|
||||
out, err := runner.run(opDeleteChain, fullArgs)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error deleting chain %q: %v: %s", chain, err, out)
|
||||
@@ -319,10 +248,7 @@ func (runner *runner) DeleteChain(table Table, chain Chain) error {
|
||||
func (runner *runner) EnsureRule(position RulePosition, table Table, chain Chain, args ...string) (bool, error) {
|
||||
fullArgs := makeFullArgs(table, chain, args...)
|
||||
|
||||
runner.mu.Lock()
|
||||
defer runner.mu.Unlock()
|
||||
|
||||
exists, err := runner.checkRule(table, chain, args...)
|
||||
exists, err := runner.checkRule(fullArgs)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -340,10 +266,7 @@ func (runner *runner) EnsureRule(position RulePosition, table Table, chain Chain
|
||||
func (runner *runner) DeleteRule(table Table, chain Chain, args ...string) error {
|
||||
fullArgs := makeFullArgs(table, chain, args...)
|
||||
|
||||
runner.mu.Lock()
|
||||
defer runner.mu.Unlock()
|
||||
|
||||
exists, err := runner.checkRule(table, chain, args...)
|
||||
exists, err := runner.checkRule(fullArgs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -367,9 +290,6 @@ func (runner *runner) Protocol() Protocol {
|
||||
|
||||
// SaveInto is part of Interface.
|
||||
func (runner *runner) SaveInto(table Table, buffer *bytes.Buffer) error {
|
||||
runner.mu.Lock()
|
||||
defer runner.mu.Unlock()
|
||||
|
||||
trace := utiltrace.New("iptables save")
|
||||
defer trace.LogIfLong(2 * time.Second)
|
||||
|
||||
@@ -403,15 +323,8 @@ func (runner *runner) RestoreAll(data []byte, flush FlushFlag, counters RestoreC
|
||||
return runner.restoreInternal(args, data, flush, counters)
|
||||
}
|
||||
|
||||
type iptablesLocker interface {
|
||||
Close() error
|
||||
}
|
||||
|
||||
// restoreInternal is the shared part of Restore/RestoreAll
|
||||
func (runner *runner) restoreInternal(args []string, data []byte, flush FlushFlag, counters RestoreCountersFlag) error {
|
||||
runner.mu.Lock()
|
||||
defer runner.mu.Unlock()
|
||||
|
||||
trace := utiltrace.New("iptables restore")
|
||||
defer trace.LogIfLong(2 * time.Second)
|
||||
|
||||
@@ -422,24 +335,8 @@ func (runner *runner) restoreInternal(args []string, data []byte, flush FlushFla
|
||||
args = append(args, "--counters")
|
||||
}
|
||||
|
||||
// Grab the iptables lock to prevent iptables-restore and iptables
|
||||
// from stepping on each other. iptables-restore 1.6.2 will have
|
||||
// a --wait option like iptables itself, but that's not widely deployed.
|
||||
if len(runner.restoreWaitFlag) == 0 {
|
||||
locker, err := grabIptablesLocks(runner.lockfilePath14x, runner.lockfilePath16x)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
trace.Step("Locks grabbed")
|
||||
defer func(locker iptablesLocker) {
|
||||
if err := locker.Close(); err != nil {
|
||||
klog.ErrorS(err, "Failed to close iptables locks")
|
||||
}
|
||||
}(locker)
|
||||
}
|
||||
|
||||
// run the command and return the output or an error including the output and error
|
||||
fullArgs := append(runner.restoreWaitFlag, args...)
|
||||
fullArgs := append([]string{WaitString, WaitSecondsValue}, args...)
|
||||
iptablesRestoreCmd := iptablesRestoreCommand(runner.protocol)
|
||||
klog.V(4).InfoS("Running", "command", iptablesRestoreCmd, "arguments", fullArgs)
|
||||
cmd := runner.exec.Command(iptablesRestoreCmd, fullArgs...)
|
||||
@@ -482,8 +379,7 @@ func (runner *runner) run(op operation, args []string) ([]byte, error) {
|
||||
|
||||
func (runner *runner) runContext(ctx context.Context, op operation, args []string) ([]byte, error) {
|
||||
iptablesCmd := iptablesCommand(runner.protocol)
|
||||
fullArgs := append(runner.waitFlag, string(op))
|
||||
fullArgs = append(fullArgs, args...)
|
||||
fullArgs := append([]string{WaitString, WaitSecondsValue, string(op)}, args...)
|
||||
klog.V(5).InfoS("Running", "command", iptablesCmd, "arguments", fullArgs)
|
||||
if ctx == nil {
|
||||
return runner.exec.Command(iptablesCmd, fullArgs...).CombinedOutput()
|
||||
@@ -494,71 +390,7 @@ func (runner *runner) runContext(ctx context.Context, op operation, args []strin
|
||||
|
||||
// Returns (bool, nil) if it was able to check the existence of the rule, or
|
||||
// (<undefined>, error) if the process of checking failed.
|
||||
func (runner *runner) checkRule(table Table, chain Chain, args ...string) (bool, error) {
|
||||
if runner.hasCheck {
|
||||
return runner.checkRuleUsingCheck(makeFullArgs(table, chain, args...))
|
||||
}
|
||||
return runner.checkRuleWithoutCheck(table, chain, args...)
|
||||
}
|
||||
|
||||
var hexnumRE = regexp.MustCompile("0x0+([0-9])")
|
||||
|
||||
func trimhex(s string) string {
|
||||
return hexnumRE.ReplaceAllString(s, "0x$1")
|
||||
}
|
||||
|
||||
// Executes the rule check without using the "-C" flag, instead parsing iptables-save.
|
||||
// Present for compatibility with <1.4.11 versions of iptables. This is full
|
||||
// of hack and half-measures. We should nix this ASAP.
|
||||
func (runner *runner) checkRuleWithoutCheck(table Table, chain Chain, args ...string) (bool, error) {
|
||||
iptablesSaveCmd := iptablesSaveCommand(runner.protocol)
|
||||
klog.V(1).InfoS("Running", "command", iptablesSaveCmd, "table", string(table))
|
||||
out, err := runner.exec.Command(iptablesSaveCmd, "-t", string(table)).CombinedOutput()
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("error checking rule: %v", err)
|
||||
}
|
||||
|
||||
// Sadly, iptables has inconsistent quoting rules for comments. Just remove all quotes.
|
||||
// Also, quoted multi-word comments (which are counted as a single arg)
|
||||
// will be unpacked into multiple args,
|
||||
// in order to compare against iptables-save output (which will be split at whitespace boundary)
|
||||
// e.g. a single arg('"this must be before the NodePort rules"') will be unquoted and unpacked into 7 args.
|
||||
var argsCopy []string
|
||||
for i := range args {
|
||||
tmpField := strings.Trim(args[i], "\"")
|
||||
tmpField = trimhex(tmpField)
|
||||
argsCopy = append(argsCopy, strings.Fields(tmpField)...)
|
||||
}
|
||||
argset := sets.New(argsCopy...)
|
||||
|
||||
for _, line := range strings.Split(string(out), "\n") {
|
||||
fields := strings.Fields(line)
|
||||
|
||||
// Check that this is a rule for the correct chain, and that it has
|
||||
// the correct number of argument (+2 for "-A <chain name>")
|
||||
if !strings.HasPrefix(line, fmt.Sprintf("-A %s", string(chain))) || len(fields) != len(argsCopy)+2 {
|
||||
continue
|
||||
}
|
||||
|
||||
// Sadly, iptables has inconsistent quoting rules for comments.
|
||||
// Just remove all quotes.
|
||||
for i := range fields {
|
||||
fields[i] = strings.Trim(fields[i], "\"")
|
||||
fields[i] = trimhex(fields[i])
|
||||
}
|
||||
|
||||
// TODO: This misses reorderings e.g. "-x foo ! -y bar" will match "! -x foo -y bar"
|
||||
if sets.New(fields...).IsSuperset(argset) {
|
||||
return true, nil
|
||||
}
|
||||
klog.V(5).InfoS("DBG: fields is not a superset of args", "fields", fields, "arguments", args)
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// Executes the rule check using the "-C" flag
|
||||
func (runner *runner) checkRuleUsingCheck(args []string) (bool, error) {
|
||||
func (runner *runner) checkRule(args []string) (bool, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
|
||||
defer cancel()
|
||||
|
||||
@@ -640,9 +472,6 @@ func (runner *runner) Monitor(canary Chain, tables []Table, reloadFunc func(), i
|
||||
func (runner *runner) ChainExists(table Table, chain Chain) (bool, error) {
|
||||
fullArgs := makeFullArgs(table, chain)
|
||||
|
||||
runner.mu.Lock()
|
||||
defer runner.mu.Unlock()
|
||||
|
||||
trace := utiltrace.New("iptables ChainExists")
|
||||
defer trace.LogIfLong(2 * time.Second)
|
||||
|
||||
@@ -668,88 +497,6 @@ func makeFullArgs(table Table, chain Chain, args ...string) []string {
|
||||
return append([]string{string(chain), "-t", string(table)}, args...)
|
||||
}
|
||||
|
||||
const iptablesVersionPattern = `v([0-9]+(\.[0-9]+)+)`
|
||||
|
||||
// getIPTablesVersion runs "iptables --version" and parses the returned version
|
||||
func getIPTablesVersion(exec utilexec.Interface, protocol Protocol) (*utilversion.Version, error) {
|
||||
// this doesn't access mutable state so we don't need to use the interface / runner
|
||||
iptablesCmd := iptablesCommand(protocol)
|
||||
bytes, err := exec.Command(iptablesCmd, "--version").CombinedOutput()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
versionMatcher := regexp.MustCompile(iptablesVersionPattern)
|
||||
match := versionMatcher.FindStringSubmatch(string(bytes))
|
||||
if match == nil {
|
||||
return nil, fmt.Errorf("no iptables version found in string: %s", bytes)
|
||||
}
|
||||
version, err := utilversion.ParseGeneric(match[1])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("iptables version %q is not a valid version string: %v", match[1], err)
|
||||
}
|
||||
|
||||
return version, nil
|
||||
}
|
||||
|
||||
// Checks if iptables version has a "wait" flag
|
||||
func getIPTablesWaitFlag(version *utilversion.Version) []string {
|
||||
switch {
|
||||
case version.AtLeast(WaitSecondsMinVersion):
|
||||
return []string{WaitString, WaitSecondsValue}
|
||||
case version.AtLeast(WaitMinVersion):
|
||||
return []string{WaitString}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Checks if iptables-restore has a "wait" flag
|
||||
func getIPTablesRestoreWaitFlag(version *utilversion.Version, exec utilexec.Interface, protocol Protocol) []string {
|
||||
if version.AtLeast(WaitRestoreMinVersion) {
|
||||
return []string{WaitString, WaitSecondsValue}
|
||||
}
|
||||
|
||||
// Older versions may have backported features; if iptables-restore supports
|
||||
// --version, assume it also supports --wait
|
||||
vstring, err := getIPTablesRestoreVersionString(exec, protocol)
|
||||
if err != nil || vstring == "" {
|
||||
klog.V(3).InfoS("Couldn't get iptables-restore version; assuming it doesn't support --wait")
|
||||
return nil
|
||||
}
|
||||
if _, err := utilversion.ParseGeneric(vstring); err != nil {
|
||||
klog.V(3).InfoS("Couldn't parse iptables-restore version; assuming it doesn't support --wait")
|
||||
return nil
|
||||
}
|
||||
return []string{WaitString}
|
||||
}
|
||||
|
||||
// getIPTablesRestoreVersionString runs "iptables-restore --version" to get the version string
|
||||
// in the form "X.X.X"
|
||||
func getIPTablesRestoreVersionString(exec utilexec.Interface, protocol Protocol) (string, error) {
|
||||
// this doesn't access mutable state so we don't need to use the interface / runner
|
||||
|
||||
// iptables-restore hasn't always had --version, and worse complains
|
||||
// about unrecognized commands but doesn't exit when it gets them.
|
||||
// Work around that by setting stdin to nothing so it exits immediately.
|
||||
iptablesRestoreCmd := iptablesRestoreCommand(protocol)
|
||||
cmd := exec.Command(iptablesRestoreCmd, "--version")
|
||||
cmd.SetStdin(bytes.NewReader([]byte{}))
|
||||
bytes, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
versionMatcher := regexp.MustCompile(iptablesVersionPattern)
|
||||
match := versionMatcher.FindStringSubmatch(string(bytes))
|
||||
if match == nil {
|
||||
return "", fmt.Errorf("no iptables version found in string: %s", bytes)
|
||||
}
|
||||
return match[1], nil
|
||||
}
|
||||
|
||||
func (runner *runner) HasRandomFully() bool {
|
||||
return runner.hasRandomFully
|
||||
}
|
||||
|
||||
// Present tests if iptable is supported on current kernel by checking the existence
|
||||
// of default table and chain
|
||||
func (runner *runner) Present() error {
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
//go:build linux
|
||||
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package iptables
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
)
|
||||
|
||||
type locker struct {
|
||||
lock16 *os.File
|
||||
lock14 *net.UnixListener
|
||||
}
|
||||
|
||||
func (l *locker) Close() error {
|
||||
errList := []error{}
|
||||
if l.lock16 != nil {
|
||||
if err := l.lock16.Close(); err != nil {
|
||||
errList = append(errList, err)
|
||||
}
|
||||
}
|
||||
if l.lock14 != nil {
|
||||
if err := l.lock14.Close(); err != nil {
|
||||
errList = append(errList, err)
|
||||
}
|
||||
}
|
||||
return utilerrors.NewAggregate(errList)
|
||||
}
|
||||
|
||||
func grabIptablesLocks(lockfilePath14x, lockfilePath16x string) (iptablesLocker, error) {
|
||||
var err error
|
||||
var success bool
|
||||
|
||||
l := &locker{}
|
||||
defer func(l *locker) {
|
||||
// Clean up immediately on failure
|
||||
if !success {
|
||||
l.Close()
|
||||
}
|
||||
}(l)
|
||||
|
||||
// Grab both 1.6.x and 1.4.x-style locks; we don't know what the
|
||||
// iptables-restore version is if it doesn't support --wait, so we
|
||||
// can't assume which lock method it'll use.
|
||||
|
||||
// Roughly duplicate iptables 1.6.x xtables_lock() function.
|
||||
l.lock16, err = os.OpenFile(lockfilePath16x, os.O_CREATE, 0600)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to open iptables lock %s: %v", lockfilePath16x, err)
|
||||
}
|
||||
|
||||
if err := wait.PollImmediate(200*time.Millisecond, 2*time.Second, func() (bool, error) {
|
||||
if err := grabIptablesFileLock(l.lock16); err != nil {
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
}); err != nil {
|
||||
return nil, fmt.Errorf("failed to acquire new iptables lock: %v", err)
|
||||
}
|
||||
|
||||
// Roughly duplicate iptables 1.4.x xtables_lock() function.
|
||||
if err := wait.PollImmediate(200*time.Millisecond, 2*time.Second, func() (bool, error) {
|
||||
l.lock14, err = net.ListenUnix("unix", &net.UnixAddr{Name: lockfilePath14x, Net: "unix"})
|
||||
if err != nil {
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
}); err != nil {
|
||||
return nil, fmt.Errorf("failed to acquire old iptables lock: %v", err)
|
||||
}
|
||||
|
||||
success = true
|
||||
return l, nil
|
||||
}
|
||||
|
||||
func grabIptablesFileLock(f *os.File) error {
|
||||
return unix.Flock(int(f.Fd()), unix.LOCK_EX|unix.LOCK_NB)
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -190,7 +190,7 @@ func (mfc *monitorFakeCmd) Stop() {
|
||||
|
||||
func TestIPTablesMonitor(t *testing.T) {
|
||||
mfe := newMonitorFakeExec()
|
||||
ipt := newInternal(mfe, ProtocolIPv4, "", "")
|
||||
ipt := newInternal(mfe, ProtocolIPv4)
|
||||
|
||||
var reloads uint32
|
||||
stopCh := make(chan struct{})
|
||||
|
||||
@@ -30,8 +30,7 @@ import (
|
||||
|
||||
// FakeIPTables is no-op implementation of iptables Interface.
|
||||
type FakeIPTables struct {
|
||||
hasRandomFully bool
|
||||
protocol iptables.Protocol
|
||||
protocol iptables.Protocol
|
||||
|
||||
Dump *IPTablesDump
|
||||
}
|
||||
@@ -77,12 +76,6 @@ func NewIPv6Fake() *FakeIPTables {
|
||||
return f
|
||||
}
|
||||
|
||||
// SetHasRandomFully sets f's return value for HasRandomFully()
|
||||
func (f *FakeIPTables) SetHasRandomFully(can bool) *FakeIPTables {
|
||||
f.hasRandomFully = can
|
||||
return f
|
||||
}
|
||||
|
||||
// EnsureChain is part of iptables.Interface
|
||||
func (f *FakeIPTables) EnsureChain(table iptables.Table, chain iptables.Chain) (bool, error) {
|
||||
t, err := f.Dump.GetTable(table)
|
||||
@@ -321,11 +314,6 @@ func (f *FakeIPTables) RestoreAll(data []byte, flush iptables.FlushFlag, counter
|
||||
func (f *FakeIPTables) Monitor(canary iptables.Chain, tables []iptables.Table, reloadFunc func(), interval time.Duration, stopCh <-chan struct{}) {
|
||||
}
|
||||
|
||||
// HasRandomFully is part of iptables.Interface
|
||||
func (f *FakeIPTables) HasRandomFully() bool {
|
||||
return f.hasRandomFully
|
||||
}
|
||||
|
||||
func (f *FakeIPTables) Present() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user