Bring in netstack locally

This commit is contained in:
Owen
2025-11-05 13:39:54 -08:00
parent 6226a262d6
commit 348cac66c8
7 changed files with 1092 additions and 33 deletions

View File

@@ -5,9 +5,9 @@ import (
"strings" "strings"
"github.com/fosrl/newt/logger" "github.com/fosrl/newt/logger"
"github.com/fosrl/newt/netstack2"
"github.com/fosrl/newt/proxy" "github.com/fosrl/newt/proxy"
"github.com/fosrl/newt/websocket" "github.com/fosrl/newt/websocket"
"golang.zx2c4.com/wireguard/tun/netstack"
"github.com/fosrl/newt/wgnetstack" "github.com/fosrl/newt/wgnetstack"
"github.com/fosrl/newt/wgtester" "github.com/fosrl/newt/wgtester"
@@ -37,7 +37,7 @@ func setupClients(client *websocket.Client) {
} }
func setupClientsNetstack(client *websocket.Client, host string) { func setupClientsNetstack(client *websocket.Client, host string) {
logger.Info("Setting up clients with netstack...") logger.Info("Setting up clients with netstack2...")
// Create WireGuard service // Create WireGuard service
wgService, err = wgnetstack.NewWireGuardService(interfaceName, mtuInt, generateAndSaveKeyTo, host, id, client, "9.9.9.9") wgService, err = wgnetstack.NewWireGuardService(interfaceName, mtuInt, generateAndSaveKeyTo, host, id, client, "9.9.9.9")
if err != nil { if err != nil {
@@ -45,7 +45,7 @@ func setupClientsNetstack(client *websocket.Client, host string) {
} }
// // Set up callback to restart wgtester with netstack when WireGuard is ready // // Set up callback to restart wgtester with netstack when WireGuard is ready
wgService.SetOnNetstackReady(func(tnet *netstack.Net) { wgService.SetOnNetstackReady(func(tnet *netstack2.Net) {
wgTesterServer = wgtester.NewServerWithNetstack("0.0.0.0", wgService.Port, id, tnet) // TODO: maybe make this the same ip of the wg server? wgTesterServer = wgtester.NewServerWithNetstack("0.0.0.0", wgService.Port, id, tnet) // TODO: maybe make this the same ip of the wg server?
err := wgTesterServer.Start() err := wgTesterServer.Start()
@@ -66,7 +66,7 @@ func setupClientsNetstack(client *websocket.Client, host string) {
}) })
} }
func setDownstreamTNetstack(tnet *netstack.Net) { func setDownstreamTNetstack(tnet *netstack2.Net) {
if wgService != nil { if wgService != nil {
wgService.SetOthertnet(tnet) wgService.SetOthertnet(tnet)
} }

View File

@@ -20,6 +20,7 @@ import (
"github.com/fosrl/newt/docker" "github.com/fosrl/newt/docker"
"github.com/fosrl/newt/healthcheck" "github.com/fosrl/newt/healthcheck"
"github.com/fosrl/newt/logger" "github.com/fosrl/newt/logger"
"github.com/fosrl/newt/netstack2"
"github.com/fosrl/newt/proxy" "github.com/fosrl/newt/proxy"
"github.com/fosrl/newt/updates" "github.com/fosrl/newt/updates"
"github.com/fosrl/newt/websocket" "github.com/fosrl/newt/websocket"
@@ -30,7 +31,6 @@ import (
"golang.zx2c4.com/wireguard/conn" "golang.zx2c4.com/wireguard/conn"
"golang.zx2c4.com/wireguard/device" "golang.zx2c4.com/wireguard/device"
"golang.zx2c4.com/wireguard/tun" "golang.zx2c4.com/wireguard/tun"
"golang.zx2c4.com/wireguard/tun/netstack"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes" "golang.zx2c4.com/wireguard/wgctrl/wgtypes"
) )
@@ -531,7 +531,7 @@ func main() {
// Create TUN device and network stack // Create TUN device and network stack
var tun tun.Device var tun tun.Device
var tnet *netstack.Net var tnet *netstack2.Net
var dev *device.Device var dev *device.Device
var pm *proxy.ProxyManager var pm *proxy.ProxyManager
var connected bool var connected bool
@@ -637,7 +637,7 @@ func main() {
} }
logger.Debug(fmtReceivedMsg, msg) logger.Debug(fmtReceivedMsg, msg)
tun, tnet, err = netstack.CreateNetTUN( tun, tnet, err = netstack2.CreateNetTUN(
[]netip.Addr{netip.MustParseAddr(wgData.TunnelIP)}, []netip.Addr{netip.MustParseAddr(wgData.TunnelIP)},
[]netip.Addr{netip.MustParseAddr(dns)}, []netip.Addr{netip.MustParseAddr(dns)},
mtuInt) mtuInt)

1057
netstack2/tun.go Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -15,9 +15,9 @@ import (
"github.com/fosrl/newt/internal/state" "github.com/fosrl/newt/internal/state"
"github.com/fosrl/newt/internal/telemetry" "github.com/fosrl/newt/internal/telemetry"
"github.com/fosrl/newt/logger" "github.com/fosrl/newt/logger"
"github.com/fosrl/newt/netstack2"
"go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/metric"
"golang.zx2c4.com/wireguard/tun/netstack"
"gvisor.dev/gvisor/pkg/tcpip/adapters/gonet" "gvisor.dev/gvisor/pkg/tcpip/adapters/gonet"
) )
@@ -31,7 +31,7 @@ type Target struct {
// ProxyManager handles the creation and management of proxy connections // ProxyManager handles the creation and management of proxy connections
type ProxyManager struct { type ProxyManager struct {
tnet *netstack.Net tnet *netstack2.Net
tcpTargets map[string]map[int]string // map[listenIP]map[port]targetAddress tcpTargets map[string]map[int]string // map[listenIP]map[port]targetAddress
udpTargets map[string]map[int]string udpTargets map[string]map[int]string
listeners []*gonet.TCPListener listeners []*gonet.TCPListener
@@ -125,7 +125,7 @@ func classifyProxyError(err error) string {
} }
// NewProxyManager creates a new proxy manager instance // NewProxyManager creates a new proxy manager instance
func NewProxyManager(tnet *netstack.Net) *ProxyManager { func NewProxyManager(tnet *netstack2.Net) *ProxyManager {
return &ProxyManager{ return &ProxyManager{
tnet: tnet, tnet: tnet,
tcpTargets: make(map[string]map[int]string), tcpTargets: make(map[string]map[int]string),
@@ -214,7 +214,7 @@ func NewProxyManagerWithoutTNet() *ProxyManager {
} }
// Function to add tnet to existing ProxyManager // Function to add tnet to existing ProxyManager
func (pm *ProxyManager) SetTNet(tnet *netstack.Net) { func (pm *ProxyManager) SetTNet(tnet *netstack2.Net) {
pm.mutex.Lock() pm.mutex.Lock()
defer pm.mutex.Unlock() defer pm.mutex.Unlock()
pm.tnet = tnet pm.tnet = tnet

10
util.go
View File

@@ -17,12 +17,12 @@ import (
"github.com/fosrl/newt/internal/telemetry" "github.com/fosrl/newt/internal/telemetry"
"github.com/fosrl/newt/logger" "github.com/fosrl/newt/logger"
"github.com/fosrl/newt/netstack2"
"github.com/fosrl/newt/proxy" "github.com/fosrl/newt/proxy"
"github.com/fosrl/newt/websocket" "github.com/fosrl/newt/websocket"
"golang.org/x/net/icmp" "golang.org/x/net/icmp"
"golang.org/x/net/ipv4" "golang.org/x/net/ipv4"
"golang.zx2c4.com/wireguard/device" "golang.zx2c4.com/wireguard/device"
"golang.zx2c4.com/wireguard/tun/netstack"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
) )
@@ -42,7 +42,7 @@ func fixKey(key string) string {
return hex.EncodeToString(decoded) return hex.EncodeToString(decoded)
} }
func ping(tnet *netstack.Net, dst string, timeout time.Duration) (time.Duration, error) { func ping(tnet *netstack2.Net, dst string, timeout time.Duration) (time.Duration, error) {
logger.Debug("Pinging %s", dst) logger.Debug("Pinging %s", dst)
socket, err := tnet.Dial("ping4", dst) socket, err := tnet.Dial("ping4", dst)
if err != nil { if err != nil {
@@ -108,7 +108,7 @@ func ping(tnet *netstack.Net, dst string, timeout time.Duration) (time.Duration,
} }
// reliablePing performs multiple ping attempts with adaptive timeout // reliablePing performs multiple ping attempts with adaptive timeout
func reliablePing(tnet *netstack.Net, dst string, baseTimeout time.Duration, maxAttempts int) (time.Duration, error) { func reliablePing(tnet *netstack2.Net, dst string, baseTimeout time.Duration, maxAttempts int) (time.Duration, error) {
var lastErr error var lastErr error
var totalLatency time.Duration var totalLatency time.Duration
successCount := 0 successCount := 0
@@ -152,7 +152,7 @@ func reliablePing(tnet *netstack.Net, dst string, baseTimeout time.Duration, max
return totalLatency / time.Duration(successCount), nil return totalLatency / time.Duration(successCount), nil
} }
func pingWithRetry(tnet *netstack.Net, dst string, timeout time.Duration) (stopChan chan struct{}, err error) { func pingWithRetry(tnet *netstack2.Net, dst string, timeout time.Duration) (stopChan chan struct{}, err error) {
if healthFile != "" { if healthFile != "" {
err = os.Remove(healthFile) err = os.Remove(healthFile)
@@ -236,7 +236,7 @@ func pingWithRetry(tnet *netstack.Net, dst string, timeout time.Duration) (stopC
return stopChan, fmt.Errorf("initial ping attempts failed, continuing in background") return stopChan, fmt.Errorf("initial ping attempts failed, continuing in background")
} }
func startPingCheck(tnet *netstack.Net, serverIP string, client *websocket.Client, tunnelID string) chan struct{} { func startPingCheck(tnet *netstack2.Net, serverIP string, client *websocket.Client, tunnelID string) chan struct{} {
maxInterval := 6 * time.Second maxInterval := 6 * time.Second
currentInterval := pingInterval currentInterval := pingInterval
consecutiveFailures := 0 consecutiveFailures := 0

View File

@@ -17,6 +17,7 @@ import (
"time" "time"
"github.com/fosrl/newt/logger" "github.com/fosrl/newt/logger"
"github.com/fosrl/newt/netstack2"
"github.com/fosrl/newt/network" "github.com/fosrl/newt/network"
"github.com/fosrl/newt/proxy" "github.com/fosrl/newt/proxy"
"github.com/fosrl/newt/websocket" "github.com/fosrl/newt/websocket"
@@ -25,7 +26,6 @@ import (
"golang.zx2c4.com/wireguard/conn" "golang.zx2c4.com/wireguard/conn"
"golang.zx2c4.com/wireguard/device" "golang.zx2c4.com/wireguard/device"
"golang.zx2c4.com/wireguard/tun" "golang.zx2c4.com/wireguard/tun"
"golang.zx2c4.com/wireguard/tun/netstack"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes" "golang.zx2c4.com/wireguard/wgctrl/wgtypes"
"github.com/fosrl/newt/internal/telemetry" "github.com/fosrl/newt/internal/telemetry"
@@ -83,14 +83,14 @@ type WireGuardService struct {
stopGetConfig func() stopGetConfig func()
// Netstack fields // Netstack fields
tun tun.Device tun tun.Device
tnet *netstack.Net tnet *netstack2.Net
device *device.Device device *device.Device
dns []netip.Addr dns []netip.Addr
// Callback for when netstack is ready // Callback for when netstack is ready
onNetstackReady func(*netstack.Net) onNetstackReady func(*netstack2.Net)
// Callback for when netstack is closed // Callback for when netstack is closed
onNetstackClose func() onNetstackClose func()
othertnet *netstack.Net othertnet *netstack2.Net
// Proxy manager for tunnel // Proxy manager for tunnel
proxyManager *proxy.ProxyManager proxyManager *proxy.ProxyManager
TunnelIP string TunnelIP string
@@ -247,7 +247,9 @@ func NewWireGuardService(interfaceName string, mtu int, generateAndSaveKeyTo str
// ReportRTT allows reporting native RTTs to telemetry, rate-limited externally. // ReportRTT allows reporting native RTTs to telemetry, rate-limited externally.
func (s *WireGuardService) ReportRTT(seconds float64) { func (s *WireGuardService) ReportRTT(seconds float64) {
if s.serverPubKey == "" { return } if s.serverPubKey == "" {
return
}
telemetry.ObserveTunnelLatency(context.Background(), s.serverPubKey, "wireguard", seconds) telemetry.ObserveTunnelLatency(context.Background(), s.serverPubKey, "wireguard", seconds)
} }
@@ -257,8 +259,8 @@ func (s *WireGuardService) addTcpTarget(msg websocket.WSMessage) {
// if there is no wgData or pm, we can't add targets // if there is no wgData or pm, we can't add targets
if s.TunnelIP == "" || s.proxyManager == nil { if s.TunnelIP == "" || s.proxyManager == nil {
logger.Info("No tunnel IP or proxy manager available") logger.Info("No tunnel IP or proxy manager available")
return return
} }
targetData, err := parseTargetData(msg.Data) targetData, err := parseTargetData(msg.Data)
if err != nil { if err != nil {
@@ -331,7 +333,7 @@ func (s *WireGuardService) removeTcpTarget(msg websocket.WSMessage) {
} }
} }
func (s *WireGuardService) SetOthertnet(tnet *netstack.Net) { func (s *WireGuardService) SetOthertnet(tnet *netstack2.Net) {
s.othertnet = tnet s.othertnet = tnet
} }
@@ -382,7 +384,7 @@ func (s *WireGuardService) SetToken(token string) {
} }
// GetNetstackNet returns the netstack network interface for use by other components // GetNetstackNet returns the netstack network interface for use by other components
func (s *WireGuardService) GetNetstackNet() *netstack.Net { func (s *WireGuardService) GetNetstackNet() *netstack2.Net {
s.mu.Lock() s.mu.Lock()
defer s.mu.Unlock() defer s.mu.Unlock()
return s.tnet return s.tnet
@@ -401,7 +403,7 @@ func (s *WireGuardService) GetPublicKey() wgtypes.Key {
} }
// SetOnNetstackReady sets a callback function to be called when the netstack interface is ready // SetOnNetstackReady sets a callback function to be called when the netstack interface is ready
func (s *WireGuardService) SetOnNetstackReady(callback func(*netstack.Net)) { func (s *WireGuardService) SetOnNetstackReady(callback func(*netstack2.Net)) {
s.onNetstackReady = callback s.onNetstackReady = callback
} }
@@ -493,7 +495,7 @@ func (s *WireGuardService) ensureWireguardInterface(wgconfig WgConfig) error {
// Create TUN device and network stack using netstack // Create TUN device and network stack using netstack
var err error var err error
s.tun, s.tnet, err = netstack.CreateNetTUN( s.tun, s.tnet, err = netstack2.CreateNetTUN(
[]netip.Addr{tunnelIP}, []netip.Addr{tunnelIP},
s.dns, s.dns,
s.mtu) s.mtu)
@@ -1202,7 +1204,7 @@ func (s *WireGuardService) ReplaceNetstack() error {
s.proxyManager.Stop() s.proxyManager.Stop()
// Create new TUN device and netstack with new DNS // Create new TUN device and netstack with new DNS
newTun, newTnet, err := netstack.CreateNetTUN( newTun, newTnet, err := netstack2.CreateNetTUN(
[]netip.Addr{tunnelIP}, []netip.Addr{tunnelIP},
s.dns, s.dns,
s.mtu) s.mtu)

View File

@@ -8,7 +8,7 @@ import (
"time" "time"
"github.com/fosrl/newt/logger" "github.com/fosrl/newt/logger"
"golang.zx2c4.com/wireguard/tun/netstack" "github.com/fosrl/newt/netstack2"
"gvisor.dev/gvisor/pkg/tcpip/adapters/gonet" "gvisor.dev/gvisor/pkg/tcpip/adapters/gonet"
) )
@@ -39,7 +39,7 @@ type Server struct {
newtID string newtID string
outputPrefix string outputPrefix string
useNetstack bool useNetstack bool
tnet interface{} // Will be *netstack.Net when using netstack tnet interface{} // Will be *netstack2.Net when using netstack
} }
// NewServer creates a new connection test server using UDP // NewServer creates a new connection test server using UDP
@@ -56,7 +56,7 @@ func NewServer(serverAddr string, serverPort uint16, newtID string) *Server {
} }
// NewServerWithNetstack creates a new connection test server using WireGuard netstack // NewServerWithNetstack creates a new connection test server using WireGuard netstack
func NewServerWithNetstack(serverAddr string, serverPort uint16, newtID string, tnet *netstack.Net) *Server { func NewServerWithNetstack(serverAddr string, serverPort uint16, newtID string, tnet *netstack2.Net) *Server {
return &Server{ return &Server{
serverAddr: serverAddr, serverAddr: serverAddr,
serverPort: serverPort + 1, // use the next port for the server serverPort: serverPort + 1, // use the next port for the server
@@ -82,7 +82,7 @@ func (s *Server) Start() error {
if s.useNetstack && s.tnet != nil { if s.useNetstack && s.tnet != nil {
// Use WireGuard netstack // Use WireGuard netstack
tnet := s.tnet.(*netstack.Net) tnet := s.tnet.(*netstack2.Net)
udpAddr := &net.UDPAddr{Port: int(s.serverPort)} udpAddr := &net.UDPAddr{Port: int(s.serverPort)}
netstackConn, err := tnet.ListenUDP(udpAddr) netstackConn, err := tnet.ListenUDP(udpAddr)
if err != nil { if err != nil {
@@ -130,7 +130,7 @@ func (s *Server) Stop() {
} }
// RestartWithNetstack stops the current server and restarts it with netstack // RestartWithNetstack stops the current server and restarts it with netstack
func (s *Server) RestartWithNetstack(tnet *netstack.Net) error { func (s *Server) RestartWithNetstack(tnet *netstack2.Net) error {
s.Stop() s.Stop()
// Update configuration to use netstack // Update configuration to use netstack