Ce tutoriel est conçu pour le système Debian 8 (jessie). J'utilise la version 4 du PowerDNS et la répositoire du développeur.

Installation du MySQL

apt-get install mysql-server mysql-client

Dans les examples ci-dessous j'utilise la commande suivant lors de la connexion à MySQL.

mysql -u root -p

Installation et configuration du PowerDNS 4

echo "deb http://repo.powerdns.com/debian jessie-auth-40 main" >> /etc/apt/sources.list.d/pdns.list
wget -O - https://repo.powerdns.com/FD380FBB-pub.asc | sudo apt-key add -
echo "Package: pdns-*
Pin: origin repo.powerdns.com
Pin-Priority: 600" > /etc/apt/preferences.d/pdns
apt-get update
apt-get install pdns-server pdns-backend-mysql

https://doc.powerdns.com/md/authoritative/installation/

Création de l'utilisateur de base de données.

mysql>
create database pdns;
grant all on pdns.* to pdnsusr@localhost identified by 'pdnspw';
grant usage on *.* to pdnsusr@localhost;

https://doc.powerdns.com/md/authoritative/howtos/#basic-setup-configuring-database-connectivity

Chargement du schéma de base de données dans la base de données.

mysql>
CREATE TABLE domains (
 id                    INT AUTO_INCREMENT,
 name                  VARCHAR(255) NOT NULL,
 master                VARCHAR(128) DEFAULT NULL,
 last_check            INT DEFAULT NULL,
 type                  VARCHAR(6) NOT NULL,
 notified_serial       INT DEFAULT NULL,
 account               VARCHAR(40) DEFAULT NULL,
 PRIMARY KEY (id)
) Engine=InnoDB;

CREATE UNIQUE INDEX name_index ON domains(name);

CREATE TABLE records (
 id                    INT AUTO_INCREMENT,
 domain_id             INT DEFAULT NULL,
 name                  VARCHAR(255) DEFAULT NULL,
 type                  VARCHAR(10) DEFAULT NULL,
 content               VARCHAR(64000) DEFAULT NULL,
 ttl                   INT DEFAULT NULL,
 prio                  INT DEFAULT NULL,
 change_date           INT DEFAULT NULL,
 disabled              TINYINT(1) DEFAULT 0,
 ordername             VARCHAR(255) BINARY DEFAULT NULL,
 auth                  TINYINT(1) DEFAULT 1,
 PRIMARY KEY (id)
) Engine=InnoDB;

CREATE INDEX nametype_index ON records(name,type);
CREATE INDEX domain_id ON records(domain_id);
CREATE INDEX recordorder ON records (domain_id, ordername);

CREATE TABLE supermasters (
 ip                    VARCHAR(64) NOT NULL,
 nameserver            VARCHAR(255) NOT NULL,
 account               VARCHAR(40) NOT NULL,
 PRIMARY KEY (ip, nameserver)
) Engine=InnoDB;

CREATE TABLE comments (
 id                    INT AUTO_INCREMENT,
 domain_id             INT NOT NULL,
 name                  VARCHAR(255) NOT NULL,
 type                  VARCHAR(10) NOT NULL,
 modified_at           INT NOT NULL,
 account               VARCHAR(40) NOT NULL,
 comment               VARCHAR(64000) NOT NULL,
 PRIMARY KEY (id)
) Engine=InnoDB;

CREATE INDEX comments_domain_id_idx ON comments (domain_id);
CREATE INDEX comments_name_type_idx ON comments (name, type);
CREATE INDEX comments_order_idx ON comments (domain_id, modified_at);

CREATE TABLE domainmetadata (
 id                    INT AUTO_INCREMENT,
 domain_id             INT NOT NULL,
 kind                  VARCHAR(32),
 content               TEXT,
 PRIMARY KEY (id)
) Engine=InnoDB;

CREATE INDEX domainmetadata_idx ON domainmetadata (domain_id, kind);

