July 1, 2025

Firewall and VM Safety, A Comprehensive Guide

Article image

🎯 Objectifs

  • Limiter les requêtes ping
  • Protéger l’accès SSH avec Fail2Ban
  • Rediriger un port vers un service
  • Logger les accès HTTP
  • Bloquer les requêtes contenant certains mots-clés

🔧 Prérequis

  • Une VM Linux (Debian/Ubuntu)
  • Accès root (sudo)
  • Un service tournant (ex: un serveur web sur le port 8080)

1. 🔐 Limiter le Ping (ICMP)

Limiter les requêtes ping entrantes à 1 par seconde :

sudo iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 30/minute -j ACCEPT
sudo iptables -A INPUT -p icmp --icmp-type echo-request -j DROP

✅ Vérifie avec :

ping -f <adresse_ip_de_ta_vm>

2. 🛡️ Sécuriser SSH avec Fail2Ban

Installation

sudo apt update
sudo apt install fail2ban -y

Configuration

sudo nano /etc/fail2ban/jail.local

Ajouter :

[sshd]
enabled = true
port    = ssh
logpath = %(sshd_log)s
backend = systemd
maxretry = 3
bantime  = 3600
findtime = 600

Activation

sudo systemctl restart fail2ban
sudo fail2ban-client status sshd

✅ Vérifie que Fail2Ban détecte bien des tentatives de connexion SSH anormales.


3. 🔁 Redirection du port 8000 vers un service (ex: 8080)

Si ton application écoute sur le port 8080, redirige le trafic entrant sur 8000 :

sudo iptables -t nat -A PREROUTING -p tcp --dport 8000 -j REDIRECT --to-port 8080
sudo iptables -t nat -A OUTPUT -p tcp --dport 8000 -j REDIRECT --to-port 8080

✅ Teste avec :

curl http://localhost:8000

4. 📜 Logger les accès HTTP (port 80)

Ajouter une règle de log pour surveiller les accès au port 80 :

sudo iptables -A INPUT -p tcp --dport 80 -j LOG --log-prefix "HTTP ACCESS: "

✅ Voir les logs :

sudo tail -f /var/log/syslog

5. 🚫 Bloquer les requêtes contenant le mot “lamp”

Fonctionne uniquement avec du trafic HTTP (non-HTTPS) :

sudo iptables -A INPUT -p tcp --dport 80 -m string --string "lamp" --algo bm -j DROP

✅ Teste en envoyant une requête contenant ce mot (curl, telnet…).


🧠 Bonus : Rendre les règles persistantes

sudo apt install iptables-persistent -y
sudo netfilter-persistent save

📄 Vérification de l’état des règles

Lister les règles iptables :

sudo iptables -L -n -v

Lister les règles NAT :

sudo iptables -t nat -L -n -v

📦 Script Bash (optionnel)

Créer un script pour automatiser tout le TP :

nano tp_firewall.sh

Contenu :

#!/bin/bash
# TP Firewall

# Limiter le ping
iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 1/second -j ACCEPT
iptables -A INPUT -p icmp --icmp-type echo-request -j DROP

# Redirection du port 8000 vers 8080
iptables -t nat -A PREROUTING -p tcp --dport 8000 -j REDIRECT --to-port 8080

# Log des accès sur le port 80
iptables -A INPUT -p tcp --dport 80 -j LOG --log-prefix "HTTP ACCESS: "

# Bloquer les requêtes contenant "lamp"
iptables -A INPUT -p tcp --dport 80 -m string --string "lamp" --algo bm -j DROP

# Sauvegarde
netfilter-persistent save

Puis rends-le exécutable :

chmod +x tp_firewall.sh
sudo ./tp_firewall.sh

Ping delayed

