mirror of
https://github.com/fosrl/olm.git
synced 2026-02-28 07:46:41 +00:00
Remove ping
This commit is contained in:
214
main.go
214
main.go
@@ -6,20 +6,16 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/fosrl/newt/logger"
|
"github.com/fosrl/newt/logger"
|
||||||
"github.com/fosrl/olm/websocket"
|
"github.com/fosrl/olm/websocket"
|
||||||
|
|
||||||
"golang.org/x/net/icmp"
|
|
||||||
"golang.org/x/net/ipv4"
|
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
"golang.zx2c4.com/wireguard/conn"
|
"golang.zx2c4.com/wireguard/conn"
|
||||||
"golang.zx2c4.com/wireguard/device"
|
"golang.zx2c4.com/wireguard/device"
|
||||||
@@ -65,135 +61,55 @@ const (
|
|||||||
ENV_WG_PROCESS_FOREGROUND = "WG_PROCESS_FOREGROUND"
|
ENV_WG_PROCESS_FOREGROUND = "WG_PROCESS_FOREGROUND"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ping(dst string) error {
|
// func startPingCheck(serverIP string, stopChan chan struct{}) {
|
||||||
logger.Info("Pinging %s over WireGuard tunnel", dst)
|
// ticker := time.NewTicker(10 * time.Second)
|
||||||
|
// defer ticker.Stop()
|
||||||
|
|
||||||
// Create a raw socket for ICMP
|
// go func() {
|
||||||
conn, err := icmp.ListenPacket("ip4:icmp", "0.0.0.0")
|
// for {
|
||||||
if err != nil {
|
// select {
|
||||||
return fmt.Errorf("failed to create ICMP socket: %w", err)
|
// case <-ticker.C:
|
||||||
}
|
// err := ping(serverIP)
|
||||||
defer conn.Close()
|
// if err != nil {
|
||||||
|
// logger.Warn("Periodic ping failed: %v", err)
|
||||||
|
// logger.Warn("HINT: Check if the WireGuard tunnel is up and the server is reachable")
|
||||||
|
// }
|
||||||
|
// case <-stopChan:
|
||||||
|
// logger.Info("Stopping ping check")
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }()
|
||||||
|
// }
|
||||||
|
|
||||||
// Parse destination IP
|
// func pingWithRetry(dst string) error {
|
||||||
dstIP := net.ParseIP(dst)
|
// const (
|
||||||
if dstIP == nil {
|
// maxAttempts = 5
|
||||||
return fmt.Errorf("invalid destination IP: %s", dst)
|
// retryDelay = 2 * time.Second
|
||||||
}
|
// )
|
||||||
|
|
||||||
// Create ICMP message
|
// var lastErr error
|
||||||
requestPing := icmp.Echo{
|
// for attempt := 1; attempt <= maxAttempts; attempt++ {
|
||||||
ID: os.Getpid() & 0xffff,
|
// logger.Info("Ping attempt %d of %d", attempt, maxAttempts)
|
||||||
Seq: rand.Intn(1 << 16),
|
|
||||||
Data: []byte("wireguard ping"),
|
|
||||||
}
|
|
||||||
|
|
||||||
msg := icmp.Message{
|
// if err := ping(dst); err != nil {
|
||||||
Type: ipv4.ICMPTypeEcho,
|
// lastErr = err
|
||||||
Code: 0,
|
// logger.Warn("Ping attempt %d failed: %v", attempt, err)
|
||||||
Body: &requestPing,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Marshal the message
|
// if attempt < maxAttempts {
|
||||||
icmpBytes, err := msg.Marshal(nil)
|
// time.Sleep(retryDelay)
|
||||||
if err != nil {
|
// continue
|
||||||
return fmt.Errorf("failed to marshal ICMP message: %w", err)
|
// }
|
||||||
}
|
// return fmt.Errorf("all ping attempts failed after %d tries, last error: %w",
|
||||||
|
// maxAttempts, lastErr)
|
||||||
|
// }
|
||||||
|
|
||||||
// Set read deadline
|
// // Successful ping
|
||||||
if err := conn.SetReadDeadline(time.Now().Add(time.Second * 10)); err != nil {
|
// return nil
|
||||||
return fmt.Errorf("failed to set read deadline: %w", err)
|
// }
|
||||||
}
|
|
||||||
|
|
||||||
// Send the ping
|
// return fmt.Errorf("unexpected error: all ping attempts failed")
|
||||||
start := time.Now()
|
// }
|
||||||
_, err = conn.WriteTo(icmpBytes, &net.IPAddr{IP: dstIP})
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to write ICMP packet: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for reply
|
|
||||||
reply := make([]byte, 1500)
|
|
||||||
n, peer, err := conn.ReadFrom(reply)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to read ICMP packet: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse reply
|
|
||||||
replyMsg, err := icmp.ParseMessage(1, reply[:n])
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to parse ICMP reply: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify reply
|
|
||||||
switch replyMsg.Type {
|
|
||||||
case ipv4.ICMPTypeEchoReply:
|
|
||||||
replyEcho, ok := replyMsg.Body.(*icmp.Echo)
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("invalid reply type: got %T, want *icmp.Echo", replyMsg.Body)
|
|
||||||
}
|
|
||||||
if replyEcho.ID != requestPing.ID || replyEcho.Seq != requestPing.Seq {
|
|
||||||
return fmt.Errorf("invalid echo reply: got id=%d seq=%d, want id=%d seq=%d",
|
|
||||||
replyEcho.ID, replyEcho.Seq, requestPing.ID, requestPing.Seq)
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("unexpected ICMP message type: %+v", replyMsg)
|
|
||||||
}
|
|
||||||
|
|
||||||
duration := time.Since(start)
|
|
||||||
logger.Info("Ping reply from %v: time=%v", peer, duration)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func startPingCheck(serverIP string, stopChan chan struct{}) {
|
|
||||||
ticker := time.NewTicker(10 * time.Second)
|
|
||||||
defer ticker.Stop()
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-ticker.C:
|
|
||||||
err := ping(serverIP)
|
|
||||||
if err != nil {
|
|
||||||
logger.Warn("Periodic ping failed: %v", err)
|
|
||||||
logger.Warn("HINT: Check if the WireGuard tunnel is up and the server is reachable")
|
|
||||||
}
|
|
||||||
case <-stopChan:
|
|
||||||
logger.Info("Stopping ping check")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
func pingWithRetry(dst string) error {
|
|
||||||
const (
|
|
||||||
maxAttempts = 5
|
|
||||||
retryDelay = 2 * time.Second
|
|
||||||
)
|
|
||||||
|
|
||||||
var lastErr error
|
|
||||||
for attempt := 1; attempt <= maxAttempts; attempt++ {
|
|
||||||
logger.Info("Ping attempt %d of %d", attempt, maxAttempts)
|
|
||||||
|
|
||||||
if err := ping(dst); err != nil {
|
|
||||||
lastErr = err
|
|
||||||
logger.Warn("Ping attempt %d failed: %v", attempt, err)
|
|
||||||
|
|
||||||
if attempt < maxAttempts {
|
|
||||||
time.Sleep(retryDelay)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return fmt.Errorf("all ping attempts failed after %d tries, last error: %w",
|
|
||||||
maxAttempts, lastErr)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Successful ping
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmt.Errorf("unexpected error: all ping attempts failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseLogLevel(level string) logger.LogLevel {
|
func parseLogLevel(level string) logger.LogLevel {
|
||||||
switch strings.ToUpper(level) {
|
switch strings.ToUpper(level) {
|
||||||
@@ -321,7 +237,7 @@ func main() {
|
|||||||
flag.StringVar(&logLevel, "log-level", "INFO", "Log level (DEBUG, INFO, WARN, ERROR, FATAL)")
|
flag.StringVar(&logLevel, "log-level", "INFO", "Log level (DEBUG, INFO, WARN, ERROR, FATAL)")
|
||||||
}
|
}
|
||||||
if interfaceName == "" {
|
if interfaceName == "" {
|
||||||
flag.StringVar(&interfaceName, "interface", "wg-1", "Name of the WireGuard interface")
|
flag.StringVar(&interfaceName, "interface", "wg2", "Name of the WireGuard interface")
|
||||||
}
|
}
|
||||||
if generateAndSaveKeyTo == "" {
|
if generateAndSaveKeyTo == "" {
|
||||||
flag.StringVar(&generateAndSaveKeyTo, "generateAndSaveKeyTo", "", "Path to save generated private key")
|
flag.StringVar(&generateAndSaveKeyTo, "generateAndSaveKeyTo", "", "Path to save generated private key")
|
||||||
@@ -367,7 +283,7 @@ func main() {
|
|||||||
|
|
||||||
// Create TUN device and network stack
|
// Create TUN device and network stack
|
||||||
var dev *device.Device
|
var dev *device.Device
|
||||||
var connected bool
|
// var connected bool
|
||||||
var wgData WgData
|
var wgData WgData
|
||||||
|
|
||||||
olm.RegisterHandler("olm/terminate", func(msg websocket.WSMessage) {
|
olm.RegisterHandler("olm/terminate", func(msg websocket.WSMessage) {
|
||||||
@@ -382,16 +298,16 @@ func main() {
|
|||||||
olm.RegisterHandler("olm/wg/connect", func(msg websocket.WSMessage) {
|
olm.RegisterHandler("olm/wg/connect", func(msg websocket.WSMessage) {
|
||||||
logger.Info("Received registration message")
|
logger.Info("Received registration message")
|
||||||
|
|
||||||
if connected {
|
// if connected {
|
||||||
logger.Info("Already connected! But I will send a ping anyway...")
|
// logger.Info("Already connected! But I will send a ping anyway...")
|
||||||
err := pingWithRetry(wgData.ServerIP)
|
// err := pingWithRetry(wgData.ServerIP)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
// Handle complete failure after all retries
|
// // Handle complete failure after all retries
|
||||||
logger.Warn("Failed to ping %s: %v", wgData.ServerIP, err)
|
// logger.Warn("Failed to ping %s: %v", wgData.ServerIP, err)
|
||||||
logger.Warn("HINT: Do you have UDP port 51280 (or the port in config.yml) open on your Pangolin server?")
|
// logger.Warn("HINT: Do you have UDP port 51280 (or the port in config.yml) open on your Pangolin server?")
|
||||||
}
|
// }
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
|
|
||||||
jsonData, err := json.Marshal(msg.Data)
|
jsonData, err := json.Marshal(msg.Data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -461,20 +377,20 @@ persistent_keepalive_interval=5`, fixKey(privateKey.String()), fixKey(wgData.Pub
|
|||||||
logger.Error("Failed to bring up WireGuard device: %v", err)
|
logger.Error("Failed to bring up WireGuard device: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Info("WireGuard device created. Lets ping the server now...")
|
logger.Info("WireGuard device created.")
|
||||||
// Ping to bring the tunnel up on the server side quickly
|
// Ping to bring the tunnel up on the server side quickly
|
||||||
// ping(tnet, wgData.ServerIP)
|
// ping(tnet, wgData.ServerIP)
|
||||||
err = pingWithRetry(wgData.ServerIP)
|
// err = pingWithRetry(wgData.ServerIP)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
// Handle complete failure after all retries
|
// // Handle complete failure after all retries
|
||||||
logger.Error("Failed to ping %s: %v", wgData.ServerIP, err)
|
// logger.Error("Failed to ping %s: %v", wgData.ServerIP, err)
|
||||||
}
|
// }
|
||||||
|
|
||||||
if !connected {
|
// if !connected {
|
||||||
logger.Info("Starting ping check")
|
// logger.Info("Starting ping check")
|
||||||
startPingCheck(wgData.ServerIP, pingStopChan)
|
// startPingCheck(wgData.ServerIP, pingStopChan)
|
||||||
}
|
// }
|
||||||
connected = true
|
// connected = true
|
||||||
})
|
})
|
||||||
|
|
||||||
olm.OnConnect(func() error {
|
olm.OnConnect(func() error {
|
||||||
|
|||||||
Reference in New Issue
Block a user