Repository: netty/netty
Issue: Allow to config the listen address on DnsResolver

The DnsResolver default start address listen to "0.0.0.0", which may have some security risks.
Can we allow to config the listen address on DnsResolver?

Issue comments:
@Shoothzj sure... Maybe provide a PR that allows to configure the `SocketAddress` via the `DnsResolverBuilder` ?
@normanmaurer I am new to Netty code contributing. How about java property `io.netty.dnsResolverListenAddress`
I would prefer to make it configurable via the builder.. 

Pull request review comments:
This should be an `InetSocketAddress`.  Also we will need to preserve the old constructor to not break things, which means you should add a new one (package-private)
See below... pass in `null` for using the default. 
See below... should be `SocketAddress`
call `register` if the `bindAddress` is `null`, otherwise call `bind()`
please call this `localAddress` to be consistent with `Bootstrap` and make it take a `SocketAddress`.
One question, Why `InetSocketAddress` is better than `String`, It's the reason the `InetSocketAddress` are more reliable?
And the InetSocketAddress contains the port config?
Rename the name to `localAddress`, And change the type to `SocketAddress `
@Shoothzj Yes, `InetSocketAddress` contains IP Address and Port.
Change `{@code this` to something else.
```suggestion
     * Configure the address that will be used to bind too. If `null` the default will be used.
```
Should we make this `SocketAddress` just for the sake of be consistent with `Bootstrap` ?
```suggestion
            SocketAddress localAddress,
```
```suggestion
import java.net.SocketAddress;
```
```suggestion
    private SocketAddress localAddress;
```
```suggestion
    public DnsNameResolverBuilder localAddress(SocketAddress localAddress) {
```
![image](https://user-images.githubusercontent.com/12933197/110261777-76f96f80-7fec-11eb-85f1-fad453cf9bcb.png)
I saw the code below write this.
The "Dns name resolver Builder" will be better?
Sorry, I don't know I can commit the suggestion, Fixed
Sorry, I don't know I can commit the suggestion, I Fixed manually
Sorry, I don't know I can commit the suggestion, I Fixed manually
Sorry, I don't know I can commit the suggestion, I Fixed manually
Sorry, I don't know I can commit the suggestion, I Fixed manually
Sorry, I don't know I can commit the suggestion, I Fixed manually

Patch that resolved the issue:
diff --git a/resolver-dns/src/main/java/io/netty/resolver/dns/DnsNameResolver.java b/resolver-dns/src/main/java/io/netty/resolver/dns/DnsNameResolver.java
index 3781bd4015b..bf594db0627 100644
--- a/resolver-dns/src/main/java/io/netty/resolver/dns/DnsNameResolver.java
+++ b/resolver-dns/src/main/java/io/netty/resolver/dns/DnsNameResolver.java
@@ -383,6 +383,35 @@ public DnsNameResolver(
             int ndots,
             boolean decodeIdn,
             boolean completeOncePreferredResolved) {
+        this(eventLoop, channelFactory, socketChannelFactory, resolveCache, cnameCache, authoritativeDnsServerCache,
+                null, dnsQueryLifecycleObserverFactory, queryTimeoutMillis, resolvedAddressTypes,
+                recursionDesired, maxQueriesPerResolve, traceEnabled, maxPayloadSize, optResourceEnabled,
+                hostsFileEntriesResolver, dnsServerAddressStreamProvider, searchDomains, ndots, decodeIdn,
+                completeOncePreferredResolved);
+    }
+
+    DnsNameResolver(
+            EventLoop eventLoop,
+            ChannelFactory<? extends DatagramChannel> channelFactory,
+            ChannelFactory<? extends SocketChannel> socketChannelFactory,
+            final DnsCache resolveCache,
+            final DnsCnameCache cnameCache,
+            final AuthoritativeDnsServerCache authoritativeDnsServerCache,
+            SocketAddress localAddress,
+            DnsQueryLifecycleObserverFactory dnsQueryLifecycleObserverFactory,
+            long queryTimeoutMillis,
+            ResolvedAddressTypes resolvedAddressTypes,
+            boolean recursionDesired,
+            int maxQueriesPerResolve,
+            boolean traceEnabled,
+            int maxPayloadSize,
+            boolean optResourceEnabled,
+            HostsFileEntriesResolver hostsFileEntriesResolver,
+            DnsServerAddressStreamProvider dnsServerAddressStreamProvider,
+            String[] searchDomains,
+            int ndots,
+            boolean decodeIdn,
+            boolean completeOncePreferredResolved) {
         super(eventLoop);
         this.queryTimeoutMillis = queryTimeoutMillis > 0
             ? queryTimeoutMillis
@@ -453,7 +482,12 @@ protected void initChannel(DatagramChannel ch) {
         });
 
         channelFuture = responseHandler.channelActivePromise;
-        ChannelFuture future = b.register();
+        final ChannelFuture future;
+        if (localAddress == null) {
+            future = b.register();
+        } else {
+            future = b.bind(localAddress);
+        }
         Throwable cause = future.cause();
         if (cause != null) {
             if (cause instanceof RuntimeException) {
diff --git a/resolver-dns/src/main/java/io/netty/resolver/dns/DnsNameResolverBuilder.java b/resolver-dns/src/main/java/io/netty/resolver/dns/DnsNameResolverBuilder.java
index 5a0b5b14e84..197aa0aa831 100644
--- a/resolver-dns/src/main/java/io/netty/resolver/dns/DnsNameResolverBuilder.java
+++ b/resolver-dns/src/main/java/io/netty/resolver/dns/DnsNameResolverBuilder.java
@@ -25,6 +25,7 @@
 import io.netty.resolver.ResolvedAddressTypes;
 import io.netty.util.concurrent.Future;
 
+import java.net.SocketAddress;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -42,6 +43,7 @@ public final class DnsNameResolverBuilder {
     private DnsCache resolveCache;
     private DnsCnameCache cnameCache;
     private AuthoritativeDnsServerCache authoritativeDnsServerCache;
+    private SocketAddress localAddress;
     private Integer minTtl;
     private Integer maxTtl;
     private Integer negativeTtl;
@@ -201,6 +203,16 @@ public DnsNameResolverBuilder authoritativeDnsServerCache(AuthoritativeDnsServer
         return this;
     }
 
+    /**
+     * Configure the address that will be used to bind too. If `null` the default will be used.
+     * @param localAddress the bind address
+     * @return {@code this}
+     */
+    public DnsNameResolverBuilder localAddress(SocketAddress localAddress) {
+        this.localAddress = localAddress;
+        return this;
+    }
+
     /**
      * Sets the minimum and maximum TTL of the cached DNS resource records (in seconds). If the TTL of the DNS
      * resource record returned by the DNS server is less than the minimum TTL or greater than the maximum TTL,
@@ -480,6 +492,7 @@ public DnsNameResolver build() {
                 resolveCache,
                 cnameCache,
                 authoritativeDnsServerCache,
+                localAddress,
                 dnsQueryLifecycleObserverFactory,
                 queryTimeoutMillis,
                 resolvedAddressTypes,


Test patch: