Skip to content

Commit 210dc3d

Browse files
authored
avoids adding kube-router specific rules to enforce network policies in (#909)
built in chain used in fitler table - adds one level of indirection INPUT -> KUBE-ROUTER-INPUT FORWARD -> KUBE-ROUTER-FORWARD OUTPUT -> KUBE-ROUTER-OUTPUT - easy to troubleshoot with namesake custom chains Fixes #185
1 parent 8f5c959 commit 210dc3d

File tree

1 file changed

+80
-14
lines changed

1 file changed

+80
-14
lines changed

pkg/controllers/netpol/network_policy_controller.go

Lines changed: 80 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ const (
3636
kubeNetworkPolicyChainPrefix = "KUBE-NWPLCY-"
3737
kubeSourceIpSetPrefix = "KUBE-SRC-"
3838
kubeDestinationIpSetPrefix = "KUBE-DST-"
39+
kubeInputChainName = "KUBE-ROUTER-INPUT"
40+
kubeForwardChainName = "KUBE-ROUTER-FORWARD"
41+
kubeOutputChainName = "KUBE-ROUTER-OUTPUT"
3942
)
4043

4144
// Network policy controller provides both ingress and egress filtering for the pods as per the defined network
@@ -141,6 +144,9 @@ func (npc *NetworkPolicyController) Run(healthChan chan<- *healthcheck.Controlle
141144
glog.Info("Starting network policy controller")
142145
npc.healthChan = healthChan
143146

147+
// setup kube-router specific top level cutoms chains
148+
npc.ensureTopLevelChains()
149+
144150
// Full syncs of the network policy controller take a lot of time and can only be processed one at a time,
145151
// therefore, we start it in it's own goroutine and request a sync through a single item channel
146152
glog.Info("Starting network policy controller full sync goroutine")
@@ -179,6 +185,62 @@ func (npc *NetworkPolicyController) Run(healthChan chan<- *healthcheck.Controlle
179185
}
180186
}
181187

188+
// Creates custom chains KUBE-ROUTER-INPUT, KUBE-ROUTER-FORWARD, KUBE-ROUTER-OUTPUT
189+
// and following rules in the filter table to jump from builtin chain to custom chain
190+
// -A INPUT -m comment --comment "kube-router netpol" -j KUBE-ROUTER-INPUT
191+
// -A FORWARD -m comment --comment "kube-router netpol" -j KUBE-ROUTER-FORWARD
192+
// -A OUTPUT -m comment --comment "kube-router netpol" -j KUBE-ROUTER-OUTPUT
193+
func (npc *NetworkPolicyController) ensureTopLevelChains() {
194+
195+
iptablesCmdHandler, err := iptables.New()
196+
if err != nil {
197+
glog.Fatalf("Failed to initialize iptables executor due to %s", err.Error())
198+
}
199+
200+
chains := map[string]string{"INPUT": kubeInputChainName, "FORWARD": kubeForwardChainName, "OUTPUT": kubeOutputChainName}
201+
202+
for builtinChain, customChain := range chains {
203+
err = iptablesCmdHandler.NewChain("filter", customChain)
204+
if err != nil && err.(*iptables.Error).ExitStatus() != 1 {
205+
glog.Fatalf("Failed to run iptables command to create %s chain due to %s", customChain, err.Error())
206+
}
207+
args := []string{"-m", "comment", "--comment", "kube-router netpol", "-j", customChain}
208+
exists, err := iptablesCmdHandler.Exists("filter", builtinChain, args...)
209+
if err != nil {
210+
glog.Fatalf("Failed to verify rule exists to jump to chain %s in %s chain due to %s", customChain, builtinChain, err.Error())
211+
}
212+
if !exists {
213+
err := iptablesCmdHandler.Insert("filter", builtinChain, 1, args...)
214+
if err != nil {
215+
glog.Fatalf("Failed to run iptables command to insert in %s chain %s", builtinChain, err.Error())
216+
}
217+
} else {
218+
rules, err := iptablesCmdHandler.List("filter", builtinChain)
219+
if err != nil {
220+
glog.Fatalf("failed to list rules in filter table %s chain due to %s", builtinChain, err.Error())
221+
}
222+
223+
var ruleNo int
224+
for i, rule := range rules {
225+
if strings.Contains(rule, customChain) {
226+
ruleNo = i
227+
break
228+
}
229+
}
230+
if ruleNo != 1 {
231+
err = iptablesCmdHandler.Insert("filter", builtinChain, 1, args...)
232+
if err != nil {
233+
glog.Fatalf("Failed to run iptables command to insert in %s chain %s", builtinChain, err.Error())
234+
}
235+
err = iptablesCmdHandler.Delete("filter", builtinChain, strconv.Itoa(ruleNo+1))
236+
if err != nil {
237+
glog.Fatalf("Failed to delete wrong rule to jump to chain %s in %s chain due to %s", customChain, builtinChain, err.Error())
238+
}
239+
}
240+
}
241+
}
242+
}
243+
182244
// OnPodUpdate handles updates to pods from the Kubernetes api server
183245
func (npc *NetworkPolicyController) OnPodUpdate(obj interface{}) {
184246
pod := obj.(*api.Pod)
@@ -225,6 +287,10 @@ func (npc *NetworkPolicyController) fullPolicySync() {
225287
}()
226288

227289
glog.V(1).Infof("Starting sync of iptables with version: %s", syncVersion)
290+
291+
// ensure kube-router specific top level chains and corresponding rules exist
292+
npc.ensureTopLevelChains()
293+
228294
if npc.v1NetworkPolicy {
229295
networkPoliciesInfo, err = npc.buildNetworkPoliciesInfo()
230296
if err != nil {
@@ -760,25 +826,25 @@ func (npc *NetworkPolicyController) syncPodFirewallChains(networkPoliciesInfo []
760826
comment = "rule to jump traffic destined to POD name:" + pod.name + " namespace: " + pod.namespace +
761827
" to chain " + podFwChainName
762828
args = []string{"-m", "comment", "--comment", comment, "-d", pod.ip, "-j", podFwChainName}
763-
exists, err = iptablesCmdHandler.Exists("filter", "FORWARD", args...)
829+
exists, err = iptablesCmdHandler.Exists("filter", kubeForwardChainName, args...)
764830
if err != nil {
765831
return nil, fmt.Errorf("Failed to run iptables command: %s", err.Error())
766832
}
767833
if !exists {
768-
err := iptablesCmdHandler.Insert("filter", "FORWARD", 1, args...)
834+
err := iptablesCmdHandler.Insert("filter", kubeForwardChainName, 1, args...)
769835
if err != nil {
770836
return nil, fmt.Errorf("Failed to run iptables command: %s", err.Error())
771837
}
772838
}
773839

774840
// ensure there is rule in filter table and OUTPUT chain to jump to pod specific firewall chain
775841
// this rule applies to the traffic from a pod getting routed back to another pod on same node by service proxy
776-
exists, err = iptablesCmdHandler.Exists("filter", "OUTPUT", args...)
842+
exists, err = iptablesCmdHandler.Exists("filter", kubeOutputChainName, args...)
777843
if err != nil {
778844
return nil, fmt.Errorf("Failed to run iptables command: %s", err.Error())
779845
}
780846
if !exists {
781-
err := iptablesCmdHandler.Insert("filter", "OUTPUT", 1, args...)
847+
err := iptablesCmdHandler.Insert("filter", kubeOutputChainName, 1, args...)
782848
if err != nil {
783849
return nil, fmt.Errorf("Failed to run iptables command: %s", err.Error())
784850
}
@@ -792,12 +858,12 @@ func (npc *NetworkPolicyController) syncPodFirewallChains(networkPoliciesInfo []
792858
"-m", "comment", "--comment", comment,
793859
"-d", pod.ip,
794860
"-j", podFwChainName}
795-
exists, err = iptablesCmdHandler.Exists("filter", "FORWARD", args...)
861+
exists, err = iptablesCmdHandler.Exists("filter", kubeForwardChainName, args...)
796862
if err != nil {
797863
return nil, fmt.Errorf("Failed to run iptables command: %s", err.Error())
798864
}
799865
if !exists {
800-
err = iptablesCmdHandler.Insert("filter", "FORWARD", 1, args...)
866+
err = iptablesCmdHandler.Insert("filter", kubeForwardChainName, 1, args...)
801867
if err != nil {
802868
return nil, fmt.Errorf("Failed to run iptables command: %s", err.Error())
803869
}
@@ -874,7 +940,7 @@ func (npc *NetworkPolicyController) syncPodFirewallChains(networkPoliciesInfo []
874940
}
875941
}
876942

877-
egressFilterChains := []string{"FORWARD", "OUTPUT", "INPUT"}
943+
egressFilterChains := []string{kubeInputChainName, kubeForwardChainName, kubeOutputChainName}
878944
for _, chain := range egressFilterChains {
879945
// ensure there is rule in filter table and FORWARD chain to jump to pod specific firewall chain
880946
// this rule applies to the traffic getting forwarded/routed (traffic from the pod destinted
@@ -902,12 +968,12 @@ func (npc *NetworkPolicyController) syncPodFirewallChains(networkPoliciesInfo []
902968
"-m", "comment", "--comment", comment,
903969
"-s", pod.ip,
904970
"-j", podFwChainName}
905-
exists, err = iptablesCmdHandler.Exists("filter", "FORWARD", args...)
971+
exists, err = iptablesCmdHandler.Exists("filter", kubeForwardChainName, args...)
906972
if err != nil {
907973
return nil, fmt.Errorf("Failed to run iptables command: %s", err.Error())
908974
}
909975
if !exists {
910-
err = iptablesCmdHandler.Insert("filter", "FORWARD", 1, args...)
976+
err = iptablesCmdHandler.Insert("filter", kubeForwardChainName, 1, args...)
911977
if err != nil {
912978
return nil, fmt.Errorf("Failed to run iptables command: %s", err.Error())
913979
}
@@ -982,7 +1048,7 @@ func cleanupStaleRules(activePolicyChains, activePodFwChains, activePolicyIPSets
9821048
// remove stale iptables podFwChain references from the filter table chains
9831049
for _, podFwChain := range cleanupPodFwChains {
9841050

985-
primaryChains := []string{"FORWARD", "OUTPUT", "INPUT"}
1051+
primaryChains := []string{kubeInputChainName, kubeForwardChainName, kubeOutputChainName}
9861052
for _, egressChain := range primaryChains {
9871053
forwardChainRules, err := iptablesCmdHandler.List("filter", egressChain)
9881054
if err != nil {
@@ -1536,7 +1602,7 @@ func (npc *NetworkPolicyController) Cleanup() {
15361602
}
15371603

15381604
// delete jump rules in FORWARD chain to pod specific firewall chain
1539-
forwardChainRules, err := iptablesCmdHandler.List("filter", "FORWARD")
1605+
forwardChainRules, err := iptablesCmdHandler.List("filter", kubeForwardChainName)
15401606
if err != nil {
15411607
glog.Errorf("Failed to delete iptables rules as part of cleanup")
15421608
return
@@ -1546,7 +1612,7 @@ func (npc *NetworkPolicyController) Cleanup() {
15461612
var realRuleNo int
15471613
for i, rule := range forwardChainRules {
15481614
if strings.Contains(rule, kubePodFirewallChainPrefix) {
1549-
err = iptablesCmdHandler.Delete("filter", "FORWARD", strconv.Itoa(i-realRuleNo))
1615+
err = iptablesCmdHandler.Delete("filter", kubeForwardChainName, strconv.Itoa(i-realRuleNo))
15501616
if err != nil {
15511617
glog.Errorf("Failed to delete iptables rule as part of cleanup: %s", err)
15521618
}
@@ -1555,7 +1621,7 @@ func (npc *NetworkPolicyController) Cleanup() {
15551621
}
15561622

15571623
// delete jump rules in OUTPUT chain to pod specific firewall chain
1558-
forwardChainRules, err = iptablesCmdHandler.List("filter", "OUTPUT")
1624+
forwardChainRules, err = iptablesCmdHandler.List("filter", kubeOutputChainName)
15591625
if err != nil {
15601626
glog.Errorf("Failed to delete iptables rules as part of cleanup")
15611627
return
@@ -1565,7 +1631,7 @@ func (npc *NetworkPolicyController) Cleanup() {
15651631
realRuleNo = 0
15661632
for i, rule := range forwardChainRules {
15671633
if strings.Contains(rule, kubePodFirewallChainPrefix) {
1568-
err = iptablesCmdHandler.Delete("filter", "OUTPUT", strconv.Itoa(i-realRuleNo))
1634+
err = iptablesCmdHandler.Delete("filter", kubeOutputChainName, strconv.Itoa(i-realRuleNo))
15691635
if err != nil {
15701636
glog.Errorf("Failed to delete iptables rule as part of cleanup: %s", err)
15711637
}

0 commit comments

Comments
 (0)