From b512e4d81786d2f62e06cd7cdae3ce861e224b1b Mon Sep 17 00:00:00 2001 From: Daniel Lorch Date: Wed, 14 May 2025 21:49:18 +0200 Subject: [PATCH] Enable Ipv4 forwarding --- internal/network/nat.go | 66 +++++++++++++++++++++++++++++++++++++++ internal/network/netif.go | 10 ++++-- 2 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 internal/network/nat.go diff --git a/internal/network/nat.go b/internal/network/nat.go new file mode 100644 index 0000000..39a7722 --- /dev/null +++ b/internal/network/nat.go @@ -0,0 +1,66 @@ +package network + +import ( + "fmt" + "os" + "os/exec" +) + +const ( + procIpv4ForwardPath = "/proc/sys/net/ipv4/ip_forward" +) + +func (s *NetworkInterfaceState) reconfigureNat(wantNat bool, sourceAddr string) error { + scopedLogger := s.l.With().Str("iface", s.interfaceName).Logger() + + if wantNat && s.IsOnline() { + scopedLogger.Info().Msg("enabling NAT") + err := enableNat(sourceAddr, s.interfaceName, s.IPv4String()) + if err != nil { + s.l.Error().Err(err).Msg("failed to enable NAT") + } + } else { + scopedLogger.Info().Msg("disabling NAT") + err := disableNat() + if err != nil { + s.l.Error().Err(err).Msg("failed to disable NAT") + } + } + return nil +} + +func enableNat(sourceAddr string, oIfName string, snatToAddr string) error { + if err := os.WriteFile(procIpv4ForwardPath, []byte("1"), 0644); err != nil { + return fmt.Errorf("failed to write %s: %w", procIpv4ForwardPath, err) + } + + if err := exec.Command("nft", "add table nat").Run(); err != nil { + return fmt.Errorf("failed to add table nat: %w", err) + } + + if err := exec.Command("nft", "flush table nat").Run(); err != nil { + return fmt.Errorf("failed to flush table nat: %w", err) + } + + if err := exec.Command("nft", "add chain nat postrouting { type nat hook postrouting priority 100 ; }").Run(); err != nil { + return fmt.Errorf("failed to add chain nat: %w", err) + } + + if err := exec.Command("nft", "add rule nat postrouting ip saddr", sourceAddr, "oif", oIfName, "snat to", snatToAddr).Run(); err != nil { + return fmt.Errorf("failed to add postrouting rule: %w", err) + } + + return nil +} + +func disableNat() error { + if err := os.WriteFile(procIpv4ForwardPath, []byte("0"), 0644); err != nil { + return fmt.Errorf("failed to write %s: %w", procIpv4ForwardPath, err) + } + + if err := exec.Command("nft", "delete table nat").Run(); err != nil { + return fmt.Errorf("failed to run nft: %w", err) + } + + return nil +} \ No newline at end of file diff --git a/internal/network/netif.go b/internal/network/netif.go index 66ebcdb..d848a86 100644 --- a/internal/network/netif.go +++ b/internal/network/netif.go @@ -72,8 +72,14 @@ func NewNetworkInterfaceState(opts *NetworkInterfaceOptions) (*NetworkInterfaceS defaultHostname: opts.DefaultHostname, stateLock: sync.Mutex{}, l: l, - onStateChange: opts.OnStateChange, - onInitialCheck: opts.OnInitialCheck, + onStateChange: func(s *NetworkInterfaceState) { + s.reconfigureNat(true, "172.16.55.0/24") + opts.OnStateChange(s) + }, + onInitialCheck: func(s *NetworkInterfaceState) { + s.reconfigureNat(true, "172.16.55.0/24") + opts.OnInitialCheck(s) + }, cbConfigChange: opts.OnConfigChange, config: opts.NetworkConfig, }