Beginner

Critical Network Services: DNS, DHCP and NAT

critical · network · services · dns · dhcp · nat · networking · fundamentals · systems · security · cisco · configuring · router · dora · global · hierarchy · hosts · managing · mapping ·...

This reference covers three critical network services that underpin almost every IP network: DHCP (automatic IP address assignment), NAT (Network Address Translation, allowing private networks to reach and be reached from the public internet), and DNS (translating human-readable names into IP addresses). The material builds a complete working lab network step by step, using Cisco routers and Ubuntu Linux servers virtualized inside Cisco Modeling Labs (CML), progressing from basic IP assignment to a fully routed, NAT’d, and name-resolved infrastructure.

Table of Contents


Module 1: Understanding and Configuring DHCP on a Cisco Router

This module covers IP address assignment using DHCP, the Dynamic Host Configuration Protocol (RFC 2131). The lab environment builds toward a complete working network infrastructure, starting with a single DHCP-enabled LAN and expanding to a multi-LAN topology using DHCP relay agents.

DHCP and the DORA Process

Manually assigning an IP address to every device that connects to a network — including mobile devices — is impractical. It requires maintaining a running list of already-assigned addresses and manually releasing them when devices leave the network. DHCP automates this entire process.

DHCP address assignment follows the DORA sequence:

  1. Discover – When a client starts up, it sends an IP broadcast on UDP port 67, looking for any DHCP server on the network.
  2. Offer – One or more DHCP servers can respond with a DHCP offer. This is still an IP broadcast, but it can now target the client’s MAC address (Layer 2 address) directly, because that MAC address was included in the Discover packet.
  3. Request – The client broadcasts a DHCP request back to the network, saying, in effect, “I would like this IP address.” It is still a broadcast, but it targets the MAC address of the server that issued the offer.
  4. Acknowledge – The server responds with an acknowledgement, again as a broadcast but targeted at the client’s MAC address. Once the client receives the acknowledgement, it has an IP address it can use.
sequenceDiagram
    participant C as DHCP Client
    participant S as DHCP Server
    C->>S: 1. DHCP Discover (broadcast, UDP/67)
    S->>C: 2. DHCP Offer (broadcast, targeted at client MAC)
    C->>S: 3. DHCP Request (broadcast, targeted at server MAC)
    S->>C: 4. DHCP Acknowledge (broadcast, targeted at client MAC)
StepMessageDirectionTransportTargeting
1DiscoverClient → NetworkBroadcast, UDP/67None (client has no IP yet)
2OfferServer → NetworkBroadcastTargets client MAC address
3RequestClient → NetworkBroadcastTargets server MAC address
4Acknowledge (ACK)Server → NetworkBroadcastTargets client MAC address

Lab Environment: Cisco Modeling Labs

The labs in this course use Cisco Modeling Labs (CML), available in a free tier, to run virtualized Cisco and Linux operating systems. CML itself runs as a virtual machine, so the host system needs to support nested virtualization.

Reference documentation: https://developer.cisco.com/docs/modeling-labs/cml-free/#cisco-modeling-labs---free

RequirementMinimum
Virtualization supportNested virtualization support in the host CPU
CPU cores4 cores
RAM8 GB

Observing the DORA Process with Wireshark

A practical way to observe DORA on the wire is to capture the traffic with Wireshark, a network protocol analyzer, on a Windows client:

  1. Download and install the Wireshark Windows x64 installer, accepting the GNU Public License and default component selection.
  2. During installation, also install Npcap (from nmap.org) — this is the packet-capture driver Wireshark relies on to actually capture traffic on the wire. USBPcap can be skipped if there are no USB capture devices involved.
  3. Launch Wireshark, select the active network interface, and apply a capture filter for port 67 or port 68 (UDP port 67 is where the DHCP server listens; UDP port 68 is where the DHCP client listens).
  4. Open a PowerShell window alongside Wireshark and check the current IP configuration:
ipconfig
  1. Release the current lease. This immediately tells the DHCP server that the client is finished with its address — note this itself does not trigger a new DORA exchange:
ipconfig /release

After a release, the interface typically falls back to an Automatic Private IP Addressing (APIPA) address in the 169.254.0.0/16 range, which is a strong indicator that no DHCP server is currently reachable.

  1. Trigger the full DORA exchange by renewing the lease:
ipconfig /renew

Wireshark then captures all four DORA packets in sequence: DHCP Discover sent by the client, DHCP Offer returned by the server, DHCP Request sent back by the client, and the final DHCP Acknowledgement from the server — confirming the four-way handshake used to automate IP address assignment.

