Skip to content
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
71 changes: 64 additions & 7 deletions internal/net/nat/nat.go
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down Expand Up @@ -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 = &current
}
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
}
56 changes: 56 additions & 0 deletions internal/net/nat/nat_test.go
Original file line number Diff line number Diff line change
@@ -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))
}
Loading