mirror of
https://github.com/SagerNet/sing-box.git
synced 2026-05-13 05:51:36 +00:00
Update hysteria2 realm
This commit is contained in:
parent
34c90e6f2e
commit
2e1a7a53ae
11 changed files with 109 additions and 43 deletions
|
|
@ -42,16 +42,16 @@ type DNSQueryOptions struct {
|
|||
ClientSubnet netip.Prefix
|
||||
}
|
||||
|
||||
func DNSQueryOptionsFrom(ctx context.Context, options *option.DomainResolveOptions) (*DNSQueryOptions, error) {
|
||||
if options == nil {
|
||||
return &DNSQueryOptions{}, nil
|
||||
func DNSQueryOptionsFrom(ctx context.Context, options *option.DomainResolveOptions) (DNSQueryOptions, error) {
|
||||
if options == nil || options.Server == "" {
|
||||
return DNSQueryOptions{}, nil
|
||||
}
|
||||
transportManager := service.FromContext[DNSTransportManager](ctx)
|
||||
transport, loaded := transportManager.Transport(options.Server)
|
||||
if !loaded {
|
||||
return nil, E.New("domain resolver not found: " + options.Server)
|
||||
return DNSQueryOptions{}, E.New("domain resolver not found: " + options.Server)
|
||||
}
|
||||
return &DNSQueryOptions{
|
||||
return DNSQueryOptions{
|
||||
Transport: transport,
|
||||
Strategy: C.DomainStrategy(options.Strategy),
|
||||
DisableCache: options.DisableCache,
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ icon: material/alert-decagram
|
|||
"token": "",
|
||||
"realm_id": "",
|
||||
"stun_servers": [],
|
||||
"stun_domain_resolver": "", // or {}
|
||||
"http_client": {}
|
||||
}
|
||||
}
|
||||
|
|
@ -209,7 +210,15 @@ Outbounds must use the same `realm_id` to find this server.
|
|||
|
||||
List of STUN servers (`host` or `host:port`) used to discover public addresses.
|
||||
|
||||
Port defaults to `3478`.
|
||||
#### realm.stun_domain_resolver
|
||||
|
||||
Set domain resolver to use for resolving STUN server domain names.
|
||||
|
||||
This option uses the same format as the [route DNS rule action](/configuration/dns/rule_action/#route) without the `action` field.
|
||||
|
||||
Setting this option directly to a string is equivalent to setting `server` of this options.
|
||||
|
||||
If empty, the default domain resolver is used.
|
||||
|
||||
#### realm.http_client
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ icon: material/alert-decagram
|
|||
"token": "",
|
||||
"realm_id": "",
|
||||
"stun_servers": [],
|
||||
"stun_domain_resolver": "", // 或 {}
|
||||
"http_client": {}
|
||||
}
|
||||
}
|
||||
|
|
@ -206,7 +207,15 @@ Realm 上的槽位标识符。
|
|||
|
||||
用于发现公网地址的 STUN 服务器列表(`host` 或 `host:port`)。
|
||||
|
||||
端口默认为 `3478`。
|
||||
#### realm.stun_domain_resolver
|
||||
|
||||
用于解析 STUN 服务器域名的域名解析器。
|
||||
|
||||
此选项的格式与 [路由 DNS 规则动作](/zh/configuration/dns/rule_action/#route) 相同,但不包含 `action` 字段。
|
||||
|
||||
若直接将此选项设置为字符串,则等同于设置该选项的 `server` 字段。
|
||||
|
||||
如果为空,则使用默认域名解析器。
|
||||
|
||||
#### realm.http_client
|
||||
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ The same slot identifier the target Hysteria2 server registered.
|
|||
|
||||
List of STUN servers (`host` or `host:port`) used to discover this client's public addresses.
|
||||
|
||||
Port defaults to `3478`.
|
||||
Domain names are resolved using [`domain_resolver`](/configuration/shared/dial/#domain_resolver) from Dial Fields.
|
||||
|
||||
#### realm.http_client
|
||||
|
||||
|
|
|
|||
|
|
@ -189,7 +189,7 @@ Realm 的 Bearer 令牌,需与 realm 上配置的 `users[].token` 之一匹配
|
|||
|
||||
用于发现本客户端公网地址的 STUN 服务器列表(`host` 或 `host:port`)。
|
||||
|
||||
端口默认为 `3478`。
|
||||
域名通过 [拨号字段](/zh/configuration/shared/dial/) 中的 [`domain_resolver`](/zh/configuration/shared/dial/#domain_resolver) 解析。
|
||||
|
||||
#### realm.http_client
|
||||
|
||||
|
|
|
|||
2
go.mod
2
go.mod
|
|
@ -40,7 +40,7 @@ require (
|
|||
github.com/sagernet/sing v0.8.10-0.20260428084616-2bc976d03e39
|
||||
github.com/sagernet/sing-cloudflared v0.1.0
|
||||
github.com/sagernet/sing-mux v0.3.4
|
||||
github.com/sagernet/sing-quic v0.6.2-0.20260510042401-4055a2bb2381
|
||||
github.com/sagernet/sing-quic v0.6.2-0.20260511084842-9deddf006024
|
||||
github.com/sagernet/sing-shadowsocks v0.2.8
|
||||
github.com/sagernet/sing-shadowsocks2 v0.2.1
|
||||
github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11
|
||||
|
|
|
|||
4
go.sum
4
go.sum
|
|
@ -248,8 +248,8 @@ github.com/sagernet/sing-cloudflared v0.1.0 h1:to+2fcCx8zu4X/DirRw9Ihc+FrEZ7oEyI
|
|||
github.com/sagernet/sing-cloudflared v0.1.0/go.mod h1:bH2NKX+NpDTY1Zkxfboxw6MXB/ZywaNLmrDJYgKMJ2Y=
|
||||
github.com/sagernet/sing-mux v0.3.4 h1:ZQplKl8MNXutjzbMVtWvWG31fohhgOfCuUZR4dVQ8+s=
|
||||
github.com/sagernet/sing-mux v0.3.4/go.mod h1:QvlKMyNBNrQoyX4x+gq028uPbLM2XeRpWtDsWBJbFSk=
|
||||
github.com/sagernet/sing-quic v0.6.2-0.20260510042401-4055a2bb2381 h1:bwja5I7Sgr4Z1nyCLlN6T5eBhhSE/ilYZmkEFIoPAhQ=
|
||||
github.com/sagernet/sing-quic v0.6.2-0.20260510042401-4055a2bb2381/go.mod h1:+oqD54aHel4ALKkp1hVXWCgLU/EjLojvm6AUzDfvj0I=
|
||||
github.com/sagernet/sing-quic v0.6.2-0.20260511084842-9deddf006024 h1:P1iab6udg2I2igIrn+mNKpPZNcuejSqno3jwJ/94upw=
|
||||
github.com/sagernet/sing-quic v0.6.2-0.20260511084842-9deddf006024/go.mod h1:+oqD54aHel4ALKkp1hVXWCgLU/EjLojvm6AUzDfvj0I=
|
||||
github.com/sagernet/sing-shadowsocks v0.2.8 h1:PURj5PRoAkqeHh2ZW205RWzN9E9RtKCVCzByXruQWfE=
|
||||
github.com/sagernet/sing-shadowsocks v0.2.8/go.mod h1:lo7TWEMDcN5/h5B8S0ew+r78ZODn6SwVaFhvB6H+PTI=
|
||||
github.com/sagernet/sing-shadowsocks2 v0.2.1 h1:dWV9OXCeFPuYGHb6IRqlSptVnSzOelnqqs2gQ2/Qioo=
|
||||
|
|
|
|||
|
|
@ -19,10 +19,10 @@ type Hysteria2InboundOptions struct {
|
|||
IgnoreClientBandwidth bool `json:"ignore_client_bandwidth,omitempty"`
|
||||
InboundTLSOptionsContainer
|
||||
QUICOptions
|
||||
Masquerade *Hysteria2Masquerade `json:"masquerade,omitempty"`
|
||||
BBRProfile string `json:"bbr_profile,omitempty"`
|
||||
BrutalDebug bool `json:"brutal_debug,omitempty"`
|
||||
Realm *Hysteria2Realm `json:"realm,omitempty"`
|
||||
Masquerade *Hysteria2Masquerade `json:"masquerade,omitempty"`
|
||||
BBRProfile string `json:"bbr_profile,omitempty"`
|
||||
BrutalDebug bool `json:"brutal_debug,omitempty"`
|
||||
Realm *Hysteria2InboundRealm `json:"realm,omitempty"`
|
||||
}
|
||||
|
||||
type Hysteria2Realm struct {
|
||||
|
|
@ -33,6 +33,11 @@ type Hysteria2Realm struct {
|
|||
HTTPClient *HTTPClientOptions `json:"http_client,omitempty"`
|
||||
}
|
||||
|
||||
type Hysteria2InboundRealm struct {
|
||||
Hysteria2Realm
|
||||
STUNDomainResolver *DomainResolveOptions `json:"stun_domain_resolver,omitempty"`
|
||||
}
|
||||
|
||||
type Hysteria2Obfs struct {
|
||||
Type string `json:"type,omitempty"`
|
||||
Password string `json:"password,omitempty"`
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
"net"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/netip"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
|
|
@ -18,11 +19,13 @@ import (
|
|||
qtls "github.com/sagernet/sing-quic"
|
||||
"github.com/sagernet/sing-quic/hysteria"
|
||||
"github.com/sagernet/sing-quic/hysteria2"
|
||||
"github.com/sagernet/sing-quic/hysteria2/realm"
|
||||
"github.com/sagernet/sing/common"
|
||||
"github.com/sagernet/sing/common/auth"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
"github.com/sagernet/sing/service"
|
||||
)
|
||||
|
||||
func RegisterInbound(registry *inbound.Registry) {
|
||||
|
|
@ -114,9 +117,35 @@ func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLo
|
|||
} else {
|
||||
udpTimeout = C.UDPTimeout
|
||||
}
|
||||
realmOptions, err := buildRealmOptions(ctx, logger, options.Realm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var realmOptions *realm.Options
|
||||
if options.Realm != nil {
|
||||
queryOptions, err := adapter.DNSQueryOptionsFrom(ctx, options.Realm.STUNDomainResolver)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
httpClientTransport, err := service.FromContext[adapter.HTTPClientManager](ctx).ResolveTransport(ctx, logger, common.PtrValueOrDefault(options.Realm.HTTPClient))
|
||||
if err != nil {
|
||||
return nil, E.Cause(err, "create realm http client")
|
||||
}
|
||||
dnsRouter := service.FromContext[adapter.DNSRouter](ctx)
|
||||
realmOptions = &realm.Options{
|
||||
ServerURL: options.Realm.ServerURL,
|
||||
Token: options.Realm.Token,
|
||||
RealmID: options.Realm.RealmID,
|
||||
STUNServers: options.Realm.STUNServers,
|
||||
HTTPClient: &http.Client{Transport: httpClientTransport},
|
||||
Resolver: func(ctx context.Context, host string, ipv4, ipv6 bool) ([]netip.Addr, error) {
|
||||
dnsOptions := queryOptions
|
||||
switch {
|
||||
case ipv4 && !ipv6:
|
||||
dnsOptions.Strategy = C.DomainStrategyIPv4Only
|
||||
case !ipv4 && ipv6:
|
||||
dnsOptions.Strategy = C.DomainStrategyIPv6Only
|
||||
}
|
||||
return dnsRouter.Lookup(ctx, host, dnsOptions)
|
||||
},
|
||||
Logger: logger,
|
||||
}
|
||||
}
|
||||
hysteriaService, err := hysteria2.NewService[int](hysteria2.ServiceOptions{
|
||||
Context: ctx,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ package hysteria2
|
|||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/netip"
|
||||
"net/url"
|
||||
"os"
|
||||
"time"
|
||||
|
|
@ -18,12 +20,14 @@ import (
|
|||
qtls "github.com/sagernet/sing-quic"
|
||||
"github.com/sagernet/sing-quic/hysteria"
|
||||
"github.com/sagernet/sing-quic/hysteria2"
|
||||
"github.com/sagernet/sing-quic/hysteria2/realm"
|
||||
"github.com/sagernet/sing/common"
|
||||
"github.com/sagernet/sing/common/bufio"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
"github.com/sagernet/sing/common/logger"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
"github.com/sagernet/sing/service"
|
||||
)
|
||||
|
||||
func RegisterOutbound(registry *outbound.Registry) {
|
||||
|
|
@ -66,13 +70,43 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
|
|||
return nil, E.New("unknown obfs type: ", options.Obfs.Type)
|
||||
}
|
||||
}
|
||||
outboundDialer, err := dialer.New(ctx, options.DialerOptions, options.ServerIsDomain())
|
||||
outboundDialer, err := dialer.NewWithOptions(dialer.Options{
|
||||
Context: ctx,
|
||||
Options: options.DialerOptions,
|
||||
RemoteIsDomain: options.ServerIsDomain(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
realmOptions, err := buildRealmOptions(ctx, logger, options.Realm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var realmOptions *realm.Options
|
||||
if options.Realm != nil {
|
||||
queryOptions, err := adapter.DNSQueryOptionsFrom(ctx, options.DialerOptions.DomainResolver)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
httpClientTransport, err := service.FromContext[adapter.HTTPClientManager](ctx).ResolveTransport(ctx, logger, common.PtrValueOrDefault(options.Realm.HTTPClient))
|
||||
if err != nil {
|
||||
return nil, E.Cause(err, "create realm http client")
|
||||
}
|
||||
dnsRouter := service.FromContext[adapter.DNSRouter](ctx)
|
||||
realmOptions = &realm.Options{
|
||||
ServerURL: options.Realm.ServerURL,
|
||||
Token: options.Realm.Token,
|
||||
RealmID: options.Realm.RealmID,
|
||||
STUNServers: options.Realm.STUNServers,
|
||||
HTTPClient: &http.Client{Transport: httpClientTransport},
|
||||
Resolver: func(ctx context.Context, host string, ipv4, ipv6 bool) ([]netip.Addr, error) {
|
||||
dnsOptions := queryOptions
|
||||
switch {
|
||||
case ipv4 && !ipv6:
|
||||
dnsOptions.Strategy = C.DomainStrategyIPv4Only
|
||||
case !ipv4 && ipv6:
|
||||
dnsOptions.Strategy = C.DomainStrategyIPv6Only
|
||||
}
|
||||
return dnsRouter.Lookup(ctx, host, dnsOptions)
|
||||
},
|
||||
Logger: logger,
|
||||
}
|
||||
}
|
||||
networkList := options.Network.Build()
|
||||
client, err := hysteria2.NewClient(hysteria2.ClientOptions{
|
||||
|
|
|
|||
|
|
@ -13,13 +13,11 @@ import (
|
|||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
"github.com/sagernet/sing-quic/hysteria2/realm"
|
||||
"github.com/sagernet/sing/common"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
aTLS "github.com/sagernet/sing/common/tls"
|
||||
sHTTP "github.com/sagernet/sing/protocol/http"
|
||||
"github.com/sagernet/sing/service"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-chi/chi/v5/middleware"
|
||||
|
|
@ -31,24 +29,6 @@ func RegisterRealmService(registry *boxService.Registry) {
|
|||
boxService.Register[option.HysteriaRealmServiceOptions](registry, C.TypeHysteriaRealm, NewRealmService)
|
||||
}
|
||||
|
||||
func buildRealmOptions(ctx context.Context, logger log.ContextLogger, options *option.Hysteria2Realm) (*realm.Options, error) {
|
||||
if options == nil {
|
||||
return nil, nil
|
||||
}
|
||||
transport, err := service.FromContext[adapter.HTTPClientManager](ctx).ResolveTransport(ctx, logger, common.PtrValueOrDefault(options.HTTPClient))
|
||||
if err != nil {
|
||||
return nil, E.Cause(err, "create realm http client")
|
||||
}
|
||||
return &realm.Options{
|
||||
ServerURL: options.ServerURL,
|
||||
Token: options.Token,
|
||||
RealmID: options.RealmID,
|
||||
STUNServers: options.STUNServers,
|
||||
HTTPClient: &http.Client{Transport: transport},
|
||||
Logger: logger,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type RealmService struct {
|
||||
boxService.Adapter
|
||||
ctx context.Context
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue