mirror of
https://github.com/fosrl/gerbil.git
synced 2026-02-27 07:16:47 +00:00
Basic relay working!
This commit is contained in:
107
main.go
107
main.go
@@ -16,6 +16,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/fosrl/gerbil/logger"
|
||||
"github.com/fosrl/gerbil/relay"
|
||||
"github.com/vishvananda/netlink"
|
||||
"golang.zx2c4.com/wireguard/wgctrl"
|
||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||
@@ -88,99 +89,26 @@ func parseLogLevel(level string) logger.LogLevel {
|
||||
}
|
||||
}
|
||||
|
||||
// Update the startUDPServer function
|
||||
func startUDPServer(addr string, server string) {
|
||||
udpAddr, err := net.ResolveUDPAddr("udp", addr)
|
||||
if err != nil {
|
||||
logger.Fatal("Failed to resolve UDP address: %v", err)
|
||||
}
|
||||
|
||||
conn, err := net.ListenUDP("udp", udpAddr)
|
||||
if err != nil {
|
||||
logger.Fatal("Failed to start UDP server: %v", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
logger.Info("UDP server listening on %s", addr)
|
||||
|
||||
buffer := make([]byte, 1024)
|
||||
for {
|
||||
n, remoteAddr, err := conn.ReadFromUDP(buffer)
|
||||
if err != nil {
|
||||
logger.Error("Error reading UDP packet: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
var msg HolePunchMessage
|
||||
if err := json.Unmarshal(buffer[:n], &msg); err != nil {
|
||||
logger.Error("Error unmarshaling message: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
// Create endpoint info
|
||||
endpoint := ClientEndpoint{
|
||||
OlmID: msg.OlmID,
|
||||
NewtID: msg.NewtID,
|
||||
IP: remoteAddr.IP.String(),
|
||||
Port: remoteAddr.Port,
|
||||
Timestamp: time.Now().Unix(),
|
||||
}
|
||||
|
||||
// Send the endpoint info to the Olm server
|
||||
go notifyServer(endpoint, server)
|
||||
}
|
||||
}
|
||||
|
||||
// Add this new function
|
||||
func notifyServer(endpoint ClientEndpoint, server string) {
|
||||
jsonData, err := json.Marshal(endpoint)
|
||||
if err != nil {
|
||||
logger.Error("Failed to marshal endpoint data: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := http.Post(server,
|
||||
"application/json",
|
||||
bytes.NewBuffer(jsonData))
|
||||
if err != nil {
|
||||
logger.Error("Failed to notify Olm server: %v", err)
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
logger.Error("Olm server returned non-OK status: %d, body: %s",
|
||||
resp.StatusCode,
|
||||
string(body))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
var (
|
||||
err error
|
||||
wgconfig WgConfig
|
||||
configFile string
|
||||
remoteConfigURL string
|
||||
reportBandwidthTo string
|
||||
generateAndSaveKeyTo string
|
||||
reachableAt string
|
||||
logLevel string
|
||||
mtu string
|
||||
reportHolePunchTo string
|
||||
)
|
||||
|
||||
interfaceName = os.Getenv("INTERFACE")
|
||||
configFile = os.Getenv("CONFIG")
|
||||
remoteConfigURL = os.Getenv("REMOTE_CONFIG")
|
||||
listenAddr = os.Getenv("LISTEN")
|
||||
reportBandwidthTo = os.Getenv("REPORT_BANDWIDTH_TO")
|
||||
generateAndSaveKeyTo = os.Getenv("GENERATE_AND_SAVE_KEY_TO")
|
||||
reachableAt = os.Getenv("REACHABLE_AT")
|
||||
logLevel = os.Getenv("LOG_LEVEL")
|
||||
mtu = os.Getenv("MTU")
|
||||
reportHolePunchTo = os.Getenv("REPORT_HOLE_PUNCH_TO")
|
||||
|
||||
if interfaceName == "" {
|
||||
flag.StringVar(&interfaceName, "interface", "wg0", "Name of the WireGuard interface")
|
||||
@@ -189,17 +117,16 @@ func main() {
|
||||
flag.StringVar(&configFile, "config", "", "Path to local configuration file")
|
||||
}
|
||||
if remoteConfigURL == "" {
|
||||
flag.StringVar(&remoteConfigURL, "remoteConfig", "", "URL to fetch remote configuration")
|
||||
flag.StringVar(&remoteConfigURL, "remoteConfig", "", "URL of the Pangolin server")
|
||||
}
|
||||
if listenAddr == "" {
|
||||
flag.StringVar(&listenAddr, "listen", ":3003", "Address to listen on")
|
||||
}
|
||||
if reportBandwidthTo == "" {
|
||||
flag.StringVar(&reportBandwidthTo, "reportBandwidthTo", "", "Address to listen on")
|
||||
}
|
||||
if reportHolePunchTo == "" {
|
||||
flag.StringVar(&reportHolePunchTo, "reportHolePunchTo", "", "Address to listen on")
|
||||
}
|
||||
// DEPRECATED AND UNSED: reportBandwidthTo
|
||||
// allow reportBandwidthTo to be passed but dont do anything with it just thow it away
|
||||
reportBandwidthTo := ""
|
||||
flag.StringVar(&reportBandwidthTo, "reportBandwidthTo", "", "DEPRECATED: Use remoteConfig instead")
|
||||
|
||||
if generateAndSaveKeyTo == "" {
|
||||
flag.StringVar(&generateAndSaveKeyTo, "generateAndSaveKeyTo", "", "Path to save generated private key")
|
||||
}
|
||||
@@ -232,6 +159,10 @@ func main() {
|
||||
logger.Fatal("You must provide either a config file or a remote config URL, not both")
|
||||
}
|
||||
|
||||
// clean up the reomte config URL for backwards compatibility
|
||||
remoteConfigURL = strings.TrimSuffix(remoteConfigURL, "/gerbil/get-config")
|
||||
remoteConfigURL = strings.TrimSuffix(remoteConfigURL, "/")
|
||||
|
||||
var key wgtypes.Key
|
||||
// if generateAndSaveKeyTo is provided, generate a private key and save it to the file. if the file already exists, load the key from the file
|
||||
if generateAndSaveKeyTo != "" {
|
||||
@@ -279,8 +210,8 @@ func main() {
|
||||
} else {
|
||||
// loop until we get the config
|
||||
for wgconfig.PrivateKey == "" {
|
||||
logger.Info("Fetching remote config from %s", remoteConfigURL)
|
||||
wgconfig, err = loadRemoteConfig(remoteConfigURL, key, reachableAt)
|
||||
logger.Info("Fetching remote config from %s", remoteConfigURL+"/gerbil/get-config")
|
||||
wgconfig, err = loadRemoteConfig(remoteConfigURL+"/gerbil/get-config", key, reachableAt)
|
||||
if err != nil {
|
||||
logger.Error("Failed to load configuration: %v", err)
|
||||
time.Sleep(5 * time.Second)
|
||||
@@ -304,12 +235,14 @@ func main() {
|
||||
// Ensure the WireGuard peers exist
|
||||
ensureWireguardPeers(wgconfig.Peers)
|
||||
|
||||
if reportBandwidthTo != "" {
|
||||
go periodicBandwidthCheck(reportBandwidthTo)
|
||||
}
|
||||
go periodicBandwidthCheck(remoteConfigURL + "/gerbil/receive-bandwidth")
|
||||
|
||||
// run the udp server
|
||||
go startUDPServer(":21820", reportHolePunchTo)
|
||||
server := relay.NewUDPProxyServer(":21820", remoteConfigURL, key)
|
||||
err = server.Start()
|
||||
if err != nil {
|
||||
logger.Fatal("Failed to start server: %v", err)
|
||||
}
|
||||
defer server.Stop()
|
||||
|
||||
http.HandleFunc("/peer", handlePeer)
|
||||
logger.Info("Starting server on %s", listenAddr)
|
||||
|
||||
Reference in New Issue
Block a user