mirror of
https://github.com/fosrl/newt.git
synced 2025-05-13 05:30:39 +01:00
Basic relay working!
This commit is contained in:
parent
f6429b6eee
commit
b68502de9e
4 changed files with 44 additions and 72 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,3 +1,4 @@
|
||||||
newt
|
newt
|
||||||
.DS_Store
|
.DS_Store
|
||||||
bin/
|
bin/
|
||||||
|
nohup.out
|
14
main.go
14
main.go
|
@ -258,7 +258,6 @@ func main() {
|
||||||
logLevel string
|
logLevel string
|
||||||
interfaceName string
|
interfaceName string
|
||||||
generateAndSaveKeyTo 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
|
// 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")
|
logLevel = os.Getenv("LOG_LEVEL")
|
||||||
interfaceName = os.Getenv("INTERFACE")
|
interfaceName = os.Getenv("INTERFACE")
|
||||||
generateAndSaveKeyTo = os.Getenv("GENERATE_AND_SAVE_KEY_TO")
|
generateAndSaveKeyTo = os.Getenv("GENERATE_AND_SAVE_KEY_TO")
|
||||||
reachableAt = os.Getenv("REACHABLE_AT")
|
|
||||||
|
|
||||||
if endpoint == "" {
|
if endpoint == "" {
|
||||||
flag.StringVar(&endpoint, "endpoint", "", "Endpoint of your pangolin server")
|
flag.StringVar(&endpoint, "endpoint", "", "Endpoint of your pangolin server")
|
||||||
|
@ -296,9 +294,6 @@ func main() {
|
||||||
if generateAndSaveKeyTo == "" {
|
if generateAndSaveKeyTo == "" {
|
||||||
flag.StringVar(&generateAndSaveKeyTo, "generateAndSaveKeyTo", "", "Path to save generated private key")
|
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
|
// do a --version check
|
||||||
version := flag.Bool("version", false, "Print the version")
|
version := flag.Bool("version", false, "Print the version")
|
||||||
|
@ -353,7 +348,7 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create WireGuard service
|
// 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 {
|
if err != nil {
|
||||||
logger.Fatal("Failed to create WireGuard service: %v", err)
|
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})
|
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()
|
err = pm.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("Failed to start proxy manager: %v", err)
|
logger.Error("Failed to start proxy manager: %v", err)
|
||||||
|
|
25
nohup.out
25
nohup.out
|
@ -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
|
|
74
wg/wg.go
74
wg/wg.go
|
@ -51,12 +51,12 @@ type WireGuardService struct {
|
||||||
wgClient *wgctrl.Client
|
wgClient *wgctrl.Client
|
||||||
config WgConfig
|
config WgConfig
|
||||||
key wgtypes.Key
|
key wgtypes.Key
|
||||||
reachableAt string
|
|
||||||
newtId string
|
newtId string
|
||||||
lastReadings map[string]PeerReading
|
lastReadings map[string]PeerReading
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
port uint16
|
Port uint16
|
||||||
stopHolepunch chan struct{}
|
stopHolepunch chan struct{}
|
||||||
|
host string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add this type definition
|
// 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)
|
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()
|
wgClient, err := wgctrl.New()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to create WireGuard client: %v", err)
|
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,
|
client: wsClient,
|
||||||
wgClient: wgClient,
|
wgClient: wgClient,
|
||||||
key: key,
|
key: key,
|
||||||
reachableAt: reachableAt,
|
|
||||||
newtId: newtId,
|
newtId: newtId,
|
||||||
lastReadings: make(map[string]PeerReading),
|
lastReadings: make(map[string]PeerReading),
|
||||||
port: port,
|
Port: port,
|
||||||
stopHolepunch: make(chan struct{}),
|
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
|
// Register websocket handlers
|
||||||
wsClient.RegisterHandler("newt/wg/receive-config", service.handleConfig)
|
wsClient.RegisterHandler("newt/wg/receive-config", service.handleConfig)
|
||||||
wsClient.RegisterHandler("newt/wg/peer/add", service.handleAddPeer)
|
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{}{
|
err := s.client.SendMessage("newt/wg/get-config", map[string]interface{}{
|
||||||
"publicKey": fmt.Sprintf("%s", s.key.PublicKey().String()),
|
"publicKey": fmt.Sprintf("%s", s.key.PublicKey().String()),
|
||||||
"endpoint": s.reachableAt,
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("Failed to send registration message: %v", err)
|
logger.Error("Failed to send registration message: %v", err)
|
||||||
|
@ -216,9 +208,6 @@ func (s *WireGuardService) handleConfig(msg websocket.WSMessage) {
|
||||||
}
|
}
|
||||||
s.config = config
|
s.config = config
|
||||||
|
|
||||||
// stop the holepunch
|
|
||||||
// close(s.stopHolepunch)
|
|
||||||
|
|
||||||
// Ensure the WireGuard interface and peers are configured
|
// Ensure the WireGuard interface and peers are configured
|
||||||
if err := s.ensureWireguardInterface(config); err != nil {
|
if err := s.ensureWireguardInterface(config); err != nil {
|
||||||
logger.Error("Failed to ensure WireGuard interface: %v", err)
|
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 {
|
if err := s.ensureWireguardPeers(config.Peers); err != nil {
|
||||||
logger.Error("Failed to ensure WireGuard peers: %v", err)
|
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 {
|
func (s *WireGuardService) ensureWireguardInterface(wgconfig WgConfig) error {
|
||||||
|
@ -245,6 +241,17 @@ func (s *WireGuardService) ensureWireguardInterface(wgconfig WgConfig) error {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.Info("WireGuard interface %s already exists\n", s.interfaceName)
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,7 +280,7 @@ func (s *WireGuardService) ensureWireguardInterface(wgconfig WgConfig) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use the service's fixed port instead of the config port
|
// 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
|
// Create and configure the WireGuard interface
|
||||||
err = s.wgClient.ConfigureDevice(s.interfaceName, config)
|
err = s.wgClient.ConfigureDevice(s.interfaceName, config)
|
||||||
|
@ -390,6 +397,7 @@ func (s *WireGuardService) handleAddPeer(msg websocket.WSMessage) {
|
||||||
|
|
||||||
err = s.addPeer(peer)
|
err = s.addPeer(peer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
logger.Info("Error adding peer: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -411,16 +419,18 @@ func (s *WireGuardService) addPeer(peer Peer) error {
|
||||||
}
|
}
|
||||||
// add keep alive using *time.Duration of 1 second
|
// add keep alive using *time.Duration of 1 second
|
||||||
keepalive := time.Second
|
keepalive := time.Second
|
||||||
endpoint, err := net.ResolveUDPAddr("udp", peer.Endpoint)
|
// endpoint, err := net.ResolveUDPAddr("udp", peer.Endpoint)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return fmt.Errorf("failed to resolve endpoint address: %w", err)
|
// return fmt.Errorf("failed to resolve endpoint address: %w", err)
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
// make the endpoint localhost to test
|
||||||
|
|
||||||
peerConfig := wgtypes.PeerConfig{
|
peerConfig := wgtypes.PeerConfig{
|
||||||
PublicKey: pubKey,
|
PublicKey: pubKey,
|
||||||
AllowedIPs: allowedIPs,
|
AllowedIPs: allowedIPs,
|
||||||
PersistentKeepaliveInterval: &keepalive,
|
PersistentKeepaliveInterval: &keepalive,
|
||||||
Endpoint: endpoint,
|
// Endpoint: endpoint,
|
||||||
}
|
}
|
||||||
|
|
||||||
config := wgtypes.Config{
|
config := wgtypes.Config{
|
||||||
|
@ -626,7 +636,7 @@ func (s *WireGuardService) sendUDPHolePunch(serverAddr string) error {
|
||||||
|
|
||||||
client := &network.PeerNet{
|
client := &network.PeerNet{
|
||||||
IP: clientIP,
|
IP: clientIP,
|
||||||
Port: s.port,
|
Port: s.Port,
|
||||||
NewtID: s.newtId,
|
NewtID: s.newtId,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -647,27 +657,11 @@ func (s *WireGuardService) sendUDPHolePunch(serverAddr string) error {
|
||||||
return fmt.Errorf("failed to send UDP packet: %v", err)
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *WireGuardService) keepSendingUDPHolePunch(host string) {
|
func (s *WireGuardService) keepSendingUDPHolePunch(host string) {
|
||||||
ticker := time.NewTicker(1 * time.Second)
|
ticker := time.NewTicker(3 * time.Second)
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
|
Loading…
Reference in a new issue