Sauvegarde – via RSS

Un petit hack de 5min pour télécharger des sauvegardes via un agrégateur RSS.

Pour faire court, je cherchai un moyen simple, fiable et peu couteux en temps de rapatrier automatiquement les sauvegardes de ce site chez moi, sur mon NAS (un Synology).

Il existe plein de manière de le faire, mais je voulais un truc qui marche tout de suite sans installer quoi que ce soit d’un coté (serveur) ou de l’autre (NAS).

Ce NAS dispose d’un logiciel bien pratique pour télécharger automatiquement des podcasts via leurs flux RSS, j’ai donc décidé de m’en servir pour récupérer mes sauvegardes. Il faut juste lui donner l’adresse d’un XML et lui dire où copier les données.

Le script suivant permet de générer ce XML :

#!/bin/bash
#une petite rotation avant de créer le XML
/usr/sbin/logrotate -f  /etc/logrotate.d/backup
#emplacement des fichiers à récupérer
BASEDIR='/home/backups'
#adresse à utiliser pour les liens vers les fichiers
URL='http://mon.serveur.internet'
DATE=`date -R`
cd $BASEDIR
#une petite boucle qui va créer un XML pour chaque dossier
for DIR in `ls`;do
    Dtype=`stat --printf="%F" $DIR`
    if [ "$Dtype" == "directory" ]; then
        echo '<?xml version="1.0" ?>
            <rss version="2.0">
                <channel>
                    <title>Les fichiers du dossier '$DIR'</title>
                    <link>'$URL'/'$DIR'.xml</link>
                    <description>Backup '$DIR'</description>
                    <lastBuildDate>'$DATE'</lastBuildDate>'
        > $BASEDIR/$DIR.xml
        #une autre boucle qui va créer une entrée "item" pour chaque fichier
        cd $DIR
        for FILE in `find . -type f`; do
            Fname=`basename $FILE`
            Fsize=`stat --printf=%s $FILE`
            Fdate=`stat --printf=%Y $FILE`
            Fdate=`date -R -d @$Fdate`
            Fmime=`file --mime-type $FILE | awk '{print $2}'`
            echo '<item>
                <title>'$Fname'</title>
                <guid isPermaLink="false">'$URL'/'$DIR'/'$Fname'</guid>
                <pubDate>'$Fdate'</pubDate>
                <enclosure url="'$URL'/'$DIR'/'$Fname'" length="'$Fsize'" type="'$Fmime'"></enclosure>
            </item>'
            >> $BASEDIR/$DIR.xml
        done
        echo '</channel>
        </rss>' >> $BASEDIR/$DIR.xml
        cd $BASEDIR
    fi
done

Il ne reste plus qu’à planifier l’exécution de ce script sur le serveur afin qu’il actualise les XML et à donner leurs adresses au NAS qui se charge du reste (il va régulièrement vérifier si le flux RSS a été mis à jour et le cas échéant télécharge les nouvelles sauvegardes).

Je n’ai pas testé avec d’autres logiciels de podcast (je n’utilise que celui de Synology), mais ça devrait marcher avec la plupart d’entre eux.

Veillez bien à ce que ces XML et surtout les fichiers qui y sont référencés (vos sauvegardes) ne soient pas accessibles à tout le monde !!!!

Freeradius – ActiveDirectory

Cet article montre les étapes nécessaires à l’utilisation de Freeradius sur une Debian Wheezy pour authentifier les utilisateurs sur un serveur ActiveDirectory (Windows Server 2012).

Les requêtes EAP seront encapsulées en TTLS ou en PEAP, l’authentification sera effectuée via un challenge EAP MSCHAP v2.

La partie proxy sera aussi configurée pour permettre l’authentification via d’autres serveurs radius disposant de leurs propres bases d’utilisateurs.

Informations générales

  • domaine DNS : test.example.org
  • domaine NetBios : TEST
  • nom du serveur AD : ad.test.example.org
  • adresse du DNS de l’AD : 10.0.0.1

Une parfaite résolution DNS est essentielle à tout système, en particulier quand il y a un annuaire ActiveDirectory. On modifie donc les paramètres DNS de la Debian pour utiliser le DNS de l’AD.

#/etc/hosts
127.0.0.1       radius.test.example.org localhost radius
#/etc/resolv.conf
domain test.example.org
search test.example.org
nameserver 10.0.0.1

De même une synchronisation horaire précise est essentielle. On modifie donc la configuration NTP pour utiliser le serveur AD comme source de temps. Ici j’utilise openntp :

#/etc/openntpd/ntpd.conf
servers test.example.org

