violet/proxy/hybrid-transport.go

99 lines
3.2 KiB
Go
Raw Normal View History

2023-06-03 19:33:06 +01:00
package proxy
import (
"crypto/tls"
2024-05-13 19:33:33 +01:00
"github.com/1f349/violet/logger"
2023-08-17 14:38:00 +01:00
"github.com/1f349/violet/proxy/websocket"
"github.com/google/uuid"
2023-06-03 19:33:06 +01:00
"net"
"net/http"
"sync"
"time"
)
2024-05-13 19:33:33 +01:00
var loggerSecure = logger.Logger.WithPrefix("Violet Secure Transport")
var loggerInsecure = logger.Logger.WithPrefix("Violet Insecure Transport")
var loggerWebsocket = logger.Logger.WithPrefix("Violet Websocket Transport")
2023-06-03 19:33:06 +01:00
type HybridTransport struct {
baseDialer *net.Dialer
normalTransport http.RoundTripper
insecureTransport http.RoundTripper
socksSync *sync.RWMutex
socksTransport map[string]http.RoundTripper
2023-08-17 14:38:00 +01:00
ws *websocket.Server
2023-06-03 19:33:06 +01:00
}
// NewHybridTransport creates a new hybrid transport
2023-08-17 14:38:00 +01:00
func NewHybridTransport(ws *websocket.Server) *HybridTransport {
return NewHybridTransportWithCalls(nil, nil, ws)
2023-06-03 19:33:06 +01:00
}
// NewHybridTransportWithCalls creates new hybrid transport with custom normal
// and insecure http.RoundTripper functions.
//
// NewHybridTransportWithCalls(nil, nil) is equivalent to NewHybridTransport()
2023-08-17 14:38:00 +01:00
func NewHybridTransportWithCalls(normal, insecure http.RoundTripper, ws *websocket.Server) *HybridTransport {
2023-06-03 19:33:06 +01:00
h := &HybridTransport{
baseDialer: &net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
},
normalTransport: normal,
insecureTransport: insecure,
2023-08-17 14:38:00 +01:00
ws: ws,
2023-06-03 19:33:06 +01:00
}
if h.normalTransport == nil {
h.normalTransport = &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: h.baseDialer.DialContext,
ForceAttemptHTTP2: true,
MaxIdleConns: 15,
TLSHandshakeTimeout: 10 * time.Second,
IdleConnTimeout: 30 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
ResponseHeaderTimeout: 10 * time.Second,
2023-08-30 13:24:39 +01:00
DisableKeepAlives: true,
2023-06-03 19:33:06 +01:00
}
}
if h.insecureTransport == nil {
h.insecureTransport = &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: h.baseDialer.DialContext,
ForceAttemptHTTP2: true,
MaxIdleConns: 15,
TLSHandshakeTimeout: 10 * time.Second,
IdleConnTimeout: 30 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
ResponseHeaderTimeout: 10 * time.Second,
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
2023-08-30 13:24:39 +01:00
DisableKeepAlives: true,
2023-06-03 19:33:06 +01:00
}
}
return h
}
// SecureRoundTrip calls the secure transport
func (h *HybridTransport) SecureRoundTrip(req *http.Request) (*http.Response, error) {
u := uuid.New()
2024-05-13 19:33:33 +01:00
loggerSecure.Info("Start upgrade", "id", u)
defer loggerSecure.Info("Stop upgrade", "id", u)
2023-06-03 19:33:06 +01:00
return h.normalTransport.RoundTrip(req)
}
// InsecureRoundTrip calls the insecure transport
func (h *HybridTransport) InsecureRoundTrip(req *http.Request) (*http.Response, error) {
u := uuid.New()
2024-05-13 19:33:33 +01:00
loggerInsecure.Info("Start upgrade", "id", u)
defer loggerInsecure.Info("Stop upgrade", "id", u)
2023-06-03 19:33:06 +01:00
return h.insecureTransport.RoundTrip(req)
}
2023-08-17 14:38:00 +01:00
// ConnectWebsocket calls the websocket upgrader and thus hijacks the connection
func (h *HybridTransport) ConnectWebsocket(rw http.ResponseWriter, req *http.Request) {
u := uuid.New()
2024-05-13 19:33:33 +01:00
loggerWebsocket.Info("Start upgrade", "id", u)
2023-08-17 14:38:00 +01:00
h.ws.Upgrade(rw, req)
2024-05-13 19:33:33 +01:00
loggerWebsocket.Info("Stop upgrade", "id", u)
2023-08-17 14:38:00 +01:00
}