direct.go 6.6 KB

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