direct.go 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  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/buf"
  14. "github.com/sagernet/sing/common/bufio"
  15. E "github.com/sagernet/sing/common/exceptions"
  16. M "github.com/sagernet/sing/common/metadata"
  17. N "github.com/sagernet/sing/common/network"
  18. "github.com/pires/go-proxyproto"
  19. )
  20. var (
  21. _ adapter.Outbound = (*Direct)(nil)
  22. _ N.ParallelDialer = (*Direct)(nil)
  23. )
  24. type Direct struct {
  25. myOutboundAdapter
  26. dialer N.Dialer
  27. domainStrategy dns.DomainStrategy
  28. fallbackDelay time.Duration
  29. overrideOption int
  30. overrideDestination M.Socksaddr
  31. proxyProto uint8
  32. }
  33. func NewDirect(router adapter.Router, logger log.ContextLogger, tag string, options option.DirectOutboundOptions) (*Direct, error) {
  34. options.UDPFragmentDefault = true
  35. outboundDialer, err := dialer.New(router, options.DialerOptions)
  36. if err != nil {
  37. return nil, err
  38. }
  39. outbound := &Direct{
  40. myOutboundAdapter: myOutboundAdapter{
  41. protocol: C.TypeDirect,
  42. network: []string{N.NetworkTCP, N.NetworkUDP},
  43. router: router,
  44. logger: logger,
  45. tag: tag,
  46. dependencies: withDialerDependency(options.DialerOptions),
  47. },
  48. domainStrategy: dns.DomainStrategy(options.DomainStrategy),
  49. fallbackDelay: time.Duration(options.FallbackDelay),
  50. dialer: outboundDialer,
  51. proxyProto: options.ProxyProtocol,
  52. }
  53. if options.ProxyProtocol > 2 {
  54. return nil, E.New("invalid proxy protocol option: ", options.ProxyProtocol)
  55. }
  56. if options.OverrideAddress != "" && options.OverridePort != 0 {
  57. outbound.overrideOption = 1
  58. outbound.overrideDestination = M.ParseSocksaddrHostPort(options.OverrideAddress, options.OverridePort)
  59. } else if options.OverrideAddress != "" {
  60. outbound.overrideOption = 2
  61. outbound.overrideDestination = M.ParseSocksaddrHostPort(options.OverrideAddress, options.OverridePort)
  62. } else if options.OverridePort != 0 {
  63. outbound.overrideOption = 3
  64. outbound.overrideDestination = M.Socksaddr{Port: options.OverridePort}
  65. }
  66. return outbound, nil
  67. }
  68. func (h *Direct) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
  69. ctx, metadata := adapter.AppendContext(ctx)
  70. originDestination := metadata.Destination
  71. metadata.Outbound = h.tag
  72. metadata.Destination = destination
  73. switch h.overrideOption {
  74. case 1:
  75. destination = h.overrideDestination
  76. case 2:
  77. newDestination := h.overrideDestination
  78. newDestination.Port = destination.Port
  79. destination = newDestination
  80. case 3:
  81. destination.Port = h.overrideDestination.Port
  82. }
  83. network = N.NetworkName(network)
  84. switch network {
  85. case N.NetworkTCP:
  86. h.logger.InfoContext(ctx, "outbound connection to ", destination)
  87. case N.NetworkUDP:
  88. h.logger.InfoContext(ctx, "outbound packet connection to ", destination)
  89. }
  90. conn, err := h.dialer.DialContext(ctx, network, destination)
  91. if err != nil {
  92. return nil, err
  93. }
  94. if h.proxyProto > 0 {
  95. source := metadata.Source
  96. if !source.IsValid() {
  97. source = M.SocksaddrFromNet(conn.LocalAddr())
  98. }
  99. if originDestination.Addr.Is6() {
  100. source = M.SocksaddrFrom(netip.AddrFrom16(source.Addr.As16()), source.Port)
  101. }
  102. header := proxyproto.HeaderProxyFromAddrs(h.proxyProto, source.TCPAddr(), originDestination.TCPAddr())
  103. _, err = header.WriteTo(conn)
  104. if err != nil {
  105. conn.Close()
  106. return nil, E.Cause(err, "write proxy protocol header")
  107. }
  108. }
  109. return conn, nil
  110. }
  111. func (h *Direct) DialParallel(ctx context.Context, network string, destination M.Socksaddr, destinationAddresses []netip.Addr) (net.Conn, error) {
  112. ctx, metadata := adapter.AppendContext(ctx)
  113. originDestination := metadata.Destination
  114. metadata.Outbound = h.tag
  115. metadata.Destination = destination
  116. switch h.overrideOption {
  117. case 1, 2:
  118. // override address
  119. return h.DialContext(ctx, network, destination)
  120. case 3:
  121. destination.Port = h.overrideDestination.Port
  122. }
  123. network = N.NetworkName(network)
  124. switch network {
  125. case N.NetworkTCP:
  126. h.logger.InfoContext(ctx, "outbound connection to ", destination)
  127. case N.NetworkUDP:
  128. h.logger.InfoContext(ctx, "outbound packet connection to ", destination)
  129. }
  130. var domainStrategy dns.DomainStrategy
  131. if h.domainStrategy != dns.DomainStrategyAsIS {
  132. domainStrategy = h.domainStrategy
  133. } else {
  134. domainStrategy = dns.DomainStrategy(metadata.InboundOptions.DomainStrategy)
  135. }
  136. conn, err := N.DialParallel(ctx, h.dialer, network, destination, destinationAddresses, domainStrategy == dns.DomainStrategyPreferIPv6, h.fallbackDelay)
  137. if err != nil {
  138. return nil, err
  139. }
  140. if h.proxyProto > 0 {
  141. source := metadata.Source
  142. if !source.IsValid() {
  143. source = M.SocksaddrFromNet(conn.LocalAddr())
  144. }
  145. if originDestination.Addr.Is6() {
  146. source = M.SocksaddrFrom(netip.AddrFrom16(source.Addr.As16()), source.Port)
  147. }
  148. header := proxyproto.HeaderProxyFromAddrs(h.proxyProto, source.TCPAddr(), originDestination.TCPAddr())
  149. _, err = header.WriteTo(conn)
  150. if err != nil {
  151. conn.Close()
  152. return nil, E.Cause(err, "write proxy protocol header")
  153. }
  154. }
  155. return conn, nil
  156. }
  157. func (h *Direct) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
  158. ctx, metadata := adapter.ExtendContext(ctx)
  159. metadata.Outbound = h.tag
  160. metadata.Destination = destination
  161. switch h.overrideOption {
  162. case 1:
  163. destination = h.overrideDestination
  164. case 2:
  165. newDestination := h.overrideDestination
  166. newDestination.Port = destination.Port
  167. destination = newDestination
  168. case 3:
  169. destination.Port = h.overrideDestination.Port
  170. }
  171. if h.overrideOption == 0 {
  172. h.logger.InfoContext(ctx, "outbound packet connection")
  173. } else {
  174. h.logger.InfoContext(ctx, "outbound packet connection to ", destination)
  175. }
  176. conn, err := h.dialer.ListenPacket(ctx, destination)
  177. if err != nil {
  178. return nil, err
  179. }
  180. if h.overrideOption == 0 {
  181. return conn, nil
  182. } else {
  183. return &overridePacketConn{bufio.NewPacketConn(conn), destination}, nil
  184. }
  185. }
  186. func (h *Direct) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
  187. return NewConnection(ctx, h, conn, metadata)
  188. }
  189. func (h *Direct) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
  190. return NewPacketConnection(ctx, h, conn, metadata)
  191. }
  192. type overridePacketConn struct {
  193. N.NetPacketConn
  194. overrideDestination M.Socksaddr
  195. }
  196. func (c *overridePacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error {
  197. return c.NetPacketConn.WritePacket(buffer, c.overrideDestination)
  198. }
  199. func (c *overridePacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
  200. return c.NetPacketConn.WriteTo(p, c.overrideDestination.UDPAddr())
  201. }
  202. func (c *overridePacketConn) Upstream() any {
  203. return c.NetPacketConn
  204. }