blog_hero_Host je eigen DNS server in je labo

Host je eigen DNS server in je labo

Oct 18 2023

Waarom willen we een eigen DNS server?

Het is heel leuk als we onze eigen Gitlab server of Zabbix opzetten. Maar als alleenstaande installaties hebben we er niet zo veel aan. We kunnen wel in alle servers de hosts bestanden gaan aanpassen tot een paar servers. Daarna wordt het eigenlijk niet meer beheerbaar. Iedere server moet een entry krijgen en moet up to date gehouden worden.

De DNS server kan ons niet alleen helpen om het beheer van die IP-adressen te centraliseren. Daarnaast is het ook fijn om met hostnamen te kunnen werken. Die onthouden toch iets beter dan een reeks IP-adressen.

Een populaire keuze in de Linux wereld voor DNS is BIND.

Installatie

We hebben twee onderdelen nodig om deze service op te zetten:

sudo dnf install bind bind-utils -y

Dit installeert de named service. Configuratie kan gemaakt worden in /etc/named.conf. Daar gaan we nu de configuratie doorvoeren.

Configuratie

Eerst moeten we instellen via welke weg we configuratie beschikbaar willen stellen. De poort staat vaak al goed. Daarnaast moeten we het IP-adres van de server nog toevoegen alsook wie verzoeken mag sturen. Hier heeft mijn server het IP-adres 192.168.124.115. Andere servers in mijn labo bevinden zich in hetzelfde subnet dus die mogen verzoeken sturen; 192.168.124.0/24

...
listen-on port 53 { 127.0.0.1; 192.168.124.115; };
...
allow-query { localhost; 192.168.124.0/24; }

Onderaan dat bestand kunnen we dan aangeven welke zones we gaan aanbieden. Doe dat net boven de include regel. Per zone kan je een domein configureren. Hier gaan we twee entries voorzien. De eerste is voor het forward domain zone en de tweede is voor de reverse DNS.

Onthou goed wat je onder file noteert. Dat worden de namen van de bestanden voor de volgende stap.

...
zone "winderickx.me" IN {
type master;
file "forward.winderickx.me";
allow-update { none; };
};

zone "124.168.192.in-addr.arpa" IN {
type master;
file "reverse.winderickx.me";
allow-update { none; };
};
include "/etc/named.rfc1912.zones";
...

Nu deze configuratie klaar staat, kunnen we de effectieve data invullen in de bestanden die we in de vorige stap hebben ingegeven. Deze bestanden staan standaard in /var/named map.

Domeinnamen in DNS eindigen altijd met een . om duidelijk het TLD (Top Level Domain) aan te geven.

forward.winderickx.me

$TTL 86400
@   IN  SOA     dns.winderickx.me. root.winderickx.me. (
        2011071001  ;Serial
        3600        ;Refresh
        1800        ;Retry
        604800      ;Expire
        86400       ;Minimum TTL
)
@       IN  NS          dns.winderickx.me.
@       IN  A           192.168.124.99
dns           IN  A   192.168.124.115
<servers>          IN  A   <IP-adressen>

reverse.winderickx.me

$TTL 86400
@   IN  SOA     dns.winderickx.me. root.winderickx.me. (
        2011071001  ;Serial
        3600        ;Refresh
        1800        ;Retry
        604800      ;Expire
        86400       ;Minimum TTL
)
@       IN  NS          dns.winderickx.me.
@       IN  PTR         winderickx.me.
dns           IN  A   192.168.1.115
115     IN  PTR         dns.winderickx.me.
<laatste octet van IP>     IN  PTR         <Servers>.

Zorg er voor dat de named groep rechten heeft op het bestand.

sudo chgrp named -R /var/named

Vergeet niet de firewall aan te passen!

sudo firewall-cmd --add-service=dns --permanent
sudo firewall-cmd --reload

Controleer nu de configuratie.

sudo named-checkconf /etc/named.conf
sudo named-checkzone /var/named/forward.winderickx.me
sudo named-checkzone /var/named/reverse.winderickx.me

Als daar geen fouten uitkomen, kan je nu de service starten.

sudo systemctl restart named

Client configuratie

We gaan er even van uit dat je gebruik maakt van NetworkManager voor jouw netwerk configuratie. Dit kan je dan gebruiken om jouw nieuwe DNS in te stellen op alle hosts.