J’utilise le nom du domaine de l’AD pour profiter du RR DNS.
On redémarre le serveur pour bien prendre en compte les modifications.

Intégration du serveur dans l’ActiveDirectory

Installation des paquets

aptitude install samba winbind samba-common-bin krb5-user

Kerberos

L’utilisation de Kerberos n’est pas indispensable pour joindre une machine à l’AD, mais elle est recommandée.

Configuration

La casse est importante dans le protocole Kerberos, par convention on utilise le nom DNS en majuscule pour les royaumes.

#/etc/krb5.conf
[libdefaults]
default_realm = TEST.EXAMPLE.ORG
krb4_config = /etc/krb.conf
krb4_realms = /etc/krb.realms
kdc_timesync = 1
ccache_type = 4
forwardable = true
proxiable = true
v4_instance_resolve = false
v4_name_convert = {
    host = {
        rcmd = host
        ftp = ftp
    }
    plain = {
        something = something-else
    }
}
fcc-mit-ticketflags = true

[realms]
TEST.EXAMPLE.ORG = {
    kdc = ad.test.example.org:88
    admin_server = ad.test.example.org
    default_domain = test.example.org
}

[domain_realm]
.test.example.org = TEST.EXAMPLE.ORG
test.example.org = TEST.EXAMPLE.ORG
[login]
krb4_convert = true
krb4_get_tickets = false

Récupération d’un ticket Kerberos

kinit administrator@TEST.EXAMPLE.ORG

Vérification du ticket

klist
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: administrator@TEST.EXAMPLE.ORG
[...]

Samba

Configuration

#/etc/samba/smb.conf
[global]
workgroup = TEST
server string = %h server
dns proxy = no
log file = /var/log/samba/log.%m
max log size = 1000
syslog = 0
panic action = /usr/share/samba/panic-action %d
security = ads
realm = TEST.EXAMPLE.ORG
password server = ad.test.example.org
winbind use default domain = yes
domain master = no
local master = no
preferred master = no
winbind enum groups = yes
winbind enum users = yes
winbind use default domain = no
encrypt passwords = true

Redémarrage de Samba

service samba restart

Intégration dans l’AD

net ads join -U administrator

Si le ticket Kerberos est valide, vous devriez obtenir le message suivant :

Using short domain name -- TEST
Joined 'RADIUS' to realm 'test.example.org'

Dans le cas contraire, ou en l’absence de Kerberos, vous obtiendrez ceci :

Using short domain name -- TEST
Joined 'RADAD' to realm 'test.example.org'
DNS Update for radius.test.example.org failed: ERROR_DNS_GSS_ERROR
DNS update failed!

Les 2 dernières lignes indiquent que l’ajout du serveur dans le DNS de l’AD a échoué, cela n’a rien d’anormal si vous n’utilisez pas Kerberos ou si vos DNS n’acceptent pas la création dynamique d’objets, il vous suffit d’aller créer manuellement une entrée pour votre serveur Linux dans le DNS de l’AD.
Si vous obtenez autre chose, c’est probablement qu’il y a un problème de résolution de nom ou de configuration.

Redémarrage de WinBind

service winbind restart

Tests de la liaison avec l’annuaire

Test de la connexion RCP :

wbinfo -t
checking the trust secret for domain TEST via RPC calls succeeded

Lister les utilisateurs de l’annuaire (attention si vous avez un grand nombre de comptes) :

wbinfo -u
TESTadministrator
TESTguest
TESTkrbtgt
[...]

Test d’authentification :

wbinfo -a testuser%passtest
plaintext password authentication failed
Could not authenticate user testuser%passtest with plaintext password
challenge/response password authentication succeeded

Les 2 premières lignes indiquent que l’authentification en clair a échoué, ce qui est normal, c’est la dernière ligne qui est importante, elle indique que l’authentification par Challenge/Response est valide.

Freeradius

Installation des paquets

aptitude install freeradius freeradius-utils

Autorisation pour le ntlm

L’authentification sur l’annuaire est effectuée en NTLM, il faut donc que le service radius ait le droit d’utiliser winbind.

addgroup freerad winbindd_priv

Configuration de Freeradius

La configuration de Freeradius est très complexe car très complète. Elle couvre par défaut une très grande variété de cas d’utilisation. Il est donc recommandé de ne pas la modifier, mais juste de l’adapter.
Dans le cas présent, j’ai choisi de ne pas respecter cette recommandation pour éviter de poster plus de 5000 lignes de configuration, c’est environ le nombre de lignes des différents fichiers de configuration.

