Pare-feu et Fail2ban : verrouiller les accès réseau du NAS

Pare-feu et Fail2ban : verrouiller les accès réseau du NAS

·6 min de lecture·Mis à jour le 20 janvier 2026

Pourquoi un pare-feu sur un NAS domestique

Un NAS est un serveur qui tourne 24h/24 et héberge des données sensibles : partages de fichiers, media server, parfois de la domotique. Sans pare-feu, tous les ports sont ouverts par défaut et n'importe quel appareil du réseau peut y accéder. Dès qu'un port est exposé vers l'extérieur pour de l'accès distant, la surface d'attaque explose.

Deux couches complémentaires sur ce TerraMaster F4-424 : UFW pour filtrer les ports, Fail2ban pour détecter et bannir les tentatives d'intrusion.

UFW : un pare-feu lisible

UFW est un frontend pour iptables/nftables dont l'avantage principal est la lisibilité des règles, face à la syntaxe cryptique d'iptables.

Politique par défaut — tout verrouiller d'abord :

ufw default deny incoming
ufw default allow outgoing

Tout le trafic entrant est bloqué sauf autorisation explicite, tandis que le NAS peut communiquer vers l'extérieur (mises à jour, DNS, NTP).

SSH — plutôt qu'un simple allow, limit restreint à 3 connexions par minute depuis la même IP, ce qui constitue une première défense contre le brute-force avant même Fail2ban :

ufw limit ssh

Services LAN uniquement — les partages de fichiers n'ont pas besoin d'être joignables depuis Internet :

# Samba (Windows/macOS)
ufw allow from 192.168.1.0/24 to any port 445
ufw allow from 192.168.1.0/24 to any port 139

# NFS (Linux)
ufw allow from 192.168.1.0/24 to any port 2049

Services Docker exposés — certains conteneurs doivent rester accessibles, y compris via VPN :

ufw allow 8096/tcp   # Jellyfin
ufw allow 6881/tcp   # qBittorrent
ufw allow 22000/tcp  # Syncthing
ufw allow 8123/tcp   # Home Assistant

Un ufw status verbose donne l'état complet :

Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)

To                         Action      From
--                         ------      ----
22/tcp                     LIMIT       Anywhere
445                        ALLOW       192.168.1.0/24
139                        ALLOW       192.168.1.0/24
2049                       ALLOW       192.168.1.0/24
8096/tcp                   ALLOW       Anywhere
6881/tcp                   ALLOW       Anywhere
22000/tcp                  ALLOW       Anywhere
8123/tcp                   ALLOW       Anywhere

Le piège Docker + UFW

Docker bypasse UFW. Quand Docker publie un port (-p 8080:80), il injecte ses règles directement dans iptables avant UFW. Résultat : les conteneurs sont accessibles depuis partout même si UFW bloque le port.

Option 1 — désactiver iptables dans Docker, via /etc/docker/daemon.json :

{
  "iptables": false
}

Attention : Docker ne gère alors plus le NAT des conteneurs, il faut le configurer manuellement.

Option 2, préférable — ajouter des règles dans DOCKER-USER, qui s'évalue avant les règles Docker :

# /etc/ufw/after.rules (à la fin du fichier)
*filter
:DOCKER-USER - [0:0]
-A DOCKER-USER -s 192.168.1.0/24 -j ACCEPT
-A DOCKER-USER -j DROP
COMMIT

Docker reste fonctionnel, mais les conteneurs sont limités au LAN.

Fail2ban : bannir les intrus

UFW filtre les ports mais ne détecte pas les tentatives de brute-force. Fail2ban surveille les logs et bannit temporairement les IP suspectes.

La jail SSH, dans /etc/fail2ban/jail.local :

[sshd]
enabled  = true
port     = ssh
filter   = sshd
logpath  = /var/log/auth.log
backend  = systemd

# 3 tentatives max avant ban
maxretry = 3

# Fenêtre de détection : 10 minutes
findtime = 600

Bans progressifs

Plutôt qu'un ban fixe, une stratégie progressive : une erreur de mot de passe coûte dix minutes, un attaquant qui insiste se retrouve banni de plus en plus longtemps.

# Ban progressif
bantime.increment    = true
bantime.multipliers  = 1 5 30 60 180 360 720
bantime              = 600
RécidiveMultiplicateurDurée du ban
1er banx110 minutes
2e banx550 minutes
3e banx305 heures
4e banx60~10 heures
5e banx180~30 heures
6e banx360~2.5 jours
7e banx720~5 semaines

Un bot qui insiste finit banni cinq semaines ; en pratique, la quasi-totalité abandonne avant.

L'action par défaut bloque l'IP via iptables. action = %(action_mwl)s ajoute un email avec les logs et le whois de l'attaquant, utile pour monitorer.

Vérification de l'état de la jail :

fail2ban-client status sshd
Status for the jail: sshd
|- Filter
|  |- Currently failed: 0
|  |- Total failed:     47
|  `- File list:        /var/log/auth.log
`- Actions
   |- Currently banned: 2
   |- Total banned:     12
   `- Banned IP list:   203.0.113.42 198.51.100.7

Automatisation Ansible

Le pare-feu et Fail2ban sont déployés via un rôle Ansible idempotent :

# roles/firewall/tasks/main.yml
- name: Install UFW and Fail2ban
  ansible.builtin.apt:
    name:
      - ufw
      - fail2ban
    state: present
  tags: [firewall]

- name: Set UFW default policies
  community.general.ufw:
    direction: '{{ item.direction }}'
    policy: '{{ item.policy }}'
  loop:
    - { direction: incoming, policy: deny }
    - { direction: outgoing, policy: allow }
  tags: [firewall, ufw]

- name: Configure UFW rules
  community.general.ufw:
    rule: '{{ item.rule }}'
    port: '{{ item.port }}'
    proto: "{{ item.proto | default('tcp') }}"
    from_ip: "{{ item.from_ip | default('any') }}"
  loop: '{{ firewall_rules }}'
  tags: [firewall, ufw]

- name: Deploy Fail2ban jail configuration
  ansible.builtin.template:
    src: jail.local.j2
    dest: /etc/fail2ban/jail.local
    mode: '0644'
  notify: Restart fail2ban
  tags: [firewall, fail2ban]

Les règles vivent dans les variables du rôle : déclaratif et versionnable dans Git.

Conclusion

UFW rend le filtrage de ports accessible, Fail2ban ajoute une détection active, et Ansible garantit que tout survit aux réinstallations. Le piège Docker/UFW reste le point le plus critique : sans l'avoir adressé, les conteneurs sont probablement exposés sans qu'on le sache.

PartagerLinkedInXBluesky

Articles similaires