CREATE TABLE cryptokeys (
 id                    INT AUTO_INCREMENT,
 domain_id             INT NOT NULL,
 flags                 INT NOT NULL,
 active                BOOL,
 content               TEXT,
 PRIMARY KEY(id)
) Engine=InnoDB;

CREATE INDEX domainidindex ON cryptokeys(domain_id);

CREATE TABLE tsigkeys (
 id                    INT AUTO_INCREMENT,
 name                  VARCHAR(255),
 algorithm             VARCHAR(50),
 secret                VARCHAR(255),
 PRIMARY KEY (id)
) Engine=InnoDB;

CREATE UNIQUE INDEX namealgoindex ON tsigkeys(name, algorithm);

Configuration du PowerDNS pour l'utilisation du backend MySQL.

echo "launch=gmysql
gmysql-host=127.0.0.1
gmysql-user=pdnsusr
gmysql-dbname=pdns
gmysql-password=pdnspw" > /etc/powerdns/pdns.d/pdns.mysettings.conf

systemctl restart pdns

Importation de zones dans la base de données du PowerDNS

zone2sql --named-conf=/etc/bind/named.conf --gmysql --slave | mysql -u pdnsusr -p pdns

https://doc.powerdns.com/md/authoritative/migration/#from-zonefiles-to-powerdns

Mise en place du DNSSEC, migration des clés

On récupère les clés du SoftHSM. On a besoin du CKA_ID pour l'exportation softhsm.

$ ods-ksmutil key list --verbose
SQLite database set to: /var/lib/opendnssec/kasp.db
Keys:
Zone:         Keytype:  State:   Date of next transition (to):  Size:  Algorithm:  CKA_ID:     Repository:  Keytag:
example.com   ZSK       active   2016-10-09 07:32:33 (retire)   1024   8           hf78o4h...  SoftHSM      64812
example.com   KSK       active   2017-06-01 11:51:39 (retire)   2048   8           3892zhr...  SoftHSM      53675

On a besoin du Token label de la liste des slots.

softhsm --show-slots
Available slots:
Slot 0
          Token present: yes
          Token initialized: yes
          User PIN initialized: yes
          Token label: OpenDNSSEC

L'id vient de la ligne KSK (CKA_ID) de la commande ods-ksm-util key list --verbose example.com.

softhsm --export ksk.pem --slot 0 --label "OpenDNSSEC" --pin 12345678 --id 3892zhr...

https://wiki.opendnssec.org/display/DOCS/Migrating+to+OpenDNSSEC

Il faut convertir le format PEM en BIND et importer la clé.

softhsm-keyconv --tobind --in ksk.pem --name example.com --ksk --algorithm RSASHA256
pdnsutil import-zone-key example.com Kksk+008+53675.private active ksk

Les autres KSK actifs peuvent être inactivés ou supprimés. L'id 12 n'est qu'un exemple.

pdnsutil list-keys example.com
pdnsutil remove-zone-key example.com 12

La migration de la configuration NSEC3 de l'OpenDNSSEC vers PowerDNS commence par la vue de la section <Denial> du fichier /etc/opendnssec/kasp.xml. Le content des éléments <OptOut> et <Iterations> peuvent être migrer directement. Concernant les autres éléments, consultez RFC 5155, et la section 10.3 du RFC 5155.

Une partie du fichier /etc/opendnssec/kasp.xml:

...
       <Denial>
           <NSEC3>
               <TTL>PT3600S</TTL>
               <!-- <OptOut/> -->
               <Resalt>P100D</Resalt>
               <Hash>
                   <Algorithm>1</Algorithm>
                   <Iterations>5</Iterations>
                   <Salt length="8"/>
               </Hash>
           </NSEC3>
       </Denial>
...

Une configuration PowerDNS possible se basant de ci-dessus (voir man pdnsutil):

pdnsutil set-nsec3 1 0 5 abcdef01

Deux PowerDNS avec MySQL replication maitre-esclave, et connexion SSL

Le mode de réplication conseillé du PowerDNS est d'utiliser la replication de la système de réplication de la systeme de base de données.

