Skip to content

Instantly share code, notes, and snippets.

@michele-tn
Last active January 17, 2026 15:26
Show Gist options
  • Select an option

  • Save michele-tn/3a6eac5b927486d8cb9405f2ce66a370 to your computer and use it in GitHub Desktop.

Select an option

Save michele-tn/3a6eac5b927486d8cb9405f2ce66a370 to your computer and use it in GitHub Desktop.

IONOS VPS DNS Hardening Script v3

This project provides a hardened Bash script to enforce persistent, secure DNS configuration on Ubuntu VPS systems hosted on IONOS.

Key improvement vs v2: DHCP is still used for IP/gateway, but DHCP-provided DNS (IONOS 212.227.x.x) is ignoredsee technical discussion.


Features

  • Disables cloud-init network management (network config)
  • Disables netplan configuration generated by cloud-init
  • Enables systemd-networkd
  • Keeps DHCP for IP on ens6 but rejects DHCP DNS
  • Forces Cloudflare DNS on interface ens6
  • Enables DNS-over-TLS using systemd-resolved
  • Adds Quad9 as fallback DNS provider
  • Makes DNS configuration persistent across reboots

DNS Providers Used

Primary

  • 1.1.1.1
  • 1.0.0.1

Fallback

  • 9.9.9.9
  • 149.112.112.112

All DNS queries are encrypted using DNS-over-TLS.


Why IONOS DNS still appeared before (and how v3 fixes it)

IONOS typically injects DNS via DHCP. Even if you set DNS= in [Network], systemd-networkd may still accept and expose the DHCP DNS unless you explicitly disable it.

v3 adds:

[DHCPv4]
UseDNS=no

[DHCPv6]
UseDNS=no

This keeps DHCP for addressing but prevents the resolver stack from learning/using the IONOS DNS servers.


Requirements

  • Ubuntu 20.04 / 22.04 / 24.04
  • VPS network interface name: ens6
  • Root privileges

Installation

Download and run:

chmod +x setup-dns-ionos-v3.sh
sudo ./setup-dns-ionos-v3.sh
sudo reboot

Verification

After reboot:

resolvectl status ens6
resolvectl status

Expected:

  • On link ens6: DNS Servers show 1.1.1.1 1.0.0.1
  • DNSOverTLS: yes
  • IONOS 212.227.x.x must not appear as active DNS servers

Note: depending on Ubuntu/systemd version, DHCP DNS might still be visible under “DHCP Server” info, but it must not be selected as “DNS Servers” for the link nor as the “Current DNS Server”.


Files Created

  • /etc/systemd/network/10-ens6.network
  • /etc/systemd/resolved.conf.d/dns-hardened.conf
  • /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg

Rollback

sudo rm /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg
sudo rm /etc/systemd/network/10-ens6.network
sudo rm /etc/systemd/resolved.conf.d/dns-hardened.conf
sudo mv /etc/netplan/50-cloud-init.yaml.bak /etc/netplan/50-cloud-init.yaml
sudo reboot

If /etc/resolv.conf was replaced and you want the previous one back, restore the backup created by the script: /etc/resolv.conf.bak.<timestamp>.


Download

Sources (technical references)

@michele-tn
Copy link
Author

📦Bash script - rollback-dns-ionos.sh

#!/usr/bin/env bash
set -e

echo "========================================"
echo " DNS HARDENING ROLLBACK SCRIPT"
echo "========================================"

if [ "$(id -u)" -ne 0 ]; then
  echo "Run as root."
  exit 1
fi

echo "[1] Restoring netplan..."
if [ -f /etc/netplan/50-cloud-init.yaml.bak ]; then
  mv /etc/netplan/50-cloud-init.yaml.bak /etc/netplan/50-cloud-init.yaml
fi

echo "[2] Re-enabling cloud-init networking..."
rm -f /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg

echo "[3] Removing systemd-networkd config..."
rm -f /etc/systemd/network/10-ens6.network

echo "[4] Removing systemd-resolved custom config..."
rm -f /etc/systemd/resolved.conf.d/dns-enterprise.conf
rm -f /etc/systemd/resolved.conf.d/dns-hardened.conf

echo "[5] Restoring resolv.conf..."
if [ -f /etc/resolv.conf.bak* ]; then
  latest=$(ls -t /etc/resolv.conf.bak* | head -n1)
  mv "$latest" /etc/resolv.conf
fi

echo "[6] Removing nftables DNS firewall..."
rm -f /etc/nftables.d/dns-firewall.nft
sed -i '/dns-firewall.nft/d' /etc/nftables.conf || true

echo "[7] Disabling DNS fallback watchdog..."
systemctl disable dns-fallback-watchdog.timer || true
systemctl stop dns-fallback-watchdog.timer || true
rm -f /etc/systemd/system/dns-fallback-watchdog.*
rm -f /usr/local/bin/dns-fallback-watchdog.sh

echo "[8] Restarting services..."
systemctl restart systemd-resolved || true
systemctl restart systemd-networkd || true
systemctl restart nftables || true

echo "========================================"
echo " ROLLBACK COMPLETED"
echo "========================================"
echo "Reboot recommended:"
echo " sudo reboot"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment