samedi 23 novembre 2013

Connexion IPv6 à un serveur PostgreSQL

A la fin de ce billet (maintenant en partie obsolète), nous avons expliqué comment réaliser une connexion IPv4 entre un serveur PostgreSQL et une machine client située sur un réseau local.
Nous allons cette fois expliquer comment procéder pour une connexion IPv6.
Tout d'abord il s'agit d'adapter le fichier pg_hba.conf (situé sur le serveur).
Voici un extrait d'un tel fichier modifié en conséquence:

# TYPE  DATABASE        USER            ADDRESS                 METHOD
# "local" is for Unix domain socket connections only
local   all             all                                     peer  map=map01
# IPv4 local connections:
host    all             all             127.0.0.1/32            ident map=map01
# IPv4 lan connections
host    all             all             192.168.1.0/24          md5
# IPv6 local connections:
host    all             all             ::1/128                 md5
# IPv6  lan connections
host    all             all             fe80::/10               md5

(en bleu ce qui concerne les connexions réseau IPv4, en rouge les connexions IPv6)

Évidemment avec un tel fichier pg_hba.conf, pg_ident.conf doit contenir ce qui convient, par exemple:

# MAPNAME       SYSTEM-USERNAME         PG-USERNAME
map01           toto                    toto
map01           toto                    titine

pour que toto puisse se connecter lui-même ou en tant que titine.

Mais ceci nous éloigne du sujet, d'autant plus que les connexions qui nous intéressent ne sont pas concernées.

Revenons aux connexions réseau: les modifications à effectuer sur le fichier postgresql.conf sont les mêmes que celles présentées auparavant:

# - Connection Settings -
listen_addresses = '*' # what IP address(es) to listen on;
# comma-separated list of addresses;
# defaults to 'localhost', '*' = all
# (change requires restart)
port = 5432 # (change requires restart)

Si nous toutefois nous voulons accepter exclusivement les connexions IPv6, il suffit par exemple de remplacer

listen_addresses = '*'
par:
listen_addresses = '::'

Si un pare-feu est actif, il reste à y effectuer quelques petits aménagements.
Nous pouvons procéder avec gufw via l'onglet avancé du panneau 'Ajouter des règles":



Pour IPv4, nous ajoutons cette règle:


et pour IPv6 celle-ci:


Nous aurions pu agir en ligne de commande avec les commandes:

# ufw allow in from 192.168.1.0/24 to any port postgresql

# ufw allow in from fe80::/10 to any port postgresql

# ufw reload

Si le serveur est un serveur Fedora (utilisant firewalld), les commandes équivalentes sont:


firewall-cmd --permanent --add-rich-rule 'rule family="ipv4" source address="192.168.1.0/24" service name="postgres" accept'

# firewall-cmd --permanent --add-rich-rule 'rule family="ipv6" source address="fe80::/10" service name="postgres" accept'

# firewall-cmd --reload

En IPv4, nous avons configuré la connexion réseau de notre serveur pour que celui-ci dispose d'une adresse IP fixe (située dans une plage qui n'est pas accessible au serveur DHCP):


Nous pouvons connecter un terminal psql avec la commande
psql bd01 -h 192.168.1.2
(connexion de l'utilisateur courant à la base de données bd01).
Si dans le fichier /etc/hosts du poste client nous avons ajouté l'entrée:
192.168.1.2   rigel
(rigel étant le nom d'hôte de la machine serveur)
on peut alors utiliser la commande
psql bd01 -h rigel

(Rappelons que le mot de passe demandé est un mot de passe PostgreSQL et non un mot de passe système)

Pour se connecter en IPv6, il faut utiliser une autre adresse.
Cherchant des infos sur la connexion, nous obtenons ceci:

Mais l'adresse IPv6 qui apparaît ici n'est pas celle à utiliser: elle est destinée aux communications vers l'extérieur et de plus elle est temporaire.
La ligne de commande nous donne plus d'infos:

toto@rigel:~$ ifconfig
eth0      Link encap:Ethernet  HWaddr f4:6d:04:b6:41:4c 
          inet adr:192.168.1.2  Bcast:192.168.1.255  Masque:255.255.255.0
          adr inet6: 2a02:a03f:2082:2500:785e:2571:1adf:b2b6/64 Scope:Global
          adr inet6: 2a02:a03f:2082:2500:f66d:4ff:feb6:414c/64 Scope:Global
          adr inet6: fe80::f66d:4ff:feb6:414c/64 Scope:Lien

                    .................................

Nous découvrons l'existence d'une deuxième adresse IPv6 (adr inet6) destinée aux communications vers l'extérieur mais dont l'utilisation n'est pas privilégiée car elle est construite sur base de l'adresse matérielle.
La 3ième adresse IPv6 (également construite sur base de l'adresse matérielle) est celle qui nous intéresse.
Cependant la commande
 psql bd01 -h fe80::f66d:4ff:feb6:414c
produit le message d'erreur "psql: could not connect to server: Argument invalide":


L'astuce est qu'il faut faire suivre l'adresse de % puis de l'interface à utiliser (par exemple wlan0)pour atteindre la cible:


 Il faut procéder de même pour établir une connexion avec libreoffice:



Nous aimerions maintenant utiliser le nom d'hôte comme en IPv4.
Pour ce faire ajoutons dans le fichier /etc/hosts  du poste client la ligne 

fe80::f66d:4ff:feb6:414c    rigel6

Procédons:

 
Le message reçu est le même que pour la commande

 psql bd01 -h fe80::f66d:4ff:feb6:414c

Mais cette fois ajouter %wlan0 ne nous est d'aucun secours. On reçoit le message:

psql: could not translate host name "rigel6%wlan0" to address: Nom ou service inconnu

Nous pouvons contourner le problème en plaçant dans /usr/local/bin un script (que nous appelons ah et rendu exécutable avec la commande chmod +x) contenant:

#!/bin/sh

awk -v "var=$1" '$2 == var {print $1 "%wlan0"}' /etc/hosts

$1, paramètre transmis au script (rigel6) est sauvegardé dans var.
Ensuite $1 et $2 contiennent les champs de chaque ligne lue par awk.
L'action (print) est exécutée lorsque $2 vaut rigel6.

Vérifions que ça fonctionne:


Bingo!
Cependant ce moyen est inopérant sur l'écran de connexion libreoffice.
Il faut donc saisir pour se connecter à bd01

dbname:bd01 host=fe80::f66d:4ff:feb6:414c%wlan0

mais cela ne doit être effectué qu'une seule fois: lors de la création du fichier odb