mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-25 10:01:30 +00:00
Add multi user support for hysteria inbound
This commit is contained in:
parent
5510c474c7
commit
617aba84e4
|
@ -3,7 +3,6 @@
|
||||||
package inbound
|
package inbound
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"context"
|
"context"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
@ -16,9 +15,13 @@ import (
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
"github.com/sagernet/sing-box/transport/hysteria"
|
"github.com/sagernet/sing-box/transport/hysteria"
|
||||||
"github.com/sagernet/sing/common"
|
"github.com/sagernet/sing/common"
|
||||||
|
"github.com/sagernet/sing/common/auth"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
|
F "github.com/sagernet/sing/common/format"
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
|
||||||
|
"golang.org/x/exp/slices"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ adapter.Inbound = (*Hysteria)(nil)
|
var _ adapter.Inbound = (*Hysteria)(nil)
|
||||||
|
@ -27,7 +30,8 @@ type Hysteria struct {
|
||||||
myInboundAdapter
|
myInboundAdapter
|
||||||
quicConfig *quic.Config
|
quicConfig *quic.Config
|
||||||
tlsConfig tls.ServerConfig
|
tlsConfig tls.ServerConfig
|
||||||
authKey []byte
|
authKey []string
|
||||||
|
authUser []string
|
||||||
xplusKey []byte
|
xplusKey []byte
|
||||||
sendBPS uint64
|
sendBPS uint64
|
||||||
recvBPS uint64
|
recvBPS uint64
|
||||||
|
@ -60,12 +64,16 @@ func NewHysteria(ctx context.Context, router adapter.Router, logger log.ContextL
|
||||||
if quicConfig.MaxIncomingStreams == 0 {
|
if quicConfig.MaxIncomingStreams == 0 {
|
||||||
quicConfig.MaxIncomingStreams = hysteria.DefaultMaxIncomingStreams
|
quicConfig.MaxIncomingStreams = hysteria.DefaultMaxIncomingStreams
|
||||||
}
|
}
|
||||||
var auth []byte
|
authKey := common.Map(options.Users, func(it option.HysteriaUser) string {
|
||||||
if len(options.Auth) > 0 {
|
if len(it.Auth) > 0 {
|
||||||
auth = options.Auth
|
return string(it.Auth)
|
||||||
} else {
|
} else {
|
||||||
auth = []byte(options.AuthString)
|
return it.AuthString
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
authUser := common.Map(options.Users, func(it option.HysteriaUser) string {
|
||||||
|
return it.Name
|
||||||
|
})
|
||||||
var xplus []byte
|
var xplus []byte
|
||||||
if options.Obfs != "" {
|
if options.Obfs != "" {
|
||||||
xplus = []byte(options.Obfs)
|
xplus = []byte(options.Obfs)
|
||||||
|
@ -104,7 +112,8 @@ func NewHysteria(ctx context.Context, router adapter.Router, logger log.ContextL
|
||||||
listenOptions: options.ListenOptions,
|
listenOptions: options.ListenOptions,
|
||||||
},
|
},
|
||||||
quicConfig: quicConfig,
|
quicConfig: quicConfig,
|
||||||
authKey: auth,
|
authKey: authKey,
|
||||||
|
authUser: authUser,
|
||||||
xplusKey: xplus,
|
xplusKey: xplus,
|
||||||
sendBPS: up,
|
sendBPS: up,
|
||||||
recvBPS: down,
|
recvBPS: down,
|
||||||
|
@ -158,7 +167,6 @@ func (h *Hysteria) acceptLoop() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
h.logger.InfoContext(ctx, "inbound connection from ", conn.RemoteAddr())
|
|
||||||
go func() {
|
go func() {
|
||||||
hErr := h.accept(ctx, conn)
|
hErr := h.accept(ctx, conn)
|
||||||
if hErr != nil {
|
if hErr != nil {
|
||||||
|
@ -178,12 +186,21 @@ func (h *Hysteria) accept(ctx context.Context, conn quic.Connection) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if !bytes.Equal(clientHello.Auth, h.authKey) {
|
userIndex := slices.Index(h.authKey, string(clientHello.Auth))
|
||||||
|
if userIndex == -1 {
|
||||||
err = hysteria.WriteServerHello(controlStream, hysteria.ServerHello{
|
err = hysteria.WriteServerHello(controlStream, hysteria.ServerHello{
|
||||||
Message: "wrong password",
|
Message: "wrong password",
|
||||||
})
|
})
|
||||||
return E.Errors(E.New("wrong password: ", string(clientHello.Auth)), err)
|
return E.Errors(E.New("wrong password: ", string(clientHello.Auth)), err)
|
||||||
}
|
}
|
||||||
|
user := h.authUser[userIndex]
|
||||||
|
if user == "" {
|
||||||
|
user = F.ToString(userIndex)
|
||||||
|
} else {
|
||||||
|
ctx = auth.ContextWithUser(ctx, user)
|
||||||
|
}
|
||||||
|
h.logger.InfoContext(ctx, "[", user, "] inbound connection from ", conn.RemoteAddr())
|
||||||
|
h.logger.DebugContext(ctx, "peer send speed: ", clientHello.SendBPS/1024/1024, " MBps, peer recv speed: ", clientHello.RecvBPS/1024/1024, " MBps")
|
||||||
if clientHello.SendBPS == 0 || clientHello.RecvBPS == 0 {
|
if clientHello.SendBPS == 0 || clientHello.RecvBPS == 0 {
|
||||||
return E.New("invalid rate from client")
|
return E.New("invalid rate from client")
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,7 @@ type HysteriaInboundOptions struct {
|
||||||
Down string `json:"down,omitempty"`
|
Down string `json:"down,omitempty"`
|
||||||
DownMbps int `json:"down_mbps,omitempty"`
|
DownMbps int `json:"down_mbps,omitempty"`
|
||||||
Obfs string `json:"obfs,omitempty"`
|
Obfs string `json:"obfs,omitempty"`
|
||||||
Auth []byte `json:"auth,omitempty"`
|
Users []HysteriaUser `json:"users,omitempty"`
|
||||||
AuthString string `json:"auth_str,omitempty"`
|
|
||||||
ReceiveWindowConn uint64 `json:"recv_window_conn,omitempty"`
|
ReceiveWindowConn uint64 `json:"recv_window_conn,omitempty"`
|
||||||
ReceiveWindowClient uint64 `json:"recv_window_client,omitempty"`
|
ReceiveWindowClient uint64 `json:"recv_window_client,omitempty"`
|
||||||
MaxConnClient int `json:"max_conn_client,omitempty"`
|
MaxConnClient int `json:"max_conn_client,omitempty"`
|
||||||
|
@ -16,6 +15,12 @@ type HysteriaInboundOptions struct {
|
||||||
TLS *InboundTLSOptions `json:"tls,omitempty"`
|
TLS *InboundTLSOptions `json:"tls,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type HysteriaUser struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Auth []byte `json:"auth,omitempty"`
|
||||||
|
AuthString string `json:"auth_str,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
type HysteriaOutboundOptions struct {
|
type HysteriaOutboundOptions struct {
|
||||||
DialerOptions
|
DialerOptions
|
||||||
ServerOptions
|
ServerOptions
|
||||||
|
|
Loading…
Reference in a new issue