Skip to content

Commit 61a8d25

Browse files
committed
Expose ip tables package (#361)
- enable the use iptables as a library - adda functionality to remove already configured rules. Signed-off-by: Zahari Dichev <[email protected]>
1 parent 21dce30 commit 61a8d25

File tree

11 files changed

+125
-36
lines changed

11 files changed

+125
-36
lines changed

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ FROM --platform=$BUILDPLATFORM golang:1.21-alpine as go
99
WORKDIR /build
1010
COPY --link go.mod go.sum .
1111
COPY --link ./proxy-init ./proxy-init
12-
COPY --link ./internal ./internal
12+
COPY --link ./pkg ./pkg
1313
RUN go mod download
1414
ARG TARGETARCH
1515
RUN CGO_ENABLED=0 GOOS=linux GOARCH=$TARGETARCH GO111MODULE=on \

Dockerfile-cni-plugin

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ WORKDIR /build
66
COPY --link go.mod go.sum ./
77
COPY --link ./cni-plugin ./cni-plugin
88
COPY --link ./proxy-init ./proxy-init
9-
COPY --link ./internal ./internal
9+
COPY --link ./pkg ./pkg
1010
RUN go mod download
1111
ARG TARGETARCH
1212
RUN CGO_ENABLED=0 GOOS=linux GOARCH=$TARGETARCH GO111MODULE=on \

cni-plugin/integration/Dockerfile-tester

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ ENV GOCACHE=/tmp/
1414
WORKDIR /src
1515
COPY --link go.mod go.sum .
1616
COPY --link cni-plugin cni-plugin
17-
COPY --link internal internal
17+
COPY --link pkg pkg
1818
COPY --link proxy-init proxy-init
1919
RUN go mod tidy && go mod download

cni-plugin/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import (
3030
"github.com/containernetworking/cni/pkg/types"
3131
cniv1 "github.com/containernetworking/cni/pkg/types/100"
3232
"github.com/containernetworking/cni/pkg/version"
33-
"github.com/linkerd/linkerd2-proxy-init/internal/iptables"
33+
"github.com/linkerd/linkerd2-proxy-init/pkg/iptables"
3434
"github.com/linkerd/linkerd2-proxy-init/proxy-init/cmd"
3535

3636
"github.com/sirupsen/logrus"

justfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ proxy-init-lint *flags:
111111
# Run proxy-init unit tests
112112
proxy-init-test-unit:
113113
go test -v ./proxy-init/...
114-
go test -v ./internal/...
114+
go test -v ./pkg/...
115115

116116
# Run proxy-init integration tests after preparing dependencies
117117
proxy-init-test-integration: proxy-init-test-integration-deps proxy-init-test-integration-run
@@ -161,7 +161,7 @@ build-cni-plugin-test-image *args='--load':
161161

162162
##
163163
## CNI plugin integration
164-
##
164+
##
165165

166166

167167
# Run cni-plugin integration tests after preparing dependencies By default,

internal/iptables/iptables.go renamed to pkg/iptables/iptables.go

Lines changed: 83 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010

1111
log "github.com/sirupsen/logrus"
1212

13-
util "github.com/linkerd/linkerd2-proxy-init/internal/util"
13+
util "github.com/linkerd/linkerd2-proxy-init/pkg/util"
1414
)
1515

1616
const (
@@ -35,15 +35,15 @@ const (
3535

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

4040
preroutingRuleRegex = regexp.MustCompile(`(?m)^-A PREROUTING (.+ )?-j PROXY_INIT_REDIRECT`)
4141
outputRuleRegex = regexp.MustCompile(`(?m)^-A OUTPUT (.+ )?-j PROXY_INIT_OUTPUT`)
4242
redirectChainRegex = regexp.MustCompile(`(?m)^:PROXY_INIT_REDIRECT `)
4343
outputChainRegex = regexp.MustCompile(`(?m)^:PROXY_INIT_OUTPUT `)
4444
)
4545

46-
// FirewallConfiguration specifies how to configure a pod's iptables.
46+
// FirewallConfiguration specifies how to configure iptables.
4747
type FirewallConfiguration struct {
4848
Mode string
4949
PortsToRedirectInbound []int
@@ -58,13 +58,14 @@ type FirewallConfiguration struct {
5858
UseWaitFlag bool
5959
BinPath string
6060
SaveBinPath string
61+
ContinueOnError bool
6162
}
6263

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

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

9293
if _, err := executeCommand(firewallConfiguration, cmd); err != nil {
93-
return err
94+
if !firewallConfiguration.ContinueOnError {
95+
return err
96+
}
97+
98+
log.Debugf("continuing despite error: %s", err)
99+
}
100+
}
101+
102+
_, _ = executeCommand(firewallConfiguration, firewallConfiguration.makeShowAllRules())
103+
104+
return nil
105+
}
106+
107+
// CleanupFirewallConfig removes the iptables rules that have been added as a result of
108+
// calling ConfigureFirewall.
109+
func CleanupFirewallConfig(firewallConfiguration FirewallConfiguration) error {
110+
log.Debugf("tracing script execution as [%s]", executionTraceID)
111+
log.Debugf("using '%s' to clean-up firewall rules", firewallConfiguration.BinPath)
112+
log.Debugf("using '%s' to list all available rules", firewallConfiguration.SaveBinPath)
113+
114+
commands := make([]*exec.Cmd, 0)
115+
commands = firewallConfiguration.cleanupRules(commands)
116+
117+
if firewallConfiguration.UseWaitFlag {
118+
log.Debug("'useWaitFlag' set: iptables will wait for xtables to become available")
119+
}
120+
121+
for _, cmd := range commands {
122+
if firewallConfiguration.UseWaitFlag {
123+
cmd.Args = append(cmd.Args, "-w")
124+
}
125+
126+
if _, err := executeCommand(firewallConfiguration, cmd); err != nil {
127+
if !firewallConfiguration.ContinueOnError {
128+
return err
129+
}
130+
131+
log.Debugf("continuing despite error: %s", err)
94132
}
95133
}
96134

@@ -99,10 +137,39 @@ func ConfigureFirewall(firewallConfiguration FirewallConfiguration) error {
99137
return nil
100138
}
101139

102-
// formatComment is used to format iptables comments in such way that it is possible to identify when the rules were added.
103-
// This helps debug when iptables has some stale rules from previous runs, something that can happen frequently on minikube.
140+
func (fc FirewallConfiguration) cleanupRules(commands []*exec.Cmd) []*exec.Cmd {
141+
// delete ref from prerouting
142+
commands = append(
143+
commands,
144+
fc.makeJumpFromChainToAnotherForAllProtocols(
145+
IptablesPreroutingChainName,
146+
redirectChainName,
147+
"install-proxy-init-prerouting",
148+
true))
149+
150+
// delete ref from output
151+
commands = append(
152+
commands,
153+
fc.makeJumpFromChainToAnotherForAllProtocols(
154+
IptablesOutputChainName,
155+
outputChainName,
156+
"install-proxy-init-output",
157+
true))
158+
159+
// flush chains
160+
commands = append(commands, fc.makeFlushChain(outputChainName))
161+
commands = append(commands, fc.makeFlushChain(redirectChainName))
162+
163+
// delete chains
164+
commands = append(commands, fc.makeDeleteChain(outputChainName))
165+
commands = append(commands, fc.makeDeleteChain(redirectChainName))
166+
167+
return commands
168+
}
169+
170+
// formatComment is used to format iptables comments
104171
func formatComment(text string) string {
105-
return fmt.Sprintf("proxy-init/%s/%s", text, ExecutionTraceID)
172+
return fmt.Sprintf("proxy-init/%s", text)
106173
}
107174

108175
func (fc FirewallConfiguration) addOutgoingTrafficRules(existingRules []byte, commands []*exec.Cmd) []*exec.Cmd {
@@ -270,6 +337,12 @@ func (fc FirewallConfiguration) makeFlushChain(name string) *exec.Cmd {
270337
"-F", name)
271338
}
272339

340+
func (fc FirewallConfiguration) makeDeleteChain(name string) *exec.Cmd {
341+
return exec.Command(fc.BinPath,
342+
"-t", "nat",
343+
"-X", name)
344+
}
345+
273346
func (fc FirewallConfiguration) makeCreateNewChain(name string) *exec.Cmd {
274347
return exec.Command(fc.BinPath,
275348
"-t", "nat",

internal/iptables/iptables_test.go renamed to pkg/iptables/iptables_test.go

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,16 @@ var existingRules = []byte(`# iptables-save
3232
:POSTROUTING ACCEPT [0:0]
3333
:PROXY_INIT_OUTPUT - [0:0]
3434
:PROXY_INIT_REDIRECT - [0:0]
35-
-A PREROUTING -m comment --comment "proxy-init/install-proxy-init-prerouting/testExecutionTraceID" -j PROXY_INIT_REDIRECT
36-
-A OUTPUT -m comment --comment "proxy-init/install-proxy-init-output/testExecutionTraceID" -j PROXY_INIT_OUTPUT
37-
-A PROXY_INIT_OUTPUT -o lo -m comment --comment "proxy-init/ignore-loopback/testExecutionTraceID" -j RETURN
38-
-A PROXY_INIT_OUTPUT -p tcp -m comment --comment "proxy-init/redirect-all-outgoing-to-proxy-port/testExecutionTraceID" -j REDIRECT --to-ports 1234
39-
-A PROXY_INIT_REDIRECT -p tcp -m multiport --dports 1234 -m comment --comment "proxy-init/ignore-port-1234/testExecutionTraceID" -j RETURN
35+
-A PREROUTING -m comment --comment "proxy-init/install-proxy-init-prerouting" -j PROXY_INIT_REDIRECT
36+
-A OUTPUT -m comment --comment "proxy-init/install-proxy-init-output" -j PROXY_INIT_OUTPUT
37+
-A PROXY_INIT_OUTPUT -o lo -m comment --comment "proxy-init/ignore-loopback" -j RETURN
38+
-A PROXY_INIT_OUTPUT -p tcp -m comment --comment "proxy-init/redirect-all-outgoing-to-proxy-port" -j REDIRECT --to-ports 1234
39+
-A PROXY_INIT_REDIRECT -p tcp -m multiport --dports 1234 -m comment --comment "proxy-init/ignore-port-1234" -j RETURN
4040
COMMIT
4141
# Completed on Fri Jan 6 23:00:00 2023
4242
`)
4343

4444
func TestAddIncomingTrafficRules(t *testing.T) {
45-
ExecutionTraceID = "testExecutionTraceID"
46-
4745
for _, tt := range []struct {
4846
name string
4947
existingRules []byte
@@ -53,16 +51,16 @@ func TestAddIncomingTrafficRules(t *testing.T) {
5351
name: "no existing rules, create new chain and PREROUTING rule",
5452
wantCommands: []*exec.Cmd{
5553
exec.Command("<iptables>", "-t", "nat", "-N", "PROXY_INIT_REDIRECT"),
56-
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"),
57-
exec.Command("<iptables>", "-t", "nat", "-A", "PREROUTING", "-j", "PROXY_INIT_REDIRECT", "-m", "comment", "--comment", "proxy-init/install-proxy-init-prerouting/testExecutionTraceID"),
54+
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"),
55+
exec.Command("<iptables>", "-t", "nat", "-A", "PREROUTING", "-j", "PROXY_INIT_REDIRECT", "-m", "comment", "--comment", "proxy-init/install-proxy-init-prerouting"),
5856
},
5957
},
6058
{
6159
name: "existing rules, flush existing chain and reuse PREROUTING rule",
6260
existingRules: existingRules,
6361
wantCommands: []*exec.Cmd{
6462
exec.Command("<iptables>", "-t", "nat", "-F", "PROXY_INIT_REDIRECT"),
65-
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"),
63+
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"),
6664
},
6765
},
6866
} {
@@ -78,8 +76,6 @@ func TestAddIncomingTrafficRules(t *testing.T) {
7876
}
7977

8078
func TestAddOutgoingTrafficRules(t *testing.T) {
81-
ExecutionTraceID = "testExecutionTraceID"
82-
8379
for _, tt := range []struct {
8480
name string
8581
existingRules []byte
@@ -89,18 +85,18 @@ func TestAddOutgoingTrafficRules(t *testing.T) {
8985
name: "no existing rules, create new chain and OUTPUT rule",
9086
wantCommands: []*exec.Cmd{
9187
exec.Command("<iptables>", "-t", "nat", "-N", "PROXY_INIT_OUTPUT"),
92-
exec.Command("<iptables>", "-t", "nat", "-A", "PROXY_INIT_OUTPUT", "-o", "lo", "-j", "RETURN", "-m", "comment", "--comment", "proxy-init/ignore-loopback/testExecutionTraceID"),
93-
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"),
94-
exec.Command("<iptables>", "-t", "nat", "-A", "OUTPUT", "-j", "PROXY_INIT_OUTPUT", "-m", "comment", "--comment", "proxy-init/install-proxy-init-output/testExecutionTraceID"),
88+
exec.Command("<iptables>", "-t", "nat", "-A", "PROXY_INIT_OUTPUT", "-o", "lo", "-j", "RETURN", "-m", "comment", "--comment", "proxy-init/ignore-loopback"),
89+
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"),
90+
exec.Command("<iptables>", "-t", "nat", "-A", "OUTPUT", "-j", "PROXY_INIT_OUTPUT", "-m", "comment", "--comment", "proxy-init/install-proxy-init-output"),
9591
},
9692
},
9793
{
9894
name: "existing rules, flush existing chain and reuse OUTPUT rule",
9995
existingRules: existingRules,
10096
wantCommands: []*exec.Cmd{
10197
exec.Command("<iptables>", "-t", "nat", "-F", "PROXY_INIT_OUTPUT"),
102-
exec.Command("<iptables>", "-t", "nat", "-A", "PROXY_INIT_OUTPUT", "-o", "lo", "-j", "RETURN", "-m", "comment", "--comment", "proxy-init/ignore-loopback/testExecutionTraceID"),
103-
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"),
98+
exec.Command("<iptables>", "-t", "nat", "-A", "PROXY_INIT_OUTPUT", "-o", "lo", "-j", "RETURN", "-m", "comment", "--comment", "proxy-init/ignore-loopback"),
99+
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"),
104100
},
105101
},
106102
} {
@@ -113,6 +109,26 @@ func TestAddOutgoingTrafficRules(t *testing.T) {
113109
assertEqual(t, cmds, tt.wantCommands)
114110
})
115111
}
112+
113+
}
114+
115+
func TestCleanupFirewallConfig(t *testing.T) {
116+
wantCommands := []*exec.Cmd{
117+
exec.Command("<iptables>", "-t", "nat", "-D", "PREROUTING", "-j", "PROXY_INIT_REDIRECT", "-m", "comment", "--comment", "proxy-init/install-proxy-init-prerouting"),
118+
exec.Command("<iptables>", "-t", "nat", "-D", "OUTPUT", "-j", "PROXY_INIT_OUTPUT", "-m", "comment", "--comment", "proxy-init/install-proxy-init-output"),
119+
exec.Command("<iptables>", "-t", "nat", "-F", "PROXY_INIT_OUTPUT"),
120+
exec.Command("<iptables>", "-t", "nat", "-F", "PROXY_INIT_REDIRECT"),
121+
exec.Command("<iptables>", "-t", "nat", "-X", "PROXY_INIT_OUTPUT"),
122+
exec.Command("<iptables>", "-t", "nat", "-X", "PROXY_INIT_REDIRECT"),
123+
}
124+
125+
fc := &FirewallConfiguration{
126+
BinPath: "<iptables>",
127+
InboundPortsToIgnore: []string{"1234"},
128+
}
129+
cmds := fc.cleanupRules(nil)
130+
assertEqual(t, cmds, wantCommands)
131+
116132
}
117133

118134
func assertEqual(t *testing.T, check, expected interface{}) {
File renamed without changes.
File renamed without changes.

proxy-init/cmd/root.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ import (
99
log "github.com/sirupsen/logrus"
1010
"github.com/spf13/cobra"
1111

12-
"github.com/linkerd/linkerd2-proxy-init/internal/iptables"
13-
"github.com/linkerd/linkerd2-proxy-init/internal/util"
12+
"github.com/linkerd/linkerd2-proxy-init/pkg/iptables"
13+
"github.com/linkerd/linkerd2-proxy-init/pkg/util"
1414
)
1515

1616
// RootOptions provides the information that will be used to build a firewall configuration.

0 commit comments

Comments
 (0)