Skip to content

Commit 13421da

Browse files
authored
Use SNAT instead of MASQUERADE to source NAT outbound IPVS traffic (#668)
* Use SNAT instead of MASQUERADE to source NAT outbound IPVS traffic * Perform cleanup of depreciated masquerade iptables rules (if needed)
1 parent 230ff15 commit 13421da

File tree

1 file changed

+47
-8
lines changed

1 file changed

+47
-8
lines changed

pkg/controllers/proxy/network_services_controller.go

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -283,8 +283,14 @@ func (nsc *NetworkServicesController) Run(healthChan chan<- *healthcheck.Control
283283

284284
glog.Infof("Starting network services controller")
285285

286-
err := ensureMasqueradeIptablesRule(nsc.masqueradeAll, nsc.podCidr)
286+
glog.V(1).Info("Performing cleanup of depreciated masquerade iptables rules (if needed).")
287+
err := nsc.deleteBadMasqueradeIptablesRules()
288+
if err != nil {
289+
glog.Errorf("Error cleaning up old/bad masquerade rules: %s", err.Error())
290+
}
291+
287292
// enable masquerade rule
293+
err = nsc.ensureMasqueradeIptablesRule()
288294
if err != nil {
289295
glog.Errorf("Failed to do add masquerade rule in POSTROUTING chain of nat table due to: %s", err.Error())
290296
}
@@ -410,8 +416,8 @@ func (nsc *NetworkServicesController) doSync() error {
410416
nsc.mu.Lock()
411417
defer nsc.mu.Unlock()
412418

413-
err = ensureMasqueradeIptablesRule(nsc.masqueradeAll, nsc.podCidr)
414419
// enable masquerade rule
420+
err = nsc.ensureMasqueradeIptablesRule()
415421
if err != nil {
416422
glog.Errorf("Failed to do add masquerade rule in POSTROUTING chain of nat table due to: %s", err.Error())
417423
}
@@ -1144,13 +1150,13 @@ func (nsc *NetworkServicesController) buildEndpointsInfo() endpointsInfoMap {
11441150
// Add an iptables rule to masquerade outbound IPVS traffic. IPVS nat requires that reverse path traffic
11451151
// to go through the director for its functioning. So the masquerade rule ensures source IP is modifed
11461152
// to node ip, so return traffic from real server (endpoint pods) hits the node/lvs director
1147-
func ensureMasqueradeIptablesRule(masqueradeAll bool, podCidr string) error {
1153+
func (nsc *NetworkServicesController) ensureMasqueradeIptablesRule() error {
11481154
iptablesCmdHandler, err := iptables.New()
11491155
if err != nil {
11501156
return errors.New("Failed to initialize iptables executor" + err.Error())
11511157
}
1152-
var args = []string{"-m", "ipvs", "--ipvs", "--vdir", "ORIGINAL", "--vmethod", "MASQ", "-m", "comment", "--comment", "", "-j", "MASQUERADE"}
1153-
if masqueradeAll {
1158+
var args = []string{"-m", "ipvs", "--ipvs", "--vdir", "ORIGINAL", "--vmethod", "MASQ", "-m", "comment", "--comment", "", "-j", "SNAT", "--to-source", nsc.nodeIP.String()}
1159+
if nsc.masqueradeAll {
11541160
err = iptablesCmdHandler.AppendUnique("nat", "POSTROUTING", args...)
11551161
if err != nil {
11561162
return errors.New("Failed to create iptables rule to masquerade all outbound IPVS traffic" + err.Error())
@@ -1169,10 +1175,10 @@ func ensureMasqueradeIptablesRule(masqueradeAll bool, podCidr string) error {
11691175
glog.Infof("Deleted iptables rule to masquerade all outbound IVPS traffic.")
11701176
}
11711177
}
1172-
if len(podCidr) > 0 {
1178+
if len(nsc.podCidr) > 0 {
11731179
//TODO: ipset should be used for destination podCidr(s) match after multiple podCidr(s) per node get supported
11741180
args = []string{"-m", "ipvs", "--ipvs", "--vdir", "ORIGINAL", "--vmethod", "MASQ", "-m", "comment", "--comment", "",
1175-
"!", "-s", podCidr, "!", "-d", podCidr, "-j", "MASQUERADE"}
1181+
"!", "-s", nsc.podCidr, "!", "-d", nsc.podCidr, "-j", "SNAT", "--to-source", nsc.nodeIP.String()}
11761182
err = iptablesCmdHandler.AppendUnique("nat", "POSTROUTING", args...)
11771183
if err != nil {
11781184
return errors.New("Failed to run iptables command" + err.Error())
@@ -1182,6 +1188,39 @@ func ensureMasqueradeIptablesRule(masqueradeAll bool, podCidr string) error {
11821188
return nil
11831189
}
11841190

1191+
// Delete old/bad iptables rules to masquerade outbound IPVS traffic.
1192+
func (nsc *NetworkServicesController) deleteBadMasqueradeIptablesRules() error {
1193+
iptablesCmdHandler, err := iptables.New()
1194+
if err != nil {
1195+
return errors.New("Failed create iptables handler:" + err.Error())
1196+
}
1197+
1198+
var argsBad = [][]string{
1199+
{"-m", "ipvs", "--ipvs", "--vdir", "ORIGINAL", "--vmethod", "MASQ", "-m", "comment", "--comment", "", "-j", "MASQUERADE"},
1200+
{"-m", "ipvs", "--ipvs", "--vdir", "ORIGINAL", "--vmethod", "MASQ", "-m", "comment", "--comment", "", "!", "-s", nsc.podCidr, "!", "-d", nsc.podCidr, "-j", "MASQUERADE"},
1201+
}
1202+
1203+
for _, args := range argsBad {
1204+
exists, err := iptablesCmdHandler.Exists("nat", "POSTROUTING", args...)
1205+
if err != nil {
1206+
return fmt.Errorf("Failed to lookup iptables rule: %s", err.Error())
1207+
}
1208+
1209+
if exists {
1210+
err = iptablesCmdHandler.Delete("nat", "POSTROUTING", args...)
1211+
if err != nil {
1212+
return fmt.Errorf("Failed to delete old/bad iptables rule to "+
1213+
"masquerade outbound IVPS traffic: %s.\n"+
1214+
"Masquerade all might still work, or bugs may persist after upgrade...",
1215+
err)
1216+
}
1217+
glog.Infof("Deleted old/bad iptables rule to masquerade outbound traffic.")
1218+
}
1219+
}
1220+
1221+
return nil
1222+
}
1223+
11851224
// syncHairpinIptablesRules adds/removes iptables rules pertaining to traffic
11861225
// from an Endpoint (Pod) to its own service VIP. Rules are only applied if
11871226
// enabled globally via CLI argument or a service has an annotation requesting
@@ -1387,7 +1426,7 @@ func deleteMasqueradeIptablesRule() error {
13871426
return errors.New("Failed to list iptables rules in POSTROUTING chain in nat table" + err.Error())
13881427
}
13891428
for i, rule := range postRoutingChainRules {
1390-
if strings.Contains(rule, "ipvs") && strings.Contains(rule, "MASQUERADE") {
1429+
if strings.Contains(rule, "ipvs") && strings.Contains(rule, "SNAT") {
13911430
err = iptablesCmdHandler.Delete("nat", "POSTROUTING", strconv.Itoa(i))
13921431
if err != nil {
13931432
return errors.New("Failed to run iptables command" + err.Error())

0 commit comments

Comments
 (0)