POWERDNS

Nous avions depuis quelques années laissé la gestion de nos serveurs DNS au registrar bien connu OVH, et ceci principalement suite à diverses attaques que nous avions reçu sur nos DNS. Avec notre inscription au RIPE, nous allons avoir a gérer les reverses de nos IP Publiques. Nous avons alors 2 solutions : soit externaliser ceux-ci, soit installer nos propres serveurs DNS, comme nous l’avions fait dans le passé.

Ma principale problématique est la gestion de la sécurité sur ces DNS, en effet il y a quelques années nous avons subi beaucoup d’attaques. Suite à une discussion avec l’un de mes confrères chez FCNET, celui-ci me dit de regarder du coté de PowerDNS qui est en effet très avancé par rapport a Bind. Effectivement, celui-ci permet une gestion des tables DNS dans une base SQL au lieu des bons vieux fichiers de configuration.

Cerise sur le gâteau 🙂

J’ai mis en place un nouvel outil de gestion, pour faciliter la gestion de nos IP nommé « phpipam », qui est capable de remonter directement des infos du RIPE, et qui possède un module « PowerDNS » qui devrait grandement nous simplifier la gestion de nos adressages privés et publics au jour le jour.

Notre choix

Finalement nous allons mettre en place des serveurs DNS sous PowerDNS et utiliser dnsdist un nouveau processus développé par l’équipe de PowerDNS permettant de mettre en place de la haute disponibilité, et tous les outils permettant la gestion du DoS et abuse-aware.

http://www.dnsdist.org
https://www.powerdns.com

Nous allons utiliser POWERDNS avec un stockage des tables DNS dans une base de données MARIADB.

Nous aurons besoin sur cette machine d’un serveur Web / PHP, je suis donc la procédure d’installation d’un serveur LAMP.

Installation de PowerDNS

yum -y install pdns pdns-backend-mysql

mysql -u root -p

mysql> CREATE DATABASE powerdns;

mysql> GRANT ALL PRIVILEGES ON powerdns.* TO 'powerdns'@'localhost' IDENTIFIED BY 'powerdnsPassword';

mysql> use powerdns;
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);

On connecte PowerDNS à la base MARIADB

/etc/pdns/pdns.conf
launch=gmysql
gmysql-host=localhost
gmysql-user=powerdns
gmysql-password=powerdnsPassword
gmysql-dbname=powerdns

On démarre le service : 

systemctl enable pdns.service 
systemctl start pdns.service 

Installation de PowerAdmin
yum install httpd php php-devel php-gd php-imap php-ldap php-mysql php-odbc php-pear php-xml php-xmlrpc php-mbstring php-mcrypt php-mhash gettext
yum -y install php-pear-DB php-pear-MDB2-Driver-mysql 
# cd /var/www/html/
# wget http://downloads.sourceforge.net/project/poweradmin/poweradmin-2.1.7.tgz 
# tar xfv poweradmin-2.1.7.tgz

http://IP/poweradmin-2.1.7/install/

Une fois l’installation terminé, je fais un essai en créant un domaine de test : azylis.priv

la commande host ns.azylis.priv localhost me renvois bien un résultat.

Mon serveur DNS est opérationnel et résous les adresses stockées en base de données.

 

La récursivité

Pour que le serveur ne résolve pas seulement les adresses présentent dans la base de données, il va falloir l’autoriser a faire des requêtes à d’autres serveurs.

Pour cela nous allons ajouter au fichier de configuration de PowerDNS l’option

recursor=8.8.8.8

Mais attention en ajoutant uniquement cette option nous allons devenir un serveur OpenDNS, c’est à dire que n’importe qui sur Internet pourra utiliser nos DNS pour effectuer des requêtes, et cela n’est simplement pas possible pour des raisons des consommations de performances et de consommation de la bande passante Internet (nous laissons cela à Google :))

Nous allons donc ajouter l’option

allow-recursion=127.0.0.1/32, 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8, 185.165.64.0/22, 2a0b:6400::/29, ::1

Ce qui correspond aux IP de la RFC1918 ainsi que les plages d’IP dont nous avons la gestion.