mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-07-03 02:08:45 +00:00
refactor: use path plus header for browser dialer upgrade
Agent-Logs-Url: https://github.com/XTLS/Xray-core/sessions/33541da0-fdc4-4415-b7c4-7183f01b762e Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
c48c475256
commit
57253b736d
@@ -18,7 +18,6 @@ import (
|
|||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/platform"
|
"github.com/xtls/xray-core/common/platform"
|
||||||
"github.com/xtls/xray-core/common/uuid"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed dialer.html
|
//go:embed dialer.html
|
||||||
@@ -35,6 +34,8 @@ var sockoptDialers map[string]*dialerInstance
|
|||||||
var dialerServers map[string]*dialerServer
|
var dialerServers map[string]*dialerServer
|
||||||
var mu sync.RWMutex
|
var mu sync.RWMutex
|
||||||
|
|
||||||
|
const browserDialerSubprotocol = "browser-dialer"
|
||||||
|
|
||||||
var upgrader = &websocket.Upgrader{
|
var upgrader = &websocket.Upgrader{
|
||||||
ReadBufferSize: 0,
|
ReadBufferSize: 0,
|
||||||
WriteBufferSize: 0,
|
WriteBufferSize: 0,
|
||||||
@@ -56,14 +57,12 @@ type webSocketExtra struct {
|
|||||||
type dialerInstance struct {
|
type dialerInstance struct {
|
||||||
conns chan *websocket.Conn
|
conns chan *websocket.Conn
|
||||||
pagePath string
|
pagePath string
|
||||||
wsPath string
|
|
||||||
page []byte
|
page []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type dialerServer struct {
|
type dialerServer struct {
|
||||||
server *http.Server
|
server *http.Server
|
||||||
pageRoutes map[string]*dialerInstance
|
pageRoutes map[string]*dialerInstance
|
||||||
wsRoutes map[string]*dialerInstance
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type browserDialerAddress struct {
|
type browserDialerAddress struct {
|
||||||
@@ -105,16 +104,10 @@ func parseBrowserDialerAddress(addr string) (*browserDialerAddress, bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func newDialerInstance(path string) *dialerInstance {
|
func newDialerInstance(path string) *dialerInstance {
|
||||||
token := uuid.New()
|
|
||||||
csrfToken := token.String()
|
|
||||||
escapedCsrfToken := url.PathEscape(csrfToken)
|
|
||||||
wsPath := path + "/" + escapedCsrfToken
|
|
||||||
page := bytes.ReplaceAll(webpage, []byte("dialerPath"), []byte(strings.TrimPrefix(path, "/")))
|
page := bytes.ReplaceAll(webpage, []byte("dialerPath"), []byte(strings.TrimPrefix(path, "/")))
|
||||||
page = bytes.ReplaceAll(page, []byte("csrfToken"), []byte(escapedCsrfToken))
|
|
||||||
dialer := &dialerInstance{
|
dialer := &dialerInstance{
|
||||||
conns: make(chan *websocket.Conn, 256),
|
conns: make(chan *websocket.Conn, 256),
|
||||||
pagePath: path,
|
pagePath: path,
|
||||||
wsPath: wsPath,
|
|
||||||
page: page,
|
page: page,
|
||||||
}
|
}
|
||||||
return dialer
|
return dialer
|
||||||
@@ -123,19 +116,28 @@ func newDialerInstance(path string) *dialerInstance {
|
|||||||
func newDialerServer(listenAddr string) *dialerServer {
|
func newDialerServer(listenAddr string) *dialerServer {
|
||||||
dialer := &dialerServer{
|
dialer := &dialerServer{
|
||||||
pageRoutes: make(map[string]*dialerInstance),
|
pageRoutes: make(map[string]*dialerInstance),
|
||||||
wsRoutes: make(map[string]*dialerInstance),
|
|
||||||
}
|
}
|
||||||
dialer.server = &http.Server{
|
dialer.server = &http.Server{
|
||||||
Addr: listenAddr,
|
Addr: listenAddr,
|
||||||
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
mu.RLock()
|
mu.RLock()
|
||||||
wsDialer := dialer.wsRoutes[r.URL.Path]
|
|
||||||
pageDialer := dialer.pageRoutes[r.URL.Path]
|
pageDialer := dialer.pageRoutes[r.URL.Path]
|
||||||
mu.RUnlock()
|
mu.RUnlock()
|
||||||
|
|
||||||
if wsDialer != nil {
|
if pageDialer != nil && websocket.IsWebSocketUpgrade(r) {
|
||||||
if conn, err := upgrader.Upgrade(w, r, nil); err == nil {
|
ok := false
|
||||||
wsDialer.conns <- conn
|
for _, protocol := range websocket.Subprotocols(r) {
|
||||||
|
if protocol == browserDialerSubprotocol {
|
||||||
|
ok = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !ok {
|
||||||
|
closeConnection(w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if conn, err := upgrader.Upgrade(w, r, http.Header{"Sec-WebSocket-Protocol": []string{browserDialerSubprotocol}}); err == nil {
|
||||||
|
pageDialer.conns <- conn
|
||||||
} else {
|
} else {
|
||||||
errors.LogError(context.Background(), "Browser dialer http upgrade unexpected error: ", err)
|
errors.LogError(context.Background(), "Browser dialer http upgrade unexpected error: ", err)
|
||||||
}
|
}
|
||||||
@@ -224,7 +226,6 @@ func getDialerByAddress(addr string) *dialerInstance {
|
|||||||
dialer := newDialerInstance(parsed.path)
|
dialer := newDialerInstance(parsed.path)
|
||||||
sockoptDialers[key] = dialer
|
sockoptDialers[key] = dialer
|
||||||
server.pageRoutes[dialer.pagePath] = dialer
|
server.pageRoutes[dialer.pagePath] = dialer
|
||||||
server.wsRoutes[dialer.wsPath] = dialer
|
|
||||||
mu.Unlock()
|
mu.Unlock()
|
||||||
|
|
||||||
if startServer {
|
if startServer {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
// Enable a much more aggressive JIT for performance gains
|
// Enable a much more aggressive JIT for performance gains
|
||||||
|
|
||||||
// Copyright (c) 2021 XRAY. Mozilla Public License 2.0.
|
// Copyright (c) 2021 XRAY. Mozilla Public License 2.0.
|
||||||
let url = "ws://" + window.location.host + "/dialerPath/csrfToken";
|
let url = "ws://" + window.location.host + "/dialerPath";
|
||||||
let clientIdleCount = 0;
|
let clientIdleCount = 0;
|
||||||
let upstreamGetCount = 0;
|
let upstreamGetCount = 0;
|
||||||
let upstreamWsCount = 0;
|
let upstreamWsCount = 0;
|
||||||
@@ -67,7 +67,7 @@
|
|||||||
}
|
}
|
||||||
clientIdleCount += 1;
|
clientIdleCount += 1;
|
||||||
console.log("Prepare", url);
|
console.log("Prepare", url);
|
||||||
let ws = new WebSocket(url);
|
let ws = new WebSocket(url, "browser-dialer");
|
||||||
// arraybuffer is significantly faster in chrome than default
|
// arraybuffer is significantly faster in chrome than default
|
||||||
// blob, tested with chrome 123
|
// blob, tested with chrome 123
|
||||||
ws.binaryType = "arraybuffer";
|
ws.binaryType = "arraybuffer";
|
||||||
|
|||||||
Reference in New Issue
Block a user