default.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. package outbound
  2. import (
  3. "context"
  4. "net"
  5. "runtime"
  6. "sync"
  7. "time"
  8. "github.com/database64128/tfo-go"
  9. "github.com/sagernet/sing-box/adapter"
  10. "github.com/sagernet/sing-box/log"
  11. "github.com/sagernet/sing-box/option"
  12. "github.com/sagernet/sing/common"
  13. "github.com/sagernet/sing/common/buf"
  14. "github.com/sagernet/sing/common/bufio"
  15. "github.com/sagernet/sing/common/control"
  16. E "github.com/sagernet/sing/common/exceptions"
  17. M "github.com/sagernet/sing/common/metadata"
  18. N "github.com/sagernet/sing/common/network"
  19. )
  20. type myOutboundAdapter struct {
  21. protocol string
  22. logger log.Logger
  23. tag string
  24. dialer N.Dialer
  25. }
  26. func (a *myOutboundAdapter) Type() string {
  27. return a.protocol
  28. }
  29. func (a *myOutboundAdapter) Tag() string {
  30. return a.tag
  31. }
  32. type defaultDialer struct {
  33. tfo.Dialer
  34. net.ListenConfig
  35. }
  36. func (d *defaultDialer) DialContext(ctx context.Context, network string, address M.Socksaddr) (net.Conn, error) {
  37. return d.Dialer.DialContext(ctx, network, address.String())
  38. }
  39. func (d *defaultDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
  40. return d.ListenConfig.ListenPacket(ctx, "udp", "")
  41. }
  42. func newDialer(options option.DialerOptions) N.Dialer {
  43. var dialer net.Dialer
  44. var listener net.ListenConfig
  45. if options.BindInterface != "" {
  46. dialer.Control = control.Append(dialer.Control, control.BindToInterface(options.BindInterface))
  47. listener.Control = control.Append(listener.Control, control.BindToInterface(options.BindInterface))
  48. }
  49. if options.RoutingMark != 0 {
  50. dialer.Control = control.Append(dialer.Control, control.RoutingMark(options.RoutingMark))
  51. listener.Control = control.Append(listener.Control, control.RoutingMark(options.RoutingMark))
  52. }
  53. if options.ReuseAddr {
  54. listener.Control = control.Append(listener.Control, control.ReuseAddr())
  55. }
  56. if options.ConnectTimeout != 0 {
  57. dialer.Timeout = time.Duration(options.ConnectTimeout) * time.Second
  58. }
  59. return &defaultDialer{tfo.Dialer{Dialer: dialer, DisableTFO: !options.TCPFastOpen}, listener}
  60. }
  61. type lazyDialer struct {
  62. router adapter.Router
  63. options option.DialerOptions
  64. dialer N.Dialer
  65. initOnce sync.Once
  66. initErr error
  67. }
  68. func NewDialer(router adapter.Router, options option.DialerOptions) N.Dialer {
  69. if options.Detour == "" {
  70. return newDialer(options)
  71. }
  72. return &lazyDialer{
  73. router: router,
  74. options: options,
  75. }
  76. }
  77. func (d *lazyDialer) Dialer() (N.Dialer, error) {
  78. d.initOnce.Do(func() {
  79. var loaded bool
  80. d.dialer, loaded = d.router.Outbound(d.options.Detour)
  81. if !loaded {
  82. d.initErr = E.New("outbound detour not found: ", d.options.Detour)
  83. }
  84. })
  85. return d.dialer, d.initErr
  86. }
  87. func (d *lazyDialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
  88. dialer, err := d.Dialer()
  89. if err != nil {
  90. return nil, err
  91. }
  92. return dialer.DialContext(ctx, network, destination)
  93. }
  94. func (d *lazyDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
  95. dialer, err := d.Dialer()
  96. if err != nil {
  97. return nil, err
  98. }
  99. return dialer.ListenPacket(ctx, destination)
  100. }
  101. func CopyEarlyConn(ctx context.Context, conn net.Conn, serverConn net.Conn) error {
  102. _payload := buf.StackNew()
  103. payload := common.Dup(_payload)
  104. err := conn.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
  105. if err != nil {
  106. return err
  107. }
  108. _, err = payload.ReadFrom(conn)
  109. if err != nil && !E.IsTimeout(err) {
  110. return E.Cause(err, "read payload")
  111. }
  112. err = conn.SetReadDeadline(time.Time{})
  113. if err != nil {
  114. payload.Release()
  115. return err
  116. }
  117. _, err = serverConn.Write(payload.Bytes())
  118. if err != nil {
  119. return E.Cause(err, "client handshake")
  120. }
  121. runtime.KeepAlive(_payload)
  122. return bufio.CopyConn(ctx, conn, serverConn)
  123. }