Fix Tunnel: ID-Sync Backend<->Agent, bidirektionaler Proxy, API-Key via Query-Param
- Backend gibt tunnel_id vor, Agent uebernimmt sie - Proxy-Verbindung bidirektional: Daten vom Agent zurueck an TCP-Client - Middleware akzeptiert api_key als Query-Parameter (fuer WebSocket) - Getestet: OPNsense WebUI erreichbar ueber Tunnel
This commit is contained in:
parent
f47154787d
commit
fa68e191f9
@ -116,8 +116,11 @@ func (h *Handler) handleTunnelOpen(msg Message) Message {
|
||||
}
|
||||
targetPort := int(targetPortFloat)
|
||||
|
||||
// Tunnel öffnen
|
||||
tunnelID, err := h.client.tunnelManager.OpenTunnel(targetHost, targetPort)
|
||||
// Tunnel-ID vom Backend uebernehmen (falls vorhanden)
|
||||
backendTunnelID, _ := msg.Params["tunnel_id"].(string)
|
||||
|
||||
// Tunnel oeffnen
|
||||
tunnelID, err := h.client.tunnelManager.OpenTunnel(targetHost, targetPort, backendTunnelID)
|
||||
if err != nil {
|
||||
response.Status = "error"
|
||||
response.Error = fmt.Sprintf("Tunnel öffnen fehlgeschlagen: %v", err)
|
||||
|
||||
@ -33,9 +33,14 @@ func NewTunnelManager(client *Client) *TunnelManager {
|
||||
}
|
||||
}
|
||||
|
||||
func (tm *TunnelManager) OpenTunnel(targetHost string, targetPort int) (string, error) {
|
||||
// Eindeutige Tunnel-ID generieren
|
||||
tunnelID := tm.generateTunnelID()
|
||||
func (tm *TunnelManager) OpenTunnel(targetHost string, targetPort int, tunnelID ...string) (string, error) {
|
||||
// Tunnel-ID vom Backend uebernehmen oder selbst generieren
|
||||
id := ""
|
||||
if len(tunnelID) > 0 && tunnelID[0] != "" {
|
||||
id = tunnelID[0]
|
||||
} else {
|
||||
id = tm.generateTunnelID()
|
||||
}
|
||||
|
||||
// Verbindung zum Ziel aufbauen
|
||||
target := fmt.Sprintf("%s:%d", targetHost, targetPort)
|
||||
@ -46,7 +51,7 @@ func (tm *TunnelManager) OpenTunnel(targetHost string, targetPort int) (string,
|
||||
|
||||
// Tunnel erstellen
|
||||
tunnel := &Tunnel{
|
||||
ID: tunnelID,
|
||||
ID: id,
|
||||
TargetHost: targetHost,
|
||||
TargetPort: targetPort,
|
||||
Conn: conn,
|
||||
@ -56,13 +61,13 @@ func (tm *TunnelManager) OpenTunnel(targetHost string, targetPort int) (string,
|
||||
|
||||
// Tunnel registrieren
|
||||
tm.mutex.Lock()
|
||||
tm.tunnels[tunnelID] = tunnel
|
||||
tm.tunnels[id] = tunnel
|
||||
tm.mutex.Unlock()
|
||||
|
||||
// Data-Forwarding starten
|
||||
go tm.forwardData(tunnel)
|
||||
|
||||
return tunnelID, nil
|
||||
return id, nil
|
||||
}
|
||||
|
||||
func (tm *TunnelManager) CloseTunnel(tunnelID string) error {
|
||||
|
||||
@ -15,6 +15,10 @@ func APIKeyAuth(validKeys []string, next http.Handler) http.Handler {
|
||||
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
key := r.Header.Get("X-API-Key")
|
||||
// Fallback: Query-Parameter (fuer WebSocket-Verbindungen)
|
||||
if key == "" {
|
||||
key = r.URL.Query().Get("api_key")
|
||||
}
|
||||
if key == "" || !keySet[key] {
|
||||
http.Error(w, `{"error":"unauthorized"}`, http.StatusUnauthorized)
|
||||
return
|
||||
|
||||
@ -21,6 +21,9 @@ type BackendTunnel struct {
|
||||
Listener net.Listener
|
||||
Active bool
|
||||
CreatedAt time.Time
|
||||
// Aktive Proxy-Verbindungen (fuer Rueckkanal)
|
||||
proxyConn net.Conn
|
||||
proxyMutex sync.Mutex
|
||||
}
|
||||
|
||||
type TunnelManager struct {
|
||||
@ -86,12 +89,13 @@ func (tm *TunnelManager) OpenTunnel(agentID, targetHost string, targetPort int)
|
||||
// Proxy-Server starten
|
||||
go tm.runTunnelProxy(tunnel)
|
||||
|
||||
// Command an Agent senden
|
||||
// Command an Agent senden — tunnel_id vorgeben damit Backend und Agent dieselbe ID nutzen
|
||||
cmd := map[string]interface{}{
|
||||
"type": "command",
|
||||
"id": tm.generateTunnelID(),
|
||||
"command": "tunnel_open",
|
||||
"params": map[string]interface{}{
|
||||
"tunnel_id": tunnelID,
|
||||
"target_host": targetHost,
|
||||
"target_port": targetPort,
|
||||
},
|
||||
@ -220,28 +224,38 @@ func (tm *TunnelManager) handleProxyConnection(tunnel *BackendTunnel, conn net.C
|
||||
|
||||
log.Printf("Tunnel %s: Proxy-Verbindung von %s", tunnel.ID, conn.RemoteAddr())
|
||||
|
||||
// Buffer für TCP-Data
|
||||
// Aktive Proxy-Verbindung registrieren (fuer Rueckkanal vom Agent)
|
||||
tunnel.proxyMutex.Lock()
|
||||
tunnel.proxyConn = conn
|
||||
tunnel.proxyMutex.Unlock()
|
||||
|
||||
defer func() {
|
||||
tunnel.proxyMutex.Lock()
|
||||
tunnel.proxyConn = nil
|
||||
tunnel.proxyMutex.Unlock()
|
||||
log.Printf("Tunnel %s: Proxy-Verbindung beendet", tunnel.ID)
|
||||
}()
|
||||
|
||||
// Buffer fuer TCP-Data
|
||||
buffer := make([]byte, 32768)
|
||||
|
||||
for {
|
||||
for tunnel.Active {
|
||||
n, err := conn.Read(buffer)
|
||||
if err != nil {
|
||||
if err.Error() != "EOF" {
|
||||
if err.Error() != "EOF" && tunnel.Active {
|
||||
log.Printf("Tunnel %s: Proxy-Read-Fehler: %v", tunnel.ID, err)
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
if n > 0 {
|
||||
// Daten über WebSocket an Agent weiterleiten
|
||||
// Daten ueber WebSocket an Agent weiterleiten
|
||||
if err := tm.sendTunnelData(tunnel.ID, buffer[:n]); err != nil {
|
||||
log.Printf("Tunnel %s: Weiterleitung fehlgeschlagen: %v", tunnel.ID, err)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.Printf("Tunnel %s: Proxy-Verbindung beendet", tunnel.ID)
|
||||
}
|
||||
|
||||
func (tm *TunnelManager) sendTunnelData(tunnelID string, data []byte) error {
|
||||
@ -284,12 +298,19 @@ func (tm *TunnelManager) ProcessBinaryMessage(agentID string, data []byte) error
|
||||
return fmt.Errorf("Tunnel %s nicht gefunden oder inaktiv", tunnelID)
|
||||
}
|
||||
|
||||
// Hier würden wir die Daten an aktive Proxy-Verbindungen weiterleiten
|
||||
// Da das komplexer ist, implementieren wir erstmal nur das Logging
|
||||
log.Printf("Tunnel %s: %d Bytes von Agent erhalten", tunnelID, len(payload))
|
||||
// Daten an aktive Proxy-Verbindung weiterleiten
|
||||
tunnel.proxyMutex.Lock()
|
||||
conn := tunnel.proxyConn
|
||||
tunnel.proxyMutex.Unlock()
|
||||
|
||||
// TODO: Implement actual forwarding to active proxy connections
|
||||
// Das würde einen Connection-Pool pro Tunnel erfordern
|
||||
if conn == nil {
|
||||
return fmt.Errorf("Tunnel %s: keine aktive Proxy-Verbindung", tunnelID)
|
||||
}
|
||||
|
||||
_, writeErr := conn.Write(payload)
|
||||
if writeErr != nil {
|
||||
return fmt.Errorf("Tunnel %s: Proxy-Write fehlgeschlagen: %w", tunnelID, writeErr)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user