Bootstrapping DHCP on Cisco Routers

DHCP is not only a Windows or Linux server role — infrastructure devices such as routers and switches are excellent hosts for critical services because they are powered on and available at all times. Cisco routers (and other vendors’ routers) can pick up their configuration through bootstrap files, retrieved either from the network or loaded locally.

The bootstrap configuration for the first router in the lab (Router1) sets the hostname, configures a “backbone” interface that connects to other routers, configures a second interface facing the internal/departmental network, and defines two DHCP pools:

hostname Router1
interface GigabitEthernet0/0
 ip address 192.168.20.1 255.255.255.0
 no shutdown
interface GigabitEthernet0/1
 ip address 192.168.10.1 255.255.255.0
 no shutdown
ip route 192.168.30.0 255.255.255.0 192.168.20.2
ip dhcp excluded-address 192.168.10.1 192.168.10.10
ip dhcp pool LAN_POOL_10
 network 192.168.10.0 255.255.255.0
 default-router 192.168.10.1
 dns-server 8.8.8.8
ip dhcp excluded-address 192.168.30.1 192.168.30.10
ip dhcp pool LAN_POOL_30
 network 192.168.30.0 255.255.255.0
 default-router 192.168.30.1
 dns-server 8.8.8.8
end

Key points in this configuration:

  • GigabitEthernet0/0 is the backbone interface (192.168.20.1) connecting Router1 to other routers.
  • GigabitEthernet0/1 faces the internal/departmental network (192.168.10.1). These two interfaces sit on different subnets.
  • A static route to the 192.168.30.0/24 network is pre-configured, pointing at Router2 (192.168.20.2), even though that network is not directly connected to Router1 and will only exist once Router2 is added.
  • ip dhcp excluded-address reserves the first addresses of each pool (.1.10) for statically-addressed devices such as the router itself or servers.
  • LAN_POOL_10 serves the 192.168.10.0/24 network, advertising Router1 (192.168.10.1) as the default router and a public DNS server (8.8.8.8) initially.
  • LAN_POOL_30 serves the 192.168.30.0/24 network (physically attached to Router2), advertising 192.168.30.1 as the default router, again with 8.8.8.8 as DNS initially. Router1 can manage this remote pool because Router2 will be configured with a DHCP relay pointing back at Router1 (covered later in this module).

Building a Single-LAN DHCP Topology in CML

CML lets you build a network topology visually and inspect its topological layout. The initial single-LAN lab is built as follows:

  1. From the Nodes palette, drag in an IOSv virtual router node and an Ubuntu Linux server node.
  2. Rename the router node to Router1 and the Ubuntu node to Client1 via the node’s Settings tab.
  3. Connect them: right-click on Client1, choose Add Link, and drag the connection to Router1. On the router side, select GigabitEthernet0/1 (not the default 0/0, which is reserved for the backbone network). CML displays the resulting interface names on the canvas (e.g., G0/1 and ens2).
  4. Open the Config tab on Router1 and paste in the bootstrap configuration shown above (from hostname Router1 through end).
  5. Save the configuration, then start the node. Startup can take a few minutes.
  6. Open the console on Router1. During boot, the router will time out trying to reach a network-based configuration source and fall back to the locally-provided configuration.
  7. At the unprivileged prompt, use enable to reach privileged mode, then inspect the interfaces:
Router1> enable
Router1# show ip interface brief

By default the router has four interfaces; two have been configured (20.1 on the backbone, 10.1 on the internal LAN) and the rest remain unassigned.

  1. Check DHCP bindings (command can be abbreviated, e.g. sh ip dhcp bind):
Router1# show ip dhcp binding

With no clients powered on yet, no leases will be shown.

  1. Start Client1. Ubuntu boots as a DHCP client by default. Log in with the default credentials cisco / cisco, then check the assigned address:
ip a

Expected result: 192.168.10.11 — the first usable address in the pool after the excluded range.

  1. Back on Router1, show ip dhcp binding now shows the leased address, the client identifier (the client’s MAC address), and the lease expiration time (24 hours by default, since no explicit lease time was configured in the pool).

Centralizing DHCP with Relay Agents

Rather than configuring and maintaining a DHCP server on every subnet, a DHCP relay agent can forward DHCP requests from a remote subnet to a central DHCP server. This means DHCP only needs to be configured and managed on one server, even though it can service multiple LANs.

To extend the lab, a second router (Router2) is introduced, connected to Router1 over a new “backbone” network (192.168.20.0/24). Router2’s own LAN becomes the 192.168.30.0/24 network — a pool that was already pre-configured on Router1 (LAN_POOL_30). Router2 does not need to run its own DHCP server; it simply relays DHCP requests back to Router1.

