Skip to content

Commit

Permalink
add ability to remove iptables config
Browse files Browse the repository at this point in the history
Signed-off-by: Zahari Dichev <[email protected]>
  • Loading branch information
zaharidichev committed Apr 1, 2024
1 parent bb4604f commit 194719b
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 25 deletions.
88 changes: 81 additions & 7 deletions iptables/iptables.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,15 @@ const (

var (
// ExecutionTraceID provides a unique identifier for this script's execution.
ExecutionTraceID = strconv.Itoa(int(time.Now().Unix()))
executionTraceID = strconv.Itoa(int(time.Now().Unix()))

preroutingRuleRegex = regexp.MustCompile(`(?m)^-A PREROUTING (.+ )?-j PROXY_INIT_REDIRECT`)
outputRuleRegex = regexp.MustCompile(`(?m)^-A OUTPUT (.+ )?-j PROXY_INIT_OUTPUT`)
redirectChainRegex = regexp.MustCompile(`(?m)^:PROXY_INIT_REDIRECT `)
outputChainRegex = regexp.MustCompile(`(?m)^:PROXY_INIT_OUTPUT `)
)

// FirewallConfiguration specifies how to configure a pod's iptables.
// FirewallConfiguration specifies how to configure iptables.
type FirewallConfiguration struct {
Mode string
PortsToRedirectInbound []int
Expand All @@ -58,13 +58,14 @@ type FirewallConfiguration struct {
UseWaitFlag bool
BinPath string
SaveBinPath string
ContinueOnError bool
}

// ConfigureFirewall configures a pod's internal iptables to redirect all desired traffic through the proxy, allowing for
// the pod to join the service mesh. A lot of this logic was based on
// ConfigureFirewall configures iptables to redirect all desired traffic through the proxy, allowing for
// the workload to join the service mesh. A lot of this logic was based on
// https://github.com/istio/istio/blob/e83411e/pilot/docker/prepare_proxy.sh
func ConfigureFirewall(firewallConfiguration FirewallConfiguration) error {
log.Debugf("tracing script execution as [%s]", ExecutionTraceID)
log.Debugf("tracing script execution as [%s]", executionTraceID)
log.Debugf("using '%s' to set-up firewall rules", firewallConfiguration.BinPath)
log.Debugf("using '%s' to list all available rules", firewallConfiguration.SaveBinPath)

Expand All @@ -90,7 +91,44 @@ func ConfigureFirewall(firewallConfiguration FirewallConfiguration) error {
}

if _, err := executeCommand(firewallConfiguration, cmd); err != nil {
return err
if !firewallConfiguration.ContinueOnError {
return err
}

log.Debugf("continuing despite error: %s", err)
}
}

_, _ = executeCommand(firewallConfiguration, firewallConfiguration.makeShowAllRules())

return nil
}

// CleanupFirewallConfig removed the iptables rules that have been added as a result of
// calling ConfigureFirewall.
func CleanupFirewallConfig(firewallConfiguration FirewallConfiguration) error {
log.Debugf("tracing script execution as [%s]", executionTraceID)
log.Debugf("using '%s' to clean-up firewall rules", firewallConfiguration.BinPath)
log.Debugf("using '%s' to list all available rules", firewallConfiguration.SaveBinPath)

commands := make([]*exec.Cmd, 0)
commands = firewallConfiguration.cleanupRules(commands)

if firewallConfiguration.UseWaitFlag {
log.Debug("'useWaitFlag' set: iptables will wait for xtables to become available")
}

for _, cmd := range commands {
if firewallConfiguration.UseWaitFlag {
cmd.Args = append(cmd.Args, "-w")
}

if _, err := executeCommand(firewallConfiguration, cmd); err != nil {
if !firewallConfiguration.ContinueOnError {
return err
}

log.Debugf("continuing despite error: %s", err)
}
}

Expand All @@ -99,10 +137,40 @@ func ConfigureFirewall(firewallConfiguration FirewallConfiguration) error {
return nil
}

func (fc FirewallConfiguration) cleanupRules(commands []*exec.Cmd) []*exec.Cmd {
// delete ref from prerouting
commands = append(
commands,
fc.makeJumpFromChainToAnotherForAllProtocols(
IptablesPreroutingChainName,
redirectChainName,
"install-proxy-init-prerouting",
true))

// delete ref from output
commands = append(
commands,
fc.makeJumpFromChainToAnotherForAllProtocols(
IptablesOutputChainName,
outputChainName,
"install-proxy-init-output",
true))

// flush chains
commands = append(commands, fc.makeFlushChain(outputChainName))
commands = append(commands, fc.makeFlushChain(redirectChainName))

// delete chains
commands = append(commands, fc.makeDeleteChain(outputChainName))
commands = append(commands, fc.makeDeleteChain(redirectChainName))

return commands
}

// formatComment is used to format iptables comments in such way that it is possible to identify when the rules were added.
// This helps debug when iptables has some stale rules from previous runs, something that can happen frequently on minikube.
func formatComment(text string) string {
return fmt.Sprintf("proxy-init/%s/%s", text, ExecutionTraceID)
return fmt.Sprintf("proxy-init/%s", text)
}

func (fc FirewallConfiguration) addOutgoingTrafficRules(existingRules []byte, commands []*exec.Cmd) []*exec.Cmd {
Expand Down Expand Up @@ -270,6 +338,12 @@ func (fc FirewallConfiguration) makeFlushChain(name string) *exec.Cmd {
"-F", name)
}

func (fc FirewallConfiguration) makeDeleteChain(name string) *exec.Cmd {
return exec.Command(fc.BinPath,
"-t", "nat",
"-X", name)
}

func (fc FirewallConfiguration) makeCreateNewChain(name string) *exec.Cmd {
return exec.Command(fc.BinPath,
"-t", "nat",
Expand Down
1 change: 0 additions & 1 deletion iptables/iptables_cleaner.go

This file was deleted.

50 changes: 33 additions & 17 deletions iptables/iptables_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,16 @@ var existingRules = []byte(`# iptables-save
:POSTROUTING ACCEPT [0:0]
:PROXY_INIT_OUTPUT - [0:0]
:PROXY_INIT_REDIRECT - [0:0]
-A PREROUTING -m comment --comment "proxy-init/install-proxy-init-prerouting/testExecutionTraceID" -j PROXY_INIT_REDIRECT
-A OUTPUT -m comment --comment "proxy-init/install-proxy-init-output/testExecutionTraceID" -j PROXY_INIT_OUTPUT
-A PROXY_INIT_OUTPUT -o lo -m comment --comment "proxy-init/ignore-loopback/testExecutionTraceID" -j RETURN
-A PROXY_INIT_OUTPUT -p tcp -m comment --comment "proxy-init/redirect-all-outgoing-to-proxy-port/testExecutionTraceID" -j REDIRECT --to-ports 1234
-A PROXY_INIT_REDIRECT -p tcp -m multiport --dports 1234 -m comment --comment "proxy-init/ignore-port-1234/testExecutionTraceID" -j RETURN
-A PREROUTING -m comment --comment "proxy-init/install-proxy-init-prerouting" -j PROXY_INIT_REDIRECT
-A OUTPUT -m comment --comment "proxy-init/install-proxy-init-output" -j PROXY_INIT_OUTPUT
-A PROXY_INIT_OUTPUT -o lo -m comment --comment "proxy-init/ignore-loopback" -j RETURN
-A PROXY_INIT_OUTPUT -p tcp -m comment --comment "proxy-init/redirect-all-outgoing-to-proxy-port" -j REDIRECT --to-ports 1234
-A PROXY_INIT_REDIRECT -p tcp -m multiport --dports 1234 -m comment --comment "proxy-init/ignore-port-1234" -j RETURN
COMMIT
# Completed on Fri Jan 6 23:00:00 2023
`)

func TestAddIncomingTrafficRules(t *testing.T) {
ExecutionTraceID = "testExecutionTraceID"

for _, tt := range []struct {
name string
existingRules []byte
Expand All @@ -53,16 +51,16 @@ func TestAddIncomingTrafficRules(t *testing.T) {
name: "no existing rules, create new chain and PREROUTING rule",
wantCommands: []*exec.Cmd{
exec.Command("<iptables>", "-t", "nat", "-N", "PROXY_INIT_REDIRECT"),
exec.Command("<iptables>", "-t", "nat", "-A", "PROXY_INIT_REDIRECT", "-p", "tcp", "--match", "multiport", "--dports", "1234", "-j", "RETURN", "-m", "comment", "--comment", "proxy-init/ignore-port-1234/testExecutionTraceID"),
exec.Command("<iptables>", "-t", "nat", "-A", "PREROUTING", "-j", "PROXY_INIT_REDIRECT", "-m", "comment", "--comment", "proxy-init/install-proxy-init-prerouting/testExecutionTraceID"),
exec.Command("<iptables>", "-t", "nat", "-A", "PROXY_INIT_REDIRECT", "-p", "tcp", "--match", "multiport", "--dports", "1234", "-j", "RETURN", "-m", "comment", "--comment", "proxy-init/ignore-port-1234"),
exec.Command("<iptables>", "-t", "nat", "-A", "PREROUTING", "-j", "PROXY_INIT_REDIRECT", "-m", "comment", "--comment", "proxy-init/install-proxy-init-prerouting"),
},
},
{
name: "existing rules, flush existing chain and reuse PREROUTING rule",
existingRules: existingRules,
wantCommands: []*exec.Cmd{
exec.Command("<iptables>", "-t", "nat", "-F", "PROXY_INIT_REDIRECT"),
exec.Command("<iptables>", "-t", "nat", "-A", "PROXY_INIT_REDIRECT", "-p", "tcp", "--match", "multiport", "--dports", "1234", "-j", "RETURN", "-m", "comment", "--comment", "proxy-init/ignore-port-1234/testExecutionTraceID"),
exec.Command("<iptables>", "-t", "nat", "-A", "PROXY_INIT_REDIRECT", "-p", "tcp", "--match", "multiport", "--dports", "1234", "-j", "RETURN", "-m", "comment", "--comment", "proxy-init/ignore-port-1234"),
},
},
} {
Expand All @@ -78,8 +76,6 @@ func TestAddIncomingTrafficRules(t *testing.T) {
}

func TestAddOutgoingTrafficRules(t *testing.T) {
ExecutionTraceID = "testExecutionTraceID"

for _, tt := range []struct {
name string
existingRules []byte
Expand All @@ -89,18 +85,18 @@ func TestAddOutgoingTrafficRules(t *testing.T) {
name: "no existing rules, create new chain and OUTPUT rule",
wantCommands: []*exec.Cmd{
exec.Command("<iptables>", "-t", "nat", "-N", "PROXY_INIT_OUTPUT"),
exec.Command("<iptables>", "-t", "nat", "-A", "PROXY_INIT_OUTPUT", "-o", "lo", "-j", "RETURN", "-m", "comment", "--comment", "proxy-init/ignore-loopback/testExecutionTraceID"),
exec.Command("<iptables>", "-t", "nat", "-A", "PROXY_INIT_OUTPUT", "-p", "tcp", "-j", "REDIRECT", "--to-port", "1234", "-m", "comment", "--comment", "proxy-init/redirect-all-outgoing-to-proxy-port/testExecutionTraceID"),
exec.Command("<iptables>", "-t", "nat", "-A", "OUTPUT", "-j", "PROXY_INIT_OUTPUT", "-m", "comment", "--comment", "proxy-init/install-proxy-init-output/testExecutionTraceID"),
exec.Command("<iptables>", "-t", "nat", "-A", "PROXY_INIT_OUTPUT", "-o", "lo", "-j", "RETURN", "-m", "comment", "--comment", "proxy-init/ignore-loopback"),
exec.Command("<iptables>", "-t", "nat", "-A", "PROXY_INIT_OUTPUT", "-p", "tcp", "-j", "REDIRECT", "--to-port", "1234", "-m", "comment", "--comment", "proxy-init/redirect-all-outgoing-to-proxy-port"),
exec.Command("<iptables>", "-t", "nat", "-A", "OUTPUT", "-j", "PROXY_INIT_OUTPUT", "-m", "comment", "--comment", "proxy-init/install-proxy-init-output"),
},
},
{
name: "existing rules, flush existing chain and reuse OUTPUT rule",
existingRules: existingRules,
wantCommands: []*exec.Cmd{
exec.Command("<iptables>", "-t", "nat", "-F", "PROXY_INIT_OUTPUT"),
exec.Command("<iptables>", "-t", "nat", "-A", "PROXY_INIT_OUTPUT", "-o", "lo", "-j", "RETURN", "-m", "comment", "--comment", "proxy-init/ignore-loopback/testExecutionTraceID"),
exec.Command("<iptables>", "-t", "nat", "-A", "PROXY_INIT_OUTPUT", "-p", "tcp", "-j", "REDIRECT", "--to-port", "1234", "-m", "comment", "--comment", "proxy-init/redirect-all-outgoing-to-proxy-port/testExecutionTraceID"),
exec.Command("<iptables>", "-t", "nat", "-A", "PROXY_INIT_OUTPUT", "-o", "lo", "-j", "RETURN", "-m", "comment", "--comment", "proxy-init/ignore-loopback"),
exec.Command("<iptables>", "-t", "nat", "-A", "PROXY_INIT_OUTPUT", "-p", "tcp", "-j", "REDIRECT", "--to-port", "1234", "-m", "comment", "--comment", "proxy-init/redirect-all-outgoing-to-proxy-port"),
},
},
} {
Expand All @@ -113,6 +109,26 @@ func TestAddOutgoingTrafficRules(t *testing.T) {
assertEqual(t, cmds, tt.wantCommands)
})
}

}

func TestCleanupFirewallConfig(t *testing.T) {
wantCommands := []*exec.Cmd{
exec.Command("<iptables>", "-t", "nat", "-D", "PREROUTING", "-j", "PROXY_INIT_REDIRECT", "-m", "comment", "--comment", "proxy-init/install-proxy-init-prerouting"),
exec.Command("<iptables>", "-t", "nat", "-D", "OUTPUT", "-j", "PROXY_INIT_OUTPUT", "-m", "comment", "--comment", "proxy-init/install-proxy-init-output"),
exec.Command("<iptables>", "-t", "nat", "-F", "PROXY_INIT_OUTPUT"),
exec.Command("<iptables>", "-t", "nat", "-F", "PROXY_INIT_REDIRECT"),
exec.Command("<iptables>", "-t", "nat", "-X", "PROXY_INIT_OUTPUT"),
exec.Command("<iptables>", "-t", "nat", "-X", "PROXY_INIT_REDIRECT"),
}

fc := &FirewallConfiguration{
BinPath: "<iptables>",
InboundPortsToIgnore: []string{"1234"},
}
cmds := fc.cleanupRules(nil)
assertEqual(t, cmds, wantCommands)

}

func assertEqual(t *testing.T, check, expected interface{}) {
Expand Down

0 comments on commit 194719b

Please sign in to comment.