inbound.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. package mixed
  2. import (
  3. std_bufio "bufio"
  4. "context"
  5. "net"
  6. "time"
  7. "github.com/sagernet/sing-box/adapter"
  8. "github.com/sagernet/sing-box/adapter/inbound"
  9. "github.com/sagernet/sing-box/common/listener"
  10. "github.com/sagernet/sing-box/common/tls"
  11. "github.com/sagernet/sing-box/common/uot"
  12. C "github.com/sagernet/sing-box/constant"
  13. "github.com/sagernet/sing-box/log"
  14. "github.com/sagernet/sing-box/option"
  15. "github.com/sagernet/sing/common"
  16. "github.com/sagernet/sing/common/auth"
  17. E "github.com/sagernet/sing/common/exceptions"
  18. N "github.com/sagernet/sing/common/network"
  19. "github.com/sagernet/sing/protocol/http"
  20. "github.com/sagernet/sing/protocol/socks"
  21. "github.com/sagernet/sing/protocol/socks/socks4"
  22. "github.com/sagernet/sing/protocol/socks/socks5"
  23. )
  24. func RegisterInbound(registry *inbound.Registry) {
  25. inbound.Register[option.HTTPMixedInboundOptions](registry, C.TypeMixed, NewInbound)
  26. }
  27. var _ adapter.TCPInjectableInbound = (*Inbound)(nil)
  28. type Inbound struct {
  29. inbound.Adapter
  30. router adapter.ConnectionRouterEx
  31. logger log.ContextLogger
  32. listener *listener.Listener
  33. authenticator *auth.Authenticator
  34. tlsConfig tls.ServerConfig
  35. udpTimeout time.Duration
  36. }
  37. func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.HTTPMixedInboundOptions) (adapter.Inbound, error) {
  38. var udpTimeout time.Duration
  39. if options.UDPTimeout != 0 {
  40. udpTimeout = time.Duration(options.UDPTimeout)
  41. } else {
  42. udpTimeout = C.UDPTimeout
  43. }
  44. inbound := &Inbound{
  45. Adapter: inbound.NewAdapter(C.TypeMixed, tag),
  46. router: uot.NewRouter(router, logger),
  47. logger: logger,
  48. authenticator: auth.NewAuthenticator(options.Users),
  49. udpTimeout: udpTimeout,
  50. }
  51. if options.TLS != nil {
  52. tlsConfig, err := tls.NewServerWithOptions(tls.ServerOptions{
  53. Context: ctx,
  54. Logger: logger,
  55. Options: common.PtrValueOrDefault(options.TLS),
  56. KTLSCompatible: true,
  57. })
  58. if err != nil {
  59. return nil, err
  60. }
  61. inbound.tlsConfig = tlsConfig
  62. }
  63. inbound.listener = listener.New(listener.Options{
  64. Context: ctx,
  65. Logger: logger,
  66. Network: []string{N.NetworkTCP},
  67. Listen: options.ListenOptions,
  68. ConnectionHandler: inbound,
  69. SetSystemProxy: options.SetSystemProxy,
  70. SystemProxySOCKS: true,
  71. })
  72. return inbound, nil
  73. }
  74. func (h *Inbound) Start(stage adapter.StartStage) error {
  75. if stage != adapter.StartStateStart {
  76. return nil
  77. }
  78. if h.tlsConfig != nil {
  79. err := h.tlsConfig.Start()
  80. if err != nil {
  81. return E.Cause(err, "create TLS config")
  82. }
  83. }
  84. return h.listener.Start()
  85. }
  86. func (h *Inbound) Close() error {
  87. return common.Close(
  88. h.listener,
  89. h.tlsConfig,
  90. )
  91. }
  92. func (h *Inbound) NewConnectionEx(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) {
  93. err := h.newConnection(ctx, conn, metadata, onClose)
  94. N.CloseOnHandshakeFailure(conn, onClose, err)
  95. if err != nil {
  96. if E.IsClosedOrCanceled(err) {
  97. h.logger.DebugContext(ctx, "connection closed: ", err)
  98. } else {
  99. h.logger.ErrorContext(ctx, E.Cause(err, "process connection from ", metadata.Source))
  100. }
  101. }
  102. }
  103. func (h *Inbound) newConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) error {
  104. if h.tlsConfig != nil {
  105. tlsConn, err := tls.ServerHandshake(ctx, conn, h.tlsConfig)
  106. if err != nil {
  107. return E.Cause(err, "TLS handshake")
  108. }
  109. conn = tlsConn
  110. }
  111. reader := std_bufio.NewReader(conn)
  112. headerBytes, err := reader.Peek(1)
  113. if err != nil {
  114. return E.Cause(err, "peek first byte")
  115. }
  116. switch headerBytes[0] {
  117. case socks4.Version, socks5.Version:
  118. return socks.HandleConnectionEx(ctx, conn, reader, h.authenticator, adapter.NewUpstreamHandlerEx(metadata, h.newUserConnection, h.streamUserPacketConnection), h.listener, h.udpTimeout, metadata.Source, onClose)
  119. default:
  120. return http.HandleConnectionEx(ctx, conn, reader, h.authenticator, adapter.NewUpstreamHandlerEx(metadata, h.newUserConnection, h.streamUserPacketConnection), metadata.Source, onClose)
  121. }
  122. }
  123. func (h *Inbound) newUserConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) {
  124. metadata.Inbound = h.Tag()
  125. metadata.InboundType = h.Type()
  126. user, loaded := auth.UserFromContext[string](ctx)
  127. if !loaded {
  128. h.logger.InfoContext(ctx, "inbound connection to ", metadata.Destination)
  129. h.router.RouteConnectionEx(ctx, conn, metadata, onClose)
  130. return
  131. }
  132. metadata.User = user
  133. h.logger.InfoContext(ctx, "[", user, "] inbound connection to ", metadata.Destination)
  134. h.router.RouteConnectionEx(ctx, conn, metadata, onClose)
  135. }
  136. func (h *Inbound) streamUserPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) {
  137. metadata.Inbound = h.Tag()
  138. metadata.InboundType = h.Type()
  139. user, loaded := auth.UserFromContext[string](ctx)
  140. if !loaded {
  141. if !metadata.Destination.IsValid() {
  142. h.logger.InfoContext(ctx, "inbound packet connection")
  143. } else {
  144. h.logger.InfoContext(ctx, "inbound packet connection to ", metadata.Destination)
  145. }
  146. h.router.RoutePacketConnectionEx(ctx, conn, metadata, onClose)
  147. return
  148. }
  149. metadata.User = user
  150. if !metadata.Destination.IsValid() {
  151. h.logger.InfoContext(ctx, "[", user, "] inbound packet connection")
  152. } else {
  153. h.logger.InfoContext(ctx, "[", user, "] inbound packet connection to ", metadata.Destination)
  154. }
  155. h.router.RoutePacketConnectionEx(ctx, conn, metadata, onClose)
  156. }