Il n’y a normalement que 4 fichiers à modifier :

  • /etc/freeradius/eap.conf : il contient la configuration des méthodes EAP
  • /etc/freeradius/modules/mschap : c’est ce module qui fera l’authentification sur l’AD
  • /etc/freeradius/proxy.conf : sert à relayer les requêtes sur d’autres serveurs radius
  • /etc/freeradius/clients.conf : c’est ici que sont déclarés les NAS autorisés à utiliser le radius

Configuration de l’EAP

#/etc/freeradius/eap.conf
eap {
    default_eap_type = ttls
    timer_expire     = 60
    ignore_unknown_eap_types = no
    cisco_accounting_username_bug = no
    max_sessions = 4096
    tls {
        certdir = ${confdir}/certs
        cadir = ${confdir}/certs
        private_key_password = whatever
        private_key_file = ${certdir}/server.key
        certificate_file = ${certdir}/server.pem
        CA_file = ${cadir}/ca.pem
        dh_file = ${certdir}/dh
        random_file = /dev/urandom
        CA_path = ${cadir}
        cipher_list = "DEFAULT"
        make_cert_command = "${certdir}/bootstrap"
        ecdh_curve = "prime256v1"
        cache {
            enable = no
            lifetime = 24 # hours
            max_entries = 255
        }
    }
    ttls {
        default_eap_type = mschapv2
        copy_request_to_tunnel = yes
        use_tunneled_reply = yes
        virtual_server = "inner-tunnel"
    }
    peap {
        default_eap_type = mschapv2
        copy_request_to_tunnel = yes
        use_tunneled_reply = yes
        virtual_server = "inner-tunnel"
    }
    mschapv2 {
    }
}

Configuration du MS-CHAP v2

#/etc/freeradius/modules/mschap
mschap {
    use_mppe=yes
    require_encryption = yes
    require_strong = yes
    with_ntdomain_hack = yes
    ntlm_auth = "/usr/bin/ntlm_auth --request-nt-key --username=%{%{Stripped-User-Name}:-%{%{User-Name}:-None}} --challenge=%{%{mschap:Challenge}:-00} --nt-response=%{%{mschap:NT-Response}:-00}"
}

Dans certaines configuration, il faudra ajouter votre nom de domaine à la commande ntlm_auth avec la directive suivante : –domain=TEST

Configuration du proxy radius

#/etc/freeradius/proxy.conf
proxy server {
    default_fallback = no
}
realm NULL {
}
realm LOCAL {
}
realm example.org {
    authhost = LOCAL
    accthost = LOCAL
}
realm test.example.org {
    authhost = LOCAL
    accthost = LOCAL
}
realm DEFAULT {
    type = radius
    authhost = 1.1.1.1
    accthost = 1.1.1.1
    secret = proxysharedsecret
    nostrip
}

Les requêtes des utilisateurs précisant un domaine d’authentification qui n’est pas le notre seront transmises à un autre serveur radius (1.1.1.1 dans l’exemple).

Déclaration des NAS

On déclare ici les NAS qui pourront interroger notre serveur radius

#/etc/freeradius/clients.conf
client 10.1.1.1/32 {
    secret          = secretnas1
    shortname       = nas1
}
client localhost {
    ipaddr = 127.0.0.1
    secret          = testing123
    require_message_authenticator = no
    nastype     = other
}

Redémarrage du service

service freeradius restart

Test local

radtest -t mschap testuser passtest 127.0.0.1 0 testing123
Sending Access-Request of id 83 to 127.0.0.1 port 1812
User-Name = "testuser"
NAS-IP-Address = 127.0.1.1
NAS-Port = 0
Message-Authenticator = 0x00000000000000000000000000000000
MS-CHAP-Challenge = 0xe44df59956405035
MS-CHAP-Response = 0x0001000000000000000000000000000000000000000000000000e7cb832715175c312efcb8a07922a1a23c82c715773e9216
rad_recv: Access-Accept packet from host 127.0.0.1 port 1812, id=83, length=84
MS-CHAP-MPPE-Keys = 0x0000000000000000490de11896511cd8de93afd472151ddd0000000000000000
MS-MPPE-Encryption-Policy = 0x00000002
MS-MPPE-Encryption-Types = 0x00000004

Conclusion

Je n’ai pas couvert le détail de la configuration, il s’agit encore une fois d’une prise de notes mise en forme.

Il faudrait compléter cette installation avec le paramétrage des journaux, l’accounting et la sécurisation de la configuration avant d’envisager une mise en production. Peut être dans un prochain article.

LXC – virtualisation/conteneur

