Merge 485e22e1b6
into b187f32407
This commit is contained in:
commit
ae7ba8247f
2
go.mod
2
go.mod
@ -7,7 +7,7 @@ require (
|
|||||||
github.com/campoy/embedmd v1.0.0
|
github.com/campoy/embedmd v1.0.0
|
||||||
github.com/containernetworking/cni v1.0.1
|
github.com/containernetworking/cni v1.0.1
|
||||||
github.com/containernetworking/plugins v1.1.1
|
github.com/containernetworking/plugins v1.1.1
|
||||||
github.com/coreos/go-iptables v0.6.0
|
github.com/coreos/go-iptables v0.6.1-0.20220901214115-d2b8608923d1
|
||||||
github.com/go-kit/kit v0.9.0
|
github.com/go-kit/kit v0.9.0
|
||||||
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348
|
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348
|
||||||
github.com/metalmatze/signal v0.0.0-20210307161603-1c9aa721a97a
|
github.com/metalmatze/signal v0.0.0-20210307161603-1c9aa721a97a
|
||||||
|
4
go.sum
4
go.sum
@ -106,8 +106,8 @@ github.com/containernetworking/plugins v1.1.1 h1:+AGfFigZ5TiQH00vhR8qPeSatj53eNG
|
|||||||
github.com/containernetworking/plugins v1.1.1/go.mod h1:Sr5TH/eBsGLXK/h71HeLfX19sZPp3ry5uHSkI4LPxV8=
|
github.com/containernetworking/plugins v1.1.1/go.mod h1:Sr5TH/eBsGLXK/h71HeLfX19sZPp3ry5uHSkI4LPxV8=
|
||||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||||
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||||
github.com/coreos/go-iptables v0.6.0 h1:is9qnZMPYjLd8LYqmm/qlE+wwEgJIkTYdhV3rfZo4jk=
|
github.com/coreos/go-iptables v0.6.1-0.20220901214115-d2b8608923d1 h1:zSiUKnogKeEwIIeUQP/WPH7m0BJ/IvW0VyL4muaauUY=
|
||||||
github.com/coreos/go-iptables v0.6.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q=
|
github.com/coreos/go-iptables v0.6.1-0.20220901214115-d2b8608923d1/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q=
|
||||||
github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
|
github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
|
||||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||||
|
@ -96,8 +96,8 @@ func (f *cilium) Init(_ int) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Rules is a no-op.
|
// Rules is a no-op.
|
||||||
func (f *cilium) Rules(_ []*net.IPNet) []iptables.Rule {
|
func (f *cilium) Rules(_ []*net.IPNet) iptables.RuleSet {
|
||||||
return nil
|
return iptables.RuleSet{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set is a no-op.
|
// Set is a no-op.
|
||||||
|
@ -49,7 +49,7 @@ type Encapsulator interface {
|
|||||||
Gw(net.IP, net.IP, *net.IPNet) net.IP
|
Gw(net.IP, net.IP, *net.IPNet) net.IP
|
||||||
Index() int
|
Index() int
|
||||||
Init(int) error
|
Init(int) error
|
||||||
Rules([]*net.IPNet) []iptables.Rule
|
Rules([]*net.IPNet) iptables.RuleSet
|
||||||
Set(*net.IPNet) error
|
Set(*net.IPNet) error
|
||||||
Strategy() Strategy
|
Strategy() Strategy
|
||||||
}
|
}
|
||||||
|
@ -95,8 +95,8 @@ func (f *flannel) Init(_ int) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Rules is a no-op.
|
// Rules is a no-op.
|
||||||
func (f *flannel) Rules(_ []*net.IPNet) []iptables.Rule {
|
func (f *flannel) Rules(_ []*net.IPNet) iptables.RuleSet {
|
||||||
return nil
|
return iptables.RuleSet{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set is a no-op.
|
// Set is a no-op.
|
||||||
|
@ -65,20 +65,20 @@ func (i *ipip) Init(base int) error {
|
|||||||
|
|
||||||
// Rules returns a set of iptables rules that are necessary
|
// Rules returns a set of iptables rules that are necessary
|
||||||
// when traffic between nodes must be encapsulated.
|
// when traffic between nodes must be encapsulated.
|
||||||
func (i *ipip) Rules(nodes []*net.IPNet) []iptables.Rule {
|
func (i *ipip) Rules(nodes []*net.IPNet) iptables.RuleSet {
|
||||||
var rules []iptables.Rule
|
rules := iptables.RuleSet{}
|
||||||
proto := ipipProtocolName()
|
proto := ipipProtocolName()
|
||||||
rules = append(rules, iptables.NewIPv4Chain("filter", "KILO-IPIP"))
|
rules.AddToAppend(iptables.NewIPv4Chain("filter", "KILO-IPIP"))
|
||||||
rules = append(rules, iptables.NewIPv6Chain("filter", "KILO-IPIP"))
|
rules.AddToAppend(iptables.NewIPv6Chain("filter", "KILO-IPIP"))
|
||||||
rules = append(rules, iptables.NewIPv4Rule("filter", "INPUT", "-p", proto, "-m", "comment", "--comment", "Kilo: jump to IPIP chain", "-j", "KILO-IPIP"))
|
rules.AddToAppend(iptables.NewIPv4Rule("filter", "INPUT", "-p", proto, "-m", "comment", "--comment", "Kilo: jump to IPIP chain", "-j", "KILO-IPIP"))
|
||||||
rules = append(rules, iptables.NewIPv6Rule("filter", "INPUT", "-p", proto, "-m", "comment", "--comment", "Kilo: jump to IPIP chain", "-j", "KILO-IPIP"))
|
rules.AddToAppend(iptables.NewIPv6Rule("filter", "INPUT", "-p", proto, "-m", "comment", "--comment", "Kilo: jump to IPIP chain", "-j", "KILO-IPIP"))
|
||||||
for _, n := range nodes {
|
for _, n := range nodes {
|
||||||
// Accept encapsulated traffic from peers.
|
// Accept encapsulated traffic from peers.
|
||||||
rules = append(rules, iptables.NewRule(iptables.GetProtocol(n.IP), "filter", "KILO-IPIP", "-s", n.String(), "-m", "comment", "--comment", "Kilo: allow IPIP traffic", "-j", "ACCEPT"))
|
rules.AddToPrepend(iptables.NewRule(iptables.GetProtocol(n.IP), "filter", "KILO-IPIP", "-s", n.String(), "-m", "comment", "--comment", "Kilo: allow IPIP traffic", "-j", "ACCEPT"))
|
||||||
}
|
}
|
||||||
// Drop all other IPIP traffic.
|
// Drop all other IPIP traffic.
|
||||||
rules = append(rules, iptables.NewIPv4Rule("filter", "INPUT", "-p", proto, "-m", "comment", "--comment", "Kilo: reject other IPIP traffic", "-j", "DROP"))
|
rules.AddToAppend(iptables.NewIPv4Rule("filter", "INPUT", "-p", proto, "-m", "comment", "--comment", "Kilo: reject other IPIP traffic", "-j", "DROP"))
|
||||||
rules = append(rules, iptables.NewIPv6Rule("filter", "INPUT", "-p", proto, "-m", "comment", "--comment", "Kilo: reject other IPIP traffic", "-j", "DROP"))
|
rules.AddToAppend(iptables.NewIPv6Rule("filter", "INPUT", "-p", proto, "-m", "comment", "--comment", "Kilo: reject other IPIP traffic", "-j", "DROP"))
|
||||||
|
|
||||||
return rules
|
return rules
|
||||||
}
|
}
|
||||||
|
@ -44,8 +44,8 @@ func (n Noop) Init(_ int) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Rules will also do nothing.
|
// Rules will also do nothing.
|
||||||
func (n Noop) Rules(_ []*net.IPNet) []iptables.Rule {
|
func (n Noop) Rules(_ []*net.IPNet) iptables.RuleSet {
|
||||||
return nil
|
return iptables.RuleSet{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set will also do nothing.
|
// Set will also do nothing.
|
||||||
|
@ -46,6 +46,24 @@ type fakeClient struct {
|
|||||||
|
|
||||||
var _ Client = &fakeClient{}
|
var _ Client = &fakeClient{}
|
||||||
|
|
||||||
|
func (f *fakeClient) InsertUnique(table, chain string, pos int, spec ...string) error {
|
||||||
|
atomic.AddUint64(&f.calls, 1)
|
||||||
|
exists, err := f.Exists(table, chain, spec...)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if exists {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
index := pos - 1 // iptables are 1-based
|
||||||
|
rule := &rule{table: table, chain: chain, spec: spec}
|
||||||
|
prefix := append([]Rule{}, f.storage[:index]...)
|
||||||
|
suffix := append([]Rule{}, f.storage[index:]...)
|
||||||
|
prefix = append(prefix, rule)
|
||||||
|
f.storage = append(prefix, suffix...)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (f *fakeClient) AppendUnique(table, chain string, spec ...string) error {
|
func (f *fakeClient) AppendUnique(table, chain string, spec ...string) error {
|
||||||
atomic.AddUint64(&f.calls, 1)
|
atomic.AddUint64(&f.calls, 1)
|
||||||
exists, err := f.Exists(table, chain, spec...)
|
exists, err := f.Exists(table, chain, spec...)
|
||||||
|
@ -46,6 +46,11 @@ func ipv6Disabled() (bool, error) {
|
|||||||
// Protocol represents an IP protocol.
|
// Protocol represents an IP protocol.
|
||||||
type Protocol byte
|
type Protocol byte
|
||||||
|
|
||||||
|
type RuleSet struct {
|
||||||
|
appendRules []Rule // Rules to append to the chain - order matters.
|
||||||
|
prependRules []Rule // Rules to prepend to the chain - order does not matter.
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// ProtocolIPv4 represents the IPv4 protocol.
|
// ProtocolIPv4 represents the IPv4 protocol.
|
||||||
ProtocolIPv4 Protocol = iota
|
ProtocolIPv4 Protocol = iota
|
||||||
@ -53,6 +58,21 @@ const (
|
|||||||
ProtocolIPv6
|
ProtocolIPv6
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (rs *RuleSet) AddToAppend(rule Rule) {
|
||||||
|
rs.appendRules = append(rs.appendRules, rule)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rs *RuleSet) AddToPrepend(rule Rule) {
|
||||||
|
rs.prependRules = append(rs.prependRules, rule)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rs *RuleSet) AppendRuleSet(other RuleSet) RuleSet {
|
||||||
|
return RuleSet{
|
||||||
|
appendRules: append(rs.appendRules, other.appendRules...),
|
||||||
|
prependRules: append(rs.prependRules, other.prependRules...),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// GetProtocol will return a protocol from the length of an IP address.
|
// GetProtocol will return a protocol from the length of an IP address.
|
||||||
func GetProtocol(ip net.IP) Protocol {
|
func GetProtocol(ip net.IP) Protocol {
|
||||||
if len(ip) == net.IPv4len || ip.To4() != nil {
|
if len(ip) == net.IPv4len || ip.To4() != nil {
|
||||||
@ -64,6 +84,7 @@ func GetProtocol(ip net.IP) Protocol {
|
|||||||
// Client represents any type that can administer iptables rules.
|
// Client represents any type that can administer iptables rules.
|
||||||
type Client interface {
|
type Client interface {
|
||||||
AppendUnique(table string, chain string, rule ...string) error
|
AppendUnique(table string, chain string, rule ...string) error
|
||||||
|
InsertUnique(table, chain string, pos int, rule ...string) error
|
||||||
Delete(table string, chain string, rule ...string) error
|
Delete(table string, chain string, rule ...string) error
|
||||||
Exists(table string, chain string, rule ...string) (bool, error)
|
Exists(table string, chain string, rule ...string) (bool, error)
|
||||||
List(table string, chain string) ([]string, error)
|
List(table string, chain string) ([]string, error)
|
||||||
@ -75,7 +96,8 @@ type Client interface {
|
|||||||
|
|
||||||
// Rule is an interface for interacting with iptables objects.
|
// Rule is an interface for interacting with iptables objects.
|
||||||
type Rule interface {
|
type Rule interface {
|
||||||
Add(Client) error
|
Append(Client) error
|
||||||
|
Prepend(Client) error
|
||||||
Delete(Client) error
|
Delete(Client) error
|
||||||
Exists(Client) (bool, error)
|
Exists(Client) (bool, error)
|
||||||
String() string
|
String() string
|
||||||
@ -106,7 +128,14 @@ func NewIPv6Rule(table, chain string, spec ...string) Rule {
|
|||||||
return &rule{table, chain, spec, ProtocolIPv6}
|
return &rule{table, chain, spec, ProtocolIPv6}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *rule) Add(client Client) error {
|
func (r *rule) Prepend(client Client) error {
|
||||||
|
if err := client.InsertUnique(r.table, r.chain, 1, r.spec...); err != nil {
|
||||||
|
return fmt.Errorf("failed to add iptables rule: %v", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *rule) Append(client Client) error {
|
||||||
if err := client.AppendUnique(r.table, r.chain, r.spec...); err != nil {
|
if err := client.AppendUnique(r.table, r.chain, r.spec...); err != nil {
|
||||||
return fmt.Errorf("failed to add iptables rule: %v", err)
|
return fmt.Errorf("failed to add iptables rule: %v", err)
|
||||||
}
|
}
|
||||||
@ -162,7 +191,11 @@ func NewIPv6Chain(table, name string) Rule {
|
|||||||
return &chain{table, name, ProtocolIPv6}
|
return &chain{table, name, ProtocolIPv6}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *chain) Add(client Client) error {
|
func (c *chain) Prepend(client Client) error {
|
||||||
|
return c.Append(client)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *chain) Append(client Client) error {
|
||||||
// Note: `ClearChain` creates a chain if it does not exist.
|
// Note: `ClearChain` creates a chain if it does not exist.
|
||||||
if err := client.ClearChain(c.table, c.chain); err != nil {
|
if err := client.ClearChain(c.table, c.chain); err != nil {
|
||||||
return fmt.Errorf("failed to add iptables chain: %v", err)
|
return fmt.Errorf("failed to add iptables chain: %v", err)
|
||||||
@ -224,7 +257,8 @@ type Controller struct {
|
|||||||
registerer prometheus.Registerer
|
registerer prometheus.Registerer
|
||||||
|
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
rules []Rule
|
appendRules []Rule
|
||||||
|
prependRules []Rule
|
||||||
subscribed bool
|
subscribed bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -333,14 +367,21 @@ func (c *Controller) reconcile() error {
|
|||||||
c.Lock()
|
c.Lock()
|
||||||
defer c.Unlock()
|
defer c.Unlock()
|
||||||
var rc ruleCache
|
var rc ruleCache
|
||||||
for i, r := range c.rules {
|
if err := c.reconcileAppendRules(rc); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return c.reconcilePrependRules(rc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Controller) reconcileAppendRules(rc ruleCache) error {
|
||||||
|
for i, r := range c.appendRules {
|
||||||
ok, err := rc.exists(c.client(r.Proto()), r)
|
ok, err := rc.exists(c.client(r.Proto()), r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to check if rule exists: %v", err)
|
return fmt.Errorf("failed to check if rule exists: %v", err)
|
||||||
}
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
level.Info(c.logger).Log("msg", fmt.Sprintf("applying %d iptables rules", len(c.rules)-i))
|
level.Info(c.logger).Log("msg", fmt.Sprintf("applying %d iptables rules", len(c.appendRules)-i))
|
||||||
if err := c.resetFromIndex(i, c.rules); err != nil {
|
if err := c.resetFromIndex(i, c.appendRules); err != nil {
|
||||||
return fmt.Errorf("failed to add rule: %v", err)
|
return fmt.Errorf("failed to add rule: %v", err)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
@ -349,6 +390,22 @@ func (c *Controller) reconcile() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Controller) reconcilePrependRules(rc ruleCache) error {
|
||||||
|
for _, r := range c.prependRules {
|
||||||
|
ok, err := rc.exists(c.client(r.Proto()), r)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to check if rule exists: %v", err)
|
||||||
|
}
|
||||||
|
if !ok {
|
||||||
|
level.Info(c.logger).Log("msg", "prepending iptables rule")
|
||||||
|
if err := r.Prepend(c.client(r.Proto())); err != nil {
|
||||||
|
return fmt.Errorf("failed to prepend rule: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// resetFromIndex re-adds all rules starting from the given index.
|
// resetFromIndex re-adds all rules starting from the given index.
|
||||||
func (c *Controller) resetFromIndex(i int, rules []Rule) error {
|
func (c *Controller) resetFromIndex(i int, rules []Rule) error {
|
||||||
if i >= len(rules) {
|
if i >= len(rules) {
|
||||||
@ -358,7 +415,7 @@ func (c *Controller) resetFromIndex(i int, rules []Rule) error {
|
|||||||
if err := rules[j].Delete(c.client(rules[j].Proto())); err != nil {
|
if err := rules[j].Delete(c.client(rules[j].Proto())); err != nil {
|
||||||
return fmt.Errorf("failed to delete rule: %v", err)
|
return fmt.Errorf("failed to delete rule: %v", err)
|
||||||
}
|
}
|
||||||
if err := rules[j].Add(c.client(rules[j].Proto())); err != nil {
|
if err := rules[j].Append(c.client(rules[j].Proto())); err != nil {
|
||||||
return fmt.Errorf("failed to add rule: %v", err)
|
return fmt.Errorf("failed to add rule: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -383,34 +440,87 @@ func (c *Controller) deleteFromIndex(i int, rules *[]Rule) error {
|
|||||||
|
|
||||||
// Set idempotently overwrites any iptables rules previously defined
|
// Set idempotently overwrites any iptables rules previously defined
|
||||||
// for the controller with the given set of rules.
|
// for the controller with the given set of rules.
|
||||||
func (c *Controller) Set(rules []Rule) error {
|
func (c *Controller) Set(rules RuleSet) error {
|
||||||
c.Lock()
|
c.Lock()
|
||||||
defer c.Unlock()
|
defer c.Unlock()
|
||||||
|
if err := c.setAppendRules(rules.appendRules); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return c.setPrependRules(rules.prependRules)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Controller) setAppendRules(appendRules []Rule) error {
|
||||||
var i int
|
var i int
|
||||||
for ; i < len(rules); i++ {
|
for ; i < len(appendRules); i++ {
|
||||||
if i < len(c.rules) {
|
if i < len(c.appendRules) {
|
||||||
if rules[i].String() != c.rules[i].String() {
|
if appendRules[i].String() != c.appendRules[i].String() {
|
||||||
if err := c.deleteFromIndex(i, &c.rules); err != nil {
|
if err := c.deleteFromIndex(i, &c.appendRules); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if i >= len(c.rules) {
|
if i >= len(c.appendRules) {
|
||||||
if err := rules[i].Add(c.client(rules[i].Proto())); err != nil {
|
if err := appendRules[i].Append(c.client(appendRules[i].Proto())); err != nil {
|
||||||
return fmt.Errorf("failed to add rule: %v", err)
|
return fmt.Errorf("failed to add rule: %v", err)
|
||||||
}
|
}
|
||||||
c.rules = append(c.rules, rules[i])
|
c.appendRules = append(c.appendRules, appendRules[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err := c.deleteFromIndex(i, &c.appendRules)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to delete rule: %v", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Controller) setPrependRules(prependRules []Rule) error {
|
||||||
|
for _, prependRule := range prependRules {
|
||||||
|
if !containsRule(c.prependRules, prependRule) {
|
||||||
|
if err := prependRule.Prepend(c.client(prependRule.Proto())); err != nil {
|
||||||
|
return fmt.Errorf("failed to add rule: %v", err)
|
||||||
}
|
}
|
||||||
return c.deleteFromIndex(i, &c.rules)
|
c.prependRules = append(c.prependRules, prependRule)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, existingRule := range c.prependRules {
|
||||||
|
if !containsRule(prependRules, existingRule) {
|
||||||
|
if err := existingRule.Delete(c.client(existingRule.Proto())); err != nil {
|
||||||
|
return fmt.Errorf("failed to delete rule: %v", err)
|
||||||
|
}
|
||||||
|
c.prependRules = removeRule(c.prependRules, existingRule)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func removeRule(rules []Rule, toRemove Rule) []Rule {
|
||||||
|
ret := make([]Rule, 0, len(rules))
|
||||||
|
for _, rule := range rules {
|
||||||
|
if rule.String() != toRemove.String() {
|
||||||
|
ret = append(ret, rule)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func containsRule(haystack []Rule, needle Rule) bool {
|
||||||
|
for _, element := range haystack {
|
||||||
|
if element.String() == needle.String() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// CleanUp will clean up any rules created by the controller.
|
// CleanUp will clean up any rules created by the controller.
|
||||||
func (c *Controller) CleanUp() error {
|
func (c *Controller) CleanUp() error {
|
||||||
c.Lock()
|
c.Lock()
|
||||||
defer c.Unlock()
|
defer c.Unlock()
|
||||||
return c.deleteFromIndex(0, &c.rules)
|
err := c.deleteFromIndex(0, &c.prependRules)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return c.deleteFromIndex(0, &c.appendRules)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) client(p Protocol) Client {
|
func (c *Controller) client(p Protocol) Client {
|
||||||
|
@ -18,16 +18,23 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
var rules = []Rule{
|
var appendRules = []Rule{
|
||||||
NewIPv4Rule("filter", "FORWARD", "-s", "10.4.0.0/16", "-j", "ACCEPT"),
|
NewIPv4Rule("filter", "FORWARD", "-s", "10.4.0.0/16", "-j", "ACCEPT"),
|
||||||
NewIPv4Rule("filter", "FORWARD", "-d", "10.4.0.0/16", "-j", "ACCEPT"),
|
NewIPv4Rule("filter", "FORWARD", "-d", "10.4.0.0/16", "-j", "ACCEPT"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var prependRules = []Rule{
|
||||||
|
NewIPv4Rule("filter", "FORWARD", "-s", "10.5.0.0/16", "-j", "DROP"),
|
||||||
|
NewIPv4Rule("filter", "FORWARD", "-s", "10.6.0.0/16", "-j", "DROP"),
|
||||||
|
}
|
||||||
|
|
||||||
func TestSet(t *testing.T) {
|
func TestSet(t *testing.T) {
|
||||||
for _, tc := range []struct {
|
for _, tc := range []struct {
|
||||||
name string
|
name string
|
||||||
sets [][]Rule
|
sets []RuleSet
|
||||||
out []Rule
|
appendOut []Rule
|
||||||
|
prependOut []Rule
|
||||||
|
storageOut []Rule
|
||||||
actions []func(Client) error
|
actions []func(Client) error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
@ -35,53 +42,70 @@ func TestSet(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "single",
|
name: "single",
|
||||||
sets: [][]Rule{
|
sets: []RuleSet{
|
||||||
{rules[0]},
|
{appendRules: []Rule{appendRules[0]}},
|
||||||
},
|
},
|
||||||
out: []Rule{rules[0]},
|
appendOut: []Rule{appendRules[0]},
|
||||||
|
storageOut: []Rule{appendRules[0]},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "two rules",
|
name: "two rules",
|
||||||
sets: [][]Rule{
|
sets: []RuleSet{
|
||||||
{rules[0], rules[1]},
|
{appendRules: []Rule{appendRules[0], appendRules[1]}},
|
||||||
},
|
},
|
||||||
out: []Rule{rules[0], rules[1]},
|
appendOut: []Rule{appendRules[0], appendRules[1]},
|
||||||
|
storageOut: []Rule{appendRules[0], appendRules[1]},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "multiple",
|
name: "multiple",
|
||||||
sets: [][]Rule{
|
sets: []RuleSet{
|
||||||
{rules[0], rules[1]},
|
{appendRules: []Rule{appendRules[0], appendRules[1]}},
|
||||||
{rules[1]},
|
{appendRules: []Rule{appendRules[1]}},
|
||||||
},
|
},
|
||||||
out: []Rule{rules[1]},
|
appendOut: []Rule{appendRules[1]},
|
||||||
|
storageOut: []Rule{appendRules[1]},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "re-add",
|
name: "re-add",
|
||||||
sets: [][]Rule{
|
sets: []RuleSet{
|
||||||
{rules[0], rules[1]},
|
{appendRules: []Rule{appendRules[0], appendRules[1]}},
|
||||||
},
|
},
|
||||||
out: []Rule{rules[0], rules[1]},
|
appendOut: []Rule{appendRules[0], appendRules[1]},
|
||||||
|
storageOut: []Rule{appendRules[0], appendRules[1]},
|
||||||
actions: []func(c Client) error{
|
actions: []func(c Client) error{
|
||||||
func(c Client) error {
|
func(c Client) error {
|
||||||
return rules[0].Delete(c)
|
return appendRules[0].Delete(c)
|
||||||
},
|
},
|
||||||
func(c Client) error {
|
func(c Client) error {
|
||||||
return rules[1].Delete(c)
|
return appendRules[1].Delete(c)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "order",
|
name: "order",
|
||||||
sets: [][]Rule{
|
sets: []RuleSet{
|
||||||
{rules[0], rules[1]},
|
{appendRules: []Rule{appendRules[0], appendRules[1]}},
|
||||||
},
|
},
|
||||||
out: []Rule{rules[0], rules[1]},
|
appendOut: []Rule{appendRules[0], appendRules[1]},
|
||||||
|
storageOut: []Rule{appendRules[0], appendRules[1]},
|
||||||
actions: []func(c Client) error{
|
actions: []func(c Client) error{
|
||||||
func(c Client) error {
|
func(c Client) error {
|
||||||
return rules[0].Delete(c)
|
return appendRules[0].Delete(c)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "append and prepend",
|
||||||
|
sets: []RuleSet{
|
||||||
|
{
|
||||||
|
prependRules: []Rule{prependRules[0], prependRules[1]},
|
||||||
|
appendRules: []Rule{appendRules[0], appendRules[1]},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
appendOut: []Rule{appendRules[0], appendRules[1]},
|
||||||
|
prependOut: []Rule{prependRules[0], prependRules[1]},
|
||||||
|
storageOut: []Rule{prependRules[1], prependRules[0], appendRules[0], appendRules[1]},
|
||||||
|
},
|
||||||
} {
|
} {
|
||||||
client := &fakeClient{}
|
client := &fakeClient{}
|
||||||
controller, err := New(WithClients(client, client))
|
controller, err := New(WithClients(client, client))
|
||||||
@ -90,7 +114,7 @@ func TestSet(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for i := range tc.sets {
|
for i := range tc.sets {
|
||||||
if err := controller.Set(tc.sets[i]); err != nil {
|
if err := controller.Set(tc.sets[i]); err != nil {
|
||||||
t.Fatalf("test case %q: got unexpected error seting rule set %d: %v", tc.name, i, err)
|
t.Fatalf("test case %q: got unexpected error setting rule set %d: %v", tc.name, i, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i, f := range tc.actions {
|
for i, f := range tc.actions {
|
||||||
@ -101,21 +125,30 @@ func TestSet(t *testing.T) {
|
|||||||
if err := controller.reconcile(); err != nil {
|
if err := controller.reconcile(); err != nil {
|
||||||
t.Fatalf("test case %q: got unexpected error %v", tc.name, err)
|
t.Fatalf("test case %q: got unexpected error %v", tc.name, err)
|
||||||
}
|
}
|
||||||
if len(tc.out) != len(client.storage) {
|
if len(tc.storageOut) != len(client.storage) {
|
||||||
t.Errorf("test case %q: expected %d rules in storage, got %d", tc.name, len(tc.out), len(client.storage))
|
t.Errorf("test case %q: expected %d rules in storage, got %d", tc.name, len(tc.storageOut), len(client.storage))
|
||||||
} else {
|
} else {
|
||||||
for i := range tc.out {
|
for i := range tc.storageOut {
|
||||||
if tc.out[i].String() != client.storage[i].String() {
|
if tc.storageOut[i].String() != client.storage[i].String() {
|
||||||
t.Errorf("test case %q: expected rule %d in storage to be equal: expected %v, got %v", tc.name, i, tc.out[i], client.storage[i])
|
t.Errorf("test case %q: expected rule %d in storage to be equal: expected %v, got %v", tc.name, i, tc.storageOut[i], client.storage[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(tc.out) != len(controller.rules) {
|
if len(tc.appendOut) != len(controller.appendRules) {
|
||||||
t.Errorf("test case %q: expected %d rules in controller, got %d", tc.name, len(tc.out), len(controller.rules))
|
t.Errorf("test case %q: expected %d appendRules in controller, got %d", tc.name, len(tc.appendOut), len(controller.appendRules))
|
||||||
} else {
|
} else {
|
||||||
for i := range tc.out {
|
for i := range tc.appendOut {
|
||||||
if tc.out[i].String() != controller.rules[i].String() {
|
if tc.appendOut[i].String() != controller.appendRules[i].String() {
|
||||||
t.Errorf("test case %q: expected rule %d in controller to be equal: expected %v, got %v", tc.name, i, tc.out[i], controller.rules[i])
|
t.Errorf("test case %q: expected appendRule %d in controller to be equal: expected %v, got %v", tc.name, i, tc.appendOut[i], controller.appendRules[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(tc.prependOut) != len(controller.prependRules) {
|
||||||
|
t.Errorf("test case %q: expected %d prependRules in controller, got %d", tc.name, len(tc.prependOut), len(controller.prependRules))
|
||||||
|
} else {
|
||||||
|
for i := range tc.prependOut {
|
||||||
|
if tc.prependOut[i].String() != controller.prependRules[i].String() {
|
||||||
|
t.Errorf("test case %q: expected prependRule %d in controller to be equal: expected %v, got %v", tc.name, i, tc.prependOut[i], controller.prependRules[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -125,19 +158,25 @@ func TestSet(t *testing.T) {
|
|||||||
func TestCleanUp(t *testing.T) {
|
func TestCleanUp(t *testing.T) {
|
||||||
for _, tc := range []struct {
|
for _, tc := range []struct {
|
||||||
name string
|
name string
|
||||||
rules []Rule
|
appendRules []Rule
|
||||||
|
prependRules []Rule
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "empty",
|
name: "empty",
|
||||||
rules: nil,
|
appendRules: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "single",
|
name: "single append",
|
||||||
rules: []Rule{rules[0]},
|
appendRules: []Rule{appendRules[0]},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "multiple",
|
name: "multiple append",
|
||||||
rules: []Rule{rules[0], rules[1]},
|
appendRules: []Rule{appendRules[0], appendRules[1]},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "multiple append and prepend",
|
||||||
|
appendRules: []Rule{appendRules[0], appendRules[1]},
|
||||||
|
prependRules: []Rule{prependRules[0], prependRules[1]},
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
client := &fakeClient{}
|
client := &fakeClient{}
|
||||||
@ -145,11 +184,12 @@ func TestCleanUp(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("test case %q: got unexpected error instantiating controller: %v", tc.name, err)
|
t.Fatalf("test case %q: got unexpected error instantiating controller: %v", tc.name, err)
|
||||||
}
|
}
|
||||||
if err := controller.Set(tc.rules); err != nil {
|
ruleSet := RuleSet{appendRules: tc.appendRules, prependRules: tc.prependRules}
|
||||||
|
if err := controller.Set(ruleSet); err != nil {
|
||||||
t.Fatalf("test case %q: Set should not fail: %v", tc.name, err)
|
t.Fatalf("test case %q: Set should not fail: %v", tc.name, err)
|
||||||
}
|
}
|
||||||
if len(client.storage) != len(tc.rules) {
|
if len(client.storage) != len(tc.appendRules)+len(tc.prependRules) {
|
||||||
t.Errorf("test case %q: expected %d rules in storage, got %d rules", tc.name, len(tc.rules), len(client.storage))
|
t.Errorf("test case %q: expected %d rules in storage, got %d rules", tc.name, len(ruleSet.appendRules)+len(ruleSet.prependRules), len(client.storage))
|
||||||
}
|
}
|
||||||
if err := controller.CleanUp(); err != nil {
|
if err := controller.CleanUp(); err != nil {
|
||||||
t.Errorf("test case %q: got unexpected error: %v", tc.name, err)
|
t.Errorf("test case %q: got unexpected error: %v", tc.name, err)
|
||||||
@ -159,3 +199,42 @@ func TestCleanUp(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestReconcile(t *testing.T) {
|
||||||
|
for _, tc := range []struct {
|
||||||
|
name string
|
||||||
|
appendRules []Rule
|
||||||
|
prependRules []Rule
|
||||||
|
storageOut []Rule
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "append and prepend rules",
|
||||||
|
appendRules: []Rule{appendRules[0], appendRules[1]},
|
||||||
|
prependRules: []Rule{prependRules[0], prependRules[1]},
|
||||||
|
storageOut: []Rule{prependRules[1], prependRules[0], appendRules[0], appendRules[1]},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
client := &fakeClient{}
|
||||||
|
controller, err := New(WithClients(client, client))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("test case %q: got unexpected error instantiating controller: %v", tc.name, err)
|
||||||
|
}
|
||||||
|
controller.appendRules = tc.appendRules
|
||||||
|
controller.prependRules = tc.prependRules
|
||||||
|
|
||||||
|
err = controller.reconcile()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("test case %q: unexpected error during reconcile: %v", tc.name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(tc.storageOut) != len(client.storage) {
|
||||||
|
t.Errorf("test case %q: expected %d rules in storage, got %d", tc.name, len(tc.storageOut), len(client.storage))
|
||||||
|
} else {
|
||||||
|
for i := range tc.storageOut {
|
||||||
|
if tc.storageOut[i].String() != client.storage[i].String() {
|
||||||
|
t.Errorf("test case %q: expected rule %d in storage to be equal: expected %v, got %v", tc.name, i, tc.storageOut[i], client.storage[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -51,6 +51,15 @@ func (m *metricsClientWrapper) AppendUnique(table string, chain string, rule ...
|
|||||||
return m.client.AppendUnique(table, chain, rule...)
|
return m.client.AppendUnique(table, chain, rule...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *metricsClientWrapper) InsertUnique(table, chain string, pos int, rule ...string) error {
|
||||||
|
m.operationCounter.With(prometheus.Labels{
|
||||||
|
"operation": "InsertUnique",
|
||||||
|
"table": table,
|
||||||
|
"chain": chain,
|
||||||
|
}).Inc()
|
||||||
|
return m.client.InsertUnique(table, chain, pos, rule...)
|
||||||
|
}
|
||||||
|
|
||||||
func (m *metricsClientWrapper) Delete(table string, chain string, rule ...string) error {
|
func (m *metricsClientWrapper) Delete(table string, chain string, rule ...string) error {
|
||||||
m.operationCounter.With(prometheus.Labels{
|
m.operationCounter.With(prometheus.Labels{
|
||||||
"operation": "Delete",
|
"operation": "Delete",
|
||||||
|
@ -29,21 +29,21 @@ func TestRuleCache(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "empty",
|
name: "empty",
|
||||||
rules: nil,
|
rules: nil,
|
||||||
check: []Rule{rules[0]},
|
check: []Rule{appendRules[0]},
|
||||||
out: []bool{false},
|
out: []bool{false},
|
||||||
calls: 1,
|
calls: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "single negative",
|
name: "single negative",
|
||||||
rules: []Rule{rules[1]},
|
rules: []Rule{appendRules[1]},
|
||||||
check: []Rule{rules[0]},
|
check: []Rule{appendRules[0]},
|
||||||
out: []bool{false},
|
out: []bool{false},
|
||||||
calls: 1,
|
calls: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "single positive",
|
name: "single positive",
|
||||||
rules: []Rule{rules[1]},
|
rules: []Rule{appendRules[1]},
|
||||||
check: []Rule{rules[1]},
|
check: []Rule{appendRules[1]},
|
||||||
out: []bool{true},
|
out: []bool{true},
|
||||||
calls: 1,
|
calls: 1,
|
||||||
},
|
},
|
||||||
@ -56,29 +56,29 @@ func TestRuleCache(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "rule on chain means chain exists",
|
name: "rule on chain means chain exists",
|
||||||
rules: []Rule{rules[0]},
|
rules: []Rule{appendRules[0]},
|
||||||
check: []Rule{rules[0], &chain{"filter", "FORWARD", ProtocolIPv4}},
|
check: []Rule{appendRules[0], &chain{"filter", "FORWARD", ProtocolIPv4}},
|
||||||
out: []bool{true, true},
|
out: []bool{true, true},
|
||||||
calls: 1,
|
calls: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "rule on chain does not mean table is fully populated",
|
name: "rule on chain does not mean table is fully populated",
|
||||||
rules: []Rule{rules[0], &chain{"filter", "INPUT", ProtocolIPv4}},
|
rules: []Rule{appendRules[0], &chain{"filter", "INPUT", ProtocolIPv4}},
|
||||||
check: []Rule{rules[0], &chain{"filter", "OUTPUT", ProtocolIPv4}, &chain{"filter", "INPUT", ProtocolIPv4}},
|
check: []Rule{appendRules[0], &chain{"filter", "OUTPUT", ProtocolIPv4}, &chain{"filter", "INPUT", ProtocolIPv4}},
|
||||||
out: []bool{true, false, true},
|
out: []bool{true, false, true},
|
||||||
calls: 2,
|
calls: 2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "multiple rules on chain",
|
name: "multiple rules on chain",
|
||||||
rules: []Rule{rules[0], rules[1]},
|
rules: []Rule{appendRules[0], appendRules[1]},
|
||||||
check: []Rule{rules[0], rules[1], &chain{"filter", "FORWARD", ProtocolIPv4}},
|
check: []Rule{appendRules[0], appendRules[1], &chain{"filter", "FORWARD", ProtocolIPv4}},
|
||||||
out: []bool{true, true, true},
|
out: []bool{true, true, true},
|
||||||
calls: 1,
|
calls: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "checking rule on chain does not mean chain exists",
|
name: "checking rule on chain does not mean chain exists",
|
||||||
rules: nil,
|
rules: nil,
|
||||||
check: []Rule{rules[0], &chain{"filter", "FORWARD", ProtocolIPv4}},
|
check: []Rule{appendRules[0], &chain{"filter", "FORWARD", ProtocolIPv4}},
|
||||||
out: []bool{false, false},
|
out: []bool{false, false},
|
||||||
calls: 2,
|
calls: 2,
|
||||||
},
|
},
|
||||||
@ -101,7 +101,8 @@ func TestRuleCache(t *testing.T) {
|
|||||||
client := &fakeClient{}
|
client := &fakeClient{}
|
||||||
controller.v4 = client
|
controller.v4 = client
|
||||||
controller.v6 = client
|
controller.v6 = client
|
||||||
if err := controller.Set(tc.rules); err != nil {
|
ruleSet := RuleSet{appendRules: tc.rules}
|
||||||
|
if err := controller.Set(ruleSet); err != nil {
|
||||||
t.Fatalf("test case %q: Set should not fail: %v", tc.name, err)
|
t.Fatalf("test case %q: Set should not fail: %v", tc.name, err)
|
||||||
}
|
}
|
||||||
// Reset the client's calls so we can examine how many times
|
// Reset the client's calls so we can examine how many times
|
||||||
|
@ -525,7 +525,8 @@ func (m *Mesh) applyTopology() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ipRules = append(m.enc.Rules(cidrs), ipRules...)
|
encIpRules := m.enc.Rules(cidrs)
|
||||||
|
ipRules = encIpRules.AppendRuleSet(ipRules)
|
||||||
|
|
||||||
// If we are handling local routes, ensure the local
|
// If we are handling local routes, ensure the local
|
||||||
// tunnel has an IP address.
|
// tunnel has an IP address.
|
||||||
|
@ -311,12 +311,12 @@ func encapsulateRoute(route *netlink.Route, encapsulate encapsulation.Strategy,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Rules returns the iptables rules required by the local node.
|
// Rules returns the iptables rules required by the local node.
|
||||||
func (t *Topology) Rules(cni, iptablesForwardRule bool) []iptables.Rule {
|
func (t *Topology) Rules(cni, iptablesForwardRule bool) iptables.RuleSet {
|
||||||
var rules []iptables.Rule
|
rules := iptables.RuleSet{}
|
||||||
rules = append(rules, iptables.NewIPv4Chain("nat", "KILO-NAT"))
|
rules.AddToAppend(iptables.NewIPv4Chain("nat", "KILO-NAT"))
|
||||||
rules = append(rules, iptables.NewIPv6Chain("nat", "KILO-NAT"))
|
rules.AddToAppend(iptables.NewIPv6Chain("nat", "KILO-NAT"))
|
||||||
if cni {
|
if cni {
|
||||||
rules = append(rules, iptables.NewRule(iptables.GetProtocol(t.subnet.IP), "nat", "POSTROUTING", "-s", t.subnet.String(), "-m", "comment", "--comment", "Kilo: jump to KILO-NAT chain", "-j", "KILO-NAT"))
|
rules.AddToPrepend(iptables.NewRule(iptables.GetProtocol(t.subnet.IP), "nat", "POSTROUTING", "-s", t.subnet.String(), "-m", "comment", "--comment", "Kilo: jump to KILO-NAT chain", "-j", "KILO-NAT"))
|
||||||
// Some linux distros or docker will set forward DROP in the filter table.
|
// Some linux distros or docker will set forward DROP in the filter table.
|
||||||
// To still be able to have pod to pod communication we need to ALLOW packets from and to pod CIDRs within a location.
|
// To still be able to have pod to pod communication we need to ALLOW packets from and to pod CIDRs within a location.
|
||||||
// Leader nodes will forward packets from all nodes within a location because they act as a gateway for them.
|
// Leader nodes will forward packets from all nodes within a location because they act as a gateway for them.
|
||||||
@ -326,52 +326,48 @@ func (t *Topology) Rules(cni, iptablesForwardRule bool) []iptables.Rule {
|
|||||||
if s.location == t.location {
|
if s.location == t.location {
|
||||||
// Make sure packets to and from pod cidrs are not dropped in the forward chain.
|
// Make sure packets to and from pod cidrs are not dropped in the forward chain.
|
||||||
for _, c := range s.cidrs {
|
for _, c := range s.cidrs {
|
||||||
rules = append(rules, iptables.NewRule(iptables.GetProtocol(c.IP), "filter", "FORWARD", "-m", "comment", "--comment", "Kilo: forward packets from the pod subnet", "-s", c.String(), "-j", "ACCEPT"))
|
rules.AddToPrepend(iptables.NewRule(iptables.GetProtocol(c.IP), "filter", "FORWARD", "-m", "comment", "--comment", "Kilo: forward packets from the pod subnet", "-s", c.String(), "-j", "ACCEPT"))
|
||||||
rules = append(rules, iptables.NewRule(iptables.GetProtocol(c.IP), "filter", "FORWARD", "-m", "comment", "--comment", "Kilo: forward packets to the pod subnet", "-d", c.String(), "-j", "ACCEPT"))
|
rules.AddToPrepend(iptables.NewRule(iptables.GetProtocol(c.IP), "filter", "FORWARD", "-m", "comment", "--comment", "Kilo: forward packets to the pod subnet", "-d", c.String(), "-j", "ACCEPT"))
|
||||||
}
|
}
|
||||||
// Make sure packets to and from allowed location IPs are not dropped in the forward chain.
|
// Make sure packets to and from allowed location IPs are not dropped in the forward chain.
|
||||||
for _, c := range s.allowedLocationIPs {
|
for _, c := range s.allowedLocationIPs {
|
||||||
rules = append(rules, iptables.NewRule(iptables.GetProtocol(c.IP), "filter", "FORWARD", "-m", "comment", "--comment", "Kilo: forward packets from allowed location IPs", "-s", c.String(), "-j", "ACCEPT"))
|
rules.AddToPrepend(iptables.NewRule(iptables.GetProtocol(c.IP), "filter", "FORWARD", "-m", "comment", "--comment", "Kilo: forward packets from allowed location IPs", "-s", c.String(), "-j", "ACCEPT"))
|
||||||
rules = append(rules, iptables.NewRule(iptables.GetProtocol(c.IP), "filter", "FORWARD", "-m", "comment", "--comment", "Kilo: forward packets to allowed location IPs", "-d", c.String(), "-j", "ACCEPT"))
|
rules.AddToPrepend(iptables.NewRule(iptables.GetProtocol(c.IP), "filter", "FORWARD", "-m", "comment", "--comment", "Kilo: forward packets to allowed location IPs", "-d", c.String(), "-j", "ACCEPT"))
|
||||||
}
|
}
|
||||||
// Make sure packets to and from private IPs are not dropped in the forward chain.
|
// Make sure packets to and from private IPs are not dropped in the forward chain.
|
||||||
for _, c := range s.privateIPs {
|
for _, c := range s.privateIPs {
|
||||||
rules = append(rules, iptables.NewRule(iptables.GetProtocol(c), "filter", "FORWARD", "-m", "comment", "--comment", "Kilo: forward packets from private IPs", "-s", oneAddressCIDR(c).String(), "-j", "ACCEPT"))
|
rules.AddToPrepend(iptables.NewRule(iptables.GetProtocol(c), "filter", "FORWARD", "-m", "comment", "--comment", "Kilo: forward packets from private IPs", "-s", oneAddressCIDR(c).String(), "-j", "ACCEPT"))
|
||||||
rules = append(rules, iptables.NewRule(iptables.GetProtocol(c), "filter", "FORWARD", "-m", "comment", "--comment", "Kilo: forward packets to private IPs", "-d", oneAddressCIDR(c).String(), "-j", "ACCEPT"))
|
rules.AddToPrepend(iptables.NewRule(iptables.GetProtocol(c), "filter", "FORWARD", "-m", "comment", "--comment", "Kilo: forward packets to private IPs", "-d", oneAddressCIDR(c).String(), "-j", "ACCEPT"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if iptablesForwardRule {
|
} else if iptablesForwardRule {
|
||||||
rules = append(rules, iptables.NewRule(iptables.GetProtocol(t.subnet.IP), "filter", "FORWARD", "-m", "comment", "--comment", "Kilo: forward packets from the node's pod subnet", "-s", t.subnet.String(), "-j", "ACCEPT"))
|
rules.AddToPrepend(iptables.NewRule(iptables.GetProtocol(t.subnet.IP), "filter", "FORWARD", "-m", "comment", "--comment", "Kilo: forward packets from the node's pod subnet", "-s", t.subnet.String(), "-j", "ACCEPT"))
|
||||||
rules = append(rules, iptables.NewRule(iptables.GetProtocol(t.subnet.IP), "filter", "FORWARD", "-m", "comment", "--comment", "Kilo: forward packets to the node's pod subnet", "-d", t.subnet.String(), "-j", "ACCEPT"))
|
rules.AddToPrepend(iptables.NewRule(iptables.GetProtocol(t.subnet.IP), "filter", "FORWARD", "-m", "comment", "--comment", "Kilo: forward packets to the node's pod subnet", "-d", t.subnet.String(), "-j", "ACCEPT"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, s := range t.segments {
|
for _, s := range t.segments {
|
||||||
rules = append(rules, iptables.NewRule(iptables.GetProtocol(s.wireGuardIP), "nat", "KILO-NAT", "-d", oneAddressCIDR(s.wireGuardIP).String(), "-m", "comment", "--comment", "Kilo: do not NAT packets destined for WireGuared IPs", "-j", "RETURN"))
|
rules.AddToPrepend(iptables.NewRule(iptables.GetProtocol(s.wireGuardIP), "nat", "KILO-NAT", "-d", oneAddressCIDR(s.wireGuardIP).String(), "-m", "comment", "--comment", "Kilo: do not NAT packets destined for WireGuared IPs", "-j", "RETURN"))
|
||||||
for _, aip := range s.allowedIPs {
|
for _, aip := range s.allowedIPs {
|
||||||
rules = append(rules, iptables.NewRule(iptables.GetProtocol(aip.IP), "nat", "KILO-NAT", "-d", aip.String(), "-m", "comment", "--comment", "Kilo: do not NAT packets destined for known IPs", "-j", "RETURN"))
|
rules.AddToPrepend(iptables.NewRule(iptables.GetProtocol(aip.IP), "nat", "KILO-NAT", "-d", aip.String(), "-m", "comment", "--comment", "Kilo: do not NAT packets destined for known IPs", "-j", "RETURN"))
|
||||||
}
|
}
|
||||||
// Make sure packets to allowed location IPs go through the KILO-NAT chain, so they can be MASQUERADEd,
|
// Make sure packets to allowed location IPs go through the KILO-NAT chain, so they can be MASQUERADEd,
|
||||||
// Otherwise packets to these destinations will reach the destination, but never find their way back.
|
// Otherwise packets to these destinations will reach the destination, but never find their way back.
|
||||||
// We only want to NAT in locations of the corresponding allowed location IPs.
|
// We only want to NAT in locations of the corresponding allowed location IPs.
|
||||||
if t.location == s.location {
|
if t.location == s.location {
|
||||||
for _, alip := range s.allowedLocationIPs {
|
for _, alip := range s.allowedLocationIPs {
|
||||||
rules = append(rules,
|
rules.AddToPrepend(iptables.NewRule(iptables.GetProtocol(alip.IP), "nat", "POSTROUTING", "-d", alip.String(), "-m", "comment", "--comment", "Kilo: jump to NAT chain", "-j", "KILO-NAT"))
|
||||||
iptables.NewRule(iptables.GetProtocol(alip.IP), "nat", "POSTROUTING", "-d", alip.String(), "-m", "comment", "--comment", "Kilo: jump to NAT chain", "-j", "KILO-NAT"),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, p := range t.peers {
|
for _, p := range t.peers {
|
||||||
for _, aip := range p.AllowedIPs {
|
for _, aip := range p.AllowedIPs {
|
||||||
rules = append(rules,
|
rules.AddToPrepend(iptables.NewRule(iptables.GetProtocol(aip.IP), "nat", "POSTROUTING", "-s", aip.String(), "-m", "comment", "--comment", "Kilo: jump to NAT chain", "-j", "KILO-NAT"))
|
||||||
iptables.NewRule(iptables.GetProtocol(aip.IP), "nat", "POSTROUTING", "-s", aip.String(), "-m", "comment", "--comment", "Kilo: jump to NAT chain", "-j", "KILO-NAT"),
|
rules.AddToPrepend(iptables.NewRule(iptables.GetProtocol(aip.IP), "nat", "KILO-NAT", "-d", aip.String(), "-m", "comment", "--comment", "Kilo: do not NAT packets destined for peers", "-j", "RETURN"))
|
||||||
iptables.NewRule(iptables.GetProtocol(aip.IP), "nat", "KILO-NAT", "-d", aip.String(), "-m", "comment", "--comment", "Kilo: do not NAT packets destined for peers", "-j", "RETURN"),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rules = append(rules, iptables.NewIPv4Rule("nat", "KILO-NAT", "-m", "comment", "--comment", "Kilo: NAT remaining packets", "-j", "MASQUERADE"))
|
rules.AddToAppend(iptables.NewIPv4Rule("nat", "KILO-NAT", "-m", "comment", "--comment", "Kilo: NAT remaining packets", "-j", "MASQUERADE"))
|
||||||
rules = append(rules, iptables.NewIPv6Rule("nat", "KILO-NAT", "-m", "comment", "--comment", "Kilo: NAT remaining packets", "-j", "MASQUERADE"))
|
rules.AddToAppend(iptables.NewIPv6Rule("nat", "KILO-NAT", "-m", "comment", "--comment", "Kilo: NAT remaining packets", "-j", "MASQUERADE"))
|
||||||
return rules
|
return rules
|
||||||
}
|
}
|
||||||
|
|
||||||
|
29
vendor/github.com/coreos/go-iptables/iptables/iptables.go
generated
vendored
29
vendor/github.com/coreos/go-iptables/iptables/iptables.go
generated
vendored
@ -109,6 +109,7 @@ func Timeout(timeout int) option {
|
|||||||
// For backwards compatibility, by default always uses IPv4 and timeout 0.
|
// For backwards compatibility, by default always uses IPv4 and timeout 0.
|
||||||
// i.e. you can create an IPv6 IPTables using a timeout of 5 seconds passing
|
// i.e. you can create an IPv6 IPTables using a timeout of 5 seconds passing
|
||||||
// the IPFamily and Timeout options as follow:
|
// the IPFamily and Timeout options as follow:
|
||||||
|
//
|
||||||
// ip6t := New(IPFamily(ProtocolIPv6), Timeout(5))
|
// ip6t := New(IPFamily(ProtocolIPv6), Timeout(5))
|
||||||
func New(opts ...option) (*IPTables, error) {
|
func New(opts ...option) (*IPTables, error) {
|
||||||
|
|
||||||
@ -185,6 +186,20 @@ func (ipt *IPTables) Insert(table, chain string, pos int, rulespec ...string) er
|
|||||||
return ipt.run(cmd...)
|
return ipt.run(cmd...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// InsertUnique acts like Insert except that it won't insert a duplicate (no matter the position in the chain)
|
||||||
|
func (ipt *IPTables) InsertUnique(table, chain string, pos int, rulespec ...string) error {
|
||||||
|
exists, err := ipt.Exists(table, chain, rulespec...)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !exists {
|
||||||
|
return ipt.Insert(table, chain, pos, rulespec...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Append appends rulespec to specified table/chain
|
// Append appends rulespec to specified table/chain
|
||||||
func (ipt *IPTables) Append(table, chain string, rulespec ...string) error {
|
func (ipt *IPTables) Append(table, chain string, rulespec ...string) error {
|
||||||
cmd := append([]string{"-t", table, "-A", chain}, rulespec...)
|
cmd := append([]string{"-t", table, "-A", chain}, rulespec...)
|
||||||
@ -219,6 +234,16 @@ func (ipt *IPTables) DeleteIfExists(table, chain string, rulespec ...string) err
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// List rules in specified table/chain
|
||||||
|
func (ipt *IPTables) ListById(table, chain string, id int) (string, error) {
|
||||||
|
args := []string{"-t", table, "-S", chain, strconv.Itoa(id)}
|
||||||
|
rule, err := ipt.executeList(args)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return rule[0], nil
|
||||||
|
}
|
||||||
|
|
||||||
// List rules in specified table/chain
|
// List rules in specified table/chain
|
||||||
func (ipt *IPTables) List(table, chain string) ([]string, error) {
|
func (ipt *IPTables) List(table, chain string) ([]string, error) {
|
||||||
args := []string{"-t", table, "-S", chain}
|
args := []string{"-t", table, "-S", chain}
|
||||||
@ -510,7 +535,9 @@ func (ipt *IPTables) runWithOutput(args []string, stdout io.Writer) error {
|
|||||||
syscall.Close(fmu.fd)
|
syscall.Close(fmu.fd)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer ul.Unlock()
|
defer func() {
|
||||||
|
_ = ul.Unlock()
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
var stderr bytes.Buffer
|
var stderr bytes.Buffer
|
||||||
|
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
@ -39,7 +39,7 @@ github.com/containernetworking/plugins/pkg/ns
|
|||||||
github.com/containernetworking/plugins/pkg/utils/sysctl
|
github.com/containernetworking/plugins/pkg/utils/sysctl
|
||||||
github.com/containernetworking/plugins/plugins/ipam/host-local/backend
|
github.com/containernetworking/plugins/plugins/ipam/host-local/backend
|
||||||
github.com/containernetworking/plugins/plugins/ipam/host-local/backend/allocator
|
github.com/containernetworking/plugins/plugins/ipam/host-local/backend/allocator
|
||||||
# github.com/coreos/go-iptables v0.6.0
|
# github.com/coreos/go-iptables v0.6.1-0.20220901214115-d2b8608923d1
|
||||||
## explicit; go 1.16
|
## explicit; go 1.16
|
||||||
github.com/coreos/go-iptables/iptables
|
github.com/coreos/go-iptables/iptables
|
||||||
# github.com/davecgh/go-spew v1.1.1
|
# github.com/davecgh/go-spew v1.1.1
|
||||||
|
Loading…
Reference in New Issue
Block a user