feat: add ws-path to vmess listener

This commit is contained in:
wwqgtxx 2023-10-07 16:45:15 +08:00
parent 5ff4473083
commit 791ecfbb32
5 changed files with 36 additions and 9 deletions

View file

@ -936,6 +936,7 @@ listeners:
- username: 1
uuid: 9d0cb9d0-964f-4ef6-897d-6c6b3ccf9e68
alterId: 1
# ws-path: "/" # 如果不为空则开启websocket传输层
- name: tuic-in-1
type: tuic

View file

@ -14,6 +14,7 @@ type VmessServer struct {
Enable bool
Listen string
Users []VmessUser
WsPath string
}
func (t VmessServer) String() string {

View file

@ -9,7 +9,8 @@ import (
type VmessOption struct {
BaseOption
Users []VmessUser `inbound:"users"`
Users []VmessUser `inbound:"users"`
WsPath string `inbound:"ws-path,omitempty"`
}
type VmessUser struct {
@ -49,6 +50,7 @@ func NewVmess(options *VmessOption) (*Vmess, error) {
Enable: true,
Listen: base.RawAddress(),
Users: users,
WsPath: options.WsPath,
},
}, nil
}

View file

@ -3,6 +3,7 @@ package sing_vmess
import (
"context"
"net"
"net/http"
"net/url"
"strings"
@ -12,6 +13,7 @@ import (
LC "github.com/Dreamacro/clash/listener/config"
"github.com/Dreamacro/clash/listener/sing"
"github.com/Dreamacro/clash/ntp"
clashVMess "github.com/Dreamacro/clash/transport/vmess"
vmess "github.com/metacubex/sing-vmess"
"github.com/sagernet/sing/common"
@ -65,6 +67,20 @@ func New(config LC.VmessServer, tunnel C.Tunnel, additions ...inbound.Addition)
sl = &Listener{false, config, nil, service}
var httpMux *http.ServeMux
if config.WsPath != "" {
httpMux = http.NewServeMux()
httpMux.HandleFunc(config.WsPath, func(w http.ResponseWriter, r *http.Request) {
conn, err := clashVMess.StreamUpgradedWebsocketConn(w, r)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
sl.HandleConn(conn, tunnel)
})
}
for _, addr := range strings.Split(config.Listen, ",") {
addr := addr
@ -76,6 +92,10 @@ func New(config LC.VmessServer, tunnel C.Tunnel, additions ...inbound.Addition)
sl.listeners = append(sl.listeners, l)
go func() {
if httpMux != nil {
_ = http.Serve(l, httpMux)
return
}
for {
c, err := l.Accept()
if err != nil {

View file

@ -118,12 +118,17 @@ func (wsc *websocketConn) WriteBuffer(buffer *buf.Buffer) error {
var headerLen int
headerLen += 1 // FIN / RSV / OPCODE
headerLen += payloadBitLength
headerLen += 4 // MASK KEY
if wsc.state.ClientSide() {
headerLen += 4 // MASK KEY
}
header := buffer.ExtendHeader(headerLen)
_ = header[2] // bounds check hint to compiler
header[0] = byte(ws.OpBinary) | 0x80
header[1] = 1 << 7
if wsc.state.ClientSide() {
header[1] = 1 << 7
} else {
header[1] = 0
}
if dataLen < 126 {
header[1] |= byte(dataLen)
@ -456,17 +461,15 @@ func decodeXray0rtt(requestHeader http.Header) ([]byte, http.Header) {
func StreamUpgradedWebsocketConn(w http.ResponseWriter, r *http.Request) (net.Conn, error) {
edBuf, responseHeader := decodeXray0rtt(r.Header)
wsConn, rw, _, err := ws.HTTPUpgrader{
Header: responseHeader,
}.Upgrade(r, w)
wsConn, rw, _, err := ws.HTTPUpgrader{Header: responseHeader}.Upgrade(r, w)
if err != nil {
return nil, err
}
conn := newWebsocketConn(wsConn, rw.Reader, ws.StateServerSide)
if len(edBuf) > 0 {
return &websocketWithReaderConn{conn, io.MultiReader(bytes.NewReader(edBuf), conn)}, nil
return N.NewDeadlineConn(&websocketWithReaderConn{conn, io.MultiReader(bytes.NewReader(edBuf), conn)}), nil
}
return conn, nil
return N.NewDeadlineConn(conn), nil
}
type websocketWithReaderConn struct {