Router2’s bootstrap configuration:

hostname Router2
interface GigabitEthernet0/0
 ip address 192.168.20.2 255.255.255.0
 no shutdown
interface GigabitEthernet0/1
 ip address 192.168.30.1 255.255.255.0
 ip helper-address 192.168.20.1
 no shutdown
ip route 0.0.0.0 0.0.0.0 192.168.20.1
end

Key points:

  • GigabitEthernet0/0 is the backbone interface (192.168.20.2), consistently facing the same direction as Router1’s backbone interface.
  • GigabitEthernet0/1 faces the internal network (192.168.30.1), and carries the ip helper-address 192.168.20.1 command — this is the DHCP relay agent configuration. It tells Router2 to forward any DHCP broadcast received on this interface as a unicast to 192.168.20.1 (Router1), which is reachable because both routers share the backbone network.
  • A default route (0.0.0.0 0.0.0.0 via 192.168.20.1) sends any traffic Router2 doesn’t have an explicit route for back through Router1.
flowchart LR
    Client2[Client2 on LAN30] -->|DHCP Discover broadcast| R2[Router2 G0/1]
    R2 -->|Unicast via ip helper-address 192.168.20.1| R1[Router1 - DHCP Server]
    R1 -->|DHCP Offer and Ack for LAN_POOL_30| R2
    R2 -->|Relayed to client| Client2

Building a Multi-LAN DHCP Relay Topology

  1. Add a second IOSv node and rename it Router2; add a second Ubuntu node and rename it Client2.
  2. Link the backbone: right-click Router2, drag a connection to Router1, matching GigabitEthernet0/0 to GigabitEthernet0/0.
  3. Link Client2 to Router2 using GigabitEthernet0/1 as the internal-facing interface.
  4. Paste the Router2 bootstrap configuration into its Config tab, save, and start the node (startup takes a few minutes, same as before).
  5. Start Client2. Log in with cisco / cisco, then check the address:
ip a

Expected result: 192.168.30.11 — the first usable address from the LAN_POOL_30 range, obtained via the relay agent on Router2 even though DHCP is only running on Router1.

  1. Because DHCP is centralized on Router1, both leases are visible from a single point of management:
Router1# show ip dhcp binding

This shows both the 10.11 and 30.11 leases, including each client’s client-identifier (MAC address) and lease expiry time — proof that a single DHCP server, combined with relay agents, can serve multiple LANs.

Overall topology at the end of Module 1:

flowchart LR
    subgraph Router1
      R1G0[G0/0 - Backbone 192.168.20.1]
      R1G1[G0/1 - LAN10 192.168.10.1]
    end
    subgraph Router2
      R2G0[G0/0 - Backbone 192.168.20.2]
      R2G1[G0/1 - LAN30 192.168.30.1 helper-address to R1]
    end
    R1G0 --- R2G0
    R1G1 --- Client1[Client1 192.168.10.11]
    R2G1 --- Client2[Client2 192.168.30.11]

Module 2: Managing Network Address Translation (NAT) on a Router

This module covers routing between the private networks built in Module 1, connecting the lab to the internet, and enabling Network Address Translation (NAT) so private hosts can reach — and, selectively, be reached from — the public internet. It covers Source NAT (SNAT), Destination NAT (DNAT), and Port Mapping (PNAT), along with access control lists that govern who may use NAT.

Routing Fundamentals and Static Routes

A router automatically knows about the networks it is physically connected to. At this point in the lab:

  • Router1 is connected to 192.168.10.0/24 (LAN10) and 192.168.20.0/24 (the backbone), and manages DHCP pools for both 192.168.10.0/24 and 192.168.30.0/24.
  • Router1 has no knowledge of 192.168.30.0/24, because that network is only directly connected to Router2.

Private IP address ranges (such as 192.168.0.0/16) can be reused by anyone, so routers cannot automatically forward or propagate routing information about them across administrative boundaries — the routes must be configured explicitly as static routes.

  • On Router1, a static route sends traffic for the 192.168.30.0/24 network via Router2’s backbone address:
ip route 192.168.30.0 255.255.255.0 192.168.20.2
  • On Router2, rather than pointing explicitly at 192.168.10.0/24, a default route sends any unknown destination back through Router1:
ip route 0.0.0.0 0.0.0.0 192.168.20.1

Each router’s DHCP pool also advertises the local router as the default gateway for its clients (10.1 or 30.1, depending on the subnet).

