shadowsocks.go 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. package outbound
  2. import (
  3. "context"
  4. "net"
  5. "github.com/sagernet/sing-box/adapter"
  6. "github.com/sagernet/sing-box/common/dialer"
  7. "github.com/sagernet/sing-box/common/mux"
  8. C "github.com/sagernet/sing-box/constant"
  9. "github.com/sagernet/sing-box/log"
  10. "github.com/sagernet/sing-box/option"
  11. "github.com/sagernet/sing-box/transport/sip003"
  12. "github.com/sagernet/sing-shadowsocks"
  13. "github.com/sagernet/sing-shadowsocks/shadowimpl"
  14. "github.com/sagernet/sing/common"
  15. "github.com/sagernet/sing/common/bufio"
  16. E "github.com/sagernet/sing/common/exceptions"
  17. M "github.com/sagernet/sing/common/metadata"
  18. N "github.com/sagernet/sing/common/network"
  19. "github.com/sagernet/sing/common/uot"
  20. )
  21. var _ adapter.Outbound = (*Shadowsocks)(nil)
  22. type Shadowsocks struct {
  23. myOutboundAdapter
  24. dialer N.Dialer
  25. method shadowsocks.Method
  26. serverAddr M.Socksaddr
  27. plugin sip003.Plugin
  28. uot bool
  29. uotVersion int
  30. multiplexDialer N.Dialer
  31. }
  32. func NewShadowsocks(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.ShadowsocksOutboundOptions) (*Shadowsocks, error) {
  33. method, err := shadowimpl.FetchMethod(options.Method, options.Password, router.TimeFunc())
  34. if err != nil {
  35. return nil, err
  36. }
  37. outbound := &Shadowsocks{
  38. myOutboundAdapter: myOutboundAdapter{
  39. protocol: C.TypeShadowsocks,
  40. network: options.Network.Build(),
  41. router: router,
  42. logger: logger,
  43. tag: tag,
  44. },
  45. dialer: dialer.New(router, options.DialerOptions),
  46. method: method,
  47. serverAddr: options.ServerOptions.Build(),
  48. uot: options.UoT,
  49. }
  50. if options.Plugin != "" {
  51. outbound.plugin, err = sip003.CreatePlugin(options.Plugin, options.PluginOptions, router, outbound.dialer, outbound.serverAddr)
  52. if err != nil {
  53. return nil, err
  54. }
  55. }
  56. if !options.UoT {
  57. outbound.multiplexDialer, err = mux.NewClientWithOptions(ctx, (*shadowsocksDialer)(outbound), common.PtrValueOrDefault(options.MultiplexOptions))
  58. if err != nil {
  59. return nil, err
  60. }
  61. }
  62. switch options.UoTVersion {
  63. case uot.LegacyVersion:
  64. outbound.uotVersion = uot.LegacyVersion
  65. case 0, uot.Version:
  66. outbound.uotVersion = uot.Version
  67. default:
  68. return nil, E.New("unknown udp over tcp protocol version ", options.UoTVersion)
  69. }
  70. return outbound, nil
  71. }
  72. func (h *Shadowsocks) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
  73. ctx, metadata := adapter.AppendContext(ctx)
  74. metadata.Outbound = h.tag
  75. metadata.Destination = destination
  76. if h.multiplexDialer == nil {
  77. switch N.NetworkName(network) {
  78. case N.NetworkTCP:
  79. h.logger.InfoContext(ctx, "outbound connection to ", destination)
  80. case N.NetworkUDP:
  81. if h.uot {
  82. h.logger.InfoContext(ctx, "outbound UoT packet connection to ", destination)
  83. var uotDestination M.Socksaddr
  84. if h.uotVersion == uot.Version {
  85. uotDestination.Fqdn = uot.MagicAddress
  86. } else {
  87. uotDestination.Fqdn = uot.LegacyMagicAddress
  88. }
  89. tcpConn, err := (*shadowsocksDialer)(h).DialContext(ctx, N.NetworkTCP, uotDestination)
  90. if err != nil {
  91. return nil, err
  92. }
  93. if h.uotVersion == uot.Version {
  94. return uot.NewLazyConn(tcpConn, uot.Request{IsConnect: true, Destination: destination}), nil
  95. } else {
  96. return uot.NewConn(tcpConn, false, destination), nil
  97. }
  98. }
  99. h.logger.InfoContext(ctx, "outbound packet connection to ", destination)
  100. }
  101. return (*shadowsocksDialer)(h).DialContext(ctx, network, destination)
  102. } else {
  103. switch N.NetworkName(network) {
  104. case N.NetworkTCP:
  105. h.logger.InfoContext(ctx, "outbound multiplex connection to ", destination)
  106. case N.NetworkUDP:
  107. h.logger.InfoContext(ctx, "outbound multiplex packet connection to ", destination)
  108. }
  109. return h.multiplexDialer.DialContext(ctx, network, destination)
  110. }
  111. }
  112. func (h *Shadowsocks) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
  113. ctx, metadata := adapter.AppendContext(ctx)
  114. metadata.Outbound = h.tag
  115. metadata.Destination = destination
  116. if h.multiplexDialer == nil {
  117. if h.uot {
  118. h.logger.InfoContext(ctx, "outbound UoT packet connection to ", destination)
  119. var uotDestination M.Socksaddr
  120. if h.uotVersion == uot.Version {
  121. uotDestination.Fqdn = uot.MagicAddress
  122. } else {
  123. uotDestination.Fqdn = uot.LegacyMagicAddress
  124. }
  125. tcpConn, err := (*shadowsocksDialer)(h).DialContext(ctx, N.NetworkTCP, uotDestination)
  126. if err != nil {
  127. return nil, err
  128. }
  129. if h.uotVersion == uot.Version {
  130. return uot.NewLazyConn(tcpConn, uot.Request{Destination: destination}), nil
  131. } else {
  132. return uot.NewConn(tcpConn, false, destination), nil
  133. }
  134. }
  135. h.logger.InfoContext(ctx, "outbound packet connection to ", destination)
  136. return (*shadowsocksDialer)(h).ListenPacket(ctx, destination)
  137. } else {
  138. h.logger.InfoContext(ctx, "outbound multiplex packet connection to ", destination)
  139. return h.multiplexDialer.ListenPacket(ctx, destination)
  140. }
  141. }
  142. func (h *Shadowsocks) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
  143. return NewConnection(ctx, h, conn, metadata)
  144. }
  145. func (h *Shadowsocks) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
  146. return NewPacketConnection(ctx, h, conn, metadata)
  147. }
  148. func (h *Shadowsocks) Close() error {
  149. return common.Close(h.multiplexDialer)
  150. }
  151. var _ N.Dialer = (*shadowsocksDialer)(nil)
  152. type shadowsocksDialer Shadowsocks
  153. func (h *shadowsocksDialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
  154. switch N.NetworkName(network) {
  155. case N.NetworkTCP:
  156. var outConn net.Conn
  157. var err error
  158. if h.plugin != nil {
  159. outConn, err = h.plugin.DialContext(ctx)
  160. } else {
  161. outConn, err = h.dialer.DialContext(ctx, N.NetworkTCP, h.serverAddr)
  162. }
  163. if err != nil {
  164. return nil, err
  165. }
  166. return h.method.DialEarlyConn(outConn, destination), nil
  167. case N.NetworkUDP:
  168. outConn, err := h.dialer.DialContext(ctx, N.NetworkUDP, h.serverAddr)
  169. if err != nil {
  170. return nil, err
  171. }
  172. return &bufio.BindPacketConn{PacketConn: h.method.DialPacketConn(outConn), Addr: destination}, nil
  173. default:
  174. return nil, E.Extend(N.ErrUnknownNetwork, network)
  175. }
  176. }
  177. func (h *shadowsocksDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
  178. outConn, err := h.dialer.DialContext(ctx, N.NetworkUDP, h.serverAddr)
  179. if err != nil {
  180. return nil, err
  181. }
  182. return h.method.DialPacketConn(outConn), nil
  183. }