Un petit article pour décrire le fonctionnement de LXC (LinuX Containers) et son utilisation sur une Debian Wheezy.

J’avais commencé ce blog en parlant de Linux Vserver, un système de « virtualisations au niveau du système d’exploitation ».

Ça m’a bien rendu service, mais vserver n’est plus intégré à la Debian Wheezy, il a été remplacé par LXC, hors il fallait bien que je fasse la mise à jour de mes Squeeze.

Je vais faire court car il existe de nombreuses docs sur LXC.

On commence par mettre à jour la Debian (sauf exceptions, il vaut mieux utiliser aptitude que apt-get) :

aptitude update && aptitude full-upgrade

On installe le paquet LXC :

aptitude install lxc

Je rajoute aussi le paquet bridge-utils, mais il n’est pas obligatoire.

Dans /etc/fstab, on ajoute un point de montage pour gérer les ressources :

cgroup /sys/fs/cgroup cgroup defaults 0 0

Attention, il y a un bug dans le script de création des premières Wheezy (corrigé en 7.4 de mémoire).

Le plus simple est de créer un nouveau fichier de modèle, je me suis librement inspiré de celui proposé ici.

Voici mon template /usr/share/lxc/templates/lxc-debian-wheezy :

#!/bin/bash

#Debian Wheezy LXC template
configure_debian()
{
    rootfs=$1
    hostname=$2
    
    # squeeze only has /dev/tty and /dev/tty0 by default,
    # therefore creating missing device nodes for tty1-4.
    for tty in $(seq 1 4); do
    if [ ! -e $rootfs/dev/tty$tty ]; then
        mknod $rootfs/dev/tty$tty c 4 $tty
    fi
    done
    
    # configure the inittab
    cat <<EOF > $rootfs/etc/inittab
    id:3:initdefault:
    si::sysinit:/etc/init.d/rcS
    l0:0:wait:/etc/init.d/rc 0
    l1:1:wait:/etc/init.d/rc 1
    l2:2:wait:/etc/init.d/rc 2
    l3:3:wait:/etc/init.d/rc 3
    l4:4:wait:/etc/init.d/rc 4
    l5:5:wait:/etc/init.d/rc 5
    l6:6:wait:/etc/init.d/rc 6
    # Normally not reached, but fallthrough in case of emergency.
    z6:6:respawn:/sbin/sulogin
    1:2345:respawn:/sbin/getty 38400 console
    c1:12345:respawn:/sbin/getty 38400 tty1 linux
    c2:12345:respawn:/sbin/getty 38400 tty2 linux
    c3:12345:respawn:/sbin/getty 38400 tty3 linux
    c4:12345:respawn:/sbin/getty 38400 tty4 linux
    EOF
    
    # disable selinux in debian
    mkdir -p $rootfs/selinux
    echo 0 > $rootfs/selinux/enforce
    
    # configure the network
    cat <<EOF > $rootfs/etc/network/interfaces
    auto lo
    iface lo inet loopback
    EOF
    
    # set the hostname
    cat <<EOF > $rootfs/etc/hostname
    $hostname
    EOF
    
    # reconfigure timezone
    echo "Europe/Paris" > $rootfs/etc/timezone
    chroot $rootfs dpkg-reconfigure -f noninteractive tzdata
    
    # reconfigure language
    sed -i "s/^# en_US.UTF-8/en_US.UTF-8/" $rootfs/etc/locale.gen
    chroot $rootfs locale-gen
    
    # remove pointless services in a container
    chroot $rootfs /usr/sbin/update-rc.d -f umountfs remove
    chroot $rootfs /usr/sbin/update-rc.d -f hwclock.sh remove
    chroot $rootfs /usr/sbin/update-rc.d -f hwclockfirst.sh remove
    
    echo "root:root" | chroot $rootfs chpasswd
    echo "Root password is 'root', please change !"
    
    return 0
}

download_debian()
{
    packages=
    ifupdown,
    locales,
    libui-dialog-perl,
    dialog,
    netbase,
    net-tools,
    iproute,
    vim,
    bash-completion,
    locales,
    iputils-ping,
    aptitude
    
    cache=$1
    arch=$2
    
    # check the mini debian was not already downloaded
    mkdir -p "$cache/partial-$arch"
    if [ $? -ne 0 ]; then
        echo "Failed to create '$cache/partial-$arch' directory"
       return 1
    fi
    
    # download a mini debian into a cache
    echo "Downloading debian minimal ..."
    debootstrap --verbose --variant=minbase --arch=$arch
    --include $packages
    wheezy $cache/partial-$arch http://ftp.debian.org/debian
    if [ $? -ne 0 ]; then
        echo "Failed to download the rootfs, aborting."
        return 1
    fi
    
    mv "$1/partial-$arch" "$1/rootfs-$arch"
    echo "Download complete."
    
    return 0
}

