diff --git a/.gitignore b/.gitignore index 8b1c477..100fc81 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ newt .DS_Store -bin/ \ No newline at end of file +bin/ +nohup.out \ No newline at end of file diff --git a/main.go b/main.go index e08eefd..da80c48 100644 --- a/main.go +++ b/main.go @@ -258,7 +258,6 @@ func main() { logLevel string interfaceName string generateAndSaveKeyTo string - reachableAt string ) // if PANGOLIN_ENDPOINT, NEWT_ID, and NEWT_SECRET are set as environment variables, they will be used as default values @@ -270,7 +269,6 @@ func main() { logLevel = os.Getenv("LOG_LEVEL") interfaceName = os.Getenv("INTERFACE") generateAndSaveKeyTo = os.Getenv("GENERATE_AND_SAVE_KEY_TO") - reachableAt = os.Getenv("REACHABLE_AT") if endpoint == "" { flag.StringVar(&endpoint, "endpoint", "", "Endpoint of your pangolin server") @@ -296,9 +294,6 @@ func main() { if generateAndSaveKeyTo == "" { flag.StringVar(&generateAndSaveKeyTo, "generateAndSaveKeyTo", "", "Path to save generated private key") } - if reachableAt == "" { - flag.StringVar(&reachableAt, "reachableAt", "", "Endpoint of the http server to tell remote config about") - } // do a --version check version := flag.Bool("version", false, "Print the version") @@ -353,7 +348,7 @@ func main() { } // Create WireGuard service - wgService, err = wg.NewWireGuardService(interfaceName, mtuInt, reachableAt, generateAndSaveKeyTo, host, id, client) + wgService, err = wg.NewWireGuardService(interfaceName, mtuInt, generateAndSaveKeyTo, host, id, client) if err != nil { logger.Fatal("Failed to create WireGuard service: %v", err) } @@ -469,6 +464,13 @@ persistent_keepalive_interval=5`, fixKey(fmt.Sprintf("%s", privateKey)), fixKey( updateTargets(pm, "add", wgData.TunnelIP, "udp", TargetData{Targets: wgData.Targets.UDP}) } + // first make sure the wpgService has a port + if wgService != nil { + // add a udp proxy for localost and the wgService port + // TODO: make sure this port is not used in a target + pm.AddTarget("udp", wgData.TunnelIP, int(wgService.Port), fmt.Sprintf("localhost:%d", wgService.Port)) + } + err = pm.Start() if err != nil { logger.Error("Failed to start proxy manager: %v", err) diff --git a/nohup.out b/nohup.out deleted file mode 100644 index 58bc6f3..0000000 --- a/nohup.out +++ /dev/null @@ -1,25 +0,0 @@ -INFO: 2025/02/22 23:25:47 Requesting WireGuard configuration from remote server -INFO: 2025/02/22 23:25:47 Sent registration message -INFO: 2025/02/22 23:25:47 Received message: {newt/wg/receive-config map[ipAddress:100.90.128.1/24 listenPort:51822 peers:[]]} -INFO: 2025/02/22 23:25:47 Created WireGuard interface wg1 -INFO: 2025/02/22 23:25:47 Assigning IP address 100.90.128.1/24 to interface wg1 -INFO: 2025/02/22 23:25:47 WireGuard interface wg1 created and configured -INFO: 2025/02/22 23:25:47 Received registration message -INFO: 2025/02/22 23:25:47 Received: {Type:newt/wg/connect Data:map[endpoint:pangolin.fosrl.io:51820 publicKey:tng9Z/BN32flFjqwwT1yAxN/twFkmgbZA+D9N+YqdjM= serverIP:100.89.128.1 targets:map[tcp:[] udp:[]] tunnelIP:100.89.128.4]} -INFO: 2025/02/22 23:25:47 WireGuard device created. Lets ping the server now... -INFO: 2025/02/22 23:25:47 Ping attempt 1 of 5 -INFO: 2025/02/22 23:25:47 Pinging 100.89.128.1 -INFO: 2025/02/22 23:25:47 Ping latency: 9.00105ms -INFO: 2025/02/22 23:25:47 Starting ping check -INFO: 2025/02/22 23:26:48 Peer P9pacnRfUSfvDibaQTdTk59q27eRpgtbMMmMpkNwKl0= removed successfully -INFO: 2025/02/22 23:26:48 Peer NMrcorGgTTi4tAUZ1lLru0qISNrt9D9JdsFGyDYlcSQ= added successfully -INFO: 2025/02/22 23:28:58 Peer NMrcorGgTTi4tAUZ1lLru0qISNrt9D9JdsFGyDYlcSQ= removed successfully -INFO: 2025/02/22 23:28:58 Peer n8ZKTG8vsROL/OiqHYJELU/Rg9XDifz0YjE/lQsL0m0= added successfully -INFO: 2025/02/22 23:33:59 Peer n8ZKTG8vsROL/OiqHYJELU/Rg9XDifz0YjE/lQsL0m0= removed successfully -INFO: 2025/02/22 23:33:59 Peer /i8YTgrLkZh08HKXLXqNFQJsyg1E8I2ELXqF0zuP9D8= added successfully -INFO: 2025/02/22 23:34:06 Peer /i8YTgrLkZh08HKXLXqNFQJsyg1E8I2ELXqF0zuP9D8= removed successfully -INFO: 2025/02/22 23:34:06 Peer 50+RB00sDoSG+KAKzl/baaqPkKGOe7upX7uqRCKqsRo= added successfully -INFO: 2025/02/22 23:35:07 Peer 50+RB00sDoSG+KAKzl/baaqPkKGOe7upX7uqRCKqsRo= removed successfully -INFO: 2025/02/22 23:35:07 Peer Aa2Y2NEmc+SITlT89+fsOeqDkXJVu9RBY14+77TXa3w= added successfully -INFO: 2025/02/23 00:55:55 Peer Aa2Y2NEmc+SITlT89+fsOeqDkXJVu9RBY14+77TXa3w= removed successfully -INFO: 2025/02/23 00:55:55 Peer 2AXNjMQzT7GGvdbIG6MJVFpO3FIzQ+qCqZkdSnBA3DE= added successfully diff --git a/wg/wg.go b/wg/wg.go index fa6760f..f77bdcd 100644 --- a/wg/wg.go +++ b/wg/wg.go @@ -51,12 +51,12 @@ type WireGuardService struct { wgClient *wgctrl.Client config WgConfig key wgtypes.Key - reachableAt string newtId string lastReadings map[string]PeerReading mu sync.Mutex - port uint16 + Port uint16 stopHolepunch chan struct{} + host string } // Add this type definition @@ -113,7 +113,7 @@ func FindAvailableUDPPort(minPort, maxPort uint16) (uint16, error) { return 0, fmt.Errorf("no available UDP ports found in range %d-%d", minPort, maxPort) } -func NewWireGuardService(interfaceName string, mtu int, reachableAt string, generateAndSaveKeyTo string, host string, newtId string, wsClient *websocket.Client) (*WireGuardService, error) { +func NewWireGuardService(interfaceName string, mtu int, generateAndSaveKeyTo string, host string, newtId string, wsClient *websocket.Client) (*WireGuardService, error) { wgClient, err := wgctrl.New() if err != nil { return nil, fmt.Errorf("failed to create WireGuard client: %v", err) @@ -155,20 +155,13 @@ func NewWireGuardService(interfaceName string, mtu int, reachableAt string, gene client: wsClient, wgClient: wgClient, key: key, - reachableAt: reachableAt, newtId: newtId, lastReadings: make(map[string]PeerReading), - port: port, + Port: port, stopHolepunch: make(chan struct{}), + host: host, } - if err := service.sendUDPHolePunch(host + ":21820"); err != nil { - logger.Error("Failed to send UDP hole punch: %v", err) - } - - // start the UDP holepunch - go service.keepSendingUDPHolePunch(host) - // Register websocket handlers wsClient.RegisterHandler("newt/wg/receive-config", service.handleConfig) wsClient.RegisterHandler("newt/wg/peer/add", service.handleAddPeer) @@ -185,7 +178,6 @@ func (s *WireGuardService) LoadRemoteConfig() error { err := s.client.SendMessage("newt/wg/get-config", map[string]interface{}{ "publicKey": fmt.Sprintf("%s", s.key.PublicKey().String()), - "endpoint": s.reachableAt, }) if err != nil { logger.Error("Failed to send registration message: %v", err) @@ -216,9 +208,6 @@ func (s *WireGuardService) handleConfig(msg websocket.WSMessage) { } s.config = config - // stop the holepunch - // close(s.stopHolepunch) - // Ensure the WireGuard interface and peers are configured if err := s.ensureWireguardInterface(config); err != nil { logger.Error("Failed to ensure WireGuard interface: %v", err) @@ -227,6 +216,13 @@ func (s *WireGuardService) handleConfig(msg websocket.WSMessage) { if err := s.ensureWireguardPeers(config.Peers); err != nil { logger.Error("Failed to ensure WireGuard peers: %v", err) } + + if err := s.sendUDPHolePunch(s.host + ":21820"); err != nil { + logger.Error("Failed to send UDP hole punch: %v", err) + } + + // start the UDP holepunch + go s.keepSendingUDPHolePunch(s.host) } func (s *WireGuardService) ensureWireguardInterface(wgconfig WgConfig) error { @@ -245,6 +241,17 @@ func (s *WireGuardService) ensureWireguardInterface(wgconfig WgConfig) error { } } else { logger.Info("WireGuard interface %s already exists\n", s.interfaceName) + + // get the exising wireguard port + device, err := s.wgClient.Device(s.interfaceName) + if err != nil { + return fmt.Errorf("failed to get device: %v", err) + } + + // get the existing port + s.Port = uint16(device.ListenPort) + logger.Info("WireGuard interface %s already exists with port %d\n", s.interfaceName, s.Port) + return nil } @@ -273,7 +280,7 @@ func (s *WireGuardService) ensureWireguardInterface(wgconfig WgConfig) error { } // Use the service's fixed port instead of the config port - *config.ListenPort = int(s.port) + *config.ListenPort = int(s.Port) // Create and configure the WireGuard interface err = s.wgClient.ConfigureDevice(s.interfaceName, config) @@ -390,6 +397,7 @@ func (s *WireGuardService) handleAddPeer(msg websocket.WSMessage) { err = s.addPeer(peer) if err != nil { + logger.Info("Error adding peer: %v", err) return } } @@ -411,16 +419,18 @@ func (s *WireGuardService) addPeer(peer Peer) error { } // add keep alive using *time.Duration of 1 second keepalive := time.Second - endpoint, err := net.ResolveUDPAddr("udp", peer.Endpoint) - if err != nil { - return fmt.Errorf("failed to resolve endpoint address: %w", err) - } + // endpoint, err := net.ResolveUDPAddr("udp", peer.Endpoint) + // if err != nil { + // return fmt.Errorf("failed to resolve endpoint address: %w", err) + // } + + // make the endpoint localhost to test peerConfig := wgtypes.PeerConfig{ PublicKey: pubKey, AllowedIPs: allowedIPs, PersistentKeepaliveInterval: &keepalive, - Endpoint: endpoint, + // Endpoint: endpoint, } config := wgtypes.Config{ @@ -626,7 +636,7 @@ func (s *WireGuardService) sendUDPHolePunch(serverAddr string) error { client := &network.PeerNet{ IP: clientIP, - Port: s.port, + Port: s.Port, NewtID: s.newtId, } @@ -647,27 +657,11 @@ func (s *WireGuardService) sendUDPHolePunch(serverAddr string) error { return fmt.Errorf("failed to send UDP packet: %v", err) } - // logger.Info("Sent UDP hole punch to %s", serverAddr) - - // // Wait for response if needed - // response, err := network.RecvDataPacket(rawConn, server, client) - // if err != nil { - // if err, ok := err.(net.Error); ok && err.Timeout() { - // return fmt.Errorf("connection to %s timed out", serverAddr) - // } - // return fmt.Errorf("error receiving response: %v", err) - // } - - // // Process response if needed - // if len(response) > 0 { - // logger.Info("Received response from server") - // } - return nil } func (s *WireGuardService) keepSendingUDPHolePunch(host string) { - ticker := time.NewTicker(1 * time.Second) + ticker := time.NewTicker(3 * time.Second) defer ticker.Stop() for {