Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Guarantee the order of rules. #411

Closed
wants to merge 24 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
6679391
Refactoring.
lostcharlie Sep 11, 2023
fc43fe6
Refactoring.
lostcharlie Sep 11, 2023
1b8d794
Refactoring. Extract functions from iptables.go of connector and clou…
lostcharlie Sep 12, 2023
e04f8b2
Refactoring. Ensure FabEdge foward rules.
lostcharlie Sep 13, 2023
a47bbeb
iptables_helper: Replace usage for maintaining forward rules.
lostcharlie Sep 13, 2023
03ad0f3
iptables-helper: Switch to iptables-helper.
lostcharlie Sep 15, 2023
fd86d37
iptables-helper: Add locks to guarantee the order of rules.
lostcharlie Sep 15, 2023
a5bc7bf
Merge branch 'FabEdge:main' into iptables-helper
lostcharlie Sep 20, 2023
389308b
iptables-helper: Refactoring. Remove usage of go-iptables in other mo…
lostcharlie Sep 20, 2023
27a370c
iptables-helper: Use iptables-restore to maintain rules.
lostcharlie Sep 20, 2023
e891a90
iptables-helper: Switch to new iptables-helper in connector.
lostcharlie Sep 21, 2023
06acfb6
iptables-helper: Switch to new iptables-helper in agent.
lostcharlie Sep 21, 2023
e7a8820
iptables-helper: Clean up. Remove depndency of coreos/go-iptables.
lostcharlie Sep 21, 2023
7b33e85
Merge branch 'FabEdge:main' into iptables-helper
lostcharlie Sep 21, 2023
7e4d42b
iptables-helper: Refactoring. Move functions and constants.
lostcharlie Sep 22, 2023
9c948d4
Merge from fabedge:main
lostcharlie Sep 22, 2023
6e04cbb
iptables-helper: Add unit tests.
lostcharlie Sep 22, 2023
24a5272
iptables-helper: Add function to append rules instead of replacing.
lostcharlie Oct 7, 2023
5d5837d
Improve the way to maintain iptables rules
yanjianbo1983 Oct 7, 2023
583d3d3
Merge from fabedge:main.
lostcharlie Oct 11, 2023
7c2084c
Merge from yanjianbo1983:improve-iptables
lostcharlie Oct 11, 2023
ec67f1b
iptables-helper: Refactoring. Extract and move constants.
lostcharlie Oct 11, 2023
207cc90
iptables-helper: Use template based iptables-helper in cloud-agent.
lostcharlie Oct 12, 2023
50f886d
iptables-helper: Use template based iptables-helper in agent.
lostcharlie Oct 12, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 0 additions & 13 deletions pkg/agent/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (
"time"

debpkg "github.com/bep/debounce"
"github.com/coreos/go-iptables/iptables"
"github.com/spf13/pflag"
"k8s.io/klog/v2/klogr"
"k8s.io/utils/exec"
Expand Down Expand Up @@ -174,21 +173,9 @@ func (cfg Config) Manager() (*Manager, error) {
return nil, err
}

ipt, err := iptables.New()
if err != nil {
return nil, err
}

ipt6, err := iptables.NewWithProtocol(iptables.ProtocolIPv6)
if err != nil {
return nil, err
}

m := &Manager{
Config: cfg,
tm: tm,
ipt4: ipt,
ipt6: ipt6,
log: klogr.New().WithName("manager"),

events: make(chan struct{}),
Expand Down
166 changes: 63 additions & 103 deletions pkg/agent/iptables.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,34 +15,85 @@
package agent

import (
"fmt"
"strings"

"github.com/coreos/go-iptables/iptables"
"k8s.io/apimachinery/pkg/util/sets"

"github.com/fabedge/fabedge/pkg/util/ipset"
"github.com/fabedge/fabedge/pkg/util/iptables"
)

type IPSet struct {
IPSet *ipset.IPSet
EntrySet sets.String
}

var jumpChains = []iptables.JumpChain{
{Table: iptables.TableFilter, SrcChain: iptables.ChainForward, DstChain: iptables.ChainFabEdgeForward, Position: iptables.Append},
{Table: iptables.TableNat, SrcChain: iptables.ChainPostRouting, DstChain: iptables.ChainFabEdgeNatOutgoing, Position: iptables.Prepend},
}

func buildRuleData(ipsetName string, subnets []string) []byte {
var builder strings.Builder
builder.WriteString(`
*filter
:FABEDGE-FORWARD - [0:0]

`)

for _, subnet := range subnets {
builder.WriteString("-A FABEDGE-FORWARD -s ")
builder.WriteString(subnet)
builder.WriteString(" -j ACCEPT\n")

builder.WriteString("-A FABEDGE-FORWARD -d ")
builder.WriteString(subnet)
builder.WriteString(" -j ACCEPT\n")
}

builder.WriteString(`COMMIT

*nat
:FABEDGE-NAT-OUTGOING - [0:0]

`)

for _, subnet := range subnets {
builder.WriteString("-A FABEDGE-NAT-OUTGOING -s ")
builder.WriteString(subnet)
builder.WriteString(" -m set --match-set ")
builder.WriteString(ipsetName)
builder.WriteString(" dst -j RETURN\n")

builder.WriteString("-A FABEDGE-NAT-OUTGOING -s ")
builder.WriteString(subnet)
builder.WriteString(" -d ")
builder.WriteString(subnet)
builder.WriteString(" -j RETURN\n")

builder.WriteString("-A FABEDGE-NAT-OUTGOING -s ")
builder.WriteString(subnet)
builder.WriteString(" -j MASQUERADE\n")
}

builder.WriteString("COMMIT\n")

return []byte(builder.String())
}

func (m *Manager) ensureIPTablesRules() error {
current := m.getCurrentEndpoint()

peerIPSet4, peerIPSet6 := m.getAllPeerCIDRs()
subnetsIP4, subnetsIP6 := classifySubnets(current.Subnets)

configs := []struct {
ipt *iptables.IPTables
peerIPSet IPSet
loopbackIPSet IPSet
subnets []string
helper iptables.ApplierCleaner
}{
{
ipt: m.ipt4,
peerIPSet: IPSet{
IPSet: &ipset.IPSet{
Name: IPSetFabEdgePeerCIDR,
Expand All @@ -52,9 +103,9 @@ func (m *Manager) ensureIPTablesRules() error {
EntrySet: peerIPSet4,
},
subnets: subnetsIP4,
helper: iptables.NewApplierCleaner(iptables.ProtocolIPv4, jumpChains, buildRuleData(IPSetFabEdgePeerCIDR, subnetsIP4)),
},
{
ipt: m.ipt6,
peerIPSet: IPSet{
IPSet: &ipset.IPSet{
Name: IPSetFabEdgePeerCIDR6,
Expand All @@ -64,98 +115,20 @@ func (m *Manager) ensureIPTablesRules() error {
EntrySet: peerIPSet6,
},
subnets: subnetsIP6,
helper: iptables.NewApplierCleaner(iptables.ProtocolIPv6, jumpChains, buildRuleData(IPSetFabEdgePeerCIDR6, subnetsIP6)),
},
}

clearOutgoingChain := !m.areSubnetsEqual(current.Subnets, m.lastSubnets)
for _, c := range configs {
if err := m.ensureIPForwardRules(c.ipt, c.subnets); err != nil {
return err
}

if m.MASQOutgoing {
if err := m.configureOutboundRules(c.ipt, c.peerIPSet, c.subnets, clearOutgoingChain); err != nil {
return err
}
}
}
// must be done after configureOutboundRules are executed
m.lastSubnets = current.Subnets

return nil
}

func (m *Manager) ensureIPForwardRules(ipt *iptables.IPTables, subnets []string) error {
if err := ensureChain(ipt, TableFilter, ChainFabEdgeForward); err != nil {
m.log.Error(err, "failed to check or create iptables chain", "table", TableFilter, "chain", ChainFabEdgeForward)
return err
}

ensureRule := ipt.AppendUnique
if err := ensureRule(TableFilter, ChainForward, "-j", ChainFabEdgeForward); err != nil {
m.log.Error(err, "failed to check or add rule", "table", TableFilter, "chain", ChainForward, "rule", "-j FABEDGE")
return err
}

// subnets won't change most of the time, and is append-only, so for now we don't need
// to handle removing old subnet
for _, subnet := range subnets {
if err := ensureRule(TableFilter, ChainFabEdgeForward, "-s", subnet, "-j", "ACCEPT"); err != nil {
m.log.Error(err, "failed to check or add rule", "table", TableFilter, "chain", ChainFabEdgeForward, "rule", fmt.Sprintf("-s %s -j ACCEPT", subnet))
return err
}

if err := ensureRule(TableFilter, ChainFabEdgeForward, "-d", subnet, "-j", "ACCEPT"); err != nil {
m.log.Error(err, "failed to check or add rule", "table", TableFilter, "chain", ChainFabEdgeForward, "rule", fmt.Sprintf("-d %s -j ACCEPT", subnet))
return err
}
}

return nil
}

// outbound NAT from pods to outside the cluster
func (m *Manager) configureOutboundRules(ipt *iptables.IPTables, peerIPSet IPSet, subnets []string, clearFabEdgeNatOutgoingChain bool) error {
if clearFabEdgeNatOutgoingChain {
m.log.V(3).Info("Subnets are changed, clear iptables chain FABEDGE-NAT-OUTGOING")
if err := ipt.ClearChain(TableNat, ChainFabEdgeNatOutgoing); err != nil {
m.log.Error(err, "failed to check or add rule", "table", TableNat, "chain", ChainFabEdgeNatOutgoing)
return err
}
} else {
if err := ensureChain(ipt, TableNat, ChainFabEdgeNatOutgoing); err != nil {
m.log.Error(err, "failed to check or add rule", "table", TableNat, "chain", ChainFabEdgeNatOutgoing)
if err := m.ipset.EnsureIPSet(c.peerIPSet.IPSet, c.peerIPSet.EntrySet); err != nil {
m.log.Error(err, "failed to sync ipset", "ipsetName", c.peerIPSet.IPSet.Name)
return err
}
}

if err := m.ipset.EnsureIPSet(peerIPSet.IPSet, peerIPSet.EntrySet); err != nil {
m.log.Error(err, "failed to sync ipset", "ipsetName", peerIPSet.IPSet.Name)
return err
}

for _, subnet := range subnets {
m.log.V(3).Info("configure outgoing NAT iptables rules")

ensureRule := ipt.AppendUnique
if err := ensureRule(TableNat, ChainFabEdgeNatOutgoing, "-s", subnet, "-m", "set", "--match-set", peerIPSet.IPSet.Name, "dst", "-j", "RETURN"); err != nil {
m.log.Error(err, "failed to append rule", "table", TableNat, "chain", ChainFabEdgeNatOutgoing, "rule", fmt.Sprintf("-s %s -m set --match-set %s dst -j RETURN", subnet, peerIPSet.IPSet.Name))
continue
}

if err := ensureRule(TableNat, ChainFabEdgeNatOutgoing, "-s", subnet, "-d", subnet, "-j", "RETURN"); err != nil {
m.log.Error(err, "failed to append rule", "table", TableNat, "chain", ChainFabEdgeNatOutgoing, "rule", fmt.Sprintf("-s %s -d %s -j RETURN", subnet, subnet))
continue
}

if err := ensureRule(TableNat, ChainFabEdgeNatOutgoing, "-s", subnet, "-j", ChainMasquerade); err != nil {
m.log.Error(err, "failed to append rule", "table", TableNat, "chain", ChainFabEdgeNatOutgoing, "rule", fmt.Sprintf("-s %s -j %s", subnet, ChainMasquerade))
continue
}

if err := ensureRule(TableNat, ChainPostRouting, "-j", ChainFabEdgeNatOutgoing); err != nil {
m.log.Error(err, "failed to append rule", "table", TableNat, "chain", ChainPostRouting, "rule", fmt.Sprintf("-j %s", ChainFabEdgeNatOutgoing))
continue
if err := c.helper.Apply(); err != nil {
m.log.Error(err, "failed to sync iptables rules")
} else {
m.log.V(5).Info("iptables rules is synced")
}
}

Expand All @@ -176,19 +149,6 @@ func (m *Manager) areSubnetsEqual(sa1, sa2 []string) bool {
return true
}

func ensureChain(ipt *iptables.IPTables, table, chain string) error {
exists, err := ipt.ChainExists(table, chain)
if err != nil {
return err
}

if exists {
return nil
}

return ipt.NewChain(table, chain)
}

func (m *Manager) getAllPeerCIDRs() (cidrSet4, cidrSet6 sets.String) {
cidrSet4, cidrSet6 = sets.NewString(), sets.NewString()

Expand Down
18 changes: 4 additions & 14 deletions pkg/agent/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import (
"sync"
"time"

"github.com/coreos/go-iptables/iptables"
"github.com/go-logr/logr"
"k8s.io/apimachinery/pkg/util/sets"

Expand All @@ -37,15 +36,8 @@ import (
)

const (
TableFilter = "filter"
TableNat = "nat"
ChainForward = "FORWARD"
ChainPostRouting = "POSTROUTING"
ChainMasquerade = "MASQUERADE"
ChainFabEdgeForward = "FABEDGE-FORWARD"
ChainFabEdgeNatOutgoing = "FABEDGE-NAT-OUTGOING"
IPSetFabEdgePeerCIDR = "FABEDGE-PEER-CIDR"
IPSetFabEdgePeerCIDR6 = "FABEDGE-PEER-CIDR6"
IPSetFabEdgePeerCIDR = "FABEDGE-PEER-CIDR"
IPSetFabEdgePeerCIDR6 = "FABEDGE-PEER-CIDR6"
)

type Manager struct {
Expand All @@ -54,10 +46,8 @@ type Manager struct {
ipvs ipvs.Interface
ipset ipset.Interface

tm tunnel.Manager
ipt4 *iptables.IPTables
ipt6 *iptables.IPTables
log logr.Logger
tm tunnel.Manager
log logr.Logger

currentEndpoint Endpoint
mediatorEndpoint *Endpoint
Expand Down
20 changes: 8 additions & 12 deletions pkg/cloud-agent/cloud_agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (
"time"

"github.com/bep/debounce"
"github.com/coreos/go-iptables/iptables"
flag "github.com/spf13/pflag"
"github.com/vishvananda/netlink"
utilerrors "k8s.io/apimachinery/pkg/util/errors"
Expand Down Expand Up @@ -108,15 +107,8 @@ func Execute() {
}

func NewCloudAgent() (*CloudAgent, error) {
iph, err := newIptableHandler(iptables.ProtocolIPv4)
if err != nil {
return nil, err
}

iph6, err := newIptableHandler(iptables.ProtocolIPv6)
if err != nil {
return nil, err
}
iph, _ := newIptableHandler()
iph6, _ := newIp6tableHandler()

if iph == nil && iph6 == nil {
return nil, fmt.Errorf("at lease one iptablesHandler is required")
Expand Down Expand Up @@ -147,10 +139,14 @@ func (a *CloudAgent) addAndSaveRoutes(cp routing.ConnectorPrefixes) {
}

routes := a.syncRoutes(cp.LocalPrefixes, cp.RemotePrefixes)

routes = append(routes, a.syncRoutes(cp.LocalPrefixes6, cp.RemotePrefixes6)...)

whitelist := sets.NewString(cp.RemotePrefixes...)
whitelist.Insert(cp.RemotePrefixes6...)
whitelist := sets.NewString()
for _, route := range routes {
whitelist.Insert(route.Dst.String())
}

if err := routeutil.PurgeStrongSwanRoutes(routeutil.NewDstWhitelist(whitelist)); err != nil {
logger.Error(err, "failed to purge stale routes in strongswan table")
}
Expand Down
Loading
Loading