mirror of
https://github.com/fosrl/gerbil.git
synced 2026-03-01 16:26:42 +00:00
Allow for updating destinations
This commit is contained in:
83
main.go
83
main.go
@@ -82,6 +82,12 @@ type ProxyMappingUpdate struct {
|
|||||||
NewDestination relay.PeerDestination `json:"newDestination"`
|
NewDestination relay.PeerDestination `json:"newDestination"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UpdateDestinationsRequest struct {
|
||||||
|
SourceIP string `json:"sourceIp"`
|
||||||
|
SourcePort int `json:"sourcePort"`
|
||||||
|
Destinations []relay.PeerDestination `json:"destinations"`
|
||||||
|
}
|
||||||
|
|
||||||
func parseLogLevel(level string) logger.LogLevel {
|
func parseLogLevel(level string) logger.LogLevel {
|
||||||
switch strings.ToUpper(level) {
|
switch strings.ToUpper(level) {
|
||||||
case "DEBUG":
|
case "DEBUG":
|
||||||
@@ -252,7 +258,7 @@ func main() {
|
|||||||
go periodicBandwidthCheck(remoteConfigURL + "/gerbil/receive-bandwidth")
|
go periodicBandwidthCheck(remoteConfigURL + "/gerbil/receive-bandwidth")
|
||||||
|
|
||||||
// Start the UDP proxy server
|
// Start the UDP proxy server
|
||||||
proxyServer = relay.NewUDPProxyServer(":21820", remoteConfigURL, key)
|
proxyServer = relay.NewUDPProxyServer(":21820", remoteConfigURL, key, reachableAt)
|
||||||
err = proxyServer.Start()
|
err = proxyServer.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatal("Failed to start UDP proxy server: %v", err)
|
logger.Fatal("Failed to start UDP proxy server: %v", err)
|
||||||
@@ -262,6 +268,7 @@ func main() {
|
|||||||
// Set up HTTP server
|
// Set up HTTP server
|
||||||
http.HandleFunc("/peer", handlePeer)
|
http.HandleFunc("/peer", handlePeer)
|
||||||
http.HandleFunc("/update-proxy-mapping", handleUpdateProxyMapping)
|
http.HandleFunc("/update-proxy-mapping", handleUpdateProxyMapping)
|
||||||
|
http.HandleFunc("/update-destinations", handleUpdateDestinations)
|
||||||
logger.Info("Starting HTTP server on %s", listenAddr)
|
logger.Info("Starting HTTP server on %s", listenAddr)
|
||||||
|
|
||||||
// Run HTTP server in a goroutine
|
// Run HTTP server in a goroutine
|
||||||
@@ -727,29 +734,34 @@ func removePeerInternal(publicKey string) error {
|
|||||||
|
|
||||||
func handleUpdateProxyMapping(w http.ResponseWriter, r *http.Request) {
|
func handleUpdateProxyMapping(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.Method != http.MethodPost {
|
if r.Method != http.MethodPost {
|
||||||
|
logger.Error("Invalid method: %s", r.Method)
|
||||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var update ProxyMappingUpdate
|
var update ProxyMappingUpdate
|
||||||
if err := json.NewDecoder(r.Body).Decode(&update); err != nil {
|
if err := json.NewDecoder(r.Body).Decode(&update); err != nil {
|
||||||
|
logger.Error("Failed to decode request body: %v", err)
|
||||||
http.Error(w, fmt.Sprintf("Failed to decode request body: %v", err), http.StatusBadRequest)
|
http.Error(w, fmt.Sprintf("Failed to decode request body: %v", err), http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate the update request
|
// Validate the update request
|
||||||
if update.OldDestination.DestinationIP == "" || update.NewDestination.DestinationIP == "" {
|
if update.OldDestination.DestinationIP == "" || update.NewDestination.DestinationIP == "" {
|
||||||
|
logger.Error("Both old and new destination IP addresses are required")
|
||||||
http.Error(w, "Both old and new destination IP addresses are required", http.StatusBadRequest)
|
http.Error(w, "Both old and new destination IP addresses are required", http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if update.OldDestination.DestinationPort <= 0 || update.NewDestination.DestinationPort <= 0 {
|
if update.OldDestination.DestinationPort <= 0 || update.NewDestination.DestinationPort <= 0 {
|
||||||
|
logger.Error("Both old and new destination ports must be positive integers")
|
||||||
http.Error(w, "Both old and new destination ports must be positive integers", http.StatusBadRequest)
|
http.Error(w, "Both old and new destination ports must be positive integers", http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the proxy mappings in the relay server
|
// Update the proxy mappings in the relay server
|
||||||
if proxyServer == nil {
|
if proxyServer == nil {
|
||||||
|
logger.Error("Proxy server is not available")
|
||||||
http.Error(w, "Proxy server is not available", http.StatusInternalServerError)
|
http.Error(w, "Proxy server is not available", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -770,6 +782,75 @@ func handleUpdateProxyMapping(w http.ResponseWriter, r *http.Request) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func handleUpdateDestinations(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.Method != http.MethodPost {
|
||||||
|
logger.Error("Invalid method: %s", r.Method)
|
||||||
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var request UpdateDestinationsRequest
|
||||||
|
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
|
||||||
|
logger.Error("Failed to decode request body: %v", err)
|
||||||
|
http.Error(w, fmt.Sprintf("Failed to decode request body: %v", err), http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the request
|
||||||
|
if request.SourceIP == "" {
|
||||||
|
logger.Error("Source IP address is required")
|
||||||
|
http.Error(w, "Source IP address is required", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if request.SourcePort <= 0 {
|
||||||
|
logger.Error("Source port must be a positive integer")
|
||||||
|
http.Error(w, "Source port must be a positive integer", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(request.Destinations) == 0 {
|
||||||
|
logger.Error("At least one destination is required")
|
||||||
|
http.Error(w, "At least one destination is required", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate each destination
|
||||||
|
for i, dest := range request.Destinations {
|
||||||
|
if dest.DestinationIP == "" {
|
||||||
|
logger.Error("Destination IP is required for destination %d", i)
|
||||||
|
http.Error(w, fmt.Sprintf("Destination IP is required for destination %d", i), http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if dest.DestinationPort <= 0 {
|
||||||
|
logger.Error("Destination port must be a positive integer for destination %d", i)
|
||||||
|
http.Error(w, fmt.Sprintf("Destination port must be a positive integer for destination %d", i), http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the proxy mappings in the relay server
|
||||||
|
if proxyServer == nil {
|
||||||
|
logger.Error("Proxy server is not available")
|
||||||
|
http.Error(w, "Proxy server is not available", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
proxyServer.UpdateProxyMapping(request.SourceIP, request.SourcePort, request.Destinations)
|
||||||
|
|
||||||
|
logger.Info("Updated proxy mapping for %s:%d with %d destinations",
|
||||||
|
request.SourceIP, request.SourcePort, len(request.Destinations))
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
json.NewEncoder(w).Encode(map[string]interface{}{
|
||||||
|
"status": "Destinations updated successfully",
|
||||||
|
"sourceIP": request.SourceIP,
|
||||||
|
"sourcePort": request.SourcePort,
|
||||||
|
"destinationCount": len(request.Destinations),
|
||||||
|
"destinations": request.Destinations,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func periodicBandwidthCheck(endpoint string) {
|
func periodicBandwidthCheck(endpoint string) {
|
||||||
ticker := time.NewTicker(10 * time.Second)
|
ticker := time.NewTicker(10 * time.Second)
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -31,12 +30,13 @@ type HolePunchMessage struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ClientEndpoint struct {
|
type ClientEndpoint struct {
|
||||||
OlmID string `json:"olmId"`
|
OlmID string `json:"olmId"`
|
||||||
NewtID string `json:"newtId"`
|
NewtID string `json:"newtId"`
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
IP string `json:"ip"`
|
IP string `json:"ip"`
|
||||||
Port int `json:"port"`
|
Port int `json:"port"`
|
||||||
Timestamp int64 `json:"timestamp"`
|
Timestamp int64 `json:"timestamp"`
|
||||||
|
ReachableAt string `json:"reachableAt"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Updated to support multiple destination peers
|
// Updated to support multiple destination peers
|
||||||
@@ -104,15 +104,18 @@ type UDPProxyServer struct {
|
|||||||
// Session tracking for WireGuard peers
|
// Session tracking for WireGuard peers
|
||||||
// Key format: "senderIndex:receiverIndex"
|
// Key format: "senderIndex:receiverIndex"
|
||||||
wgSessions sync.Map
|
wgSessions sync.Map
|
||||||
|
// ReachableAt is the URL where this server can be reached
|
||||||
|
ReachableAt string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewUDPProxyServer initializes the server with a buffered packet channel.
|
// NewUDPProxyServer initializes the server with a buffered packet channel.
|
||||||
func NewUDPProxyServer(addr, serverURL string, privateKey wgtypes.Key) *UDPProxyServer {
|
func NewUDPProxyServer(addr, serverURL string, privateKey wgtypes.Key, reachableAt string) *UDPProxyServer {
|
||||||
return &UDPProxyServer{
|
return &UDPProxyServer{
|
||||||
addr: addr,
|
addr: addr,
|
||||||
serverURL: serverURL,
|
serverURL: serverURL,
|
||||||
privateKey: privateKey,
|
privateKey: privateKey,
|
||||||
packetChan: make(chan Packet, 1000),
|
packetChan: make(chan Packet, 1000),
|
||||||
|
ReachableAt: reachableAt,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,12 +218,13 @@ func (s *UDPProxyServer) packetWorker() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
endpoint := ClientEndpoint{
|
endpoint := ClientEndpoint{
|
||||||
NewtID: msg.NewtID,
|
NewtID: msg.NewtID,
|
||||||
OlmID: msg.OlmID,
|
OlmID: msg.OlmID,
|
||||||
Token: msg.Token,
|
Token: msg.Token,
|
||||||
IP: packet.remoteAddr.IP.String(),
|
IP: packet.remoteAddr.IP.String(),
|
||||||
Port: packet.remoteAddr.Port,
|
Port: packet.remoteAddr.Port,
|
||||||
Timestamp: time.Now().Unix(),
|
Timestamp: time.Now().Unix(),
|
||||||
|
ReachableAt: s.ReachableAt,
|
||||||
}
|
}
|
||||||
logger.Debug("Created endpoint from packet remoteAddr %s: IP=%s, Port=%d", packet.remoteAddr.String(), endpoint.IP, endpoint.Port)
|
logger.Debug("Created endpoint from packet remoteAddr %s: IP=%s, Port=%d", packet.remoteAddr.String(), endpoint.IP, endpoint.Port)
|
||||||
s.notifyServer(endpoint)
|
s.notifyServer(endpoint)
|
||||||
@@ -644,7 +648,7 @@ func (s *UDPProxyServer) notifyServer(endpoint ClientEndpoint) {
|
|||||||
|
|
||||||
// Updated to support multiple destinations
|
// Updated to support multiple destinations
|
||||||
func (s *UDPProxyServer) UpdateProxyMapping(sourceIP string, sourcePort int, destinations []PeerDestination) {
|
func (s *UDPProxyServer) UpdateProxyMapping(sourceIP string, sourcePort int, destinations []PeerDestination) {
|
||||||
key := net.JoinHostPort(sourceIP, strconv.Itoa(sourcePort))
|
key := fmt.Sprintf("%s:%d", sourceIP, sourcePort)
|
||||||
mapping := ProxyMapping{
|
mapping := ProxyMapping{
|
||||||
Destinations: destinations,
|
Destinations: destinations,
|
||||||
LastUsed: time.Now(),
|
LastUsed: time.Now(),
|
||||||
|
|||||||
Reference in New Issue
Block a user