Archives pour février, 2011

OpenSSH : multiplexage des connexions

Si comme moi, vous vous connectez plusieurs fois sur un même serveur SSH (perso, plus j’ai de term, plus je suis content), il existe une astuce pour éviter l’invite de mot de passe (le cas échéant) tout en gagnant en rapidité d’établissement.

OpenSSH peut en effet multiplexer plusieurs sessions – un shell, un envoi de fichier, une redirection de port est une session – dans un seul tunnel – une connexion réseau -. On évite donc de créer un tunnel supplémentaire, sa connexion associée, l’authentification, etc. Si un tunnel existe déjà, la session est alors directement ouverte et sans demande de mot de passe.

Si vous utilisez OpenVPN, le principe est exactement le même : toutes les connexions réseaux sont multiplexées dans un seul tunnel SSH.

Pour ce faire, méthode hard :

  • se connecter en mode master, en précisant un fichier socket pour nommer le tunnel et pouvoir le réutiliser par la suite :
bhuisgen:~ bhuisgen$ ssh user@host -M -S ~/.ssh/socket/tunnel

Le mot de passe est demandé (si non, votre clé SSH a été prise en compte, mais le temps d’établissement est plus rapide). Attention à ce que le répertoire ~/.ssh/socket existe bien au préalable.

  • ensuite pour tout autre session, faire un slave avec le fichier socket du tunnel :
bhuisgen:~ bhuisgen$ ssh user@host -S ~/.ssh/socket/tunnel

Et là, c’est le drame … la session s’ouvre directement, sans demande de mot de passe. A noter que le tunnel SSH n’est pas détruit tant que toutes les sessions slave ne sont pas terminées.

Maintenant, méthode playmobil : on automatise tout çà dans sa configuration comme un grand :

bhuisgen:~ bhuisgen$ more ~/.ssh/config
Host=*
ControlMaster auto
ControlPath ~/.ssh/sockets/ssh-socket-%r-%h-%p

Le multiplexage est désormais transparent et on en revient aux options habituelles :

bhuisgen:~ bhuisgen$ ssh user@host

OpenLDAP 2.4 : réplication d’un annuaire LDAP

Afin de déployer un annuaire LDAP au sein d’une entreprise, j’ai pour habitude d’avoir recours à la réplication d’OpenLDAP (version 2.4) en installant un serveur esclave sur chaque réseau secondaire.

La réplication LDAP a de multiples intérêts :

  • décharger votre serveur maître
  • accélérer les opérations de lecture
  • copier votre annuaire sur chaque esclave
  • déployer votre annuaire complet/en partie sur l’ensemble des réseaux

En cas d’opération d’écriture, le serveur esclave peut indiquer au client LDAP le nom du serveur maître afin d’y soumettre son opération.

La configuration à ajouter dans le fichier slapd.conf au niveau du serveur maître master.my.domain est la suivante :

overlay syncprov
syncprov-checkpoint 100 10
syncprov-sessionlog 100

Au niveau de l’esclave slave.my.domain, c’est un peu plus long :

syncrepl rid=1
    provider=ldap://master.my.domain
    type=refreshAndPersist
    searchbase="dc=my,dc=domain"
    scope=sub
    schemachecking=off
    bindmethod=simple
    binddn="cn=repl,dc=my,dc=domain"
    credentials=mypa$$w0rd
    starttls=yestls_key=/etc/openldap/my_domain.key
    tls_reqcert=never
updateref ldap://master.my.domain/

Un identifiant rid distinct est à spécifier pour chaque esclave. La réplication est ici du type refreshAndPersist : à chaque modification de l’annuaire, les esclaves se synchronisent. Il est possible de limite cette synchronisation à un intervalle de temps défini en utilisant le type refresh. L’option searchbase spécifie le DN où débute la réplication : l’annuaire peut être alors répliqué qu’en partie et non en totalité. Reste ensuite la déclaration du compte LDAP utilisé pour la connexion au maître (je vous conseille fortement une connexion par TLS). Côté maître, il faut s’assurer que les ACL permettent l’accès aux données à répliquer. Enfin, la dernière option permet de rediriger les clients sur le maître en cas d’opération d’écriture. Ce n’est pas obligatoire et permet de limiter l’accès en lecture seule à vos clients LDAP.

Pour les options avancées, je vous invite à consulter la documentation à ce sujet.

OpenVZ : accès IPv6 en mode Virtual Ethernet (veth)