copy_debian()
{
    cache=$1
    arch=$2
    rootfs=$3
    
    # make a local copy of the minidebian
    echo -n "Copying rootfs to $rootfs..."
    cp -a $cache/rootfs-$arch $rootfs || return 1
    return 0
}

install_debian()
{
    cache="/var/cache/lxc/debian-wheezy"
    rootfs=$1
    mkdir -p /var/lock/subsys/
    (
        flock -n -x 200
        if [ $? -ne 0 ]; then
            echo "Cache repository is busy."
            return 1
        fi
        
        arch=$(arch)
        if [ "$arch" == "x86_64" ]; then
            arch=amd64
        fi
        
        if [ "$arch" == "i686" ]; then
            arch=i386
        fi
        
        if [ "$arch" == "armv5tel" ]; then
            arch=armel
        fi
        
        echo "Checking cache download in $cache/rootfs-$arch ... "
        if [ ! -e "$cache/rootfs-$arch" ]; then
            download_debian $cache $arch
            if [ $? -ne 0 ]; then
                echo "Failed to download 'debian base'"
                return 1
            fi
        fi
        
        copy_debian $cache $arch $rootfs
        if [ $? -ne 0 ]; then
            echo "Failed to copy rootfs"
            return 1
        fi
        
        return 0
    
    ) 200>/var/lock/subsys/lxc
    
    return $?
}

copy_configuration()
{
    path=$1
    rootfs=$2
    name=$3
    
    cat <<EOF >> $path/config
    lxc.tty = 4
    lxc.pts = 1024
    lxc.rootfs = $rootfs
    lxc.cgroup.devices.deny = a
    # /dev/null and zero
    lxc.cgroup.devices.allow = c 1:3 rwm
    lxc.cgroup.devices.allow = c 1:5 rwm
    # consoles
    lxc.cgroup.devices.allow = c 5:1 rwm
    lxc.cgroup.devices.allow = c 5:0 rwm
    lxc.cgroup.devices.allow = c 4:0 rwm
    lxc.cgroup.devices.allow = c 4:1 rwm
    # /dev/{,u}random
    lxc.cgroup.devices.allow = c 1:9 rwm
    lxc.cgroup.devices.allow = c 1:8 rwm
    lxc.cgroup.devices.allow = c 136:* rwm
    lxc.cgroup.devices.allow = c 5:2 rwm
    # rtc
    lxc.cgroup.devices.allow = c 254:0 rwm
    
    # mounts point
    lxc.mount.entry=proc $rootfs/proc proc nodev,noexec,nosuid 0 0
    lxc.mount.entry=devpts $rootfs/dev/pts devpts defaults 0 0
    lxc.mount.entry=sysfs $rootfs/sys sysfs defaults  0 0
    
    # networking
    
    lxc.utsname = $name
    lxc.network.type = veth
    lxc.network.flags = up
    lxc.network.link = br0
    lxc.network.ipv4 = 10.1.1.2/24
    lxc.network.ipv4.gateway = 10.1.1.1
    lxc.network.hwaddr = 00:1E:$(hex):$(hex):$(hex):$(hex)
    EOF
    
    if [ $? -ne 0 ]; then
        echo "Failed to add configuration"
        return 1
    fi
    
    return 0
}

# nice trick from: http://mindref.blogspot.com/2011/01/debian-lxc-create.html
hex()
{
    echo "`tr -dc A-F0-9 < /dev/urandom | head -c 2 | xargs`"
}

clean()
{
    cache="/var/cache/lxc/debian-wheezy"
    
    if [ ! -e $cache ]; then
        exit 0
    fi
    
    # lock, so we won't purge while someone is creating a repository
    (
    flock -n -x 200
    if [ $? != 0 ]; then
        echo "Cache repository is busy."
        exit 1
    fi
    
    echo -n "Purging the download cache..."
    rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1
    exit 0
    
    ) 200>/var/lock/subsys/lxc
}

usage()
{
    cat <<EOF
    $1 -h|--help -p|--path=<path> --clean
    EOF
    return 0
}

options=$(getopt -o hp:n:c -l help,path:,name:,clean -- "$@")
if [ $? -ne 0 ]; then
    usage $(basename $0)
    exit 1
fi
eval set -- "$options"

