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

Expose ip tables package #361

Merged
merged 4 commits into from
Apr 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ FROM --platform=$BUILDPLATFORM golang:1.22-alpine as go
WORKDIR /build
COPY --link go.mod go.sum .
COPY --link ./proxy-init ./proxy-init
COPY --link ./internal ./internal
COPY --link ./pkg ./pkg
RUN go mod download
ARG TARGETARCH
RUN CGO_ENABLED=0 GOOS=linux GOARCH=$TARGETARCH GO111MODULE=on \
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile-cni-plugin
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ WORKDIR /build
COPY --link go.mod go.sum ./
COPY --link ./cni-plugin ./cni-plugin
COPY --link ./proxy-init ./proxy-init
COPY --link ./internal ./internal
COPY --link ./pkg ./pkg
RUN go mod download
ARG TARGETARCH
RUN CGO_ENABLED=0 GOOS=linux GOARCH=$TARGETARCH GO111MODULE=on \
Expand Down
2 changes: 1 addition & 1 deletion cni-plugin/integration/Dockerfile-tester
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ ENV GOCACHE=/tmp/
WORKDIR /src
COPY --link go.mod go.sum .
COPY --link cni-plugin cni-plugin
COPY --link internal internal
COPY --link pkg pkg
COPY --link proxy-init proxy-init
RUN go mod tidy && go mod download
2 changes: 1 addition & 1 deletion cni-plugin/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import (
"github.com/containernetworking/cni/pkg/types"
cniv1 "github.com/containernetworking/cni/pkg/types/100"
"github.com/containernetworking/cni/pkg/version"
"github.com/linkerd/linkerd2-proxy-init/internal/iptables"
"github.com/linkerd/linkerd2-proxy-init/pkg/iptables"
"github.com/linkerd/linkerd2-proxy-init/proxy-init/cmd"

"github.com/sirupsen/logrus"
Expand Down
4 changes: 2 additions & 2 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ proxy-init-lint *flags:
# Run proxy-init unit tests
proxy-init-test-unit:
go test -v ./proxy-init/...
go test -v ./internal/...
go test -v ./pkg/...

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

##
## CNI plugin integration
##
##


# Run cni-plugin integration tests after preparing dependencies By default,
Expand Down
93 changes: 83 additions & 10 deletions internal/iptables/iptables.go → pkg/iptables/iptables.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (

log "github.com/sirupsen/logrus"

util "github.com/linkerd/linkerd2-proxy-init/internal/util"
util "github.com/linkerd/linkerd2-proxy-init/pkg/util"
)

const (
Expand All @@ -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 removes 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,39 @@ func ConfigureFirewall(firewallConfiguration FirewallConfiguration) error {
return nil
}

// 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 (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
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 +337,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
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
File renamed without changes.
File renamed without changes.
4 changes: 2 additions & 2 deletions proxy-init/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import (
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"

"github.com/linkerd/linkerd2-proxy-init/internal/iptables"
"github.com/linkerd/linkerd2-proxy-init/internal/util"
"github.com/linkerd/linkerd2-proxy-init/pkg/iptables"
"github.com/linkerd/linkerd2-proxy-init/pkg/util"
)

const (
Expand Down
2 changes: 1 addition & 1 deletion proxy-init/cmd/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"reflect"
"testing"

"github.com/linkerd/linkerd2-proxy-init/internal/iptables"
"github.com/linkerd/linkerd2-proxy-init/pkg/iptables"
)

func TestBuildFirewallConfiguration(t *testing.T) {
Expand Down
Loading