PowerDNS mit DNSSEC

Ich möchte gern meine eigenen DNS-Server nutzen und bin ungern auf „fremde“ Lösungen angewiesen. Aus diesem Grund habe ich mir PowerDNS mit PowerDNS-Admin angeschaut um eine für mich gute und auch praktikable Lösung zu haben.

Zuerst benötigen wir zwei Server, idealerweise in unterschiedlichen Rechenzentren. Meine Server befinden sich beide beim gleichen Hoster, also habe ich den ersten Schritt nicht optimal gelöst. Aber was nicht ist, kann ja noch werden. ;-)

Für meinen Anwendungsfall reichen mir zwei Server für je 1,–€ monatlich.

Die Server habe ich mit Debian 12 minimal installiert und dann weitestgehend abgesichert, indem ich ufw sowie Docker installiert habe. Das PowerDNS-Setup habe ich mit Docker-Containern realisiert.


Also, los geht´s: – PowerDNS Master
erstmal alles aktualisieren

apt update && apt upgrade -y

Docker installieren: Schritt 1 – Docker Repository einbinden

# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

# Add the repository to Apt sources:
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update

Schritt 2 – Docker installieren

sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Schritt 3 – Verzeichnisse anlegen und docker-compose.yml anlegen. Ich habe dazu ein Verzeichnis /opt/pdns angelegt.

services:
  mariadb:
    image: bitnami/mariadb:10.4
    volumes:
      - mariadb-data:/bitnami/mariadb
    environment:
      MARIADB_ROOT_PASSWORD: 123123123123 #bitte abändern
      MARIADB_DATABASE: pdns
      MARIADB_USER: pdns
      MARIADB_PASSWORD: 321321321321 #bitte abändern
      MARIADB_REPLICATION_MODE: master
      MARIADB_REPLICATION_USER: replicator
      MARIADB_REPLICATION_PASSWORD: 456456456 #bitte abändern - wird für den Slave gebraucht
    ports:
      - 3306:3306
    restart: unless-stopped

  pdns:
    image: psitrax/powerdns:v4.2
    environment:
      MYSQL_HOST: mariadb
      MYSQL_DB: pdns
      MYSQL_USER: pdns
      MYSQL_PASS: 321321321321 #bitte anpassen (Zeile10)
      MYSQL_DNSSEC: yes
      MYSQL_AUTOCONF: "true"
    ports:
      - 53:53/tcp
      - 53:53/udp
      - 8081:8081

    command:
      - --api=yes
      - --api-key=abcdefabcdef  #bitte abändern
      - --webserver-address=0.0.0.0
      - --webserver-allow-from=0.0.0.0/0
      - --gmysql-dnssec=yes
    restart: unless-stopped
    volumes:
      - ./pdns.conf:/opt/pdns/pdns.conf

  admin:
    image: powerdnsadmin/pda-legacy:latest
    environment:
      SQLALCHEMY_DATABASE_URI: mysql://pdns:321321321321@mariadb/pdns #bitte das DB-Passwort anpassen (Zeile 10)
      PDA_API_URL: http://pdns:8081/api/v1
      PDA_API_KEY: abcdefabcdef #bitte abändern (Zeile 34)
    volumes:
      - admin-data:/data
    ports:
      - 8080:80
    logging:
      driver: json-file
      options:
        max-size: 50m
    restart: unless-stopped

  nginx:
    image: nginx:latest
    container_name: nginx
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
      - ./certs:/etc/nginx/certs

volumes:
  mariadb-data:
    driver: local
  admin-data:
    driver: local

Soweit so Gut. Was haben wir gemacht? Zum einen haben wir PowerDNS in den Container gepackt, PowerDNS -Admin, MariaDB sowie NGINX um das Backend schlussendlich SSL-gesichert aufrufen zu können.

Jetzt müssen wir uns noch um eine URL für das Backend kümmern sowie die Zertifikate beziehen.

wir erstellen im gleichen Verzeichnis noch eine nginx.conf

events {}

http {
    server {
        listen 80;
        server_name pdns.meinedomain.de; #anpassen 
        return 301 https://$host$request_uri;
    }

    server {
        listen 443 ssl;
        server_name pdns.meinedomain.de; #anpassen

        ssl_certificate /etc/nginx/certs/fullchain.pem;
        ssl_certificate_key /etc/nginx/certs/privkey.pem;

        location / {
            proxy_pass http://pdns-admin:80;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }
}

um die benötigten Zertifikate für unser Backend zu erhalten installieren wir im ersten Schritt certbot

apt install certbot

um dann mittels DNS-Challenge unser Zertifikat zu beziehen

certbot certonly --manual --preferred-challenges dns -d pdns.meinedomain.de

dabei folgen wir den Anweisungen von certbot.
Sobald wir die Zertifikate erfolgreich bezogen haben kopieren wir diese noch in die richtigen Verzeichnisse:

cp /etc/letsencrypt/live/pdns.meinedomain.de/fullchain.pem ./certs/
cp /etc/letsencrypt/live/pdns.meinedomain.de/privkey.pem ./certs/

Jetzt haben wir es fast geschafft, es fehlt noch ein letztes

docker compose up -d

und die images werden bezogen sowie die Container gestartet.

ABER
Wir müssen ja noch unseren SLAVE einrichten. Also einloggen auf dem zweiten Server, ebenfalls das Verzeichnis /opt/pdns erstellen und die folgende docker-compose.yml anlegen. Natürlich auch auf diesem Server zuerst docker installieren (siehe Schritt 1&2 ganz am Anfang)

services:
  mariadb:
    image: bitnami/mariadb:10.4
    volumes:
      - mariadb-data:/bitnami/mariadb
    environment:
      MARIADB_REPLICATION_MODE: slave
      MARIADB_MASTER_HOST: 123.123.123.123 #IP des Master-Server
      MARIADB_MASTER_ROOT_USER: root
      MARIADB_MASTER_ROOT_PASSWORD: 123123123123 #anpassen an Master
      MARIADB_REPLICATION_USER: replicator
      MARIADB_REPLICATION_PASSWORD: 456456456 #anpassen an Master
    restart: unless-stopped
  pdns:
    image: psitrax/powerdns:v4.2
    # mariadb slave is readonly, so we cannot autoconfigure the database
    environment:
      MYSQL_AUTOCONF: "false"
    # all database options must be passed as command args
    # unless https://github.com/psi-4ward/docker-powerdns/blob/master/entrypoint.sh
    # contains an option to disable schema updates only
    command:
    - --gmysql-host=123.123.123.123 # IP des Master-Server
    - --gmysql-dbname=pdns
    - --gmysql-user=pdns
    - --gmysql-password=321321321321 #anpassen an den Master
    - --gmysql-dnssec=yes
    ports:
      - 53:53/tcp
      - 53:53/udp
    restart: unless-stopped
volumes:
  mariadb-data:
    driver: local

auch hier noch ein abschließendes

docker compose up -d

und schon kannst Du dich über die URL

https://pdns.meinedomain.de

anmelden.

Jetzt noch „schnell“ einen Account erstellen (der erste Account ist automatisch der Admin-Account) und anschließend einloggen.

Aller Wahrscheinlichkeit musst noch im Backend die Zugangsdaten zur API hinterlegen. Den API-Key hast Du in der docker-compose.yml des Master-Server in Zeile 34 selbst vergeben ;-)

Viel Spaß mit deinem eigenen PowerDNS Setup!