debian – NAS/SAN open source avec support ZFS

nas

Ces dernières années, le secteur qui a connu d’importantes évolutions est celui du stockage de données. Le volume, la vitesse, les techniques de stockage et pour surtout les prix. HDD, RAID, cloud, NAS, SAN, iSCSI, … sont le vocabulaire couramment utilisé par nos revendeurs. Dans ce tutoriel, nous nous intéresserons ici à la mise en place d’un NAS (Network-Attached Storage) open source « made in home » a base de distribution Debian 10 et du système de fichier ZFS. Je détaillerai ici la construction du pool de stockage, l’installation du service Samba couplé à des snapshots et pour terminer un pseudo PRA via l’export zrepl du stockage vers un serveur tiers.

Prérequis matériels

Pour ce tutoriel j’utilise une machine type KVM sur un cluster Proxmox. Voici un exemple de configuration :

2021-04-08 14.48.47

ZFS depuis Debian Buster 10

À partir de votre Debian 10 fraîchement installée, vérifier et ajouter le dépôt backports

vi /etc/apt/sources.list
...
###############################################
## buster
deb http://deb.debian.org/debian/ buster main contrib non-free
deb-src http://deb.debian.org/debian/ buster main contrib non-free

## buster security
deb http://deb.debian.org/debian-security/ buster/updates main contrib non-free
deb-src http://deb.debian.org/debian-security/ buster/updates main contrib non-free

## buster update
deb http://deb.debian.org/debian/ buster-updates main contrib non-free
deb-src http://deb.debian.org/debian/ buster-updates main contrib non-free

## buster backports
deb http://deb.debian.org/debian buster-backports main contrib non-free
deb-src http://deb.debian.org/debian buster-backports main contrib non-free
...

Mettre à jour votre système et installer les paquets nécessaires à la prise en charge de ZFS pour debian

apt update
apt install linux-headers-`uname -r` -y
apt install -t buster-backports dkms spl-dkms -y
apt install -t buster-backports zfs-dkms zfsutils-linux -y

Déterminer la taille maximale de l’ARC (Adaptive Replacement Cache) ZFS. Par défaut, c’est 75 % de mémoire sur les systèmes dotés de moins de 4 Go de mémoire. Vous pouvez vous aider de cette calculatrice : http://www.matisse.net/bitcalc/

Éditer ensuite le fichier /etc/modprobe.d/zfs.conf

# vi /etc/modprobe.d/zfs.conf

Quelques exemples en fonction de votre mémoire disponible

#96Go
options zfs zfs_arc_max=103079215104
#80Go
options zfs zfs_arc_max=85899345920
#50Go
options zfs zfs_arc_max=53687091200
#40Go
options zfs zfs_arc_max=42949672960
#30Go
options zfs zfs_arc_max=32212254720
#24Go
options zfs zfs_arc_max=25769803776
#16Go
options zfs zfs_arc_max=17179869184

Après le reboot de votre debian, vérifier la prise en compte des xxGo en visualisant la consommation de l’ARC

# arc_summary -p 1
...
Target size (adaptive):                       100.0 %   XX.0 GiB
...

Afin de construite le pool ZFS et éviter d’utiliser le nom des disques sous le format sdx car en cas de panne d’un, la numérotation va changer au redémarrage. Nous allons privilégier l’utilisation des numéros séries. Pour cela, visualiser les disques par ID :

ls -lh /dev/disk/by-id/
scsi-0QEMU_QEMU_HARDDISK_drive-scsi0
scsi-0QEMU_QEMU_HARDDISK_drive-scsi1
scsi-0QEMU_QEMU_HARDDISK_drive-scsi2

Création du pool tank en mode raidz équivalent au raid1 ()

zpool create tank -o ashift=12 raidz scsi-0QEMU_QEMU_HARDDISK_drive-scsi0 scsi-0QEMU_QEMU_HARDDISK_drive-scsi1 scsi-0QEMU_QEMU_HARDDISK_drive-scsi2

Création du volume home et timemachine sur le pool tank

zfs create -o casesensitivity=mixed -o xattr=sa -o dnodesize=auto tank/home
zfs create -o xattr=sa -o dnodesize=auto tank/timemachine

Lister le résultat des commandes précédentes

zfs list
NAME        USED  AVAIL     REFER  MOUNTPOINT
tank        155K   965G     30.6K  /tank
tank/home  30.6K   965G     30.6K  /tank/home
tank/timemachine  30.6K   965G     30.6K  /tank/timemachine

Changer le point de montage des volumes home et timemachine

zfs set mountpoint=/home tank/home
zfs set mountpoint=/timemachine tank/timemachine
zfs mount -a

Lancer un scrub

zpool scrub tank 

Arrêter un scrub

zpool scrub -s tank

Dans le cadre de l’utilisation du NFS, CIFS et éventullement de l’iSCSI il est recommandé de changer les propriétés du pool tank comme indiqué (Docs Oracle Propriétés ZFS)

Activer les acls posix (getfacl, setfacl) :

zfs set acltype=posixacl tank     

Stocker les attributs étendus dans les inodes afin d’obtenir plus d’IO :

zfs set dnodesize=auto tank
zfs set xattr=sa tank

Désactiver la déduplication

zfs set dedup=off tank

Activer la compression

zfs set compression=lz4 tank

Pour de la performance

zfs set atime=off tank
zfs set sync=disabled tank

Au cours d’une opération chmod, les ACE autres que owner@, group@ ou everyone@ ne sont modifiés d’aucune manière. Les ACE owner@, group@ ou everyone@ sont désactivés afin de définir le mode de fichier comme demandé par l’opération chmod.

zfs set aclinherit=passthrough tank

Visualiser les propriétés modifiées sur le pool tank