To inspect the routing table, use show ip route (which can be abbreviated, e.g. sh ip ro, as long as the abbreviation is unambiguous):

CommandPurpose
show ip routeShow the full routing table
show ip route connectedShow only directly-connected networks
show ip route staticShow only statically-configured routes
show ip route 0.0.0.0Show only the default route (if configured)

Verifying Routing and Route Tables

With the lab started (both routers boot faster on subsequent starts since they already have a saved configuration), connectivity can be verified from Client1:

ip a
# 192.168.10.11

ping 192.168.30.11
# Ctrl+C to stop, since ping runs continuously without a count

On Router1:

show ip route            # full table
show ip route connected  # shows 10 and 20 networks
show ip route static     # shows the 30 network (via 192.168.20.2)
show ip route 0.0.0.0    # not present yet: no default route configured on Router1

On Router2:

show ip route            # full table
show ip route static     # only route is the default route, via 192.168.20.1
show ip route connected  # shows 20 and 30 networks
show ip route 0.0.0.0    # default route present: via 192.168.20.1

This confirms end-to-end connectivity between the known, internally-managed networks — but it does not yet provide access to the outside world.

Connecting the Lab to the Internet

To reach the internet, an External Connector node is added in CML:

  1. Drag an External Connector node onto the canvas (this is not a virtual machine — it is simply a connector to the outside world).
  2. Link it to Router1, using GigabitEthernet0/2 (since 0/0 is already used for the backbone network).
  3. Configure the External Connector: set its target to System Bridge (bridging to the physical network the CML VM itself is attached to, rather than the default NAT interface).
  4. Start the External Connector.
  5. Configure Router1’s external-facing interface to obtain an address via DHCP from the outside network:
Router1> enable
Router1# configure terminal
Router1(config)# interface G0/2
Router1(config-if)# ip address dhcp
Router1(config-if)# no shutdown
Router1(config-if)# exit
Router1(config)# exit
Router1# write memory

Verification:

Router1# show ip route 0.0.0.0
# default route via 192.168.4.1 (the lab host's own network router)

Router1# show ip interface brief
# GigabitEthernet0/2 now shows an address such as 192.168.4.28

At this point, Router1 itself can reach the internet:

Router1# ping 8.8.8.8
# Success — Router1 is directly connected to the 192.168.4.0/24 network

However, from Router2:

Router2# ping 8.8.8.8
# No response

Router2 can send packets outward via its default route through Router1, but the response cannot find its way back, because the wider internet has no route back to Router2’s private address (192.168.20.2) — private addressing is not routable across the public internet. This is precisely the problem that Network Address Translation (NAT) solves.

Understanding Source NAT (SNAT)

Source NAT (SNAT) is the most common form of NAT: internal hosts share the router’s single external/public IP address when initiating connections to the internet. This is often referred to as NAT overload, or Port Address Translation (PAT), because multiple internal hosts multiplex their traffic through one public IP address using different source ports.

Configuration proceeds as follows:

  1. Mark the “inside” interfaces (those facing internal networks):
interface GigabitEthernet0/0
 ip nat inside
interface GigabitEthernet0/1
 ip nat inside
  1. Mark the “outside” interface (facing the internet — already configured for ip address dhcp):
interface GigabitEthernet0/2
 ip nat outside
  1. Define which internal networks are permitted to use NAT via an access control list:
access-list 1 permit 192.168.10.0 0.0.0.255
access-list 1 permit 192.168.20.0 0.0.0.255
access-list 1 permit 192.168.30.0 0.0.0.255
  1. Bind the ACL to the outside interface with overload, so the single public address on GigabitEthernet0/2 can be shared by many internal devices:
ip nat inside source list 1 interface GigabitEthernet0/2 overload

Configuring SNAT on a Cisco Router

Only Router1 needs to be configured, since it hosts the external connection. Full command sequence, as entered at the console:

Router1> enable
Router1# configure terminal
Router1(config)# interface G0/0
Router1(config-if)# ip nat inside
Router1(config-if)# exit
Router1(config)# interface G0/1
Router1(config-if)# ip nat inside
Router1(config-if)# exit
! GigabitEthernet0/2 is already configured as "ip nat outside"
Router1(config)# access-list 1 permit 192.168.10.0 0.0.0.255
Router1(config)# access-list 1 permit 192.168.20.0 0.0.0.255
Router1(config)# access-list 1 permit 192.168.30.0 0.0.0.255
Router1(config)# ip nat inside source list 1 interface GigabitEthernet0/2 overload
Router1(config)# end
Router1# write memory