Contrairement au mode routé venet, le mode virtual ethernet veth d’OpenVZ permet de mapper directement une interface virtuelle Ethernet depuis l’hôte réel dans un serveur virtuel. La virtualisation réseau ne s’effectue donc plus au niveau 3 (routage IP) mais au niveau 2 (Ethernet). Chaque interface virtuelle possède alors son adresse MAC., ce qui autorise le trafic multicast (par finalité DHCP, SMB) et la gestion iptables dans vos CT. Les interfaces réseaux sont d’ailleurs adressables dans le serveur virtuel, pour peu que le mappage soit effectué entre l’hôte réel et l’hôte virtuel.

Je vais expliquer  dans ce billet les points importants afin de configurer le mode veth en IPv4 mais surtout IPv6. Ceci ne vous empêche pas une configuration mixte venet & veth.

OpenVZ est installé sous un hôte réel Debian Lenny 64 bits. Au niveau de sa configuration réseau, une interface bridge vmbr0 est créée à laquelle j’ajoute les IP publiques du serveur  : une IPv6 et une IPv4 en alias. Par la suite, les interfaces réseaux virtuelles veth<CTID>.<ID> seront créées par OpenVZ, qui les ajoutera au bridge, tout en les mappant dans le CT considéré en interface eth<ID>.

root@HN:/# more /etc/network/interfaces
root@HN:/# network interface settings
auto lo
iface lo inet loopback

iface eth0 inet manual

auto vmbr0
iface vmbr0 inet6 static
 address  2001:1234:5678::2
 netmask  48
 gateway  2001:1234:5678::1
 bridge_ports eth0
 bridge_stp off
 bridge_fd 0
auto vmbr0:0
iface vmbr0:0 inet static
 address  81.23.45.226
 netmask  255.255.255.224
 gateway  81.23.45.225

Les paramètres noyaux suivants sont à fixer pour pouvoir bénéficier du support IPv4 et IPv6 depuis l’environnement virtualisé :

root@HN:/# more /etc/sysctl.conf
kernel.sysrq = 1
net.ipv4.ip_forward = 1
net.ipv4.conf.default.proxy_arp = 0
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.send_redirects = 1
net.ipv4.conf.all.send_redirects = 0
net.ipv6.conf.default.forwarding = 1
net.ipv6.conf.all.forwarding = 1
net.ipv6.conf.default.forwarding = 1
net.ipv6.conf.default.proxy_ndp = 1
net.ipv6.conf.all.proxy_ndp = 1
# custom
net.ipv6.conf.default.autoconf = 0
net.ipv6.conf.all.autoconf = 0

L’activation du forwarding IPv4 n’est nécessaire que si vos VPS sont susceptibles d’utiliser des adresses IP privées (le NAT devant être réalisé par un firewall). Le forwarding IPv6 est quant à lui obligatoire. Les deux dernièrs paramètres permettent de désactiver l’auto-configuration IPv6 des interfaces réseaux, ce qui sera répercuté dans les serveurs virtuels. Ceci n’est pas obligatoire, mais sécurise le tout en rendant obligatoire une configuration statique.

La création d’un CT en mode veth est simple, il suffit d’omettre la configuration réseau au moment de sa création :

root@HN:/# vzctl create 101 --ostemplate debian-6.0-standard_6.0-2_amd64

Par contre, il faut créer les interfaces réseaux par la suite :

root@HN:/# vzctl set 101 --netif_add eth0 --save
root@HN:/# vzctl set 101 --netif_add eth1 --save

Ici, j’ai créé la première interface pour son IPv6 et la seconde pour son IPv4. Le serveur virtuel peut maintenant être démarré :

# vzctl start 101
Starting container ...
Container is mounted
Setting CPU units: 1000
Setting CPUs: 1
Set hostname: vps101.interact.lu
File resolv.conf was modified
Setting quota ugidlimit: 0
Configure veth devices: veth101.0 veth101.1
Adding interface veth101.0 to bridge vmbr0 on CT0 for CT101
Adding interface veth101.1 to bridge vmbr0 on CT0 for CT101
Container start in progress...

OpenVZ a donc créé les interfaces veth101.0 (mappée sur eth0) et veth101.1 (mappée sur eth1), tout en les ajoutant à notre bridge vmbr0.

root@HN:/# vzctl enter 101

Avant de configuer les interfaces réseaux côté CT, il faut désactiver le forwarding :

root@HN:/# vzctl enter 101
root@CT:/# more /etc/sysctl.conf
net.ipv4.ip_forward = 0
net.ipv6.conf.all.forwarding = 0
net.ipv6.conf.all.mc_forwarding = 0