zfs get acltype tank
zfs get casesensitivity tank
zfs get dnodesize tank
zfs get xattr tank
zfs get dedup tank
zfs get compression tank
zfs get atime tank
zfs get sync tank
zfs get aclinherit tank

Réinitialiser les propriétés modifiées sur le pool tank à la valeur d’origine

# zfs inherit -Sr xattr tank/home
# zfs inherit -Sr dnodesize tank/home

Visualiser toutes les valeurs locales modifiées pour un tank

# zfs get -s local all

Acquitter une erreur disque sur votre pool tank

zpool clear tank scsi-0QEMU_QEMU_HARDDISK_drive-scsi0
zpool status

Remplacement automatique disques défectueux dans le pool tank si un disque de spare est présent

zpool set autoreplace=on tank

Activer les notifications mail pour ZFS

# apt install zfs-zed
# vi /etc/zfs/zed.d/zed.rc

Activer immédiatement SWAP on ZFS

sysctl -w vm.swappiness=10

Activer SWAP on ZFS de manière persistante

vi /etc/sysctl.conf

# JEROME ZFS
# vm.swappiness = 0 The kernel will swap only to avoid an out of memory condition
# vm.swappiness = 1 Minimum amount of swapping without disabling it entirely
# vm.swappiness = 10 This value is sometimes recommended to improve performance when sufficient memory exists in a system
# vm.swappiness = 60 The default value
# vm.swappiness = 100|The kernel will swap aggressively
# https://pve.proxmox.com/wiki/ZFS_on_Linux
vm.swappiness = 10

Rebooter le serveur pour prendre en compte tous les paramètres ZFS

reboot

Smartmontools

Gérer l’état du smart de vos disques

apt install smartmontools
smartctl -A /dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi0
smartctl -t short /dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi0
smartctl -t long /dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi0
smartctl -l selftest /dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi0

Paquets deb requis pour construire votre NAS

# apt install vim logwatch apticron screen git lshw unzip tree lwatch dirmngr multiarch-support net-tools python-setuptools ncdu iptraf iptraf-ng iotop iftop htop locate sudo nmap dnsutils ncdu lnav rsync ufw nfs-common ifenslave-2.6

Vérifier la nom présence de fichier en rc

# dpkg --list |grep "^rc"
# dpkg --list |grep "^rc" | cut -d " " -f 3

Tuning de la VM

Pydf