Verification from a client (e.g. Client1 / Ubuntu):

ping 8.8.8.8
# Success — the response comes back through NAT

sudo apt update
# Full two-way communication with package repository servers over the internet

All internal hosts now share Router1’s single external IP address when accessing internet resources.

flowchart LR
    C1[Client 192.168.10.11] -->|"Source: 192.168.10.11"| R1NAT[Router1 NAT Table - SNAT Overload]
    R1NAT -->|"Source: 192.168.4.28 public IP"| Internet((Internet))
    Internet -->|"Destination: 192.168.4.28 port 80 or 22"| R1NAT
    R1NAT -->|"Destination: 192.168.10.11 port 80 or 22 via PNAT"| C1

Understanding Destination NAT (DNAT) and Port Mapping

Destination NAT (DNAT) is the reverse scenario: instead of hiding many internal hosts behind one external IP, multiple public IP addresses on the router’s external interface are each mapped to a specific internal host, making the whole internal server reachable from the outside. For example, a public IP address 203.192.56.12 could be mapped through to internal server 192.168.10.11.

Port Mapping (PNAT), also a form of Destination NAT, is more granular: rather than exposing an entire internal host, only specific services are exposed on the router’s single external IP address, differentiated by port number. For example:

  • Incoming web traffic (port 80) is redirected to the internal web server.
  • Incoming SSH traffic (port 22) is redirected to the internal console/management server.

Example configuration for redirecting incoming HTTP traffic:

Router1> enable
Router1# configure terminal
! Redirect external HTTP (port 80) to the internal web server
Router1(config)# ip nat inside source static tcp 192.168.10.11 80 interface GigabitEthernet0/2 80

The external listening port does not have to match the internal port — for example, the router could listen on 8080 externally while still forwarding to port 80 internally. The same pattern applies to SSH:

Router1(config)# ip nat inside source static tcp 192.168.10.11 22 interface GigabitEthernet0/2 22
NAT typeDirectionPublic IP usageTypical use case
SNAT (Source NAT / overload / PAT)Outbound (internal → internet)Many internal hosts share one public IPGiving internal clients internet access
DNAT (Destination NAT)Inbound (internet → internal)One public IP per internal hostMaking an entire internal server reachable
PNAT (Port Mapping)Inbound (internet → internal)One public IP, differentiated by portExposing specific services (web, SSH) only

Configuring Port Mapping (PNAT) for Private Hosts

On Ubuntu1 (192.168.10.11), first confirm the address and check which services are listening:

ip a
# 192.168.10.11

ss -ntl
# Port 53 (DNS) and Port 22 (SSH) are open

Install a web server so port 80 is also available:

sudo apt install -y apache2

Re-check listening sockets (!ss re-runs the last command beginning with ss):

!ss
# Now listening on port 22 (SSH) and port 80 (Apache web server)

These services are only reachable on the private IP at this point. To expose them externally, configure Port Mapping on Router1:

Router1> enable
Router1# configure terminal
Router1(config)# ip nat inside source static tcp 192.168.10.11 80 interface GigabitEthernet0/2 80
Router1(config)# ip nat inside source static tcp 192.168.10.11 22 interface GigabitEthernet0/2 22
Router1(config)# end
Router1# write memory

Confirm the router’s public-facing address:

Router1# show ip interface brief
# GigabitEthernet0/2: 192.168.4.27 (example address on the lab's outer network)

Verification from an external host:

# Browse to http://192.168.4.27 (default port 80)
# -> The Apache default welcome page is returned, even though the browser
#    connected to the router's IP address, because traffic was forwarded
#    to 192.168.10.11 on port 80.

ssh cisco@192.168.4.27
# Connects successfully; the shell session is running on 192.168.10.11
# even though the client connected to 192.168.4.27.
sequenceDiagram
    participant U as External User
    participant R as Router1 Public IP
    participant S as Ubuntu1 192.168.10.11
    U->>R: HTTP request to PublicIP port 80
    R->>S: Forward to 192.168.10.11 port 80
    S->>R: HTTP response
    R->>U: HTTP response
    U->>R: SSH request to PublicIP port 22
    R->>S: Forward to 192.168.10.11 port 22
    S->>R: SSH session data
    R->>U: SSH session data

Module 2 Summary

Internal routing between the private networks was established using static routes, since private addresses cannot be automatically advertised or propagated between routers. Connecting the lab out to the internet introduced a new problem: the internet does not know how to route back to private addresses. SNAT solves this for outbound, established connections initiated from inside the network, letting internal hosts share the router’s single public IP. Port Mapping (PNAT), a form of Destination NAT, solves the opposite problem — allowing new connections from the internet into the private network, but in a tightly controlled way, exposing only specific services rather than entire hosts.


