1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
package network
import (
"fmt"
"strings"
logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
"github.com/coreos/go-iptables/iptables"
)
var log = logf.Log.WithName("network")
type IPTables interface {
AppendUnique(table string, chain string, rulespec ...string) error
Delete(table string, chain string, rulespec ...string) error
Exists(table string, chain string, rulespec ...string) (bool, error)
}
type IPTablesRule struct {
table string
chain string
rulespec []string
}
func MasqRules(ifname string) []IPTablesRule {
return []IPTablesRule{
// This rule makes sure ifname is SNAT
{"nat", "POSTROUTING", []string{"-o", ifname, "-j", "MASQUERADE"}},
}
}
func ForwardRules(ovnNetwork string) []IPTablesRule {
return []IPTablesRule{
// These rules allow traffic to be forwarded if it is to or from the ovn network range.
{"filter", "FORWARD", []string{"-s", ovnNetwork, "-j", "ACCEPT"}},
{"filter", "FORWARD", []string{"-d", ovnNetwork, "-j", "ACCEPT"}},
}
}
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 {
// this shouldn't ever happen
return false, fmt.Errorf("failed to check rule existence: %v", err)
}
if !exists {
return false, nil
}
}
return true, nil
}
func SetupAndEnsureIPTables(rules []IPTablesRule) error {
ipt, err := iptables.New()
if err != nil {
// if we can't find iptables, give up and return
log.Error(err, "Failed to setup IPTables. iptables binary was not found")
return err
}
// Ensure that all the iptables rules exist every 5 seconds
if err := ensureIPTables(ipt, rules); err != nil {
log.Error(err, "Failed to ensure iptables rules")
return err
}
return nil
}
// DeleteIPTables delete specified iptables rules
func DeleteIPTables(rules []IPTablesRule) error {
ipt, err := iptables.New()
if err != nil {
// if we can't find iptables, give up and return
log.Error(err, "Failed to setup IPTables. iptables binary was not found")
return err
}
teardownIPTables(ipt, rules)
return nil
}
func ensureIPTables(ipt IPTables, rules []IPTablesRule) error {
exists, err := ipTablesRulesExist(ipt, rules)
if err != nil {
return fmt.Errorf("Error checking rule existence: %v", err)
}
if exists {
// if all the rules already exist, no need to do anything
return nil
}
// Otherwise, teardown all the rules and set them up again
// We do this because the order of the rules is important
log.Info("Some iptables rules are missing; deleting and recreating rules")
teardownIPTables(ipt, rules)
if err = setupIPTables(ipt, rules); err != nil {
return fmt.Errorf("Error setting up rules: %v", err)
}
return nil
}
func setupIPTables(ipt IPTables, rules []IPTablesRule) error {
for _, rule := range rules {
log.Info("Adding iptables rule: ", "rule", strings.Join(rule.rulespec, " "))
err := ipt.AppendUnique(rule.table, rule.chain, rule.rulespec...)
if err != nil {
return fmt.Errorf("failed to insert IPTables rule: %v", err)
}
}
return nil
}
func teardownIPTables(ipt IPTables, rules []IPTablesRule) {
for _, rule := range rules {
log.Info("Deleting iptables rule: ", "rule", strings.Join(rule.rulespec, " "))
// 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)
ipt.Delete(rule.table, rule.chain, rule.rulespec...)
}
}
|