Repository: mageddo/dns-proxy-server
Pull request #410 (2023-04-07 16:15:03)

Option to disable remote servers
Relates to #386 


Patch:
diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md
index 97fffa68..af1ab6f7 100644
--- a/RELEASE-NOTES.md
+++ b/RELEASE-NOTES.md
@@ -7,9 +7,13 @@
 for more details
 * Fixed arm64 images stopped being pushed at `3.19`
 * Cache improvement for a concurrent approach synchronized by key
-* Increasing tcp and udp server parallelism from 20 to 50 threads each, threads are created lazilly
+* Increasing tcp and udp server parallelism from 20 to 50 threads each, threads are created lazily
 * Fixing solver NPE on unsupported query types
-* Option to not comment out existing nameservers from resolv.conf [see the docs](http://mageddo.github.io/dns-proxy-server/3.15/en/3-configuration/)
+* Option to not comment out existing nameservers from resolv.conf [see the docs][1]
+* Option to disable remote solvers, see [the docs][2] for more details.
+
+[1]: http://mageddo.github.io/dns-proxy-server/3.15/en/3-configuration/
+[2]: https://mageddo.github.io/dns-proxy-server/3.15/en/3-configuration/#no-remote-servers
 
 ## 3.14.5
 * Specify minimum required docker api version `1.21` (as DPS 2)
diff --git a/docs/content/2-features/local-entries/_index.en.md b/docs/content/2-features/local-entries/_index.en.md
new file mode 100644
index 00000000..308a9a0d
--- /dev/null
+++ b/docs/content/2-features/local-entries/_index.en.md
@@ -0,0 +1,25 @@
+---
+title: Local Entries Solving (LocalDB)
+---
+You can configure pre-defined A, AAAA, CNAME entries to solve Records, DPS will query them after docker containers
+and before remote servers. You can configure them by the JSON config file or [using the GUI][1].
+
+JSON Configuration Example
+
+```json
+{
+  "activeEnv": "",
+  "envs" : [{
+    "name": "", // empty string is the default enviroment
+    "hostnames": [{ // all local hostnames entries
+      "id": 1, // (optional) used to control it will be automatically generated if not passed
+      "type": "A", // Other options: CNAME, AAAA
+      "hostname": "github.com",
+      "ip": "192.168.0.1",
+      "ttl": 255 // how many seconds cache this entry
+    }]
+  }]
+}
+```
+
+[1]: {{%relref "2-features/gui/_index.md" %}}
diff --git a/docs/content/3-configuration/_index.en.md b/docs/content/3-configuration/_index.en.md
index 3f9f36d1..3197ace0 100755
--- a/docs/content/3-configuration/_index.en.md
+++ b/docs/content/3-configuration/_index.en.md
@@ -4,25 +4,129 @@ weight: 3
 pre: "<b>3. </b>"
 ---
 
-### JSON configuration
+## Configs
+
+### Remote DNS Servers
+Remote DNS servers to be asked when can not solve from docker or local storage.
+Default: `8.8.8.8`.
+
+### Web Server Port
+Web GUI port, Default: `5380`.
+
+### DNS Server Port 
+Default: `53`.
+
+### Log Level
+Default: `INFO`.
+
+| Env            | JSON       | Terminal   |
+|----------------|------------|------------|
+| `MG_LOG_LEVEL` | `logLevel` | See --help |
+
+### Log File
+Where the log will be written. Default: console.
+
+| Env           | JSON      | Terminal   |
+|---------------|-----------|------------|
+| `MG_LOG_FILE` | `logFile` | See --help |
+
+### Register Container Names
+If should register container name / service name as a hostname. Default: false.
+
+| Env                           | JSON                     | Terminal   |
+|-------------------------------|--------------------------|------------|
+| `MG_REGISTER_CONTAINER_NAMES` | `registerContainerNames` | See --help |
+
+### Domain
+The container names domain used on the registered container, services. Default: `docker`.
+
+Ex: 
+```bash
+docker run --rm --name nginx nginx
+```
+Will register a container with the name `nginx.docker`
+
+| Env         | JSON     | Terminal   |
+|-------------|----------|------------|
+| `MG_DOMAIN` | `domain` | See --help |
+
+### DPS Network
+If should create a bridge network for dps container. Default: false.
+
+### DPS Network Auto Connect
+If should connect all containers to dps container so they can surely talk with each other. requires DPS Network Option.
+Default: false.
+
+### Default DNS
+If DPS must be set as the default DNS automatically, commonly requires DPS be run as sudo/administrator permissions,
+this options also won't work in some cases when running inside a docker container, [see the feature details][1].
+
+### Host Machine Hostname 
+Hostname to solve machine IP, domain can be changed by Domain option. Default: `host.docker`. 
+
+| Env                        | JSON                  | Terminal   |
+|----------------------------|-----------------------|------------|
+| `MG_HOST_MACHINE_HOSTNAME` | `hostMachineHostname` | See --help |
+
+### Server Protocol
+Protocol to start the dns server. Default: `UDP_TCP`.
+
+### Docker Host
+Docker host address. Default value is SO dependent.
+
+| Env              | JSON         | Terminal   |
+|------------------|--------------|------------|
+| `MG_DOCKER_HOST` | `dockerHost` | See --help |
+
+### Resolvconf Override Name Servers
+If must comment all existing nameservers at `resolv.conf` file (Linux, MacOS) or just put DPS at the first place. 
+Default: true.
+
+| Env                                  | JSON                            | Terminal   |
+|--------------------------------------|---------------------------------|------------|
+| `MG_RESOLVCONF_OVERRIDE_NAMESERVERS` | `resolvConfOverrideNameServers` | See --help |
+
+### Resolvconf
+Linux/Mac resolvconf or systemd-resolved path to set DPS as default DNS. 
+Default: `/host/etc/systemd/resolved.conf,/host/etc/resolv.conf,/etc/systemd/resolved.conf,/etc/resolv.conf`.
+
+| Env           | JSON | Terminal   |
+|---------------|------|------------|
+| MG_RESOLVCONF |      | See --help |
+
+### No Remote Servers
+If remote servers like 8.8.8.8 must be disabled and only local solvers like docker containers or local db must be used.
+Default: false.
+
+| Env                 | JSON              | Terminal   |
+|---------------------|-------------------|------------|
+| `NO_REMOTE_SERVERS` | `noRemoteServers` | See --help |
+
+### Active Env
+Active Env used to query local db entries. Default `` (Empty String).
+
+| Env | JSON        | Terminal |
+|-----|-------------|----------|
+|     | `activeEnv` |          |
+
+### Local Entries Solving (LocalDB)
+See [Local Entries Solving][2] docs.
+
+## Example JSON configuration
 
 __Version 2__
 
 ```json
 {
   "version": 2,
-  // Remote DNS servers to be asked when can not solve from docker or local storage
-  // If no one server was specified then the 8.8.8.8 will be used
   "remoteDnsServers": [ "8.8.8.8", "4.4.4.4:54" ],
-
-  // all existent environments  
   "envs": [
     {
       "name": "", // empty string is the default enviroment
       "hostnames": [ // all local hostnames entries
         {
-          // (optional) used to control it will be automatically generated if not passed
-          "id": 1,
+          "id": 1, // (optional) used to control it will be automatically generated if not passed
+          "type": "A",
           "hostname": "github.com",
           "ip": "192.168.0.1",
           "ttl": 255 // how many seconds cache this entry
@@ -30,42 +134,32 @@ __Version 2__
       ]
     }
   ],
-  "activeEnv": "", // the current environment keyname 
-  "webServerPort": 5380, // web admin port, when null the default value is used, see --help option
-  "dnsServerPort": 53, // dns server port, when null the default value is used
+  "activeEnv": "", 
+  "webServerPort": 5380, 
+  "dnsServerPort": 53, 
   "logLevel": "INFO",
-  "logFile": "console" // where the log will be written,
-  "registerContainerNames": false, // if should register container name / service name as a hostname
-  "domain": "docker", // The container names domain
-  "dpsNetwork": false, // if should create a bridge network for dps container
-  "dpsNetworkAutoConnect": false, // if should connect all containers to dps container
-  "defaultDns" : true, // if must be set as the default DNS
-  "hostMachineHostname" : "host.docker", // hostname to solve machine IP
-  "serverProtocol" : "UDP_TCP", // protocol to start the dns server
-  "dockerHost" : null, // docker host address, default value is SO dependent,
-  "resolvConfOverrideNameServers": true // If must comment all existing nameservers at resolv.conf file or just put DPS at the first place.
+  "logFile": "console",
+  "registerContainerNames": false, 
+  "domain": "docker", 
+  "dpsNetwork": false,
+  "dpsNetworkAutoConnect": false, 
+  "defaultDns": true,
+  "hostMachineHostname" : "host.docker", 
+  "serverProtocol": "UDP_TCP", 
+  "dockerHost": null,
+  "resolvConfOverrideNameServers": true,
+  "noRemoteServers": false
 }
 ```
 
-### Environment variable configuration
+## Environment variable configuration
 
 Boolean values
 
 > You can use `1` or `true` (case insensitive) to specify which the flag is activated, any other
 > value will be considered false.
 
-| VARIBLE                            | DESCRIPTION                                                                                      | DEFAULT VALUE                                                                                     |
-|------------------------------------|--------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------|
-| MG_RESOLVCONF                      | Linux resolvconf or systemd-resolved path to set DPS as default DNS                              | /host/etc/systemd/resolved.conf,/host/etc/resolv.conf,/etc/systemd/resolved.conf,/etc/resolv.conf |
-| MG_LOG_LEVEL                       |                                                                                                  | INFO                                                                                              |
-| MG_LOG_FILE                        | Path where to logs will be stored                                                                | console                                                                                           |
-| MG_REGISTER_CONTAINER_NAMES        | if should register container name / service name as a hostname                                   | false                                                                                             |
-| MG_HOST_MACHINE_HOSTNAME           | hostname to solve host machine IP                                                                | host.docker                                                                                       |
-| MG_DOMAIN                          | The container names domain (requires MG_REGISTER_CONTINER_NAMES=TRUE)                            | .docker                                                                                           |
-| MG_DOCKER_HOST                     | Docker host address                                                                              | depends on the SO                                                                                 |
-| MG_RESOLVCONF_OVERRIDE_NAMESERVERS | If must comment all existing nameservers at resolv.conf file or just put DPS at the first place. | true                                                                                              |
-
-### Terminal configuration
+## Terminal configuration
 Run one of the commands below to get the commandline instructions help:
 
 ```bash
@@ -75,3 +169,6 @@ $ ./dns-proxy-server --help
 ```bash
 $ docker run defreitas/dns-proxy-server --help
 ```
+
+[1]: {{%relref "2-features/auto-configuration-as-default-dns/_index.md" %}}
+[2]: {{%relref "2-features/local-entries/_index.md" %}}
diff --git a/gradle.properties b/gradle.properties
index 88a28d14..d4660e5b 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,1 +1,1 @@
-version=3.15.10-snapshot
+version=3.15.11-snapshot
diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/Config.java b/src/main/java/com/mageddo/dnsproxyserver/config/Config.java
index 1100ee42..d91fd6ba 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/config/Config.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/config/Config.java
@@ -85,6 +85,8 @@ public class Config {
 
   private boolean resolvConfOverrideNameServers;
 
+  private boolean noRemoteServers;
+
   public void resetConfigFile() {
     try {
       Files.deleteIfExists(this.getConfigPath());
diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/Configs.java b/src/main/java/com/mageddo/dnsproxyserver/config/Configs.java
index d0c36f5d..d297a5ff 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/config/Configs.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/config/Configs.java
@@ -68,6 +68,9 @@ public class Configs {
       .resolvConfOverrideNameServers(firstNonNullRequiring(
         env.getResolvConfOverrideNameServers(), json.getResolvConfOverrideNameServers(), flag.getResolvConfOverrideNameServers()
       ))
+      .noRemoteServers(firstNonNullRequiring(
+        env.getNoRemoteServers(), json.getNoRemoteServers(), flag.getNoRemoteServers()
+      ))
       .build();
   }
 
diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/entrypoint/ConfigEnv.java b/src/main/java/com/mageddo/dnsproxyserver/config/entrypoint/ConfigEnv.java
index de0a2f2e..6f7cb7de 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/config/entrypoint/ConfigEnv.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/config/entrypoint/ConfigEnv.java
@@ -16,7 +16,9 @@ public class ConfigEnv {
   public static final String MG_WORK_DIR = "MG_WORK_DIR";
 
   public static final String MG_RESOLVCONF = "MG_RESOLVCONF";
+
   public static final String MG_LOG_FILE = "MG_LOG_FILE";
+
   public static final String MG_LOG_LEVEL = "MG_LOG_LEVEL";
 
   /**
@@ -25,14 +27,22 @@ public class ConfigEnv {
   public static final String MG_REGISTER_CONTAINER_NAMES = "MG_REGISTER_CONTAINER_NAMES";
 
   public static final String MG_HOST_MACHINE_HOSTNAME = "MG_HOST_MACHINE_HOSTNAME";
+
   public static final String MG_DOMAIN = "MG_DOMAIN";
+
   public static final String MG_DPS_NETWORK = "MG_DPS_NETWORK";
+
   public static final String MG_DPS_NETWORK_AUTO_CONNECT = "MG_DPS_NETWORK_AUTO_CONNECT";
+
   public static final String DEFAULT_RESOLV_CONF_PATH =
     "/host/etc/systemd/resolved.conf,/host/etc/resolv.conf,/etc/systemd/resolved.conf,/etc/resolv.conf";
+
   public static final String MG_DOCKER_HOST = "MG_DOCKER_HOST";
+
   public static final String MG_RESOLVCONF_OVERRIDE_NAMESERVERS = "MG_RESOLVCONF_OVERRIDE_NAMESERVERS";
 
+  private static final String MG_NO_REMOTE_SERVERS = "MG_NO_REMOTE_SERVERS";
+
   private Path currentPath;
   private String resolvConfPath;
   private String logFile;
@@ -44,6 +54,7 @@ public class ConfigEnv {
   private Boolean dpsNetworkAutoConnect;
   private URI dockerHost;
   private Boolean resolvConfOverrideNameServers;
+  private Boolean noRemoteServers;
 
   public static ConfigEnv fromEnv() {
     return ConfigEnv
@@ -59,6 +70,7 @@ public class ConfigEnv {
       .dpsNetworkAutoConnect(Envs.getBooleanOrNull(MG_DPS_NETWORK_AUTO_CONNECT))
       .dockerHost(UriUtils.createURI(Envs.getStringOrNull(MG_DOCKER_HOST)))
       .resolvConfOverrideNameServers(Envs.getBooleanOrNull(MG_RESOLVCONF_OVERRIDE_NAMESERVERS))
+      .noRemoteServers(Envs.getBooleanOrNull(MG_NO_REMOTE_SERVERS))
       .build();
   }
 
diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/entrypoint/ConfigFlag.java b/src/main/java/com/mageddo/dnsproxyserver/config/entrypoint/ConfigFlag.java
index 8c36eddf..0aa37fba 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/config/entrypoint/ConfigFlag.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/config/entrypoint/ConfigFlag.java
@@ -137,13 +137,25 @@ public class ConfigFlag implements Callable<Boolean> {
   @Option(
     names = {"-resolvconf-override-name-servers", "--resolvconf-override-name-servers"},
     description = """
-      If must comment all existing nameservers at resolv.conf file or just put DPS at the first place.
+      If must comment all existing nameservers at resolv.conf file
+      or just put DPS at the first place.
       (default true)
        """,
     defaultValue = "true"
   )
   private Boolean resolvConfOverrideNameServers;
 
+  @Option(
+    names = {"-no-remote-servers", "--no-remote-servers"},
+    description = """
+      If remote servers like 8.8.8.8 must be disabled and only local solvers like docker
+      containers or local db must be used.
+      (default false)
+       """,
+    defaultValue = "false"
+  )
+  private Boolean noRemoteServers;
+
   @Option(
     names = {"-help", "--help"},
     description = "This message (default false)",
diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/entrypoint/ConfigJson.java b/src/main/java/com/mageddo/dnsproxyserver/config/entrypoint/ConfigJson.java
index 6637ff87..a0910ede 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/config/entrypoint/ConfigJson.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/config/entrypoint/ConfigJson.java
@@ -40,4 +40,6 @@ public interface ConfigJson {
   URI getDockerHost();
 
   Boolean getResolvConfOverrideNameServers();
+
+  Boolean getNoRemoteServers();
 }
diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/entrypoint/ConfigJsonV1.java b/src/main/java/com/mageddo/dnsproxyserver/config/entrypoint/ConfigJsonV1.java
index 3d72e13f..36fb0e65 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/config/entrypoint/ConfigJsonV1.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/config/entrypoint/ConfigJsonV1.java
@@ -87,6 +87,11 @@ public class ConfigJsonV1 implements ConfigJson {
     return null;
   }
 
+  @Override
+  public Boolean getNoRemoteServers() {
+    return null;
+  }
+
   public ConfigJsonV2 toConfigV2() {
     return new ConfigJsonV2()
       .setDomain(this.getDomain())
diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/entrypoint/ConfigJsonV2.java b/src/main/java/com/mageddo/dnsproxyserver/config/entrypoint/ConfigJsonV2.java
index 2c5d008e..8b7c1ed8 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/config/entrypoint/ConfigJsonV2.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/config/entrypoint/ConfigJsonV2.java
@@ -55,6 +55,8 @@ public class ConfigJsonV2 implements ConfigJson {
 
   private Boolean resolvConfOverrideNameServers;
 
+  private Boolean noRemoteServers;
+
   @JsonIgnore
   public List<IpAddr> getRemoteDnsServers() {
     return this.remoteDnsServers
@@ -69,7 +71,6 @@ public class ConfigJsonV2 implements ConfigJson {
     return ConfigJsonV2EnvsConverter.toDomainEnvs(this._envs);
   }
 
-
   @Data
   @Accessors(chain = true)
   public static class Env {
diff --git a/src/main/java/com/mageddo/dnsproxyserver/quarkus/Instances.java b/src/main/java/com/mageddo/dnsproxyserver/quarkus/Instances.java
index 59475830..4b311dfd 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/quarkus/Instances.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/quarkus/Instances.java
@@ -1,12 +1,15 @@
 package com.mageddo.dnsproxyserver.quarkus;
 
+import com.mageddo.dnsproxyserver.di.InstanceImpl;
+
 import javax.enterprise.inject.Instance;
 import java.util.List;
 import java.util.Set;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 public class Instances {
-  public static  <T> List<T> toList(Instance<T> instance) {
+  public static <T> List<T> toList(Instance<T> instance) {
     return instance
       .stream()
       .toList()
@@ -19,4 +22,8 @@ public class Instances {
       .collect(Collectors.toSet())
       ;
   }
+
+  public static <T> Instance<T> of(T... instances) {
+    return new InstanceImpl<>(Stream.of(instances).toList());
+  }
 }
diff --git a/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/Solver.java b/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/Solver.java
index 529eba63..342a384c 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/Solver.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/Solver.java
@@ -10,4 +10,8 @@ public interface Solver {
   default String name() {
     return ClassUtils.getSimpleName(getClass());
   }
+
+  default boolean is(String name){
+    return this.name().equals(name);
+  }
 }
diff --git a/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverCache.java b/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverCache.java
index ab410cc9..cc43e0b8 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverCache.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverCache.java
@@ -5,7 +5,6 @@ import com.mageddo.commons.lang.Objects;
 import com.mageddo.commons.lang.tuple.Pair;
 import com.mageddo.dnsproxyserver.server.dns.Messages;
 import com.mageddo.dnsproxyserver.server.dns.solver.CacheName.Name;
-import lombok.NonNull;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.xbill.DNS.Message;
@@ -26,7 +25,6 @@ public class SolverCache {
 
   private final LruTTLCache cache = new LruTTLCache(2048, Duration.ofSeconds(5), false);
 
-  @NonNull
   private final Name name;
 
   public Message handle(Message query, Function<Message, Response> delegate) {
diff --git a/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverCachedRemote.java b/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverCachedRemote.java
index e9c20afa..35482b76 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverCachedRemote.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverCachedRemote.java
@@ -14,6 +14,8 @@ import java.time.Duration;
 @Singleton
 public class SolverCachedRemote implements Solver {
 
+  public static final String NAME = "SolverCachedRemote";
+
   private final SolverRemote solverRemote;
   private final SolverCache solversCache;
 
@@ -34,4 +36,9 @@ public class SolverCachedRemote implements Solver {
     });
     return Objects.mapOrNull(res, response -> response.withTTL(Duration.ofSeconds(20)));
   }
+
+  @Override
+  public String name() {
+    return NAME;
+  }
 }
diff --git a/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverDelegate.java b/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverDelegate.java
index 20cd52a5..210e8a27 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverDelegate.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverDelegate.java
@@ -12,7 +12,8 @@ import javax.inject.Singleton;
 import java.time.Duration;
 
 /**
- * When {@link SolverLocalDB} finds a wildcard hostname, delegate the found hostname to this class.
+ * Query all configured solvers to solve a cname address.
+ * @see SolverLocalDB
  */
 @Slf4j
 @Singleton
@@ -27,7 +28,8 @@ public class SolverDelegate {
     final var cnameAnswer = cnameAnswer(query, entry);
     final var question = Messages.copyQuestionForNowHostname(query, Hostnames.toAbsoluteName(entry.getTarget()));
 
-    for (final var solver : this.solverProvider.getSolversExcludingLocalDB()) {
+    final var solvers = this.solverProvider.getSolversExcluding(SolverLocalDB.class);
+    for (final var solver : solvers) {
       final var res = solver.handle(question);
       if (res != null) {
         log.debug("status=cnameARecordSolved, host={}, r={}", entry.getHostname(), Messages.simplePrint(res));
diff --git a/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverLocalDB.java b/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverLocalDB.java
index 28d82790..b0c49cb2 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverLocalDB.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverLocalDB.java
@@ -15,11 +15,16 @@ import javax.inject.Inject;
 import javax.inject.Singleton;
 import java.time.Duration;
 
+/**
+ * When finds a wildcard hostname, delegate the found hostname to {@link SolverDelegate} class.
+ */
 @Slf4j
 @Singleton
 @AllArgsConstructor(onConstructor = @__({@Inject}))
 public class SolverLocalDB implements Solver {
 
+  public  static final String NAME = "SolverLocalDB";
+
   private final ConfigDAO configDAO;
   private final Lazy<SolverDelegate> solverDelegate;
 
@@ -68,6 +73,11 @@ public class SolverLocalDB implements Solver {
     return null;
   }
 
+  @Override
+  public String name() {
+    return NAME;
+  }
+
   Config.Entry findEntryTo(HostnameQuery host) {
     return this.configDAO.findEntryForActiveEnv(host);
   }
diff --git a/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverMock.java b/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverMock.java
index 97567389..9821cd0b 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverMock.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverMock.java
@@ -12,13 +12,24 @@ import java.util.stream.Stream;
 @Slf4j
 public class SolverMock implements Solver {
 
+  public static final String NAME = "SolverMock";
   private final List<Pair<String, IP>> mocks;
+  private final String name;
 
   public SolverMock(Pair<String, IP>... mocks) {
-    this(Stream.of(mocks).toList());
+    this(NAME, mocks);
+  }
+
+  public SolverMock(String name, Pair<String, IP>... mocks) {
+    this(name, Stream.of(mocks).toList());
   }
 
   public SolverMock(List<Pair<String, IP>> mocks) {
+    this(NAME, mocks);
+  }
+
+  public SolverMock(String name, List<Pair<String, IP>> mocks) {
+    this.name = name;
     this.mocks = mocks;
   }
 
@@ -32,4 +43,9 @@ public class SolverMock implements Solver {
     }
     return null;
   }
+
+  @Override
+  public String name() {
+    return this.name;
+  }
 }
diff --git a/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverProvider.java b/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverProvider.java
index 976f1dd4..3bf97783 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverProvider.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverProvider.java
@@ -1,5 +1,8 @@
 package com.mageddo.dnsproxyserver.server.dns.solver;
 
+import com.mageddo.dnsproxyserver.config.Config;
+import com.mageddo.dnsproxyserver.config.Configs;
+import com.mageddo.utils.Priorities;
 import lombok.extern.slf4j.Slf4j;
 
 import javax.enterprise.inject.Instance;
@@ -12,26 +15,46 @@ import java.util.stream.Collectors;
 @Singleton
 public class SolverProvider {
 
-  private List<Solver> solvers;
+  static final String[] solversOrder = {
+    "SolverSystem",
+    "SolverDocker",
+    SolverLocalDB.NAME,
+    SolverCachedRemote.NAME
+  };
+
+  private final List<Solver> solvers;
 
   @Inject
   public SolverProvider(Instance<Solver> solvers) {
-    this.solvers = sorted(solvers);
+    this(solvers, Configs.getInstance());
   }
 
-  public List<Solver> getSolversExcludingLocalDB() {
-    return this.solvers
-        .stream()
-        .filter(it -> it.getClass() != SolverLocalDB.class)
-        .collect(Collectors.toList())
-        ;
+  public SolverProvider(Instance<Solver> solvers, Config config) {
+    this.solvers = solvers
+      .stream()
+      .sorted(Priorities.comparator(Solver::name, solversOrder))
+      .filter(it -> !(config.isNoRemoteServers() && it.is(SolverCachedRemote.NAME)))
+      .toList()
+    ;
   }
 
   public List<Solver> getSolvers() {
     return this.solvers;
   }
 
-  static List<Solver> sorted(Instance<Solver> solvers) {
-    return Solvers.sorted(solvers.stream().toList());
+  public List<Solver> getSolversExcluding(final Class<?> clazz) {
+    return this.solvers
+      .stream()
+      .filter(it -> it.getClass() != clazz)
+      .collect(Collectors.toList())
+      ;
+  }
+
+  public List<String> getSolversNames() {
+    return getSolvers()
+      .stream()
+      .map(Solver::name)
+      .toList();
   }
+
 }
diff --git a/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/Solvers.java b/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/Solvers.java
deleted file mode 100644
index 069cd12b..00000000
--- a/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/Solvers.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.mageddo.dnsproxyserver.server.dns.solver;
-
-import com.mageddo.utils.Priorities;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Map;
-
-public class Solvers {
-
-  private static final Map<String, Integer> priorities = Priorities.build(
-    "SolverCached", "SolverSystem", "SolverDocker", "SolverLocalDB", "SolverCachedRemote"
-  );
-
-  public static List<Solver> sorted(Collection<Solver> source) {
-    final var solvers = new ArrayList<>(source);
-    solvers.sort(Solvers.comparator());
-    return solvers;
-  }
-
-  public static Comparator<Solver> comparator() {
-    return Comparator.comparing(it -> Priorities.compare(priorities, it.name()));
-  }
-
-}
diff --git a/src/main/java/com/mageddo/utils/Priorities.java b/src/main/java/com/mageddo/utils/Priorities.java
index fcd326ba..e6076882 100644
--- a/src/main/java/com/mageddo/utils/Priorities.java
+++ b/src/main/java/com/mageddo/utils/Priorities.java
@@ -3,12 +3,18 @@ package com.mageddo.utils;
 import org.apache.commons.lang3.Validate;
 import org.apache.commons.lang3.tuple.Pair;
 
+import java.util.Comparator;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
 public class Priorities {
+
+  private Priorities() {
+  }
+
   public static Map<String, Integer> build(String... keys) {
     final var counter = new AtomicInteger();
     return Stream
@@ -22,4 +28,13 @@ public class Priorities {
     Validate.isTrue(priorities.containsKey(name), "Key not found: %s", name);
     return priorities.get(name);
   }
+
+  public static <T> Comparator<T> comparator(Function<T, String> fn, String ... keys) {
+    return comparator(build(keys), fn);
+  }
+
+  public static <T> Comparator<T> comparator(Map<String, Integer> priorities, Function<T, String> fn) {
+    return Comparator.comparing(it -> Priorities.compare(priorities, fn.apply(it)));
+  }
+
 }
diff --git a/src/main/java/com/sun/jna/Native.java b/src/main/java/com/sun/jna/Native.java
index 18ed7989..1aacaaa4 100644
--- a/src/main/java/com/sun/jna/Native.java
+++ b/src/main/java/com/sun/jna/Native.java
@@ -105,6 +105,7 @@ import java.util.logging.Logger;
  * @author Todd Fast, todd.fast@sun.com
  * @author twall@users.sf.net
  */
+@SuppressWarnings("ALL")
 public final class Native implements Version {
 
     private static final Logger LOG = Logger.getLogger(Native.class.getName());
@@ -256,7 +257,7 @@ public final class Native implements Version {
 
     /** Force a dispose when the Native class is GC'd. */
     private static final Object finalizer = new Object() {
-        @Override
+      @Override
         protected void finalize() throws Throwable {
             dispose();
             super.finalize();


Test patch:
diff --git a/src/test/java/com/mageddo/dnsproxyserver/config/flags/ConfigFlagTest.java b/src/test/java/com/mageddo/dnsproxyserver/config/flags/ConfigFlagTest.java
index a9e57cda..14f37e13 100644
--- a/src/test/java/com/mageddo/dnsproxyserver/config/flags/ConfigFlagTest.java
+++ b/src/test/java/com/mageddo/dnsproxyserver/config/flags/ConfigFlagTest.java
@@ -17,7 +17,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 class ConfigFlagTest {
 
   @Test
-  void mustParseDefaultConfigs() throws Exception {
+  void mustParseDefaultConfigs() {
 
     // arrange
     final var args = new String[]{};
diff --git a/src/test/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverDelegateTest.java b/src/test/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverDelegateTest.java
index 9bc90130..43f17368 100644
--- a/src/test/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverDelegateTest.java
+++ b/src/test/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverDelegateTest.java
@@ -37,7 +37,7 @@ class SolverDelegateTest {
 
     doReturn(List.of(SolverMockTemplates.whateverMock("acme.com.br")))
       .when(this.solverProvider)
-      .getSolversExcludingLocalDB();
+      .getSolversExcluding(SolverLocalDB.class);
 
     // act
     final var response = this.delegate.solve(query, cname);
diff --git a/src/test/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverLocalDBCompTest.java b/src/test/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverLocalDBCompTest.java
index e7cc366f..4a688cc8 100644
--- a/src/test/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverLocalDBCompTest.java
+++ b/src/test/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverLocalDBCompTest.java
@@ -43,7 +43,7 @@ class SolverLocalDBCompTest {
 
     // assert
     assertNull(res);
-    verify(this.solverProvider, never()).getSolversExcludingLocalDB();
+    verify(this.solverProvider, never()).getSolversExcluding(SolverLocalDB.class);
 
   }
 
@@ -80,7 +80,7 @@ class SolverLocalDBCompTest {
 
     doReturn(SolverTemplates.mockTo192())
         .when(this.solverProvider)
-        .getSolversExcludingLocalDB()
+        .getSolversExcluding(SolverLocalDB.class)
     ;
 
     final var msg = Messages.aQuestion(toAbsoluteName(from));
diff --git a/src/test/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverProviderCompTest.java b/src/test/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverProviderCompTest.java
index 9be788cc..0080bfc9 100644
--- a/src/test/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverProviderCompTest.java
+++ b/src/test/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverProviderCompTest.java
@@ -6,6 +6,7 @@ import testing.ContextSupplier;
 import testing.Events;
 
 import javax.inject.Inject;
+import java.util.Arrays;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
@@ -16,17 +17,15 @@ class SolverProviderCompTest {
   SolverProvider provider;
 
   @Test
-  void mustCreateSolverListInRightOrder(){
+  void mustCreateSolverListInRightOrder() {
 
     // arrange
 
     // act
-    final var names = this.provider.getSolvers()
-      .stream()
-      .map(Solver::name)
-      .toList();
+    final var names = this.provider.getSolversNames();
 
     // assert
-    assertEquals("[SolverSystem, SolverDocker, SolverLocalDB, SolverCachedRemote]", names.toString());
+    assertEquals(Arrays.toString(SolverProvider.solversOrder), names.toString());
   }
+
 }
diff --git a/src/test/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverProviderTest.java b/src/test/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverProviderTest.java
new file mode 100644
index 00000000..f7720575
--- /dev/null
+++ b/src/test/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverProviderTest.java
@@ -0,0 +1,39 @@
+package com.mageddo.dnsproxyserver.server.dns.solver;
+
+import com.mageddo.dnsproxyserver.config.Configs;
+import com.mageddo.dnsproxyserver.quarkus.Instances;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
+@ExtendWith(MockitoExtension.class)
+class SolverProviderTest {
+
+  @Test
+  void mustDisableRemoteSolversWhenNoRemoteServersOptionIsEnabled() {
+    // arrange
+    final var config = spy(Configs.getInstance());
+
+    doReturn(true)
+      .when(config)
+      .isNoRemoteServers();
+
+    final var solvers = Instances.<Solver>of(
+      new SolverMock("SolverSystem"),
+      new SolverMock("SolverDocker"),
+      new SolverMock("SolverLocalDB"),
+      new SolverMock("SolverCachedRemote")
+    );
+    final var provider = spy(new SolverProvider(solvers, config));
+
+    // act
+    final var names = provider.getSolversNames();
+
+    // assert
+    assertEquals("[SolverSystem, SolverDocker, SolverLocalDB]", names.toString());
+  }
+}
diff --git a/src/test/java/dagger/sheath/CtxWrapper.java b/src/test/java/dagger/sheath/CtxWrapper.java
index dd39da91..26ffc955 100644
--- a/src/test/java/dagger/sheath/CtxWrapper.java
+++ b/src/test/java/dagger/sheath/CtxWrapper.java
@@ -7,6 +7,7 @@ import org.apache.commons.lang3.reflect.FieldUtils;
 
 import java.lang.reflect.Field;
 import java.util.Objects;
+import java.util.function.Consumer;
 
 @Slf4j
 public class CtxWrapper {
@@ -71,10 +72,10 @@ public class CtxWrapper {
     return ctx;
   }
 
-  public void initializeWithMockOrThrows(Class<?> type) {
+  public void initializeWithOrThrows(Class<?> type, Consumer<ProviderWrapper> c) {
     final var provider = this.findProviderFor(type);
     Validate.notNull(provider, "No provider found for: %s, try create an @IntoMap bind", type);
-    provider.mock();
+    c.accept(provider);
   }
 
   ProviderWrapper findProviderFor(Class<?> type) {
diff --git a/src/test/java/dagger/sheath/InjectSpy.java b/src/test/java/dagger/sheath/InjectSpy.java
new file mode 100644
index 00000000..e29ae295
--- /dev/null
+++ b/src/test/java/dagger/sheath/InjectSpy.java
@@ -0,0 +1,15 @@
+package dagger.sheath;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * When used on a field of a test class, the field becomes a Mockito spy,
+ * that is then used to mock the normal scoped bean which the field represents
+ */
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface InjectSpy {
+}
diff --git a/src/test/java/dagger/sheath/junit/DaggerExtension.java b/src/test/java/dagger/sheath/junit/DaggerExtension.java
index 1cfc6364..40a4b61b 100644
--- a/src/test/java/dagger/sheath/junit/DaggerExtension.java
+++ b/src/test/java/dagger/sheath/junit/DaggerExtension.java
@@ -3,9 +3,10 @@ package dagger.sheath.junit;
 import dagger.sheath.CtxWrapper;
 import dagger.sheath.EventHandler;
 import dagger.sheath.InjectMock;
+import dagger.sheath.InjectSpy;
 import dagger.sheath.NopSupplier;
+import dagger.sheath.ProviderWrapper;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.Validate;
 import org.apache.commons.lang3.reflect.FieldUtils;
 import org.apache.commons.lang3.reflect.MethodUtils;
 import org.junit.jupiter.api.extension.AfterAllCallback;
@@ -22,7 +23,10 @@ import org.mockito.internal.util.MockUtil;
 import javax.inject.Inject;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Field;
+import java.util.List;
 import java.util.Optional;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
 import java.util.function.Supplier;
 
 import static org.junit.jupiter.api.extension.ExtensionContext.Namespace.create;
@@ -32,7 +36,7 @@ import static org.junit.jupiter.api.extension.ExtensionContext.Namespace.create;
  */
 @Slf4j
 public class DaggerExtension implements Extension, BeforeAllCallback, AfterAllCallback,
-    BeforeEachCallback, ParameterResolver {
+  BeforeEachCallback, ParameterResolver {
 
   private final static ExtensionContext.Namespace DAGGER = create("dagger2");
   private final static String
@@ -60,7 +64,7 @@ public class DaggerExtension implements Extension, BeforeAllCallback, AfterAllCa
 
   @Override
   public void beforeEach(ExtensionContext context) throws Exception {
-    injectMocks(context);
+    injectMocksAndSpies(context);
     injectFields(context);
     resetMocks(context);
     if (!Boolean.TRUE.equals(context.getStore(DAGGER).get(DAGGER_SETUP, Boolean.class))) {
@@ -100,24 +104,52 @@ public class DaggerExtension implements Extension, BeforeAllCallback, AfterAllCa
     }
   }
 
-  void injectMocks(ExtensionContext context) {
+  void injectMocksAndSpies(ExtensionContext context) {
     final var testInstances = context.getRequiredTestInstances().getAllInstances();
     final var ctxWrapper = findCtxWrapper(context);
-    for (Object instance : testInstances) {
-
-      final var fields = FieldUtils.getFieldsListWithAnnotation(instance.getClass(), InjectMock.class);
-      for (Field field : fields) {
-        try {
-
-          log.debug("status=injectMockField, field={} {}", field.getType().getSimpleName(), field.getName());
-          ctxWrapper.initializeWithMockOrThrows(field.getType());
-          final var mock = ctxWrapper.get(field.getType());
-          Validate.isTrue(MockUtil.isMock(mock), "Mock didn't work for type: %s", field.getType());
-          FieldUtils.writeField(field, instance, mock, true);
+    for (Object testInstance : testInstances) {
+
+      {
+        final var fields = FieldUtils.getFieldsListWithAnnotation(testInstance.getClass(), InjectMock.class);
+        inject(
+          ctxWrapper,
+          testInstance,
+          fields,
+          ProviderWrapper::mock,
+          MockUtil::isMock
+        );
+      }
+      {
+        final var fields = FieldUtils.getFieldsListWithAnnotation(testInstance.getClass(), InjectSpy.class);
+        inject(
+          ctxWrapper,
+          testInstance,
+          fields,
+          ProviderWrapper::spy,
+          MockUtil::isSpy
+        );
+      }
+    }
+  }
 
-        } catch (IllegalAccessException e) {
-          throw new IllegalStateException(e);
+  private static void inject(
+    CtxWrapper ctxWrapper,
+    Object instance,
+    List<Field> fields,
+    Consumer<ProviderWrapper> initializer,
+    Predicate<Object> validator
+  ) {
+    for (Field field : fields) {
+      try {
+        log.debug("status=injectMockSpyInField, field={} {}", field.getType().getSimpleName(), field.getName());
+        ctxWrapper.initializeWithOrThrows(field.getType(), initializer);
+        final var mock = ctxWrapper.get(field.getType());
+        if (!validator.test(mock)) {
+          throw new IllegalStateException(String.format("Mock/Stub didn't work for type: %s", field.getType()));
         }
+        FieldUtils.writeField(field, instance, mock, true);
+      } catch (IllegalAccessException e) {
+        throw new IllegalStateException(e);
       }
     }
   }
@@ -179,22 +211,22 @@ public class DaggerExtension implements Extension, BeforeAllCallback, AfterAllCa
     final var parent = context.getParent().get();
     parent.getStore(DAGGER).put(DAGGER_SETUP, true);
     log.debug(
-        "status=triggeredSetupEvent, context={}, parent={}, root={}",
-        context.hashCode(), parent.hashCode(), context.getRoot().hashCode()
+      "status=triggeredSetupEvent, context={}, parent={}, root={}",
+      context.hashCode(), parent.hashCode(), context.getRoot().hashCode()
     );
   }
 
   private void triggerAfterAllEvent(ExtensionContext context) {
     findLifecycleHander(context).afterAll(findCtx(context));
     log.debug(
-        "status=triggeredAfterAllEvent"
+      "status=triggeredAfterAllEvent"
     );
   }
 
   private static EventHandler findLifecycleHander(ExtensionContext context) {
     return context
-        .getStore(DAGGER)
-        .get(DAGGER_LIFECYCLE_HANDLER, EventHandler.class);
+      .getStore(DAGGER)
+      .get(DAGGER_LIFECYCLE_HANDLER, EventHandler.class);
   }
 
   static Object createInstance(Class<?> clazz) throws Exception {
diff --git a/src/test/resources/config-json-v1-test/002.json b/src/test/resources/config-json-v1-test/002.json
index 8ce00c35..0faf2485 100644
--- a/src/test/resources/config-json-v1-test/002.json
+++ b/src/test/resources/config-json-v1-test/002.json
@@ -20,6 +20,7 @@
   "hostMachineHostname" : null,
   "logFile" : "console",
   "logLevel" : "DEBUG",
+  "noRemoteServers": null,
   "registerContainerNames" : false,
   "remoteDnsServers" : [ "8.8.8.8", "4.4.4.4" ],
   "version" : 2,
diff --git a/src/test/resources/configs-test/001.json b/src/test/resources/configs-test/001.json
index afc8b827..d14a3bf6 100644
--- a/src/test/resources/configs-test/001.json
+++ b/src/test/resources/configs-test/001.json
@@ -7,6 +7,7 @@
   "hostMachineHostname" : "host.docker",
   "logFile" : "console",
   "logLevel" : "INFO",
+  "noRemoteServers" : false,
   "registerContainerNames" : false,
   "remoteDnsServers" : [ {
     "ip" : "8.8.8.8",
diff --git a/src/test/resources/configs-test/002.json b/src/test/resources/configs-test/002.json
index f6e57b25..8d39a227 100644
--- a/src/test/resources/configs-test/002.json
+++ b/src/test/resources/configs-test/002.json
@@ -20,6 +20,7 @@
   "hostMachineHostname" : null,
   "logFile" : null,
   "logLevel" : null,
+  "noRemoteServers" : null,
   "registerContainerNames" : null,
   "remoteDnsServers" : [ ],
   "version" : 2,
diff --git a/src/test/resources/configs-test/004.json b/src/test/resources/configs-test/004.json
index d2fa674e..5606c155 100644
--- a/src/test/resources/configs-test/004.json
+++ b/src/test/resources/configs-test/004.json
@@ -7,6 +7,7 @@
   "hostMachineHostname" : "batata.com",
   "logFile" : "/var/log/dns-proxy-server.log",
   "logLevel" : "DEBUG",
+  "noRemoteServers" : false,
   "registerContainerNames" : true,
   "remoteDnsServers" : [ {
     "ip" : "8.8.8.8",
diff --git a/src/test/resources/flags-test/001.json b/src/test/resources/flags-test/001.json
index 03c2be25..c24c479e 100644
--- a/src/test/resources/flags-test/001.json
+++ b/src/test/resources/flags-test/001.json
@@ -9,6 +9,7 @@
   "publishServicePort" : true,
   "logToFile" : "console",
   "logLevel" : "INFO",
+  "noRemoteServers" : false,
   "registerContainerNames" : false,
   "hostMachineHostname" : "host.docker",
   "domain" : "docker",
diff --git a/src/test/resources/flags-test/002.txt b/src/test/resources/flags-test/002.txt
index 4bbb387e..e7c6ccea 100644
--- a/src/test/resources/flags-test/002.txt
+++ b/src/test/resources/flags-test/002.txt
@@ -1,6 +1,6 @@
-Usage: <main class> [-default-dns] [-dps-network] [-dps-network-auto-connect] [-help] [-register-container-names]
-                    [-resolvconf-override-name-servers] [-service-publish-web-port] [-version]
-                    [-conf-path=<configPath>] [-docker-host=<dockerHost>] [-domain=<domain>]
+Usage: <main class> [-default-dns] [-dps-network] [-dps-network-auto-connect] [-help] [-no-remote-servers]
+                    [-register-container-names] [-resolvconf-override-name-servers] [-service-publish-web-port]
+                    [-version] [-conf-path=<configPath>] [-docker-host=<dockerHost>] [-domain=<domain>]
                     [-host-machine-hostname=<hostMachineHostname>] [-log-file=<logToFile>] [-log-level=<logLevel>]
                     [-server-port=<dnsServerPort>] [-service=<service>] [-web-server-port=<webServerPort>]
       -conf-path, --conf-path=<configPath>
@@ -30,11 +30,16 @@ Usage: <main class> [-default-dns] [-dps-network] [-dps-network-auto-connect] [-
 
       -log-level, --log-level=<logLevel>
                             Log Level ERROR, WARNING, INFO, DEBUG (default INFO)
+      -no-remote-servers, --no-remote-servers
+                            If remote servers like 8.8.8.8 must be disabled and only local solvers like docker
+                            containers or local db must be used.
+                            (default false)
+
       -register-container-names, --register-container-names
                             If must register container name / service name as host in DNS server (default false)
       -resolvconf-override-name-servers, --resolvconf-override-name-servers
-                            If must comment all existing nameservers at resolv.conf file or just put DPS at the first
-                              place.
+                            If must comment all existing nameservers at resolv.conf file
+                            or just put DPS at the first place.
                             (default true)
 
       -server-port, --server-port=<dnsServerPort>
diff --git a/src/test/resources/json-configs-test/001.json b/src/test/resources/json-configs-test/001.json
index 810960e8..162be974 100644
--- a/src/test/resources/json-configs-test/001.json
+++ b/src/test/resources/json-configs-test/001.json
@@ -24,6 +24,7 @@
   "hostMachineHostname": null,
   "logFile": "console",
   "logLevel": "DEBUG",
+  "noRemoteServers" : null,
   "registerContainerNames": false,
   "remoteDnsServers": [
     "8.8.8.8",