Module 3: Understanding DNS Fundamentals and the Global DNS Hierarchy

This module explains what happens when a domain name is typed into a browser, tracing the history and structure of the Domain Name System (DNS).

From a Single Hosts File to the Global DNS Hierarchy

Before DNS — and before the modern internet, back when the ARPANET was in use — name resolution relied on a single text file, HOSTS.TXT, containing every known host. Every machine on the network downloaded this file, and it mapped hostnames to IP addresses, since humans generally find names easier to remember than numbers. There was no hierarchy and no distributed system — just one replicated list, standardized as RFC 952.

This approach was workable in 1977, but does not scale: there are now on the order of hundreds of millions of registered domain names, each potentially containing many hosts, adding up to billions of individual entries. This is why the single flat file was replaced by a hierarchical, distributed database: the DNS.

DNS is structured as an inverted tree:

  • At the very top is the root domain.
  • Below that are the top-level domains (TLDs), such as .com, .org, .uk.
  • Below the TLDs are individual domains.

Using dig with the +trace flag shows this resolution process directly: looking up a domain such as example.com first queries the root zone servers, which refer to the .com servers, which in turn refer to the authoritative servers for example.com. A country-code lookup such as example.co.uk follows the same pattern, starting at the root, then to .uk, then to .co.uk, and finally to the domain itself.

flowchart TD
    Root[Root Zone] --> COM[.com TLD]
    Root --> ORG[.org TLD]
    Root --> UK[.uk TLD]
    COM --> Example[example.com]
    UK --> COUK[.co.uk]
    COUK --> ExampleCoUk[example.co.uk]
    Example --> WWW[www.example.com A record]
    Example --> MX[Mail exchanger MX record]
    Example --> NS[Name servers NS record]

DNS is not just about host records. A domain can have several different record types:

Record typePurpose
AMaps a hostname to an IPv4 address (the default record type)
NSIdentifies the name servers authoritative for a domain
MXIdentifies mail exchanger(s) responsible for handling email for a domain, each with a priority
SOAStart of Authority — administrative information about a zone (serial number, refresh/retry/expire timers)

For example, sending email to support@example.com does not resolve the domain’s A record — it looks up the domain’s MX records to find the mail server(s) responsible for handling that domain’s email.

Resolving Names with dig

The dig command is the primary tool for interactively querying DNS and observing how resolution works, typically run from a Linux system:

dig www.example.com

The critical part of the output is the ANSWER SECTION — if no answer section is returned, the record was not found.

For a brief, IP-only response:

dig www.example.com +short

To see the entire resolution path from the root down, use +trace:

dig +trace www.example.com

To force IPv4-only lookups (skip AAAA/IPv6 queries) and page long output:

dig -4 +trace www.example.com | less

Looking up the name servers responsible for a domain:

dig ns example.com +short

Looking up mail servers, where a lower priority number indicates a higher-priority mail server:

dig mx example.com

Looking up standard address records explicitly:

dig a www.example.com
dig flag/usageEffect
dig <name>Full query and response, including the ANSWER SECTION
+shortBrief output — just the resolved value(s)
+traceShow the full resolution path from the root servers down
-4Force IPv4-only lookups
ns <name>Query name server (NS) records
mx <name>Query mail exchanger (MX) records
a <name>Query address (A) records explicitly
@<server>Query a specific DNS server directly

Module 4: Managing DNS on a Linux Server

Having seen how the global DNS hierarchy works, this module sets up an authoritative DNS server for a private zone on a Linux system, using BIND9 on Ubuntu.

Installing and Configuring BIND9 on Ubuntu

On Ubuntu1 (which will act as the DNS server), first refresh package metadata and install BIND along with useful utilities:

sudo apt update
sudo apt install bind9 bind9-utils bind9-dnsutils dnsutils

Three configuration files then need to be edited (a text editor such as vim or nano can be used):

1. /etc/bind/named.conf.options — global server options (recursion, allowed queries, forwarders, DNSSEC, listening interfaces):

// /etc/bind/named.coonf.options
//
options {
    directory "/var/cache/bind";

    recursion yes;
    allow-query { any; };

    forwarders {
        8.8.8.8;
    };

    dnssec-validation auto;

    listen-on { any; };
};

2. /etc/bind/named.conf.local — defines the zone this server is authoritative for:

// /etc/bind/named.conf.local
// Do any local configuration here
//