Au niveau de la configuration réseau dans le CT, rien de spécial à spécifier mais il faut forcer les routes par défaut. En IPv6, la route par défaut n’est pas appliquée par l’option gateway (peut être une subtilité Debian, rien de dramatique).J’ai donc recours aux options up :

root@CT:/# more /etc/network/interfaces
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet6 static
   address 2001:1234:5678::3
   netmask 48
   up /sbin/ip -6 route add default via 2001:1234:5678::1
auto eth1
  iface eth1 inet static
  address 81.23.45.227
  netmask 255.255.255.224
  up /sbin/ip route add default via 81.23.45.225

Reste à appliquer la nouvelle configuration  :

root@CT:/# /etc/init.d/networking restart
Running /etc/init.d/networking restart is deprecated because it may not enable again some interfaces ... (warning).
Reconfiguring network interfaces...done.

Puis à vérifier l’accès réseau :

root@CT:/# ifconfig
eth0      Link encap:Ethernet  HWaddr 1a:a5:96:8c:72:91
 inet6 addr: fe80::18a5:96ff:fe8c:7291/64 Scope:Link
 inet6 addr: 2001:1234:5678::3/48 Scope:Global
 UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
 RX packets:68106 errors:0 dropped:0 overruns:0 frame:0
 TX packets:33712 errors:0 dropped:0 overruns:0 carrier:0
 collisions:0 txqueuelen:0
 RX bytes:98987770 (94.4 MiB)  TX bytes:2480372 (2.3 MiB)

eth1      Link encap:Ethernet  HWaddr 00:18:51:e2:0e:f8
 inet addr:81.23.45.227  Bcast:81.23.45.255  Mask:255.255.255.224
 inet6 addr: fe80::218:51ff:fee2:ef8/64 Scope:Link
 UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
 RX packets:2194 errors:0 dropped:0 overruns:0 frame:0
 TX packets:74 errors:0 dropped:0 overruns:0 carrier:0
 collisions:0 txqueuelen:0
 RX bytes:101387 (99.0 KiB)  TX bytes:2743 (2.6 KiB)

lo        Link encap:Local Loopback
 inet addr:127.0.0.1  Mask:255.0.0.0
 inet6 addr: ::1/128 Scope:Host
 UP LOOPBACK RUNNING  MTU:16436  Metric:1
 RX packets:0 errors:0 dropped:0 overruns:0 frame:0
 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
 collisions:0 txqueuelen:0
 RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
root@CT:/# ping6 -c4 2001:1234:5678::1
PING 2001:1234:5678::1(2001:1234:5678::1) 56 data bytes
64 bytes from 2001:1234:5678::1: icmp_seq=1 ttl=64 time=0.460 ms
64 bytes from 2001:1234:5678::1: icmp_seq=2 ttl=64 time=0.445 ms
64 bytes from 2001:1234:5678::1: icmp_seq=3 ttl=64 time=0.422 ms
64 bytes from 2001:1234:5678::1: icmp_seq=4 ttl=64 time=0.420 ms

--- 2001:1610:4::1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 2998ms
rtt min/avg/max/mdev = 0.420/0.436/0.460/0.030 ms

Reste ensuite à sécuriser le tout en faisant votre parefeu iptables, mais ceci sera l’objet d’un article à venir.

OpenVZ : script de sauvegarde des CT

Voici le script que j’utilise pour dumper quotidiennement l’ensemble de mes CT OpenVZ. Outre les options de dump habituelles, il  est possible de préciser le nombre de dumps à conserver localement sur le HN et d’activer une copie des dumps par rsync sur un serveur distant, en vue de constituer un historique plus conséquent. Il est possible de limiter le débit I/O de génération des dumps (I/O disque) tout comme pour la copie (I/O réseau) afin d’éviter une perturbation conséquente de votre serveur.

Bref, c’est simple et efficace, donc à placer en cron très rapidement !

#!/bin/bash
#
# vzbackup.sh
#
# Boris HUISGEN <bhuisgen@hbis.fr>
#

PATH=$PATH:/usr/sbin

# backup settings

VZDUMP_DIR="/home/backup/vz"    # backup directory
VZDUMP_MODE="snapshot"          # dump mode (stop/suspend/snapshot)
VZDUMP_COMPRESS="yes"           # compress dump files (yes/no)
VZDUMP_MAXFILES="3"             # maximum backups per CT to keep in local
VZDUMP_BWLIMIT="0"              # limit I/O bandwith (unit kbytes/s, 0 to disable)
VZDUMP_EXTRA_OPTIONS=""         # extra options (man vzdump)

# remote copy settings

