direct.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  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. E "github.com/sagernet/sing/common/exceptions"
  14. M "github.com/sagernet/sing/common/metadata"
  15. N "github.com/sagernet/sing/common/network"
  16. "github.com/pires/go-proxyproto"
  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. proxyProto uint8
  30. }
  31. func NewDirect(router adapter.Router, logger log.ContextLogger, tag string, options option.DirectOutboundOptions) (*Direct, error) {
  32. options.UDPFragmentDefault = true
  33. outbound := &Direct{
  34. myOutboundAdapter: myOutboundAdapter{
  35. protocol: C.TypeDirect,
  36. network: []string{N.NetworkTCP, N.NetworkUDP},
  37. router: router,
  38. logger: logger,
  39. tag: tag,
  40. },
  41. domainStrategy: dns.DomainStrategy(options.DomainStrategy),
  42. fallbackDelay: time.Duration(options.FallbackDelay),
  43. dialer: dialer.New(router, options.DialerOptions),
  44. proxyProto: options.ProxyProtocol,
  45. }
  46. if options.ProxyProtocol > 2 {
  47. return nil, E.New("invalid proxy protocol option: ", options.ProxyProtocol)
  48. }
  49. if options.OverrideAddress != "" && options.OverridePort != 0 {
  50. outbound.overrideOption = 1
  51. outbound.overrideDestination = M.ParseSocksaddrHostPort(options.OverrideAddress, options.OverridePort)
  52. } else if options.OverrideAddress != "" {
  53. outbound.overrideOption = 2
  54. outbound.overrideDestination = M.ParseSocksaddrHostPort(options.OverrideAddress, options.OverridePort)
  55. } else if options.OverridePort != 0 {
  56. outbound.overrideOption = 3
  57. outbound.overrideDestination = M.Socksaddr{Port: options.OverridePort}
  58. }
  59. return outbound, nil
  60. }
  61. func (h *Direct) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
  62. ctx, metadata := adapter.AppendContext(ctx)
  63. originDestination := metadata.Destination
  64. metadata.Outbound = h.tag
  65. metadata.Destination = destination
  66. switch h.overrideOption {
  67. case 1:
  68. destination = h.overrideDestination
  69. case 2:
  70. newDestination := h.overrideDestination
  71. newDestination.Port = destination.Port
  72. destination = newDestination
  73. case 3:
  74. destination.Port = h.overrideDestination.Port
  75. }
  76. network = N.NetworkName(network)
  77. switch network {
  78. case N.NetworkTCP:
  79. h.logger.InfoContext(ctx, "outbound connection to ", destination)
  80. case N.NetworkUDP:
  81. h.logger.InfoContext(ctx, "outbound packet connection to ", destination)
  82. }
  83. conn, err := h.dialer.DialContext(ctx, network, destination)
  84. if err != nil {
  85. return nil, err
  86. }
  87. if h.proxyProto > 0 {
  88. source := metadata.Source
  89. if !source.IsValid() {
  90. source = M.SocksaddrFromNet(conn.LocalAddr())
  91. }
  92. if originDestination.Addr.Is6() {
  93. source = M.SocksaddrFrom(netip.AddrFrom16(source.Addr.As16()), source.Port)
  94. }
  95. header := proxyproto.HeaderProxyFromAddrs(h.proxyProto, source.TCPAddr(), originDestination.TCPAddr())
  96. _, err = header.WriteTo(conn)
  97. if err != nil {
  98. conn.Close()
  99. return nil, E.Cause(err, "write proxy protocol header")
  100. }
  101. }
  102. return conn, nil
  103. }
  104. func (h *Direct) DialParallel(ctx context.Context, network string, destination M.Socksaddr, destinationAddresses []netip.Addr) (net.Conn, error) {
  105. ctx, metadata := adapter.AppendContext(ctx)
  106. originDestination := metadata.Destination
  107. metadata.Outbound = h.tag
  108. metadata.Destination = destination
  109. switch h.overrideOption {
  110. case 1, 2:
  111. // override address
  112. return h.DialContext(ctx, network, destination)
  113. case 3:
  114. destination.Port = h.overrideDestination.Port
  115. }
  116. network = N.NetworkName(network)
  117. switch network {
  118. case N.NetworkTCP:
  119. h.logger.InfoContext(ctx, "outbound connection to ", destination)
  120. case N.NetworkUDP:
  121. h.logger.InfoContext(ctx, "outbound packet connection to ", destination)
  122. }
  123. var domainStrategy dns.DomainStrategy
  124. if h.domainStrategy != dns.DomainStrategyAsIS {
  125. domainStrategy = h.domainStrategy
  126. } else {
  127. domainStrategy = dns.DomainStrategy(metadata.InboundOptions.DomainStrategy)
  128. }
  129. conn, err := N.DialParallel(ctx, h.dialer, network, destination, destinationAddresses, domainStrategy == dns.DomainStrategyPreferIPv6, h.fallbackDelay)
  130. if err != nil {
  131. return nil, err
  132. }
  133. if h.proxyProto > 0 {
  134. source := metadata.Source
  135. if !source.IsValid() {
  136. source = M.SocksaddrFromNet(conn.LocalAddr())
  137. }
  138. if originDestination.Addr.Is6() {
  139. source = M.SocksaddrFrom(netip.AddrFrom16(source.Addr.As16()), source.Port)
  140. }
  141. header := proxyproto.HeaderProxyFromAddrs(h.proxyProto, source.TCPAddr(), originDestination.TCPAddr())
  142. _, err = header.WriteTo(conn)
  143. if err != nil {
  144. conn.Close()
  145. return nil, E.Cause(err, "write proxy protocol header")
  146. }
  147. }
  148. return conn, nil
  149. }
  150. func (h *Direct) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
  151. ctx, metadata := adapter.AppendContext(ctx)
  152. metadata.Outbound = h.tag
  153. metadata.Destination = destination
  154. h.logger.InfoContext(ctx, "outbound packet connection")
  155. return h.dialer.ListenPacket(ctx, destination)
  156. }
  157. func (h *Direct) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
  158. return NewConnection(ctx, h, conn, metadata)
  159. }
  160. func (h *Direct) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
  161. return NewPacketConnection(ctx, h, conn, metadata)
  162. }