mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-08-07 14:25:17 +03:00
Update sing-box core
This commit is contained in:
64
protocol/anytls/client_metadata.go
Normal file
64
protocol/anytls/client_metadata.go
Normal file
@@ -0,0 +1,64 @@
|
||||
package anytls
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"net"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
"unsafe"
|
||||
|
||||
"github.com/sagernet/sing/common"
|
||||
|
||||
anytls "github.com/anytls/sing-anytls"
|
||||
"github.com/anytls/sing-anytls/session"
|
||||
)
|
||||
|
||||
const (
|
||||
commandSettings = 4
|
||||
frameHeaderSize = 7
|
||||
)
|
||||
|
||||
var (
|
||||
clientSessionField, _ = reflect.TypeFor[anytls.Client]().FieldByName("sessionClient")
|
||||
streamSessionField, _ = reflect.TypeFor[session.Stream]().FieldByName("sess")
|
||||
sessionConnLockField, _ = reflect.TypeFor[session.Session]().FieldByName("connLock")
|
||||
sessionBufferField, _ = reflect.TypeFor[session.Session]().FieldByName("buffer")
|
||||
)
|
||||
|
||||
func sessionClientOf(client *anytls.Client) *session.Client {
|
||||
return *(**session.Client)(unsafe.Add(unsafe.Pointer(client), clientSessionField.Offset))
|
||||
}
|
||||
|
||||
func (h *Outbound) rewriteClientMetadata(conn net.Conn) {
|
||||
sess := *(**session.Session)(unsafe.Add(unsafe.Pointer(conn.(*session.Stream)), streamSessionField.Offset))
|
||||
connLock := (*sync.Mutex)(unsafe.Add(unsafe.Pointer(sess), sessionConnLockField.Offset))
|
||||
bufferPointer := (*[]byte)(unsafe.Add(unsafe.Pointer(sess), sessionBufferField.Offset))
|
||||
connLock.Lock()
|
||||
defer connLock.Unlock()
|
||||
buffer := *bufferPointer
|
||||
offset := 0
|
||||
for offset+frameHeaderSize <= len(buffer) {
|
||||
dataLength := int(binary.BigEndian.Uint16(buffer[offset+5 : offset+7]))
|
||||
frameEnd := offset + frameHeaderSize + dataLength
|
||||
if frameEnd > len(buffer) {
|
||||
return
|
||||
}
|
||||
if buffer[offset] == commandSettings {
|
||||
data := []byte(strings.Join(common.Map(strings.Split(string(buffer[offset+frameHeaderSize:frameEnd]), "\n"), func(line string) string {
|
||||
if strings.HasPrefix(line, "client=") {
|
||||
return "client=" + h.clientMetadata
|
||||
}
|
||||
return line
|
||||
}), "\n"))
|
||||
newBuffer := make([]byte, 0, offset+frameHeaderSize+len(data)+len(buffer)-frameEnd)
|
||||
newBuffer = append(newBuffer, buffer[:offset+5]...)
|
||||
newBuffer = binary.BigEndian.AppendUint16(newBuffer, uint16(len(data)))
|
||||
newBuffer = append(newBuffer, data...)
|
||||
newBuffer = append(newBuffer, buffer[frameEnd:]...)
|
||||
*bufferPointer = newBuffer
|
||||
return
|
||||
}
|
||||
offset = frameEnd
|
||||
}
|
||||
}
|
||||
@@ -19,20 +19,25 @@ import (
|
||||
"github.com/sagernet/sing/common/uot"
|
||||
|
||||
anytls "github.com/anytls/sing-anytls"
|
||||
"github.com/anytls/sing-anytls/session"
|
||||
)
|
||||
|
||||
func RegisterOutbound(registry *outbound.Registry) {
|
||||
outbound.Register[option.AnyTLSOutboundOptions](registry, C.TypeAnyTLS, NewOutbound)
|
||||
}
|
||||
|
||||
var _ adapter.OutboundWithMultiplex = (*Outbound)(nil)
|
||||
|
||||
type Outbound struct {
|
||||
outbound.Adapter
|
||||
dialer tls.Dialer
|
||||
server M.Socksaddr
|
||||
tlsConfig tls.Config
|
||||
client *anytls.Client
|
||||
uotClient *uot.Client
|
||||
logger log.ContextLogger
|
||||
dialer tls.Dialer
|
||||
server M.Socksaddr
|
||||
tlsConfig tls.Config
|
||||
clientMetadata string
|
||||
client *anytls.Client
|
||||
sessionClient *session.Client
|
||||
uotClient *uot.Client
|
||||
logger log.ContextLogger
|
||||
}
|
||||
|
||||
func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.AnyTLSOutboundOptions) (adapter.Outbound, error) {
|
||||
@@ -81,14 +86,30 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
|
||||
return nil, err
|
||||
}
|
||||
outbound.client = client
|
||||
outbound.clientMetadata = options.ClientMetadata
|
||||
outbound.sessionClient = sessionClientOf(client)
|
||||
|
||||
outbound.uotClient = &uot.Client{
|
||||
Dialer: anytlsDialer(client.CreateProxy),
|
||||
Dialer: (anytlsDialer)(outbound.createProxy),
|
||||
Version: uot.Version,
|
||||
}
|
||||
return outbound, nil
|
||||
}
|
||||
|
||||
func (h *Outbound) createProxy(ctx context.Context, destination M.Socksaddr) (net.Conn, error) {
|
||||
conn, err := h.sessionClient.CreateStream(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
h.rewriteClientMetadata(conn)
|
||||
err = M.SocksaddrSerializer.WriteAddrPort(conn, destination)
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
return nil, err
|
||||
}
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
type anytlsDialer func(ctx context.Context, destination M.Socksaddr) (net.Conn, error)
|
||||
|
||||
func (d anytlsDialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||
@@ -103,6 +124,10 @@ func (h *Outbound) dialOut(ctx context.Context) (net.Conn, error) {
|
||||
return h.dialer.DialTLSContext(ctx, h.server)
|
||||
}
|
||||
|
||||
func (h *Outbound) MultiplexEnabled() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (h *Outbound) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||
ctx, metadata := adapter.ExtendContext(ctx)
|
||||
metadata.Outbound = h.Tag()
|
||||
@@ -110,7 +135,7 @@ func (h *Outbound) DialContext(ctx context.Context, network string, destination
|
||||
switch N.NetworkName(network) {
|
||||
case N.NetworkTCP:
|
||||
h.logger.InfoContext(ctx, "outbound connection to ", destination)
|
||||
return h.client.CreateProxy(ctx, destination)
|
||||
return h.createProxy(ctx, destination)
|
||||
case N.NetworkUDP:
|
||||
h.logger.InfoContext(ctx, "outbound UoT packet connection to ", destination)
|
||||
return h.uotClient.DialContext(ctx, network, destination)
|
||||
|
||||
Reference in New Issue
Block a user