RSYNC_ENABLE="yes"              # copy backup directory to remote server (yes/no)
RSYNC_HOST="backup.my.domain"   # remote server host
RSYNC_USER="root"               # remote server user
RSYNC_DIR="/home/backup/mcbain" # remote server directory
RSYNC_DELETE="no"               # delete old backups on remote server (set to no to keep a remote historic)
RSYNC_BWLIMIT="0"               # limit I/O bandwith (unit kbytes/s, 0 to disable)
RSYNC_EXTRA_OPTIONS=""          # extra options (man rsync)

#
# DO NOT MODIFY AFTER THIS LINE !!!
#

VZLIST="$(which vzlist)"
VZDUMP="$(which vzdump)"
VZDUMP_OPTIONS="--stdexcludes"

RSYNC="$(which rsync)"
RSYNC_OPTIONS="-avz"

function log {
 echo "[" `date "+%Y-%m-%d %H:%M:%S"` "] $1"
}

# create backup directory
if [ ! -d $VZDUMP_DIR ]
then
 mkdir -p $VZDUMP_DIR;
fi

# set vzdump options
VZDUMP_OPTIONS="$VZDUMP_OPTIONS --$VZDUMP_MODE"

if [ $VZDUMP_COMPRESS = "yes" ]
then
 VZDUMP_OPTIONS="$VZDUMP_OPTIONS --compress"
fi

VZDUMP_OPTIONS="$VZDUMP_OPTIONS --maxfiles $VZDUMP_MAXFILES"

if [ $VZDUMP_BWLIMIT -gt "0" ]
then
 VZDUMP_OPTIONS="$VZDUMP_OPTIONS --bwlimit $VZDUMP_BWLIMIT"
fi

if [ -z $VZDUMP_EXTRA_OPTIONS ]
then
 VZDUMP_OPTIONS="$VZDUMP_OPTIONS $VZDUMP_EXTRA_OPTIONS"
fi

# set rsync options
if [ $RSYNC_DELETE = "yes" ]
then
 RSYNC_OPTIONS="$RSYNC_OPTIONS --delete"
fi

if [ $RSYNC_BWLIMIT -gt "0" ]
then
 RSYNC_OPTIONS="$RSYNC_OPTIONS --bwlimit=$RSYNC_BWLIMIT"fi
fi

if [ -z $RSYNC_EXTRA_OPTIONS ]
then
 RSYNC_OPTIONS="$RSYNC_OPTIONS $RSYNC_EXTRA_OPTIONS"
fi

# dump all CT
for CT in `$VZLIST -Ho veid`; do
 log "Starting backup of CT $CT..."

 # create CT directory
 VZDUMP_SUBDIR="$VZDUMP_DIR/$CT"
 if [ ! -d $VZDUMP_SUBDIR ]
 then
  mkdir $VZDUMP_SUBDIR
 fi

 # start vzdump
 $VZDUMP $VZDUMP_OPTIONS --dumpdir=$VZDUMP_SUBDIR $CT

 log "Backup done."
done

# copy backup directory to remote server
if [ $RSYNC_ENABLE = "yes" ]
then
 log "Synchronizing to remote server..."

 # start rsync
 $RSYNC $RSYNC_OPTIONS $VZDUMP_DIR/ $RSYNC_USER@$RSYNC_HOST:$RSYNC_DIR/

 log "Synchronization done."
fi

# end of script

Voici un exemple de sortie :

# ./vzbackup.sh
Starting backup of CT 101...
INFO: starting new backup job: vzdump --stdexcludes --snapshot --compress --maxfiles 4 --dumpdir=/home/backup/vz/101 101
INFO: Starting Backup of VM 101 (openvz)
INFO: CTID 101 exist mounted running
INFO: status = CTID 101 exist mounted running
INFO: backup mode: snapshot
INFO: ionice priority: 7
INFO: creating lvm snapshot of /dev/mapper/openvz-vz ('/dev/openvz/vzsnap-mcbain-0')
INFO:   Logical volume "vzsnap-mcbain-0" created
INFO: creating archive '/home/backup/vz/101/vzdump-openvz-101-2011_02_16-17_42_01.tgz'
INFO: Total bytes written: 2044569600 (2.0GiB, 8.9MiB/s)
INFO: archive file size: 1016MB
INFO:   Logical volume "vzsnap-mcbain-0" successfully removed
INFO: Finished Backup of VM 101 (00:05:24)
INFO: Backup job finished successfuly
Backup done.
Synchronizing to remote server...
sending incremental file list
101/
101/vzdump-openvz-101-2011_02_16-17_42_01.log
101/vzdump-openvz-101-2011_02_16-17_42_01.tgz
Synchronization done.
Haut de page