mirror of
https://github.com/cedar2025/hysteria.git
synced 2025-06-10 22:49:54 +00:00
feat: server resolver config options
This commit is contained in:
parent
be76f0650e
commit
7c94b072ed
@ -19,6 +19,7 @@ import (
|
|||||||
"github.com/apernet/hysteria/core/server"
|
"github.com/apernet/hysteria/core/server"
|
||||||
"github.com/apernet/hysteria/extras/auth"
|
"github.com/apernet/hysteria/extras/auth"
|
||||||
"github.com/apernet/hysteria/extras/obfs"
|
"github.com/apernet/hysteria/extras/obfs"
|
||||||
|
"github.com/apernet/hysteria/extras/outbounds"
|
||||||
)
|
)
|
||||||
|
|
||||||
var serverCmd = &cobra.Command{
|
var serverCmd = &cobra.Command{
|
||||||
@ -41,6 +42,7 @@ type serverConfig struct {
|
|||||||
DisableUDP bool `mapstructure:"disableUDP"`
|
DisableUDP bool `mapstructure:"disableUDP"`
|
||||||
UDPIdleTimeout time.Duration `mapstructure:"udpIdleTimeout"`
|
UDPIdleTimeout time.Duration `mapstructure:"udpIdleTimeout"`
|
||||||
Auth serverConfigAuth `mapstructure:"auth"`
|
Auth serverConfigAuth `mapstructure:"auth"`
|
||||||
|
Resolver serverConfigResolver `mapstructure:"resolver"`
|
||||||
Masquerade serverConfigMasquerade `mapstructure:"masquerade"`
|
Masquerade serverConfigMasquerade `mapstructure:"masquerade"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,6 +91,22 @@ type serverConfigAuth struct {
|
|||||||
Password string `mapstructure:"password"`
|
Password string `mapstructure:"password"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type serverConfigResolverTCP struct {
|
||||||
|
Addr string `mapstructure:"addr"`
|
||||||
|
Timeout time.Duration `mapstructure:"timeout"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type serverConfigResolverUDP struct {
|
||||||
|
Addr string `mapstructure:"addr"`
|
||||||
|
Timeout time.Duration `mapstructure:"timeout"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type serverConfigResolver struct {
|
||||||
|
Type string `mapstructure:"type"`
|
||||||
|
TCP serverConfigResolverTCP `mapstructure:"tcp"`
|
||||||
|
UDP serverConfigResolverUDP `mapstructure:"udp"`
|
||||||
|
}
|
||||||
|
|
||||||
type serverConfigMasqueradeFile struct {
|
type serverConfigMasqueradeFile struct {
|
||||||
Dir string `mapstructure:"dir"`
|
Dir string `mapstructure:"dir"`
|
||||||
}
|
}
|
||||||
@ -214,6 +232,36 @@ func (c *serverConfig) fillQUICConfig(hyConfig *server.Config) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *serverConfig) fillOutboundConfig(hyConfig *server.Config) error {
|
||||||
|
// Resolver, ACL, actual outbound are all implemented through the Outbound interface.
|
||||||
|
// Depending on the config, we build a chain like this:
|
||||||
|
// Resolver(ACL(Outbounds...))
|
||||||
|
|
||||||
|
// Outbounds
|
||||||
|
ob := outbounds.NewDirectOutboundSimple(outbounds.DirectOutboundModeAuto)
|
||||||
|
|
||||||
|
// Resolver
|
||||||
|
switch strings.ToLower(c.Resolver.Type) {
|
||||||
|
case "", "system":
|
||||||
|
// Do nothing. DirectOutbound will use system resolver by default.
|
||||||
|
case "tcp":
|
||||||
|
if c.Resolver.TCP.Addr == "" {
|
||||||
|
return configError{Field: "resolver.tcp.addr", Err: errors.New("empty resolver address")}
|
||||||
|
}
|
||||||
|
ob = outbounds.NewStandardResolverTCP(c.Resolver.TCP.Addr, c.Resolver.TCP.Timeout, ob)
|
||||||
|
case "udp":
|
||||||
|
if c.Resolver.UDP.Addr == "" {
|
||||||
|
return configError{Field: "resolver.udp.addr", Err: errors.New("empty resolver address")}
|
||||||
|
}
|
||||||
|
ob = outbounds.NewStandardResolverUDP(c.Resolver.UDP.Addr, c.Resolver.UDP.Timeout, ob)
|
||||||
|
default:
|
||||||
|
return configError{Field: "resolver.type", Err: errors.New("unsupported resolver type")}
|
||||||
|
}
|
||||||
|
|
||||||
|
hyConfig.Outbound = &outbounds.PluggableOutboundAdapter{PluggableOutbound: ob}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *serverConfig) fillBandwidthConfig(hyConfig *server.Config) error {
|
func (c *serverConfig) fillBandwidthConfig(hyConfig *server.Config) error {
|
||||||
var err error
|
var err error
|
||||||
if c.Bandwidth.Up != "" {
|
if c.Bandwidth.Up != "" {
|
||||||
@ -308,6 +356,7 @@ func (c *serverConfig) Config() (*server.Config, error) {
|
|||||||
c.fillConn,
|
c.fillConn,
|
||||||
c.fillTLSConfig,
|
c.fillTLSConfig,
|
||||||
c.fillQUICConfig,
|
c.fillQUICConfig,
|
||||||
|
c.fillOutboundConfig,
|
||||||
c.fillBandwidthConfig,
|
c.fillBandwidthConfig,
|
||||||
c.fillDisableUDP,
|
c.fillDisableUDP,
|
||||||
c.fillUDPIdleTimeout,
|
c.fillUDPIdleTimeout,
|
||||||
@ -320,6 +369,7 @@ func (c *serverConfig) Config() (*server.Config, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return hyConfig, nil
|
return hyConfig, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,6 +61,17 @@ func TestServerConfig(t *testing.T) {
|
|||||||
Type: "password",
|
Type: "password",
|
||||||
Password: "goofy_ahh_password",
|
Password: "goofy_ahh_password",
|
||||||
},
|
},
|
||||||
|
Resolver: serverConfigResolver{
|
||||||
|
Type: "udp",
|
||||||
|
TCP: serverConfigResolverTCP{
|
||||||
|
Addr: "123.123.123.123:5353",
|
||||||
|
Timeout: 4 * time.Second,
|
||||||
|
},
|
||||||
|
UDP: serverConfigResolverUDP{
|
||||||
|
Addr: "4.6.8.0:53",
|
||||||
|
Timeout: 2 * time.Second,
|
||||||
|
},
|
||||||
|
},
|
||||||
Masquerade: serverConfigMasquerade{
|
Masquerade: serverConfigMasquerade{
|
||||||
Type: "proxy",
|
Type: "proxy",
|
||||||
File: serverConfigMasqueradeFile{
|
File: serverConfigMasqueradeFile{
|
||||||
|
@ -41,6 +41,15 @@ auth:
|
|||||||
type: password
|
type: password
|
||||||
password: goofy_ahh_password
|
password: goofy_ahh_password
|
||||||
|
|
||||||
|
resolver:
|
||||||
|
type: udp
|
||||||
|
tcp:
|
||||||
|
addr: 123.123.123.123:5353
|
||||||
|
timeout: 4s
|
||||||
|
udp:
|
||||||
|
addr: 4.6.8.0:53
|
||||||
|
timeout: 2s
|
||||||
|
|
||||||
masquerade:
|
masquerade:
|
||||||
type: proxy
|
type: proxy
|
||||||
file:
|
file:
|
||||||
|
@ -40,6 +40,12 @@ auth:
|
|||||||
type: password
|
type: password
|
||||||
password: some_password
|
password: some_password
|
||||||
|
|
||||||
|
# resolver:
|
||||||
|
# type: udp
|
||||||
|
# udp:
|
||||||
|
# addr: 8.8.4.4
|
||||||
|
# timeout: 2s
|
||||||
|
|
||||||
masquerade:
|
masquerade:
|
||||||
type: proxy
|
type: proxy
|
||||||
proxy:
|
proxy:
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
standardResolverDefaultTimeout = 2 * time.Second
|
||||||
standardResolverRetryTimes = 2
|
standardResolverRetryTimes = 2
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -22,9 +23,9 @@ type standardResolver struct {
|
|||||||
|
|
||||||
func NewStandardResolverUDP(addr string, timeout time.Duration, next PluggableOutbound) PluggableOutbound {
|
func NewStandardResolverUDP(addr string, timeout time.Duration, next PluggableOutbound) PluggableOutbound {
|
||||||
return &standardResolver{
|
return &standardResolver{
|
||||||
Addr: addr,
|
Addr: addDefaultPort(addr),
|
||||||
Client: &dns.Client{
|
Client: &dns.Client{
|
||||||
Timeout: timeout,
|
Timeout: timeoutOrDefault(timeout),
|
||||||
},
|
},
|
||||||
Next: next,
|
Next: next,
|
||||||
}
|
}
|
||||||
@ -32,15 +33,30 @@ func NewStandardResolverUDP(addr string, timeout time.Duration, next PluggableOu
|
|||||||
|
|
||||||
func NewStandardResolverTCP(addr string, timeout time.Duration, next PluggableOutbound) PluggableOutbound {
|
func NewStandardResolverTCP(addr string, timeout time.Duration, next PluggableOutbound) PluggableOutbound {
|
||||||
return &standardResolver{
|
return &standardResolver{
|
||||||
Addr: addr,
|
Addr: addDefaultPort(addr),
|
||||||
Client: &dns.Client{
|
Client: &dns.Client{
|
||||||
Net: "tcp",
|
Net: "tcp",
|
||||||
Timeout: timeout,
|
Timeout: timeoutOrDefault(timeout),
|
||||||
},
|
},
|
||||||
Next: next,
|
Next: next,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// addDefaultPort adds the default DNS port (53) to the address if not present.
|
||||||
|
func addDefaultPort(addr string) string {
|
||||||
|
if _, _, err := net.SplitHostPort(addr); err != nil {
|
||||||
|
return net.JoinHostPort(addr, "53")
|
||||||
|
}
|
||||||
|
return addr
|
||||||
|
}
|
||||||
|
|
||||||
|
func timeoutOrDefault(timeout time.Duration) time.Duration {
|
||||||
|
if timeout == 0 {
|
||||||
|
return standardResolverDefaultTimeout
|
||||||
|
}
|
||||||
|
return timeout
|
||||||
|
}
|
||||||
|
|
||||||
// skipCNAMEChain skips the CNAME chain and returns the last CNAME target.
|
// skipCNAMEChain skips the CNAME chain and returns the last CNAME target.
|
||||||
// Sometimes the DNS server returns a CNAME chain like this, in one packet:
|
// Sometimes the DNS server returns a CNAME chain like this, in one packet:
|
||||||
// domain1.com. CNAME domain2.com.
|
// domain1.com. CNAME domain2.com.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user