direct.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  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. }
  93. func (h *Direct) DialParallel(ctx context.Context, network string, destination M.Socksaddr, destinationAddresses []netip.Addr) (net.Conn, error) {
  94. ctx, metadata := adapter.ExtendContext(ctx)
  95. metadata.Outbound = h.tag
  96. metadata.Destination = destination
  97. switch h.overrideOption {
  98. case 1, 2:
  99. // override address
  100. return h.DialContext(ctx, network, destination)
  101. case 3:
  102. destination.Port = h.overrideDestination.Port
  103. }
  104. network = N.NetworkName(network)
  105. switch network {
  106. case N.NetworkTCP:
  107. h.logger.InfoContext(ctx, "outbound connection to ", destination)
  108. case N.NetworkUDP:
  109. h.logger.InfoContext(ctx, "outbound packet connection to ", destination)
  110. }
  111. var domainStrategy dns.DomainStrategy
  112. if h.domainStrategy != dns.DomainStrategyAsIS {
  113. domainStrategy = h.domainStrategy
  114. } else {
  115. domainStrategy = dns.DomainStrategy(metadata.InboundOptions.DomainStrategy)
  116. }
  117. return N.DialParallel(ctx, h.dialer, network, destination, destinationAddresses, domainStrategy == dns.DomainStrategyPreferIPv6, h.fallbackDelay)
  118. }
  119. func (h *Direct) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
  120. ctx, metadata := adapter.ExtendContext(ctx)
  121. metadata.Outbound = h.tag
  122. metadata.Destination = destination
  123. originDestination := destination
  124. switch h.overrideOption {
  125. case 1:
  126. destination = h.overrideDestination
  127. case 2:
  128. newDestination := h.overrideDestination
  129. newDestination.Port = destination.Port
  130. destination = newDestination
  131. case 3:
  132. destination.Port = h.overrideDestination.Port
  133. }
  134. if h.overrideOption == 0 {
  135. h.logger.InfoContext(ctx, "outbound packet connection")
  136. } else {
  137. h.logger.InfoContext(ctx, "outbound packet connection to ", destination)
  138. }
  139. conn, err := h.dialer.ListenPacket(ctx, destination)
  140. if err != nil {
  141. return nil, err
  142. }
  143. conn = h.loopBack.NewPacketConn(bufio.NewPacketConn(conn), destination)
  144. if originDestination != destination {
  145. conn = bufio.NewNATPacketConn(bufio.NewPacketConn(conn), destination, originDestination)
  146. }
  147. return conn, nil
  148. }
  149. func (h *Direct) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
  150. if h.loopBack.CheckConn(metadata.Source.AddrPort(), M.AddrPortFromNet(conn.LocalAddr())) {
  151. return E.New("reject loopback connection to ", metadata.Destination)
  152. }
  153. return NewConnection(ctx, h, conn, metadata)
  154. }
  155. func (h *Direct) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
  156. if h.loopBack.CheckPacketConn(metadata.Source.AddrPort(), M.AddrPortFromNet(conn.LocalAddr())) {
  157. return E.New("reject loopback packet connection to ", metadata.Destination)
  158. }
  159. return NewPacketConnection(ctx, h, conn, metadata)
  160. }