while true
do
    case "$1" in
        -h|--help)      usage $0 && exit 0;;
        -p|--path)      path=$2; shift 2;;
        -n|--name)      name=$2; shift 2;;
        -c|--clean)     clean=$2; shift 2;;
        --)             shift 1; break ;;
        *)              break ;;
    esac
done

if [ ! -z "$clean" -a -z "$path" ]; then
    clean || exit 1
    exit 0
fi

type debootstrap
if [ $? -ne 0 ]; then
    echo "'debootstrap' command is missing"
    exit 1
fi

if [ -z "$path" ]; then
    echo "'path' parameter is required"
    exit 1
fi

if [ "$(id -u)" != "0" ]; then
    echo "This script should be run as 'root'"
    exit 1
fi

rootfs=$path/rootfs

install_debian $rootfs
if [ $? -ne 0 ]; then
    echo "failed to install debian"
    exit 1
fi

configure_debian $rootfs $name
if [ $? -ne 0 ]; then
    echo "failed to configure debian for a container"
    exit 1
fi

copy_configuration $path $rootfs $name
if [ $? -ne 0 ]; then
    echo "failed write configuration file"
    exit 1
fi

if [ ! -z $clean ]; then
    clean || exit 1
    exit 0
fi

Attention à la ligne 65, il faut bien évidemment changer le mot de passe, soit dans le template lui-même, soit dans le conteneur une fois déployé.

Pour le reste, libre à vous d’adapter le script, en particulier les lignes 74 à 85 (paquets installés par défaut) et les lignes 179 à 212 qui contiennent le paramétrage du conteneur, en particulier la configuration réseau :

lxc.network.type = veth #type réseau pour le conteneur (empty/veth/vlan/macvlan/phys)
lxc.network.flags = up #la carte monte au démarrage
lxc.network.link = br0 #elle est attachée à l'interface br0 de l'hôte
lxc.network.ipv4 = 10.1.1.2/24 #son IP/masque
lxc.network.ipv4.gateway = 10.1.1.1 #le routeur par défaut
lxc.network.hwaddr = 00:1E:$(hex):$(hex):$(hex):$(hex) #une adresse physique aléatoire

Le paquet LXC vient avec toute une panoplie d’outils de gestion des conteneurs, entre autre :

  • lxc-create – déployer un conteneur
  • lxc-ls – lister les conteneurs déployés
  • lxc-list – lister le status des conteneurs
  • lxc-start – démarrer un conteneur
  • lxc-stop – arrêter un conteneur
  • lxc-console – « entrer » dans un conteneur
  • lxc-destroy – supprimer un conteneur
  • Par exemple pour créer un conteneur :
lxc-create -n mon.premier.conteneur -t debian-wheezy
  • On peut modifier sa configuration en éditant le fichier :
/var/lib/lxc/mon.premier.conteneur/config
  • On démarre le conteneur avec :
lxc-start -n mon.premier.conteneur
  • On se connecte à la console avec :
lxc-console mon.premier.conteneur

Pour quitter la console il faut faire CTRL+a, q

  • On arrête le conteneur avec :
lxc-stop -n mon.premier.conteneur
  • On le supprime avec :
lxc-destroy -n mon.premier.conteneur
  • Pour qu’un conteneur démarre avec l’hôte, il suffit de créer un lien vers son fichier « config » dans /etc/lxc/auto/ :
ln -s /var/lib/lxc/mon.premier.conteneur/config /etc/lxc/auto/mon.premier.conteneur

Quelques recommandations pour terminer :

  • l’utilisation de LVM est fortement recommandée, ne serait ce que pour faire des sauvegardes à chaud;
  • il vaut mieux laisser les conteneurs dans l’emplacement par défaut (/var/lib/lxc),
  • donc il est recommandé de faire un point de montage sur ce dossier
Sources :

IPv6 – pare feu

Objectif : profiter de l’ipv6 en conservant un bon niveau de sécurité réseau et sans avoir à gérer les pare-feu de tous ses équipements.

Petite précision avant de commencer. Bien qu’ils allouent un préfixe IPv6 à leur clients, la plupart des certains* FAI ne permettent pas de le segmenter en sous réseaux, ils s’attendent à ce que toutes les machines du réseau soient directement connectés à leur Box, il va donc falloir ruser un peu.

*edit : la situation a changé depuis que j’ai écrit cet article, par exemple avec la Freebox Revolution, Free semble (je ne peux pas tester) offrir un /61 avec possibilité de configurer la délégation, vous trouverez un exemple ici : http://www.goudal.net/?p=6

La suite reste valable dans le cas d’une Freebox V5

