|
@@ -20,37 +20,52 @@ import (
|
|
|
|
|
|
log "github.com/golang/glog"
|
|
log "github.com/golang/glog"
|
|
|
|
|
|
|
|
+ "time"
|
|
|
|
+
|
|
"github.com/coreos/flannel/pkg/ip"
|
|
"github.com/coreos/flannel/pkg/ip"
|
|
"github.com/coreos/flannel/subnet"
|
|
"github.com/coreos/flannel/subnet"
|
|
"github.com/coreos/go-iptables/iptables"
|
|
"github.com/coreos/go-iptables/iptables"
|
|
- "time"
|
|
|
|
)
|
|
)
|
|
|
|
|
|
-type IPTablesRules interface {
|
|
|
|
|
|
+type IPTables interface {
|
|
AppendUnique(table string, chain string, rulespec ...string) error
|
|
AppendUnique(table string, chain string, rulespec ...string) error
|
|
Delete(table string, chain string, rulespec ...string) error
|
|
Delete(table string, chain string, rulespec ...string) error
|
|
Exists(table string, chain string, rulespec ...string) (bool, error)
|
|
Exists(table string, chain string, rulespec ...string) (bool, error)
|
|
}
|
|
}
|
|
|
|
|
|
-func rules(ipn ip.IP4Net, lease *subnet.Lease) [][]string {
|
|
|
|
|
|
+type IPTablesRule struct {
|
|
|
|
+ table string
|
|
|
|
+ chain string
|
|
|
|
+ rulespec []string
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func MasqRules(ipn ip.IP4Net, lease *subnet.Lease) []IPTablesRule {
|
|
n := ipn.String()
|
|
n := ipn.String()
|
|
sn := lease.Subnet.String()
|
|
sn := lease.Subnet.String()
|
|
|
|
|
|
- return [][]string{
|
|
|
|
|
|
+ return []IPTablesRule{
|
|
// This rule makes sure we don't NAT traffic within overlay network (e.g. coming out of docker0)
|
|
// This rule makes sure we don't NAT traffic within overlay network (e.g. coming out of docker0)
|
|
- {"-s", n, "-d", n, "-j", "RETURN"},
|
|
|
|
|
|
+ {"nat", "POSTROUTING", []string{"-s", n, "-d", n, "-j", "RETURN"}},
|
|
// NAT if it's not multicast traffic
|
|
// NAT if it's not multicast traffic
|
|
- {"-s", n, "!", "-d", "224.0.0.0/4", "-j", "MASQUERADE"},
|
|
|
|
|
|
+ {"nat", "POSTROUTING", []string{"-s", n, "!", "-d", "224.0.0.0/4", "-j", "MASQUERADE"}},
|
|
// Prevent performing Masquerade on external traffic which arrives from a Node that owns the container/pod IP address
|
|
// Prevent performing Masquerade on external traffic which arrives from a Node that owns the container/pod IP address
|
|
- {"!", "-s", n, "-d", sn, "-j", "RETURN"},
|
|
|
|
|
|
+ {"nat", "POSTROUTING", []string{"!", "-s", n, "-d", sn, "-j", "RETURN"}},
|
|
// Masquerade anything headed towards flannel from the host
|
|
// Masquerade anything headed towards flannel from the host
|
|
- {"!", "-s", n, "-d", n, "-j", "MASQUERADE"},
|
|
|
|
|
|
+ {"nat", "POSTROUTING", []string{"!", "-s", n, "-d", n, "-j", "MASQUERADE"}},
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func ForwardRules(flannelNetwork string) []IPTablesRule {
|
|
|
|
+ return []IPTablesRule{
|
|
|
|
+ // These rules allow traffic to be forwarded if it is to or from the flannel network range.
|
|
|
|
+ {"filter", "FORWARD", []string{"-s", flannelNetwork, "-j", "ACCEPT"}},
|
|
|
|
+ {"filter", "FORWARD", []string{"-d", flannelNetwork, "-j", "ACCEPT"}},
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-func ipMasqRulesExist(ipt IPTablesRules, ipn ip.IP4Net, lease *subnet.Lease) (bool, error) {
|
|
|
|
- for _, rule := range rules(ipn, lease) {
|
|
|
|
- exists, err := ipt.Exists("nat", "POSTROUTING", rule...)
|
|
|
|
|
|
+func ipTablesRulesExist(ipt IPTables, rules []IPTablesRule) (bool, error) {
|
|
|
|
+ for _, rule := range rules {
|
|
|
|
+ exists, err := ipt.Exists(rule.table, rule.chain, rule.rulespec...)
|
|
if err != nil {
|
|
if err != nil {
|
|
// this shouldn't ever happen
|
|
// this shouldn't ever happen
|
|
return false, fmt.Errorf("failed to check rule existence: %v", err)
|
|
return false, fmt.Errorf("failed to check rule existence: %v", err)
|
|
@@ -63,30 +78,30 @@ func ipMasqRulesExist(ipt IPTablesRules, ipn ip.IP4Net, lease *subnet.Lease) (bo
|
|
return true, nil
|
|
return true, nil
|
|
}
|
|
}
|
|
|
|
|
|
-func SetupAndEnsureIPMasq(network ip.IP4Net, lease *subnet.Lease) {
|
|
|
|
|
|
+func SetupAndEnsureIPTables(rules []IPTablesRule) {
|
|
ipt, err := iptables.New()
|
|
ipt, err := iptables.New()
|
|
if err != nil {
|
|
if err != nil {
|
|
// if we can't find iptables, give up and return
|
|
// if we can't find iptables, give up and return
|
|
- log.Errorf("Failed to setup IP Masquerade. IPTables was not found: %v", err)
|
|
|
|
|
|
+ log.Errorf("Failed to setup IPTables. iptables binary was not found: %v", err)
|
|
return
|
|
return
|
|
}
|
|
}
|
|
|
|
|
|
defer func() {
|
|
defer func() {
|
|
- teardownIPMasq(ipt, network, lease)
|
|
|
|
|
|
+ teardownIPTables(ipt, rules)
|
|
}()
|
|
}()
|
|
|
|
|
|
for {
|
|
for {
|
|
- // Ensure that all the rules exist every 5 seconds
|
|
|
|
- if err := ensureIPMasq(ipt, network, lease); err != nil {
|
|
|
|
- log.Errorf("Failed to ensure IP Masquerade: %v", err)
|
|
|
|
|
|
+ // Ensure that all the iptables rules exist every 5 seconds
|
|
|
|
+ if err := ensureIPTables(ipt, rules); err != nil {
|
|
|
|
+ log.Errorf("Failed to ensure iptables rules: %v", err)
|
|
}
|
|
}
|
|
|
|
|
|
time.Sleep(5 * time.Second)
|
|
time.Sleep(5 * time.Second)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-func ensureIPMasq(ipt IPTablesRules, ipn ip.IP4Net, lease *subnet.Lease) error {
|
|
|
|
- exists, err := ipMasqRulesExist(ipt, ipn, lease)
|
|
|
|
|
|
+func ensureIPTables(ipt IPTables, rules []IPTablesRule) error {
|
|
|
|
+ exists, err := ipTablesRulesExist(ipt, rules)
|
|
if err != nil {
|
|
if err != nil {
|
|
return fmt.Errorf("Error checking rule existence: %v", err)
|
|
return fmt.Errorf("Error checking rule existence: %v", err)
|
|
}
|
|
}
|
|
@@ -97,30 +112,30 @@ func ensureIPMasq(ipt IPTablesRules, ipn ip.IP4Net, lease *subnet.Lease) error {
|
|
// Otherwise, teardown all the rules and set them up again
|
|
// Otherwise, teardown all the rules and set them up again
|
|
// We do this because the order of the rules is important
|
|
// We do this because the order of the rules is important
|
|
log.Info("Some iptables rules are missing; deleting and recreating rules")
|
|
log.Info("Some iptables rules are missing; deleting and recreating rules")
|
|
- teardownIPMasq(ipt, ipn, lease)
|
|
|
|
- if err = setupIPMasq(ipt, ipn, lease); err != nil {
|
|
|
|
|
|
+ teardownIPTables(ipt, rules)
|
|
|
|
+ if err = setupIPTables(ipt, rules); err != nil {
|
|
return fmt.Errorf("Error setting up rules: %v", err)
|
|
return fmt.Errorf("Error setting up rules: %v", err)
|
|
}
|
|
}
|
|
return nil
|
|
return nil
|
|
}
|
|
}
|
|
|
|
|
|
-func setupIPMasq(ipt IPTablesRules, ipn ip.IP4Net, lease *subnet.Lease) error {
|
|
|
|
- for _, rule := range rules(ipn, lease) {
|
|
|
|
- log.Info("Adding iptables rule: ", strings.Join(rule, " "))
|
|
|
|
- err := ipt.AppendUnique("nat", "POSTROUTING", rule...)
|
|
|
|
|
|
+func setupIPTables(ipt IPTables, rules []IPTablesRule) error {
|
|
|
|
+ for _, rule := range rules {
|
|
|
|
+ log.Info("Adding iptables rule: ", strings.Join(rule.rulespec, " "))
|
|
|
|
+ err := ipt.AppendUnique(rule.table, rule.chain, rule.rulespec...)
|
|
if err != nil {
|
|
if err != nil {
|
|
- return fmt.Errorf("failed to insert IP masquerade rule: %v", err)
|
|
|
|
|
|
+ return fmt.Errorf("failed to insert IPTables rule: %v", err)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
return nil
|
|
return nil
|
|
}
|
|
}
|
|
|
|
|
|
-func teardownIPMasq(ipt IPTablesRules, ipn ip.IP4Net, lease *subnet.Lease) {
|
|
|
|
- for _, rule := range rules(ipn, lease) {
|
|
|
|
- log.Info("Deleting iptables rule: ", strings.Join(rule, " "))
|
|
|
|
|
|
+func teardownIPTables(ipt IPTables, rules []IPTablesRule) {
|
|
|
|
+ for _, rule := range rules {
|
|
|
|
+ log.Info("Deleting iptables rule: ", strings.Join(rule.rulespec, " "))
|
|
// We ignore errors here because if there's an error it's almost certainly because the rule
|
|
// We ignore errors here because if there's an error it's almost certainly because the rule
|
|
// doesn't exist, which is fine (we don't need to delete rules that don't exist)
|
|
// doesn't exist, which is fine (we don't need to delete rules that don't exist)
|
|
- ipt.Delete("nat", "POSTROUTING", rule...)
|
|
|
|
|
|
+ ipt.Delete(rule.table, rule.chain, rule.rulespec...)
|
|
}
|
|
}
|
|
}
|
|
}
|