From cc025f5b9dbb90b5debcb3cd62cebb8043d0a657 Mon Sep 17 00:00:00 2001 From: josexy Date: Tue, 9 Jul 2024 14:31:38 +0800 Subject: [PATCH] fix: support dns lookup local hosts file --- cmd/local.go | 1 + config/config.go | 25 ++++++++++++--------- example-configs/simple-client-config.yaml | 1 + resolver/resolver.go | 20 ++++++++++++----- resolver/resolver_test.go | 2 +- ss/option.go | 27 ++++++++++++++--------- ss/ss_client.go | 2 +- ss/ss_server.go | 2 +- util/hostsutil/hosts.go | 6 +++-- 9 files changed, 55 insertions(+), 31 deletions(-) diff --git a/cmd/local.go b/cmd/local.go index 76e2f22..4017a59 100644 --- a/cmd/local.go +++ b/cmd/local.go @@ -39,6 +39,7 @@ func init() { localCmd.Flags().StringVarP(&cfg.Local.MixedAddr, "mixed", "M", "", "mixed proxy for SOCKS and HTTP") localCmd.Flags().StringSliceVar(&cfg.Local.TCPTunAddr, "tcp-tun", nil, "simple tcp tun listening address (format: \"local:port=remote:port\")") localCmd.Flags().BoolVar(&cfg.Local.SystemProxy, "system-proxy", false, "enable system proxy settings") + localCmd.Flags().BoolVar(&cfg.Local.LookupHostsFile, "lookup-hostsfile", false, "dns lookup local hosts file") // ssr localCmd.Flags().StringVarP(&cfg.Server[0].Type, "type", "T", "", "enable shadowsocksr") diff --git a/config/config.go b/config/config.go index 677b6c2..7fe973c 100644 --- a/config/config.go +++ b/config/config.go @@ -110,16 +110,17 @@ type MitmOption struct { } type LocalConfig struct { - SocksAddr string `yaml:"socks_addr,omitempty" json:"socks_addr,omitempty"` - HTTPAddr string `yaml:"http_addr,omitempty" json:"http_addr,omitempty"` - SocksAuth string `yaml:"socks_auth,omitempty" json:"socks_auth,omitempty"` - HTTPAuth string `yaml:"http_auth,omitempty" json:"http_auth,omitempty"` - MixedAddr string `yaml:"mixed_addr,omitempty" json:"mixed_addr,omitempty"` - TCPTunAddr []string `yaml:"tcp_tun_addr,omitempty" json:"tcp_tun_addr,omitempty"` - SystemProxy bool `yaml:"system_proxy,omitempty" json:"system_proxy,omitempty"` - Mitm *MitmOption `yaml:"mitm,omitempty" json:"mitm,omitempty"` - Tun *TunOption `yaml:"tun,omitempty" json:"tun,omitempty"` - DNS *DnsOption `yaml:"dns,omitempty" json:"dns,omitempty"` + SocksAddr string `yaml:"socks_addr,omitempty" json:"socks_addr,omitempty"` + HTTPAddr string `yaml:"http_addr,omitempty" json:"http_addr,omitempty"` + SocksAuth string `yaml:"socks_auth,omitempty" json:"socks_auth,omitempty"` + HTTPAuth string `yaml:"http_auth,omitempty" json:"http_auth,omitempty"` + MixedAddr string `yaml:"mixed_addr,omitempty" json:"mixed_addr,omitempty"` + TCPTunAddr []string `yaml:"tcp_tun_addr,omitempty" json:"tcp_tun_addr,omitempty"` + SystemProxy bool `yaml:"system_proxy,omitempty" json:"system_proxy,omitempty"` + LookupHostsFile bool `yaml:"lookup_hostsfile,omitempty" json:"lookup_hostsfile,omitempty"` + Mitm *MitmOption `yaml:"mitm,omitempty" json:"mitm,omitempty"` + Tun *TunOption `yaml:"tun,omitempty" json:"tun,omitempty"` + DNS *DnsOption `yaml:"dns,omitempty" json:"dns,omitempty"` } type Domain struct { @@ -468,6 +469,10 @@ func (cfg *Config) BuildLocalOptions() []ss.SSOption { opts = append(opts, ss.WithSystemProxy()) } + if cfg.Local.LookupHostsFile { + opts = append(opts, ss.WithLookupHostsFile()) + } + return opts } diff --git a/example-configs/simple-client-config.yaml b/example-configs/simple-client-config.yaml index 51a91db..d8241fa 100644 --- a/example-configs/simple-client-config.yaml +++ b/example-configs/simple-client-config.yaml @@ -12,6 +12,7 @@ local: mixed_addr: :10088 # socks_auth: "123:123" # http_auth: '123:123' + lookup_hostsfile: true log: color: true log_level: trace diff --git a/resolver/resolver.go b/resolver/resolver.go index 530061f..928ff7e 100644 --- a/resolver/resolver.go +++ b/resolver/resolver.go @@ -37,9 +37,10 @@ type nameserverExt struct { type Resolver struct { *fakeIPResolver // UDP/TCP/DoT/DoH - nameservers []nameserverExt - clients map[string]*DnsClient - lookupGroup singleflight.Group + nameservers []nameserverExt + clients map[string]*DnsClient + lookupGroup singleflight.Group + lookupHostPref bool } func parseNameserver(nameservers []string) []nameserverExt { @@ -112,7 +113,7 @@ func parseNameserver(nameservers []string) []nameserverExt { return list } -func NewDnsResolver(nameservers []string) *Resolver { +func NewDnsResolver(nameservers []string, lookupHostsFile bool) *Resolver { nameserver := parseNameserver(nameservers) // default system config dns fallback := parseNameserver(dnsutil.GetLocalDnsList()) @@ -121,8 +122,9 @@ func NewDnsResolver(nameservers []string) *Resolver { } resolver := &Resolver{ - clients: make(map[string]*DnsClient), - nameservers: append(nameserver, fallback...), + clients: make(map[string]*DnsClient), + nameservers: append(nameserver, fallback...), + lookupHostPref: lookupHostsFile, } for _, ns := range resolver.nameservers { @@ -157,6 +159,12 @@ func (r *Resolver) LookupHost(ctx context.Context, host string) netip.Addr { } func (r *Resolver) LookupIP(ctx context.Context, host string) ([]netip.Addr, error) { + if r.lookupHostPref { + ip := hostsutil.LookupIP(host) + if ip.IsValid() { + return []netip.Addr{ip}, nil + } + } ipsCh := make(chan []netip.Addr, 1) // lookup ipv6 address go func() { diff --git a/resolver/resolver_test.go b/resolver/resolver_test.go index 12c0683..87e5d04 100644 --- a/resolver/resolver_test.go +++ b/resolver/resolver_test.go @@ -24,7 +24,7 @@ func TestDnsResolver(t *testing.T) { "https://dns.alidns.com/dns-query", } logger.Logger = logger.LogContext.Copy().WithCaller(false, true, false, true).BuildConsoleLogger(logx.LevelTrace) - r := NewDnsResolver(nameservers) + r := NewDnsResolver(nameservers, false) for _, ns := range nameservers { for i := 0; i < 2; i++ { diff --git a/ss/option.go b/ss/option.go index c43ca31..5c3bd34 100644 --- a/ss/option.go +++ b/ss/option.go @@ -28,16 +28,17 @@ type serverOptions struct { } type localOptions struct { - socksAddr string - httpAddr string - mixedAddr string - socksAuth *Auth - httpAuth *Auth - tcpTunAddr [][]string - systemProxy bool - enableTun bool - enhancerConfig enhancer.EnhancerConfig - mitmConfig proxy.MimtOption + socksAddr string + httpAddr string + mixedAddr string + socksAuth *Auth + httpAuth *Auth + tcpTunAddr [][]string + systemProxy bool + enableTun bool + lookupHostsFile bool + enhancerConfig enhancer.EnhancerConfig + mitmConfig proxy.MimtOption } type ssOptions struct { @@ -257,6 +258,12 @@ func WithSystemProxy() SSOption { }) } +func WithLookupHostsFile() SSOption { + return ssOptionFunc(func(so *ssOptions) { + so.localOpts.lookupHostsFile = true + }) +} + func WithSocksUserInfo(username, password string) SSOption { return ssOptionFunc(func(so *ssOptions) { so.localOpts.socksAuth = NewAuth(username, password) diff --git a/ss/ss_client.go b/ss/ss_client.go index 92d7cb5..f69b411 100644 --- a/ss/ss_client.go +++ b/ss/ss_client.go @@ -58,7 +58,7 @@ func NewShadowsocksClient(opts ...SSOption) *ShadowsocksClient { } // init the global default dns resolver - resolver.DefaultResolver = resolver.NewDnsResolver(resolver.DefaultDnsNameservers) + resolver.DefaultResolver = resolver.NewDnsResolver(resolver.DefaultDnsNameservers, s.Opts.localOpts.lookupHostsFile) // only one proxy node with command line if len(s.Opts.serverOpts) == 1 && s.Opts.serverOpts[0].name == "" && rule.MatchRuler.GlobalTo == "" { diff --git a/ss/ss_server.go b/ss/ss_server.go index 9d6cd9e..53801ff 100644 --- a/ss/ss_server.go +++ b/ss/ss_server.go @@ -33,7 +33,7 @@ func NewShadowsocksServer(opts ...SSOption) *ShadowsocksServer { if len(s.Opts.serverOpts) == 0 { logger.Logger.Fatal("ss-server need configuration") } - resolver.DefaultResolver = resolver.NewDnsResolver(nil) + resolver.DefaultResolver = resolver.NewDnsResolver(nil, false) for _, opt := range s.Opts.serverOpts { if err := s.initServerHandler(&opt); err != nil { logger.Logger.Error("init server failed", logx.Error("error", err)) diff --git a/util/hostsutil/hosts.go b/util/hostsutil/hosts.go index 62bc128..a2852af 100644 --- a/util/hostsutil/hosts.go +++ b/util/hostsutil/hosts.go @@ -23,8 +23,10 @@ func initHostsMap() { } for ip, hosts := range mp { for _, host := range hosts { - logger.Logger.Infof("read hosts record: [%s]->[%s]", ip, host) - hostsMap[host] = append(hostsMap[host], netip.MustParseAddr(ip)) + if addr, err := netip.ParseAddr(ip); err == nil { + logger.Logger.Infof("read hosts record: [%s]->[%s]", host, ip) + hostsMap[host] = append(hostsMap[host], addr) + } } } }