package websocket
import (
"fmt"
"net/http"
"net/url"
portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/crypto"
"github.com/gorilla/websocket"
"github.com/koding/websocketproxy"
)
func (handler *Handler) proxyEdgeAgentWebsocketRequest(w http.ResponseWriter, r *http.Request, params *webSocketRequestParams) error {
tunnel, err := handler.ReverseTunnelService.GetActiveTunnel(params.endpoint)
if err != nil {
return err
}
endpointURL, err := url.Parse(fmt.Sprintf("http://127.0.0.1:%d", tunnel.Port))
endpointURL.Scheme = "ws"
proxy := websocketproxy.NewProxy(endpointURL)
signature, err := handler.SignatureService.CreateSignature(portainer.PortainerAgentSignatureMessage)
proxy.Director = func(incoming *http.Request, out http.Header) {
out.Set(portainer.PortainerAgentPublicKeyHeader, handler.SignatureService.EncodedPublicKey())
out.Set(portainer.PortainerAgentSignatureHeader, signature)
out.Set(portainer.PortainerAgentTargetHeader, params.nodeName)
out.Set(portainer.PortainerAgentKubernetesSATokenHeader, params.token)
handler.ReverseTunnelService.SetTunnelStatusToActive(params.endpoint.ID)
handler.ReverseTunnelService.KeepTunnelAlive(params.endpoint.ID, r.Context(), portainer.WebSocketKeepAlive)
proxy.ServeHTTP(w, r)
return nil
func (handler *Handler) proxyAgentWebsocketRequest(w http.ResponseWriter, r *http.Request, params *webSocketRequestParams) error {
endpointURL := params.endpoint.URL
if params.endpoint.Type == portainer.AgentOnKubernetesEnvironment {
endpointURL = fmt.Sprintf("http://%s", params.endpoint.URL)
agentURL, err := url.Parse(endpointURL)
agentURL.Scheme = "ws"
proxy := websocketproxy.NewProxy(agentURL)
if params.endpoint.TLSConfig.TLS || params.endpoint.TLSConfig.TLSSkipVerify {
agentURL.Scheme = "wss"
tlsConfig := crypto.CreateTLSConfiguration()
tlsConfig.InsecureSkipVerify = params.endpoint.TLSConfig.TLSSkipVerify
proxy.Dialer = &websocket.Dialer{
TLSClientConfig: tlsConfig,