Desktop Network Configuration
A desktop connected to a well-designed network should be doing more than just getting a DHCP lease and using the ISP’s DNS resolvers. It should be on the correct VLAN for its purpose, using a local DNS resolver that validates DNSSEC, and capable of reaching all three sites in the network through the VPN. This page covers getting from a freshly installed Kubuntu desktop to that state.
The network design section established the addressing scheme. This page assumes you are working from one of the three sites and connecting to the relevant core VLAN.
Network Manager on Kubuntu
Kubuntu uses NetworkManager for connection management, with the KDE Plasma Network Manager applet as the graphical frontend. It lives in the system tray as the network icon. All configuration in this page can be done through either the GUI or the nmcli command line tool. Both are covered where the choice is meaningful.
Unlike the source material this series draws on, which uses GNOME Network Manager, the KDE frontend behaves differently in a few places, particularly around DNS configuration and VPN integration. These differences are noted throughout.
DNS: the problem with defaults
Out of the box, Kubuntu uses systemd-resolved for DNS resolution. This is a reasonable starting point but has two limitations worth addressing for this setup.
First, the default configuration uses DNS servers pushed by DHCP, which are typically your router’s upstream resolvers or your ISP’s. These may or may not validate DNSSEC, and they definitely do not know about your private internal domain names.
Second, systemd-resolved in its default stub resolver mode (127.0.0.53) does not play well with Unbound running locally, and the split DNS needed to resolve both internal hostnames and external domains cleanly requires some care.
The approach taken here: configure NetworkManager to use systemd-resolved for connection management, but override the DNS servers per connection to point at your internal resolvers, with Unbound as a local DNSSEC-validating cache for when you are off-network.
Installing Unbound
Unbound is a validating, recursive DNS resolver. When your desktop is away from the home network and connected to an untrusted network, Unbound handles resolution directly rather than relying on whatever DNS the network pushes.
sudo apt install unbound
Configure NetworkManager to hand DNS queries to Unbound when no per-connection DNS is configured. Create /etc/NetworkManager/conf.d/dns-unbound.conf:
[main]
dns=unbound
rc-manager=unmanaged
This tells NetworkManager to talk to Unbound directly and not to touch /etc/resolv.conf. Restart NetworkManager:
sudo systemctl restart NetworkManager
Configure Unbound in /etc/unbound/unbound.conf.d/local.conf:
server:
# Listen on localhost only
interface: 127.0.0.1
interface: ::1
port: 53
# Allow queries from localhost
access-control: 127.0.0.0/8 allow
access-control: ::1 allow
# Enable DNSSEC validation
auto-trust-anchor-file: "/var/lib/unbound/root.key"
# Cache settings
cache-max-ttl: 86400
cache-min-ttl: 300
# Hide version and identity
hide-version: yes
hide-identity: yes
# Harden against certain attacks
harden-glue: yes
harden-dnssec-stripped: yes
harden-referral-path: yes
# Use 0x20-encoded random bits in queries as per RFC
use-caps-for-id: yes
# Reduce EDNS reassembly buffer size
edns-buffer-size: 1232
# Prefetch popular items before they expire
prefetch: yes
prefetch-key: yes
# Log settings
verbosity: 0
# Forward internal domains to your internal DNS resolver
# when connected to the home network, these are handled per-connection
# by NetworkManager. This handles any fallback cases.
forward-zone:
name: "yourdomain.net"
forward-addr: 10.1.0.1
forward-zone:
name: "1.10.in-addr.arpa."
forward-addr: 10.1.0.1
forward-zone:
name: "2.10.in-addr.arpa."
forward-addr: 10.1.0.1
forward-zone:
name: "3.10.in-addr.arpa."
forward-addr: 10.1.0.1
Replace 10.1.0.1 with the actual DNS resolver address on your core VLAN, and update the domain zone to your actual domain. Restart Unbound:
sudo systemctl restart unbound
sudo systemctl enable unbound
Test DNSSEC validation is working:
dig +dnssec sigok.verteiltesysteme.net @127.0.0.1
The response should include ad (authentic data) in the flags. A response for a known DNSSEC-failing domain should return SERVFAIL:
dig sigfail.verteiltesysteme.net @127.0.0.1
Configuring connections in NetworkManager
Wired connection on the Core VLAN
For a desktop permanently connected to the Core VLAN at Burnage Mad House (VLAN 14, 10.1.0.0/24):
Open the network applet in the system tray, click the connection, and select Configure. Under the IPv4 tab, set the DNS server to your internal resolver address (for example 10.1.0.1). Under the IPv6 tab, do the same for the IPv6 DNS address if applicable.
Add your internal search domain so short hostnames resolve correctly:
Search domains: yourdomain.net lan
Via nmcli:
nmcli con mod "Wired connection 1" \
ipv4.dns "10.1.0.1" \
ipv4.dns-search "yourdomain.net,lan" \
ipv6.dns "your::ipv6::resolver" \
ipv6.dns-search "yourdomain.net,lan"
nmcli con up "Wired connection 1"
Verify resolution works:
resolvectl status
resolvectl query server.yourdomain.net
VLAN connections
If your desktop connects to multiple VLANs on a single physical interface (for example, both the Core VLAN and a specific service VLAN), configure them as VLAN interfaces in NetworkManager.
Create a VLAN connection for each required VLAN:
# Example: add VLAN 14 (Core) on physical interface enp3s0
nmcli con add type vlan \
con-name "Core-VLAN14" \
dev enp3s0 \
id 14 \
ipv4.method auto \
ipv4.dns "10.1.0.1" \
ipv4.dns-search "yourdomain.net,lan"
Check your physical interface name with ip link show before running this.
VPN client configuration
The VPN connects the three sites together. When connected, your desktop should be able to reach 10.1.x.x, 10.2.x.x, and 10.3.x.x regardless of which site you are physically at.
The VPN section of this series covers server-side configuration. On the desktop, the client side depends on which VPN protocol the routers are using. For WireGuard, which is the recommended protocol for inter-site connectivity with Ubiquiti UniFi:
Install WireGuard tools:
sudo apt install wireguard
NetworkManager supports WireGuard natively on Kubuntu 24.04. Import the client configuration file provided by your router:
nmcli con import type wireguard file /path/to/client.conf
Or configure it manually through the KDE Network Manager applet: click the VPN section, add a new WireGuard connection, and enter the peer public key, endpoint, and allowed IPs.
Set the allowed IPs to cover all three site subnets for split tunnelling, so only traffic destined for the internal network goes through the VPN:
AllowedIPs = 10.1.0.0/16, 10.2.0.0/16, 10.3.0.0/16
If you want all traffic to go through the VPN (full tunnel), use 0.0.0.0/0, ::/0 instead, but be aware this routes all internet traffic through your home connection.
Add DNS for the VPN connection to ensure internal hostnames resolve when connected:
nmcli con mod "client" \
ipv4.dns "10.1.0.1" \
ipv4.dns-search "yourdomain.net,lan"
Test the VPN by connecting and pinging a host at another site:
ping 10.2.0.1
Dynamic DNS for the desktop hostname
Non-server machines get dynamic DHCP addresses and may need to update DNS when their address changes. If your internal DNS server supports dynamic updates, configure nsupdate to register the desktop hostname automatically on connection.
Create /etc/NetworkManager/dispatcher.d/99-nsupdate:
#!/bin/bash
# Update internal DNS when network connection changes
INTERFACE=$1
EVENT=$2
if [ "$EVENT" = "up" ]; then
IP=$(ip -4 addr show $INTERFACE | grep inet | awk '{print $2}' | cut -d/ -f1)
HOST=$(hostname -s)
DOMAIN="yourdomain.net"
nsupdate -k /etc/rndc.key <<EOF
server 10.1.0.1
zone $DOMAIN
update delete $HOST.$DOMAIN A
update add $HOST.$DOMAIN 300 A $IP
send
EOF
fi
Make it executable:
sudo chmod +x /etc/NetworkManager/dispatcher.d/99-nsupdate
This requires a TSIG key configured on your DNS server for authenticated dynamic updates. The DNS server configuration is covered in the server section of this series.
Verifying the full setup
With everything configured, a quick end-to-end check:
# Local DNS resolution with DNSSEC
resolvectl query sigok.verteiltesysteme.net
# Internal hostname resolution
resolvectl query server.yourdomain.net
# Reverse DNS
resolvectl query 10.1.0.1
# VPN reachability (when connected)
ping -c3 10.2.0.1
ping -c3 10.3.0.1
# Check which DNS server is being used
resolvectl status
A clean result across all of these means the desktop is properly integrated into the network.
The most common issue after this configuration is search domain precedence. If short hostnames are resolving to the wrong address, check the DNS search domain order in
resolvectl statusand reorder them in the connection configuration if needed.