Repository: mageddo/dns-proxy-server
Pull request #399 (2023-03-24 00:52:11)

IP classes refactoring to support IPV6


Patch:
diff --git a/build.gradle b/build.gradle
index c1e643f5..7103ef15 100644
--- a/build.gradle
+++ b/build.gradle
@@ -36,7 +36,7 @@ dependencies {
   implementation 'org.graalvm.sdk:graal-sdk:22.3.1'
   implementation('jakarta.enterprise:jakarta.enterprise.cdi-api:2.0.2')
   implementation('jakarta.ws.rs:jakarta.ws.rs-api:2.1.6')
-  implementation('com.mageddo.commons:commons-lang:0.1.15')
+  implementation('com.mageddo.commons:commons-lang:0.1.16')
   implementation('org.apache.commons:commons-exec:1.3')
 
   implementation('ch.qos.logback:logback-classic:1.4.5')
diff --git a/gradle.properties b/gradle.properties
index 32fe7907..152b47ff 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,1 +1,1 @@
-version=3.15.3-snapshot
+version=3.15.4-snapshot
diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/Config.java b/src/main/java/com/mageddo/dnsproxyserver/config/Config.java
index 73a94ac9..a60315b9 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/config/Config.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/config/Config.java
@@ -1,8 +1,9 @@
 package com.mageddo.dnsproxyserver.config;
 
 import com.mageddo.dnsproxyserver.config.entrypoint.LogLevel;
-import com.mageddo.dnsproxyserver.server.dns.IpAddr;
+import com.mageddo.net.IpAddr;
 import com.mageddo.dnsproxyserver.server.dns.SimpleServer;
+import com.mageddo.net.IP;
 import lombok.Builder;
 import lombok.NonNull;
 import lombok.RequiredArgsConstructor;
@@ -155,6 +156,10 @@ public class Config {
        */
       private final int type;
 
+      public boolean isNot(Type ... types) {
+        return isNot(this.type, types);
+      }
+
       public static Type of(Integer code) {
         for (final var t : values()) {
           if (Objects.equals(t.type, code)) {
@@ -186,6 +191,15 @@ public class Config {
           .collect(Collectors.toSet())
           .contains(current);
       }
+
+      public IP.Version toVersion() {
+        return switch (this) {
+          case A -> IP.Version.IPV4;
+          case AAAA -> IP.Version.IPV6;
+          default -> throw new IllegalStateException("Unexpected value: " + this);
+        };
+      }
+
     }
   }
 }
diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/Configs.java b/src/main/java/com/mageddo/dnsproxyserver/config/Configs.java
index 5aeeac2f..7d5c934e 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/config/Configs.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/config/Configs.java
@@ -7,7 +7,7 @@ import com.mageddo.dnsproxyserver.config.entrypoint.ConfigJson;
 import com.mageddo.dnsproxyserver.config.entrypoint.ConfigProps;
 import com.mageddo.dnsproxyserver.config.entrypoint.JsonConfigs;
 import com.mageddo.dnsproxyserver.config.entrypoint.LogLevel;
-import com.mageddo.dnsproxyserver.server.dns.IpAddr;
+import com.mageddo.net.IpAddr;
 import com.mageddo.dnsproxyserver.server.dns.SimpleServer;
 import com.mageddo.dnsproxyserver.utils.Numbers;
 import com.mageddo.utils.Files;
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 223cfa62..8038d176 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/config/entrypoint/ConfigJson.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/config/entrypoint/ConfigJson.java
@@ -1,7 +1,7 @@
 package com.mageddo.dnsproxyserver.config.entrypoint;
 
 import com.mageddo.dnsproxyserver.config.Config;
-import com.mageddo.dnsproxyserver.server.dns.IpAddr;
+import com.mageddo.net.IpAddr;
 import com.mageddo.dnsproxyserver.server.dns.SimpleServer;
 
 import java.net.URI;
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 6441c1bf..7f1241a3 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/config/entrypoint/ConfigJsonV1.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/config/entrypoint/ConfigJsonV1.java
@@ -3,7 +3,7 @@ package com.mageddo.dnsproxyserver.config.entrypoint;
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.mageddo.dnsproxyserver.config.Config;
-import com.mageddo.dnsproxyserver.server.dns.IpAddr;
+import com.mageddo.net.IpAddr;
 import com.mageddo.dnsproxyserver.server.dns.SimpleServer;
 import lombok.Data;
 import lombok.NoArgsConstructor;
diff --git a/src/main/java/com/mageddo/dnsproxyserver/config/entrypoint/ConfigJsonV1EnvsConverter.java b/src/main/java/com/mageddo/dnsproxyserver/config/entrypoint/ConfigJsonV1EnvsConverter.java
index f02b5acf..aa191e07 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/config/entrypoint/ConfigJsonV1EnvsConverter.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/config/entrypoint/ConfigJsonV1EnvsConverter.java
@@ -1,7 +1,7 @@
 package com.mageddo.dnsproxyserver.config.entrypoint;
 
 import com.mageddo.dnsproxyserver.config.Config;
-import com.mageddo.dnsproxyserver.server.dns.IpAddr;
+import com.mageddo.net.IpAddr;
 
 import java.util.List;
 
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 1502cc9e..d83e1cc7 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/config/entrypoint/ConfigJsonV2.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/config/entrypoint/ConfigJsonV2.java
@@ -4,7 +4,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.mageddo.dnsproxyserver.config.Config;
 import com.mageddo.dnsproxyserver.config.Config.Entry.Type;
-import com.mageddo.dnsproxyserver.server.dns.IpAddr;
+import com.mageddo.net.IpAddr;
 import com.mageddo.dnsproxyserver.server.dns.SimpleServer;
 import lombok.Data;
 import lombok.experimental.Accessors;
diff --git a/src/main/java/com/mageddo/dnsproxyserver/dnsconfigurator/DnsConfigurator.java b/src/main/java/com/mageddo/dnsproxyserver/dnsconfigurator/DnsConfigurator.java
index 97e8846c..3ef9ec9f 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/dnsconfigurator/DnsConfigurator.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/dnsconfigurator/DnsConfigurator.java
@@ -1,6 +1,6 @@
 package com.mageddo.dnsproxyserver.dnsconfigurator;
 
-import com.mageddo.dnsproxyserver.server.dns.IpAddr;
+import com.mageddo.net.IpAddr;
 
 public interface DnsConfigurator {
 
diff --git a/src/main/java/com/mageddo/dnsproxyserver/dnsconfigurator/DnsConfiguratorDefault.java b/src/main/java/com/mageddo/dnsproxyserver/dnsconfigurator/DnsConfiguratorDefault.java
index 13ddc6d4..61d96735 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/dnsconfigurator/DnsConfiguratorDefault.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/dnsconfigurator/DnsConfiguratorDefault.java
@@ -1,6 +1,6 @@
 package com.mageddo.dnsproxyserver.dnsconfigurator;
 
-import com.mageddo.dnsproxyserver.server.dns.IpAddr;
+import com.mageddo.net.IpAddr;
 import com.mageddo.dnsproxyserver.utils.Dns;
 import com.mageddo.net.Network;
 import lombok.extern.slf4j.Slf4j;
diff --git a/src/main/java/com/mageddo/dnsproxyserver/dnsconfigurator/DnsConfiguratorOSX.java b/src/main/java/com/mageddo/dnsproxyserver/dnsconfigurator/DnsConfiguratorOSX.java
index 887757a4..7d487941 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/dnsconfigurator/DnsConfiguratorOSX.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/dnsconfigurator/DnsConfiguratorOSX.java
@@ -1,7 +1,7 @@
 package com.mageddo.dnsproxyserver.dnsconfigurator;
 
 import com.mageddo.dnsproxyserver.dnsconfigurator.linux.DnsConfiguratorLinux;
-import com.mageddo.dnsproxyserver.server.dns.IpAddr;
+import com.mageddo.net.IpAddr;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 
diff --git a/src/main/java/com/mageddo/dnsproxyserver/dnsconfigurator/DnsConfigurators.java b/src/main/java/com/mageddo/dnsproxyserver/dnsconfigurator/DnsConfigurators.java
index 7fd4b211..5814fe10 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/dnsconfigurator/DnsConfigurators.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/dnsconfigurator/DnsConfigurators.java
@@ -5,7 +5,7 @@ import com.mageddo.dnsproxyserver.config.Config;
 import com.mageddo.dnsproxyserver.config.Configs;
 import com.mageddo.dnsproxyserver.di.StartupEvent;
 import com.mageddo.dnsproxyserver.dnsconfigurator.linux.DnsConfiguratorLinux;
-import com.mageddo.dnsproxyserver.server.dns.IpAddr;
+import com.mageddo.net.IpAddr;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.exec.OS;
diff --git a/src/main/java/com/mageddo/dnsproxyserver/dnsconfigurator/DpsIpDiscover.java b/src/main/java/com/mageddo/dnsproxyserver/dnsconfigurator/DpsIpDiscover.java
index f8c2f46d..b5f97442 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/dnsconfigurator/DpsIpDiscover.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/dnsconfigurator/DpsIpDiscover.java
@@ -2,8 +2,8 @@ package com.mageddo.dnsproxyserver.dnsconfigurator;
 
 import com.mageddo.dnsproxyserver.docker.DockerDAO;
 import com.mageddo.dnsproxyserver.docker.DpsContainerManager;
+import com.mageddo.net.IP;
 import com.mageddo.net.Networks;
-import com.mageddo.dnsproxyserver.server.dns.IP;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 
diff --git a/src/main/java/com/mageddo/dnsproxyserver/dnsconfigurator/linux/DnsConfiguratorLinux.java b/src/main/java/com/mageddo/dnsproxyserver/dnsconfigurator/linux/DnsConfiguratorLinux.java
index 66db3468..cdef7e09 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/dnsconfigurator/linux/DnsConfiguratorLinux.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/dnsconfigurator/linux/DnsConfiguratorLinux.java
@@ -4,7 +4,7 @@ import com.mageddo.commons.lang.Objects;
 import com.mageddo.dnsproxyserver.config.Configs;
 import com.mageddo.dnsproxyserver.dnsconfigurator.DnsConfigurator;
 import com.mageddo.dnsproxyserver.dnsconfigurator.linux.ResolvFile.Type;
-import com.mageddo.dnsproxyserver.server.dns.IpAddr;
+import com.mageddo.net.IpAddr;
 import com.mageddo.dnsproxyserver.systemd.ResolvedService;
 import com.mageddo.utils.Tests;
 import lombok.RequiredArgsConstructor;
diff --git a/src/main/java/com/mageddo/dnsproxyserver/dnsconfigurator/linux/ResolvconfConfigurator.java b/src/main/java/com/mageddo/dnsproxyserver/dnsconfigurator/linux/ResolvconfConfigurator.java
index 7e44eba9..fdfce5f7 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/dnsconfigurator/linux/ResolvconfConfigurator.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/dnsconfigurator/linux/ResolvconfConfigurator.java
@@ -2,7 +2,7 @@ package com.mageddo.dnsproxyserver.dnsconfigurator.linux;
 
 import com.mageddo.conf.parser.ConfParser;
 import com.mageddo.conf.parser.EntryType;
-import com.mageddo.dnsproxyserver.server.dns.IpAddr;
+import com.mageddo.net.IpAddr;
 import com.mageddo.dnsproxyserver.utils.Dns;
 
 import java.nio.file.Path;
@@ -17,7 +17,7 @@ public class ResolvconfConfigurator {
     ConfParser.process(
         confFile,
         createParser(),
-        new ConfigureDPSHandler(() -> String.format("nameserver %s # dps-entry", addr.getIp().raw()))
+        new ConfigureDPSHandler(() -> String.format("nameserver %s # dps-entry", addr.getIp().toText()))
     );
   }
 
diff --git a/src/main/java/com/mageddo/dnsproxyserver/dnsconfigurator/linux/ResolvedConfigurator.java b/src/main/java/com/mageddo/dnsproxyserver/dnsconfigurator/linux/ResolvedConfigurator.java
index b4bcbb32..6bf984cd 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/dnsconfigurator/linux/ResolvedConfigurator.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/dnsconfigurator/linux/ResolvedConfigurator.java
@@ -2,7 +2,7 @@ package com.mageddo.dnsproxyserver.dnsconfigurator.linux;
 
 import com.mageddo.conf.parser.ConfParser;
 import com.mageddo.conf.parser.EntryType;
-import com.mageddo.dnsproxyserver.server.dns.IpAddr;
+import com.mageddo.net.IpAddr;
 import com.mageddo.dnsproxyserver.utils.Dns;
 
 import java.nio.file.Path;
diff --git a/src/main/java/com/mageddo/dnsproxyserver/docker/ContainerSolvingService.java b/src/main/java/com/mageddo/dnsproxyserver/docker/ContainerSolvingService.java
index 91d76cdb..1ad197af 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/docker/ContainerSolvingService.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/docker/ContainerSolvingService.java
@@ -1,8 +1,8 @@
 package com.mageddo.dnsproxyserver.docker;
 
 import com.github.dockerjava.api.command.InspectContainerResponse;
-import com.mageddo.dnsproxyserver.server.dns.IP;
 import com.mageddo.dnsproxyserver.server.dns.solver.HostnameQuery;
+import com.mageddo.net.IP;
 import com.mageddo.net.Networks;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
diff --git a/src/main/java/com/mageddo/dnsproxyserver/docker/DockerDAO.java b/src/main/java/com/mageddo/dnsproxyserver/docker/DockerDAO.java
index 9a28f2ed..9c9fddd0 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/docker/DockerDAO.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/docker/DockerDAO.java
@@ -2,7 +2,7 @@ package com.mageddo.dnsproxyserver.docker;
 
 import com.github.dockerjava.api.command.InspectContainerResponse;
 import com.github.dockerjava.api.model.Container;
-import com.mageddo.dnsproxyserver.server.dns.IP;
+import com.mageddo.net.IP;
 
 import java.util.List;
 
diff --git a/src/main/java/com/mageddo/dnsproxyserver/docker/DockerDAODefault.java b/src/main/java/com/mageddo/dnsproxyserver/docker/DockerDAODefault.java
index d90cd0a3..9fa6ad4d 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/docker/DockerDAODefault.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/docker/DockerDAODefault.java
@@ -5,7 +5,7 @@ import com.github.dockerjava.api.command.InspectContainerResponse;
 import com.github.dockerjava.api.model.Container;
 import com.github.dockerjava.api.model.Network;
 import com.mageddo.commons.lang.Objects;
-import com.mageddo.dnsproxyserver.server.dns.IP;
+import com.mageddo.net.IP;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 
diff --git a/src/main/java/com/mageddo/dnsproxyserver/docker/DockerDAOMock.java b/src/main/java/com/mageddo/dnsproxyserver/docker/DockerDAOMock.java
index d5917932..4ad99fa5 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/docker/DockerDAOMock.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/docker/DockerDAOMock.java
@@ -2,7 +2,7 @@ package com.mageddo.dnsproxyserver.docker;
 
 import com.github.dockerjava.api.command.InspectContainerResponse;
 import com.github.dockerjava.api.model.Container;
-import com.mageddo.dnsproxyserver.server.dns.IP;
+import com.mageddo.net.IP;
 import lombok.AllArgsConstructor;
 
 import javax.enterprise.inject.Alternative;
diff --git a/src/main/java/com/mageddo/dnsproxyserver/docker/DpsContainerManager.java b/src/main/java/com/mageddo/dnsproxyserver/docker/DpsContainerManager.java
index fd3463a7..a08e78ab 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/docker/DpsContainerManager.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/docker/DpsContainerManager.java
@@ -4,7 +4,7 @@ import com.github.dockerjava.api.DockerClient;
 import com.github.dockerjava.api.model.Container;
 import com.github.dockerjava.api.model.Network;
 import com.mageddo.dnsproxyserver.config.Configs;
-import com.mageddo.dnsproxyserver.server.dns.IP;
+import com.mageddo.net.IP;
 import com.mageddo.net.Networks;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
diff --git a/src/main/java/com/mageddo/dnsproxyserver/json/converter/IPConverter.java b/src/main/java/com/mageddo/dnsproxyserver/json/converter/IPConverter.java
index 5cc2dd5d..598996f7 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/json/converter/IPConverter.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/json/converter/IPConverter.java
@@ -6,7 +6,7 @@ import com.fasterxml.jackson.databind.DeserializationContext;
 import com.fasterxml.jackson.databind.JsonDeserializer;
 import com.fasterxml.jackson.databind.JsonSerializer;
 import com.fasterxml.jackson.databind.SerializerProvider;
-import com.mageddo.dnsproxyserver.server.dns.IP;
+import com.mageddo.net.IP;
 
 import java.io.IOException;
 
@@ -17,7 +17,7 @@ public class IPConverter {
       if (value == null) {
         gen.writeNull();
       } else {
-        gen.writeString(value.raw());
+        gen.writeString(value.toText());
       }
     }
   }
diff --git a/src/main/java/com/mageddo/dnsproxyserver/quarkus/QuarkusConfig.java b/src/main/java/com/mageddo/dnsproxyserver/quarkus/QuarkusConfig.java
index 921562fa..2e25a7d2 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/quarkus/QuarkusConfig.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/quarkus/QuarkusConfig.java
@@ -1,7 +1,7 @@
 package com.mageddo.dnsproxyserver.quarkus;
 
 import com.mageddo.dnsproxyserver.config.Configs;
-import com.mageddo.dnsproxyserver.server.dns.IpAddr;
+import com.mageddo.net.IpAddr;
 import com.mageddo.dnsproxyserver.server.dns.solver.RemoteResolvers;
 import com.mageddo.dnsproxyserver.utils.InetAddresses;
 import dagger.Module;
diff --git a/src/main/java/com/mageddo/dnsproxyserver/server/dns/IP.java b/src/main/java/com/mageddo/dnsproxyserver/server/dns/IP.java
deleted file mode 100644
index 582f439d..00000000
--- a/src/main/java/com/mageddo/dnsproxyserver/server/dns/IP.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package com.mageddo.dnsproxyserver.server.dns;
-
-import com.mageddo.dnsproxyserver.utils.Ips;
-import com.mageddo.utils.Bytes;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.Validate;
-
-public class IP {
-
-  public static final int IPV4_BYTES = 4;
-  public static final int IPV6_BYTES = 16;
-
-  private final String ip;
-  private final Version version;
-
-  public IP(String ip) {
-    this.ip = ip;
-    this.version = Version.IPV4;
-  }
-
-  @Override
-  public String toString() {
-    return this.ip;
-  }
-
-  public String raw() {
-    return this.ip;
-  }
-
-  public byte[] toByteArray() {
-    return Ips.toBytes(this.raw());
-  }
-
-  public Short[] toShortArray() {
-    return Bytes.toUnsignedShortArray(this.toByteArray());
-  }
-
-  public static IP of(String ip) {
-    if (StringUtils.isBlank(ip)) {
-      return null;
-    }
-    return new IP(ip);
-  }
-
-  public static IP of(Short[] ip) {
-    return of(Bytes.toNative(ip));
-  }
-
-  public static IP of(byte[] data) {
-    if (data == null) {
-      return null;
-    }
-    Validate.isTrue(
-      data.length == IPV4_BYTES,
-      "Array of bytes is not a valid IP representation, size must be %d",
-      IPV4_BYTES
-    );
-    return of(String.format(
-      "%d.%d.%d.%d",
-      Byte.toUnsignedInt(data[0]), Byte.toUnsignedInt(data[1]),
-      Byte.toUnsignedInt(data[2]), Byte.toUnsignedInt(data[3])
-    ));
-  }
-
-  public static Short[] toShortArray(String ip) {
-    if (StringUtils.isBlank(ip)) {
-      return null;
-    }
-    return IP.of(ip).toShortArray();
-  }
-
-  public boolean isLoopback() {
-    return this.ip.startsWith("127.");
-  }
-
-  public enum Version {
-    IPV4,
-    IPV6,
-    ;
-
-    public boolean isIpv6() {
-      return this == IPV6;
-    }
-  }
-}
diff --git a/src/main/java/com/mageddo/dnsproxyserver/server/dns/Messages.java b/src/main/java/com/mageddo/dnsproxyserver/server/dns/Messages.java
index a4ac3be4..d0f28ba3 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/server/dns/Messages.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/server/dns/Messages.java
@@ -4,6 +4,7 @@ import com.mageddo.commons.lang.Objects;
 import com.mageddo.dnsproxyserver.config.Config.Entry;
 import com.mageddo.dnsproxyserver.server.dns.solver.Response;
 import com.mageddo.dnsproxyserver.utils.Ips;
+import com.mageddo.net.IP;
 import lombok.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
 import org.xbill.DNS.AAAARecord;
diff --git a/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/HostnameMatcher.java b/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/HostnameMatcher.java
index 9ab26b9f..3d905f90 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/HostnameMatcher.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/HostnameMatcher.java
@@ -1,7 +1,7 @@
 package com.mageddo.dnsproxyserver.server.dns.solver;
 
 import com.mageddo.dnsproxyserver.server.dns.Hostname;
-import com.mageddo.dnsproxyserver.server.dns.IP;
+import com.mageddo.net.IP;
 
 import java.util.List;
 import java.util.function.Function;
diff --git a/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/HostnameQuery.java b/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/HostnameQuery.java
index f058ffe8..fcc688d2 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/HostnameQuery.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/HostnameQuery.java
@@ -1,8 +1,8 @@
 package com.mageddo.dnsproxyserver.server.dns.solver;
 
 import com.mageddo.dnsproxyserver.server.dns.Hostname;
-import com.mageddo.dnsproxyserver.server.dns.IP;
 import com.mageddo.dnsproxyserver.server.dns.Wildcards;
+import com.mageddo.net.IP;
 import lombok.Builder;
 import lombok.EqualsAndHashCode;
 import lombok.NonNull;
diff --git a/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/RemoteResolvers.java b/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/RemoteResolvers.java
index 26213de3..ba28a6b3 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/RemoteResolvers.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/RemoteResolvers.java
@@ -1,6 +1,6 @@
 package com.mageddo.dnsproxyserver.server.dns.solver;
 
-import com.mageddo.dnsproxyserver.server.dns.IpAddr;
+import com.mageddo.net.IpAddr;
 import org.xbill.DNS.Resolver;
 
 import java.util.List;
diff --git a/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverDocker.java b/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverDocker.java
index 4b30095f..f5a50757 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverDocker.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverDocker.java
@@ -4,7 +4,6 @@ import com.mageddo.commons.lang.Objects;
 import com.mageddo.dnsproxyserver.config.Config.Entry.Type;
 import com.mageddo.dnsproxyserver.docker.ContainerSolvingService;
 import com.mageddo.dnsproxyserver.docker.DockerDAO;
-import com.mageddo.dnsproxyserver.server.dns.IP;
 import com.mageddo.dnsproxyserver.server.dns.Messages;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -36,7 +35,7 @@ public class SolverDocker implements Solver {
     }
 
     final var askedHost = Messages.findQuestionHostname(query);
-    final var version = toVersion(Type.of(type));
+    final var version = Type.of(type).toVersion();
     return HostnameMatcher.match(askedHost, version, hostname -> {
       final var ip = this.containerSolvingService.findBestHostIP(hostname);
       return Objects.mapOrNull(
@@ -47,11 +46,4 @@ public class SolverDocker implements Solver {
 
   }
 
-  IP.Version toVersion(Type type) {
-    return switch (type) {
-      case A -> IP.Version.IPV4;
-      case AAAA -> IP.Version.IPV6;
-      default -> throw new IllegalStateException("Unexpected value: " + type);
-    };
-  }
 }
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 8248a69c..e5a38682 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
@@ -3,8 +3,8 @@ package com.mageddo.dnsproxyserver.server.dns.solver;
 import com.mageddo.dnsproxyserver.config.Config;
 import com.mageddo.dnsproxyserver.config.Config.Entry.Type;
 import com.mageddo.dnsproxyserver.config.ConfigDAO;
-import com.mageddo.dnsproxyserver.server.dns.IP;
 import com.mageddo.dnsproxyserver.server.dns.Messages;
+import com.mageddo.net.IP;
 import dagger.Lazy;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
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 c9154a9f..97567389 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
@@ -1,7 +1,7 @@
 package com.mageddo.dnsproxyserver.server.dns.solver;
 
-import com.mageddo.dnsproxyserver.server.dns.IP;
 import com.mageddo.dnsproxyserver.server.dns.Messages;
+import com.mageddo.net.IP;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.tuple.Pair;
 import org.xbill.DNS.Message;
@@ -27,7 +27,7 @@ public class SolverMock implements Solver {
     final var hostname = Messages.findQuestionHostname(query);
     for (final var entry : this.mocks) {
       if (entry.getKey().equalsIgnoreCase(hostname.getValue())) {
-        return Response.of(Messages.aAnswer(query, entry.getValue().raw()));
+        return Response.of(Messages.aAnswer(query, entry.getValue().toText()));
       }
     }
     return null;
diff --git a/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverSystem.java b/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverSystem.java
index 6b5e86a1..f900746b 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverSystem.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverSystem.java
@@ -1,5 +1,6 @@
 package com.mageddo.dnsproxyserver.server.dns.solver;
 
+import com.mageddo.dnsproxyserver.config.Config.Entry.Type;
 import com.mageddo.dnsproxyserver.config.Configs;
 import com.mageddo.dnsproxyserver.server.dns.Messages;
 import com.mageddo.dnsproxyserver.usecase.HostMachineService;
@@ -20,6 +21,11 @@ public class SolverSystem implements Solver {
   @Override
   public Response handle(Message query) {
     final var hostname = Messages.findQuestionHostname(query);
+    final var questionType = Messages.findQuestionType(query);
+    if (questionType.isNot(Type.A, Type.AAAA)) {
+      log.debug("status=unsupportedType, type={}, query={}", questionType, Messages.simplePrint(query));
+      return null;
+    }
     final var config = Configs.getInstance();
     if (hostname.isEqualTo(config.getHostMachineHostname())) { // fixme fazer case com hostname + search domain
       final var ip = this.machineService.findHostMachineIP();
@@ -28,7 +34,7 @@ public class SolverSystem implements Solver {
         return null;
       }
       log.debug("status=solvingHostMachineName, host={}, ip={}", hostname, ip);
-      return Response.of(Messages.aAnswer(query, ip.raw()), Messages.DEFAULT_TTL_DURATION);
+      return Response.of(Messages.aAnswer(query, ip.toText()), Messages.DEFAULT_TTL_DURATION);
     }
     return null;
   }
diff --git a/src/main/java/com/mageddo/dnsproxyserver/server/rest/reqres/HostnameV1.java b/src/main/java/com/mageddo/dnsproxyserver/server/rest/reqres/HostnameV1.java
index a9ab71d0..2b9d77fc 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/server/rest/reqres/HostnameV1.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/server/rest/reqres/HostnameV1.java
@@ -1,7 +1,7 @@
 package com.mageddo.dnsproxyserver.server.rest.reqres;
 
 import com.mageddo.dnsproxyserver.config.Config;
-import com.mageddo.dnsproxyserver.server.dns.IP;
+import com.mageddo.dnsproxyserver.utils.Ips;
 import lombok.Data;
 import lombok.experimental.Accessors;
 import org.apache.commons.lang3.StringUtils;
@@ -22,7 +22,7 @@ public class HostnameV1 {
     return new HostnameV1()
       .setHostname(entry.getHostname())
       .setId(String.valueOf(entry.getId()))
-      .setIp(IP.toShortArray(entry.getIp()))
+      .setIp(Ips.toShortArray(entry.getIp()))
       .setTtl(entry.getTtl())
       .setTarget(entry.getTarget())
       .setType(entry.getType())
@@ -33,7 +33,7 @@ public class HostnameV1 {
     return Config.Entry.builder()
       .hostname(this.hostname)
       .ttl(this.ttl)
-      .ip(this.ip != null ? IP.of(this.ip).raw() : null)
+      .ip(this.ip != null ? Ips.toIp(this.ip).toText() : null)
       .type(this.type)
       .target(this.target)
       .id(StringUtils.isBlank(this.id) ? System.nanoTime() : Long.parseLong(this.id))
diff --git a/src/main/java/com/mageddo/dnsproxyserver/usecase/HostMachineService.java b/src/main/java/com/mageddo/dnsproxyserver/usecase/HostMachineService.java
index a501d007..30b530ae 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/usecase/HostMachineService.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/usecase/HostMachineService.java
@@ -2,7 +2,7 @@ package com.mageddo.dnsproxyserver.usecase;
 
 import com.mageddo.dnsproxyserver.docker.DockerDAO;
 import com.mageddo.dnsproxyserver.docker.DpsContainerManager;
-import com.mageddo.dnsproxyserver.server.dns.IP;
+import com.mageddo.net.IP;
 import com.mageddo.net.Networks;
 import lombok.RequiredArgsConstructor;
 
@@ -30,4 +30,5 @@ public class HostMachineService {
   IP findCurrentMachineIp() {
     return Networks.findCurrentMachineIP();
   }
+
 }
diff --git a/src/main/java/com/mageddo/dnsproxyserver/utils/Dns.java b/src/main/java/com/mageddo/dnsproxyserver/utils/Dns.java
index 5916f75f..ae1ef123 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/utils/Dns.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/utils/Dns.java
@@ -1,6 +1,6 @@
 package com.mageddo.dnsproxyserver.utils;
 
-import com.mageddo.dnsproxyserver.server.dns.IpAddr;
+import com.mageddo.net.IpAddr;
 import org.apache.commons.lang3.Validate;
 
 import java.util.Objects;
diff --git a/src/main/java/com/mageddo/dnsproxyserver/utils/InetAddresses.java b/src/main/java/com/mageddo/dnsproxyserver/utils/InetAddresses.java
index d85f148f..5c333f30 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/utils/InetAddresses.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/utils/InetAddresses.java
@@ -1,6 +1,6 @@
 package com.mageddo.dnsproxyserver.utils;
 
-import com.mageddo.dnsproxyserver.server.dns.IpAddr;
+import com.mageddo.net.IpAddr;
 
 import java.net.InetSocketAddress;
 
@@ -11,6 +11,6 @@ public class InetAddresses {
   }
 
   public static InetSocketAddress toSocketAddress(IpAddr dns) {
-    return new InetSocketAddress(Ips.toAddress(dns.getIp().raw()), dns.getPort());
+    return new InetSocketAddress(Ips.toAddress(dns.getIp().toText()), dns.getPort());
   }
 }
diff --git a/src/main/java/com/mageddo/dnsproxyserver/utils/Ips.java b/src/main/java/com/mageddo/dnsproxyserver/utils/Ips.java
index f4b45da7..566c01ac 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/utils/Ips.java
+++ b/src/main/java/com/mageddo/dnsproxyserver/utils/Ips.java
@@ -1,6 +1,7 @@
 package com.mageddo.dnsproxyserver.utils;
 
-import com.mageddo.dnsproxyserver.server.dns.IP;
+import com.mageddo.net.IP;
+import com.mageddo.utils.Bytes;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.Validate;
 
@@ -45,7 +46,7 @@ public class Ips {
   }
 
   public static InetAddress toAddress(IP ip) {
-    return toAddress(ip.raw());
+    return toAddress(ip.toText());
   }
 
   public static SocketAddress toSocketAddress(String ip, int port) {
@@ -71,4 +72,15 @@ public class Ips {
   public static boolean isIpv4(String v) {
     return !isIpv6(v);
   }
+
+  public static Short[] toShortArray(String ip) {
+    if (StringUtils.isBlank(ip)) {
+      return null;
+    }
+    return IP.of(ip).toShortArray();
+  }
+
+  public static IP toIp(Short[] ip) {
+    return IP.of(Bytes.toNative(ip));
+  }
 }
diff --git a/src/main/java/com/mageddo/net/IP.java b/src/main/java/com/mageddo/net/IP.java
new file mode 100644
index 00000000..7d8509d1
--- /dev/null
+++ b/src/main/java/com/mageddo/net/IP.java
@@ -0,0 +1,40 @@
+package com.mageddo.net;
+
+import java.net.InetAddress;
+
+public interface IP {
+
+  int IPV4_BYTES = 4;
+  int IPV6_BYTES = 16;
+
+  byte[] toByteArray();
+
+  Short[] toShortArray();
+
+  String toText();
+
+  InetAddress toInetAddr();
+
+  Version version();
+
+  static IP of(String ip) {
+    return IpImpl.of(ip);
+  }
+
+  static IP of(byte[] data) {
+    return IpImpl.of(data);
+  }
+
+  boolean isLoopback();
+
+  enum Version {
+
+    IPV4,
+    IPV6,
+    ;
+
+    public boolean isIpv6() {
+      return this == IPV6;
+    }
+  }
+}
diff --git a/src/main/java/com/mageddo/dnsproxyserver/server/dns/IpAddr.java b/src/main/java/com/mageddo/net/IpAddr.java
similarity index 60%
rename from src/main/java/com/mageddo/dnsproxyserver/server/dns/IpAddr.java
rename to src/main/java/com/mageddo/net/IpAddr.java
index e507e02c..d4be2a79 100644
--- a/src/main/java/com/mageddo/dnsproxyserver/server/dns/IpAddr.java
+++ b/src/main/java/com/mageddo/net/IpAddr.java
@@ -1,4 +1,4 @@
-package com.mageddo.dnsproxyserver.server.dns;
+package com.mageddo.net;
 
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
@@ -9,7 +9,6 @@ import lombok.Builder;
 import lombok.NonNull;
 import lombok.Value;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.Validate;
 
 import java.util.regex.Pattern;
 
@@ -17,8 +16,8 @@ import java.util.regex.Pattern;
 @Builder
 public class IpAddr {
 
-  public static final Pattern IP_ADDR_REGEX =
-      Pattern.compile("^(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})((?::(\\d+)|))$");
+  public static final Pattern IPV4_REGEX = Pattern.compile("^([\\.\\d]+)((?::(\\d+)|))$");
+  public static final Pattern IPV6_REGEX = Pattern.compile("^\\[([:\\w]+)\\]((?::(\\d+)|))$");
 
   @NonNull
   @JsonDeserialize(using = IPConverter.Deserializer.class)
@@ -40,7 +39,7 @@ public class IpAddr {
   }
 
   public String getRawIP() {
-    return this.ip.raw();
+    return this.ip.toText();
   }
 
   /***
@@ -49,16 +48,18 @@ public class IpAddr {
    * @return parsed object.
    */
   public static IpAddr of(String addr) {
-    Validate.isTrue(
-        Regexes.matcher(StringUtils.trimToEmpty(addr), IP_ADDR_REGEX).matches(),
-        "Need to pass a valid addr: actual=%s", addr
-    );
-    final var groups = Regexes.groups(addr, IP_ADDR_REGEX);
-    return IpAddr
-        .builder()
-        .ip(IP.of(groups.get(1)))
-        .port(groups.get(3, s -> StringUtils.isBlank(s) ? null : Integer.parseInt(s)))
-        .build();
+    if (StringUtils.isBlank(addr)) {
+      return null;
+    }
+
+    if (Regexes.matches(addr, IPV4_REGEX)) {
+      final var groups = Regexes.groups(addr, IPV4_REGEX);
+      return IpAddr.of(IP.of(groups.get(1)), parsePort(groups.get(3)));
+    } else if (Regexes.matches(addr, IPV6_REGEX)) {
+      final var groups = Regexes.groups(addr, IPV6_REGEX);
+      return IpAddr.of(IP.of(groups.get(1)), parsePort(groups.get(3)));
+    }
+    return IpAddr.of(IP.of(addr));
   }
 
   public static IpAddr of(IP ip) {
@@ -67,10 +68,10 @@ public class IpAddr {
 
   public static IpAddr of(IP ip, Integer port) {
     return IpAddr
-        .builder()
-        .ip(ip)
-        .port(port)
-        .build();
+      .builder()
+      .ip(ip)
+      .port(port)
+      .build();
   }
 
   public static IpAddr of(Byte[] ip) {
@@ -78,7 +79,7 @@ public class IpAddr {
   }
 
   public static IpAddr of(byte[] ip) {
-    return IpAddr.of(IP.of(ip));
+    return IpAddr.of(IpImpl.of(ip));
   }
 
   public static IpAddr of(Integer[] ip) {
@@ -88,4 +89,12 @@ public class IpAddr {
   public boolean hasPort() {
     return this.port != null && this.port > 0;
   }
+
+  private static Integer parsePort(final String s) {
+    if (StringUtils.isBlank(s)) {
+      return null;
+    }
+    return Integer.parseInt(s);
+  }
+
 }
diff --git a/src/main/java/com/mageddo/net/IpImpl.java b/src/main/java/com/mageddo/net/IpImpl.java
new file mode 100644
index 00000000..0cd1304e
--- /dev/null
+++ b/src/main/java/com/mageddo/net/IpImpl.java
@@ -0,0 +1,95 @@
+package com.mageddo.net;
+
+import com.mageddo.dnsproxyserver.utils.Ips;
+import com.mageddo.utils.Bytes;
+import org.apache.commons.lang3.StringUtils;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+class IpImpl implements IP {
+
+  private final InetAddress ip;
+  private final Version version;
+
+  IpImpl(String ip) {
+    this(build(ip));
+  }
+
+  public IpImpl(InetAddress ip) {
+    this.ip = ip;
+    this.version = this.ip.getAddress().length == IP.IPV4_BYTES ? Version.IPV4 : Version.IPV6;
+  }
+
+  @Override
+  public String toString() {
+    return this.ip.getHostAddress();
+  }
+
+  @Override
+  public byte[] toByteArray() {
+    return this.ip.getAddress();
+  }
+
+  @Override
+  public Short[] toShortArray() {
+    return Bytes.toUnsignedShortArray(this.toByteArray());
+  }
+
+  @Override
+  public String toText() {
+    return this.ip.getHostAddress();
+  }
+
+  @Override
+  public InetAddress toInetAddr() {
+    return Ips.toAddress(this);
+  }
+
+  @Override
+  public Version version() {
+    return this.version;
+  }
+
+  public static IpImpl of(String ip) {
+    if (StringUtils.isBlank(ip)) {
+      return null;
+    }
+    return new IpImpl(ip);
+  }
+
+  public static IpImpl of(Short[] ip) {
+    return of(Bytes.toNative(ip));
+  }
+
+  public static IpImpl of(byte[] data) {
+    if (data == null) {
+      return null;
+    }
+    try {
+      return new IpImpl(InetAddress.getByAddress(data));
+    } catch (UnknownHostException e) {
+      throw invalidAddressEx(e);
+    }
+  }
+
+  @Override
+  public boolean isLoopback() {
+    return this.ip.isLoopbackAddress();
+  }
+
+  private static InetAddress build(String ip) {
+    try {
+      return InetAddress.getByName(ip);
+    } catch (UnknownHostException e) {
+      throw invalidAddressEx(e);
+    }
+  }
+
+  static RuntimeException invalidAddressEx(UnknownHostException e) {
+    return new RuntimeException(
+      String.format("Array of bytes is not a valid IP representation: %s", e.getMessage()),
+      e
+    );
+  }
+}
diff --git a/src/main/java/com/mageddo/net/Networks.java b/src/main/java/com/mageddo/net/Networks.java
index fe5b033e..a348043a 100644
--- a/src/main/java/com/mageddo/net/Networks.java
+++ b/src/main/java/com/mageddo/net/Networks.java
@@ -2,7 +2,6 @@ package com.mageddo.net;
 
 import com.github.dockerjava.api.model.Container;
 import com.github.dockerjava.api.model.ContainerNetwork;
-import com.mageddo.dnsproxyserver.server.dns.IP;
 import lombok.SneakyThrows;
 import org.apache.commons.lang3.StringUtils;
 
@@ -38,7 +37,7 @@ public class Networks {
       .filter(it -> it.getAddress().length == IP.IPV4_BYTES) // todo needs a filter to exclude virtual network cards
       .map(it -> IP.of(it.getHostAddress()))
       .sorted(Comparator.comparing(it -> {
-        return it.raw().startsWith("127") ? Integer.MAX_VALUE : 0;
+        return it.toText().startsWith("127") ? Integer.MAX_VALUE : 0;
       }))
       .toList()
       ;


Test patch:
diff --git a/src/test/java/com/mageddo/dnsproxyserver/docker/ContainerSolvingServiceCompTest.java b/src/test/java/com/mageddo/dnsproxyserver/docker/ContainerSolvingServiceCompTest.java
index a4d70b9c..a71e7ef7 100644
--- a/src/test/java/com/mageddo/dnsproxyserver/docker/ContainerSolvingServiceCompTest.java
+++ b/src/test/java/com/mageddo/dnsproxyserver/docker/ContainerSolvingServiceCompTest.java
@@ -1,10 +1,10 @@
 package com.mageddo.dnsproxyserver.docker;
 
 import com.mageddo.dnsproxyserver.di.Context;
-import com.mageddo.dnsproxyserver.server.dns.IP;
 import com.mageddo.dnsproxyserver.templates.IpTemplates;
 import com.mageddo.dnsproxyserver.templates.docker.InspectContainerResponseTemplates;
 import com.mageddo.dnsproxyserver.templates.docker.NetworkTemplates;
+import com.mageddo.net.IP;
 import dagger.sheath.InjectMock;
 import dagger.sheath.junit.DaggerTest;
 import org.junit.jupiter.api.DisplayName;
diff --git a/src/test/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverDockerTest.java b/src/test/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverDockerTest.java
index 9e883034..423ef85b 100644
--- a/src/test/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverDockerTest.java
+++ b/src/test/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverDockerTest.java
@@ -2,10 +2,10 @@ package com.mageddo.dnsproxyserver.server.dns.solver;
 
 import com.mageddo.dnsproxyserver.docker.ContainerSolvingService;
 import com.mageddo.dnsproxyserver.docker.DockerDAO;
-import com.mageddo.dnsproxyserver.server.dns.IP;
 import com.mageddo.dnsproxyserver.templates.HostnameTemplates;
 import com.mageddo.dnsproxyserver.templates.IpTemplates;
 import com.mageddo.dnsproxyserver.templates.MessageTemplates;
+import com.mageddo.net.IP;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
diff --git a/src/test/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverSystemCompTest.java b/src/test/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverSystemCompTest.java
index 9cd12882..331ee9bb 100644
--- a/src/test/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverSystemCompTest.java
+++ b/src/test/java/com/mageddo/dnsproxyserver/server/dns/solver/SolverSystemCompTest.java
@@ -1,8 +1,8 @@
 package com.mageddo.dnsproxyserver.server.dns.solver;
 
-import com.mageddo.dnsproxyserver.server.dns.IP;
 import com.mageddo.dnsproxyserver.server.dns.Messages;
 import com.mageddo.dnsproxyserver.usecase.HostMachineService;
+import com.mageddo.net.IP;
 import dagger.sheath.InjectMock;
 import dagger.sheath.junit.DaggerTest;
 import org.hamcrest.CoreMatchers;
diff --git a/src/test/java/com/mageddo/dnsproxyserver/templates/IpAddrTemplates.java b/src/test/java/com/mageddo/dnsproxyserver/templates/IpAddrTemplates.java
index dea853cb..d7e2d7c2 100644
--- a/src/test/java/com/mageddo/dnsproxyserver/templates/IpAddrTemplates.java
+++ b/src/test/java/com/mageddo/dnsproxyserver/templates/IpAddrTemplates.java
@@ -1,15 +1,23 @@
 package com.mageddo.dnsproxyserver.templates;
 
-import com.mageddo.dnsproxyserver.server.dns.IpAddr;
+import com.mageddo.net.IpAddr;
 
 public class IpAddrTemplates {
 
+  public static final int PORT_54 = 54;
+
+  public static final String LOCAL_54 = "10.10.0.1:54";
+  public static final String LOCAL = "10.10.0.1";
+
+  public static final String LOCAL_IPV6 = IpTemplates.LOCAL_EXTENDED_IPV6;
+  public static final String LOCAL_IPV6_54 = "[2001:db8:1:0:0:0:0:2]:54";
+
   public static IpAddr local() {
-    return IpAddr.of("10.10.0.1");
+    return IpAddr.of(LOCAL);
   }
 
   public static IpAddr localPort54() {
-    return IpAddr.of("10.10.0.1:54");
+    return IpAddr.of(LOCAL_54);
   }
 
   public static IpAddr loopback() {
diff --git a/src/test/java/com/mageddo/dnsproxyserver/templates/IpTemplates.java b/src/test/java/com/mageddo/dnsproxyserver/templates/IpTemplates.java
index 013ee185..9ebf63c7 100644
--- a/src/test/java/com/mageddo/dnsproxyserver/templates/IpTemplates.java
+++ b/src/test/java/com/mageddo/dnsproxyserver/templates/IpTemplates.java
@@ -1,6 +1,6 @@
 package com.mageddo.dnsproxyserver.templates;
 
-import com.mageddo.dnsproxyserver.server.dns.IP;
+import com.mageddo.net.IP;
 
 public class IpTemplates {
 
diff --git a/src/test/java/com/mageddo/dnsproxyserver/templates/SolverMockTemplates.java b/src/test/java/com/mageddo/dnsproxyserver/templates/SolverMockTemplates.java
index 6861a8be..e09fd1fb 100644
--- a/src/test/java/com/mageddo/dnsproxyserver/templates/SolverMockTemplates.java
+++ b/src/test/java/com/mageddo/dnsproxyserver/templates/SolverMockTemplates.java
@@ -1,7 +1,7 @@
 package com.mageddo.dnsproxyserver.templates;
 
-import com.mageddo.dnsproxyserver.server.dns.IP;
 import com.mageddo.dnsproxyserver.server.dns.solver.SolverMock;
+import com.mageddo.net.IP;
 import org.apache.commons.lang3.tuple.Pair;
 
 import java.util.stream.Collectors;
diff --git a/src/test/java/com/mageddo/net/IpAddrTest.java b/src/test/java/com/mageddo/net/IpAddrTest.java
new file mode 100644
index 00000000..0da23e51
--- /dev/null
+++ b/src/test/java/com/mageddo/net/IpAddrTest.java
@@ -0,0 +1,108 @@
+package com.mageddo.net;
+
+import com.mageddo.dnsproxyserver.templates.IpAddrTemplates;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class IpAddrTest {
+
+  @Test
+  void mustParseIpv4AddrWithoutPort(){
+
+    // arrange
+    final var str = IpAddrTemplates.LOCAL;
+
+    // act
+    final var addr = IpAddr.of(str);
+
+    // assert
+    assertNotNull(addr);
+    assertEquals(str, addr.getIp().toText());
+    assertNull(addr.getPort());
+
+  }
+
+  @Test
+  void mustParseIpv4AddrWithPort(){
+
+    // arrange
+    final var str = IpAddrTemplates.LOCAL_54;
+
+    // act
+    final var addr = IpAddr.of(str);
+
+    // assert
+    assertNotNull(addr);
+    assertEquals(IpAddrTemplates.LOCAL, addr.getIp().toText());
+    assertEquals(IpAddrTemplates.PORT_54, addr.getPort());
+
+  }
+
+  @Test
+  void mustParseIpv6AddrWithPort(){
+
+    // arrange
+    final var str = IpAddrTemplates.LOCAL_IPV6_54;
+
+    // act
+    final var addr = IpAddr.of(str);
+
+    // assert
+    assertNotNull(addr);
+    assertEquals(IpAddrTemplates.LOCAL_IPV6, addr.getIp().toText());
+    assertEquals(IpAddrTemplates.PORT_54, addr.getPort());
+
+  }
+
+  @Test
+  void mustParseIpv6AddrWithoutPort(){
+
+    // arrange
+    final var str = IpAddrTemplates.LOCAL_IPV6;
+
+    // act
+    final var addr = IpAddr.of(str);
+
+    // assert
+    assertNotNull(addr);
+    assertEquals(str, addr.getIp().toText());
+    assertNull(addr.getPort());
+
+  }
+
+  @Test
+  void mustLeadWithNullIp(){
+
+    // arrange
+    final String str = null;
+
+    // act
+    final var addr = IpAddr.of(str);
+
+    // assert
+    assertNull(addr);
+
+  }
+
+
+  @Test
+  void mustFailureWithInvalidValue(){
+
+    // arrange
+    final String str = "a";
+
+    // act
+    final var ex = assertThrows(RuntimeException.class, () -> {
+      IpAddr.of(str);
+    });
+
+    // assert
+    assertTrue(ex.getMessage().contains("valid IP"), ex.getMessage());
+
+  }
+}