How I Developed a DNS Server to Explore Networking: The NexoralDNS Story
System-level engineer building reliable backend systems with a focus on performance, correctness, and real-world constraints. I work across APIs, databases, networking, and infrastructure, enjoy understanding how systems behave under load and failure, and write to break down complex backend and distributed-systems concepts through practical, real-world learnings.
Why This Project Exists (The Real Reason)
NexoralDNS didn’t start as a “product idea”.
It started with curiosity.
When I first tried to learn how DNS servers work—from blogs and YouTube—the explanations felt abstract:
UDP call on port 53
recursive resolver
authoritative response
domain hierarchy
I understood the words, but not the flow.
So I asked myself a simple question:
If DNS is just a UDP server listening on port 53, what happens if I build one myself?
That question is where NexoralDNS was born.
The First Curiosity That Changed Everything
DNS uses UDP, and Node.js has dgram.
So I thought:
What if I start a UDP server on port 53?
What if I point my router’s DNS to my laptop’s private IP?
Will it actually resolve domains?
I tried it.
It worked.
That single experiment changed my understanding completely.
At that moment, DNS stopped being “magic infrastructure” and became:
Packets → Buffers → Logic → Response
And once that clicked, I went deeper.
What NexoralDNS Actually Provides
NexoralDNS is a LAN-focused, programmable DNS server built to understand and control DNS behavior at a low level.
It currently provides:
A custom DNS server handling UDP 53
Domain parsing from raw Buffer data
Recursive domain hierarchy understanding (
sub → root → TLD)Rule-based domain control (block, allow, redirect)
Admin panel to control DNS behavior
Internal service-to-service communication using a custom TCP broker
Automatic rebinding when IP changes via DHCP signals
It’s not meant to replace Cloudflare or public resolvers.
It’s meant for offices, labs, learning, and internal networks.
Architecture (Why Multi-Folder Matters)
The project is intentionally multi-folder, because I designed it for future evolution.
Folder Breakdown
Core DNS Engine
Handles UDP packets
Parses DNS queries from raw buffers
Generates responses
Uses Node Cluster for concurrency
DHCP
Listens for IP changes
Detects when DNS server IP changes
Notifies other services to rebind port 53
Broker
Custom TCP-based message broker
Built to understand service notifications
Replaced RabbitMQ intentionally to learn internals
Server
Admin APIs written in Fastify
Controls rules, domains, and configs
Web
Admin UI built with Next.js
Visual control over DNS rules and analytics
This separation makes one thing very important:
If I replace the Core DNS engine with Golang later,
I only need to change the core — not the Web or Admin layers.
That decision was deliberate.
Why I Chose Node.js Over Golang or Rust (Honestly)
Let me be blunt.
I didn’t choose Node.js because it’s the “best” language for DNS.
I chose it because:
I know Node.js deeply
I understand async behavior
I can move fast with logic
I trust myself to debug it
At the beginning, confidence matters more than performance.
I knew:
If I picked Golang without deep networking confidence, I’d stall
If I picked Rust, I’d fight the compiler instead of learning DNS
My belief:
Logic > Language
Languages can change.
Understanding packet flow, recursion, and hierarchy is permanent.
What I Learned While Building This
This project taught me things no tutorial ever could:
1. DNS Parsing from Raw Buffers
How queries arrive as binary
How to extract:
Domain name
Query type (A, AAAA, CNAME, etc.)
How compression pointers work
2. Recursive Domain Hierarchy
Why DNS is not just a lookup
How delegation works
How recursion actually flows internally
3. UDP Is Stateless (And That Matters)
No connection
No retry guarantee
You must respond fast
4. Node Cluster for DNS
To improve performance:
I used Node.js Cluster
Spread UDP load across CPU cores
With this setup, NexoralDNS handled:
~7,000 QPS, measured using
dnsperf
That number surprised me.
Performance Reality Check
Let’s be honest again.
Node.js at ~7k QPS: good
Golang at the same logic: 10k+ QPS easily
I know this.
That’s why my future plan is clear:
Rewrite the Core DNS handler in Golang
Keep Admin, Web, and Control layers intact
Before that:
I need to understand networking deeply — not just write faster code.
I’m learning Go now, slowly and correctly.
Why I Built My Own TCP Broker
Before using RabbitMQ, I asked:
Do I really understand how message brokers work?
So I built one.
A simple TCP-based message broker that:
Allows one service to notify another
Used by DHCP → Web → DNS engine
Handles rebinding and runtime coordination
This taught me:
Why brokers exist
Where RabbitMQ adds value
Where custom solutions make sense
This wasn’t about replacing RabbitMQ.
It was about earning the right to use it knowingly.
The Bigger Picture
NexoralDNS is not about DNS alone.
It’s about:
Understanding networking fundamentals
Removing fear from “core systems”
Proving that curiosity + experiments beat tutorials
I didn’t build this to impress anyone.
I built it because I wanted answers.
And now I have them.
What’s Next
Rewrite Core DNS engine in Golang
Improve rule engine performance
Better analytics for LAN usage
Hardening broker communication
Deeper recursion optimizations
This project already did its job:
It turned DNS from theory into intuition.
And that was the real goal.

