Skip to content

Mock DNS server #5819

@vietj

Description

@vietj

Describe the feature

We are currently using Apache DNS as a mock DNS server for some of our tests that requires it. The project seems not really active anymore and does not support latest RFCs.

We can reimplement easily such mock server using Vertx + Netty directly.

diff --git a/vertx-core/src/test/java/io/vertx/test/dns/MockDnsServer.java b/vertx-core/src/test/java/io/vertx/test/dns/MockDnsServer.java
new file mode 100644
index 000000000..0326aea41
--- /dev/null
+++ b/vertx-core/src/test/java/io/vertx/test/dns/MockDnsServer.java
@@ -0,0 +1,77 @@
+package io.vertx.test.dns;
+
+import io.netty.bootstrap.Bootstrap;
+import io.netty.bootstrap.ServerBootstrap;
+import io.netty.buffer.ByteBufUtil;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.*;
+import io.netty.channel.nio.NioIoHandler;
+import io.netty.channel.socket.DatagramChannel;
+import io.netty.channel.socket.nio.NioDatagramChannel;
+import io.netty.channel.socket.nio.NioServerSocketChannel;
+import io.netty.handler.codec.dns.*;
+import io.netty.util.NetUtil;
+
+import java.nio.charset.StandardCharsets;
+
+public class MockDnsServer {
+
+  private static final byte[] QUERY_RESULT = new byte[]{(byte) 192, (byte) 168, 1, 1};
+
+  private int port;
+  private Channel channel;
+
+  public MockDnsServer(int port) {
+    this.port = port;
+  }
+
+  private static void handleQueryResp(DatagramDnsResponse msg) {
+    if (msg.count(DnsSection.QUESTION) > 0) {
+      DnsQuestion question = msg.recordAt(DnsSection.QUESTION, 0);
+      System.out.printf("name: %s%n", question.name());
+    }
+    for (int i = 0, count = msg.count(DnsSection.ANSWER); i < count; i++) {
+      DnsRecord record = msg.recordAt(DnsSection.ANSWER, i);
+      if (record.type() == DnsRecordType.A) {
+        //just print the IP after query
+        DnsRawRecord raw = (DnsRawRecord) record;
+        System.out.println(NetUtil.bytesToIpAddress(ByteBufUtil.getBytes(raw.content())));
+      }
+    }
+  }
+
+  public void start() throws Exception {
+
+    Bootstrap bootstrap = new Bootstrap()
+      .group(new MultiThreadIoEventLoopGroup(NioIoHandler.newFactory()))
+      .channel(NioDatagramChannel.class)
+      .handler(new ChannelInitializer<DatagramChannel>() {
+        @Override
+        protected void initChannel(DatagramChannel ch) throws Exception {
+          ChannelPipeline p = ch.pipeline();
+          p.addLast(new DatagramDnsQueryDecoder())
+            .addLast(new DatagramDnsResponseEncoder())
+            .addLast(new SimpleChannelInboundHandler<DatagramDnsQuery>() {
+              @Override
+              protected void channelRead0(ChannelHandlerContext ctx, DatagramDnsQuery msg) {
+                DnsRecord dnsRecord = msg.recordAt(DnsSection.QUESTION);
+
+                DnsResponse response = new DatagramDnsResponse(msg.recipient(), msg.sender(), msg.id(), DnsOpCode.QUERY);
+                response.addRecord(DnsSection.QUESTION, dnsRecord);
+                response.addRecord(DnsSection.ANSWER, new DefaultDnsRawRecord("vertx.io", DnsRecordType.A, 100, Unpooled.copiedBuffer(new byte[]{ 10, 0, 0, 1 })));
+
+                ctx.writeAndFlush(response);
+
+//                try {
+//                  handleQueryResp(msg);
+//                } finally {
+//                  ctx.close();
+//                }
+              }
+            });
+        }
+      });
+    channel = bootstrap.bind("127.0.0.1", port).channel();
+    System.out.println("bound on " + port);
+  }
+}
diff --git a/vertx-core/src/test/java/io/vertx/tests/dns/DNSTest.java b/vertx-core/src/test/java/io/vertx/tests/dns/DNSTest.java
index eb3981cb2..70dea89ad 100644
--- a/vertx-core/src/test/java/io/vertx/tests/dns/DNSTest.java
+++ b/vertx-core/src/test/java/io/vertx/tests/dns/DNSTest.java
@@ -21,6 +21,7 @@ import io.vertx.core.dns.MxRecord;
 import io.vertx.core.dns.SrvRecord;
 import io.vertx.test.core.TestUtils;
 import io.vertx.test.core.VertxTestBase;
+import io.vertx.test.dns.MockDnsServer;
 import io.vertx.test.fakedns.FakeDNSServer;
 import io.vertx.test.netty.TestLoggerFactory;
 import org.apache.directory.server.dns.messages.DnsMessage;
@@ -107,8 +108,12 @@ public class DNSTest extends VertxTestBase {
   @Test
   public void testResolveA() throws Exception {
     final String ip = "10.0.0.1";
-    dnsServer.testResolveA(ip);
-    DnsClient dns = prepareDns();
+//    dnsServer.testResolveA(ip);
+
+    MockDnsServer server = new MockDnsServer(53531);
+    server.start();
+
+    DnsClient dns = vertx.createDnsClient(new DnsClientOptions().setPort(53531).setHost("127.0.0.1"));
 
     dns
       .resolveA("vertx.io")
diff --git a/vertx-core/src/test/java/module-info.java b/vertx-core/src/test/java/module-info.java
index c9554a80b..24721aeb2 100644
--- a/vertx-core/src/test/java/module-info.java
+++ b/vertx-core/src/test/java/module-info.java
@@ -42,6 +42,7 @@ open module io.vertx.core.tests {
   requires io.netty.resolver.dns;
   requires io.netty.handler.proxy;
   requires io.netty.codec.http3;
+  requires io.netty.codec.dns;
 
   provides VerticleFactory with ClasspathVerticleFactory, io.vertx.tests.vertx.AccessEventBusFromInitVerticleFactory;
 

Contribution

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions