1
0

direct.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. package outbound
  2. import (
  3. "context"
  4. "net"
  5. "net/netip"
  6. "time"
  7. "github.com/sagernet/sing-box/adapter"
  8. "github.com/sagernet/sing-box/common/dialer"
  9. C "github.com/sagernet/sing-box/constant"
  10. "github.com/sagernet/sing-box/log"
  11. "github.com/sagernet/sing-box/option"
  12. "github.com/sagernet/sing-dns"
  13. "github.com/sagernet/sing/common/bufio"
  14. E "github.com/sagernet/sing/common/exceptions"
  15. M "github.com/sagernet/sing/common/metadata"
  16. N "github.com/sagernet/sing/common/network"
  17. )
  18. var (
  19. _ adapter.Outbound = (*Direct)(nil)
  20. _ N.ParallelDialer = (*Direct)(nil)
  21. )
  22. type Direct struct {
  23. myOutboundAdapter
  24. dialer N.Dialer
  25. domainStrategy dns.DomainStrategy
  26. fallbackDelay time.Duration
  27. overrideOption int
  28. overrideDestination M.Socksaddr
  29. // loopBack *loopBackDetector
  30. }
  31. func NewDirect(router adapter.Router, logger log.ContextLogger, tag string, options option.DirectOutboundOptions) (*Direct, error) {
  32. options.UDPFragmentDefault = true
  33. outboundDialer, err := dialer.New(router, options.DialerOptions)
  34. if err != nil {
  35. return nil, err
  36. }
  37. outbound := &Direct{
  38. myOutboundAdapter: myOutboundAdapter{
  39. protocol: C.TypeDirect,
  40. network: []string{N.NetworkTCP, N.NetworkUDP},
  41. router: router,
  42. logger: logger,
  43. tag: tag,
  44. dependencies: withDialerDependency(options.DialerOptions),
  45. },
  46. domainStrategy: dns.DomainStrategy(options.DomainStrategy),
  47. fallbackDelay: time.Duration(options.FallbackDelay),
  48. dialer: outboundDialer,
  49. // loopBack: newLoopBackDetector(router),
  50. }
  51. if options.ProxyProtocol != 0 {
  52. return nil, E.New("Proxy Protocol is deprecated and removed in sing-box 1.6.0")
  53. }
  54. if options.OverrideAddress != "" && options.OverridePort != 0 {
  55. outbound.overrideOption = 1
  56. outbound.overrideDestination = M.ParseSocksaddrHostPort(options.OverrideAddress, options.OverridePort)
  57. } else if options.OverrideAddress != "" {
  58. outbound.overrideOption = 2
  59. outbound.overrideDestination = M.ParseSocksaddrHostPort(options.OverrideAddress, options.OverridePort)
  60. } else if options.OverridePort != 0 {
  61. outbound.overrideOption = 3
  62. outbound.overrideDestination = M.Socksaddr{Port: options.OverridePort}
  63. }
  64. return outbound, nil
  65. }
  66. func (h *Direct) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
  67. ctx, metadata := adapter.ExtendContext(ctx)
  68. metadata.Outbound = h.tag
  69. metadata.Destination = destination
  70. switch h.overrideOption {
  71. case 1:
  72. destination = h.overrideDestination
  73. case 2:
  74. newDestination := h.overrideDestination
  75. newDestination.Port = destination.Port
  76. destination = newDestination
  77. case 3:
  78. destination.Port = h.overrideDestination.Port
  79. }
  80. network = N.NetworkName(network)
  81. switch network {
  82. case N.NetworkTCP:
  83. h.logger.InfoContext(ctx, "outbound connection to ", destination)
  84. case N.NetworkUDP:
  85. h.logger.InfoContext(ctx, "outbound packet connection to ", destination)
  86. }
  87. /*conn, err := h.dialer.DialContext(ctx, network, destination)
  88. if err != nil {
  89. return nil, err
  90. }
  91. return h.loopBack.NewConn(conn), nil*/
  92. return h.dialer.DialContext(ctx, network, destination)
  93. }
  94. func (h *Direct) DialParallel(ctx context.Context, network string, destination M.Socksaddr, destinationAddresses []netip.Addr) (net.Conn, error) {
  95. ctx, metadata := adapter.ExtendContext(ctx)
  96. metadata.Outbound = h.tag
  97. metadata.Destination = destination
  98. switch h.overrideOption {
  99. case 1, 2:
  100. // override address
  101. return h.DialContext(ctx, network, destination)
  102. case 3:
  103. destination.Port = h.overrideDestination.Port
  104. }
  105. network = N.NetworkName(network)
  106. switch network {
  107. case N.NetworkTCP:
  108. h.logger.InfoContext(ctx, "outbound connection to ", destination)
  109. case N.NetworkUDP:
  110. h.logger.InfoContext(ctx, "outbound packet connection to ", destination)
  111. }
  112. var domainStrategy dns.DomainStrategy
  113. if h.domainStrategy != dns.DomainStrategyAsIS {
  114. domainStrategy = h.domainStrategy
  115. } else {
  116. domainStrategy = dns.DomainStrategy(metadata.InboundOptions.DomainStrategy)
  117. }
  118. return N.DialParallel(ctx, h.dialer, network, destination, destinationAddresses, domainStrategy == dns.DomainStrategyPreferIPv6, h.fallbackDelay)
  119. }
  120. func (h *Direct) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
  121. ctx, metadata := adapter.ExtendContext(ctx)
  122. metadata.Outbound = h.tag
  123. metadata.Destination = destination
  124. originDestination := destination
  125. switch h.overrideOption {
  126. case 1:
  127. destination = h.overrideDestination
  128. case 2:
  129. newDestination := h.overrideDestination
  130. newDestination.Port = destination.Port
  131. destination = newDestination
  132. case 3:
  133. destination.Port = h.overrideDestination.Port
  134. }
  135. if h.overrideOption == 0 {
  136. h.logger.InfoContext(ctx, "outbound packet connection")
  137. } else {
  138. h.logger.InfoContext(ctx, "outbound packet connection to ", destination)
  139. }
  140. conn, err := h.dialer.ListenPacket(ctx, destination)
  141. if err != nil {
  142. return nil, err
  143. }
  144. // conn = h.loopBack.NewPacketConn(bufio.NewPacketConn(conn), destination)
  145. if originDestination != destination {
  146. conn = bufio.NewNATPacketConn(bufio.NewPacketConn(conn), destination, originDestination)
  147. }
  148. return conn, nil
  149. }
  150. /*func (h *Direct) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
  151. if h.loopBack.CheckConn(metadata.Source.AddrPort(), M.AddrPortFromNet(conn.LocalAddr())) {
  152. return E.New("reject loopback connection to ", metadata.Destination)
  153. }
  154. return NewConnection(ctx, h, conn, metadata)
  155. }
  156. func (h *Direct) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
  157. if h.loopBack.CheckPacketConn(metadata.Source.AddrPort(), M.AddrPortFromNet(conn.LocalAddr())) {
  158. return E.New("reject loopback packet connection to ", metadata.Destination)
  159. }
  160. return NewPacketConnection(ctx, h, conn, metadata)
  161. }
  162. */