LXC : Créer un conteneur servant de modèle
Rédigé par Alexandre le 2020-06-26
Après avoir mis en place une infrastructure LXD, il convient de créer un premier conteneur.
Dans mon cas, j'ai choisi de créer un conteneur servant de "modèle" à tous les autres. Des méthodes un peu plus technique existent pour faire exactement la même chose mais en partant des modèles officiels (cloud-init ou salt pour n'en citer que deux).
Cet article documente la création et configuration d'un conteneur LXC servant de base à l'ensemble de mes conteneurs.
Instancier
Définir le nom du nouveau conteneur :
target="modele-buster"
Instancier le conteneur, ici en Debian Buster :
lxc launch images:debian/buster $target
Réseau
Histoire de vivre avec mon temps, j'utilise systemd
pour la configuration réseau. Il est nécessaire de créer trois fichiers :
/etc/systemd/network/1-lo.network
: interface de loopback/etc/systemd/network/2-eth0.network
: interface du pont interne pour IPv4 (LAN)/etc/systemd/network/3-eth1.network
: interface du pont externe pour IPv6 (WAN)
lxc exec $target -- tee /etc/systemd/network/1-lo.network <<EOF
[Match]
Name=lo
[Network]
Address=127.0.0.1/8
Address=::1/128
EOF
lxc exec $target -- tee /etc/systemd/network/2-eth0.network <<EOF
[Match]
Name=eth0
[Network]
DHCP=no
IPv6AcceptRA=no
LinkLocalAddressing=no
Address=192.168.3.189/24
Gateway=192.168.3.254
DNS=80.67.169.12 80.67.169.40
EOF
lxc exec $target -- tee /etc/systemd/network/3-eth1.network <<EOF
[Match]
Name=eth1
[Network]
DHCP=no
LinkLocalAddressing=no
Address=2001:41d0:8:XXXX::3189/64
Gateway=2001:41d0:8:XXXX::1
DNS=2001:910:800::40 2001:910:800::12
EOF
Désactiver l'écoute du serveur DNS de systemd
:
lxc exec $target -- sed -i 's/#DNSStubListener=yes/DNSStubListener=no/g' /etc/systemd/resolved.conf
Activer le réseau par systemd
:
lxc exec $target -- systemctl unmask systemd-networkd.service systemd-networkd.socket systemd-networkd-wait-online.service
lxc exec $target -- systemctl enable systemd-networkd systemd-resolved
Supprimer l'ancien fonctionnement :
lxc exec $target -- apt purge ifupdown netbase --autoremove
lxc exec $target -- rm -R /etc/network
lxc exec $target -- rm /etc/resolv.conf
lxc exec $target -- ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf
Temps
Tout comme pour le réseau, j'utilise systemd
pour maintenir le conteneur à l'heure :
lxc exec $target -- tee /etc/systemd/timesyncd.conf <<EOF
[Time]
NTP=0.fr.pool.ntp.org 1.fr.pool.ntp.org 2.fr.pool.ntp.org 3.fr.pool.ntp.org
FallbackNTP=0.debian.pool.ntp.org 1.debian.pool.ntp.org 2.debian.pool.ntp.org 3.debian.pool.ntp.org
EOF
Activer le temps par systemd
:
lxc exec $target -- timedatectl set-ntp true
Changer le fuseau horaire :
lxc exec $target -- dpkg-reconfigure tzdata
Dans la fenêtre qui s'ouvre :
- Sélectionner
Europe
- Valider avec la touche
Entrée
- Chercher
Paris
- Terminer avec la touche
Entrée
Langue
Passer le système en français :
lxc exec $target -- dpkg-reconfigure locales
Dans la fenêtre qui s'ouvre :
- Chercher
en_US.UTF-8 UTF-8
- Décocher en appuyant sur la barre espace
- Chercher
fr_FR.UTF-8
- Cocher en appuyant sur la barre espace
- Valider avec la touche
Entrée
- Choisir
fr_FR.UTF-8
- Terminer avec la touche
Entrée
Système
Changer le mot le passe du super-utilisateur :
lxc exec $target -- passwd
Créer un fichier personnel de configuration d'apt :
lxc exec $target -- tee /etc/apt/apt.conf.d/99custom <<EOF
APT::Install-Recommends "false";
APT::Install-Suggests "false";
APT::Get::Show-Versions "true";
APT::Get::Show-Upgraded "true";
APT::Get::Purge "true";
APT::Get::List-Cleanup "true";
EOF
Utiliser les dépôts français :
lxc exec $target -- tee /etc/apt/sources.list <<EOF
deb http://ftp.fr.debian.org/debian/ buster main
deb http://ftp.fr.debian.org/debian/ buster-updates main
deb http://security.debian.org/debian-security buster/updates main
EOF
Ajouter le dépôt des paquets rétro-portés :
lxc exec $target -- tee /etc/apt/sources.list.d/backports.list <<EOF
deb http://ftp.fr.debian.org/debian/ buster-backports main
EOF
/!\ Attention à la distribution et sa version !
Redémarrer :
lxc restart $target
Paquets
Purger les paquets inutiles :
lxc exec $target -- apt purge --autoremove isc-dhcp* krb5-locales openssh-client vim* xauth
Chercher et appliquer les mises à jour :
lxc exec $target -- apt update && lxc exec $target -- apt -y dist-upgrade
Nettoyer le système puis chercher et désinstaller les paquets orphelins :
lxc exec $target -- apt autoremove --purge && lxc exec $target -- apt install -y deborphan dialog && lxc exec $target -- orphaner && lxc exec $target -- apt purge -y --autoremove deborphan
Une fenêtre affiche la liste des paquets orphelins :
- Cocher les paquets en question avec la barre espace
- Désinstaller les paquets en appuyant sur la touche
Entrée
- Renouveller l'opération jusqu'à ce qu'il n'y ait plus de paquets orphelins
Installer les outils habituels :
lxc exec $target -- apt install nano apt-utils htop openssh-server locate less ca-certificates msmtp msmtp-mta nftables rsyslog curl iputils-ping sudo cron rsync logrotate
SSH
Créer un utilisateur :
lxc exec $target -- adduser ct
Permettre à l'utilisateur d'élever ses privilèges :
lxc exec $target -- adduser ct sudo
Récupérer l'UID de l'utilisateur créé :
ctUser=$(lxc exec $target -- id -u ct)
Ajouter la clef de l'hôte :
lxc exec $target --user $ctUser -- mkdir /home/ct/.ssh/ && lxc exec $target -- chmod go-rwx /home/ct/.ssh/ && lxc exec $target -- tee /home/ct/.ssh/authorized_keys <<EOF
ssh-ed25519 <clef SSH> pulsar@zira
EOF
Une fois que c'est fait, il est possible de procéder à la sécurisation de SSH.
Courriel
Configurer msmtp pour que les utilisateurs système puissent envoyer des courriels.
Pare-feu
Créer les règles du pare-feu (ici on autorise SSH sur le port 22 depuis l'hôte) (adapter les IP !) :
lxc exec $target -- tee /etc/nftables.conf <<EOF
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority 0;
# accept any localhost traffic
iif lo accept
# accept traffic originated from us
ct state established,related accept
# accept neighbour discovery otherwise IPv6 connectivity breaks.
ip6 nexthdr icmpv6 icmpv6 type { nd-neighbor-solicit, nd-router-advert, nd-neighbor-advert } accept
## Custom
# Allow SSH (port 22) from zira
ip saddr 192.168.3.254 tcp dport 22 accept
ip6 saddr 2001:41d0:8:XXXX::1 tcp dport 22 accept
# count and drop any other traffic
counter drop
}
}
EOF
Activer nftables
au démarrage et immédiatement :
lxc exec $target -- systemctl enable nftables && lxc exec $target -- systemctl start nftables
Auto-bannissement
Faute de documentation récente traitant de nftables
+fail2ban
, j'ai laissé cette partie en attente. Si certains se sentent de tester des choses, voici ce que j'ai pu lire sur le sujet :
- https://wiki.meurisse.org/wiki/Fail2Ban#nftables
- https://mondedie.fr/d/10907-securisation-serveur-debian-10
Avant que certains pensent à s'en passer complètement, un outil d'auto-bannissement tel que fail2ban permet de protéger des services qui ne peuvent pas l'être autrement. Je pense par exemple à un htpasswd qui permettra à un attaquant d'essayer autant de combinaisons qu'il le souhaite pour se connecter (attaque par force brute).
Terminer
Redémarrer simplement le conteneur :
lxc restart $target
Afficher la liste des conteneurs :
lxc list
Ce qui devrait retourner quelque chose comme ça :
+--------------------------+---------+----------------------+-------------------------------+-----------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+--------------------------+---------+----------------------+-------------------------------+-----------+-----------+
| modele-buster | RUNNING | 192.168.3.189 (eth0) | 2001:41d0:8:XXXX::3189 (eth1) | CONTAINER | 0 |
+--------------------------+---------+----------------------+-------------------------------+-----------+-----------+
Afficher plus de détail sur le conteneur avec la commande suivante :
lxc info $target