in pkg/networkutils/network.go [464:589]
func (n *linuxNetwork) buildIptablesSNATRules(vpcCIDRs []string, primaryAddr *net.IP, primaryIntf string, ipt iptableswrapper.IPTablesIface) ([]iptablesRule, error) {
type snatCIDR struct {
cidr string
isExclusion bool
}
var allCIDRs []snatCIDR
for _, cidr := range vpcCIDRs {
log.Debugf("Adding %s CIDR to NAT chain", cidr)
allCIDRs = append(allCIDRs, snatCIDR{cidr: cidr, isExclusion: false})
}
for _, cidr := range n.excludeSNATCIDRs {
log.Debugf("Adding %s Excluded CIDR to NAT chain", cidr)
allCIDRs = append(allCIDRs, snatCIDR{cidr: cidr, isExclusion: true})
}
log.Debugf("Total CIDRs to program - %d", len(allCIDRs))
// build IPTABLES chain for SNAT of non-VPC outbound traffic and excluded CIDRs
var chains []string
chain := "AWS-SNAT-CHAIN-0"
log.Debugf("Setup Host Network: iptables -N %s -t nat", chain)
if err := ipt.NewChain("nat", chain); err != nil && !containChainExistErr(err) {
log.Errorf("ipt.NewChain error for chain [%s]: %v", chain, err)
return []iptablesRule{}, errors.Wrapf(err, "host network setup: failed to add chain")
}
chains = append(chains, chain)
// build SNAT rules for outbound non-VPC traffic
var iptableRules []iptablesRule
log.Debugf("Setup Host Network: iptables -A POSTROUTING -m comment --comment \"AWS SNAT CHAIN\" -j AWS-SNAT-CHAIN-0")
iptableRules = append(iptableRules, iptablesRule{
name: "first SNAT rules for non-VPC outbound traffic",
shouldExist: !n.useExternalSNAT,
table: "nat",
chain: "POSTROUTING",
rule: []string{
"-m", "comment", "--comment", "AWS SNAT CHAIN", "-j", "AWS-SNAT-CHAIN-0",
}})
for _, cidr := range allCIDRs {
comment := "AWS SNAT CHAIN"
if cidr.isExclusion {
comment += " EXCLUSION"
}
log.Debugf("Setup Host Network: iptables -A %s -d %s -m comment --comment %s -t nat -j %s", chain, cidr.cidr, comment, "RETURN")
iptableRules = append(iptableRules, iptablesRule{
name: chain,
shouldExist: !n.useExternalSNAT,
table: "nat",
chain: chain,
rule: []string{
"-d", cidr.cidr, "-m", "comment", "--comment", comment, "-j", "RETURN",
}})
}
// Prepare the Desired Rule for SNAT Rule for non-pod ENIs
snatRule := []string{"!", "-o", "vlan+",
"-m", "comment", "--comment", "AWS, SNAT",
"-m", "addrtype", "!", "--dst-type", "LOCAL",
"-j", "SNAT", "--to-source", primaryAddr.String()}
if n.typeOfSNAT == randomHashSNAT {
snatRule = append(snatRule, "--random")
}
if n.typeOfSNAT == randomPRNGSNAT {
if ipt.HasRandomFully() {
snatRule = append(snatRule, "--random-fully")
} else {
log.Warn("prng (--random-fully) requested, but iptables version does not support it. " +
"Falling back to hashrandom (--random)")
snatRule = append(snatRule, "--random")
}
}
snatStaleRules, err := computeStaleIptablesRules(ipt, "nat", "AWS-SNAT-CHAIN", iptableRules, chains)
if err != nil {
return []iptablesRule{}, err
}
iptableRules = append(iptableRules, snatStaleRules...)
iptableRules = append(iptableRules, iptablesRule{
name: "last SNAT rule for non-VPC outbound traffic",
shouldExist: !n.useExternalSNAT,
table: "nat",
chain: chain,
rule: snatRule,
})
iptableRules = append(iptableRules, iptablesRule{
name: "connmark for primary ENI",
shouldExist: n.nodePortSupportEnabled,
table: "mangle",
chain: "PREROUTING",
rule: []string{
"-m", "comment", "--comment", "AWS, primary ENI",
"-i", primaryIntf,
"-m", "addrtype", "--dst-type", "LOCAL", "--limit-iface-in",
"-j", "CONNMARK", "--set-mark", fmt.Sprintf("%#x/%#x", n.mainENIMark, n.mainENIMark),
},
})
iptableRules = append(iptableRules, iptablesRule{
name: "connmark restore for primary ENI",
shouldExist: n.nodePortSupportEnabled || !n.useExternalSNAT,
table: "mangle",
chain: "PREROUTING",
rule: []string{
"-m", "comment", "--comment", "AWS, primary ENI",
"-i", n.vethPrefix + "+", "-j", "CONNMARK", "--restore-mark", "--mask", fmt.Sprintf("%#x", n.mainENIMark),
},
})
iptableRules = append(iptableRules, iptablesRule{
name: "connmark restore for primary ENI from vlan",
shouldExist: n.nodePortSupportEnabled,
table: "mangle",
chain: "PREROUTING",
rule: []string{
"-m", "comment", "--comment", "AWS, primary ENI",
"-i", "vlan+", "-j", "CONNMARK", "--restore-mark", "--mask", fmt.Sprintf("%#x", n.mainENIMark),
},
})
log.Debugf("iptableRules: %v", iptableRules)
return iptableRules, nil
}