outbound.go 5.9 KB

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