@@ -197,6 +197,25 @@ type autocertCache struct {
197197
198198const envCacheEncKey = "DUMBPROXY_CACHE_ENC_KEY"
199199
200+ type dnsPreferenceArg resolver.Preference
201+
202+ func (a * dnsPreferenceArg ) String () string {
203+ return resolver .Preference (* a ).String ()
204+ }
205+
206+ func (a * dnsPreferenceArg ) Set (s string ) error {
207+ p , err := resolver .ParsePreference (s )
208+ if err != nil {
209+ return nil
210+ }
211+ * a = dnsPreferenceArg (p )
212+ return nil
213+ }
214+
215+ func (a * dnsPreferenceArg ) Value () resolver.Preference {
216+ return resolver .Preference (* a )
217+ }
218+
200219type bindSpec struct {
201220 af string
202221 address string
@@ -241,6 +260,8 @@ type CLIArgs struct {
241260 bwBurst int64
242261 bwBuckets uint
243262 bwSeparate bool
263+ dnsServers []string
264+ dnsPreferAddress dnsPreferenceArg
244265 dnsCacheTTL time.Duration
245266 dnsCacheNegTTL time.Duration
246267 dnsCacheTimeout time.Duration
@@ -251,7 +272,6 @@ type CLIArgs struct {
251272 jsProxyRouterInstances int
252273 proxyproto bool
253274 shutdownTimeout time.Duration
254- nameservers []string
255275}
256276
257277func parse_args () CLIArgs {
@@ -277,6 +297,7 @@ func parse_args() CLIArgs {
277297 address : ":8080" ,
278298 af : "tcp" ,
279299 },
300+ dnsPreferAddress : dnsPreferenceArg (resolver .PreferenceIPv4 ),
280301 }
281302 args .autocertCacheEncKey .Set (os .Getenv (envCacheEncKey ))
282303 flag .Func ("bind-address" , "HTTP proxy listen address. Set empty value to use systemd socket activation. (default \" :8080\" )" , func (p string ) error {
@@ -364,12 +385,13 @@ func parse_args() CLIArgs {
364385 flag .BoolVar (& args .bwSeparate , "bw-limit-separate" , false , "separate upload and download bandwidth limits" )
365386 flag .Func ("dns-server" , "nameserver specification (udp://..., tcp://..., https://..., tls://..., doh://..., dot://..., default://). Option can be used multiple times for parallel use of multiple nameservers. Empty string resets list" , func (p string ) error {
366387 if p == "" {
367- args .nameservers = nil
388+ args .dnsServers = nil
368389 } else {
369- args .nameservers = append (args .nameservers , p )
390+ args .dnsServers = append (args .dnsServers , p )
370391 }
371392 return nil
372393 })
394+ flag .Var (& args .dnsPreferAddress , "dns-prefer-address" , "address resolution preference (none/ipv4/ipv6)" )
373395 flag .DurationVar (& args .dnsCacheTTL , "dns-cache-ttl" , 0 , "enable DNS cache with specified fixed TTL" )
374396 flag .DurationVar (& args .dnsCacheNegTTL , "dns-cache-neg-ttl" , time .Second , "TTL for negative responses of DNS cache" )
375397 flag .DurationVar (& args .dnsCacheTimeout , "dns-cache-timeout" , 5 * time .Second , "timeout for shared resolves of DNS cache" )
@@ -521,13 +543,14 @@ func run() int {
521543 dialerRoot = dialer .NewFilterDialer (filterRoot .Access , dialerRoot ) // must follow after resolving in chain
522544
523545 var nameResolver dialer.Resolver = net .DefaultResolver
524- if len (args .nameservers ) > 0 {
525- nameResolver , err = resolver .FastFromURLs (args .nameservers ... )
546+ if len (args .dnsServers ) > 0 {
547+ nameResolver , err = resolver .FastFromURLs (args .dnsServers ... )
526548 if err != nil {
527549 mainLogger .Critical ("Failed to create name resolver: %v" , err )
528550 return 3
529551 }
530552 }
553+ nameResolver = resolver .Prefer (nameResolver , args .dnsPreferAddress .Value ())
531554 if args .dnsCacheTTL > 0 {
532555 cd := dialer .NewNameResolveCachingDialer (
533556 dialerRoot ,
0 commit comments