From 45dedd12e785d2d3425b0ba989a4708cff702ed0 Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 17 Nov 2023 17:09:45 +0100 Subject: [PATCH] new: add turn server relay --- go.mod | 4 +- option/h_turn_udp_proxy.go | 8 +++ option/hysteria.go | 2 +- option/hysteria2.go | 2 +- option/tuic.go | 2 +- option/wireguard.go | 4 +- outbound/{hiddify => houtbound}/forward.go | 2 +- .../bale.go => houtbound/turn_udp_proxy.go} | 60 +++++++++---------- outbound/hysteria.go | 4 ++ outbound/hysteria2.go | 24 +++----- outbound/tuic.go | 31 +++------- outbound/wireguard.go | 8 +++ 12 files changed, 72 insertions(+), 79 deletions(-) create mode 100644 option/h_turn_udp_proxy.go rename outbound/{hiddify => houtbound}/forward.go (99%) rename outbound/{hiddify/bale.go => houtbound/turn_udp_proxy.go} (72%) diff --git a/go.mod b/go.mod index 2e5af0af30..6c79043fff 100644 --- a/go.mod +++ b/go.mod @@ -104,4 +104,6 @@ require ( lukechampine.com/blake3 v1.2.1 // indirect ) -replace github.com/sagernet/sing-box/outbound/hiddify => ./outbound/hiddify +replace github.com/sagernet/sing-box/outbound/houtbound => ./outbound/houtbound + +replace github.com/sagernet/sing-box/option => ./option diff --git a/option/h_turn_udp_proxy.go b/option/h_turn_udp_proxy.go new file mode 100644 index 0000000000..d44ab1de50 --- /dev/null +++ b/option/h_turn_udp_proxy.go @@ -0,0 +1,8 @@ +package option + +type TurnRelayOptions struct { + ServerOptions + Username string `json:"username,omitempty"` + Password string `json:"password,omitempty"` + Realm string `json:"realm,omitempty"` +} \ No newline at end of file diff --git a/option/hysteria.go b/option/hysteria.go index d3ce6a1024..7f54a8b76b 100644 --- a/option/hysteria.go +++ b/option/hysteria.go @@ -1,5 +1,4 @@ package option - type HysteriaInboundOptions struct { ListenOptions Up string `json:"up,omitempty"` @@ -36,4 +35,5 @@ type HysteriaOutboundOptions struct { DisableMTUDiscovery bool `json:"disable_mtu_discovery,omitempty"` Network NetworkList `json:"network,omitempty"` TLS *OutboundTLSOptions `json:"tls,omitempty"` + TurnRelay *TurnRelayOptions`json:"turn_relay,omitempty"` } diff --git a/option/hysteria2.go b/option/hysteria2.go index d33285b2b7..f94a59bf37 100644 --- a/option/hysteria2.go +++ b/option/hysteria2.go @@ -32,5 +32,5 @@ type Hysteria2OutboundOptions struct { Network NetworkList `json:"network,omitempty"` TLS *OutboundTLSOptions `json:"tls,omitempty"` BrutalDebug bool `json:"brutal_debug,omitempty"` - Bale bool `json:"bale,omitempty"` + TurnRelay *TurnRelayOptions`json:"turn_relay,omitempty"` } diff --git a/option/tuic.go b/option/tuic.go index 2b28b03c95..7b26535ba3 100644 --- a/option/tuic.go +++ b/option/tuic.go @@ -28,5 +28,5 @@ type TUICOutboundOptions struct { Heartbeat Duration `json:"heartbeat,omitempty"` Network NetworkList `json:"network,omitempty"` TLS *OutboundTLSOptions `json:"tls,omitempty"` - Bale bool `json:"bale,omitempty"` + TurnRelay *TurnRelayOptions`json:"turn_relay,omitempty"` } diff --git a/option/wireguard.go b/option/wireguard.go index 5ede7a61d6..866fa17a8e 100644 --- a/option/wireguard.go +++ b/option/wireguard.go @@ -1,7 +1,6 @@ package option -import "net/netip" - +import "net/netip" type WireGuardOutboundOptions struct { DialerOptions SystemInterface bool `json:"system_interface,omitempty"` @@ -16,6 +15,7 @@ type WireGuardOutboundOptions struct { Workers int `json:"workers,omitempty"` MTU uint32 `json:"mtu,omitempty"` Network NetworkList `json:"network,omitempty"` + TurnRelay *TurnRelayOptions`json:"turn_relay,omitempty"` } type WireGuardPeer struct { diff --git a/outbound/hiddify/forward.go b/outbound/houtbound/forward.go similarity index 99% rename from outbound/hiddify/forward.go rename to outbound/houtbound/forward.go index 988a45a406..4446ed1bec 100644 --- a/outbound/hiddify/forward.go +++ b/outbound/houtbound/forward.go @@ -1,4 +1,4 @@ -package hiddify +package houtbound import ( "log" diff --git a/outbound/hiddify/bale.go b/outbound/houtbound/turn_udp_proxy.go similarity index 72% rename from outbound/hiddify/bale.go rename to outbound/houtbound/turn_udp_proxy.go index 5bbefe39dd..9fd2e8fba6 100644 --- a/outbound/hiddify/bale.go +++ b/outbound/houtbound/turn_udp_proxy.go @@ -10,7 +10,7 @@ // |___/ // // Package main implements a TURN client with support for TCP -package hiddify +package houtbound import ( "fmt" @@ -18,48 +18,50 @@ import ( "github.com/pion/turn/v3" "log" "net" - "strings" "time" "math/rand" - + "github.com/sagernet/sing-box/option" ) -type Bale struct { - Host string - Port uint16 - RelayPort uint16 - Forwarder *Forwarder +type CommonTurnRelayOptions struct { + option.ServerOptions + *option.TurnRelayOptions +} + + +func genString(serverOptions option.ServerOptions) (string) { + return fmt.Sprintf("%s:%d", serverOptions.Server, serverOptions.ServerPort) } -func ApplyBale(udp_host string,udp_port uint16)(*Bale,error) { - server:=fmt.Sprintf("%s:%d", udp_host, udp_port) - host := "meet-turn.bale.sh" - port := 443 - user := "balelivekit=GygZPHQSgAV7L5L8" +func ApplyTurnRelay(option CommonTurnRelayOptions)(*Forwarder) { + if option.TurnRelayOptions == nil { + return nil + } + targetServerAddr := genString(option.ServerOptions) // fmt.Sprintf("%s:%d", option.ServerOptions.Server, option.ServerOptions.ServerPort) // Dial TURN Server - turnServerAddr := fmt.Sprintf("%s:%d", host, port) + turnServerAddr := genString(option.TurnRelayOptions.ServerOptions) //fmt.Sprintf("%s:%d", option.TurnRelay.Server, option.TurnRelay.Port) conn, err := net.Dial("udp", turnServerAddr) if err != nil { log.Panicf("Failed to connect to TURN server: %s", err) + return nil } - cred := strings.SplitN(user, "=", 2) - // Start a new TURN Client and wrap our net.Conn in a STUNConn // This allows us to simulate datagram based communication over a net.Conn cfg := &turn.ClientConfig{ STUNServerAddr: turnServerAddr, TURNServerAddr: turnServerAddr, Conn: turn.NewSTUNConn(conn), - Username: cred[0], - Password: cred[1], - Realm: "bale.ai", + Username: option.TurnRelayOptions.Username, + Password: option.TurnRelayOptions.Password, + Realm: option.TurnRelayOptions.Realm, LoggerFactory: logging.NewDefaultLoggerFactory(), } client, err := turn.NewClient(cfg) if err != nil { log.Panicf("Failed to create TURN client: %s", err) + return nil } defer client.Close() @@ -67,6 +69,7 @@ func ApplyBale(udp_host string,udp_port uint16)(*Bale,error) { err = client.Listen() if err != nil { log.Panicf("Failed to listen: %s", err) + return nil } // Allocate a relay socket on the TURN server. On success, it @@ -75,6 +78,7 @@ func ApplyBale(udp_host string,udp_port uint16)(*Bale,error) { relayConn, err := client.Allocate() if err != nil { log.Panicf("Failed to allocate: %s", err) + return nil } defer func() { if closeErr := relayConn.Close(); closeErr != nil { @@ -84,27 +88,21 @@ func ApplyBale(udp_host string,udp_port uint16)(*Bale,error) { rnd_port,err:=getRandomPort(10000,30000) if err!=nil{ log.Panicf("Failed to get random port: %s", err) - return nil,err + return nil } // The relayConn's local address is actually the transport // address assigned on the TURN server. log.Printf("relayed-address=%s", relayConn.LocalAddr().String()) // Forward(src, dst). It's asynchronous. - forwarder, err := Forward(fmt.Sprint("127.0.0.1:%d",rnd_port), server, relayConn, DefaultTimeout) + forwarder, err := Forward(fmt.Sprint("127.0.0.1:%d",rnd_port), targetServerAddr, relayConn, DefaultTimeout) if err != nil { - return nil,err + return nil } forwarder.Run() - return &Bale{ - Host:udp_host, - Port:udp_port, - RelayPort:rnd_port, - Forwarder:forwarder, - },nil -} -func (f *Bale) Close() { - f.Forwarder.Close() + option.Server="127.0.0.1" + option.ServerPort=rnd_port + return forwarder } diff --git a/outbound/hysteria.go b/outbound/hysteria.go index 8c130e33bb..c031c1d124 100644 --- a/outbound/hysteria.go +++ b/outbound/hysteria.go @@ -20,6 +20,7 @@ import ( E "github.com/sagernet/sing/common/exceptions" M "github.com/sagernet/sing/common/metadata" N "github.com/sagernet/sing/common/network" + "github.com/sagernet/sing-box/outbound/houtbound" ) var ( @@ -30,6 +31,7 @@ var ( type Hysteria struct { myOutboundAdapter client *hysteria.Client + hforwarder *houtbound.Forwarder } func NewHysteria(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.HysteriaOutboundOptions) (*Hysteria, error) { @@ -37,6 +39,7 @@ func NewHysteria(ctx context.Context, router adapter.Router, logger log.ContextL if options.TLS == nil || !options.TLS.Enabled { return nil, C.ErrTLSRequired } + hforwarder := houtbound.ApplyTurnRelay(houtbound.CommonTurnRelayOptions{ServerOptions: options.ServerOptions,TurnRelayOptions: options.TurnRelay}) tlsConfig, err := tls.NewClient(ctx, options.Server, common.PtrValueOrDefault(options.TLS)) if err != nil { return nil, err @@ -98,6 +101,7 @@ func NewHysteria(ctx context.Context, router adapter.Router, logger log.ContextL dependencies: withDialerDependency(options.DialerOptions), }, client: client, + hforwarder: hforwarder, }, nil } diff --git a/outbound/hysteria2.go b/outbound/hysteria2.go index cc99770ee5..de172747df 100644 --- a/outbound/hysteria2.go +++ b/outbound/hysteria2.go @@ -20,7 +20,7 @@ import ( E "github.com/sagernet/sing/common/exceptions" M "github.com/sagernet/sing/common/metadata" N "github.com/sagernet/sing/common/network" - "github.com/sagernet/sing-box/outbound/hiddify" + "github.com/sagernet/sing-box/outbound/houtbound" ) var ( @@ -31,7 +31,7 @@ var ( type Hysteria2 struct { myOutboundAdapter client *hysteria2.Client - bale *hiddify.Bale + hforwarder *houtbound.Forwarder } func NewHysteria2(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.Hysteria2OutboundOptions) (*Hysteria2, error) { @@ -39,18 +39,8 @@ func NewHysteria2(ctx context.Context, router adapter.Router, logger log.Context if options.TLS == nil || !options.TLS.Enabled { return nil, C.ErrTLSRequired } - var bale *hiddify.Bale - if options.Bale { - var err2 error - bale,err2 = hiddify.ApplyBale(options.Server, options.ServerPort) - if err2 == nil { - options.Server=bale.Host - options.ServerPort=bale.RelayPort - options.Server="127.0.0.1" - }else{ - return nil, err2 - } - } + hforwarder := houtbound.ApplyTurnRelay(houtbound.CommonTurnRelayOptions{ServerOptions: options.ServerOptions,TurnRelayOptions: options.TurnRelay}) + tlsConfig, err := tls.NewClient(ctx, options.Server, common.PtrValueOrDefault(options.TLS)) if err != nil { return nil, err @@ -98,7 +88,7 @@ func NewHysteria2(ctx context.Context, router adapter.Router, logger log.Context dependencies: withDialerDependency(options.DialerOptions), }, client: client, - bale: bale, + hforwarder: hforwarder, }, nil } @@ -136,8 +126,8 @@ func (h *Hysteria2) InterfaceUpdated() error { } func (h *Hysteria2) Close() error { - if h.bale != nil { - h.bale.Close() + if h.hforwarder != nil { + h.hforwarder.Close() } return h.client.CloseWithError(os.ErrClosed) } diff --git a/outbound/tuic.go b/outbound/tuic.go index 01a774489b..49cc4c0ab4 100644 --- a/outbound/tuic.go +++ b/outbound/tuic.go @@ -23,8 +23,8 @@ import ( "github.com/sagernet/sing/common/uot" "github.com/gofrs/uuid/v5" - "github.com/sagernet/sing-box/outbound/hiddify" - "fmt" + + "github.com/sagernet/sing-box/outbound/houtbound" ) var ( @@ -36,7 +36,7 @@ type TUIC struct { myOutboundAdapter client *tuic.Client udpStream bool - bale *hiddify.Bale + hforwarder *houtbound.Forwarder } func NewTUIC(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.TUICOutboundOptions) (*TUIC, error) { @@ -44,24 +44,7 @@ func NewTUIC(ctx context.Context, router adapter.Router, logger log.ContextLogge if options.TLS == nil || !options.TLS.Enabled { return nil, C.ErrTLSRequired } - var bale *hiddify.Bale - fmt.Println("===========================") - logger.Debug("bale=======") - if options.Bale { - var err2 error - fmt.Println("original tuic %+v",options) - // bale,err2 = hiddify.ApplyBale(options.Server, options.ServerPort) - bale=&hiddify.Bale{Host:"1.1.1.1",Port:443,RelayPort:1000} - err2=nil - if err2 == nil { - options.Server="127.0.0.1" - options.ServerPort=bale.RelayPort - - fmt.Println("Starting tuic with bale in %+v",options) - }else{ - return nil, err2 - } - } + hforwarder := houtbound.ApplyTurnRelay(houtbound.CommonTurnRelayOptions{ServerOptions: options.ServerOptions,TurnRelayOptions: options.TurnRelay}) tlsConfig, err := tls.NewClient(ctx, options.Server, common.PtrValueOrDefault(options.TLS)) if err != nil { return nil, err @@ -109,7 +92,7 @@ func NewTUIC(ctx context.Context, router adapter.Router, logger log.ContextLogge }, client: client, udpStream: options.UDPOverStream, - bale: bale, + hforwarder: hforwarder, }, nil } @@ -171,8 +154,8 @@ func (h *TUIC) InterfaceUpdated() { } func (h *TUIC) Close() error { - if h.bale != nil { - h.bale.Close() + if h.hforwarder != nil { + h.hforwarder.Close() } return h.client.CloseWithError(os.ErrClosed) } diff --git a/outbound/wireguard.go b/outbound/wireguard.go index e645f056c6..0c68da489f 100644 --- a/outbound/wireguard.go +++ b/outbound/wireguard.go @@ -1,3 +1,4 @@ + //go:build with_wireguard package outbound @@ -23,6 +24,7 @@ import ( M "github.com/sagernet/sing/common/metadata" N "github.com/sagernet/sing/common/network" "github.com/sagernet/wireguard-go/device" + "github.com/sagernet/sing-box/outbound/houtbound" ) var ( @@ -35,9 +37,11 @@ type WireGuard struct { bind *wireguard.ClientBind device *device.Device tunDevice wireguard.Device + hforwarder *houtbound.Forwarder } func NewWireGuard(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.WireGuardOutboundOptions) (*WireGuard, error) { + hforwarder := houtbound.ApplyTurnRelay(houtbound.CommonTurnRelayOptions{ServerOptions: options.ServerOptions,TurnRelayOptions: options.TurnRelay}) outbound := &WireGuard{ myOutboundAdapter: myOutboundAdapter{ protocol: C.TypeWireGuard, @@ -47,6 +51,7 @@ func NewWireGuard(ctx context.Context, router adapter.Router, logger log.Context tag: tag, dependencies: withDialerDependency(options.DialerOptions), }, + hforwarder: hforwarder, } var reserved [3]uint8 if len(options.Reserved) > 0 { @@ -239,6 +244,9 @@ func (w *WireGuard) Start() error { } func (w *WireGuard) Close() error { + if w.hforwarder != nil { + w.hforwarder.Close() + } if w.device != nil { w.device.Close() }