https://doc.powerdns.com/md/authoritative/modes-of-operation/#native-replication

Création du CA SSL et des certificats

Il faut créer une chaîne de certificat pour les serveurs MySQL.

Création du CA.

mkdir mysqlcerts
cd mysqlcerts/
openssl genrsa 2048 > ca-key.pem
openssl req -new -x509 -nodes -days 3600 -key ca-key.pem -out ca.pem

Création du certificat du serveur pdns1.

openssl req -newkey rsa:2048 -days 3600 -nodes -keyout pdns1-key.pem -out pdns1-req.pem
openssl rsa -in pdns1-key.pem -out pdns1-key.pem
openssl x509 -req -in pdns1-req.pem -days 3600 -CA ca.pem -CAkey ca-key.pem -set_serial 01 -out pdns1-cert.pem

Création du certificat du serveur pdns2.

openssl req -newkey rsa:2048 -days 3600 -nodes -keyout pdns2-key.pem -out pdns2-req.pem
openssl rsa -in pdns2-key.pem -out pdns2-key.pem
openssl x509 -req -in pdns2-req.pem -days 3600 -CA ca.pem -CAkey ca-key.pem -set_serial 01 -out pdns2-cert.pem

Vérification des certificats.

openssl verify -CAfile ca.pem pdns1-cert.pem pdns2-cert.pem

https://dev.mysql.com/doc/refman/5.5/en/creating-ssl-files-using-openssl.html

Mise en place de la réplication MySQL maître

Mise en place du serveur maître.

echo "[mysqld]
bind-address            = 0.0.0.0
server-id               = 1
log_bin = /var/log/mysql/mysql-bin.log
binlog_do_db = pdns
binlog_format = MIXED

ssl-ca=/etc/mysql/ca.pem
ssl-cert=/etc/mysql/pdns1-cert.pem
ssl-key=/etc/mysql/pdns1-key.pem" >> /etc/mysql/conf.d/mymaster.cnf

systemctl restart mysql
mysql>
GRANT REPLICATION SLAVE ON *.* TO 'pdnsusrslave'@'%' IDENTIFIED BY 'pdnspwslave' require ssl;
FLUSH PRIVILEGES;
use pdns;
FLUSH TABLES WITH READ LOCK;
SHOW MASTER STATUS;

Nouveau shell:

mysqldump -u root -p --opt pdns > pdns.sql

Retour au MySQL:

mysql>
UNLOCK TABLES;
QUIT;

Mise en place de la réplication MySQL esclave

mysql>
CREATE DATABSE pdns;
EXIT;
mysql -u root -p pdns < pdns.sql
echo "[mysqld]
bind-address = 0.0.0.0
server-id = 2
relay-log               = /var/log/mysql/mysql-relay-bin.log
log_bin = /var/log/mysql/mysql-bin.log
binlog_do_db = pdns
binlog_format = mixed

ssl-ca=/etc/mysql/ca.pem
ssl-cert=/etc/mysql/pdns2-cert.pem
ssl-key=/etc/mysql/pdns2-key.pem" >> /etc/mysql/conf.d/myslave.cnf

systemctl restart mysql
mysql>
CHANGE MASTER TO MASTER_HOST='<MASTER_HOST>',MASTER_USER='pdnsusrslave', MASTER_PASSWORD='pdnspwslave', MASTER_LOG_FILE='mysql-bin.000035', MASTER_LOG_POS=790, MASTER_SSL=1, MASTER_SSL_CA='/etc/mysql/ca.pem', MASTER_SSL_CERT='/etc/mysql/pdns2-cert.pem', MASTER_SSL_KEY='/etc/mysql/pdns2-key.pem';
START SLAVE;
SHOW SLAVE STATUS\G

Si cela ne marche pas:

mysql>
SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1;
SLAVE STOP;
SLAVE START;

https://dev.mysql.com/doc/refman/5.5/en/replication-solutions-secure-connections.html