mirror of
https://github.com/XTLS/Xray-core.git
synced 2025-05-07 04:38:40 +00:00
Merge branch 'main' into dns
This commit is contained in:
commit
d3533abe3c
28 changed files with 407 additions and 151 deletions
|
@ -36,6 +36,7 @@ func init() {
|
|||
type dialerConf struct {
|
||||
net.Destination
|
||||
*internet.SocketConfig
|
||||
*tls.Config
|
||||
}
|
||||
|
||||
var (
|
||||
|
@ -46,14 +47,9 @@ var (
|
|||
func dialgRPC(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (net.Conn, error) {
|
||||
grpcSettings := streamSettings.ProtocolSettings.(*Config)
|
||||
|
||||
config := tls.ConfigFromStreamSettings(streamSettings)
|
||||
var dialOption = grpc.WithInsecure()
|
||||
tlsConfig := tls.ConfigFromStreamSettings(streamSettings)
|
||||
|
||||
if config != nil {
|
||||
dialOption = grpc.WithTransportCredentials(credentials.NewTLS(config.GetTLSConfig()))
|
||||
}
|
||||
|
||||
conn, err := getGrpcClient(ctx, dest, dialOption, streamSettings.SocketSettings)
|
||||
conn, err := getGrpcClient(ctx, dest, tlsConfig, streamSettings.SocketSettings)
|
||||
|
||||
if err != nil {
|
||||
return nil, newError("Cannot dial gRPC").Base(err)
|
||||
|
@ -76,7 +72,7 @@ func dialgRPC(ctx context.Context, dest net.Destination, streamSettings *interne
|
|||
return encoding.NewHunkConn(grpcService, nil), nil
|
||||
}
|
||||
|
||||
func getGrpcClient(ctx context.Context, dest net.Destination, dialOption grpc.DialOption, sockopt *internet.SocketConfig) (*grpc.ClientConn, error) {
|
||||
func getGrpcClient(ctx context.Context, dest net.Destination, tlsConfig *tls.Config, sockopt *internet.SocketConfig) (*grpc.ClientConn, error) {
|
||||
globalDialerAccess.Lock()
|
||||
defer globalDialerAccess.Unlock()
|
||||
|
||||
|
@ -84,10 +80,16 @@ func getGrpcClient(ctx context.Context, dest net.Destination, dialOption grpc.Di
|
|||
globalDialerMap = make(map[dialerConf]*grpc.ClientConn)
|
||||
}
|
||||
|
||||
if client, found := globalDialerMap[dialerConf{dest, sockopt}]; found && client.GetState() != connectivity.Shutdown {
|
||||
if client, found := globalDialerMap[dialerConf{dest, sockopt, tlsConfig}]; found && client.GetState() != connectivity.Shutdown {
|
||||
return client, nil
|
||||
}
|
||||
|
||||
dialOption := grpc.WithInsecure()
|
||||
|
||||
if tlsConfig != nil {
|
||||
dialOption = grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig.GetTLSConfig()))
|
||||
}
|
||||
|
||||
conn, err := grpc.Dial(
|
||||
gonet.JoinHostPort(dest.Address.String(), dest.Port.String()),
|
||||
dialOption,
|
||||
|
@ -125,6 +127,6 @@ func getGrpcClient(ctx context.Context, dest net.Destination, dialOption grpc.Di
|
|||
return internet.DialSystem(gctx, net.TCPDestination(address, port), sockopt)
|
||||
}),
|
||||
)
|
||||
globalDialerMap[dialerConf{dest, sockopt}] = conn
|
||||
globalDialerMap[dialerConf{dest, sockopt, tlsConfig}] = conn
|
||||
return conn, err
|
||||
}
|
||||
|
|
|
@ -100,7 +100,7 @@ func (h *HunkReaderWriter) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
|||
}
|
||||
}
|
||||
|
||||
if cap(h.buf) == buf.Size {
|
||||
if cap(h.buf) >= buf.Size {
|
||||
b := h.buf
|
||||
h.index = len(h.buf)
|
||||
return buf.MultiBuffer{buf.NewExisted(b)}, nil
|
||||
|
|
|
@ -79,16 +79,20 @@ func (h *MultiHunkReaderWriter) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
|||
|
||||
var mb = make(buf.MultiBuffer, 0, len(h.buf))
|
||||
for _, b := range h.buf {
|
||||
if cap(b) >= buf.Size {
|
||||
mb = append(mb, buf.NewExisted(b))
|
||||
if len(b) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
nb := buf.New()
|
||||
nb.Extend(int32(len(b)))
|
||||
copy(nb.Bytes(), b)
|
||||
if cap(b) >= buf.Size {
|
||||
mb = append(mb, buf.NewExisted(b))
|
||||
} else {
|
||||
nb := buf.New()
|
||||
nb.Extend(int32(len(b)))
|
||||
copy(nb.Bytes(), b)
|
||||
|
||||
mb = append(mb, nb)
|
||||
}
|
||||
|
||||
mb = append(mb, nb)
|
||||
}
|
||||
return mb, nil
|
||||
}
|
||||
|
@ -99,12 +103,15 @@ func (h *MultiHunkReaderWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
|||
return io.ErrClosedPipe
|
||||
}
|
||||
|
||||
hunk := &MultiHunk{Data: make([][]byte, len(mb))}
|
||||
hunks := make([][]byte, 0, len(mb))
|
||||
|
||||
for _, b := range mb {
|
||||
hunk.Data = append(hunk.Data, b.Bytes())
|
||||
if b.Len() > 0 {
|
||||
hunks = append(hunks, b.Bytes())
|
||||
}
|
||||
}
|
||||
|
||||
err := h.hc.Send(hunk)
|
||||
err := h.hc.Send(&MultiHunk{Data: hunks})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import (
|
|||
type dialerConf struct {
|
||||
net.Destination
|
||||
*internet.SocketConfig
|
||||
*tls.Config
|
||||
}
|
||||
|
||||
var (
|
||||
|
@ -36,7 +37,7 @@ func getHTTPClient(ctx context.Context, dest net.Destination, tlsSettings *tls.C
|
|||
globalDialerMap = make(map[dialerConf]*http.Client)
|
||||
}
|
||||
|
||||
if client, found := globalDialerMap[dialerConf{dest, sockopt}]; found {
|
||||
if client, found := globalDialerMap[dialerConf{dest, sockopt, tlsSettings}]; found {
|
||||
return client, nil
|
||||
}
|
||||
|
||||
|
@ -92,7 +93,7 @@ func getHTTPClient(ctx context.Context, dest net.Destination, tlsSettings *tls.C
|
|||
Transport: transport,
|
||||
}
|
||||
|
||||
globalDialerMap[dialerConf{dest, sockopt}] = client
|
||||
globalDialerMap[dialerConf{dest, sockopt, tlsSettings}] = client
|
||||
return client, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -148,7 +148,6 @@ func (s *clientSessions) openConnection(destAddr net.Addr, config *Config, tlsCo
|
|||
|
||||
quicConfig := &quic.Config{
|
||||
ConnectionIDLength: 12,
|
||||
HandshakeTimeout: time.Second * 8,
|
||||
MaxIdleTimeout: time.Second * 30,
|
||||
}
|
||||
|
||||
|
|
|
@ -103,7 +103,6 @@ func Listen(ctx context.Context, address net.Address, port net.Port, streamSetti
|
|||
|
||||
quicConfig := &quic.Config{
|
||||
ConnectionIDLength: 12,
|
||||
HandshakeTimeout: time.Second * 8,
|
||||
MaxIdleTimeout: time.Second * 45,
|
||||
MaxIncomingStreams: 32,
|
||||
MaxIncomingUniStreams: -1,
|
||||
|
|
|
@ -17,3 +17,14 @@ func isUDPSocket(network string) bool {
|
|||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (v *SocketConfig) ParseTFOValue() int {
|
||||
if v.Tfo == 0 {
|
||||
return -1
|
||||
}
|
||||
tfo := int(v.Tfo)
|
||||
if tfo < 0 {
|
||||
tfo = 0
|
||||
}
|
||||
return tfo
|
||||
}
|
||||
|
|
|
@ -15,12 +15,12 @@ const (
|
|||
|
||||
func applyOutboundSocketOptions(network string, address string, fd uintptr, config *SocketConfig) error {
|
||||
if isTCPSocket(network) {
|
||||
tfo := config.Tfo
|
||||
tfo := config.ParseTFOValue()
|
||||
if tfo > 0 {
|
||||
tfo = TCP_FASTOPEN_CLIENT
|
||||
}
|
||||
if tfo >= 0 {
|
||||
if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, TCP_FASTOPEN, int(tfo)); err != nil {
|
||||
if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, TCP_FASTOPEN, tfo); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -31,12 +31,12 @@ func applyOutboundSocketOptions(network string, address string, fd uintptr, conf
|
|||
|
||||
func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig) error {
|
||||
if isTCPSocket(network) {
|
||||
tfo := config.Tfo
|
||||
tfo := config.ParseTFOValue()
|
||||
if tfo > 0 {
|
||||
tfo = TCP_FASTOPEN_SERVER
|
||||
}
|
||||
if tfo >= 0 {
|
||||
if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, TCP_FASTOPEN, int(tfo)); err != nil {
|
||||
if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, TCP_FASTOPEN, tfo); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
|
@ -130,7 +130,7 @@ func applyOutboundSocketOptions(network string, address string, fd uintptr, conf
|
|||
}
|
||||
|
||||
if isTCPSocket(network) {
|
||||
tfo := int(config.Tfo)
|
||||
tfo := config.ParseTFOValue()
|
||||
if tfo > 0 {
|
||||
tfo = 1
|
||||
}
|
||||
|
@ -163,9 +163,10 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig)
|
|||
}
|
||||
}
|
||||
if isTCPSocket(network) {
|
||||
if config.Tfo >= 0 {
|
||||
if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, unix.TCP_FASTOPEN, int(config.Tfo)); err != nil {
|
||||
return newError("failed to set TCP_FASTOPEN=", config.Tfo).Base(err)
|
||||
tfo := config.ParseTFOValue()
|
||||
if tfo >= 0 {
|
||||
if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, unix.TCP_FASTOPEN, tfo); err != nil {
|
||||
return newError("failed to set TCP_FASTOPEN=", tfo).Base(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ func applyOutboundSocketOptions(network string, address string, fd uintptr, conf
|
|||
}
|
||||
|
||||
if isTCPSocket(network) {
|
||||
tfo := int(config.Tfo)
|
||||
tfo := config.ParseTFOValue()
|
||||
if tfo > 0 {
|
||||
tfo = 1
|
||||
}
|
||||
|
@ -75,9 +75,10 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig)
|
|||
}
|
||||
}
|
||||
if isTCPSocket(network) {
|
||||
if config.Tfo >= 0 {
|
||||
if err := syscall.SetsockoptInt(int(fd), syscall.SOL_TCP, TCP_FASTOPEN, int(config.Tfo)); err != nil {
|
||||
return newError("failed to set TCP_FASTOPEN=", config.Tfo).Base(err)
|
||||
tfo := config.ParseTFOValue()
|
||||
if tfo >= 0 {
|
||||
if err := syscall.SetsockoptInt(int(fd), syscall.SOL_TCP, TCP_FASTOPEN, tfo); err != nil {
|
||||
return newError("failed to set TCP_FASTOPEN=", tfo).Base(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,12 +8,12 @@ const (
|
|||
TCP_FASTOPEN = 15
|
||||
)
|
||||
|
||||
func setTFO(fd syscall.Handle, tfo int32) error {
|
||||
func setTFO(fd syscall.Handle, tfo int) error {
|
||||
if tfo > 0 {
|
||||
tfo = 1
|
||||
}
|
||||
if tfo >= 0 {
|
||||
if err := syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, TCP_FASTOPEN, int(tfo)); err != nil {
|
||||
if err := syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, TCP_FASTOPEN, tfo); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ func setTFO(fd syscall.Handle, tfo int32) error {
|
|||
|
||||
func applyOutboundSocketOptions(network string, address string, fd uintptr, config *SocketConfig) error {
|
||||
if isTCPSocket(network) {
|
||||
if err := setTFO(syscall.Handle(fd), config.Tfo); err != nil {
|
||||
if err := setTFO(syscall.Handle(fd), config.ParseTFOValue()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@ func applyOutboundSocketOptions(network string, address string, fd uintptr, conf
|
|||
|
||||
func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig) error {
|
||||
if isTCPSocket(network) {
|
||||
if err := setTFO(syscall.Handle(fd), config.Tfo); err != nil {
|
||||
if err := setTFO(syscall.Handle(fd), config.ParseTFOValue()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@ package tcp
|
|||
import (
|
||||
"context"
|
||||
|
||||
utls "github.com/refraction-networking/utls"
|
||||
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/common/session"
|
||||
|
@ -21,14 +23,11 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me
|
|||
|
||||
if config := tls.ConfigFromStreamSettings(streamSettings); config != nil {
|
||||
tlsConfig := config.GetTLSConfig(tls.WithDestination(dest))
|
||||
/*
|
||||
if config.IsExperiment8357() {
|
||||
conn = tls.UClient(conn, tlsConfig)
|
||||
} else {
|
||||
conn = tls.Client(conn, tlsConfig)
|
||||
}
|
||||
*/
|
||||
conn = tls.Client(conn, tlsConfig)
|
||||
if fingerprint, ok := tls.Fingerprints[config.Fingerprint]; ok {
|
||||
conn = utls.UClient(conn, tls.CopyConfig(tlsConfig), fingerprint)
|
||||
} else {
|
||||
conn = tls.Client(conn, tlsConfig)
|
||||
}
|
||||
} else if config := xtls.ConfigFromStreamSettings(streamSettings); config != nil {
|
||||
xtlsConfig := config.GetXTLSConfig(xtls.WithDestination(dest))
|
||||
conn = xtls.Client(conn, xtlsConfig)
|
||||
|
|
|
@ -38,7 +38,8 @@ func ListenTCP(ctx context.Context, address net.Address, port net.Port, streamSe
|
|||
if streamSettings.SocketSettings == nil {
|
||||
streamSettings.SocketSettings = &internet.SocketConfig{}
|
||||
}
|
||||
streamSettings.SocketSettings.AcceptProxyProtocol = l.config.AcceptProxyProtocol
|
||||
streamSettings.SocketSettings.AcceptProxyProtocol =
|
||||
l.config.AcceptProxyProtocol || streamSettings.SocketSettings.AcceptProxyProtocol
|
||||
}
|
||||
var listener net.Listener
|
||||
var err error
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.25.0
|
||||
// protoc v3.14.0
|
||||
// protoc v3.15.6
|
||||
// source: transport/internet/tls/config.proto
|
||||
|
||||
package tls
|
||||
|
@ -200,6 +200,8 @@ type Config struct {
|
|||
CipherSuites string `protobuf:"bytes,9,opt,name=cipher_suites,json=cipherSuites,proto3" json:"cipher_suites,omitempty"`
|
||||
// Whether the server selects its most preferred ciphersuite.
|
||||
PreferServerCipherSuites bool `protobuf:"varint,10,opt,name=prefer_server_cipher_suites,json=preferServerCipherSuites,proto3" json:"prefer_server_cipher_suites,omitempty"`
|
||||
// TLS Client Hello fingerprint (uTLS).
|
||||
Fingerprint string `protobuf:"bytes,11,opt,name=fingerprint,proto3" json:"fingerprint,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Config) Reset() {
|
||||
|
@ -304,6 +306,13 @@ func (x *Config) GetPreferServerCipherSuites() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (x *Config) GetFingerprint() string {
|
||||
if x != nil {
|
||||
return x.Fingerprint
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
var File_transport_internet_tls_config_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_transport_internet_tls_config_proto_rawDesc = []byte{
|
||||
|
@ -333,7 +342,7 @@ var file_transport_internet_tls_config_proto_rawDesc = []byte{
|
|||
0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x4d, 0x45, 0x4e, 0x54, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10,
|
||||
0x41, 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x56, 0x45, 0x52, 0x49, 0x46, 0x59,
|
||||
0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x41, 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f,
|
||||
0x49, 0x53, 0x53, 0x55, 0x45, 0x10, 0x02, 0x22, 0xd3, 0x03, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66,
|
||||
0x49, 0x53, 0x53, 0x55, 0x45, 0x10, 0x02, 0x22, 0xf5, 0x03, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66,
|
||||
0x69, 0x67, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x6e, 0x73, 0x65,
|
||||
0x63, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x61, 0x6c, 0x6c, 0x6f,
|
||||
0x77, 0x49, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x12, 0x4a, 0x0a, 0x0b, 0x63, 0x65, 0x72,
|
||||
|
@ -362,15 +371,17 @@ var file_transport_internet_tls_config_proto_rawDesc = []byte{
|
|||
0x0a, 0x1b, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f,
|
||||
0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x73, 0x75, 0x69, 0x74, 0x65, 0x73, 0x18, 0x0a, 0x20,
|
||||
0x01, 0x28, 0x08, 0x52, 0x18, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x65,
|
||||
0x72, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x42, 0x73, 0x0a,
|
||||
0x1f, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70,
|
||||
0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x74, 0x6c, 0x73,
|
||||
0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78,
|
||||
0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x74, 0x72,
|
||||
0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74,
|
||||
0x2f, 0x74, 0x6c, 0x73, 0xaa, 0x02, 0x1b, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e,
|
||||
0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x54,
|
||||
0x6c, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x72, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x12, 0x20, 0x0a,
|
||||
0x0b, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x18, 0x0b, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x0b, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x42,
|
||||
0x73, 0x0a, 0x1f, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e,
|
||||
0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x74,
|
||||
0x6c, 0x73, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
|
||||
0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f,
|
||||
0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e,
|
||||
0x65, 0x74, 0x2f, 0x74, 0x6c, 0x73, 0xaa, 0x02, 0x1b, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x54, 0x72,
|
||||
0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74,
|
||||
0x2e, 0x54, 0x6c, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
|
|
@ -64,4 +64,7 @@ message Config {
|
|||
|
||||
// Whether the server selects its most preferred ciphersuite.
|
||||
bool prefer_server_cipher_suites = 10;
|
||||
|
||||
// TLS Client Hello fingerprint (uTLS).
|
||||
string fingerprint = 11;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@ package tls
|
|||
import (
|
||||
"crypto/tls"
|
||||
|
||||
utls "github.com/refraction-networking/utls"
|
||||
|
||||
"github.com/xtls/xray-core/common/buf"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
)
|
||||
|
@ -41,23 +43,24 @@ func Client(c net.Conn, config *tls.Config) net.Conn {
|
|||
return &Conn{Conn: tlsConn}
|
||||
}
|
||||
|
||||
/*
|
||||
func copyConfig(c *tls.Config) *utls.Config {
|
||||
var Fingerprints = map[string]utls.ClientHelloID{
|
||||
"chrome": utls.HelloChrome_Auto,
|
||||
"firefox": utls.HelloFirefox_Auto,
|
||||
"safari": utls.HelloIOS_Auto,
|
||||
"randomized": utls.HelloRandomized,
|
||||
}
|
||||
|
||||
func CopyConfig(c *tls.Config) *utls.Config {
|
||||
return &utls.Config{
|
||||
RootCAs: c.RootCAs,
|
||||
NextProtos: c.NextProtos,
|
||||
ServerName: c.ServerName,
|
||||
InsecureSkipVerify: c.InsecureSkipVerify,
|
||||
MinVersion: utls.VersionTLS12,
|
||||
MaxVersion: utls.VersionTLS12,
|
||||
MinVersion: c.MinVersion,
|
||||
MaxVersion: c.MaxVersion,
|
||||
}
|
||||
}
|
||||
|
||||
func UClient(c net.Conn, config *tls.Config) net.Conn {
|
||||
uConfig := copyConfig(config)
|
||||
return utls.Client(c, uConfig)
|
||||
}
|
||||
*/
|
||||
|
||||
// Server initiates a TLS server handshake on the given connection.
|
||||
func Server(c net.Conn, config *tls.Config) net.Conn {
|
||||
tlsConn := tls.Server(c, config)
|
||||
|
|
|
@ -2,8 +2,12 @@ package websocket
|
|||
|
||||
import (
|
||||
"context"
|
||||
_ "embed"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
|
@ -15,6 +19,27 @@ import (
|
|||
"github.com/xtls/xray-core/transport/internet/tls"
|
||||
)
|
||||
|
||||
//go:embed dialer.html
|
||||
var webpage []byte
|
||||
var conns chan *websocket.Conn
|
||||
|
||||
func init() {
|
||||
if addr := os.Getenv("XRAY_BROWSER_DIALER"); addr != "" {
|
||||
conns = make(chan *websocket.Conn, 256)
|
||||
go http.ListenAndServe(addr, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path == "/websocket" {
|
||||
if conn, err := upgrader.Upgrade(w, r, nil); err == nil {
|
||||
conns <- conn
|
||||
} else {
|
||||
fmt.Println("unexpected error")
|
||||
}
|
||||
} else {
|
||||
w.Write(webpage)
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
// Dial dials a WebSocket connection to the given destination.
|
||||
func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (internet.Connection, error) {
|
||||
newError("creating connection to ", dest).WriteToLog(session.ExportIDToError(ctx))
|
||||
|
@ -66,6 +91,30 @@ func dialWebSocket(ctx context.Context, dest net.Destination, streamSettings *in
|
|||
}
|
||||
uri := protocol + "://" + host + wsSettings.GetNormalizedPath()
|
||||
|
||||
if conns != nil {
|
||||
data := []byte(uri)
|
||||
if ed != nil {
|
||||
data = append(data, " "+base64.RawURLEncoding.EncodeToString(ed)...)
|
||||
}
|
||||
var conn *websocket.Conn
|
||||
for {
|
||||
conn = <-conns
|
||||
if conn.WriteMessage(websocket.TextMessage, data) != nil {
|
||||
conn.Close()
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
if _, p, err := conn.ReadMessage(); err != nil {
|
||||
conn.Close()
|
||||
return nil, err
|
||||
} else if s := string(p); s != "ok" {
|
||||
conn.Close()
|
||||
return nil, newError(s)
|
||||
}
|
||||
return newConnection(conn, conn.RemoteAddr(), nil), nil
|
||||
}
|
||||
|
||||
header := wsSettings.GetRequestHeader()
|
||||
if ed != nil {
|
||||
header.Set("Sec-WebSocket-Protocol", base64.StdEncoding.EncodeToString(ed))
|
||||
|
|
55
transport/internet/websocket/dialer.html
Normal file
55
transport/internet/websocket/dialer.html
Normal file
|
@ -0,0 +1,55 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Browser Dialer</title>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
// Copyright (c) 2021 XRAY. Mozilla Public License 2.0.
|
||||
var url = "ws://" + window.location.host + "/websocket"
|
||||
var count = 0
|
||||
setInterval(check, 1000)
|
||||
function check() {
|
||||
if (count <= 0) {
|
||||
count += 1
|
||||
console.log("Prepare", url)
|
||||
var ws = new WebSocket(url)
|
||||
var wss = undefined
|
||||
var first = true
|
||||
ws.onmessage = function (event) {
|
||||
if (first) {
|
||||
first = false
|
||||
count -= 1
|
||||
var arr = event.data.split(" ")
|
||||
console.log("Dial", arr[0], arr[1])
|
||||
wss = new WebSocket(arr[0], arr[1])
|
||||
var opened = false
|
||||
wss.onopen = function (event) {
|
||||
opened = true
|
||||
ws.send("ok")
|
||||
}
|
||||
wss.onmessage = function (event) {
|
||||
ws.send(event.data)
|
||||
}
|
||||
wss.onclose = function (event) {
|
||||
ws.close()
|
||||
}
|
||||
wss.onerror = function (event) {
|
||||
!opened && ws.send("fail")
|
||||
wss.close()
|
||||
}
|
||||
check()
|
||||
} else wss.send(event.data)
|
||||
}
|
||||
ws.onclose = function (event) {
|
||||
if (first) count -= 1
|
||||
else wss.close()
|
||||
}
|
||||
ws.onerror = function (event) {
|
||||
ws.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -7,6 +7,7 @@ import (
|
|||
"encoding/base64"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
|
@ -25,6 +26,8 @@ type requestHandler struct {
|
|||
ln *Listener
|
||||
}
|
||||
|
||||
var replacer = strings.NewReplacer("+", "-", "/", "_", "=", "")
|
||||
|
||||
var upgrader = &websocket.Upgrader{
|
||||
ReadBufferSize: 4 * 1024,
|
||||
WriteBufferSize: 4 * 1024,
|
||||
|
@ -39,7 +42,17 @@ func (h *requestHandler) ServeHTTP(writer http.ResponseWriter, request *http.Req
|
|||
writer.WriteHeader(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
conn, err := upgrader.Upgrade(writer, request, nil)
|
||||
|
||||
var extraReader io.Reader
|
||||
var responseHeader = http.Header{}
|
||||
if str := request.Header.Get("Sec-WebSocket-Protocol"); str != "" {
|
||||
if ed, err := base64.RawURLEncoding.DecodeString(replacer.Replace(str)); err == nil && len(ed) > 0 {
|
||||
extraReader = bytes.NewReader(ed)
|
||||
responseHeader.Set("Sec-WebSocket-Protocol", str)
|
||||
}
|
||||
}
|
||||
|
||||
conn, err := upgrader.Upgrade(writer, request, responseHeader)
|
||||
if err != nil {
|
||||
newError("failed to convert to WebSocket connection").Base(err).WriteToLog()
|
||||
return
|
||||
|
@ -54,12 +67,6 @@ func (h *requestHandler) ServeHTTP(writer http.ResponseWriter, request *http.Req
|
|||
}
|
||||
}
|
||||
|
||||
var extraReader io.Reader
|
||||
if str := request.Header.Get("Sec-WebSocket-Protocol"); str != "" {
|
||||
if ed, err := base64.StdEncoding.DecodeString(str); err == nil && len(ed) > 0 {
|
||||
extraReader = bytes.NewReader(ed)
|
||||
}
|
||||
}
|
||||
h.ln.addConn(newConnection(conn, remoteAddr, extraReader))
|
||||
}
|
||||
|
||||
|
@ -82,7 +89,8 @@ func ListenWS(ctx context.Context, address net.Address, port net.Port, streamSet
|
|||
if streamSettings.SocketSettings == nil {
|
||||
streamSettings.SocketSettings = &internet.SocketConfig{}
|
||||
}
|
||||
streamSettings.SocketSettings.AcceptProxyProtocol = l.config.AcceptProxyProtocol
|
||||
streamSettings.SocketSettings.AcceptProxyProtocol =
|
||||
l.config.AcceptProxyProtocol || streamSettings.SocketSettings.AcceptProxyProtocol
|
||||
}
|
||||
var listener net.Listener
|
||||
var err error
|
||||
|
@ -128,7 +136,7 @@ func ListenWS(ctx context.Context, address net.Address, port net.Port, streamSet
|
|||
ln: l,
|
||||
},
|
||||
ReadHeaderTimeout: time.Second * 4,
|
||||
MaxHeaderBytes: 2048,
|
||||
MaxHeaderBytes: 4096,
|
||||
}
|
||||
|
||||
go func() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue