mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-22 08:31:30 +00:00
Refactor struct & Add override dialer options
This commit is contained in:
parent
28b865acf0
commit
18e3f43df3
|
@ -22,5 +22,5 @@ type InboundContext struct {
|
||||||
|
|
||||||
SourceGeoIPCode string
|
SourceGeoIPCode string
|
||||||
GeoIPCode string
|
GeoIPCode string
|
||||||
ProcessPath string
|
// ProcessPath string
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,138 +0,0 @@
|
||||||
package outbound
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"net"
|
|
||||||
"runtime"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/database64128/tfo-go"
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
|
||||||
"github.com/sagernet/sing-box/log"
|
|
||||||
"github.com/sagernet/sing-box/option"
|
|
||||||
"github.com/sagernet/sing/common"
|
|
||||||
"github.com/sagernet/sing/common/buf"
|
|
||||||
"github.com/sagernet/sing/common/bufio"
|
|
||||||
"github.com/sagernet/sing/common/control"
|
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
|
||||||
N "github.com/sagernet/sing/common/network"
|
|
||||||
)
|
|
||||||
|
|
||||||
type myOutboundAdapter struct {
|
|
||||||
protocol string
|
|
||||||
logger log.Logger
|
|
||||||
tag string
|
|
||||||
dialer N.Dialer
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *myOutboundAdapter) Type() string {
|
|
||||||
return a.protocol
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *myOutboundAdapter) Tag() string {
|
|
||||||
return a.tag
|
|
||||||
}
|
|
||||||
|
|
||||||
type defaultDialer struct {
|
|
||||||
tfo.Dialer
|
|
||||||
net.ListenConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *defaultDialer) DialContext(ctx context.Context, network string, address M.Socksaddr) (net.Conn, error) {
|
|
||||||
return d.Dialer.DialContext(ctx, network, address.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *defaultDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
|
||||||
return d.ListenConfig.ListenPacket(ctx, "udp", "")
|
|
||||||
}
|
|
||||||
|
|
||||||
func newDialer(options option.DialerOptions) N.Dialer {
|
|
||||||
var dialer net.Dialer
|
|
||||||
var listener net.ListenConfig
|
|
||||||
if options.BindInterface != "" {
|
|
||||||
dialer.Control = control.Append(dialer.Control, control.BindToInterface(options.BindInterface))
|
|
||||||
listener.Control = control.Append(listener.Control, control.BindToInterface(options.BindInterface))
|
|
||||||
}
|
|
||||||
if options.RoutingMark != 0 {
|
|
||||||
dialer.Control = control.Append(dialer.Control, control.RoutingMark(options.RoutingMark))
|
|
||||||
listener.Control = control.Append(listener.Control, control.RoutingMark(options.RoutingMark))
|
|
||||||
}
|
|
||||||
if options.ReuseAddr {
|
|
||||||
listener.Control = control.Append(listener.Control, control.ReuseAddr())
|
|
||||||
}
|
|
||||||
if options.ConnectTimeout != 0 {
|
|
||||||
dialer.Timeout = time.Duration(options.ConnectTimeout) * time.Second
|
|
||||||
}
|
|
||||||
return &defaultDialer{tfo.Dialer{Dialer: dialer, DisableTFO: !options.TCPFastOpen}, listener}
|
|
||||||
}
|
|
||||||
|
|
||||||
type lazyDialer struct {
|
|
||||||
router adapter.Router
|
|
||||||
options option.DialerOptions
|
|
||||||
dialer N.Dialer
|
|
||||||
initOnce sync.Once
|
|
||||||
initErr error
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewDialer(router adapter.Router, options option.DialerOptions) N.Dialer {
|
|
||||||
if options.Detour == "" {
|
|
||||||
return newDialer(options)
|
|
||||||
}
|
|
||||||
return &lazyDialer{
|
|
||||||
router: router,
|
|
||||||
options: options,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *lazyDialer) Dialer() (N.Dialer, error) {
|
|
||||||
d.initOnce.Do(func() {
|
|
||||||
var loaded bool
|
|
||||||
d.dialer, loaded = d.router.Outbound(d.options.Detour)
|
|
||||||
if !loaded {
|
|
||||||
d.initErr = E.New("outbound detour not found: ", d.options.Detour)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return d.dialer, d.initErr
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *lazyDialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
|
||||||
dialer, err := d.Dialer()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return dialer.DialContext(ctx, network, destination)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *lazyDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
|
||||||
dialer, err := d.Dialer()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return dialer.ListenPacket(ctx, destination)
|
|
||||||
}
|
|
||||||
|
|
||||||
func CopyEarlyConn(ctx context.Context, conn net.Conn, serverConn net.Conn) error {
|
|
||||||
_payload := buf.StackNew()
|
|
||||||
payload := common.Dup(_payload)
|
|
||||||
err := conn.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
_, err = payload.ReadFrom(conn)
|
|
||||||
if err != nil && !E.IsTimeout(err) {
|
|
||||||
return E.Cause(err, "read payload")
|
|
||||||
}
|
|
||||||
err = conn.SetReadDeadline(time.Time{})
|
|
||||||
if err != nil {
|
|
||||||
payload.Release()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
_, err = serverConn.Write(payload.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
return E.Cause(err, "client handshake")
|
|
||||||
}
|
|
||||||
runtime.KeepAlive(_payload)
|
|
||||||
return bufio.CopyConn(ctx, conn, serverConn)
|
|
||||||
}
|
|
|
@ -59,9 +59,9 @@ func (a *myInboundAdapter) Start() error {
|
||||||
var tcpListener *net.TCPListener
|
var tcpListener *net.TCPListener
|
||||||
var err error
|
var err error
|
||||||
if !a.listenOptions.TCPFastOpen {
|
if !a.listenOptions.TCPFastOpen {
|
||||||
tcpListener, err = net.ListenTCP(M.NetworkFromNetAddr("tcp", bindAddr.Addr), bindAddr.TCPAddr())
|
tcpListener, err = net.ListenTCP(M.NetworkFromNetAddr(C.NetworkTCP, bindAddr.Addr), bindAddr.TCPAddr())
|
||||||
} else {
|
} else {
|
||||||
tcpListener, err = tfo.ListenTCP(M.NetworkFromNetAddr("tcp", bindAddr.Addr), bindAddr.TCPAddr())
|
tcpListener, err = tfo.ListenTCP(M.NetworkFromNetAddr(C.NetworkTCP, bindAddr.Addr), bindAddr.TCPAddr())
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -71,7 +71,7 @@ func (a *myInboundAdapter) Start() error {
|
||||||
listenAddr = tcpListener.Addr()
|
listenAddr = tcpListener.Addr()
|
||||||
}
|
}
|
||||||
if common.Contains(a.network, C.NetworkUDP) {
|
if common.Contains(a.network, C.NetworkUDP) {
|
||||||
udpConn, err := net.ListenUDP(M.NetworkFromNetAddr("udp", bindAddr.Addr), bindAddr.UDPAddr())
|
udpConn, err := net.ListenUDP(M.NetworkFromNetAddr(C.NetworkUDP, bindAddr.Addr), bindAddr.UDPAddr())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -136,7 +136,7 @@ func (a *myInboundAdapter) loopTCPIn() {
|
||||||
ctx := log.ContextWithID(a.ctx)
|
ctx := log.ContextWithID(a.ctx)
|
||||||
var metadata adapter.InboundContext
|
var metadata adapter.InboundContext
|
||||||
metadata.Inbound = a.tag
|
metadata.Inbound = a.tag
|
||||||
metadata.Network = "tcp"
|
metadata.Network = C.NetworkTCP
|
||||||
metadata.Source = M.SocksaddrFromNet(conn.RemoteAddr())
|
metadata.Source = M.SocksaddrFromNet(conn.RemoteAddr())
|
||||||
a.logger.WithContext(ctx).Info("inbound connection from ", metadata.Source)
|
a.logger.WithContext(ctx).Info("inbound connection from ", metadata.Source)
|
||||||
hErr := a.connHandler.NewConnection(ctx, conn, metadata)
|
hErr := a.connHandler.NewConnection(ctx, conn, metadata)
|
||||||
|
@ -165,7 +165,7 @@ func (a *myInboundAdapter) loopUDPIn() {
|
||||||
buffer.Truncate(n)
|
buffer.Truncate(n)
|
||||||
var metadata adapter.InboundContext
|
var metadata adapter.InboundContext
|
||||||
metadata.Inbound = a.tag
|
metadata.Inbound = a.tag
|
||||||
metadata.Network = "udp"
|
metadata.Network = C.NetworkUDP
|
||||||
metadata.Source = M.SocksaddrFromNetIP(addr)
|
metadata.Source = M.SocksaddrFromNetIP(addr)
|
||||||
err = a.packetHandler.NewPacket(a.ctx, packetService, buffer, metadata)
|
err = a.packetHandler.NewPacket(a.ctx, packetService, buffer, metadata)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -187,7 +187,7 @@ func (a *myInboundAdapter) loopUDPInThreadSafe() {
|
||||||
buffer.Truncate(n)
|
buffer.Truncate(n)
|
||||||
var metadata adapter.InboundContext
|
var metadata adapter.InboundContext
|
||||||
metadata.Inbound = a.tag
|
metadata.Inbound = a.tag
|
||||||
metadata.Network = "udp"
|
metadata.Network = C.NetworkUDP
|
||||||
metadata.Source = M.SocksaddrFromNetIP(addr)
|
metadata.Source = M.SocksaddrFromNetIP(addr)
|
||||||
err = a.packetHandler.NewPacket(a.ctx, packetService, buffer, metadata)
|
err = a.packetHandler.NewPacket(a.ctx, packetService, buffer, metadata)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -235,7 +235,7 @@ func (a *myInboundAdapter) NewError(ctx context.Context, err error) {
|
||||||
func (a *myInboundAdapter) writePacket(buffer *buf.Buffer, destination M.Socksaddr) error {
|
func (a *myInboundAdapter) writePacket(buffer *buf.Buffer, destination M.Socksaddr) error {
|
||||||
defer buffer.Release()
|
defer buffer.Release()
|
||||||
if destination.IsFqdn() {
|
if destination.IsFqdn() {
|
||||||
udpAddr, err := net.ResolveUDPAddr("udp", destination.String())
|
udpAddr, err := net.ResolveUDPAddr(C.NetworkUDP, destination.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
|
@ -21,7 +21,8 @@ func (v *NetworkList) UnmarshalJSON(data []byte) error {
|
||||||
}
|
}
|
||||||
for _, networkName := range networkList {
|
for _, networkName := range networkList {
|
||||||
switch networkName {
|
switch networkName {
|
||||||
case "tcp", "udp":
|
case C.NetworkTCP, C.NetworkUDP:
|
||||||
|
break
|
||||||
default:
|
default:
|
||||||
return E.New("unknown network: " + networkName)
|
return E.New("unknown network: " + networkName)
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,12 +55,20 @@ func (h *Outbound) UnmarshalJSON(bytes []byte) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
type DialerOptions struct {
|
type DialerOptions struct {
|
||||||
Detour string `json:"detour,omitempty"`
|
Detour string `json:"detour,omitempty"`
|
||||||
BindInterface string `json:"bind_interface,omitempty"`
|
BindInterface string `json:"bind_interface,omitempty"`
|
||||||
RoutingMark int `json:"routing_mark,omitempty"`
|
RoutingMark int `json:"routing_mark,omitempty"`
|
||||||
ReuseAddr bool `json:"reuse_addr,omitempty"`
|
ReuseAddr bool `json:"reuse_addr,omitempty"`
|
||||||
ConnectTimeout int `json:"connect_timeout,omitempty"`
|
ConnectTimeout int `json:"connect_timeout,omitempty"`
|
||||||
TCPFastOpen bool `json:"tcp_fast_open,omitempty"`
|
TCPFastOpen bool `json:"tcp_fast_open,omitempty"`
|
||||||
|
OverrideOptions *OverrideStreamOptions `json:"override,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type OverrideStreamOptions struct {
|
||||||
|
TLS bool `json:"tls,omitempty"`
|
||||||
|
TLSServerName string `json:"tls_servername,omitempty"`
|
||||||
|
TLSInsecure bool `json:"tls_insecure,omitempty"`
|
||||||
|
UDPOverTCP bool `json:"udp_over_tcp,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type DirectOutboundOptions struct {
|
type DirectOutboundOptions struct {
|
||||||
|
|
54
outbound/default.go
Normal file
54
outbound/default.go
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
package outbound
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net"
|
||||||
|
"runtime"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing-box/log"
|
||||||
|
"github.com/sagernet/sing/common"
|
||||||
|
"github.com/sagernet/sing/common/buf"
|
||||||
|
"github.com/sagernet/sing/common/bufio"
|
||||||
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
)
|
||||||
|
|
||||||
|
type myOutboundAdapter struct {
|
||||||
|
protocol string
|
||||||
|
logger log.Logger
|
||||||
|
tag string
|
||||||
|
dialer N.Dialer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *myOutboundAdapter) Type() string {
|
||||||
|
return a.protocol
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *myOutboundAdapter) Tag() string {
|
||||||
|
return a.tag
|
||||||
|
}
|
||||||
|
|
||||||
|
func CopyEarlyConn(ctx context.Context, conn net.Conn, serverConn net.Conn) error {
|
||||||
|
_payload := buf.StackNew()
|
||||||
|
payload := common.Dup(_payload)
|
||||||
|
err := conn.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = payload.ReadFrom(conn)
|
||||||
|
if err != nil && !E.IsTimeout(err) {
|
||||||
|
return E.Cause(err, "read payload")
|
||||||
|
}
|
||||||
|
err = conn.SetReadDeadline(time.Time{})
|
||||||
|
if err != nil {
|
||||||
|
payload.Release()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = serverConn.Write(payload.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
return E.Cause(err, "client handshake")
|
||||||
|
}
|
||||||
|
runtime.KeepAlive(_payload)
|
||||||
|
return bufio.CopyConn(ctx, conn, serverConn)
|
||||||
|
}
|
47
outbound/dialer/default.go
Normal file
47
outbound/dialer/default.go
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
package dialer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/database64128/tfo-go"
|
||||||
|
C "github.com/sagernet/sing-box/constant"
|
||||||
|
"github.com/sagernet/sing-box/option"
|
||||||
|
"github.com/sagernet/sing/common/control"
|
||||||
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
)
|
||||||
|
|
||||||
|
type defaultDialer struct {
|
||||||
|
tfo.Dialer
|
||||||
|
net.ListenConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
func newDefault(options option.DialerOptions) N.Dialer {
|
||||||
|
var dialer net.Dialer
|
||||||
|
var listener net.ListenConfig
|
||||||
|
if options.BindInterface != "" {
|
||||||
|
dialer.Control = control.Append(dialer.Control, control.BindToInterface(options.BindInterface))
|
||||||
|
listener.Control = control.Append(listener.Control, control.BindToInterface(options.BindInterface))
|
||||||
|
}
|
||||||
|
if options.RoutingMark != 0 {
|
||||||
|
dialer.Control = control.Append(dialer.Control, control.RoutingMark(options.RoutingMark))
|
||||||
|
listener.Control = control.Append(listener.Control, control.RoutingMark(options.RoutingMark))
|
||||||
|
}
|
||||||
|
if options.ReuseAddr {
|
||||||
|
listener.Control = control.Append(listener.Control, control.ReuseAddr())
|
||||||
|
}
|
||||||
|
if options.ConnectTimeout != 0 {
|
||||||
|
dialer.Timeout = time.Duration(options.ConnectTimeout) * time.Second
|
||||||
|
}
|
||||||
|
return &defaultDialer{tfo.Dialer{Dialer: dialer, DisableTFO: !options.TCPFastOpen}, listener}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *defaultDialer) DialContext(ctx context.Context, network string, address M.Socksaddr) (net.Conn, error) {
|
||||||
|
return d.Dialer.DialContext(ctx, network, address.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *defaultDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
||||||
|
return d.ListenConfig.ListenPacket(ctx, C.NetworkUDP, "")
|
||||||
|
}
|
52
outbound/dialer/detour.go
Normal file
52
outbound/dialer/detour.go
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
package dialer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
"github.com/sagernet/sing-box/option"
|
||||||
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
)
|
||||||
|
|
||||||
|
type detourDialer struct {
|
||||||
|
router adapter.Router
|
||||||
|
options option.DialerOptions
|
||||||
|
dialer N.Dialer
|
||||||
|
initOnce sync.Once
|
||||||
|
initErr error
|
||||||
|
}
|
||||||
|
|
||||||
|
func newDetour(router adapter.Router, options option.DialerOptions) N.Dialer {
|
||||||
|
return &detourDialer{router: router, options: options}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *detourDialer) Dialer() (N.Dialer, error) {
|
||||||
|
d.initOnce.Do(func() {
|
||||||
|
var loaded bool
|
||||||
|
d.dialer, loaded = d.router.Outbound(d.options.Detour)
|
||||||
|
if !loaded {
|
||||||
|
d.initErr = E.New("outbound detour not found: ", d.options.Detour)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return d.dialer, d.initErr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *detourDialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||||
|
dialer, err := d.Dialer()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return dialer.DialContext(ctx, network, destination)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *detourDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
||||||
|
dialer, err := d.Dialer()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return dialer.ListenPacket(ctx, destination)
|
||||||
|
}
|
21
outbound/dialer/dialer.go
Normal file
21
outbound/dialer/dialer.go
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
package dialer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
"github.com/sagernet/sing-box/option"
|
||||||
|
"github.com/sagernet/sing/common"
|
||||||
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
)
|
||||||
|
|
||||||
|
func New(router adapter.Router, options option.DialerOptions) N.Dialer {
|
||||||
|
var dialer N.Dialer
|
||||||
|
if options.Detour == "" {
|
||||||
|
dialer = newDefault(options)
|
||||||
|
} else {
|
||||||
|
dialer = newDetour(router, options)
|
||||||
|
}
|
||||||
|
if options.OverrideOptions != nil {
|
||||||
|
dialer = newOverride(dialer, common.PtrValueOrDefault(options.OverrideOptions))
|
||||||
|
}
|
||||||
|
return dialer
|
||||||
|
}
|
68
outbound/dialer/override.go
Normal file
68
outbound/dialer/override.go
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
package dialer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
|
"net"
|
||||||
|
|
||||||
|
C "github.com/sagernet/sing-box/constant"
|
||||||
|
"github.com/sagernet/sing-box/option"
|
||||||
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
"github.com/sagernet/sing/common/uot"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ N.Dialer = (*overrideDialer)(nil)
|
||||||
|
|
||||||
|
type overrideDialer struct {
|
||||||
|
upstream N.Dialer
|
||||||
|
tlsEnabled bool
|
||||||
|
tlsConfig tls.Config
|
||||||
|
uotEnabled bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func newOverride(upstream N.Dialer, options option.OverrideStreamOptions) N.Dialer {
|
||||||
|
if !options.TLS && !options.UDPOverTCP {
|
||||||
|
return upstream
|
||||||
|
}
|
||||||
|
return &overrideDialer{
|
||||||
|
upstream,
|
||||||
|
options.TLS,
|
||||||
|
tls.Config{
|
||||||
|
ServerName: options.TLSServerName,
|
||||||
|
InsecureSkipVerify: options.TLSInsecure,
|
||||||
|
},
|
||||||
|
options.UDPOverTCP,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *overrideDialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||||
|
switch network {
|
||||||
|
case C.NetworkTCP:
|
||||||
|
conn, err := d.upstream.DialContext(ctx, C.NetworkTCP, destination)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return tls.Client(conn, &d.tlsConfig), nil
|
||||||
|
case C.NetworkUDP:
|
||||||
|
if d.uotEnabled {
|
||||||
|
tcpConn, err := d.upstream.DialContext(ctx, C.NetworkTCP, destination)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return uot.NewClientConn(tcpConn), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return d.upstream.DialContext(ctx, network, destination)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *overrideDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
||||||
|
if d.uotEnabled {
|
||||||
|
tcpConn, err := d.upstream.DialContext(ctx, C.NetworkTCP, destination)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return uot.NewClientConn(tcpConn), nil
|
||||||
|
}
|
||||||
|
return d.upstream.ListenPacket(ctx, destination)
|
||||||
|
}
|
|
@ -8,6 +8,7 @@ import (
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
|
"github.com/sagernet/sing-box/outbound/dialer"
|
||||||
"github.com/sagernet/sing/common/bufio"
|
"github.com/sagernet/sing/common/bufio"
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
@ -27,7 +28,7 @@ func NewDirect(router adapter.Router, logger log.Logger, tag string, options opt
|
||||||
protocol: C.TypeDirect,
|
protocol: C.TypeDirect,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
tag: tag,
|
tag: tag,
|
||||||
dialer: NewDialer(router, options.DialerOptions),
|
dialer: dialer.New(router, options.DialerOptions),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if options.OverrideAddress != "" && options.OverridePort != 0 {
|
if options.OverrideAddress != "" && options.OverridePort != 0 {
|
||||||
|
@ -69,7 +70,7 @@ func (d *Direct) ListenPacket(ctx context.Context, destination M.Socksaddr) (net
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Direct) NewConnection(ctx context.Context, conn net.Conn, destination M.Socksaddr) error {
|
func (d *Direct) NewConnection(ctx context.Context, conn net.Conn, destination M.Socksaddr) error {
|
||||||
outConn, err := d.DialContext(ctx, "tcp", destination)
|
outConn, err := d.DialContext(ctx, C.NetworkTCP, destination)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
|
@ -8,6 +8,7 @@ import (
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
|
"github.com/sagernet/sing-box/outbound/dialer"
|
||||||
"github.com/sagernet/sing-shadowsocks"
|
"github.com/sagernet/sing-shadowsocks"
|
||||||
"github.com/sagernet/sing-shadowsocks/shadowimpl"
|
"github.com/sagernet/sing-shadowsocks/shadowimpl"
|
||||||
"github.com/sagernet/sing/common/bufio"
|
"github.com/sagernet/sing/common/bufio"
|
||||||
|
@ -30,7 +31,7 @@ func NewShadowsocks(router adapter.Router, logger log.Logger, tag string, option
|
||||||
protocol: C.TypeDirect,
|
protocol: C.TypeDirect,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
tag: tag,
|
tag: tag,
|
||||||
dialer: NewDialer(router, options.DialerOptions),
|
dialer: dialer.New(router, options.DialerOptions),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
var err error
|
var err error
|
||||||
|
@ -51,14 +52,14 @@ func (o *Shadowsocks) DialContext(ctx context.Context, network string, destinati
|
||||||
switch network {
|
switch network {
|
||||||
case C.NetworkTCP:
|
case C.NetworkTCP:
|
||||||
o.logger.WithContext(ctx).Info("outbound connection to ", destination)
|
o.logger.WithContext(ctx).Info("outbound connection to ", destination)
|
||||||
outConn, err := o.dialer.DialContext(ctx, "tcp", o.serverAddr)
|
outConn, err := o.dialer.DialContext(ctx, C.NetworkTCP, o.serverAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return o.method.DialEarlyConn(outConn, destination), nil
|
return o.method.DialEarlyConn(outConn, destination), nil
|
||||||
case C.NetworkUDP:
|
case C.NetworkUDP:
|
||||||
o.logger.WithContext(ctx).Info("outbound packet connection to ", destination)
|
o.logger.WithContext(ctx).Info("outbound packet connection to ", destination)
|
||||||
outConn, err := o.dialer.DialContext(ctx, "udp", o.serverAddr)
|
outConn, err := o.dialer.DialContext(ctx, C.NetworkUDP, o.serverAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -78,7 +79,7 @@ func (o *Shadowsocks) ListenPacket(ctx context.Context, destination M.Socksaddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Shadowsocks) NewConnection(ctx context.Context, conn net.Conn, destination M.Socksaddr) error {
|
func (o *Shadowsocks) NewConnection(ctx context.Context, conn net.Conn, destination M.Socksaddr) error {
|
||||||
serverConn, err := o.DialContext(ctx, "tcp", destination)
|
serverConn, err := o.DialContext(ctx, C.NetworkTCP, destination)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
|
@ -8,6 +8,7 @@ import (
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
|
"github.com/sagernet/sing-box/outbound/dialer"
|
||||||
"github.com/sagernet/sing/common/bufio"
|
"github.com/sagernet/sing/common/bufio"
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
@ -22,7 +23,7 @@ type Socks struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSocks(router adapter.Router, logger log.Logger, tag string, options option.SocksOutboundOptions) (*Socks, error) {
|
func NewSocks(router adapter.Router, logger log.Logger, tag string, options option.SocksOutboundOptions) (*Socks, error) {
|
||||||
dialer := NewDialer(router, options.DialerOptions)
|
dialer := dialer.New(router, options.DialerOptions)
|
||||||
var version socks.Version
|
var version socks.Version
|
||||||
var err error
|
var err error
|
||||||
if options.Version != "" {
|
if options.Version != "" {
|
||||||
|
@ -62,7 +63,7 @@ func (h *Socks) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Socks) NewConnection(ctx context.Context, conn net.Conn, destination M.Socksaddr) error {
|
func (h *Socks) NewConnection(ctx context.Context, conn net.Conn, destination M.Socksaddr) error {
|
||||||
outConn, err := h.DialContext(ctx, "tcp", destination)
|
outConn, err := h.DialContext(ctx, C.NetworkTCP, destination)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
10
service.go
10
service.go
|
@ -4,11 +4,11 @@ import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
"github.com/sagernet/sing-box/adapter/inbound"
|
"github.com/sagernet/sing-box/inbound"
|
||||||
"github.com/sagernet/sing-box/adapter/outbound"
|
|
||||||
"github.com/sagernet/sing-box/adapter/route"
|
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
|
outbound2 "github.com/sagernet/sing-box/outbound"
|
||||||
|
"github.com/sagernet/sing-box/route"
|
||||||
"github.com/sagernet/sing/common"
|
"github.com/sagernet/sing/common"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
)
|
)
|
||||||
|
@ -43,14 +43,14 @@ func NewService(ctx context.Context, options option.Options) (*Service, error) {
|
||||||
}
|
}
|
||||||
for i, outboundOptions := range options.Outbounds {
|
for i, outboundOptions := range options.Outbounds {
|
||||||
var outboundService adapter.Outbound
|
var outboundService adapter.Outbound
|
||||||
outboundService, err = outbound.New(router, logger, i, outboundOptions)
|
outboundService, err = outbound2.New(router, logger, i, outboundOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, E.Cause(err, "parse outbound[", i, "]")
|
return nil, E.Cause(err, "parse outbound[", i, "]")
|
||||||
}
|
}
|
||||||
outbounds = append(outbounds, outboundService)
|
outbounds = append(outbounds, outboundService)
|
||||||
}
|
}
|
||||||
if len(outbounds) == 0 {
|
if len(outbounds) == 0 {
|
||||||
outbounds = append(outbounds, outbound.NewDirect(nil, logger, "direct", option.DirectOutboundOptions{}))
|
outbounds = append(outbounds, outbound2.NewDirect(nil, logger, "direct", option.DirectOutboundOptions{}))
|
||||||
}
|
}
|
||||||
router.UpdateOutbounds(outbounds)
|
router.UpdateOutbounds(outbounds)
|
||||||
return &Service{
|
return &Service{
|
||||||
|
|
Loading…
Reference in a new issue