github.com/inazumav/sing-box@v0.0.0-20230926072359-ab51429a14f1/inbound/hysteria2.go (about) 1 //go:build with_quic 2 3 package inbound 4 5 import ( 6 "context" 7 "net" 8 "net/http" 9 "net/http/httputil" 10 "net/url" 11 12 "github.com/inazumav/sing-box/adapter" 13 "github.com/inazumav/sing-box/common/tls" 14 C "github.com/inazumav/sing-box/constant" 15 "github.com/inazumav/sing-box/log" 16 "github.com/inazumav/sing-box/option" 17 "github.com/inazumav/sing-box/transport/hysteria2" 18 "github.com/sagernet/sing/common" 19 "github.com/sagernet/sing/common/auth" 20 E "github.com/sagernet/sing/common/exceptions" 21 N "github.com/sagernet/sing/common/network" 22 ) 23 24 var _ adapter.Inbound = (*Hysteria2)(nil) 25 26 type Hysteria2 struct { 27 myInboundAdapter 28 tlsConfig tls.ServerConfig 29 server *hysteria2.Server 30 } 31 32 func NewHysteria2(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.Hysteria2InboundOptions) (*Hysteria2, error) { 33 if options.TLS == nil || !options.TLS.Enabled { 34 return nil, C.ErrTLSRequired 35 } 36 tlsConfig, err := tls.NewServer(ctx, logger, common.PtrValueOrDefault(options.TLS)) 37 if err != nil { 38 return nil, err 39 } 40 var salamanderPassword string 41 if options.Obfs != nil { 42 if options.Obfs.Password == "" { 43 return nil, E.New("missing obfs password") 44 } 45 switch options.Obfs.Type { 46 case hysteria2.ObfsTypeSalamander: 47 salamanderPassword = options.Obfs.Password 48 default: 49 return nil, E.New("unknown obfs type: ", options.Obfs.Type) 50 } 51 } 52 var masqueradeHandler http.Handler 53 if options.Masquerade != "" { 54 masqueradeURL, err := url.Parse(options.Masquerade) 55 if err != nil { 56 return nil, E.Cause(err, "parse masquerade URL") 57 } 58 switch masqueradeURL.Scheme { 59 case "file": 60 masqueradeHandler = http.FileServer(http.Dir(masqueradeURL.Path)) 61 case "http", "https": 62 masqueradeHandler = &httputil.ReverseProxy{ 63 Rewrite: func(r *httputil.ProxyRequest) { 64 r.SetURL(masqueradeURL) 65 r.Out.Host = r.In.Host 66 }, 67 ErrorHandler: func(w http.ResponseWriter, r *http.Request, err error) { 68 w.WriteHeader(http.StatusBadGateway) 69 }, 70 } 71 default: 72 return nil, E.New("unknown masquerade URL scheme: ", masqueradeURL.Scheme) 73 } 74 } 75 inbound := &Hysteria2{ 76 myInboundAdapter: myInboundAdapter{ 77 protocol: C.TypeHysteria2, 78 network: []string{N.NetworkUDP}, 79 ctx: ctx, 80 router: router, 81 logger: logger, 82 tag: tag, 83 listenOptions: options.ListenOptions, 84 }, 85 tlsConfig: tlsConfig, 86 } 87 server, err := hysteria2.NewServer(hysteria2.ServerOptions{ 88 Context: ctx, 89 Logger: logger, 90 SendBPS: uint64(options.UpMbps * 1024 * 1024), 91 ReceiveBPS: uint64(options.DownMbps * 1024 * 1024), 92 SalamanderPassword: salamanderPassword, 93 TLSConfig: tlsConfig, 94 Users: common.Map(options.Users, func(it option.Hysteria2User) hysteria2.User { 95 return hysteria2.User(it) 96 }), 97 IgnoreClientBandwidth: options.IgnoreClientBandwidth, 98 Handler: adapter.NewUpstreamHandler(adapter.InboundContext{}, inbound.newConnection, inbound.newPacketConnection, nil), 99 MasqueradeHandler: masqueradeHandler, 100 }) 101 if err != nil { 102 return nil, err 103 } 104 inbound.server = server 105 return inbound, nil 106 } 107 108 func (h *Hysteria2) newConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { 109 ctx = log.ContextWithNewID(ctx) 110 h.logger.InfoContext(ctx, "inbound connection to ", metadata.Destination) 111 metadata = h.createMetadata(conn, metadata) 112 metadata.User, _ = auth.UserFromContext[string](ctx) 113 return h.router.RouteConnection(ctx, conn, metadata) 114 } 115 116 func (h *Hysteria2) newPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { 117 ctx = log.ContextWithNewID(ctx) 118 metadata = h.createPacketMetadata(conn, metadata) 119 metadata.User, _ = auth.UserFromContext[string](ctx) 120 h.logger.InfoContext(ctx, "inbound packet connection to ", metadata.Destination) 121 return h.router.RoutePacketConnection(ctx, conn, metadata) 122 } 123 124 func (h *Hysteria2) Start() error { 125 if h.tlsConfig != nil { 126 err := h.tlsConfig.Start() 127 if err != nil { 128 return err 129 } 130 } 131 packetConn, err := h.myInboundAdapter.ListenUDP() 132 if err != nil { 133 return err 134 } 135 return h.server.Start(packetConn) 136 } 137 138 func (h *Hysteria2) Close() error { 139 return common.Close( 140 &h.myInboundAdapter, 141 h.tlsConfig, 142 common.PtrOrNil(h.server), 143 ) 144 }