// Consider adding the 1918 zones here, if they are not used in your
// organization
//include "/etc/bind/zones.rfc1918";

zone "example.lab" {
    type master;
    file "/etc/bind/db.example.lab";
};

3. /etc/bind/db.example.lab — the zone file itself, containing the actual records:

$TTL    604800
@       IN      SOA     ubuntu1.example.lab. admin.example.lab. (
                        2026022501 ; Serial
                        604800     ; Refresh
                        86400      ; Retry
                        2419200    ; Expire
                        604800 )   ; Negative Cache TTL
;

@       IN      NS      ubuntu1.example.lab.

; --- Host Records ---
ubuntu1 IN      A       192.168.10.11
router1 IN      A       192.168.10.1
router2 IN      A       192.168.30.1
ubuntu2 IN      A       192.168.30.11

Key details of the zone file:

  • $TTL 604800 — the default cache time-to-live, in seconds (604,800 seconds = one week, a common default).
  • The SOA (Start of Authority) record declares the primary name server (ubuntu1.example.lab.) and the zone’s administrative contact, followed by:
    • Serial — a change counter, conventionally based on the date plus a revision number for that day (e.g. 2026022501 = year-month-day + revision 01).
    • Refresh (604800s / 1 week), Retry (86400s / 1 day), Expire (2419200s / 4 weeks), and Negative Cache TTL (604800s / 1 week).
  • The NS record identifies ubuntu1.example.lab. as the authoritative name server for the zone.
  • A records map each host in the lab to its address: ubuntu1 (192.168.10.11, the DNS server itself), router1 (192.168.10.1), router2 (192.168.30.1), and ubuntu2 (192.168.30.11).

After saving all three files, validate the configuration before restarting the service:

named-checkconf
named-checkzone example.lab. /etc/bind/db.example.lab

No output from named-checkconf indicates the syntax is correct; named-checkzone should report the zone as loaded correctly along with its serial number. Once validated, restart the name daemon so it picks up the changes:

sudo systemctl restart named

Test resolution directly against the local server:

dig @127.0.0.1 router1.example.lab
dig @127.0.0.1 router1.example.lab +short
dig @127.0.0.1 router2.example.lab +short
dig @127.0.0.1 ubuntu2.example.lab +short
Zone file elementValue in this labMeaning
$TTL604800 (1 week)Default record cache lifetime
SOA Serial2026022501Change/version counter (date + revision)
SOA Refresh604800 (1 week)How often secondaries check for updates
SOA Retry86400 (1 day)Retry interval if refresh fails
SOA Expire2419200 (4 weeks)When a secondary should stop answering if it cannot reach the primary
SOA Negative Cache TTL604800 (1 week)How long negative (“not found”) answers are cached
NSubuntu1.example.lab.Authoritative name server for the zone
A recordsubuntu1, router1, router2, ubuntu2Host-to-IP mappings for the lab

Integrating the DNS Server with DHCP Pools

Configuring a DNS server does not automatically inform DHCP clients about it — the DHCP pools must be explicitly updated to advertise the new DNS server’s address, and existing clients need to renew their lease (or explicitly refresh DNS settings) before they pick up the change.

On Router1, check the current DHCP configuration, update each pool, and save:

Router1> enable
Router1# show running-config | section dhcp
Router1# configure terminal
Router1(config)# ip dhcp pool LAN_POOL_10
Router1(dhcp-config)# dns-server 192.168.10.11
Router1(dhcp-config)# exit
Router1(config)# ip dhcp pool LAN_POOL_30
Router1(dhcp-config)# dns-server 192.168.10.11
Router1(dhcp-config)# exit
Router1(config)# end
Router1# write memory

Both pools are updated to point clients at 192.168.10.11 (the Ubuntu1 BIND9 server) instead of the public 8.8.8.8 server used initially. Confirm with:

Router1# show running-config | section dhcp

On each Ubuntu client, check the current DNS configuration and force a lease renewal so the new DNS server takes effect immediately, without waiting for the existing lease to expire:

networkctl status
sudo networkctl renew ens2
networkctl status

Before the renewal, networkctl status shows the DNS server as the original public address (8.8.8.8); after renewal, it correctly shows 192.168.10.11. The same steps apply on Ubuntu2.

Final verification — with DNS now resolved automatically via the configured server (no need to specify @server explicitly):

dig ubuntu2.example.lab +short
# 192.168.30.11

Course Summary