Hier gebruik ik de connectie enp1s0 om de aanpassingen op uit te voeren. Om te weten te komen welke connectie voor jou actief staat, voer dan ip -br a uit.

sudo nmcli c m enp1s0 ipv4.dns "192.168.124.115"
sudo nmcli c m enp1s0 ipv4.ignore-auto-dns yes
sudo systemctl restart NetworkManager

Als dat goed gelukt is, ga je dit IP-adres terugvinden in /etc/resolv.conf. Dit is namelijk de plaats waar Linux de DNS server verwacht. Heb je dus geen NetworkManager, dan kan je ook hier manueel het IP-adres aanpassen.

En nu Ansible!

Omdat we productief lui zijn, doen we dit proces liefst zo automatisch mogelijk. Ik heb daarom dit hele proces ook in een Ansible playbook geschreven. Die kan je dus gewoon gebruiken. Mijn DNS server is een RHEL gebasseerde server. Als je een Debian gebasseerde server gebruikt, ga je mogelijk hinder ervaren. Je gaat nog steeds enkele bestanden moeten voorzien:

  • named.conf
  • Forward lookup bestand
  • reverse lookup bestand
  • resolv.conf

Geef gerust een seintje via LinkedIn als je vast zit met deze bestanden.

---
- name: Install DNS server
  hosts: dns
  vars:
    packages:
      - bind
      - bind-utils
      - firewalld
  tasks:
    - name: Install the required software
      ansible.builtin.dnf:
        name: "{{ item }}"
        state: latest
      loop: "{{ packages }}"
        
    - name: Enable and start firewall service
      ansible.builtin.service:
        name: firewalld
        state: started
        enabled: true

    - name: Allow DNS traffic on firewall
      ansible.posix.firewalld:
        service: dns
        state: enabled
        permanent: true
        immediate: true

    - name: Configure the BIND service
      ansible.builtin.copy:
        src: named.conf
        dest: /etc/named.conf
        owner: root
        group: named
        mode: 0640
      notify: restart bind service

    - name: Prepare DNS zone files
      ansible.builtin.copy:
        src: "{{ item }}"
        dest: "/var/named/{{ item }}"
        owner: root
        group: named
        mode: 0644
      loop:
        - forward.winderickx.me
        - reverse.winderickx.me
      notify: restart bind service
  handlers:
    - name: restart bind service
      ansible.builtin.service:
        name: named
        state: restarted
- name: Configure DNS for hosts
  hosts: all
  vars: 
    dns4: 192.168.124.115
    conn_name: enp1s0
  tasks:
    - name: Configure the correct DNS for the server
      community.general.nmcli:
        conn_name: "{{ conn_name }}"
        type: ethernet
        dns4: "{{ dns4 }}"
        dns4_ignore_auto: true
        state: present
      when: ansible_facts['distribution'] != "Debian"
      notify: reload NetworkManager

    - name: Configure the correct DNS for debian
      ansible.builtin.template:
        src: resolv.conf.j2
        dest: /etc/resolv.conf
        owner: root
        group: root
        mode: 0644
      when: ansible_facts['distribution'] == "Debian"
  handlers:
    - name: reload NetworkManager
      ansible.builtin.service:
        name: NetworkManager
        state: restarted

Bonus

Wil je wel Ansible gebruiken maar geen eigen DNS server? Dan heb je hier een andere playbook die de inventory van jouw Ansible gebruikt om /etc/hosts op te vullen. Dit is een heel pak simplistischer dan heel de opzet hierboven maar we moeten bij iedere aanpassing wel deze playbook uitvoeren op ALLE servers in onze inventory en die inventory wordt ineens de Single Source of Truth. Hou daar dus zeker rekening mee als je toch voor deze optie gaat!

dns.yml

- name: /etc/hosts is up to date
  hosts: all
  gather_facts: yes
  tasks:
    - name: Deploy /etc/hosts
      ansible.builtin.template:
        src: templates/hosts.j2
        dest: /etc/hosts

hosts.j2

{% for host in groups['all'] %}
{{ hostvars[host]['ansible_facts']['default_ipv4']['address'] }} {{ hostvars[host]['ansible_facts']['fqdn'] }} {{ hostvars[host]['ansible_facts']['hostname'] }}
{% endfor %}