Prérequis :

  • une machine sous linux disposant d’au moins 2 interfaces réseaux
  • un préfixe IPv6 (FDN, Free, Nerim, OVH, SFR, … le proposent à leur abonnées)

Il y a 2 principales façon de faire :

  • la première consiste à faire du « brouting ». En gros on transporte les paquets de niveau 2 au travers d’un bridge. Ça revient à brancher tous vos équipements sur un switch capable de faire du filtrage. C’est simple mais assez rigide et pas très propre.
  • la seconde que je vais utiliser ici consiste à faire du routage traditionnel agrémenté d’un proxy NDP.

Ici la machine linux est un Raspberry-Pi sous Debian Wheezy, qui ne dispose que d’une carte réseau. Cette carte sera donc divisée en plusieurs interfaces de VLAN. La connectivité IPv6 sera assurée par une Freebox (v5) configurée en switch (donc pas en routeur).

La passerelle Linux assurera plusieurs fonctions :

  1. routeur-nat pour l’IPv4 : comme le font les box
  2. pare-feu IPv4 : comme ne le font pas les box
  3. routeur IPv6 : comme ne le font pas les box
  4. pare-feu IPv6 : comme ne le font pas les box
  5. proxy NDP : pour leurrer les Box
  6. on pourra compléter l’installation par quelques services de confort (serveur DNS, serveur DHCP, serveur NTP, proxy web, …)

En pratique, notre passerelle va se comporter comme un routeur-firewall IPv4 + IPv6 classique, mais va en plus transporter les annonces NDP (et uniquement ces annonces) de part et d’autre de ses interfaces.

Notes, à remplacer par vos informations :

  • l’interface physique est eth0
  • l’interface connectée à Internet est nommée vlan6
  • l’interface connectée au réseau local est nommée vlan46
  • le préfixe IPv6 de la connexion est 2001:db8:1234:1234::/64
  • le sous réseau 2001:db8:1234:1234::/64 est coté local, avec pour passerelle 2001:db8:1234:1234:1::2
  • le sous réseau 2001:db8:1234:1234::/126 (qui empiète sur le précédent) est notre interco entre notre passerelle et la box qui a pour adresse 2001:db8:1234:1234::1
  • le serveur DNS annoncé est 2001:db8::1
  • l’adresse public IPv4 est 1.1.1.2 avec 1.1.1.1 comme passerelle IPv4 par défaut
  • le réseau local a pour adresses 192.168.0.0/24 en IPv4 et fec0:0:0:ffff::/64 en IPv6
  • la passerelle a pour adresses locale 192.168.0.1 en IPv4 et fec0:0:0:ffff::1 en IPv6

Cette dernière adresse est utile si vous avez des postes sous Windows car ces derniers ne gèrent pas les annonces RDNSS, à la place Microsoft a configuré par défaut 3 adresses de DNS dans sa pile IPv6 : FEC0:0:0: FFFF::1, FEC0:0:0: FFFF::2 et FEC0:0:0:FFFF::3

Cela signifie qu’un poste portant l’une de ses adresses peut devenir automatiquement serveur DNS pour tous les postes d’un réseau local composé de Windows, niveau sécurité on a vu mieux.

En passant, Windows ne gère pas non plus les informations de routage fournie par DHCP en IPv6. Il faut donc annoncer le routeur via NDP et les DNS via DHCP. On ne peut donc pas faire du stateless ni du statefull, il faut combiner les 2 pour avoir un truc qui marche.

Configuration de base

Avant toute chose, assurez vous d’avoir un accès physique à la passerelle et qu’elle est correctement sécurisée (pas de SSH ouvert à tout le monde avec un mot de passe bidon, …).

Installation des paquets

  • Radvd : service d’annonce IPv6
  • NDPpd : proxy pour les paquets NDP (non disponible dans les dépôts Rapsberry, mais il se compile simplement)
  • VLAN : prise en charge du 802.1q (non nécessaire si vous avez plusieurs interfaces physique)

Configuration des services

/etc/radvd.conf

C’est ce service qui va faire de votre machine Linux une passerelle IPv6. Il va annoncer les routes (en particulier la route par défaut) et les serveurs DNS aux machines du réseau local.

interface vlan46 {
    AdvSendAdvert on;
    MinRtrAdvInterval 3;
    MaxRtrAdvInterval 10;
    AdvManagedFlag off;
    AdvOtherConfigFlag off;
    prefix 2001:db8:1234:1234::/64 {
        AdvOnLink on;
        AdvAutonomous on;
        AdvRouterAddr off;
    };
    route 2001:db8:1234:1234::/64 {
    };
    RDNSS 2001:db8::1 {
    };
};