The complete lab built a working small network from the ground up:

  • The free tier of Cisco Modeling Labs (CML) was used to run virtualized Cisco routers and Ubuntu Linux hosts without requiring physical hardware.
  • DHCP was configured on Cisco IOS to issue IP addresses automatically, first on a single LAN, then extended with DHCP relay agents so a single central DHCP server could serve multiple LANs.
  • Static routes were configured so each router knew how to reach every network in the topology, since private address ranges are not automatically propagated between routers.
  • Network Address Translation was configured so internal machines could reach the internet by sharing the router’s public IP address (SNAT), and so that specific inbound services could be selectively exposed back into the private network (Port Mapping / PNAT), including a working SSH connection into the Ubuntu1 host from outside the lab.
  • DNS was installed and configured using BIND9 on an Ubuntu Linux host, hosting an authoritative zone for the lab’s private domain, and the DHCP pools were updated so clients automatically learned the correct internal DNS server.

Summary

This material covers three foundational network services that, together, make a private network usable both internally and against the public internet:

  • DHCP removes the need for manual IP address management by automating assignment through the four-step DORA process (Discover, Offer, Request, Acknowledge). On Cisco IOS, DHCP can be configured locally per-router with ip dhcp pool, or centralized using DHCP relay agents (ip helper-address) so a single server can support multiple LANs.
  • Routing between private networks requires explicit static routes, since private address space is not globally routable and cannot be automatically advertised between independently-administered routers.
  • NAT bridges private, non-routable address space and the public internet:
    • SNAT / overload (PAT) lets many internal hosts share one public IP address for outbound connections.
    • DNAT maps a dedicated public IP address to a specific internal host.
    • PNAT (Port Mapping) exposes only specific ports/services on a shared public IP address, giving fine-grained, controlled inbound access.
  • DNS replaced the original flat HOSTS.TXT file (RFC 952) with a scalable, hierarchical, distributed database structured as an inverted tree (root → TLD → domain). Tools like dig (with +short, +trace, -4, and record-type queries such as a, ns, mx) make it possible to observe and troubleshoot the resolution process directly. Running an authoritative zone (e.g., with BIND9) requires an options file, a zone-definition file, and a zone database file containing SOA, NS, and A records — and DHCP pools must be updated so that clients actually learn about the private DNS server.

Quick Reference

ServiceCisco IOS / Linux command highlights
DHCP poolip dhcp pool <name>, network, default-router, dns-server, ip dhcp excluded-address
DHCP relayip helper-address <dhcp-server-ip> on the interface facing the remote LAN
View DHCP leasesshow ip dhcp binding
Static routeip route <network> <mask> <next-hop>
Default routeip route 0.0.0.0 0.0.0.0 <next-hop>
View routesshow ip route, show ip route connected, show ip route static
Mark NAT interfacesip nat inside / ip nat outside on the relevant interfaces
SNAT / overloadaccess-list <n> permit <net> <wildcard> then ip nat inside source list <n> interface <if> overload
Port mapping (PNAT)ip nat inside source static tcp <internal-ip> <port> interface <if> <public-port>
Install DNS serversudo apt install bind9 bind9-utils bind9-dnsutils dnsutils
Validate DNS confignamed-checkconf, named-checkzone <zone> <file>
Restart DNS serversudo systemctl restart named
Query DNSdig <name>, dig <name> +short, dig +trace <name>, dig @<server> <name>
Renew DHCP lease (Linux)sudo networkctl renew <interface>, networkctl status

Checklist for Building a Similar Lab

  • Confirm host supports nested virtualization, with at least 4 CPU cores and 8 GB RAM, before installing CML.
  • Design the IP addressing plan up front (backbone network, per-LAN networks, excluded static ranges).
  • Configure DHCP pools with appropriate exclusions, default routers, and DNS servers.
  • Add DHCP relay (ip helper-address) on any router that should not run its own DHCP service.
  • Add static/default routes on every router so all networks in the topology are reachable.
  • Add an external connector only once internal routing is verified, and bridge it to the real network.
  • Enable ip nat inside / ip nat outside and configure an ACL-scoped, overloaded SNAT rule for outbound access.
  • Add PNAT rules only for the specific services that must be reachable from the internet — avoid full DNAT exposure unless required.
  • Stand up an authoritative DNS zone with correct SOA, NS, and A records, and validate with named-checkconf / named-checkzone before restarting the service.
  • Update DHCP pools to advertise the internal DNS server, and force clients to renew so they pick up the change immediately.

Search Terms

critical · network · services · dns · dhcp · nat · networking · fundamentals · systems · security · cisco · configuring · router · dora · global · hierarchy · hosts · managing · mapping · port · process · relay · routing · server

Interested in this course?

Contact us to book it or get a custom training plan for your team.