Network and DNSLocal DNSIntermediateApproximately 2 hoursLab

Create a WireGuard plus Split DNS Lab for Secure Remote Access to Self-Hosted Services

Build a two-client WireGuard lab with split DNS, explicit routing, resolver selection, firewall/NAT boundaries, and deterministic failover/teardown tests.

Last reviewed4/30/2026
Technitium DNS setupssplit DNS for self-hosted servicessecondary DNS and failover
Linux (Ubuntu)WireGuardTechnitium DNS

Expected Outcome

A reproducible remote-access lab where a client reaches only the intended private subnets through WireGuard, resolves an internal test name through the lab DNS server, and can prove which route and resolver are in use.

Assumptions

  • One Linux WireGuard server with a stable LAN address and sudo access

  • One external or isolated client that can reach the server UDP endpoint

  • A private test subnet and an internal DNS zone such as lab.example that cannot collide with production

  • Control of the server firewall/NAT and the client route/DNS configuration

  • A maintenance-safe lab network; do not reuse production VPN keys

Bill of Materials

  • WireGuard installed on the server

  • A DNS server (e.g., Technitium DNS) configured on the same or a different server

  • Client devices to test the VPN and DNS setup

Build Steps

  1. Define the topology before installing anything

    Document server WAN/LAN addresses, UDP listen port, client tunnel address, allowed private subnet, internal DNS server address, and whether internet traffic stays outside the tunnel. This lab uses split tunneling: only the lab subnet and lab DNS path traverse WireGuard.

  2. Create server and client keys with restrictive permissions

    Generate unique WireGuard key pairs on each endpoint. Store private keys with owner-only permissions and record only public keys in the lab notes.

  3. Configure the server tunnel and forwarding boundary

    Create wg0 with one tunnel subnet, the client peer public key, and an AllowedIPs entry limited to the client's tunnel address. Enable IP forwarding only on the lab server and add the minimum firewall/NAT rules needed for the client to reach the private lab subnet.

  4. Configure the client for split routing and split DNS

    Set Endpoint to the server's reachable address, AllowedIPs to the private lab subnet plus the lab DNS server if needed, and configure the client resolver so lab.example is sent to the lab DNS service while normal public lookups continue through the normal resolver. Do not use 0.0.0.0/0 in this split-tunnel exercise.

  5. Create one internal DNS record and prove resolver selection

    Create a test record such as app01.lab.example that returns a private lab address. Query the internal resolver directly, then query through the client's normal resolver path and confirm the internal suffix is resolved by the intended DNS server.

  6. Validate route, tunnel, and application path separately

    Use wg show to verify handshake and byte counters, inspect the client route table for the private subnet, query the internal DNS name, and connect to a harmless TCP/HTTP service on the private target. A successful ping alone is not sufficient.

  7. Run negative tests and restore state

    Temporarily stop the lab DNS service to prove only internal-name resolution fails, then restore it. Temporarily disable the WireGuard interface to prove the private route disappears while normal internet access remains. Re-enable, retest, then remove lab firewall/NAT rules and keys when finished.

Validation

  • wg show reports the expected peer handshake and increasing transfer counters

  • The client route table sends only the intended private subnet through WireGuard

  • app01.lab.example resolves to the expected private address through the intended lab DNS server

  • A TCP/HTTP request to the private test service succeeds through the tunnel

  • Disabling lab DNS breaks the internal name without breaking unrelated public DNS

  • Disabling the tunnel removes private reachability while ordinary non-lab connectivity remains intact

Troubleshooting

  • No handshake: verify endpoint address/UDP port, keys, peer AllowedIPs, and firewall before changing routing

  • Handshake but no private traffic: compare forwarding, server routes, NAT requirement, and return route

  • Private IP works but name fails: inspect client suffix/resolver selection and query the lab DNS server directly

  • Name resolves but service fails: test the resolved address/port and target firewall rather than changing DNS

Cleanup or Rollback

  • Bring down wg0 on client and server

  • Remove lab-only firewall/NAT rules and forwarding changes if they were created solely for this exercise

  • Delete disposable private keys and test DNS records

  • Confirm the client no longer has the lab route or split-DNS rule

Next Improvements

  • Consider adding additional clients to the WireGuard configuration.

  • Explore further DNS configurations for advanced setups.

Keep Moving

Build on what you just completed

Continue with a related Lab or return to this build path for a different implementation.