/etc/ndppd.conf

Il va transmettre les annonces NDP de part de d’autre de la passerelle. Notez le /126.

route-ttl 30000
proxy vlan46 {
    router yes
    timeout 500
    ttl 30000
    rule 2001:db8:1234:1234::/126 {
        auto
    }
}
proxy vlan6 {
    router no
    timeout 500
    ttl 30000
    rule 2001:db8:1234:1234::/64 {
        auto
    }
}

Configuration des interfaces

/etc/network/interfaces

Fichier de configuration traditionnel, j’y ai inclus le lancement des services et la configuration noyau nécessaire au routage et au proxy NDP.

auto lo eth0 vlan6 vlan46

iface lo inet loopback

iface eth0 inet manual
    pre-up /sbin/modprobe -q ipv6 ; /bin/true
    pre-up echo 1 > /proc/sys/net/ipv4/ip_forward
    pre-up echo 1 > /proc/sys/net/ipv6/conf/eth0/disable_ipv6
    pre-up echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
    pre-up echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
    pre-up echo 1 > /proc/sys/net/ipv6/conf/default/forwarding
    pre-up echo 1 > /proc/sys/net/ipv6/conf/default/proxy_ndp
    pre-up echo 1 > /proc/sys/net/ipv6/conf/all/proxy_ndp
    up ifconfig eth0 promisc up
    post-up iptables-restore < /etc/iptables.up.rules
    post-up ip6tables-restore < /etc/ip6tables.up.rules
    
iface vlan6 inet manual
    vlan-raw-device eth0
    
iface vlan6 inet static
    vlan-raw-device eth0
    address 1.1.1.2
    netmask 255.255.255.0
    gateway 1.1.1.1
    
iface vlan6 inet6 static
    up ifconfig vlan6 promisc up
    vlan-raw-device eth0
    address 2001:db8:1234:1234::2
    netmask 126
    gateway 2001:db8:1234:1234::1
    
iface vlan46 inet static
    address 192.168.0.2
    netmask 255.255.255.0
    broadcast 192.168.0.255
    network 192.168.0.0
    vlan-raw-device eth0
    
iface vlan46 inet6 static
    up ifconfig vlan46 promisc up
    post-up /usr/local/sbin/ndppd -d
    post-up service radvd start
    address 2001:db8:1234:1234:1::2
    netmask 64
    post-up ip a a fec0:0:0:ffff::1/64 dev vlan46

Filtrage

IPv4

Ici un jeu de règle basique permettant à la passerelle de remplacer la box pour l’accès internet en IPv4 (ce qu’on appelle à tord du NAT). Les règles sont minimalistes, il n’y a pas par exemple de protection contre le flood.

/etc/iptables.up.rules

# Generated by iptables-save
*nat
:INPUT DROP [0:0]
:OUTPUT DROP [0:0]
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -s 192.168.0.0/24 ! -d 192.168.0.0/24 -j MASQUERADE
COMMIT
# Generated by iptables-save
*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT
# Generated by iptables-save
*filter
:localnet - [0:0]
:INPUT DROP [0:0]
:OUTPUT DROP [0:0]
:FORWARD DROP [0:0]
-A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
-A FORWARD -j localnet
-A localnet -s 192.168.0.0/24 -j ACCEPT
-A localnet -s 127.0.0.0/8 -j ACCEPT
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -j localnet
-A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A OUTPUT -j localnet
COMMIT

IPv6

La même chose en IPv6, sans le « NAT » bien entendu, rien de compliqué.

# Generated by ip6tables-save
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
#INPUT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -i vlan46 -j ACCEPT
-A INPUT -s fe80::/10 -j ACCEPT
-A INPUT -s ff00::/8 -j ACCEPT
-A INPUT -i vlan6 -s 2001:db8:1234:1234::/64 -j ACCEPT
#OUTPUT
-A OUTPUT -j ACCEPT
#FORWARD
-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o vlan6 -j ACCEPT
-A FORWARD -s 2001:db8:1234:1234::/64 -j ACCEPT
#LOG
-A INPUT -j LOG --log-prefix "[IP6 INPUT] "
-A OUTPUT -j LOG --log-prefix "[IPv6 OUTPUT] "
-A FORWARD -j LOG --log-prefix "[IPv6 FORWARD] "
COMMIT

Il ne reste plus qu’à appliquer le tout, brancher et à vérifier que ça fonctionne.

Plusieurs sites permettent de vérifier si l’on utilise une connexion IPv4 ou IPv6, comme par exemple :

Sources :