ping 192.168.122.242
PING 192.168.122.242 (192.168.122.242) 56(84) bytes of data.
64 bytes from 192.168.122.242: icmp_seq=1 ttl=64 time=0.877 ms
64 bytes from 192.168.122.242: icmp_seq=2 ttl=64 time=0.550 ms
64 bytes from 192.168.122.242: icmp_seq=3 ttl=64 time=0.656 ms
64 bytes from 192.168.122.242: icmp_seq=4 ttl=64 time=0.604 ms
[...]
64 bytes from 192.168.122.242: icmp_seq=111 ttl=64 time=0.554 ms
64 bytes from 192.168.122.242: icmp_seq=113 ttl=64 time=0.665 ms
^C
--- 192.168.122.242 ping statistics ---
114 packets transmitted, 62 received, 45.614% packet loss, time 115693ms
rtt min/avg/max/mdev = 0.321/0.575/0.930/0.138 ms

On a bien un paquet sur deux qui est drop, ce qui correspond à ma règle de 30 ping par minute

Fail2Ban

sudo fail2ban-client status sshd
Status for the jail: sshd
|- Filter
|  |- Currently failed: 0
|  |- Total failed: 3
|  `- Journal matches: _SYSTEMD_UNIT=sshd.service + _COMM=sshd
`- Actions
   |- Currently banned: 1
   |- Total banned: 1
   `- Banned IP list: 192.168.122.1

Server on 8080

nohup python3 -m http.server 8080 >/dev/null 2>&1 &
[1] 2031

Redirect 8080 on 8000

sudo iptables -L -v -n
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
   62  5208 ACCEPT     1    --  *      *       0.0.0.0/0            0.0.0.0/0            icmptype 8 limit: avg 30/min burst 5
   52  4368 DROP       1    --  *      *       0.0.0.0/0            0.0.0.0/0            icmptype 8

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
heralys@debian:~$ sudo iptables -t nat -L -v -n
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 REDIRECT   6    --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:8000 redir ports 8080

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    1    60 REDIRECT   6    --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:8000 redir ports 8080

Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination  

Ping le localhost:8000 et on a bien le serveur python du 8080 qui répond

Requête lamp

 curl -v "http://192.168.122.242/lamp"
*   Trying 192.168.122.242:80...
* Connected to 192.168.122.242 (192.168.122.242) port 80
> GET /lamp HTTP/1.1
> Host: 192.168.122.242
> User-Agent: curl/8.9.1
> Accept: */*
> 
* Request completely sent off
^C
ubuntu@vps-67b06a10:~$ curl -v "http://192.168.122.242"
*   Trying 192.168.122.242:80...
* Connected to 192.168.122.242 (192.168.122.242) port 80
> GET / HTTP/1.1
> Host: 192.168.122.242
> User-Agent: curl/8.9.1
> Accept: */*
> 
* Request completely sent off
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Server: SimpleHTTP/0.6 Python/3.11.2
< Date: Mon, 16 Jun 2025 07:35:17 GMT
< Content-type: text/html; charset=utf-8
< Content-Length: 642
< 
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Directory listing for /</title>
</head>
<body>
<h1>Directory listing for /</h1>
<hr>
<ul>
<li><a href=".bash_history">.bash_history</a></li>
<li><a href=".bash_logout">.bash_logout</a></li>
<li><a href=".bashrc">.bashrc</a></li>
<li><a href=".cache/">.cache/</a></li>
<li><a href=".config/">.config/</a></li>
<li><a href=".face">.face</a></li>
<li><a href=".face.icon">.face.icon@</a></li>
<li><a href=".local/">.local/</a></li>
<li><a href=".profile">.profile</a></li>
<li><a href=".sudo_as_admin_successful">.sudo_as_admin_successful</a></li>
</ul>
<hr>
</body>
</html>
* shutting down connection #0

Si on a un lamp la requête est bien bloquée

sudo iptables -L INPUT -v -n --line-numbers
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1       62  5208 ACCEPT     1    --  *      *       0.0.0.0/0            0.0.0.0/0            icmptype 8 limit: avg 30/min burst 5
2       52  4368 DROP       1    --  *      *       0.0.0.0/0            0.0.0.0/0            icmptype 8
3       38  3722 LOG        6    --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:80 LOG flags 0 level 4 prefix "HTTP ACCESS: "
4       19  2546 DROP       6    --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:80 STRING match  "lamp" ALGO name bm
Share