Remplacer l’afficher df par pydf (https://github.com/k4rtik/pydf-pypi)

# wget http://kassiopeia.juls.savba.sk/~garabik/software/pydf/pydf_12_all.deb
# dpkg -i pydf_12_all.deb

DF : ancien affichage

# df
Filesystem      Size  Used Avail Use% Mounted on
udev            7.9G     0  7.9G   0% /dev
tmpfs           1.6G   11M  1.6G   1% /run
/dev/vda2        33G  2.7G   29G   9% /
tmpfs           7.9G     0  7.9G   0% /dev/shm
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs           7.9G     0  7.9G   0% /sys/fs/cgroup
/dev/vda1       511M  5.2M  506M   2% /boot/efi
tank            3.6G  128K  3.6G   1% /tank
tank/home       3.6G  128K  3.6G   1% /tank/home
# alias df='pydf'

DF : nouvel affichage

# df
Filesystem  Size  Used Avail Use%                                       Mounted on
/dev/vda2    33G 2728M   28G  8.1 [###................................] /
/dev/vda1   511M 5240k  506M  1.0 [...................................] /boot/efi
tank       3622M  128k 3622M  0.0 [...................................] /tank
tank/home  3622M  128k 3622M  0.0 [...................................] /tank/home

Zfstui

Ajouter une interface zfs en CLI pour la gestion de votre ZFS (https://github.com/volkerp/zfstui)

# apt install python3-setuptools
# cd /opt
# git clone https://github.com/volkerp/zfstui.git
# cd /opt/zfstui
# python3 setup.py install
# zfstui

Postfix

# apt install postfix -y
# apt remove --purge exim4-base exim4-config exim4-daemon-light libevent-2.1-6 libgnutls-dane0 libunbound8
echo -e 'mondomaine.fr' > /etc/mailname && more /etc/mailname 
# vi /etc/postfix/main.cf

# See /usr/share/postfix/main.cf.dist for a commented, more complete version

smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
biff = no

# appending .domain is the MUA's job.
append_dot_mydomain = no

# Uncomment the next line to generate "delayed mail" warnings
#delay_warning_time = 4h

alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
mydestination = localhost.localdomain, localhost
relayhost = smtp.mondomaine.fr
mynetworks = 127.0.0.0/8
inet_interfaces = loopback-only
recipient_delimiter = +

myorigin = /etc/mailname
mailbox_size_limit = 0
inet_protocols = ipv4
compatibility_level = 2

Relancer le service Postfix

# /etc/init.d/postfix restart

Logrotate

Paramétrage du logrotate avec sortie mail et détail des logs a High

cp /etc/logrotate.conf /etc/logrotate.conf.ori
sed -i 's/rotate 4/rotate 52/g' /etc/logrotate.conf
sed -i 's/#compress/compress/g' /etc/logrotate.conf

Vim

ajout copier/coller avec la souris dans vim

echo -e 'set mouse-=a\nsyntax on' > /root/.vimrc

Logwatch

sed -i 's/Output = stdout/Output = mail/g' /usr/share/logwatch/default.conf/logwatch.conf
sed -i 's/Detail = Low/Detail = High/g' /usr/share/logwatch/default.conf/logwatch.conf
logwatch

Rsyslog

Si vous souhaitez centraliser et envoyer vos logs avec un format compatible pour Grafana

# vi /etc/rsyslog.d/grafana.conf

$template MyFormat,"%HOSTNAME% %$YEAR%-%$MONTH%-%$DAY% %timegenerated:::date-hour%:%timegenerated:::date-minute%:%timegenerated:::date-second% %HOSTNAME% %syslogseverity-text% %syslogtag:R,ERE,1,FIELD:([a-zA-Z\/]+)(\[[0-9]{1,5}\])*:--end%%msg%\n"

*.* @192.168.0.100:514;MyFormat

Xymon

Si vous utilisez un serveur xymon vous devez installer le client :

# apt install xymon-client hobbit-plugins
192.168.0.100

Le fichier apt_no_repo_accept permet de faire des exceptions sur des paquets précis

# touch /etc/xymon/apt_no_repo_accept && more /etc/default/xymon-client

Unattended-Upgrade

Mise à jour automatique de votre système

apt install unattended-upgrades
dpkg-reconfigure unattended-upgrades
unattended-upgrade -d

Motd

Si vous souhaitez avoir un motd sympathique (https://fr.wikipedia.org/wiki/FIGlet)

rm /etc/update-motd.d/10-uname
cp /etc/motd /etc/motd.ori
0>/etc/motd
apt install figlet python-apt -y
cd /usr/share/figlet/
wget https://raw.githubusercontent.com/xero/figlet-fonts/master/ANSI%20Shadow.flf
mv ANSI\ Shadow.flf ANSI-Shadow.flf
cd /etc/update-motd.d

Apticron

Si vous souhaitez être notifié pour vos updates systèmes

cp /usr/lib/apticron/apticron.conf /etc/apticron/
sed -i 's/"root"/"root@mondomaine.fr"/g' /etc/apticron/apticron.conf
sed -i 's/# CUSTOM_FROM=""/CUSTOM_FROM="root@mondomaine.fr"/g' /etc/apticron/apticron.conf

CLI Fuzzy Finder

Si vous souhaitez avoir un prompt de recherche sympathique (https://github.com/junegunn/fzf)

git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf
~/.fzf/install
source ~/.bashrc
exec bash

CLI Powerline-Shell

Si vous souhaitez avoir un prompt design (https://github.com/b-ryan/powerline-shell)

git clone https://github.com/b-ryan/powerline-shell /opt/powerline-shell
cd /opt/powerline-shell
python setup.py install

NTP

Synchroniser l’horloge de votre serveur avec systemd

vi /etc/systemd/timesyncd.conf

[Time]
NTP=ntp.mondomaine.fr
FallbackNTP=0.debian.pool.ntp.org 1.debian.pool.ntp.org 2.debian.pool.ntp.org 3.debian.pool.ntp.org
timedatectl set-ntp true 
timedatectl status

Local time: Fri 2017-07-07 21:36:11 CEST
Universal time: Fri 2017-07-07 19:36:11 UTC
RTC time: Fri 2017-07-07 19:36:11
Time zone: Europe/Paris (CEST, +0200)
 Network time on: yes
NTP synchronized: yes
 RTC in local TZ: no

Relancer le service de temps de systemd et vérifier l’état

service systemd-timesyncd restart
service systemd-timesyncd status

Désactivation d’IPv6 au niveau des modules et du noyau

Créer le fichier suivant pour les modules

echo 'blacklist ipv6' >> /etc/modprobe.d/blacklist.conf

Il suffit d’ajouter au fichier /etc/sysctl.conf les instructions suivantes :

vi /etc/sysctl.conf
...
# désactivation de ipv6 pour toutes les interfaces
net.ipv6.conf.all.disable_ipv6 = 1

# désactivation de l’auto configuration pour toutes les interfaces
net.ipv6.conf.all.autoconf = 0

# désactivation de ipv6 pour les nouvelles interfaces (ex:si ajout de carte réseau)
net.ipv6.conf.default.disable_ipv6 = 1

# désactivation de l’auto configuration pour les nouvelles interfaces
net.ipv6.conf.default.autoconf = 0
...

Samba

Cette partie est la plus complexe, elle vous propose l’installation du service de fichiers Samba avec la configuration des quotas, de timemachine et une pseudo protection contre les ransomwares (a revoir)

Pour fonctionner avec notre domaine, Samba a besoin de Winbind

export DEBIAN_FRONTEND=noninteractive
apt-get install winbind krb5-user libnss-winbind smbclient libpam-winbind
unset DEBIAN_FRONTEND
0>/etc/krb5.conf
vi /etc/krb5.conf

Exemple de fichier krb5.conf

[libdefaults]
    default_realm = MONDOMAINE.FR
    ticket_lifetime = 1d
        renew_lifetime = 7d
        dns_lookup_realm = false
        dns_lookup_kdc = true

[realms]
    MONDOMAINE.FR = {
        kdc = 192.168.0.1
        kdc = 192.168.0.2
        admin_server = 192.168.0.1 192.168.0.2  }

Installer Samba

apt install -y samba samba-common samba-vfs-modules python-samba

Exemple de fichier smb.conf

cp /etc/samba/smb.conf /etc/samba/smb.conf.ori
0>/etc/samba/smb.conf
vi /etc/samba/smb.conf
#======================= Global Settings =======================

[global]
    workgroup = MONDOMAINE
    server string = %h server
    dns proxy = no

#### Networking ####

    interfaces = 127.0.0.0/8 eno1
    bind interfaces only = yes
    #hosts allow = 192.168.0.0/24

#### Debugging/Accounting ####

    log level = 0
    log file = /var/log/samba/log.%m
    max log size = 1000
    panic action = /usr/share/samba/panic-action %d

####### Authentication #######

    security = ADS
    realm = MONDOMAINE.FR
    idmap config *:backend = tdb
    idmap config *:range = 700001-800000
    idmap config MONDOMAINE:backend = rid
    idmap config MONDOMAINE:range = 10000-700000
    winbind use default domain = yes
    template homedir = /home/%U
    map acl inherit = Yes
    #store dos attributes = Yes
    #template shell = /bin/bash

############ Misc ############

    socket options = TCP_NODELAY IPTOS_LOWDELAY
    guest account = nobody
    load printers = no
    disable spoolss = yes
    printing = bsd
    printcap name = /dev/null
    use sendfile = yes
    aio read size = 16384
    aio write size = 16384
    time server = no
    wins support = no
    multicast dns register = no

########### Shadow ###########

    shadow: snapdir = .zfs/snapshot
    shadow: sort = desc
    shadow: format = -%Y-%m-%d-%H%M%S
    shadow: snapprefix = ^zfs-auto-snap
    shadow: delimiter = -20
    get quota command = /home/quotazfs.sh %U
    vfs objects = shadow_copy2 catia fruit streams_xattr acl_xattr
    fruit:model = Xserve
    fruit:resource = xattr
    fruit:encoding = native
    fruit:copyfile = yes

########### Security ###########

    include = /etc/samba/ransomwares.conf
    veto files = /.DS_Store/._.DS_Store/Thumbs.db/
    delete veto files = yes
    client min protocol = SMB2
    client max protocol = SMB3
    min protocol = SMB2
    max protocol = SMB3

#======================= Share Definitions =======================

[homes]
    comment = Home directories
    browseable = yes
    writable = yes
    create mask = 0600
    force create mode = 0600
    directory mask = 0700
    force directory mode = 0700
    valid users = %S

[TimeMachine]
    path = /timemachine/%U
    fruit:time machine = yes
    fruit:time machine max size = 961G
    browseable = no
    writable = yes
    vfs objects = catia fruit streams_xattr
    valid users = @mongroupe

Joindre votre serveur NAS au domaine

net ads join -U Administrateur
Enter Administrateur's password:
Using short domain name -- MONDOMAINE
Joined 'NAS' to dns domain 'mondomaine.fr'

Ajouter winbind à l’authentification linux

vi /etc/nsswitch.conf

passwd:         compat winbind
group:          compat winbind
shadow:         compat winbind
gshadow:        files

hosts:          files dns
networks:       files

protocols:      db files
services:       db files
ethers:         db files
rpc:            db files

netgroup:       nis
sudoers:        files

Après reboot vérifiez la bonne intégration dans votre domaine

wbinfo --ping-dc
checking the NETLOGON for domain[MONDOMAINE] dc connection to "dc2.mondomaine.fr" succeeded

Lister les utilisateurs

wbinfo -u

Lister les groupes

wbinfo -g

Vérifier les informations de l’utilisateur

wbinfo -i colombet
colombet:*:12345:10513::/home/colombet:/bin/bash

Création automatique du dossier utilisateur

apt-get install oddjob-mkhomedir smbclient samba
pam-auth-update --force

Activer uniquement le service smbd

systemctl enable smbd.service
systemctl status smbd.service

Vérifier les ports en écoutent

netstat -tupln
tcp        0      0 127.0.0.1:445           0.0.0.0:*               LISTEN      2219/smbd
tcp        0      0 192.168.xx.xx:445         0.0.0.0:*               LISTEN      2219/smbd
tcp        0      0 127.0.0.1:139           0.0.0.0:*               LISTEN      2219/smbd
tcp        0      0 192.168.xx.xx:139         0.0.0.0:*               LISTEN      2219/smbd

smbclient -N -L localhost
Anonymous login successful

    Sharename       Type      Comment
    ---------       ----      -------
    homes           Disk      Home directories
    IPC$            IPC       IPC Service (my server)
SMB1 disabled -- no workgroup available

Tester votre fichier samba.conf

samba-tool testparm --suppress-prompt

Il est maintenant possible d’utiliser les acls posix

mkdir /home/colombet
chmod 700 /home/colombet
chown "colombet:domain users" /home/colombet

Gérer les ACLs depuis Windows

cf : https://www.vionblog.com/manage-samba-permissions-from-windows/
cf : https://wiki.samba.org/index.php/Setting_up_a_Share_Using_Windows_ACLs

net rpc rights grant "MONDOMAINE\Domain Admins" SeDiskOperatorPrivilege -U "MONDOMAINE\Administrateur"
net rpc rights revoke "MONDOMAINE\Domain Admins" SeDiskOperatorPrivilege -U "MONDOMAINE\Administrateur"
net rpc rights list privileges SeDiskOperatorPrivilege -U "MONDOMAINE\Administrateur"  

Lire les acls

getfacl /home/colombet/

getfacl: Removing leading '/' from absolute path names
# file: home/colombet/
# owner: colombet
# group: domain\040users
user::rwx
user:colombet:rwx
group::---
group:domain\040users:---
group:colombet:rwx
mask::rwx
other::---
default:user::rwx
default:user:colombet:rwx
default:group::---
default:group:domain\040users:---
default:mask::rwx
default:other::---

Reset des ACLs en récursif d’un répertoire

setfacl -Rbn /home/colombet/

Quotas

Afin de définir des quotas, il faut dans un premier temps déléguer des permissions aux utilisateurs du domaine ou à tout le monde d’accéder aux variables userquota,userused.

zfs allow "Domain Users" userquota,userused tank/home
ou
zfs allow everyone userquota,userused tank/home

Supprimer les délégations de permission

zfs unallow everyone tank/home
zfs unallow "Domain Users" tank/home
zfs unallow colombet tank/home

Mettre un quota sur l’utilisateur colombet

zfs set userquota@"MONDOMAINE\colombet"=1G tank/home
zfs set userquota@colombet=1G tank/home

Afficher un quota

zfs get -H "userquota@MONDOMAINE\colombet" tank/home | /usr/bin/awk '{ print $3 };'
zfs get -H "userquota@colombet" tank/home

Supprimer un quota

zfs set userquota@colombet=none tank/home

Maintenant que le système de fichier est prêt, il faut indiquer à Samba comment interpréter les quotas ZFS. Pour cela, ajouter la directive get quota command dans la partie globale du fichier /etc/samba/smb.conf

get quota command = /opt/scripts/samba_quotazfs.sh %U

Créer le script bash samba_quotazfs.sh

vi /opt/scripts/samba_quotazfs.sh
#!/bin/sh
# Jerome Colombet
# 01-10-2020
username=$1
if [ ! -z  "$username" ]; then
  smbpath=${PWD}
  dataset=`/bin/df -l ${smbpath} | /usr/bin/tail -n 1 | /usr/bin/awk '{ print $1 };'`
  infoused=`/sbin/zfs get -Hp userused@$username $dataset`
  infoquota=`/sbin/zfs get -Hp userquota@$username $dataset`
  usedbytes=`echo ${infoused}| /usr/bin/awk '{ printf "%.f", $3/1024 };';`
  quotabytes=`echo ${infoquota}| /usr/bin/awk '{ if ( $3 == "none" ) { print "0"} else { printf "%.f", $3/1024 }  };'`
  echo 2 $usedbytes $quotabytes $quotabytes $usedbytes $quotabytes $quotabytes
  #dans le cas d'une utilisation de crontab
  #info=`/sbin/zfs userspace -Hpo name,used,quota $dataset | /usr/bin/grep -i ${username}`
  #info=`/bin/more /tmp/quotazfs-home | /usr/bin/grep -i ${username}`
  #usedbytes=`echo ${info}| /usr/bin/awk '{ printf "%.f", $2/1024 };';`
fi
exit

Si utilisation du script précédent via crontab

# Quota ZFS home
*/5 * * * * /sbin/zfs userspace -Hpo name,used,quota tank/home > /tmp/quotazfs-home

Pour info ; *Flags Quotas *

1 - quota flags (0 = no quotas, 1 = quotas enabled, 2 = quotas enabled and enforced)
2 - number of currently used blocks
3 - the softlimit number of blocks
4 - the hardlimit number of blocks
5 - currently used number of inodes
6 - the softlimit number of inodes
7 - the hardlimit number of inodes
8 - (optional) - the number of bytes in a block(default is 1024) 

Avahi

Afin d’utiliser TimeMachine avec Samba, il est recommandé d’utiliser Avahi afin que le serveur soit détecté par le parc MacOS

apt install avahi-daemon

Créer la configuration pour le service Samba

vi /etc/avahi/services/samba.service

Exemple de fichier samba.service




%h _smb._tcp 445 _adisk._tcp sys=waMa=0,adVF=0x100 dk0=adVN=TimeMachine,adVF=0x82 _device-info._tcp 0 model=RackMac

Clamav

Installer clamav

apt-get purge -y clamav-unofficial-sigs
apt-get update && apt-get install -y clamav-base clamav-freshclam clamav clamav-daemon

Lancer les commandes suivantes depuis votre terminal en root

mkdir -p /usr/local/sbin/
wget https://raw.githubusercontent.com/extremeshok/clamav-unofficial-sigs/master/clamav-unofficial-sigs.sh -O /usr/local/sbin/clamav-unofficial-sigs.sh && chmod 755 /usr/local/sbin/clamav-unofficial-sigs.sh
mkdir -p /etc/clamav-unofficial-sigs/
wget https://raw.githubusercontent.com/extremeshok/clamav-unofficial-sigs/master/config/master.conf -O /etc/clamav-unofficial-sigs/master.conf
wget https://raw.githubusercontent.com/extremeshok/clamav-unofficial-sigs/master/config/user.conf -O /etc/clamav-unofficial-sigs/user.conf
wget "https://raw.githubusercontent.com/extremeshok/clamav-unofficial-sigs/master/config/os/os.debian.conf" -O /etc/clamav-unofficial-sigs/os.conf

Exécuter le script suivant afin de s’assurer qu’il n’y a pas d’erreurs, corriger les dépendances manquantes le script doit s’exécuter une fois en tant que super-utilisateur pour définir toutes les autorisations et créer les répertoires pertinents

/usr/local/sbin/clamav-unofficial-sigs.sh --force
################################################################################
 eXtremeSHOK.com ClamAV Unofficial Signature Updater
 Version: v7.2.5 (2021-03-20)
 Required Configuration Version: v96
 Copyright (c) Adrian Jon Kriel :: admin@extremeshok.com
################################################################################
Loading config: /etc/clamav-unofficial-sigs/master.conf
Loading config: /etc/clamav-unofficial-sigs/os.conf
Loading config: /etc/clamav-unofficial-sigs/user.conf
+++++++++++++++++++++++
NOTICE: forcing updates
+++++++++++++++++++++++
===================
Preparing Databases
===================
Sanesecurity public GPG key successfully downloaded
Sanesecurity public GPG key successfully imported to custom keyring
==================================================
Sanesecurity Database & GPG Signature File Updates
==================================================
Checking for Sanesecurity updates...
Sanesecurity mirror site used:  62.93.225.23

Installer la rotation des logs et le man

/usr/local/sbin/clamav-unofficial-sigs.sh --install-logrotate
/usr/local/sbin/clamav-unofficial-sigs.sh --install-man

Installer les services pour clamav-unofficial-sigs via systemd

mkdir -p /etc/systemd/system/
wget https://raw.githubusercontent.com/extremeshok/clamav-unofficial-sigs/master/systemd/clamav-unofficial-sigs.service -O /etc/systemd/system/clamav-unofficial-sigs.service
wget https://raw.githubusercontent.com/extremeshok/clamav-unofficial-sigs/master/systemd/clamav-unofficial-sigs.timer -O /etc/systemd/system/clamav-unofficial-sigs.timer

systemctl enable clamav-unofficial-sigs.service
systemctl enable clamav-unofficial-sigs.timer
systemctl start clamav-unofficial-sigs.timer

Testez le scan sur le dossier /home avec et sans résumé

clamdscan --multiscan --allmatch --remove --no-summary --fdpass /home
clamdscan --multiscan --allmatch --remove --fdpass /home

Créer le fichier de log

touch /var/log/clamav/manual_clamscan.log

Activer le scan automatique via un crontab

# Tous les jours à 20h30 passage antivirus dossier home
30 20 * * * /usr/bin/clamdscan --multiscan --allmatch --remove --fdpass /home >> /var/log/clamav/manual_clamscan.log

Veto Ransomware

Crée un fichier avec le paramètre “veto files = ” tous les fichiers de rançon connus, afin d’essayer de protéger votre home.

apt install jq
mkdir /opt/scripts
wget https://raw.githubusercontent.com/mauriciomagalhaes/Ransomware-veto-samba/master/ransomware-veto-smb.sh -O /opt/scripts/samba_veto_ransomware.sh

Éditer le fichier /opt/scripts/samba_veto_ransomware.sh afin de le traduire et l’adapter à Samba Debian 10

#!/bin/bash

SMBCONF="/etc/samba"
SMBCONTROL=$(which smbcontrol)
JQ=$(which jq)

while true; do
    if curl --output /dev/null --silent --head --fail https://fsrm.experiant.ca/api/v1/combined; then
        curl --silent -o $SMBCONF/ransomwares.json https://fsrm.experiant.ca/api/v1/combined && break
    fi
done

TOTALREG=$(jq -r .api.file_group_count $SMBCONF/ransomwares.json)
DATA=$(jq -r .lastUpdated $SMBCONF/ransomwares.json)

echo "Total des ransomware connus : $TOTALREG"
echo "Dernière mise à jour : $DATA"

$JQ -r .filters[] $SMBCONF/ransomwares.json > $SMBCONF/ransomwares.conf

sed -i 's/^/\//g' $SMBCONF/ransomwares.conf
sed -i ':a;N;s/\n//g;ta' $SMBCONF/ransomwares.conf
sed -i 's/^/veto files = /g' $SMBCONF/ransomwares.conf

$SMBCONTROL smbd reload-config

Rendre exécutable le script samba_veto_ransomware.sh

chmod 755 /opt/scripts/samba_veto_ransomware.sh

Programmer une mise à jour toutes les 6 heures via crontab

crontab -l
# Mise à jour toutes les 6 heures des ransomware connus
0 */6 * * * /opt/scripts/samba_veto_ransomware.sh

Créer un include dans la section [Global] du fichier smb.conf ou dans les partages.

[Global]
...
include = /etc/samba/ransomwares.conf
...

ZnapZend – ZFS Snapshot vers un serveur distant

Télécharger et installer le dernier paquet depuis https://github.com/Gregy/znapzend-debian/releases

wget https://github.com/Gregy/znapzend-debian/releases/download/0.20.0/znapzend_0.20.0-1_amd64.deb
dpkg -i znapzend_0.20.0-1_amd64.deb
apt install mbuffer 

Création d’un plan de snapshot sans synchro distante sur 5 jours toutes les heures

# znapzendzetup create --mbuffer=/usr/bin/mbuffer --mbuffersize=1G --tsformat=zfs-auto-snap-%Y-%m-%d-%H%M%S SRC '5d=>60min,1w=>1d' tank/home
*** backup plan: tank/home ***
         enabled = on
         mbuffer = /usr/bin/mbuffer
    mbuffer_size = 1G
   post_znap_cmd = off
    pre_znap_cmd = off
       recursive = off
             src = tank/home
        src_plan = 5days=>60minutes,1week=>1day
        tsformat = zfs-auto-snap-%Y-%m-%d-%H%M%S
      zend_delay = 0

Création de snapshot avec synchro zrepl ssh sur 5 jours toutes les heures

# znapzendzetup create --mbuffer=/usr/bin/mbuffer --mbuffersize=1G --tsformat=zfs-auto-snap-%Y-%m-%d-%H%M%S SRC '5d=>60min,1w=>1d' tank/home DST '5d=>60min,1w=>1d' root@backup:tank/home
*** backup plan: tank/home ***
           dst_0 = root@backup:tank/home
      dst_0_plan = 5days=>60minutes,1week=>1day
         enabled = on
         mbuffer = /usr/bin/mbuffer
    mbuffer_size = 1G
   post_znap_cmd = off
    pre_znap_cmd = off
       recursive = off
             src = tank/home
        src_plan = 5days=>60minutes,1week=>1day
        tsformat = zfs-auto-snap-%Y-%m-%d-%H%M%S
      zend_delay = 0

L’exemple de PLANS de snapshot précédent peut prendre les options suivantes

En local :

    toutes les heures pendant 5 jours : 5d=>1h
    tous les jours pendant 1 semaine : 1w=>1d

À distance :

    toutes les 6 heures pendant 2 jours : 2d=>6h
    tous les jours pendant 1 semaine : 1w=>1d
    garder une semaine : 1m=>1w
    garder un mois : 1m=>1w
    garder une semaine pendant 3 mois : 3m=>1w

Activer et relancer le service znapzend.service

systemctl restart znapzend.service
systemctl enable znapzend.service
watch -n 1 systemctl status znapzend.service

dernier snapshot vue depuis l’hôte ayant le plan de sauvegarde:

# znapzendztatz -r tank/home
USED    LAST SNAPSHOT       DATASET
   0B   No Snapshots Yet     tank/home
   0B   No Snapshots Yet     root@backup:tank/home

Le programme de backup est sauvegardé dans les propriétés du dataset ZFS :

# zfs get all tank/home | grep org.znapzend
tank/home  org.znapzend:mbuffer_size   1G                             local
tank/home  org.znapzend:dst_0          root@backup:tank/home          local
tank/home  org.znapzend:zend_delay     0                              local
tank/home  org.znapzend:tsformat       zfs-auto-snap-%Y-%m-%d-%H%M%S  local
tank/home  org.znapzend:enabled        on                             local
tank/home  org.znapzend:mbuffer        /usr/bin/mbuffer               local
tank/home  org.znapzend:dst_0_plan     5days=>1hours                  local
tank/home  org.znapzend:recursive      on                             local
tank/home  org.znapzend:post_znap_cmd  off                            local
tank/home  org.znapzend:src_plan       5days=>1hours                  local
tank/home  org.znapzend:pre_znap_cmd   off                            local

Lister les plans de sauvegardes

# znapzendzetup list
*** backup plan: tank/home ***
           dst_0 = root@backup:tank/home
      dst_0_plan = 5days=>1hours
         enabled = on
         mbuffer = /usr/bin/mbuffer
    mbuffer_size = 1G
   post_znap_cmd = off
    pre_znap_cmd = off
       recursive = off
             src = tank/home
        src_plan = 5days=>1hours
        tsformat = %Y-%m-%d-%H%M%S
      zend_delay = 0

Supprimer un plan de sauvegardes et reprise en compte par le service znapzend

znapzendzetup delete tank/home
pkill -HUP znapzend

Éditer un plan de sauvegardes et reprise en compte par le service znapzend

znapzendzetup edit tank/home
pkill -HUP znapzend

Zfs-Prune-Snapshots

J’ai trouvé pour vous un petit script pour gérer facilement vos snapshots. Il permet de supprimer des snapshots d’un ou plusieurs pools avec vos critères. Pour plus de détails : https://github.com/bahamas10/zfs-prune-snapshots.

wget https://raw.githubusercontent.com/bahamas10/zfs-prune-snapshots/master/zfs-prune-snapshots -O /opt/scripts/zfs-prune-snapshots
chmod 755 /opt/scripts/zfs-prune-snapshots

Simuler une purge des snapshots au-delà de 15 jours

zfs-prune-snapshots -n 15d tank

Purger des snapshots au-delà de 15 jours

zfs-prune-snapshots 15d tank

Ce script vient à remplacer la commande d’origine, ici pour supprimer tous les snapshot de l’hôte

~~# zfs list -H -o name -t snapshot | xargs -n1 zfs destroy~~

iSCSI

Ajouter à votre NAS la fonctionnalité SAN afin de l’interfacer votre cluster Proxmox c’est possible. Cette partie est basée sur cette documentation : https://deepdoc.at/dokuwiki/doku.php?id=virtualisierung:proxmox_kvm_und_lxc:proxmox_debian_als_zfs-over-iscsi_server_verwenden

Sur votre cluster Proxmox, les noeuds doivent accéder dynamiquement à l’ensemble des données ZFS de votre NAS. Pour cela, ils doivent être autorisés pour les ACLs dans targetcli. J’utilise les clés SSH à cette fin.

SUR VOTRE PROXMOX

Sur un de vos noeuds proxmox, générer un couple de clés ssh et les copier vers votre NAS

cd /etc/pve/priv/zfs
ssh-keygen -f /etc/pve/priv/zfs/192.168.0.100_id_rsa
ssh-copy-id -i /etc/pve/priv/zfs/192.168.0.100_id_rsa.pub root@192.168.0.100
Number of key(s) added: 1

Vérifier la connexion ssh depuis les noeuds Proxmox vers votre NAS via le couple de clé précédent

# ssh -i /etc/pve/priv/zfs/192.168.0.100_id_rsa root@192.168.0.100
root@backup:~# logout
Connection to 192.168.0.100 closed.

Récupérer tous les noms initiateurs de vos noeuds

cat /etc/iscsi/initiatorname.iscsi
InitiatorName=iqn.1993-08.org.debian:01:1ae0ad6ebb5f

SUR VOTRE NAS

Depuis votre NAS, créer un pool iscsi

zfs create tank/iscsi

Vérifier et à adapter selon vos propriétés

zfs list
NAME         USED  AVAIL     REFER  MOUNTPOINT
tank        1.05M  3.54G      128K  /tank
tank/home    128K  3.54G      128K  /tank/home
tank/iscsi   128K  3.54G      128K  /tank/iscsi

La configuration passe par la commande targetcli. Avec ls, nous pouvons voir l’arborescence, help affiche l’aide et avec saveconfig on enregistre les modifications.

# targetcli

targetcli shell version 2.1.fb48
Copyright 2011-2013 by Datera, Inc and others.
For help on commands, type 'help'.

/> ls
o- / .......................................................................................... [...]
  o- backstores ............................................................................... [...]
  | o- block ................................................................... [Storage Objects: 0]
  | o- fileio .................................................................. [Storage Objects: 0]
  | o- pscsi ................................................................... [Storage Objects: 0]
  | o- ramdisk ................................................................. [Storage Objects: 0]
  o- iscsi ............................................................................. [Targets: 0]
  o- loopback .......................................................................... [Targets: 0]
  o- vhost ............................................................................. [Targets: 0]
  o- xen-pvscsi ........................................................................ [Targets: 0]
/

Nous allons créer un target entrant dans le dossier iscsi et en exécutant create

/> cd iscsi
/iscsi> create
Created target iqn.2003-01.org.linux-iscsi.nas.x8664:sn.2c0c3e76710e.
Created TPG 1.
Global pref auto_add_default_portal=true
Created default portal listening on all IPs (0.0.0.0), port 3260.

Nous pouvons vérifier le nom de la target unique iqn.2003-01.org.linux-iscsi.nas.x8664:sn.2c0c3e76710e

/iscsi> ls
o- iscsi ............................................................................ [Targets: 1]
  o- iqn.2003-01.org.linux-iscsi.nas.x8664:sn.2c0c3e76710e.............................. [TPGs: 1]
    o- tpg1 ............................................................... [no-gen-acls, no-auth]
      o- acls .......................................................................... [ACLs: 0]
      o- luns .......................................................................... [LUNs: 0]
      o- portals .................................................................... [Portals: 1]
        o- 0.0.0.0:3260 ..................................................................... [OK]

Ajouter des ACLs avec les initiateurs de vos noeuds proxmox

/iscsi>cd iqn.2003-01.org.linux-iscsi.nas.x8664:sn.2c0c3e76710e/
/iscsi/iqn.20....2c0c3e76710e> cd tpg1
/iscsi/iqn.20...3e76710e/tpg1> cd acls
/iscsi/iqn.20...10e/tpg1/acls> create iqn.1993-08.org.debian:01:1ae0ad6ebb5f

Ne pas oublier de sauvegarder vos paramètres

/> saveconfig
Configuration saved to /etc/rtslib-fb-target/saveconfig.json
/> exit
Global pref auto_save_on_exit=true
Last 10 configs saved in /etc/rtslib-fb-target/backup.
Configuration saved to /etc/rtslib-fb-target/saveconfig.json

SUR VOTRE PROXMOX

Depuis l’interface, ajouter un storage ZFS over iSCSI

2021-04-08 17.15.22

Ou en éditant le fichier via le CLI pour ajouter le stockage

more /etc/pve/storage.cfg

zfs: iscsi-zfs
    disable
    blocksize 4k
    iscsiprovider LIO
    pool tank/iscsi
    portal 192.168.0.100
    target iqn.2003-01.org.linux-iscsi.nas.x8664:sn.2c0c3e76710e
    content images
    lio_tpg tpg1
    nodes finn
    nowritecache 1
    sparse 1

Pour supprimer une target

/> cd iscsi/
/iscsi> delete iqn.2003-01.org.linux-iscsi.nas.x8664:sn.2c0c3e76710e
Deleted Target iqn.2003-01.org.linux-iscsi.nas.x8664:sn.2c0c3e76710e.

DEBUG

Voici un petit panel des erreurs rencontrées :

Erreur 1 :

Dec  5 20:27:20 nas systemd[3272]: gpgconf: error running '/usr/lib/gnupg/scdaemon': probably not installed

Solution, installer les paquets manquants

# apt remove gpg-agent gnupg-l10n gnupg-utils pinentry-curses gpgconf gnupg dirmngr gpg gpgconf gpgsm libgpgme11 python-gpg samba-dsdb-modules libassuan0 libksba8 libnpth0 --purge

# apt install scdaemon gpg-agent gpgconf pinentry-curses dirmngr gpg gpgconf gpgsm libgpgme11 python-gpg samba-dsdb-modules 

Erreur 2 :

 [2020/12/09 14:12:52.633413,  0] ../source3/param/loadparm.c:3362(process_usershare_file)
   process_usershare_file: stat of /var/lib/samba/usershares/systemresources failed. Permission denied
 [2020/12/09 14:12:52.635011,  0] ../source3/param/loadparm.c:3362(process_usershare_file)
   process_usershare_file: stat of /var/lib/samba/usershares/systemresources failed. No such file or directory

Solution, ajouter dans la partie [global] la directive usershare path à vide

usershare path =

Erreur 3 :

[2020/12/05 09:49:39.675193,  0] ../source3/nmbd/nmbd_namequery.c:109(query_name_response)
  query_name_response: Multiple (2) responses received for a query on subnet 10.0.210.161 for name MONDOMAINE.

Ajouter dans la partie [global] du fichier /etc/samba/smb.conf

local master = no
domain master = no 
preferred master = no
disable netbios = yes

Et désactiver le service nmbd

systemctl stop nmbd.service
systemctl disable nmbd.service

Erreur 4 :

Dec  2 09:30:02 nas clamd[8464]: Wed Dec  2 09:30:02 2020 -> Reading databases from /var/lib/clamav
Dec  2 09:30:14 nas smbd[1245]: [2020/12/02 09:30:14.291538,  0] ../source3/smbd/dosmode.c:302(get_ea_dos_attribute)
Dec  2 09:30:14 nas smbd[1245]:   get_ea_dos_attribute: Rejecting root override, invalid stat [mon-equipe]
Dec  2 09:30:18 nas smbd[1245]: [2020/12/02 09:30:18.161030,  0] ../source3/smbd/dosmode.c:302(get_ea_dos_attribute)

Supprimer dans la partie [global] les vfs objects pour TimeMachine

vfs objects = shadow_copy2 acl_xattr
#vfs objects = shadow_copy2 catia fruit streams_xattr acl_xattr

Erreur 5 :

Dec 10 08:58:21 nas smbd[37182]: [2020/12/10 08:58:21.876529,  0] ../source3/smbd/uid.c:453(change_to_user_internal)
Dec 10 08:58:21 nas smbd[37182]:   change_to_user_internal: chdir_current_service() failed!

Forcer un utilisateur pour un montage :

force user = nobody

Références

Zfs

ZnapZend – ZFS Snapshot vers un serveur distant

Timemachine

Veto Ransomware

CLAMAV