View Javadoc
1   /*
2    * Copyright 2017 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package io.netty5.resolver.dns;
17  
18  import io.netty5.util.NetUtil;
19  import io.netty5.util.internal.PlatformDependent;
20  import io.netty5.util.internal.SocketUtils;
21  import io.netty5.util.internal.logging.InternalLogger;
22  import io.netty5.util.internal.logging.InternalLoggerFactory;
23  
24  import java.net.Inet6Address;
25  import java.net.InetSocketAddress;
26  import java.util.ArrayList;
27  import java.util.Collections;
28  import java.util.List;
29  
30  import static io.netty5.resolver.dns.DnsServerAddresses.sequential;
31  
32  /**
33   * A {@link DnsServerAddressStreamProvider} which will use predefined default DNS servers to use for DNS resolution.
34   * These defaults do not respect your host's machines defaults.
35   * <p>
36   * This may use the JDK's blocking DNS resolution to bootstrap the default DNS server addresses.
37   */
38  public final class DefaultDnsServerAddressStreamProvider implements DnsServerAddressStreamProvider {
39      private static final InternalLogger logger =
40              InternalLoggerFactory.getInstance(DefaultDnsServerAddressStreamProvider.class);
41      public static final DefaultDnsServerAddressStreamProvider INSTANCE = new DefaultDnsServerAddressStreamProvider();
42  
43      private static final List<InetSocketAddress> DEFAULT_NAME_SERVER_LIST;
44      private static final DnsServerAddresses DEFAULT_NAME_SERVERS;
45      static final int DNS_PORT = 53;
46  
47      static {
48          final List<InetSocketAddress> defaultNameServers = new ArrayList<>(2);
49          if (!PlatformDependent.isAndroid()) {
50              // Only try to use when not on Android as the classes not exists there:
51              // See https://github.com/netty/netty/issues/8654
52              DirContextUtils.addNameServers(defaultNameServers, DNS_PORT);
53          }
54  
55          if (!defaultNameServers.isEmpty()) {
56              if (logger.isDebugEnabled()) {
57                  logger.debug(
58                          "Default DNS servers: {} (sun.net.dns.ResolverConfiguration)", defaultNameServers);
59              }
60          } else {
61              // Depending if IPv6 or IPv4 is used choose the correct DNS servers provided by google:
62              // https://developers.google.com/speed/public-dns/docs/using
63              // https://docs.oracle.com/javase/7/docs/api/java/net/doc-files/net-properties.html
64              if (NetUtil.isIpV6AddressesPreferred() ||
65                  NetUtil.LOCALHOST instanceof Inet6Address && !NetUtil.isIpV4StackPreferred()) {
66                  Collections.addAll(
67                          defaultNameServers,
68                          SocketUtils.socketAddress("2001:4860:4860::8888", DNS_PORT),
69                          SocketUtils.socketAddress("2001:4860:4860::8844", DNS_PORT));
70              } else {
71                  Collections.addAll(
72                          defaultNameServers,
73                          SocketUtils.socketAddress("8.8.8.8", DNS_PORT),
74                          SocketUtils.socketAddress("8.8.4.4", DNS_PORT));
75              }
76  
77              if (logger.isWarnEnabled()) {
78                  logger.warn(
79                          "Default DNS servers: {} (Google Public DNS as a fallback)", defaultNameServers);
80              }
81          }
82  
83          DEFAULT_NAME_SERVER_LIST = Collections.unmodifiableList(defaultNameServers);
84          DEFAULT_NAME_SERVERS = sequential(DEFAULT_NAME_SERVER_LIST);
85      }
86  
87      private DefaultDnsServerAddressStreamProvider() {
88      }
89  
90      @Override
91      public DnsServerAddressStream nameServerAddressStream(String hostname) {
92          return DEFAULT_NAME_SERVERS.stream();
93      }
94  
95      /**
96       * Returns the list of the system DNS server addresses. If it failed to retrieve the list of the system DNS server
97       * addresses from the environment, it will return {@code "8.8.8.8"} and {@code "8.8.4.4"}, the addresses of the
98       * Google public DNS servers.
99       */
100     public static List<InetSocketAddress> defaultAddressList() {
101         return DEFAULT_NAME_SERVER_LIST;
102     }
103 
104     /**
105      * Returns the {@link DnsServerAddresses} that yields the system DNS server addresses sequentially. If it failed to
106      * retrieve the list of the system DNS server addresses from the environment, it will use {@code "8.8.8.8"} and
107      * {@code "8.8.4.4"}, the addresses of the Google public DNS servers.
108      * <p>
109      * This method has the same effect with the following code:
110      * <pre>
111      * DnsServerAddresses.sequential(DnsServerAddresses.defaultAddressList());
112      * </pre>
113      * </p>
114      */
115     public static DnsServerAddresses defaultAddresses() {
116         return DEFAULT_NAME_SERVERS;
117     }
118 }