13/02/2010
Une fois que l'on a goûté aux jails, il devient difficile de s'en passer. Un nouveau projet, le test d'une configuration, tout est prétexte à un /etc/rc.d/jail start manouvellejail
Pour les loutres qui pensent que la solution officielle est un peu overkill, que le principe de lien+nullfs de ezjail ne correspond pas à leur besoin, je vous propose une solution à base de zfs, car zfs c'est le bien.
Bien qu'une telle solution me trottait dans la tête depuis un certain temps, je me suis largement inspiré de ce courriel.
On commence par télécharger le tgz-ki-va-bien.
> tar tzf jail.tgz
./jail/
./jail/tiny.jail
./jail/mk_template.sh
./jail/mk_jail.sh
./jail/medium.jail
./jail/large.jail
./jail/jail.common
Un rapide coup d'oeil dans mk_template.sh et jail.common nous apprend qu'il faut commencer par récupérer les sets base et manpages, sans doute la partie la plus difficile :).
Une fois cette délicate opération réalisée, à nous les joies de la création de jail:
> sudo ./mk_template.sh medium
Create 'medium' template
Create 'medium' fs
Populate 'medium'
Configure /etc/rc.conf for jail 'medium'
Configure 'medium'
Configure 'medium' /etc/rc.conf
Configure 'medium' /etc/ssh/sshd_config
Configure 'medium' /etc/resolv.conf
Configure 'medium' /etc/mail/submit.cf
Configure 'medium' /etc/periodic.conf
Configure 'medium' /etc/csh.cshrc
Configure 'medium'
'medium': done
Template medium is ready to snapshot
Next step:
- /etc/rc.d/jail start medium
- jexec medium /bin/csh
configure medium
add users (dsx)
add packages (sudo, rsync, vim, tmux ...)
...
- /etc/rc.d/jail stop medium
mk_jail medium www "lo1|172.16.0.1"
mk_jail medium www2 "lo1|172.16.0.2,em0|2001:a:b:c:d:e:f:80" /=5G
mk_jail medium www3 "vr0|2001:a:b:c:d:e:f:80" /=5G /tmp=1024M
Une jail de base est créée à partir de medium.jail. Une fois cette jail configurée on peut utiliser les fonctionnalités de zfs (snapshot + clone):
> sudo ./mk_jail.sh medium ldap "em0|2001:7a8:820:0:216:3eff:fe11:2231" /=1G /tmp=512M /var=1G
Create 'medium' snapshot
Done
Create 'medium' clone
Done
'ldap' is ready to start: /etc/rc.d/jail start ldap
Le tout est sous licence demerdeuneziziche et les modifications éventuelles sous licence larache. Enjoy :)
Update:
git clone git://repo.bsdsx.fr/mk_jail
Ou alors repo.bsdsx.fr
29/07/2009
Seul soucis:
dsx@linutop>ssh ns.bsdsx.fr df -h
Filesystem Size Used Avail Capacity Mounted on
zfs/jail/ns72 1.0G 157M 849M 16% /
Mais FreeBSD est suffisemment bien fait. Je me connecte sur le kimsufi où les sources sont disponibles. Je suis la procédure à la lettre. J'ai donc un bind 9 patché mais pas dans ma jail dns. Reste à mettre à jour la jail:
kimsufi>cd /usr/src/lib/bind
kimsufi>make DESTDIR=/zfs/jail/ns72 install
kimsufi>cd /usr/src/usr.sbin/named
kimsufi>make DESTDIR=/zfs/jail/ns72 install
Un restart pour finir:
dsx@linutop>ssh ns /etc/rc.d/named restart
Et voilà !
27/06/2009
Depuis FreeBSD 7.2, les jails peuvent avoir aucune, une ou des adresses ipv4 et/ou ipv6. Si l'utilisation d'une jail sans ip peut s'apparenter à un chroot, que faire de plusieurs ipv4/ipv6 ? Allons faire un tour au pays des jails.
/etc/rc.conf mono ip
jail_essai_rootdir=/zfs/jail/essai
jail_essai_hostname=essai.bsdsx.fr
jail_essai_ip=172.16.0.42
jail_essai_interface=lo1
jail_essai_devfs_enable="YES"
jail_essai_devfs_ruleset="devfsrules_jail"
Pour une jail à l'ancienne, il nous faut:
- une interface (ici lo1, clone de lo0)
- une ipv4 (172.16.0.42)
La configuration des services tournant dans cette jail est assez simple: tous les démons doivent écouter 172.16.0.42 (sshd -> ListenAddress, lighttpd -> server.bind, nginx -> listen ...)
/etc/rc.conf v4 + v6
jail_essai_rootdir=/zfs/jail/essai
jail_essai_hostname=essai.bsdsx.fr
jail_essai_devfs_enable="YES"
jail_essai_devfs_ruleset="devfsrules_jail"
jail_essai_ip="lo1|172.16.0.42,vr0|2001:41d0:1:34b6::42"
La syntaxe de l'option 'ip' a évolué. On peut désormais préciser l'interface d'une adresse ip. Ici, lo1 est notre interface privée et vr0 l'interface ipv6 publique.
> ifconfig
vr0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
options=2808<VLAN_MTU,WOL_UCAST,WOL_MAGIC>
ether 00:15:f2:5d:cc:a0
inet6 2001:41d0:1:34b6::17 prefixlen 128
media: Ethernet autoselect (100baseTX <full-duplex>)
status: active
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
lo1: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
inet 172.16.0.17 netmask 0xffffffff
pflog0: flags=141<UP,RUNNING,PROMISC> metric 0 mtu 33160
On remarquera l'apparition d'un lo0 (son absence dans les anciennes jails pouvait géner certains services). Les démons peuvent écouter sur toutes les interfaces, sans configuration particulière:
> grep ListenAddress /etc/ssh/sshd_config
#ListenAddress 0.0.0.0
#ListenAddress ::
> netstat -an -f inet
netstat: kvm not available: /dev/mem: No such file or directory
Active Internet connections (including servers)
Proto Recv-Q Send-Q Local Address Foreign Address (state)
tcp4 0 0 172.16.0.42.22 *.* LISTEN
> netstat -an -f inet6
netstat: kvm not available: /dev/mem: No such file or directory
Active Internet connections (including servers)
Proto Recv-Q Send-Q Local Address Foreign Address (state)
tcp6 0 48 2001:41d0:1:34b6.22 2a01:e35:2ee9:f6.35888 ESTABLISHED
tcp6 0 0 2001:41d0:1:34b6.22 *.* LISTEN
/etc/rc.conf v4 + multi v6
jail_essai_ip_multi0="vr0|2001:41d0:1:34b6::43"
jail_essai_ip_multi1="vr0|2001:41d0:1:34b6::44"
Simple non ? Attention à ne pas faire de trou dans la numérotation des multi car sinon le script /etc/rc.d/jail ne les prendra pas en compte.
> ifconfig
vr0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
options=2808<VLAN_MTU,WOL_UCAST,WOL_MAGIC>
ether 00:15:f2:5d:cc:a0
inet6 2001:41d0:1:34b6::42 prefixlen 128
inet6 2001:41d0:1:34b6::43 prefixlen 128
inet6 2001:41d0:1:34b6::44 prefixlen 128
media: Ethernet autoselect (100baseTX <full-duplex>)
status: active
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
lo1: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
inet 172.16.0.17 netmask 0xffffffff
pflog0: flags=141<UP,RUNNING,PROMISC> metric 0 mtu 33160
Utilisation
L'accès aux services des anciennes jails se faisait en ipv4 uniquement. A nous les joies des redirections/translations (mais pf est notre ami :)
nat on $ext_if from !($ext_if) -> ($ext_if:0)
rdr pass on $ext_if proto tcp from <ssh_ok> to port 65080 -> 172.16.0.1 port ssh
rdr pass on $ext_if proto tcp from <ssh_ok> to port 65081 -> 172.16.0.41 port ssh
Mais maintenant que nos jails sont ipv6 ready:
pass quick on $ext_if inet6 proto tcp from <ssh6_ok> to any port ssh
hostname et jail
Petite précision: le nom d'une jail peut contenir un underscore mais pas de tiret. Un nom d'hôte ne peut pas contenir d'underscore.
Et maintenant
Il ne me reste plus qu'à:
- renseigner mon dns (enregistrement AAAA)
- configurer mes reverses dns (que ovh propose, n'est-ce pas messieurs de chez free)
- générer des certificats SSL
- m'amuser avec nginx, sendmail, ldap, bind et j'en passe
En effet, avec toutes ces adresses disponibles, on peut vraiment affecter une ipv6 à un service et/ou un domaine virtuel (virtual host, ssl, wildcard, toussa... :)
24/06/2008
[ jail symon /var/empty ]
Ou comment ne pas casser son ssh.
J'ai décidé d'utiliser symon pour monitorer mon kimsufi. Le principe: sur l'hôte faire tourner la partie cliente (symon) qui envoie les données vers le collecteur (symux) dans une jail.
Je commence donc par installer symon dans la jail:
jail$ sudo pkg_add -r symon
Les rrdtools font partie du voyage et c'est tant mieux. Le package a créé un utilisateur _symon aux droits limités. Afin de garder un hôte le plus minimaliste possible, je copie uniquement la partie symon :
kimsufi# cp /zfs/jail/www/usr/local/bin/symon /usr/local/bin
kimsufi# cp /zfs/jail/www/usr/local/etc/rc.d/symon /usr/local/etc/rc.d/
kimsufi# cp /zfs/jail/www/usr/local/share/examples/symon/symon.conf /usr/local/etc/
Il ne me reste plus qu'à ajouter mon utilisateur _symon :
kimsufi# grep _symon /zfs/jail/www/etc/passwd
_symon:*:115:1:Symon Account:/var/empty:/usr/sbin/nologin
kimsufi# adduser
Et là c'est le drame. La grosse feign que je suis va ajouter un utilisateur dont le $HOME correspond à /var/empty. Pour bien comprendre le problème, je décide tout à coup de bien pourrir mon terminal avec un zcat /var/log/pflo.0.bz2. Une déconnexion plus tard et quelques reset, je me reconnecte au kimsufi:
maison# ssh kimsufi
ssh_exchange_identification: Connection closed by remote host
maison#
Sueurs froides, panique. Plus d'accès au kimsufi. Ké passa ? Un coup de netboot (FreeBSD 6.2: heureusement que mon / n'est pas en ZFS :), montage de la racine et direction les logs:
netboot# tail /mnt/var/log/auth.log
sshd[96744]: fatal: /var/empty must be owned by root and not group or world-writable
Et ben voila ! chmod 555 /var/empty, reboot sur hd et c'est reparti ! Conclusion: à trop vouloir faire le malin, on oublie les commandes essentielles:
jail$ pkg_info -i symon-2.75
Information for symon-2.75:
Install script:
#!/bin/sh
PATH=/bin:/usr/sbin
USER=_symon
GROUP=daemon
UID=115
case $2 in
PRE-INSTALL)
if pw user show "${USER}" 2>/dev/null; then
echo "You already have a user \"${USER}\", so I will use it."
else
if pw useradd ${USER} -u ${UID} -g ${GROUP} -h - \
-s /usr/sbin/nologin -L daemon -d /var/empty -c "Symon Account"
then
echo "Added user \"${USER}\"."
else
echo "Adding user \"${USER}\" failed..."
exit 1
fi
fi
;;
esac
A venir: je ne veux pas installer syweb (pas de php dans cette jail) pour afficher mes jolis graphes. rrcgi n'est pas encore mon ami mais je ne désespère pas :)
16/06/2008
[ freebsd kimsufi install jail ]
Prélude
Pour mon premier billet, je vais décrire l'installation de mon serveur. Après avoir pris un domaine chez gandi.net, j'ai commandé mon serveur dédié chez ovh (livré avec un peu de retard :) avec FreeBSD 7.0. Installation de la version 32 bits par défaut et un partitionnement des plus simple:
ks34581# cat /etc/fstab
# Device Mountpoint FStype Options Dump Pass#
/dev/ad4s1a / ufs rw 1 1
/dev/ad4s1b /home ufs rw 2 2
/dev/ad4s1d swap swap sw 0 0
proc /proc procfs rw 0 0
Depuis le manager je réinstalle la version 64 bits. J'en profite pour activer mon compte de backup.
Configuration de base
Modification du mot de passe root
ks34581# passwd
Suppression des getty inutiles
ks34581# grep "getty Pc" /etc/ttys
ttyv0 "/usr/libexec/getty Pc" cons25 on secure
ttyv1 "/usr/libexec/getty Pc" cons25 off secure
ttyv2 "/usr/libexec/getty Pc" cons25 off secure
ttyv3 "/usr/libexec/getty Pc" cons25 off secure
ttyv4 "/usr/libexec/getty Pc" cons25 off secure
ttyv5 "/usr/libexec/getty Pc" cons25 off secure
ttyv6 "/usr/libexec/getty Pc" cons25 off secure
ttyv7 "/usr/libexec/getty Pc" cons25 off secure
ks34581# kill -HUP 1
Heure locale
ks34581# cp /usr/share/zoneinfo/Europe/Paris /etc/localtime
Désactivation du module linux
ks34581# kldunload linux
ks34581# echo 'linux_enable="NO"' >> /etc/rc.conf
Activation de ZFS
ks34581# kldload zfs
ks34581# echo 'zfs_enable="YES"' >> /etc/rc.conf
Activation de lo1 (pour les jails)
ks34581# ifconfig lo1 create
ks34581# ifconfig lo1 inet 172.16.0.254 netmask 255.255.255.0
ks34581# echo 'network_interfaces="lo0 vr0 lo1"'
ks34581# echo '/sbin/ifconfig lo1 create' > /etc/start_if.lo1
ks34581# echo 'ifconfig_lo1="inet 172.16.0.254 netmask 255.255.255.0"' >> /etc/rc.conf
ks34581# echo '172.16.0.254 kimsufi.mondomaine.tld' >> /etc/hosts
ssh sur interface publique
ks34581# echo 'sshd_flags="-o ListenAddress=<mon.ip.publique>"' >> /etc/rc.conf
syslog en mode local
ks34581# echo 'syslogd_flags="-ss"' >> /etc/rc.conf
named ip v4 only
ks34581# echo 'named_flags="-4"' >> /etc/rc.conf
named sur interface privée
ks34581# grep 172.16.0.254 /etc/named/named.conf
listen-on { 127.0.0.1; 172.16.0.254; };
Sauvegarde
Pour l'instant, un simple backup ftp fera l'affaire. Je commence par automatiser l'accès au backup:
ks34581# cat >> /root/.netrc
machine backup
login <votre_login>
password <votre_mot_de_passe>
^D
ks34581# chmod 600 /root/.netrc
ks34581# echo "<adresse.ip.du.backup> backup" >> /etc/hosts
Un script sans prétention:
ks34581# cat /root/bin/backup.sh
#!/bin/sh
set -- `date "+%Y%m%d"`
TBZ=kimsufi-$1.tbz
tar cjf $HOME/tmp/$TBZ -T $HOME/etc/backup.cfg 2>/dev/null
cd $HOME/tmp
echo "put $TBZ" | ftp -V backup
Un fichier de configuration minimal:
ks34581# cat /root/etc/backup.cfg
/etc/rc.conf
/etc/ttys
/etc/start_if.lo1
/etc/namedb/named.conf
/root/.netrc
/root/etc/backup.cfg
/root/bin/backup.sh
Tous les jours à 2h45 du matin:
ks34581# echo '45 2 * * * $HOME/bin/backup.sh' >> /root/.crontab
ks34581# crontab .crontab
ks34581# echo '/root/.crontab' >> /root/etc/backup.cfg
Courriel
Pour l'instant, l'installation de base de FreeBSD me permet d'envoyer des courriels. J'ajuste la configuration de sendmail pour que les jails puissent en profiter. Une jail smtp est prévue pour plus tard.
ks34581# cd /etc/mail
ks34581# echo 'root: <une.adresse@email.valide>' >> aliases
ks34581# make aliases
Pour pouvoir être utilisé par les jails, sendmail doit écouter sur 172.16.0.254:
ks34581# sed -I'.orig' -e 's/^DS/DS[172.16.0.254]/' /etc/mail/submit.cf
ks34581# echo 'sendmail_submit_flags="-L sm-mta -bd -q30m -ODaemonPortOptions=Addr=172.16.0.254"' >> /etc/rc.conf
ks34581# echo '/etc/mail/submit.cf' >> $HOME/etc/backup.cfg
Il doit aussi accepter de relayer les jails:
ks34581# cat /etc/mail/relay-domains
ks34581.kimsufi.com
localhost
127.0.0.1
.mondomaine.tld
ks34581# make restart
ks34581# echo '/etc/mail/relay-domains' >> /root/etc/backup.cfg
Pf
Les jails seront sur le réseau 172.16.0.x, interface lo1. Pour accèder à ces jails du NAT s'impose:
ks34581# echo 'pf_enable="YES"' >> /etc/rc.conf
ks34581# echo 'pflog_enable="YES"' >> /etc/rc.conf
Un (trop) simple /etc/pf.conf:
ext_if="vr0"
int_if="lo1"
set block-policy return
set loginterface $ext_if
set skip on lo0
scrub in
nat on $ext_if from !($ext_if) -> ($ext_if:0)
block log on $ext_if
antispoof quick for { lo0 $int_if }
pass in on $ext_if inet proto tcp from any to ($ext_if) port ssh
pass quick on $int_if
pass out on $ext_if
Seul le ssh du kimsufi est accessible. Je rajouterai les règles rdr et pass au fur et à mesure. Je croise les doigts (un pf.conf qui bloque est si vite arrivé :) et hop:
ks34581# pfctl -n -f /etc/pf.conf
ks34581# /etc/rc.d/pf start
ks34581# echo '/etc/pf.conf' >> /root/etc/backup.cfg
Jail et Zfs
J'utilise Zfs pour définir les partitions de mes jails. N'ayant qu'une seule partition physique à ma disposition, je ne peux pas utiliser les fonctions mirror, raid, raidz ... Je ne compte que sur mes backup !
ks34581# umount /home
ks34581# cat /etc/fstab
# Device Mountpoint FStype Options Dump Pass#
/dev/ad4s1a / ufs rw 1 1
#/dev/ad4s1b /home ufs rw 2 2
/dev/ad4s1d swap swap sw 0 0
proc /proc procfs rw 0 0
ks34581# zpool create zfs /dev/ad4s1b
ks34581# zfs create zfs/jail
J'active les jails. jail_list est volontairement vide afin de ne pas démarer automatiquement une jail tant qu'elle n'est pas validée (un reboot du serveur est si vite arrivé :)
ks34581# cat >>/etc/rc.conf
jail_enable="YES"
jail_list=""
jail_set_hostname_allow="NO"
# pour postgresql et symon
jail_sysvipc_allow="YES"
^D
Un script pour simplifier l'installation d'une jail:
ks34581# cat /root/bin/mk_jail.sh
1 #!/bin/sh
2
3 JROOT=zfs/jail
4 FTP=ftp://ftp.fr.freebsd.org/pub/FreeBSD
5 CFG=$HOME/tmp/sysinstall.cfg
6 IFNAME=lo1
7
8 NAME=$1
9 SIZE=$2
10 HOSTNAME=$3
11 IP=$4
12
13 zfs create -o quota=${SIZE}M $JROOT/$NAME
14 zfs create -o quota=512M $JROOT/$NAME/tmp
15 zfs create -o quota=512M $JROOT/$NAME/var
16
17 cat <<EOF >$CFG
18 installRoot=/$JROOT/$NAME
19 _ftpPath=$FTP
20 mediaSetFTP
21 dists=base
22 distSetCustom
23 installCommit
24 EOF
25
26 sysinstall configFile=$CFG loadConfig
27
28 cat <<EOF >> /etc/rc.conf
29 jail_${NAME}_rootdir=/$JROOT/$NAME
30 jail_${NAME}_hostname=$HOSTNAME
31 jail_${NAME}_ip=$IP
32 jail_${NAME}_interface=$IFNAME
33 jail_${NAME}_devfs_enable="YES"
34 jail_${NAME}_devfs_ruleset="devfsrules_jail"
35 EOF
36
37 echo "$IP $HOSTNAME" >> /etc/hosts
38
39 cat <<EOF > /$JROOT/$NAME/etc/rc.conf
40 sshd_enable="YES"
41 sshd_flags="-o ListenAddress=$IP"
42 syslogd_flags="-ss"
43 sendmail_enable="NONE"
44 EOF
45
46 cat <<EOF >> /$JROOT/$NAME/etc/hosts
47 $IP $HOSTNAME
48 213.251.173.2 backup
49 172.16.0.254 kimsufi.mondomaine.tld
50 EOF
51
52 cat <<EOF > /$JROOT/$NAME/etc/resolv.conf
53 nameserver 172.16.0.254
54 EOF
55
56 sed -I'.orig' -e 's/^DS/DS[172.16.0.254]/' /$JROOT/$NAME/etc/mail/submit.cf
57
58 cp /etc/localtime /$JROOT/$NAME/etc
- lignes 3-6: quelques variables
- lignes 8-11: configuration de la jail
- lignes 13-15: création des partitions
- lignes 17-24: je scripte l'utilisation de sysinstall pour l'installation d'un système de base.
- ligne 26: installation du système de base
- lignes 28-35: configuration du démarrage de la jail côté serveur
- ligne 37: en attendant de configurer le named du serveur
- lignes 39-44: services lancés au démarrage de la jail
- lignes 46-50: configuration réseau de la jail
- lignes 52-54: utilisation du named du serveur
- ligne 56: le sendmail de la jail va utiliser le sendmail du serveur
- ligne 58: heure locale
Et c'est parti:
ks34581# /root/bin/mk_jail.sh toto 4096 toto.mondomaine.tld 172.16.0.1
Je vérifie que tout se passe bien à coup de:
- jls
- jexec <id> /bin/tcsh
- ps
- sockstat -4
- tail /var/log/messages
Tout est OK, je peux activer cette jail au démarrage du serveur:
ks34581# grep jail_list /etc/rc.conf
jail_list="toto"
Si toto.mondomaine.tld pointe bien vers l'adresse publique du serveur, il ne reste plus que la configuration de pf:
ks34581# cat /etc/pf.conf
[ snip ]
rdr pass on $ext_if proto tcp to port 65080 -> 172.16.0.1 port ssh
rdr pass on $ext_if proto tcp to port http -> 172.16.0.1 port http
pass quick on $ext_if inet proto tcp from any to 172.16.0.1 port ssh
pass quick on $ext_if inet proto tcp from any to 172.16.0.1 port http
[ snip ]
Ici la jail ayant pour ip 172.16.0.1 fait tourner un serveur web et son serveur ssh est accessible depuis ip.publique.du.kimsufi port 65080
A faire
- jouer avec named et les views (publique / jail)
- jail lighttpd + symon
- jail postgresql
- jail smtp+dspam
- jail dev
- limiter la taille des billet :)
- poufiner la conf de nanoblogger
Pages : 1
Rss