From 4c0491948945f209031191390b63da8d0a1162eb Mon Sep 17 00:00:00 2001 From: Philipp Winter Date: Thu, 21 May 2026 07:46:19 -0500 Subject: [PATCH] Have proxy enable IP forwarding. So far, the proxy wouldn't explicitly enable IP forwarding, which would break veil's Internet access if forwarding isn't enabled already. This PR fixes that. Codex with GPT-5.5 wrote the code and it looks good. --- internal/net/nat/nat.go | 71 ++++++++++++++++++++++++++++++++---- internal/net/nat/nat_test.go | 56 ++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+), 7 deletions(-) create mode 100644 internal/net/nat/nat_test.go diff --git a/internal/net/nat/nat.go b/internal/net/nat/nat.go index 872e511..c557986 100644 --- a/internal/net/nat/nat.go +++ b/internal/net/nat/nat.go @@ -1,22 +1,41 @@ -// Package nat provides functions to enable and disable iptables forwarding -// rules for veil-proxy. +// Package nat provides functions to enable and disable host forwarding for +// veil-proxy. package nat import ( + "errors" + "fmt" + "os" + "strings" + "sync" + "github.com/coreos/go-iptables/iptables" "github.com/Amnesic-Systems/veil/internal/net/tun" ) -// Enable enables our iptables NAT rules, which connect the enclave to the -// Internet. +var ( + ipForwardPath = "/proc/sys/net/ipv4/ip_forward" + ipForwardMu sync.Mutex + restoreIPForward *string +) + +// Enable enables IP forwarding and our iptables NAT rules, which connect the +// enclave to the Internet. func Enable() error { - return applyRules(true) + if err := applyRules(true); err != nil { + return err + } + if err := enableIPForwarding(); err != nil { + return errors.Join(err, applyRules(false)) + } + return nil } -// Disable disables our iptables NAT rules. +// Disable disables our iptables NAT rules and restores the prior IP forwarding +// state if Enable changed it. func Disable() error { - return applyRules(false) + return errors.Join(applyRules(false), restorePriorIPForwarding()) } func applyRules(toggle bool) error { @@ -45,3 +64,41 @@ func applyRules(toggle bool) error { return nil } + +func enableIPForwarding() error { + ipForwardMu.Lock() + defer ipForwardMu.Unlock() + + content, err := os.ReadFile(ipForwardPath) + if err != nil { + return fmt.Errorf("failed to read %s: %w", ipForwardPath, err) + } + + current := strings.TrimSpace(string(content)) + if current == "1" { + return nil + } + + if err := os.WriteFile(ipForwardPath, []byte("1\n"), 0644); err != nil { + return fmt.Errorf("failed to write %s: %w", ipForwardPath, err) + } + if restoreIPForward == nil { + restoreIPForward = ¤t + } + return nil +} + +func restorePriorIPForwarding() error { + ipForwardMu.Lock() + defer ipForwardMu.Unlock() + + if restoreIPForward == nil { + return nil + } + + if err := os.WriteFile(ipForwardPath, []byte(*restoreIPForward+"\n"), 0644); err != nil { + return fmt.Errorf("failed to restore %s: %w", ipForwardPath, err) + } + restoreIPForward = nil + return nil +} diff --git a/internal/net/nat/nat_test.go b/internal/net/nat/nat_test.go new file mode 100644 index 0000000..26cdd9c --- /dev/null +++ b/internal/net/nat/nat_test.go @@ -0,0 +1,56 @@ +package nat + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/require" +) + +func withIPForwardFile(t *testing.T, content string) string { + t.Helper() + + path := filepath.Join(t.TempDir(), "ip_forward") + require.NoError(t, os.WriteFile(path, []byte(content), 0644)) + + oldPath := ipForwardPath + oldRestore := restoreIPForward + ipForwardPath = path + restoreIPForward = nil + t.Cleanup(func() { + ipForwardPath = oldPath + restoreIPForward = oldRestore + }) + + return path +} + +func TestEnableIPForwardingLeavesEnabledStateAlone(t *testing.T) { + path := withIPForwardFile(t, "1\n") + + require.NoError(t, enableIPForwarding()) + require.Nil(t, restoreIPForward) + + got, err := os.ReadFile(path) + require.NoError(t, err) + require.Equal(t, "1\n", string(got)) +} + +func TestEnableIPForwardingRestoresDisabledState(t *testing.T) { + path := withIPForwardFile(t, "0\n") + + require.NoError(t, enableIPForwarding()) + require.NotNil(t, restoreIPForward) + + got, err := os.ReadFile(path) + require.NoError(t, err) + require.Equal(t, "1\n", string(got)) + + require.NoError(t, restorePriorIPForwarding()) + require.Nil(t, restoreIPForward) + + got, err = os.ReadFile(path) + require.NoError(t, err) + require.Equal(t, "0\n", string(got)) +}