github.com/sagernet/sing-box@v1.2.7/inbound/http.go (about) 1 package inbound 2 3 import ( 4 std_bufio "bufio" 5 "context" 6 "net" 7 "os" 8 9 "github.com/sagernet/sing-box/adapter" 10 "github.com/sagernet/sing-box/common/tls" 11 C "github.com/sagernet/sing-box/constant" 12 "github.com/sagernet/sing-box/log" 13 "github.com/sagernet/sing-box/option" 14 "github.com/sagernet/sing/common" 15 "github.com/sagernet/sing/common/auth" 16 E "github.com/sagernet/sing/common/exceptions" 17 N "github.com/sagernet/sing/common/network" 18 "github.com/sagernet/sing/protocol/http" 19 ) 20 21 var ( 22 _ adapter.Inbound = (*HTTP)(nil) 23 _ adapter.InjectableInbound = (*HTTP)(nil) 24 ) 25 26 type HTTP struct { 27 myInboundAdapter 28 authenticator auth.Authenticator 29 tlsConfig tls.ServerConfig 30 } 31 32 func NewHTTP(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.HTTPMixedInboundOptions) (*HTTP, error) { 33 inbound := &HTTP{ 34 myInboundAdapter: myInboundAdapter{ 35 protocol: C.TypeHTTP, 36 network: []string{N.NetworkTCP}, 37 ctx: ctx, 38 router: router, 39 logger: logger, 40 tag: tag, 41 listenOptions: options.ListenOptions, 42 setSystemProxy: options.SetSystemProxy, 43 }, 44 authenticator: auth.NewAuthenticator(options.Users), 45 } 46 if options.TLS != nil { 47 tlsConfig, err := tls.NewServer(ctx, router, logger, common.PtrValueOrDefault(options.TLS)) 48 if err != nil { 49 return nil, err 50 } 51 inbound.tlsConfig = tlsConfig 52 } 53 inbound.connHandler = inbound 54 return inbound, nil 55 } 56 57 func (h *HTTP) Start() error { 58 if h.tlsConfig != nil { 59 err := h.tlsConfig.Start() 60 if err != nil { 61 return E.Cause(err, "create TLS config") 62 } 63 } 64 return h.myInboundAdapter.Start() 65 } 66 67 func (h *HTTP) Close() error { 68 return common.Close( 69 &h.myInboundAdapter, 70 h.tlsConfig, 71 ) 72 } 73 74 func (h *HTTP) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { 75 var err error 76 if h.tlsConfig != nil { 77 conn, err = tls.ServerHandshake(ctx, conn, h.tlsConfig) 78 if err != nil { 79 return err 80 } 81 } 82 return http.HandleConnection(ctx, conn, std_bufio.NewReader(conn), h.authenticator, h.upstreamUserHandler(metadata), adapter.UpstreamMetadata(metadata)) 83 } 84 85 func (h *HTTP) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { 86 return os.ErrInvalid 87 } 88 89 func (a *myInboundAdapter) upstreamUserHandler(metadata adapter.InboundContext) adapter.UpstreamHandlerAdapter { 90 return adapter.NewUpstreamHandler(metadata, a.newUserConnection, a.streamUserPacketConnection, a) 91 } 92 93 func (a *myInboundAdapter) newUserConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { 94 user, loaded := auth.UserFromContext[string](ctx) 95 if !loaded { 96 a.logger.InfoContext(ctx, "inbound connection to ", metadata.Destination) 97 return a.router.RouteConnection(ctx, conn, metadata) 98 } 99 metadata.User = user 100 a.logger.InfoContext(ctx, "[", user, "] inbound connection to ", metadata.Destination) 101 return a.router.RouteConnection(ctx, conn, metadata) 102 } 103 104 func (a *myInboundAdapter) streamUserPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { 105 user, loaded := auth.UserFromContext[string](ctx) 106 if !loaded { 107 a.logger.InfoContext(ctx, "inbound packet connection to ", metadata.Destination) 108 return a.router.RoutePacketConnection(ctx, conn, metadata) 109 } 110 metadata.User = user 111 a.logger.InfoContext(ctx, "[", user, "] inbound packet connection to ", metadata.Destination) 112 return a.router.RoutePacketConnection(ctx, conn, metadata) 113 }