PowerDNS (Parte 2)
En esta segunda parte se instalará y configurará un clúster de bases de datos replicada con Galera y se configurarán los 3 servidores DNS del montaje, dos en modo Maestro y un tercero en Modo Esclavo.
2. Instalación
2.1. Servicio de base de datos
Se va a usar Galera para la replicación de las bases de datos, antes de instalar PowerDNS crearé el clúster de replicación.
Las dos máquinas que voy a usar se llaman dns1.dyn.alcocer.net y dns2.dyn.alcocer.net.
root@dns1:~# apt install mariadb-server root@dns1:~# mysql_secure_installation root@dns2:~# apt install mariadb-server root@dns2:~# mysql_secure_installation
2.1.1. Configuración del clúster Galera
2.1.1.1. DNS1
# necesario para la escucha bind-address = 0.0.0.0 # requisitos de galera (leerdoc) binlog_format = ROW log_bin = /var/log/mysql/mysql-bin.log default-storage-engine = innodb innodb_autoinc_lock_mode = 2 innodb_large_prefix = on innodb_file_format = Barracuda # Configuración de galera wsrep_on=ON wsrep_provider=/usr/lib/galera/libgalera_smm.so # nombre del clúster wsrep_cluster_name="powerdns_galera_cluster" # miembros del cluster IP o DNS wsrep_cluster_address="gcomm://dns1.dyn.alcocer.net,dns2.dyn.alcocer.net" wsrep_sst_method=rsync # IP o nombre DNS del nodo wsrep_node_address="dns1.dyn.alcocer.net" # nombre del nodo wsrep_node_name="dns1"
Y paramos el servicio de mariadb:
root@dns1:~# systemctl stop mariadb
2.1.1.2. DNS2
# necesario para la escucha bind-address = 0.0.0.0 # requisitos de galera (leerdoc) binlog_format = ROW log_bin = /var/log/mysql/mysql-bin.log default-storage-engine = innodb innodb_autoinc_lock_mode = 2 innodb_large_prefix = on innodb_file_format = Barracuda # Configuración de galera wsrep_on=ON wsrep_provider=/usr/lib/galera/libgalera_smm.so # nombre del clúster wsrep_cluster_name="powerdns_galera_cluster" # miembros del cluster IP o DNS wsrep_cluster_address="gcomm://dns1.dyn.alcocer.net,dns2.dyn.alcocer.net" wsrep_sst_method=rsync # IP o nombre DNS del nodo wsrep_node_address="dns2.dyn.alcocer.net" # nombre del nodo wsrep_node_name="dns2"
Aquí también hay que parar el servicio
root@dns1:~# systemctl stop mariadb
2.1.2. Primer arranque de Galera
En el nodo1, dns1, iniciamos MariaDB con el siguiente comando:
root@dns1:~# galera_new_cluster
Y en el nodo2 normalmente:
root@dns2:~# systemctl start mariadb
Si todo ha ido bien, al ejecutar el siguiente comando el resultado debe ser mayor que 1, depende de cuántos nodos se hayan configurado:
root@dns1:~# mysql -u root -p -e "show status like 'wsrep_cluster_size'" Enter password: +--------------------+-------+ | Variable_name | Value | +--------------------+-------+ | wsrep_cluster_size | 2 | +--------------------+-------+ root@dns1:~#
2.2. Instalación de PowerDNS
2.2.1. Configuración de la base de datos
Si se instala PowerDNS en uno de los nodos con el Backend de MySQL, este debe crear las tablas necesarias para PowerDNS en el nodo en cuestión y Galera realizará la magia para pasar las zonas al resto de nodos.
De momento haré la instalación en uno de ellos y comprobaré que se han replicado los cambios por el clúster.
root@dns1:~# apt install pdns-server pdns-tools pdns-backend-mysql pdns-backend-bind
Cuando nos pregunte si queremos configurar la base de datos usando el asistente durante la instalación, le decimos que no.
Para insertar el esquema de PowerDNS, necesitaremos previamente tener una base de datos y un usuario que tenga los privilegios suficientes para trabajar sobre ella.
La base de datos será ‘pdns’ y el usuario será ‘pdns’, este usuario solo podrá acceder desde la propia máquina:
MariaDB [(none)]> create database pdns; Query OK, 1 row affected (0.04 sec) MariaDB [(none)]> grant all on pdns.* to 'pdns'@'localhost' identified by 'pdns'; Query OK, 0 rows affected (0.06 sec) MariaDB [(none)]> flush privileges; Query OK, 0 rows affected (0.05 sec) MariaDB [(none)]>
Ahora seleccionamos la base de datos y ejecutamos los comandos DDL que se encuentran en el este fichero: ‘/usr/share/dbconfig-common/data/pdns-backend-mysql/install/mysql’.
MariaDB [(none)]> use pdns; Database changed MariaDB [pdns]> source /usr/share/dbconfig-common/data/pdns-backend-mysql/install/mysql;
Todo esto lo he hecho en el nodo dns1, accederé al nodo dns2 para ver que los cambios se han replicado:
MariaDB [(none)]> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | pdns | | performance_schema | +--------------------+ 4 rows in set (0.00 sec) MariaDB [(none)]>
La base de datos ‘pdns’ se ha replicado, ahora comprobaré algunas tablas:
MariaDB [pdns]> show tables; +----------------+ | Tables_in_pdns | +----------------+ | comments | | cryptokeys | | domainmetadata | | domains | | records | | supermasters | | tsigkeys | +----------------+ 7 rows in set (0.01 sec) MariaDB [pdns]>
Y la tabla de registros:
MariaDB [pdns]> describe records; +-------------+----------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------------+----------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | domain_id | int(11) | YES | MUL | NULL | | | name | varchar(255) | YES | MUL | NULL | | | type | varchar(10) | YES | | NULL | | | content | varchar(64000) | YES | | NULL | | | ttl | int(11) | YES | | NULL | | | prio | int(11) | YES | | NULL | | | change_date | int(11) | YES | | NULL | | | disabled | tinyint(1) | YES | | 0 | | | ordername | varchar(255) | YES | | NULL | | | auth | tinyint(1) | YES | | 1 | | +-------------+----------------+------+-----+---------+----------------+ 11 rows in set (0.01 sec) MariaDB [pdns]>
..yo diría que se ha replicado correctamente 😀
2.2.2. Configuración de PowerDNS
Ahora le llegó el turno a la configuración de PowerDNS.
Una configuración no muy exhaustiva, y que haga funcionar a PowerDNS de forma más que decente, es sencilla de conseguir.
Básicamente consiste en configurar los Backends, decirle el modo de funcionamiento del servidor y cegar el servicio a las Ips y puerto donde queramos que escuche y sirva las peticiones, que en el caso que estamos tratando será modo Nativo, el segmento de red 10.0.0.0/16 y dejaremos trabajar al servicio de base de datos para que mantenga replicadas las zonas apropiadamente.
Esta configuración que voy a colgar aquí debajo es casi la misma para ambos servidores pues ambos van a estar en modo Nativo y la parte en la que podrían no coincidir sería en las IPS de escucha o en los ficheros de configuración del backend, ya que cada uno estará contra una base de datos propia para él mismo.
En mi caso, solo difieren en las Ips de escucha.
2.2.2.1. /etc/powerdns/pdns.conf
Recordemos que el contenido de este fichero es el mismo en ambos servidores, ajustar a vuestras necesidades:
allow-axfr-ips=10.0.0.0/16 api=yes api-key=hackme default-soa-mail=hostmaster.alcocer.net default-soa-name=dns1.dyn.alcocer.net disable-axfr=no include-dir=/etc/powerdns/pdns.d launch= local-address=10.0.105.139 local-ipv6= local-port=53 master=yes security-poll-suffix= setgid=pdns setuid=pdns slave=no webserver=yes webserver-address=0.0.0.0 webserver-allow-from=0.0.0.0/0,::/0 webserver-password=hackme webserver-port=8081 webserver-print-arguments=yes
Hay más valores, lee la doc online o con los comentarios puede ser suficiente en algunos casos.
Evidentemente esto es un servidor DNS en una red local corporativa así que no tenemos problemas en cuanto a que alguien se descargue toda la información de las zonas.
En el caso de que fuera un servidor de acceso público desde internet, o simplemente quisiéramos limitar a determinadas máquinas la transferencia de las zonas, eso se haría mediante la línea ‘allow-axfr-ips=10.0.0.0/16’
La otra opción que hay que asegurarse de que esté establecida es ‘disable-axfr=no’, para dejar claro que las zonas del maestro no sufren actualizaciones de otros servidores.
Evidentemente decirle a la máquina que es máster y que no es esclavo.
2.2.2.2. /etc/powerdns/pdns.d/pdns.local.gmysql.conf
launch+=gmysql gmysql-host=localhost gmysql-port=3306 gmysql-dbname=pdns gmysql-user=pdns gmysql-password=pdns gmysql-dnssec=yes
Si todo ha ido bien, con un simple reinicio del servicio si no escupe nada, es que lo hemos configurado bien.
2.3. Primera prueba
Lo primero va a ser probar que el servidor escucha, la prueba la haré desde el nodo dns2:
root@dns2:~# dig @10.0.105.139 ; <<>> DiG 9.10.3-P4-Debian <<>> @10.0.105.139 ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: REFUSED, id: 16760 ;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1 ;; WARNING: recursion requested but not available ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 1680 ;; QUESTION SECTION: ;. IN NS ;; Query time: 1 msec ;; SERVER: 10.0.105.139#53(10.0.105.139) ;; WHEN: Thu Feb 15 20:58:17 CET 2018 ;; MSG SIZE rcvd: 28 root@dns2:~#
Al menos escucha…
2.3.1. Creación de una zona y sus registros
root@dns1:~# pdnsutil create-zone ejemplo.com Feb 15 21:21:02 [bindbackend] Done parsing domains, 0 rejected, 0 new, 0 removed Creating empty zone 'ejemplo.com' root@dns1:~#
2.3.1.1. Creación de los registros NS
root@dns1:~# pdnsutil add-record ejemplo.com @ NS ns1.ejemplo.com Feb 16 17:53:28 [bindbackend] Done parsing domains, 0 rejected, 0 new, 0 removed New rrset: ejemplo.com. IN NS 3600 ns1.ejemplo.com root@dns1:~#
2.3.1.2. Creación de registros A
root@dns1:~# pdnsutil add-record ejemplo.com ns1 A 10.0.105.139 Feb 16 17:54:59 [bindbackend] Done parsing domains, 0 rejected, 0 new, 0 removed New rrset: ns1.ejemplo.com. IN A 3600 10.0.105.139 root@dns1:~# pdnsutil add-record ejemplo.com @ A 1.2.3.4 Feb 16 17:56:53 [bindbackend] Done parsing domains, 0 rejected, 0 new, 0 removed New rrset: ejemplo.com. IN A 3600 1.2.3.4
2.3.1.3. Creación de CNAME
root@dns1:~# pdnsutil add-record ejemplo.com www CNAME ejemplo.com Feb 16 17:57:53 [bindbackend] Done parsing domains, 0 rejected, 0 new, 0 removed New rrset: www.ejemplo.com. IN CNAME 3600 ejemplo.com
2.3.1.4. Información sobre la zona
root@dns1:~# pdnsutil list-zone ejemplo.com Feb 16 17:59:02 [bindbackend] Done parsing domains, 0 rejected, 0 new, 0 removed ejemplo.com 3600 IN A 1.2.3.4 ejemplo.com 3600 IN NS ns1.ejemplo.com. ejemplo.com 3600 IN SOA a.misconfigured.powerdns.server hostmaster.ejemplo.com 1 10800 3600 604800 3600 ns1.ejemplo.com 3600 IN A 10.0.105.139 www.ejemplo.com 3600 IN CNAME ejemplo.com.
2.4. Comprobación final
Después de lo anterior lo que nos queda para saber que el servidor DNS está funcionando correctamente es hacerle una petición desde una máquina externa.
root@dns2:~# dig @10.0.105.139 www.ejemplo.com ; <<>> DiG 9.10.3-P4-Debian <<>> @10.0.105.139 www.ejemplo.com ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 23296 ;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1 ;; WARNING: recursion requested but not available ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 1680 ;; QUESTION SECTION: ;www.ejemplo.com. IN A ;; ANSWER SECTION: www.ejemplo.com. 3600 IN CNAME ejemplo.com. ejemplo.com. 3600 IN A 1.2.3.4 ;; Query time: 1 msec ;; SERVER: 10.0.105.139#53(10.0.105.139) ;; WHEN: Fri Feb 16 18:05:21 CET 2018 ;; MSG SIZE rcvd: 74 root@dns2:~#
Se puede ver que el servidor está respondiendo adecuadamente.
2.5. Configuración del segundo servidor DNS
El segundo servidor lo hemos dejado únicamente con la base de datos de PowerDNS configurada, para que el servidor funcione tan solo será necesario instalar los paquetes de PowerDNS:
root@dns2:~# apt install pdns-server pdns-tools pdns-backend-mysql
Hay que acordarse de decirle que no configure la base de datos, si no, se corre el riesgo de perder los datos en este servidor, sino en el primero también puesto que la base de datos está replicada en modo Maestro/Maestro.
Repetir los puntos 2.2.2.1 y 2.2.2.2, pero en este nodo.
Después de configurar y reiniciar PowerDNS en el nodo 2 hago una petición desde el otro nodo para ver si responde la zona que se creó en el servidor DNS1:
root@dns1:~# dig @10.0.105.140 www.ejemplo.com ; <<>> DiG 9.10.3-P4-Debian <<>> @10.0.105.140 www.ejemplo.com ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 52643 ;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1 ;; WARNING: recursion requested but not available ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 1680 ;; QUESTION SECTION: ;www.ejemplo.com. IN A ;; ANSWER SECTION: www.ejemplo.com. 3600 IN CNAME ejemplo.com. ejemplo.com. 3600 IN A 1.2.3.4 ;; Query time: 6 msec ;; SERVER: 10.0.105.140#53(10.0.105.140) ;; WHEN: Sat Feb 17 18:37:44 CET 2018 ;; MSG SIZE rcvd: 74 root@dns1:~#
2.6. Configuración del Servidor esclavo
En este caso como será un servidor 100% autónomo se puede hacer una instalación tipo windows de “a todo que sí”.
apt install pdns-server pdns-backend-mysql pdns-tools mariadb-server
Si decimos a todo que sí, el servidor ya saldría con la base de datos configurada.
El fichero ‘/etc/powerdns/pdns.conf’ quedaría así:
allow-axfr-ips=10.0.0.0/16 api-key=hackme api-readonly=no api=yes disable-axfr=no include-dir=/etc/powerdns/pdns.d launch= local-address=0.0.0.0 local-ipv6= master=yes query-local-address=0.0.0.0 security-poll-suffix= setgid=pdns setuid=pdns slave-cycle-interval=20 slave=yes webserver-address=0.0.0.0 webserver-allow-from=0.0.0.0/0,::/0 webserver-password=hackme webserver-port=8081 webserver-print-arguments=yes webserver=yes
Un poco de aclaración en este fichero.
Si se quisiera un servidor DNS esclavo puro habría no habría que establecer la opción ‘allow-axfr-ips=10.0.0.0/16’, dado que el servidor solo recibiría actualizaciones, no las notificaría. Y esta otra, ‘disable-axfr=no’,habría que cambiarle el ‘no’ por un ‘yes’, por el mismo motivo.
La otra opción a tener en cuenta es ‘slave-cycle-interval=20’. Este parámetro, en segundos, en el Maestro establece cada cuanto tiempo tiene que comprobar su base de datos de seriales para enviar las notificaciones a los esclavos. En el esclavo es el número de segundos entre actualizaciones de zonas. Lo he puesto en 20 porque estoy haciendo pruebas, en el caso de ser un servidor en producción con vistas a internet y una considerable cantidad de zonas, habría que dejarlo como mínimo en su valor por defecto que es 60, o incluso subirlo a 120.
Comentarios recientes