<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="fr">
	<id>https://tala-informatique.fr/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jc.forton</id>
	<title>The Linux Craftsman - Contributions [fr]</title>
	<link rel="self" type="application/atom+xml" href="https://tala-informatique.fr/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jc.forton"/>
	<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Sp%C3%A9cial:Contributions/Jc.forton"/>
	<updated>2026-07-31T23:08:47Z</updated>
	<subtitle>Contributions</subtitle>
	<generator>MediaWiki 1.43.6</generator>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4424</id>
		<title>Proxmox fail2ban</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4424"/>
		<updated>2026-07-13T09:43:20Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Comment bannir derrière un reverse-proxy ? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
Proxmox utilise une interface web d&#039;administration qui utilise le port TCP 8006 et c&#039;est un vecteur possible d&#039;attaque par force brut. Nous allons donc &#039;&#039;dresser&#039;&#039; fail2ban pour agir en cas d&#039;attaque !&lt;br /&gt;
&lt;br /&gt;
Proxmox utilise Debian, nous allons principalement reproduire les étapes décrites dans le tutoriel de [[Sécuriser_un_service_avec_Fail2ban| Fail2ban pour Rocky]] et adapter à Debian.&lt;br /&gt;
&lt;br /&gt;
Avant d&#039;aller plus loin, assurez-vous d&#039;avoir correctement installé et configuré [[proxmox_iptables |iptables sur Proxmox]]&lt;br /&gt;
&lt;br /&gt;
= Installation =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt -y install fail2ban&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Configuration =&lt;br /&gt;
Tout d&#039;abord il faut copier le fichier &#039;&#039;/etc/fail2ban/jail.conf&#039;&#039; en &#039;&#039;/etc/fail2ban/jail.local&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dans ce fichier, on va s&#039;intéresser aux variables suivantes:&lt;br /&gt;
*ignoreip : correspond à la suite d&#039;adresses IP qui ne se feront jamais bannir;&lt;br /&gt;
*maxretry : correspond au nombre d&#039;essais;&lt;br /&gt;
*findtime : correspond à la période pendant laquelle les essais vont incrémenter maxretry;&lt;br /&gt;
*bantime  : correspond au temps où l&#039;adresse IP ne peut pas se connecter.&lt;br /&gt;
&lt;br /&gt;
= Configuration de base =&lt;br /&gt;
== Choix de la punition ==&lt;br /&gt;
Il faut choisir quelque chose de cohérent (une punition suffisante) pour ne pas permettre de se faire cracker son mot de passe:&lt;br /&gt;
*maxretry = 3&lt;br /&gt;
*findtime = 86400 (correspond à 1 journée)&lt;br /&gt;
*bantime = 604800 (correspond à 1 semaine)&lt;br /&gt;
&lt;br /&gt;
Cela signifie que si une adresse IP se trompe 3 fois en 1 journée (86400s) elle se fait bannir pendant 1 semaine (604800s).&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul permet de trouver le nombre maximal de tentatives durant une année:&lt;br /&gt;
&lt;br /&gt;
365 jours / 7 jours par semaine * 3 tentatives = 156 essais, ce qui reste raisonnable. &lt;br /&gt;
&lt;br /&gt;
Si le pirate possède un [http://fr.wikipedia.org/wiki/Botnet botnet], il faut bien sûr multiplier ce nombre par le nombre de machines dans le botnet...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Attention : fail2ban parcours les logs de connexion pour connaître le numéro de la tentative, ce qui a pour conséquence, si le &#039;&#039;findtime&#039;&#039; est grand, de prendre un certain temps...&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Jail pour SSH ==&lt;br /&gt;
Il suffit d&#039;ajouter la ligne &#039;&#039;enabled=true&#039;&#039; dans la section à activer !&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[sshd]&lt;br /&gt;
&lt;br /&gt;
# To use more aggressive sshd modes set filter parameter &amp;quot;mode&amp;quot; in jail.local:&lt;br /&gt;
# normal (default), ddos, extra or aggressive (combines all).&lt;br /&gt;
# See &amp;quot;tests/files/logs/sshd&amp;quot; or &amp;quot;filter.d/sshd.conf&amp;quot; for usage example and details.&lt;br /&gt;
#mode   = normal&lt;br /&gt;
enabled = true&lt;br /&gt;
port    = ssh&lt;br /&gt;
logpath = %(sshd_log)s&lt;br /&gt;
backend = %(sshd_backend)s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Configuration spécifique =&lt;br /&gt;
== Jail pour PVEPROXY ==&lt;br /&gt;
Pveproxy écoute sur le port 8006 et ne fonctionne pas exactement comme un serveur [[HTTPD | Apache httpd]] qui mettrait ces logs dans le fichier &#039;&#039;error_log&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Nous allons mettre cette configuration spécifique dans le fichier &#039;&#039;/etc/fail2ban/jail.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[proxmox]&lt;br /&gt;
enabled = true&lt;br /&gt;
port = https,http,8006&lt;br /&gt;
filter = proxmox&lt;br /&gt;
backend = systemd&lt;br /&gt;
maxretry = 5&lt;br /&gt;
findtime = 1d&lt;br /&gt;
bantime = 1w&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le backend utilisé est systemd, exactement comme si vous utilisiez la commande :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Filtre pour PVEPROXY ==&lt;br /&gt;
Il ne nous reste plus qu&#039;à spécifier le filtre &#039;&#039;proxmox&#039;&#039; dans le fichier &#039;&#039;/etc/fail2ban/filter.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=&amp;lt;HOST&amp;gt; user=.* msg=.*&lt;br /&gt;
ignoreregex =&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Tests =&lt;br /&gt;
Il faut maintenant tester le filtre et pour ça on peut utiliser un partage de connexion et réaliser le nombre d&#039;échecs spécifié par la directive &amp;quot;maxretry&amp;quot; (ici 3) :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed:	0&lt;br /&gt;
|  |- Total failed:	3&lt;br /&gt;
|  `- Journal matches:	_SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned:	1&lt;br /&gt;
   |- Total banned:	1&lt;br /&gt;
   `- Banned IP list:	37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On voit bien l&#039;IP 37.167.23.159 qui est bannie !&lt;br /&gt;
N&#039;oubliez pas de l&#039;ajouter à &#039;&#039;ignoreip&#039;&#039; dans le fichier &#039;&#039;jails.local&#039;&#039; ou de faire &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client unban 37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Démarrage et enregistrement dans le chargeur de démarrage =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start fail2ban.service&lt;br /&gt;
# systemctl enable fail2ban.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Vous pouvez maintenant démarrer fail2ban&lt;br /&gt;
&lt;br /&gt;
= Proxification=&lt;br /&gt;
Lorsque votre serveur Proxmox se trouve derrière un reverse-proxy (Apache, Nginx, Traefik, ...), au niveau 3 OSI, l&#039;adresse IP du client est remplacée par celle du proxy et le serveur utilise l&#039;entêtes &#039;&#039;X-Forwarded-For&#039;&#039; ou &#039;&#039;X-Real-IP&#039;&#039; pour transporter l&#039;adresse du client &lt;br /&gt;
[[Fichier:Reverse proxy proxmox.png|700px|centré]]&lt;br /&gt;
Dans cette exemple:&lt;br /&gt;
* le nom de domaine utilisé est &#039;&#039;&#039;pve.tala-informatique.fr&#039;&#039;&#039;&lt;br /&gt;
* l&#039;adresse du proxy est &#039;&#039;&#039;192.168.4.100&#039;&#039;&#039;&lt;br /&gt;
* l&#039;adresse du serveur Proxmox est &#039;&#039;&#039;192.168.4.1&#039;&#039;&#039;&lt;br /&gt;
== Configuration du reverse-proxy ==&lt;br /&gt;
Sur votre reverse-proxy Apache, vous devriez avoir une configuration qui ressemble à ça:&lt;br /&gt;
&amp;lt;source lang=apache&amp;gt;&lt;br /&gt;
MDomain pve.tala-informatique.fr&lt;br /&gt;
&lt;br /&gt;
&amp;lt;VirtualHost *:80&amp;gt;&lt;br /&gt;
    ServerName pve.tala-informatique.fr&lt;br /&gt;
    Redirect / https://pve.tala-informatique.fr/&lt;br /&gt;
&amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;VirtualHost *:443&amp;gt;&lt;br /&gt;
    ServerName pve.tala-informatique.fr&lt;br /&gt;
    &lt;br /&gt;
    SSLEngine on&lt;br /&gt;
    SSLProxyEngine on&lt;br /&gt;
    SSLProxyVerify none &lt;br /&gt;
    SSLProxyCheckPeerCN off&lt;br /&gt;
    SSLProxyCheckPeerName off&lt;br /&gt;
    &lt;br /&gt;
    ProxyRequests off&lt;br /&gt;
    ProxyPreserveHost On&lt;br /&gt;
    &lt;br /&gt;
    RewriteEngine on&lt;br /&gt;
    RewriteCond %{HTTP:Connection} Upgrade [NC]&lt;br /&gt;
    RewriteCond %{HTTP:Upgrade} websocket [NC]&lt;br /&gt;
    RewriteRule ^/?(.*) wss://192.168.4.1:8006/$1 [P,L]&lt;br /&gt;
&lt;br /&gt;
    ProxyPass / https://192.168.4.1:8006/ flushpackets=On connectiontimeout=300 timeout=300&lt;br /&gt;
    ProxyPassReverse / https://192.168.4.1:8006/&lt;br /&gt;
    ProxyTimeout     600&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La première ligne renvoie à la configuration de mod_md abordée dans cette [[Httpd_certificate_security#Let&#039;s_Encrypt |article]] et permet l&#039;obtention du certificat SSL auprès de [https://letsencrypt.org Let&#039;s encrypt]&lt;br /&gt;
&amp;lt;source lang=apache&amp;gt;&lt;br /&gt;
MDomain pve.tala-informatique.fr&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le bloc suivant permet de [[Httpd_redirect_reverse-proxy_mod-rewrite#http_→_https | renvoyer les utilisateurs]] se présentant sur le port 80 vers le port 443&lt;br /&gt;
&amp;lt;source lang=apache&amp;gt;&lt;br /&gt;
&amp;lt;VirtualHost *:80&amp;gt;&lt;br /&gt;
    ServerName pve.tala-informatique.fr&lt;br /&gt;
    Redirect / https://pve.tala-informatique.fr/&lt;br /&gt;
&amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dans le bloc &#039;&#039;443&#039;&#039;, on est obligé de désactiver les vérifications SSL parce que le certificat du serveur Proxmox est autosigné (donc pas de cadenas vert), ce qui pousse Apache à bloquer la connexion si on ne désactive pas ces vérifications&lt;br /&gt;
&amp;lt;source lang=apache&amp;gt;&lt;br /&gt;
SSLProxyVerify none &lt;br /&gt;
SSLProxyCheckPeerCN off&lt;br /&gt;
SSLProxyCheckPeerName off&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
La réécriture d&#039;url doit être configuré pour prendre en compte les &#039;&#039;websockets sécurisées&#039;&#039; (wss) utilisées pour l&#039;affichage de l&#039;écran des machine ou conteneurs avec &#039;&#039;xterm.js&#039;&#039;&lt;br /&gt;
&amp;lt;source lang=apache&amp;gt;&lt;br /&gt;
RewriteEngine on&lt;br /&gt;
RewriteCond %{HTTP:Connection} Upgrade [NC]&lt;br /&gt;
RewriteCond %{HTTP:Upgrade} websocket [NC]&lt;br /&gt;
RewriteRule ^/?(.*) wss://192.168.4.1:8006/$1 [P,L]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Enfin on redirige les requêtes vers le serveur Proxmox en n&#039;oubliant pas de préciser le port 8006&lt;br /&gt;
&amp;lt;source lang=apache&amp;gt;&lt;br /&gt;
ProxyPass / https://192.168.4.1:8006/ flushpackets=On connectiontimeout=300 timeout=300&lt;br /&gt;
ProxyPassReverse / https://192.168.4.1:8006/&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
== Problème lié à la proxyfication ==&lt;br /&gt;
Le problème est que la seule adresse que fail2ban va voir apparaître dans les logs est celle du reverse-proxy (&#039;&#039;192.168.4.100&#039;&#039;) :&lt;br /&gt;
[[Fichier:Reverse proxy ip logs.png|600px|centré]]&lt;br /&gt;
Même si le filtre &#039;&#039;fail2ban&#039;&#039; est configuré pour utiliser la commande &#039;&#039;journactl&#039;&#039; sur le démon &#039;&#039;pvedaemon&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
les adresses viennent de pveproxy qui journalise tout dans &#039;&#039;/var/log/pveproxy/access.log&#039;&#039; et &#039;&#039;pvedaemon&#039;&#039; ne journalise que les échecs d&#039;authentification. &lt;br /&gt;
Il est donc plus simple de faire un &#039;&#039;tail&#039;&#039; ou un &#039;&#039;cat&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Que d&#039;utiliser &#039;&#039;journalctl&#039;&#039; pour voir les IPs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
Dec 14 10:43:01 labo unix_chkpwd[1326506]: password check failed for user (root)&lt;br /&gt;
Dec 14 10:43:01 labo IPCC.xs[1320783]: pam_unix(proxmox-ve-auth:auth): authentication failure; logname= uid=0 euid=0 tty= ruser= rhost=37.167.23.159  user=root&lt;br /&gt;
Dec 14 10:43:03 labo pvedaemon[1320783]: authentication failure; rhost=192.168.4.100 user=root@pam msg=Authentication failure&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Configuration de pveproxy ==&lt;br /&gt;
Si on veut voir l&#039;adresse du client, il faut dire au [https://fr.wikipedia.org/wiki/Daemon_(informatique)| démon] &#039;&#039;pveproxy&#039;&#039; d&#039;utiliser l&#039;une des deux entêtes précédentes ainsi que préciser l&#039;adresse du proxy. &lt;br /&gt;
&lt;br /&gt;
Préciser l&#039;adresse du proxy est essentiel pour que &#039;&#039;pveproxy&#039;&#039; n&#039;accepte de lire l&#039;adresse du client présente dans l&#039;entête &#039;&#039;&#039;uniquement&#039;&#039;&#039; si cela provient du proxy, qui est une machine de confiance. Le cas contraire, tout le monde pourrait ajouter une adresse IP dans l&#039;entête pour la faire bannir...&lt;br /&gt;
&lt;br /&gt;
Nous allons créer le fichier &#039;&#039;/etc/default/pveproxy&#039;&#039; avec les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Forwarded-For&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Real-IP&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_ALLOW_FROM=&amp;quot;192.168.4.100&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il faut maintenant redémarrer &#039;&#039;pveproxy&#039;&#039; pour que les changements s&#039;appliquent. Si vous êtes connecté via l&#039;interface web, cela va vous déconnecter, le temps que le démon redémarre, il faudra ensuite certainement rafraîchir la page web.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl restart pveproxy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à vérifier dans les logs si les bonnes adresses s&#039;affichent:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Si jamais ce n&#039;est pas le cas, poursuivez avec la modification du fichier &#039;&#039;AnyEvent.pm&#039;&#039;&lt;br /&gt;
== Modification de AnyEvent.pm ==&lt;br /&gt;
=== Application de la modification ===&lt;br /&gt;
Au jour d&#039;aujourd&#039;hui (13/12/25) la proxification ne fonctionne plus et il faut apporter une modification dans le fichier &#039;&#039;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&#039;&#039; pour que les bonnes adresses apparaissent !&lt;br /&gt;
En fonction des versions cette modification peut avoir lieu soit ligne &#039;&#039;&#039;1504&#039;&#039;&#039;, soit ligne &#039;&#039;&#039;1554&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Il faut repérer la fonction suivante:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
sub authenticate_and_handle_request {&lt;br /&gt;
    my ($self, $reqstate) = @_;&lt;br /&gt;
&lt;br /&gt;
    my $request = $reqstate-&amp;gt;{request};&lt;br /&gt;
    my $method = $request-&amp;gt;method();&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
C&#039;est un peu plus loin qu&#039;il faut insérer le code :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 ### INSERTION ICI ###&lt;br /&gt;
&lt;br /&gt;
    if ($self-&amp;gt;{spiceproxy}) {&lt;br /&gt;
        my $connect_str = $request-&amp;gt;header(&#039;Host&#039;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il faut modifier l&#039;attribut &#039;&#039;peer_host&#039;&#039; de l&#039;objet &#039;&#039;reqstate&#039;&#039; si l&#039;une des deux entêtes est présente :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if ($request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
} elsif ($request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Double IPv4 ou préfixe IPv6 ===&lt;br /&gt;
Après redémarrage, cela permet de voir l&#039;adresse du client dans les logs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/ext-all.js?ver=7.0.0 HTTP/1.1&amp;quot; 200 683505&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/js/u2f-api.js HTTP/1.1&amp;quot; 200 4898&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/resources HTTP/1.1&amp;quot; 200 1226&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/tasks HTTP/1.1&amp;quot; 200 1090&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /proxmoxlib.js?ver=v5.0.4-t1754316706 HTTP/1.1&amp;quot; 200 157086&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/theme-crisp/resources/theme-crisp-all_1.css HTTP/1.1&amp;quot; 200 32919&lt;br /&gt;
::ffff:192.168.20.22 - root@pam [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/nodes/labo/lxc/100/status/current HTTP/1.1&amp;quot; 200 523&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il nous reste un peu de nettoyage à faire, dans certains cas :&lt;br /&gt;
* l&#039;adresse apparaît non pas une fois mais deux, séparées par une virgule&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
37.167.182.207, 37.167.182.207&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* l&#039;adresse IPv4 (32 bits) est affichée dans sa représentation IPv6 (128 bits), avec le préfixe &#039;&#039;::ffff:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
::ffff:192.168.20.22&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On a deux possibilités pour faire le nettoyage :&lt;br /&gt;
*Soit on ajoute les lignes suivantes dans &#039;&#039;AnyEvent.pm&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if (index($reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
   # Remove trailing ip &lt;br /&gt;
   my @fields = split /,/, $reqstate-&amp;gt;{peer_host};&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $fields[0];&lt;br /&gt;
}&lt;br /&gt;
if($reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
   # Remove IPv6 subnet for IPv4&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $1;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*Soit on modifie le filtre /etc/fail2ban/filter.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=.*:?&amp;lt;HOST&amp;gt;,? user=.* msg=.*&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Automatisation ===&lt;br /&gt;
On peut automatiser le processus précédent avec le script suivant, que l&#039;on peut créer dans /root/remoteip_fix.sh :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=bash&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
ANYEVENT_PATH=&amp;quot;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&amp;quot;&lt;br /&gt;
ANYEVENT_REGEX=&#039;$self-&amp;gt;{spiceproxy}&#039;&lt;br /&gt;
TMP_FILE=&amp;quot;/tmp/AnyEvent.pm.tmp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if [ ! -f $ANYEVENT_PATH ]; then&lt;br /&gt;
  echo &amp;quot;$ANYEVENT_PATH does not exists !&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
if [ $(grep &#039;### BUGFIX REMOTE_IP FOR FAIL2BAN ###&#039; $ANYEVENT_PATH | wc -l) -eq 1 ]; then&lt;br /&gt;
  echo &amp;quot;AnyEvent.pm already patched !&amp;quot;&lt;br /&gt;
  exit 0&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
LINE_NUMBER_TOP=$(nl -ba $ANYEVENT_PATH | grep $ANYEVENT_REGEX | head -n 1 | awk -F &#039; &#039; &#039;{print $1}&#039;)&lt;br /&gt;
let LINE_NUMBER_TOP-=1&lt;br /&gt;
&lt;br /&gt;
if [ $LINE_NUMBER_TOP -lt 0 ]; then&lt;br /&gt;
  echo &amp;quot;Did not find the $ANYEVENT_REGEX expr in $ANYEVENT_PATH&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
echo -n &amp;quot;Applying bugfix: &amp;quot;&lt;br /&gt;
trap &amp;quot;rm -f $TMP_FILE&amp;quot; 0 1 2 5 13 15&lt;br /&gt;
head -n $LINE_NUMBER_TOP $ANYEVENT_PATH &amp;gt;$TMP_FILE&lt;br /&gt;
cat &amp;gt;&amp;gt;$TMP_FILE &amp;lt;&amp;lt;EOF&lt;br /&gt;
### BUGFIX REMOTE_IP FOR FAIL2BAN ###&lt;br /&gt;
    if (\$request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
    } elsif (\$request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
    }&lt;br /&gt;
    if (index(\$reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
        my @fields = split /,/, \$reqstate-&amp;gt;{peer_host};&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$fields[0];&lt;br /&gt;
    }&lt;br /&gt;
    if(\$reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
        # Remove IPv6 subnet for IPv4&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$1;&lt;br /&gt;
    }&lt;br /&gt;
#####################################&lt;br /&gt;
EOF&lt;br /&gt;
echo &amp;quot;$ANYEVENT_MODIF&amp;quot; &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cp $ANYEVENT_PATH $ANYEVENT_PATH.ori&lt;br /&gt;
LINE_NUMBER_BOTTOM=$(cat $ANYEVENT_PATH | wc -l)&lt;br /&gt;
let LINE_NUMBER_BOTTOM-=LINE_NUMBER_TOP&lt;br /&gt;
tail -n $LINE_NUMBER_BOTTOM $ANYEVENT_PATH &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cat $TMP_FILE &amp;gt;$ANYEVENT_PATH&lt;br /&gt;
rm -f $TMP_FILE&lt;br /&gt;
trap 0&lt;br /&gt;
echo &amp;quot;done.&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à le rendre exécutable et le lancer :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# chmod +x /root/remoteip_fix.sh&lt;br /&gt;
# /root/remoteip_fix.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne faudra pas oublier de redémarrer &#039;&#039;pveproxy&#039;&#039; pour appliquer les changements !&lt;br /&gt;
&lt;br /&gt;
== Comment bannir derrière un reverse-proxy ? ==&lt;br /&gt;
Maintenant que votre Proxmox est derrière un reverse-proxy, inutile de bannir les IP publiques avec iptables sur le serveur Proxmox, la seule IP visible est celle du reverse-proxy (dans cet exemple 192.168.4.100).&lt;br /&gt;
&lt;br /&gt;
La seule machine capable de bannir est le reverse-proxy, il faut donc lui transmettre les IP et nous allons faire ça en trois étapes:&lt;br /&gt;
* la première est de créer une &amp;quot;prison&amp;quot; proxmox sur le fail2ban présent sur le reverse-proxy&lt;br /&gt;
* la deuxième est l&#039;invention d&#039;une API pour fail2ban sur le reverse-proxy&lt;br /&gt;
* la troisième est la modification du comportement de fail2ban pour appeler cette API au lieu de modifier iptables&lt;br /&gt;
&lt;br /&gt;
=== Création d&#039;une prison sur le reverse-proxy ===&lt;br /&gt;
&lt;br /&gt;
Pour bannir nous allons créer une prison spécifique pour le / les serveurs Proxmox que nous allons appeler &#039;&#039;proxmox&#039;&#039; dans le fichier /etc/fail2ban/jail.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[proxmox]&lt;br /&gt;
enabled = true&lt;br /&gt;
port = https,http&lt;br /&gt;
filter = do-nothing&lt;br /&gt;
logpath = /dev/null&lt;br /&gt;
maxretry = 3&lt;br /&gt;
findtime = 1d&lt;br /&gt;
bantime = 1w&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
J&#039;attire votre attention sur les paramètres &#039;&#039;maxretry&#039;&#039;, &#039;&#039;findtime&#039;&#039; et &#039;&#039;bantime&#039;&#039; qui doivent concorder avec ceux du fail2ban de votre Proxmox. S&#039;il sont plus &#039;&#039;court&#039;&#039; sur le reverse-proxy, les IP seront libérées plus tôt à l&#039;inverse, plus long n&#039;est pas gênant, le fail2ban de votre Proxmox les libéreras avant celui du proxy.&lt;br /&gt;
&lt;br /&gt;
Vous avez remarquez le filtre &#039;&#039;do-nothing&#039;&#039; qu&#039;il nous reste à créer dans le fichier &#039;&#039;/etc/fail2ban/filter.d/do-nothing.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
&lt;br /&gt;
failregex = ^&amp;lt;HOST&amp;gt;$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Après redémarrage de fail2ban :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl restart fail2ban&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous devriez voir la prison&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status&lt;br /&gt;
Status&lt;br /&gt;
|- Number of jail:      2&lt;br /&gt;
`- Jail list:   proxmox, sshd&lt;br /&gt;
[root@proxy proxymox]# &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous pouvons maintenant passer à l&#039;API !&lt;br /&gt;
&lt;br /&gt;
=== Invention d&#039;une API pour fail2ban ===&lt;br /&gt;
&lt;br /&gt;
Toujours sur le reverse-proxy nous allons installer PHP pour créer un mini serveur qui répondra au urls suivantes:&lt;br /&gt;
* /ban/&amp;lt;ip&amp;gt; pour bannir&lt;br /&gt;
* /unban/&amp;lt;ip&amp;gt; pour lever le banissement&lt;br /&gt;
&lt;br /&gt;
Commençons par installer PHP:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# dnf -y install php-cli&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un répertoire &amp;quot;f2b-api&amp;quot; dans le dossier &amp;quot;opt&amp;quot; :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# mkdir /opt/f2b-api&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis créer un fichier &#039;&#039;f2b-api.php&#039;&#039; dans ce dossier:&lt;br /&gt;
&amp;lt;source lang=php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
main();&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        # On clean l&#039;uri du / de début&lt;br /&gt;
        $uri = ltrim($_SERVER[&#039;REQUEST_URI&#039;], &#039;/&#039;);&lt;br /&gt;
        # On éclate l&#039;uri en parties (action + ip)&lt;br /&gt;
        $parts = explode(&#039;/&#039;, $uri);&lt;br /&gt;
        # Récupération de l&#039;action dans une variable ou false si vide&lt;br /&gt;
        $action = empty($parts[0]) ? false : $parts[0];&lt;br /&gt;
        # Récupération de l&#039;ip dans une variable ou false si vide&lt;br /&gt;
        $ip = empty($parts[1]) ? false : $parts[1];&lt;br /&gt;
        if(!$action || !$ip){&lt;br /&gt;
                # Si action vide =&amp;gt; 400 Bad request&lt;br /&gt;
                http_response_code(400);&lt;br /&gt;
                die();&lt;br /&gt;
        }&lt;br /&gt;
        if(!in_array($action, [&#039;ban&#039;, &#039;unban&#039;])){&lt;br /&gt;
                # Si action pas dans la liste =&amp;gt; 400 Bad request&lt;br /&gt;
                http_response_code(400);&lt;br /&gt;
                die();&lt;br /&gt;
        }&lt;br /&gt;
        $cmd = &#039;&#039;;&lt;br /&gt;
        if($action == &#039;ban&#039;){&lt;br /&gt;
                $cmd = &#039;fail2ban-client set proxmox banip &#039; . $ip;&lt;br /&gt;
        } else if($action == &#039;unban&#039;){&lt;br /&gt;
                $cmd = &#039;fail2ban-client unban proxmox &#039; . $ip;&lt;br /&gt;
        }&lt;br /&gt;
        shell_exec($cmd);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
[[Fichier:Warning-icon.png|40px]]  Gardez en tête que ce code simpliste n&#039;est en aucun cas sécurisé et ne doit pas être accessible depuis Internet.&lt;br /&gt;
&lt;br /&gt;
Pour démarrer se code en mode serveur il suffit de taper la commande suivante:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# php -S 0.0.0.0:8080 -t /opt/f2b-api /opt/f2b-api/f2b-api.php&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous pouvez tester directement depuis un autre terminal en tapant les commandes:&lt;br /&gt;
* pour bannir :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# curl -X GET http://127.0.0.1:8080/ban/1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* pour dé-bannir :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# curl -X GET http://127.0.0.1:8080/unban/1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Et en vérifiant dans fail2ban:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed: 0&lt;br /&gt;
|  |- Total failed:     0&lt;br /&gt;
|  `- File list:        /dev/null&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned: 1&lt;br /&gt;
   |- Total banned:     10&lt;br /&gt;
   `- Banned IP list:   1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Nous n&#039;allons pas lancer nous même le serveur PHP, nous allons demander à SystemD de le faire et pour cela nous allons créer le fichier &#039;&#039;/opt/f2b-api/f2b-api.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=fail2ban API Server&lt;br /&gt;
After=network-online.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
UMask=007&lt;br /&gt;
ExecStart=php -S 0.0.0.0:8080 -t /opt/f2b-api /opt/f2b-api/f2b-api.php&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faut maintenant demander à SystemD de s&#039;occuper de notre service:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl link /opt/f2b-api/f2b-api.service&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Et de le lancer au démarrage du reverse-proxy:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl enable f2b-api --now&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous pouvons maintenant nous déplacer sur le serveur Proxmox pour modifier fail2ban !&lt;br /&gt;
&lt;br /&gt;
=== Modification des actions fail2ban ===&lt;br /&gt;
Sur le serveur Proxmox nous allons débrayer le comportement de base de fail2ban qui est de modifier iptables. pour cela nous alons créer le fichier &#039;&#039;/etc/fail2ban/action.d/f2b-api.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
actionstart =&lt;br /&gt;
actionstop =&lt;br /&gt;
actioncheck =&lt;br /&gt;
actionban = curl -X GET 192.168.4.100:8080/ban/&amp;lt;ip&amp;gt;&lt;br /&gt;
actionunban = curl -X GET 192.168.4.100:8080/unban/&amp;lt;ip&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Veuillez noter que:&lt;br /&gt;
* même si elles sont vide, les lignes &#039;&#039;actionstart&#039;&#039;, &#039;&#039;actionstop&#039;&#039; et &#039;&#039;actioncheck&#039;&#039; sont obligatoires !&lt;br /&gt;
* l&#039;adresse &#039;&#039;192.168.4.100&#039;&#039; doit être remplcée par celle de votre reverse-proxy&lt;br /&gt;
* &amp;lt;ip&amp;gt; est l&#039;expression utilisée par fail2ban et elle sera remplacée par l&#039;IP à bannir &lt;br /&gt;
&lt;br /&gt;
Pour ce fichier d&#039;action soit pris en compte, il faut modifier le fichier &#039;&#039;/etc/fail2ban/jail.d/proxmox.conf&#039;&#039; pour y ajouter:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
banaction = f2b-api&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne vous reste plus qu&#039;a redémarrer le service fai2ban sur le serveur Proxmox:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl restart fail2ban&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Et vous pouvez tester les commandes suivantes:&lt;br /&gt;
* pour bannir&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client set proxmox banip 1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* pour dé-bannir:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client unban proxmox 1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Et vérifier sur le reverse-proxy que les modification sont bien prises en compte:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed: 0&lt;br /&gt;
|  |- Total failed:     0&lt;br /&gt;
|  `- File list:        /dev/null&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned: 1&lt;br /&gt;
   |- Total banned:     10&lt;br /&gt;
   `- Banned IP list:   1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4423</id>
		<title>Proxmox fail2ban</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4423"/>
		<updated>2026-07-13T09:41:48Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Problème lié à la proxyfication */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
Proxmox utilise une interface web d&#039;administration qui utilise le port TCP 8006 et c&#039;est un vecteur possible d&#039;attaque par force brut. Nous allons donc &#039;&#039;dresser&#039;&#039; fail2ban pour agir en cas d&#039;attaque !&lt;br /&gt;
&lt;br /&gt;
Proxmox utilise Debian, nous allons principalement reproduire les étapes décrites dans le tutoriel de [[Sécuriser_un_service_avec_Fail2ban| Fail2ban pour Rocky]] et adapter à Debian.&lt;br /&gt;
&lt;br /&gt;
Avant d&#039;aller plus loin, assurez-vous d&#039;avoir correctement installé et configuré [[proxmox_iptables |iptables sur Proxmox]]&lt;br /&gt;
&lt;br /&gt;
= Installation =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt -y install fail2ban&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Configuration =&lt;br /&gt;
Tout d&#039;abord il faut copier le fichier &#039;&#039;/etc/fail2ban/jail.conf&#039;&#039; en &#039;&#039;/etc/fail2ban/jail.local&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dans ce fichier, on va s&#039;intéresser aux variables suivantes:&lt;br /&gt;
*ignoreip : correspond à la suite d&#039;adresses IP qui ne se feront jamais bannir;&lt;br /&gt;
*maxretry : correspond au nombre d&#039;essais;&lt;br /&gt;
*findtime : correspond à la période pendant laquelle les essais vont incrémenter maxretry;&lt;br /&gt;
*bantime  : correspond au temps où l&#039;adresse IP ne peut pas se connecter.&lt;br /&gt;
&lt;br /&gt;
= Configuration de base =&lt;br /&gt;
== Choix de la punition ==&lt;br /&gt;
Il faut choisir quelque chose de cohérent (une punition suffisante) pour ne pas permettre de se faire cracker son mot de passe:&lt;br /&gt;
*maxretry = 3&lt;br /&gt;
*findtime = 86400 (correspond à 1 journée)&lt;br /&gt;
*bantime = 604800 (correspond à 1 semaine)&lt;br /&gt;
&lt;br /&gt;
Cela signifie que si une adresse IP se trompe 3 fois en 1 journée (86400s) elle se fait bannir pendant 1 semaine (604800s).&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul permet de trouver le nombre maximal de tentatives durant une année:&lt;br /&gt;
&lt;br /&gt;
365 jours / 7 jours par semaine * 3 tentatives = 156 essais, ce qui reste raisonnable. &lt;br /&gt;
&lt;br /&gt;
Si le pirate possède un [http://fr.wikipedia.org/wiki/Botnet botnet], il faut bien sûr multiplier ce nombre par le nombre de machines dans le botnet...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Attention : fail2ban parcours les logs de connexion pour connaître le numéro de la tentative, ce qui a pour conséquence, si le &#039;&#039;findtime&#039;&#039; est grand, de prendre un certain temps...&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Jail pour SSH ==&lt;br /&gt;
Il suffit d&#039;ajouter la ligne &#039;&#039;enabled=true&#039;&#039; dans la section à activer !&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[sshd]&lt;br /&gt;
&lt;br /&gt;
# To use more aggressive sshd modes set filter parameter &amp;quot;mode&amp;quot; in jail.local:&lt;br /&gt;
# normal (default), ddos, extra or aggressive (combines all).&lt;br /&gt;
# See &amp;quot;tests/files/logs/sshd&amp;quot; or &amp;quot;filter.d/sshd.conf&amp;quot; for usage example and details.&lt;br /&gt;
#mode   = normal&lt;br /&gt;
enabled = true&lt;br /&gt;
port    = ssh&lt;br /&gt;
logpath = %(sshd_log)s&lt;br /&gt;
backend = %(sshd_backend)s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Configuration spécifique =&lt;br /&gt;
== Jail pour PVEPROXY ==&lt;br /&gt;
Pveproxy écoute sur le port 8006 et ne fonctionne pas exactement comme un serveur [[HTTPD | Apache httpd]] qui mettrait ces logs dans le fichier &#039;&#039;error_log&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Nous allons mettre cette configuration spécifique dans le fichier &#039;&#039;/etc/fail2ban/jail.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[proxmox]&lt;br /&gt;
enabled = true&lt;br /&gt;
port = https,http,8006&lt;br /&gt;
filter = proxmox&lt;br /&gt;
backend = systemd&lt;br /&gt;
maxretry = 5&lt;br /&gt;
findtime = 1d&lt;br /&gt;
bantime = 1w&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le backend utilisé est systemd, exactement comme si vous utilisiez la commande :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Filtre pour PVEPROXY ==&lt;br /&gt;
Il ne nous reste plus qu&#039;à spécifier le filtre &#039;&#039;proxmox&#039;&#039; dans le fichier &#039;&#039;/etc/fail2ban/filter.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=&amp;lt;HOST&amp;gt; user=.* msg=.*&lt;br /&gt;
ignoreregex =&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Tests =&lt;br /&gt;
Il faut maintenant tester le filtre et pour ça on peut utiliser un partage de connexion et réaliser le nombre d&#039;échecs spécifié par la directive &amp;quot;maxretry&amp;quot; (ici 3) :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed:	0&lt;br /&gt;
|  |- Total failed:	3&lt;br /&gt;
|  `- Journal matches:	_SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned:	1&lt;br /&gt;
   |- Total banned:	1&lt;br /&gt;
   `- Banned IP list:	37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On voit bien l&#039;IP 37.167.23.159 qui est bannie !&lt;br /&gt;
N&#039;oubliez pas de l&#039;ajouter à &#039;&#039;ignoreip&#039;&#039; dans le fichier &#039;&#039;jails.local&#039;&#039; ou de faire &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client unban 37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Démarrage et enregistrement dans le chargeur de démarrage =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start fail2ban.service&lt;br /&gt;
# systemctl enable fail2ban.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Vous pouvez maintenant démarrer fail2ban&lt;br /&gt;
&lt;br /&gt;
= Proxification=&lt;br /&gt;
Lorsque votre serveur Proxmox se trouve derrière un reverse-proxy (Apache, Nginx, Traefik, ...), au niveau 3 OSI, l&#039;adresse IP du client est remplacée par celle du proxy et le serveur utilise l&#039;entêtes &#039;&#039;X-Forwarded-For&#039;&#039; ou &#039;&#039;X-Real-IP&#039;&#039; pour transporter l&#039;adresse du client &lt;br /&gt;
[[Fichier:Reverse proxy proxmox.png|700px|centré]]&lt;br /&gt;
Dans cette exemple:&lt;br /&gt;
* le nom de domaine utilisé est &#039;&#039;&#039;pve.tala-informatique.fr&#039;&#039;&#039;&lt;br /&gt;
* l&#039;adresse du proxy est &#039;&#039;&#039;192.168.4.100&#039;&#039;&#039;&lt;br /&gt;
* l&#039;adresse du serveur Proxmox est &#039;&#039;&#039;192.168.4.1&#039;&#039;&#039;&lt;br /&gt;
== Configuration du reverse-proxy ==&lt;br /&gt;
Sur votre reverse-proxy Apache, vous devriez avoir une configuration qui ressemble à ça:&lt;br /&gt;
&amp;lt;source lang=apache&amp;gt;&lt;br /&gt;
MDomain pve.tala-informatique.fr&lt;br /&gt;
&lt;br /&gt;
&amp;lt;VirtualHost *:80&amp;gt;&lt;br /&gt;
    ServerName pve.tala-informatique.fr&lt;br /&gt;
    Redirect / https://pve.tala-informatique.fr/&lt;br /&gt;
&amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;VirtualHost *:443&amp;gt;&lt;br /&gt;
    ServerName pve.tala-informatique.fr&lt;br /&gt;
    &lt;br /&gt;
    SSLEngine on&lt;br /&gt;
    SSLProxyEngine on&lt;br /&gt;
    SSLProxyVerify none &lt;br /&gt;
    SSLProxyCheckPeerCN off&lt;br /&gt;
    SSLProxyCheckPeerName off&lt;br /&gt;
    &lt;br /&gt;
    ProxyRequests off&lt;br /&gt;
    ProxyPreserveHost On&lt;br /&gt;
    &lt;br /&gt;
    RewriteEngine on&lt;br /&gt;
    RewriteCond %{HTTP:Connection} Upgrade [NC]&lt;br /&gt;
    RewriteCond %{HTTP:Upgrade} websocket [NC]&lt;br /&gt;
    RewriteRule ^/?(.*) wss://192.168.4.1:8006/$1 [P,L]&lt;br /&gt;
&lt;br /&gt;
    ProxyPass / https://192.168.4.1:8006/ flushpackets=On connectiontimeout=300 timeout=300&lt;br /&gt;
    ProxyPassReverse / https://192.168.4.1:8006/&lt;br /&gt;
    ProxyTimeout     600&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La première ligne renvoie à la configuration de mod_md abordée dans cette [[Httpd_certificate_security#Let&#039;s_Encrypt |article]] et permet l&#039;obtention du certificat SSL auprès de [https://letsencrypt.org Let&#039;s encrypt]&lt;br /&gt;
&amp;lt;source lang=apache&amp;gt;&lt;br /&gt;
MDomain pve.tala-informatique.fr&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le bloc suivant permet de [[Httpd_redirect_reverse-proxy_mod-rewrite#http_→_https | renvoyer les utilisateurs]] se présentant sur le port 80 vers le port 443&lt;br /&gt;
&amp;lt;source lang=apache&amp;gt;&lt;br /&gt;
&amp;lt;VirtualHost *:80&amp;gt;&lt;br /&gt;
    ServerName pve.tala-informatique.fr&lt;br /&gt;
    Redirect / https://pve.tala-informatique.fr/&lt;br /&gt;
&amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dans le bloc &#039;&#039;443&#039;&#039;, on est obligé de désactiver les vérifications SSL parce que le certificat du serveur Proxmox est autosigné (donc pas de cadenas vert), ce qui pousse Apache à bloquer la connexion si on ne désactive pas ces vérifications&lt;br /&gt;
&amp;lt;source lang=apache&amp;gt;&lt;br /&gt;
SSLProxyVerify none &lt;br /&gt;
SSLProxyCheckPeerCN off&lt;br /&gt;
SSLProxyCheckPeerName off&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
La réécriture d&#039;url doit être configuré pour prendre en compte les &#039;&#039;websockets sécurisées&#039;&#039; (wss) utilisées pour l&#039;affichage de l&#039;écran des machine ou conteneurs avec &#039;&#039;xterm.js&#039;&#039;&lt;br /&gt;
&amp;lt;source lang=apache&amp;gt;&lt;br /&gt;
RewriteEngine on&lt;br /&gt;
RewriteCond %{HTTP:Connection} Upgrade [NC]&lt;br /&gt;
RewriteCond %{HTTP:Upgrade} websocket [NC]&lt;br /&gt;
RewriteRule ^/?(.*) wss://192.168.4.1:8006/$1 [P,L]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Enfin on redirige les requêtes vers le serveur Proxmox en n&#039;oubliant pas de préciser le port 8006&lt;br /&gt;
&amp;lt;source lang=apache&amp;gt;&lt;br /&gt;
ProxyPass / https://192.168.4.1:8006/ flushpackets=On connectiontimeout=300 timeout=300&lt;br /&gt;
ProxyPassReverse / https://192.168.4.1:8006/&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
== Problème lié à la proxyfication ==&lt;br /&gt;
Le problème est que la seule adresse que fail2ban va voir apparaître dans les logs est celle du reverse-proxy (&#039;&#039;192.168.4.100&#039;&#039;) :&lt;br /&gt;
[[Fichier:Reverse proxy ip logs.png|600px|centré]]&lt;br /&gt;
Même si le filtre &#039;&#039;fail2ban&#039;&#039; est configuré pour utiliser la commande &#039;&#039;journactl&#039;&#039; sur le démon &#039;&#039;pvedaemon&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
les adresses viennent de pveproxy qui journalise tout dans &#039;&#039;/var/log/pveproxy/access.log&#039;&#039; et &#039;&#039;pvedaemon&#039;&#039; ne journalise que les échecs d&#039;authentification. &lt;br /&gt;
Il est donc plus simple de faire un &#039;&#039;tail&#039;&#039; ou un &#039;&#039;cat&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Que d&#039;utiliser &#039;&#039;journalctl&#039;&#039; pour voir les IPs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
Dec 14 10:43:01 labo unix_chkpwd[1326506]: password check failed for user (root)&lt;br /&gt;
Dec 14 10:43:01 labo IPCC.xs[1320783]: pam_unix(proxmox-ve-auth:auth): authentication failure; logname= uid=0 euid=0 tty= ruser= rhost=37.167.23.159  user=root&lt;br /&gt;
Dec 14 10:43:03 labo pvedaemon[1320783]: authentication failure; rhost=192.168.4.100 user=root@pam msg=Authentication failure&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Configuration de pveproxy ==&lt;br /&gt;
Si on veut voir l&#039;adresse du client, il faut dire au [https://fr.wikipedia.org/wiki/Daemon_(informatique)| démon] &#039;&#039;pveproxy&#039;&#039; d&#039;utiliser l&#039;une des deux entêtes précédentes ainsi que préciser l&#039;adresse du proxy. &lt;br /&gt;
&lt;br /&gt;
Préciser l&#039;adresse du proxy est essentiel pour que &#039;&#039;pveproxy&#039;&#039; n&#039;accepte de lire l&#039;adresse du client présente dans l&#039;entête &#039;&#039;&#039;uniquement&#039;&#039;&#039; si cela provient du proxy, qui est une machine de confiance. Le cas contraire, tout le monde pourrait ajouter une adresse IP dans l&#039;entête pour la faire bannir...&lt;br /&gt;
&lt;br /&gt;
Nous allons créer le fichier &#039;&#039;/etc/default/pveproxy&#039;&#039; avec les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Forwarded-For&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Real-IP&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_ALLOW_FROM=&amp;quot;192.168.4.100&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il faut maintenant redémarrer &#039;&#039;pveproxy&#039;&#039; pour que les changements s&#039;appliquent. Si vous êtes connecté via l&#039;interface web, cela va vous déconnecter, le temps que le démon redémarre, il faudra ensuite certainement rafraîchir la page web.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl restart pveproxy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à vérifier dans les logs si les bonnes adresses s&#039;affichent:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Si jamais ce n&#039;est pas le cas, poursuivez avec la modification du fichier &#039;&#039;AnyEvent.pm&#039;&#039;&lt;br /&gt;
== Modification de AnyEvent.pm ==&lt;br /&gt;
=== Application de la modification ===&lt;br /&gt;
Au jour d&#039;aujourd&#039;hui (13/12/25) la proxification ne fonctionne plus et il faut apporter une modification dans le fichier &#039;&#039;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&#039;&#039; pour que les bonnes adresses apparaissent !&lt;br /&gt;
En fonction des versions cette modification peut avoir lieu soit ligne &#039;&#039;&#039;1504&#039;&#039;&#039;, soit ligne &#039;&#039;&#039;1554&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Il faut repérer la fonction suivante:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
sub authenticate_and_handle_request {&lt;br /&gt;
    my ($self, $reqstate) = @_;&lt;br /&gt;
&lt;br /&gt;
    my $request = $reqstate-&amp;gt;{request};&lt;br /&gt;
    my $method = $request-&amp;gt;method();&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
C&#039;est un peu plus loin qu&#039;il faut insérer le code :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 ### INSERTION ICI ###&lt;br /&gt;
&lt;br /&gt;
    if ($self-&amp;gt;{spiceproxy}) {&lt;br /&gt;
        my $connect_str = $request-&amp;gt;header(&#039;Host&#039;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il faut modifier l&#039;attribut &#039;&#039;peer_host&#039;&#039; de l&#039;objet &#039;&#039;reqstate&#039;&#039; si l&#039;une des deux entêtes est présente :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if ($request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
} elsif ($request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Double IPv4 ou préfixe IPv6 ===&lt;br /&gt;
Après redémarrage, cela permet de voir l&#039;adresse du client dans les logs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/ext-all.js?ver=7.0.0 HTTP/1.1&amp;quot; 200 683505&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/js/u2f-api.js HTTP/1.1&amp;quot; 200 4898&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/resources HTTP/1.1&amp;quot; 200 1226&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/tasks HTTP/1.1&amp;quot; 200 1090&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /proxmoxlib.js?ver=v5.0.4-t1754316706 HTTP/1.1&amp;quot; 200 157086&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/theme-crisp/resources/theme-crisp-all_1.css HTTP/1.1&amp;quot; 200 32919&lt;br /&gt;
::ffff:192.168.20.22 - root@pam [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/nodes/labo/lxc/100/status/current HTTP/1.1&amp;quot; 200 523&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il nous reste un peu de nettoyage à faire, dans certains cas :&lt;br /&gt;
* l&#039;adresse apparaît non pas une fois mais deux, séparées par une virgule&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
37.167.182.207, 37.167.182.207&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* l&#039;adresse IPv4 (32 bits) est affichée dans sa représentation IPv6 (128 bits), avec le préfixe &#039;&#039;::ffff:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
::ffff:192.168.20.22&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On a deux possibilités pour faire le nettoyage :&lt;br /&gt;
*Soit on ajoute les lignes suivantes dans &#039;&#039;AnyEvent.pm&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if (index($reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
   # Remove trailing ip &lt;br /&gt;
   my @fields = split /,/, $reqstate-&amp;gt;{peer_host};&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $fields[0];&lt;br /&gt;
}&lt;br /&gt;
if($reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
   # Remove IPv6 subnet for IPv4&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $1;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*Soit on modifie le filtre /etc/fail2ban/filter.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=.*:?&amp;lt;HOST&amp;gt;,? user=.* msg=.*&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Automatisation ===&lt;br /&gt;
On peut automatiser le processus précédent avec le script suivant, que l&#039;on peut créer dans /root/remoteip_fix.sh :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=bash&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
ANYEVENT_PATH=&amp;quot;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&amp;quot;&lt;br /&gt;
ANYEVENT_REGEX=&#039;$self-&amp;gt;{spiceproxy}&#039;&lt;br /&gt;
TMP_FILE=&amp;quot;/tmp/AnyEvent.pm.tmp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if [ ! -f $ANYEVENT_PATH ]; then&lt;br /&gt;
  echo &amp;quot;$ANYEVENT_PATH does not exists !&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
if [ $(grep &#039;### BUGFIX REMOTE_IP FOR FAIL2BAN ###&#039; $ANYEVENT_PATH | wc -l) -eq 1 ]; then&lt;br /&gt;
  echo &amp;quot;AnyEvent.pm already patched !&amp;quot;&lt;br /&gt;
  exit 0&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
LINE_NUMBER_TOP=$(nl -ba $ANYEVENT_PATH | grep $ANYEVENT_REGEX | head -n 1 | awk -F &#039; &#039; &#039;{print $1}&#039;)&lt;br /&gt;
let LINE_NUMBER_TOP-=1&lt;br /&gt;
&lt;br /&gt;
if [ $LINE_NUMBER_TOP -lt 0 ]; then&lt;br /&gt;
  echo &amp;quot;Did not find the $ANYEVENT_REGEX expr in $ANYEVENT_PATH&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
echo -n &amp;quot;Applying bugfix: &amp;quot;&lt;br /&gt;
trap &amp;quot;rm -f $TMP_FILE&amp;quot; 0 1 2 5 13 15&lt;br /&gt;
head -n $LINE_NUMBER_TOP $ANYEVENT_PATH &amp;gt;$TMP_FILE&lt;br /&gt;
cat &amp;gt;&amp;gt;$TMP_FILE &amp;lt;&amp;lt;EOF&lt;br /&gt;
### BUGFIX REMOTE_IP FOR FAIL2BAN ###&lt;br /&gt;
    if (\$request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
    } elsif (\$request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
    }&lt;br /&gt;
    if (index(\$reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
        my @fields = split /,/, \$reqstate-&amp;gt;{peer_host};&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$fields[0];&lt;br /&gt;
    }&lt;br /&gt;
    if(\$reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
        # Remove IPv6 subnet for IPv4&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$1;&lt;br /&gt;
    }&lt;br /&gt;
#####################################&lt;br /&gt;
EOF&lt;br /&gt;
echo &amp;quot;$ANYEVENT_MODIF&amp;quot; &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cp $ANYEVENT_PATH $ANYEVENT_PATH.ori&lt;br /&gt;
LINE_NUMBER_BOTTOM=$(cat $ANYEVENT_PATH | wc -l)&lt;br /&gt;
let LINE_NUMBER_BOTTOM-=LINE_NUMBER_TOP&lt;br /&gt;
tail -n $LINE_NUMBER_BOTTOM $ANYEVENT_PATH &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cat $TMP_FILE &amp;gt;$ANYEVENT_PATH&lt;br /&gt;
rm -f $TMP_FILE&lt;br /&gt;
trap 0&lt;br /&gt;
echo &amp;quot;done.&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à le rendre exécutable et le lancer :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# chmod +x /root/remoteip_fix.sh&lt;br /&gt;
# /root/remoteip_fix.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne faudra pas oublier de redémarrer &#039;&#039;pveproxy&#039;&#039; pour appliquer les changements !&lt;br /&gt;
&lt;br /&gt;
== Comment bannir derrière un reverse-proxy ? ==&lt;br /&gt;
Maintenant que votre Proxmox est derrière un reverse-proxy, inutile de bannir les IP publiques avec iptables sur le serveur Proxmox, la seule IP visible est celle du reverse-proxy (dans cet exemple 192.168.4.100).&lt;br /&gt;
&lt;br /&gt;
La seule machine capable capable de bannir est le reverse-proxy, il faut donc lui transmettre les IP et nous allons faire ça en trois étapes:&lt;br /&gt;
* la première est de créer une &amp;quot;prison&amp;quot; proxmox sur le fail2ban présent sur le reverse-proxy&lt;br /&gt;
* la deuxième est l&#039;invention d&#039;une API pour fail2ban sur le reverse-proxy&lt;br /&gt;
* la troisième est la modification du comportement de fail2ban pour appeler cette API au lieu de modifier iptables&lt;br /&gt;
&lt;br /&gt;
=== Création d&#039;une prison sur le reverse-proxy ===&lt;br /&gt;
&lt;br /&gt;
Pour bannir nous allons créer une prison spécifique pour le / les serveurs Proxmox que nous allons appeler &#039;&#039;proxmox&#039;&#039; dans le fichier /etc/fail2ban/jail.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[proxmox]&lt;br /&gt;
enabled = true&lt;br /&gt;
port = https,http&lt;br /&gt;
filter = do-nothing&lt;br /&gt;
logpath = /dev/null&lt;br /&gt;
maxretry = 3&lt;br /&gt;
findtime = 1d&lt;br /&gt;
bantime = 1w&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
J&#039;attire votre attention sur les paramètres &#039;&#039;maxretry&#039;&#039;, &#039;&#039;findtime&#039;&#039; et &#039;&#039;bantime&#039;&#039; qui doivent concorder avec ceux du fail2ban de votre Proxmox. S&#039;il sont plus &#039;&#039;court&#039;&#039; sur le reverse-proxy, les IP seront libérées plus tôt à l&#039;inverse, plus long n&#039;est pas gênant, le fail2ban de votre Proxmox les libéreras avant celui du proxy.&lt;br /&gt;
&lt;br /&gt;
Vous avez remarquez le filtre &#039;&#039;do-nothing&#039;&#039; qu&#039;il nous reste à créer dans le fichier &#039;&#039;/etc/fail2ban/filter.d/do-nothing.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
&lt;br /&gt;
failregex = ^&amp;lt;HOST&amp;gt;$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Après redémarrage de fail2ban :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl restart fail2ban&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous devriez voir la prison&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status&lt;br /&gt;
Status&lt;br /&gt;
|- Number of jail:      2&lt;br /&gt;
`- Jail list:   proxmox, sshd&lt;br /&gt;
[root@proxy proxymox]# &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous pouvons maintenant passer à l&#039;API !&lt;br /&gt;
&lt;br /&gt;
=== Invention d&#039;une API pour fail2ban ===&lt;br /&gt;
&lt;br /&gt;
Toujours sur le reverse-proxy nous allons installer PHP pour créer un mini serveur qui répondra au urls suivantes:&lt;br /&gt;
* /ban/&amp;lt;ip&amp;gt; pour bannir&lt;br /&gt;
* /unban/&amp;lt;ip&amp;gt; pour lever le banissement&lt;br /&gt;
&lt;br /&gt;
Commençons par installer PHP:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# dnf -y install php-cli&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un répertoire &amp;quot;f2b-api&amp;quot; dans le dossier &amp;quot;opt&amp;quot; :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# mkdir /opt/f2b-api&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis créer un fichier &#039;&#039;f2b-api.php&#039;&#039; dans ce dossier:&lt;br /&gt;
&amp;lt;source lang=php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
main();&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        # On clean l&#039;uri du / de début&lt;br /&gt;
        $uri = ltrim($_SERVER[&#039;REQUEST_URI&#039;], &#039;/&#039;);&lt;br /&gt;
        # On éclate l&#039;uri en parties (action + ip)&lt;br /&gt;
        $parts = explode(&#039;/&#039;, $uri);&lt;br /&gt;
        # Récupération de l&#039;action dans une variable ou false si vide&lt;br /&gt;
        $action = empty($parts[0]) ? false : $parts[0];&lt;br /&gt;
        # Récupération de l&#039;ip dans une variable ou false si vide&lt;br /&gt;
        $ip = empty($parts[1]) ? false : $parts[1];&lt;br /&gt;
        if(!$action || !$ip){&lt;br /&gt;
                # Si action vide =&amp;gt; 400 Bad request&lt;br /&gt;
                http_response_code(400);&lt;br /&gt;
                die();&lt;br /&gt;
        }&lt;br /&gt;
        if(!in_array($action, [&#039;ban&#039;, &#039;unban&#039;])){&lt;br /&gt;
                # Si action pas dans la liste =&amp;gt; 400 Bad request&lt;br /&gt;
                http_response_code(400);&lt;br /&gt;
                die();&lt;br /&gt;
        }&lt;br /&gt;
        $cmd = &#039;&#039;;&lt;br /&gt;
        if($action == &#039;ban&#039;){&lt;br /&gt;
                $cmd = &#039;fail2ban-client set proxmox banip &#039; . $ip;&lt;br /&gt;
        } else if($action == &#039;unban&#039;){&lt;br /&gt;
                $cmd = &#039;fail2ban-client unban proxmox &#039; . $ip;&lt;br /&gt;
        }&lt;br /&gt;
        shell_exec($cmd);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
[[Fichier:Warning-icon.png|40px]]  Gardez en tête que ce code simpliste n&#039;est en aucun cas sécurisé et ne doit pas être accessible depuis Internet.&lt;br /&gt;
&lt;br /&gt;
Pour démarrer se code en mode serveur il suffit de taper la commande suivante:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# php -S 0.0.0.0:8080 -t /opt/f2b-api /opt/f2b-api/f2b-api.php&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous pouvez tester directement depuis un autre terminal en tapant les commandes:&lt;br /&gt;
* pour bannir :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# curl -X GET http://127.0.0.1:8080/ban/1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* pour dé-bannir :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# curl -X GET http://127.0.0.1:8080/unban/1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Et en vérifiant dans fail2ban:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed: 0&lt;br /&gt;
|  |- Total failed:     0&lt;br /&gt;
|  `- File list:        /dev/null&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned: 1&lt;br /&gt;
   |- Total banned:     10&lt;br /&gt;
   `- Banned IP list:   1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Nous n&#039;allons pas lancer nous même le serveur PHP, nous allons demander à SystemD de le faire et pour cela nous allons créer le fichier &#039;&#039;/opt/f2b-api/f2b-api.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=fail2ban API Server&lt;br /&gt;
After=network-online.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
UMask=007&lt;br /&gt;
ExecStart=php -S 0.0.0.0:8080 -t /opt/f2b-api /opt/f2b-api/f2b-api.php&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faut maintenant demander à SystemD de s&#039;occuper de notre service:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl link /opt/f2b-api/f2b-api.service&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Et de le lancer au démarrage du reverse-proxy:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl enable f2b-api --now&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous pouvons maintenant nous déplacer sur le serveur Proxmox pour modifier fail2ban !&lt;br /&gt;
&lt;br /&gt;
=== Modification des actions fail2ban ===&lt;br /&gt;
Sur le serveur Proxmox nous allons débrayer le comportement de base de fail2ban qui est de modifier iptables. pour cela nous alons créer le fichier &#039;&#039;/etc/fail2ban/action.d/f2b-api.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
actionstart =&lt;br /&gt;
actionstop =&lt;br /&gt;
actioncheck =&lt;br /&gt;
actionban = curl -X GET 192.168.4.100:8080/ban/&amp;lt;ip&amp;gt;&lt;br /&gt;
actionunban = curl -X GET 192.168.4.100:8080/unban/&amp;lt;ip&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Veuillez noter que:&lt;br /&gt;
* même si elles sont vide, les lignes &#039;&#039;actionstart&#039;&#039;, &#039;&#039;actionstop&#039;&#039; et &#039;&#039;actioncheck&#039;&#039; sont obligatoires !&lt;br /&gt;
* l&#039;adresse &#039;&#039;192.168.4.100&#039;&#039; doit être remplcée par celle de votre reverse-proxy&lt;br /&gt;
* &amp;lt;ip&amp;gt; est l&#039;expression utilisée par fail2ban et elle sera remplacée par l&#039;IP à bannir &lt;br /&gt;
&lt;br /&gt;
Pour ce fichier d&#039;action soit pris en compte, il faut modifier le fichier &#039;&#039;/etc/fail2ban/jail.d/proxmox.conf&#039;&#039; pour y ajouter:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
banaction = f2b-api&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne vous reste plus qu&#039;a redémarrer le service fai2ban sur le serveur Proxmox:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl restart fail2ban&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Et vous pouvez tester les commandes suivantes:&lt;br /&gt;
* pour bannir&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client set proxmox banip 1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* pour dé-bannir:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client unban proxmox 1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Et vérifier sur le reverse-proxy que les modification sont bien prises en compte:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed: 0&lt;br /&gt;
|  |- Total failed:     0&lt;br /&gt;
|  `- File list:        /dev/null&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned: 1&lt;br /&gt;
   |- Total banned:     10&lt;br /&gt;
   `- Banned IP list:   1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4422</id>
		<title>Proxmox fail2ban</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4422"/>
		<updated>2026-07-13T09:41:15Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Configuration du reverse-proxy */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
Proxmox utilise une interface web d&#039;administration qui utilise le port TCP 8006 et c&#039;est un vecteur possible d&#039;attaque par force brut. Nous allons donc &#039;&#039;dresser&#039;&#039; fail2ban pour agir en cas d&#039;attaque !&lt;br /&gt;
&lt;br /&gt;
Proxmox utilise Debian, nous allons principalement reproduire les étapes décrites dans le tutoriel de [[Sécuriser_un_service_avec_Fail2ban| Fail2ban pour Rocky]] et adapter à Debian.&lt;br /&gt;
&lt;br /&gt;
Avant d&#039;aller plus loin, assurez-vous d&#039;avoir correctement installé et configuré [[proxmox_iptables |iptables sur Proxmox]]&lt;br /&gt;
&lt;br /&gt;
= Installation =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt -y install fail2ban&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Configuration =&lt;br /&gt;
Tout d&#039;abord il faut copier le fichier &#039;&#039;/etc/fail2ban/jail.conf&#039;&#039; en &#039;&#039;/etc/fail2ban/jail.local&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dans ce fichier, on va s&#039;intéresser aux variables suivantes:&lt;br /&gt;
*ignoreip : correspond à la suite d&#039;adresses IP qui ne se feront jamais bannir;&lt;br /&gt;
*maxretry : correspond au nombre d&#039;essais;&lt;br /&gt;
*findtime : correspond à la période pendant laquelle les essais vont incrémenter maxretry;&lt;br /&gt;
*bantime  : correspond au temps où l&#039;adresse IP ne peut pas se connecter.&lt;br /&gt;
&lt;br /&gt;
= Configuration de base =&lt;br /&gt;
== Choix de la punition ==&lt;br /&gt;
Il faut choisir quelque chose de cohérent (une punition suffisante) pour ne pas permettre de se faire cracker son mot de passe:&lt;br /&gt;
*maxretry = 3&lt;br /&gt;
*findtime = 86400 (correspond à 1 journée)&lt;br /&gt;
*bantime = 604800 (correspond à 1 semaine)&lt;br /&gt;
&lt;br /&gt;
Cela signifie que si une adresse IP se trompe 3 fois en 1 journée (86400s) elle se fait bannir pendant 1 semaine (604800s).&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul permet de trouver le nombre maximal de tentatives durant une année:&lt;br /&gt;
&lt;br /&gt;
365 jours / 7 jours par semaine * 3 tentatives = 156 essais, ce qui reste raisonnable. &lt;br /&gt;
&lt;br /&gt;
Si le pirate possède un [http://fr.wikipedia.org/wiki/Botnet botnet], il faut bien sûr multiplier ce nombre par le nombre de machines dans le botnet...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Attention : fail2ban parcours les logs de connexion pour connaître le numéro de la tentative, ce qui a pour conséquence, si le &#039;&#039;findtime&#039;&#039; est grand, de prendre un certain temps...&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Jail pour SSH ==&lt;br /&gt;
Il suffit d&#039;ajouter la ligne &#039;&#039;enabled=true&#039;&#039; dans la section à activer !&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[sshd]&lt;br /&gt;
&lt;br /&gt;
# To use more aggressive sshd modes set filter parameter &amp;quot;mode&amp;quot; in jail.local:&lt;br /&gt;
# normal (default), ddos, extra or aggressive (combines all).&lt;br /&gt;
# See &amp;quot;tests/files/logs/sshd&amp;quot; or &amp;quot;filter.d/sshd.conf&amp;quot; for usage example and details.&lt;br /&gt;
#mode   = normal&lt;br /&gt;
enabled = true&lt;br /&gt;
port    = ssh&lt;br /&gt;
logpath = %(sshd_log)s&lt;br /&gt;
backend = %(sshd_backend)s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Configuration spécifique =&lt;br /&gt;
== Jail pour PVEPROXY ==&lt;br /&gt;
Pveproxy écoute sur le port 8006 et ne fonctionne pas exactement comme un serveur [[HTTPD | Apache httpd]] qui mettrait ces logs dans le fichier &#039;&#039;error_log&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Nous allons mettre cette configuration spécifique dans le fichier &#039;&#039;/etc/fail2ban/jail.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[proxmox]&lt;br /&gt;
enabled = true&lt;br /&gt;
port = https,http,8006&lt;br /&gt;
filter = proxmox&lt;br /&gt;
backend = systemd&lt;br /&gt;
maxretry = 5&lt;br /&gt;
findtime = 1d&lt;br /&gt;
bantime = 1w&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le backend utilisé est systemd, exactement comme si vous utilisiez la commande :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Filtre pour PVEPROXY ==&lt;br /&gt;
Il ne nous reste plus qu&#039;à spécifier le filtre &#039;&#039;proxmox&#039;&#039; dans le fichier &#039;&#039;/etc/fail2ban/filter.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=&amp;lt;HOST&amp;gt; user=.* msg=.*&lt;br /&gt;
ignoreregex =&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Tests =&lt;br /&gt;
Il faut maintenant tester le filtre et pour ça on peut utiliser un partage de connexion et réaliser le nombre d&#039;échecs spécifié par la directive &amp;quot;maxretry&amp;quot; (ici 3) :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed:	0&lt;br /&gt;
|  |- Total failed:	3&lt;br /&gt;
|  `- Journal matches:	_SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned:	1&lt;br /&gt;
   |- Total banned:	1&lt;br /&gt;
   `- Banned IP list:	37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On voit bien l&#039;IP 37.167.23.159 qui est bannie !&lt;br /&gt;
N&#039;oubliez pas de l&#039;ajouter à &#039;&#039;ignoreip&#039;&#039; dans le fichier &#039;&#039;jails.local&#039;&#039; ou de faire &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client unban 37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Démarrage et enregistrement dans le chargeur de démarrage =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start fail2ban.service&lt;br /&gt;
# systemctl enable fail2ban.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Vous pouvez maintenant démarrer fail2ban&lt;br /&gt;
&lt;br /&gt;
= Proxification=&lt;br /&gt;
Lorsque votre serveur Proxmox se trouve derrière un reverse-proxy (Apache, Nginx, Traefik, ...), au niveau 3 OSI, l&#039;adresse IP du client est remplacée par celle du proxy et le serveur utilise l&#039;entêtes &#039;&#039;X-Forwarded-For&#039;&#039; ou &#039;&#039;X-Real-IP&#039;&#039; pour transporter l&#039;adresse du client &lt;br /&gt;
[[Fichier:Reverse proxy proxmox.png|700px|centré]]&lt;br /&gt;
Dans cette exemple:&lt;br /&gt;
* le nom de domaine utilisé est &#039;&#039;&#039;pve.tala-informatique.fr&#039;&#039;&#039;&lt;br /&gt;
* l&#039;adresse du proxy est &#039;&#039;&#039;192.168.4.100&#039;&#039;&#039;&lt;br /&gt;
* l&#039;adresse du serveur Proxmox est &#039;&#039;&#039;192.168.4.1&#039;&#039;&#039;&lt;br /&gt;
== Configuration du reverse-proxy ==&lt;br /&gt;
Sur votre reverse-proxy Apache, vous devriez avoir une configuration qui ressemble à ça:&lt;br /&gt;
&amp;lt;source lang=apache&amp;gt;&lt;br /&gt;
MDomain pve.tala-informatique.fr&lt;br /&gt;
&lt;br /&gt;
&amp;lt;VirtualHost *:80&amp;gt;&lt;br /&gt;
    ServerName pve.tala-informatique.fr&lt;br /&gt;
    Redirect / https://pve.tala-informatique.fr/&lt;br /&gt;
&amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;VirtualHost *:443&amp;gt;&lt;br /&gt;
    ServerName pve.tala-informatique.fr&lt;br /&gt;
    &lt;br /&gt;
    SSLEngine on&lt;br /&gt;
    SSLProxyEngine on&lt;br /&gt;
    SSLProxyVerify none &lt;br /&gt;
    SSLProxyCheckPeerCN off&lt;br /&gt;
    SSLProxyCheckPeerName off&lt;br /&gt;
    &lt;br /&gt;
    ProxyRequests off&lt;br /&gt;
    ProxyPreserveHost On&lt;br /&gt;
    &lt;br /&gt;
    RewriteEngine on&lt;br /&gt;
    RewriteCond %{HTTP:Connection} Upgrade [NC]&lt;br /&gt;
    RewriteCond %{HTTP:Upgrade} websocket [NC]&lt;br /&gt;
    RewriteRule ^/?(.*) wss://192.168.4.1:8006/$1 [P,L]&lt;br /&gt;
&lt;br /&gt;
    ProxyPass / https://192.168.4.1:8006/ flushpackets=On connectiontimeout=300 timeout=300&lt;br /&gt;
    ProxyPassReverse / https://192.168.4.1:8006/&lt;br /&gt;
    ProxyTimeout     600&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La première ligne renvoie à la configuration de mod_md abordée dans cette [[Httpd_certificate_security#Let&#039;s_Encrypt |article]] et permet l&#039;obtention du certificat SSL auprès de [https://letsencrypt.org Let&#039;s encrypt]&lt;br /&gt;
&amp;lt;source lang=apache&amp;gt;&lt;br /&gt;
MDomain pve.tala-informatique.fr&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le bloc suivant permet de [[Httpd_redirect_reverse-proxy_mod-rewrite#http_→_https | renvoyer les utilisateurs]] se présentant sur le port 80 vers le port 443&lt;br /&gt;
&amp;lt;source lang=apache&amp;gt;&lt;br /&gt;
&amp;lt;VirtualHost *:80&amp;gt;&lt;br /&gt;
    ServerName pve.tala-informatique.fr&lt;br /&gt;
    Redirect / https://pve.tala-informatique.fr/&lt;br /&gt;
&amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dans le bloc &#039;&#039;443&#039;&#039;, on est obligé de désactiver les vérifications SSL parce que le certificat du serveur Proxmox est autosigné (donc pas de cadenas vert), ce qui pousse Apache à bloquer la connexion si on ne désactive pas ces vérifications&lt;br /&gt;
&amp;lt;source lang=apache&amp;gt;&lt;br /&gt;
SSLProxyVerify none &lt;br /&gt;
SSLProxyCheckPeerCN off&lt;br /&gt;
SSLProxyCheckPeerName off&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
La réécriture d&#039;url doit être configuré pour prendre en compte les &#039;&#039;websockets sécurisées&#039;&#039; (wss) utilisées pour l&#039;affichage de l&#039;écran des machine ou conteneurs avec &#039;&#039;xterm.js&#039;&#039;&lt;br /&gt;
&amp;lt;source lang=apache&amp;gt;&lt;br /&gt;
RewriteEngine on&lt;br /&gt;
RewriteCond %{HTTP:Connection} Upgrade [NC]&lt;br /&gt;
RewriteCond %{HTTP:Upgrade} websocket [NC]&lt;br /&gt;
RewriteRule ^/?(.*) wss://192.168.4.1:8006/$1 [P,L]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Enfin on redirige les requêtes vers le serveur Proxmox en n&#039;oubliant pas de préciser le port 8006&lt;br /&gt;
&amp;lt;source lang=apache&amp;gt;&lt;br /&gt;
ProxyPass / https://192.168.4.1:8006/ flushpackets=On connectiontimeout=300 timeout=300&lt;br /&gt;
ProxyPassReverse / https://192.168.4.1:8006/&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
== Problème lié à la proxyfication ==&lt;br /&gt;
Le problème est que la seule adresse que fail2ban va voir apparaître dans les logs est celle du reverse-proxy (&#039;&#039;192.168.4.100&#039;&#039;) :&lt;br /&gt;
[[Fichier:Reverse proxy ip logs.png|600px|centré]]&lt;br /&gt;
Même si le filtre &#039;&#039;fail2ban&#039;&#039; est configuré pour utiliser la commande &#039;&#039;journactl&#039;&#039; sur le démon &#039;&#039;pvedaemon&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
les adresses viennent de pveproxy qui journalise tout dans &#039;&#039;/var/log/pveproxy/access.log&#039;&#039; et &#039;&#039;pvedaemon&#039;&#039; ne journalise que les échecs d&#039;authentification. &lt;br /&gt;
Il est donc plus simple de faire un &#039;&#039;tail&#039;&#039; ou un &#039;&#039;cat&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Que d&#039;utiliser &#039;&#039;journalctl&#039;&#039; pour voir les IPs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
Dec 14 10:43:01 labo unix_chkpwd[1326506]: password check failed for user (root)&lt;br /&gt;
Dec 14 10:43:01 labo IPCC.xs[1320783]: pam_unix(proxmox-ve-auth:auth): authentication failure; logname= uid=0 euid=0 tty= ruser= rhost=37.167.23.159  user=root&lt;br /&gt;
Dec 14 10:43:03 labo pvedaemon[1320783]: authentication failure; rhost=37.167.23.159 user=root@pam msg=Authentication failure&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Configuration de pveproxy ==&lt;br /&gt;
Si on veut voir l&#039;adresse du client, il faut dire au [https://fr.wikipedia.org/wiki/Daemon_(informatique)| démon] &#039;&#039;pveproxy&#039;&#039; d&#039;utiliser l&#039;une des deux entêtes précédentes ainsi que préciser l&#039;adresse du proxy. &lt;br /&gt;
&lt;br /&gt;
Préciser l&#039;adresse du proxy est essentiel pour que &#039;&#039;pveproxy&#039;&#039; n&#039;accepte de lire l&#039;adresse du client présente dans l&#039;entête &#039;&#039;&#039;uniquement&#039;&#039;&#039; si cela provient du proxy, qui est une machine de confiance. Le cas contraire, tout le monde pourrait ajouter une adresse IP dans l&#039;entête pour la faire bannir...&lt;br /&gt;
&lt;br /&gt;
Nous allons créer le fichier &#039;&#039;/etc/default/pveproxy&#039;&#039; avec les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Forwarded-For&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Real-IP&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_ALLOW_FROM=&amp;quot;192.168.4.100&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il faut maintenant redémarrer &#039;&#039;pveproxy&#039;&#039; pour que les changements s&#039;appliquent. Si vous êtes connecté via l&#039;interface web, cela va vous déconnecter, le temps que le démon redémarre, il faudra ensuite certainement rafraîchir la page web.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl restart pveproxy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à vérifier dans les logs si les bonnes adresses s&#039;affichent:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Si jamais ce n&#039;est pas le cas, poursuivez avec la modification du fichier &#039;&#039;AnyEvent.pm&#039;&#039;&lt;br /&gt;
== Modification de AnyEvent.pm ==&lt;br /&gt;
=== Application de la modification ===&lt;br /&gt;
Au jour d&#039;aujourd&#039;hui (13/12/25) la proxification ne fonctionne plus et il faut apporter une modification dans le fichier &#039;&#039;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&#039;&#039; pour que les bonnes adresses apparaissent !&lt;br /&gt;
En fonction des versions cette modification peut avoir lieu soit ligne &#039;&#039;&#039;1504&#039;&#039;&#039;, soit ligne &#039;&#039;&#039;1554&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Il faut repérer la fonction suivante:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
sub authenticate_and_handle_request {&lt;br /&gt;
    my ($self, $reqstate) = @_;&lt;br /&gt;
&lt;br /&gt;
    my $request = $reqstate-&amp;gt;{request};&lt;br /&gt;
    my $method = $request-&amp;gt;method();&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
C&#039;est un peu plus loin qu&#039;il faut insérer le code :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 ### INSERTION ICI ###&lt;br /&gt;
&lt;br /&gt;
    if ($self-&amp;gt;{spiceproxy}) {&lt;br /&gt;
        my $connect_str = $request-&amp;gt;header(&#039;Host&#039;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il faut modifier l&#039;attribut &#039;&#039;peer_host&#039;&#039; de l&#039;objet &#039;&#039;reqstate&#039;&#039; si l&#039;une des deux entêtes est présente :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if ($request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
} elsif ($request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Double IPv4 ou préfixe IPv6 ===&lt;br /&gt;
Après redémarrage, cela permet de voir l&#039;adresse du client dans les logs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/ext-all.js?ver=7.0.0 HTTP/1.1&amp;quot; 200 683505&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/js/u2f-api.js HTTP/1.1&amp;quot; 200 4898&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/resources HTTP/1.1&amp;quot; 200 1226&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/tasks HTTP/1.1&amp;quot; 200 1090&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /proxmoxlib.js?ver=v5.0.4-t1754316706 HTTP/1.1&amp;quot; 200 157086&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/theme-crisp/resources/theme-crisp-all_1.css HTTP/1.1&amp;quot; 200 32919&lt;br /&gt;
::ffff:192.168.20.22 - root@pam [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/nodes/labo/lxc/100/status/current HTTP/1.1&amp;quot; 200 523&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il nous reste un peu de nettoyage à faire, dans certains cas :&lt;br /&gt;
* l&#039;adresse apparaît non pas une fois mais deux, séparées par une virgule&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
37.167.182.207, 37.167.182.207&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* l&#039;adresse IPv4 (32 bits) est affichée dans sa représentation IPv6 (128 bits), avec le préfixe &#039;&#039;::ffff:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
::ffff:192.168.20.22&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On a deux possibilités pour faire le nettoyage :&lt;br /&gt;
*Soit on ajoute les lignes suivantes dans &#039;&#039;AnyEvent.pm&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if (index($reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
   # Remove trailing ip &lt;br /&gt;
   my @fields = split /,/, $reqstate-&amp;gt;{peer_host};&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $fields[0];&lt;br /&gt;
}&lt;br /&gt;
if($reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
   # Remove IPv6 subnet for IPv4&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $1;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*Soit on modifie le filtre /etc/fail2ban/filter.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=.*:?&amp;lt;HOST&amp;gt;,? user=.* msg=.*&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Automatisation ===&lt;br /&gt;
On peut automatiser le processus précédent avec le script suivant, que l&#039;on peut créer dans /root/remoteip_fix.sh :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=bash&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
ANYEVENT_PATH=&amp;quot;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&amp;quot;&lt;br /&gt;
ANYEVENT_REGEX=&#039;$self-&amp;gt;{spiceproxy}&#039;&lt;br /&gt;
TMP_FILE=&amp;quot;/tmp/AnyEvent.pm.tmp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if [ ! -f $ANYEVENT_PATH ]; then&lt;br /&gt;
  echo &amp;quot;$ANYEVENT_PATH does not exists !&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
if [ $(grep &#039;### BUGFIX REMOTE_IP FOR FAIL2BAN ###&#039; $ANYEVENT_PATH | wc -l) -eq 1 ]; then&lt;br /&gt;
  echo &amp;quot;AnyEvent.pm already patched !&amp;quot;&lt;br /&gt;
  exit 0&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
LINE_NUMBER_TOP=$(nl -ba $ANYEVENT_PATH | grep $ANYEVENT_REGEX | head -n 1 | awk -F &#039; &#039; &#039;{print $1}&#039;)&lt;br /&gt;
let LINE_NUMBER_TOP-=1&lt;br /&gt;
&lt;br /&gt;
if [ $LINE_NUMBER_TOP -lt 0 ]; then&lt;br /&gt;
  echo &amp;quot;Did not find the $ANYEVENT_REGEX expr in $ANYEVENT_PATH&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
echo -n &amp;quot;Applying bugfix: &amp;quot;&lt;br /&gt;
trap &amp;quot;rm -f $TMP_FILE&amp;quot; 0 1 2 5 13 15&lt;br /&gt;
head -n $LINE_NUMBER_TOP $ANYEVENT_PATH &amp;gt;$TMP_FILE&lt;br /&gt;
cat &amp;gt;&amp;gt;$TMP_FILE &amp;lt;&amp;lt;EOF&lt;br /&gt;
### BUGFIX REMOTE_IP FOR FAIL2BAN ###&lt;br /&gt;
    if (\$request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
    } elsif (\$request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
    }&lt;br /&gt;
    if (index(\$reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
        my @fields = split /,/, \$reqstate-&amp;gt;{peer_host};&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$fields[0];&lt;br /&gt;
    }&lt;br /&gt;
    if(\$reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
        # Remove IPv6 subnet for IPv4&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$1;&lt;br /&gt;
    }&lt;br /&gt;
#####################################&lt;br /&gt;
EOF&lt;br /&gt;
echo &amp;quot;$ANYEVENT_MODIF&amp;quot; &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cp $ANYEVENT_PATH $ANYEVENT_PATH.ori&lt;br /&gt;
LINE_NUMBER_BOTTOM=$(cat $ANYEVENT_PATH | wc -l)&lt;br /&gt;
let LINE_NUMBER_BOTTOM-=LINE_NUMBER_TOP&lt;br /&gt;
tail -n $LINE_NUMBER_BOTTOM $ANYEVENT_PATH &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cat $TMP_FILE &amp;gt;$ANYEVENT_PATH&lt;br /&gt;
rm -f $TMP_FILE&lt;br /&gt;
trap 0&lt;br /&gt;
echo &amp;quot;done.&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à le rendre exécutable et le lancer :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# chmod +x /root/remoteip_fix.sh&lt;br /&gt;
# /root/remoteip_fix.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne faudra pas oublier de redémarrer &#039;&#039;pveproxy&#039;&#039; pour appliquer les changements !&lt;br /&gt;
&lt;br /&gt;
== Comment bannir derrière un reverse-proxy ? ==&lt;br /&gt;
Maintenant que votre Proxmox est derrière un reverse-proxy, inutile de bannir les IP publiques avec iptables sur le serveur Proxmox, la seule IP visible est celle du reverse-proxy (dans cet exemple 192.168.4.100).&lt;br /&gt;
&lt;br /&gt;
La seule machine capable capable de bannir est le reverse-proxy, il faut donc lui transmettre les IP et nous allons faire ça en trois étapes:&lt;br /&gt;
* la première est de créer une &amp;quot;prison&amp;quot; proxmox sur le fail2ban présent sur le reverse-proxy&lt;br /&gt;
* la deuxième est l&#039;invention d&#039;une API pour fail2ban sur le reverse-proxy&lt;br /&gt;
* la troisième est la modification du comportement de fail2ban pour appeler cette API au lieu de modifier iptables&lt;br /&gt;
&lt;br /&gt;
=== Création d&#039;une prison sur le reverse-proxy ===&lt;br /&gt;
&lt;br /&gt;
Pour bannir nous allons créer une prison spécifique pour le / les serveurs Proxmox que nous allons appeler &#039;&#039;proxmox&#039;&#039; dans le fichier /etc/fail2ban/jail.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[proxmox]&lt;br /&gt;
enabled = true&lt;br /&gt;
port = https,http&lt;br /&gt;
filter = do-nothing&lt;br /&gt;
logpath = /dev/null&lt;br /&gt;
maxretry = 3&lt;br /&gt;
findtime = 1d&lt;br /&gt;
bantime = 1w&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
J&#039;attire votre attention sur les paramètres &#039;&#039;maxretry&#039;&#039;, &#039;&#039;findtime&#039;&#039; et &#039;&#039;bantime&#039;&#039; qui doivent concorder avec ceux du fail2ban de votre Proxmox. S&#039;il sont plus &#039;&#039;court&#039;&#039; sur le reverse-proxy, les IP seront libérées plus tôt à l&#039;inverse, plus long n&#039;est pas gênant, le fail2ban de votre Proxmox les libéreras avant celui du proxy.&lt;br /&gt;
&lt;br /&gt;
Vous avez remarquez le filtre &#039;&#039;do-nothing&#039;&#039; qu&#039;il nous reste à créer dans le fichier &#039;&#039;/etc/fail2ban/filter.d/do-nothing.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
&lt;br /&gt;
failregex = ^&amp;lt;HOST&amp;gt;$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Après redémarrage de fail2ban :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl restart fail2ban&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous devriez voir la prison&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status&lt;br /&gt;
Status&lt;br /&gt;
|- Number of jail:      2&lt;br /&gt;
`- Jail list:   proxmox, sshd&lt;br /&gt;
[root@proxy proxymox]# &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous pouvons maintenant passer à l&#039;API !&lt;br /&gt;
&lt;br /&gt;
=== Invention d&#039;une API pour fail2ban ===&lt;br /&gt;
&lt;br /&gt;
Toujours sur le reverse-proxy nous allons installer PHP pour créer un mini serveur qui répondra au urls suivantes:&lt;br /&gt;
* /ban/&amp;lt;ip&amp;gt; pour bannir&lt;br /&gt;
* /unban/&amp;lt;ip&amp;gt; pour lever le banissement&lt;br /&gt;
&lt;br /&gt;
Commençons par installer PHP:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# dnf -y install php-cli&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un répertoire &amp;quot;f2b-api&amp;quot; dans le dossier &amp;quot;opt&amp;quot; :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# mkdir /opt/f2b-api&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis créer un fichier &#039;&#039;f2b-api.php&#039;&#039; dans ce dossier:&lt;br /&gt;
&amp;lt;source lang=php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
main();&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        # On clean l&#039;uri du / de début&lt;br /&gt;
        $uri = ltrim($_SERVER[&#039;REQUEST_URI&#039;], &#039;/&#039;);&lt;br /&gt;
        # On éclate l&#039;uri en parties (action + ip)&lt;br /&gt;
        $parts = explode(&#039;/&#039;, $uri);&lt;br /&gt;
        # Récupération de l&#039;action dans une variable ou false si vide&lt;br /&gt;
        $action = empty($parts[0]) ? false : $parts[0];&lt;br /&gt;
        # Récupération de l&#039;ip dans une variable ou false si vide&lt;br /&gt;
        $ip = empty($parts[1]) ? false : $parts[1];&lt;br /&gt;
        if(!$action || !$ip){&lt;br /&gt;
                # Si action vide =&amp;gt; 400 Bad request&lt;br /&gt;
                http_response_code(400);&lt;br /&gt;
                die();&lt;br /&gt;
        }&lt;br /&gt;
        if(!in_array($action, [&#039;ban&#039;, &#039;unban&#039;])){&lt;br /&gt;
                # Si action pas dans la liste =&amp;gt; 400 Bad request&lt;br /&gt;
                http_response_code(400);&lt;br /&gt;
                die();&lt;br /&gt;
        }&lt;br /&gt;
        $cmd = &#039;&#039;;&lt;br /&gt;
        if($action == &#039;ban&#039;){&lt;br /&gt;
                $cmd = &#039;fail2ban-client set proxmox banip &#039; . $ip;&lt;br /&gt;
        } else if($action == &#039;unban&#039;){&lt;br /&gt;
                $cmd = &#039;fail2ban-client unban proxmox &#039; . $ip;&lt;br /&gt;
        }&lt;br /&gt;
        shell_exec($cmd);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
[[Fichier:Warning-icon.png|40px]]  Gardez en tête que ce code simpliste n&#039;est en aucun cas sécurisé et ne doit pas être accessible depuis Internet.&lt;br /&gt;
&lt;br /&gt;
Pour démarrer se code en mode serveur il suffit de taper la commande suivante:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# php -S 0.0.0.0:8080 -t /opt/f2b-api /opt/f2b-api/f2b-api.php&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous pouvez tester directement depuis un autre terminal en tapant les commandes:&lt;br /&gt;
* pour bannir :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# curl -X GET http://127.0.0.1:8080/ban/1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* pour dé-bannir :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# curl -X GET http://127.0.0.1:8080/unban/1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Et en vérifiant dans fail2ban:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed: 0&lt;br /&gt;
|  |- Total failed:     0&lt;br /&gt;
|  `- File list:        /dev/null&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned: 1&lt;br /&gt;
   |- Total banned:     10&lt;br /&gt;
   `- Banned IP list:   1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Nous n&#039;allons pas lancer nous même le serveur PHP, nous allons demander à SystemD de le faire et pour cela nous allons créer le fichier &#039;&#039;/opt/f2b-api/f2b-api.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=fail2ban API Server&lt;br /&gt;
After=network-online.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
UMask=007&lt;br /&gt;
ExecStart=php -S 0.0.0.0:8080 -t /opt/f2b-api /opt/f2b-api/f2b-api.php&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faut maintenant demander à SystemD de s&#039;occuper de notre service:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl link /opt/f2b-api/f2b-api.service&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Et de le lancer au démarrage du reverse-proxy:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl enable f2b-api --now&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous pouvons maintenant nous déplacer sur le serveur Proxmox pour modifier fail2ban !&lt;br /&gt;
&lt;br /&gt;
=== Modification des actions fail2ban ===&lt;br /&gt;
Sur le serveur Proxmox nous allons débrayer le comportement de base de fail2ban qui est de modifier iptables. pour cela nous alons créer le fichier &#039;&#039;/etc/fail2ban/action.d/f2b-api.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
actionstart =&lt;br /&gt;
actionstop =&lt;br /&gt;
actioncheck =&lt;br /&gt;
actionban = curl -X GET 192.168.4.100:8080/ban/&amp;lt;ip&amp;gt;&lt;br /&gt;
actionunban = curl -X GET 192.168.4.100:8080/unban/&amp;lt;ip&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Veuillez noter que:&lt;br /&gt;
* même si elles sont vide, les lignes &#039;&#039;actionstart&#039;&#039;, &#039;&#039;actionstop&#039;&#039; et &#039;&#039;actioncheck&#039;&#039; sont obligatoires !&lt;br /&gt;
* l&#039;adresse &#039;&#039;192.168.4.100&#039;&#039; doit être remplcée par celle de votre reverse-proxy&lt;br /&gt;
* &amp;lt;ip&amp;gt; est l&#039;expression utilisée par fail2ban et elle sera remplacée par l&#039;IP à bannir &lt;br /&gt;
&lt;br /&gt;
Pour ce fichier d&#039;action soit pris en compte, il faut modifier le fichier &#039;&#039;/etc/fail2ban/jail.d/proxmox.conf&#039;&#039; pour y ajouter:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
banaction = f2b-api&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne vous reste plus qu&#039;a redémarrer le service fai2ban sur le serveur Proxmox:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl restart fail2ban&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Et vous pouvez tester les commandes suivantes:&lt;br /&gt;
* pour bannir&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client set proxmox banip 1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* pour dé-bannir:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client unban proxmox 1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Et vérifier sur le reverse-proxy que les modification sont bien prises en compte:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed: 0&lt;br /&gt;
|  |- Total failed:     0&lt;br /&gt;
|  `- File list:        /dev/null&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned: 1&lt;br /&gt;
   |- Total banned:     10&lt;br /&gt;
   `- Banned IP list:   1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4421</id>
		<title>Proxmox fail2ban</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4421"/>
		<updated>2026-07-13T09:39:45Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Proxification */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
Proxmox utilise une interface web d&#039;administration qui utilise le port TCP 8006 et c&#039;est un vecteur possible d&#039;attaque par force brut. Nous allons donc &#039;&#039;dresser&#039;&#039; fail2ban pour agir en cas d&#039;attaque !&lt;br /&gt;
&lt;br /&gt;
Proxmox utilise Debian, nous allons principalement reproduire les étapes décrites dans le tutoriel de [[Sécuriser_un_service_avec_Fail2ban| Fail2ban pour Rocky]] et adapter à Debian.&lt;br /&gt;
&lt;br /&gt;
Avant d&#039;aller plus loin, assurez-vous d&#039;avoir correctement installé et configuré [[proxmox_iptables |iptables sur Proxmox]]&lt;br /&gt;
&lt;br /&gt;
= Installation =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt -y install fail2ban&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Configuration =&lt;br /&gt;
Tout d&#039;abord il faut copier le fichier &#039;&#039;/etc/fail2ban/jail.conf&#039;&#039; en &#039;&#039;/etc/fail2ban/jail.local&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dans ce fichier, on va s&#039;intéresser aux variables suivantes:&lt;br /&gt;
*ignoreip : correspond à la suite d&#039;adresses IP qui ne se feront jamais bannir;&lt;br /&gt;
*maxretry : correspond au nombre d&#039;essais;&lt;br /&gt;
*findtime : correspond à la période pendant laquelle les essais vont incrémenter maxretry;&lt;br /&gt;
*bantime  : correspond au temps où l&#039;adresse IP ne peut pas se connecter.&lt;br /&gt;
&lt;br /&gt;
= Configuration de base =&lt;br /&gt;
== Choix de la punition ==&lt;br /&gt;
Il faut choisir quelque chose de cohérent (une punition suffisante) pour ne pas permettre de se faire cracker son mot de passe:&lt;br /&gt;
*maxretry = 3&lt;br /&gt;
*findtime = 86400 (correspond à 1 journée)&lt;br /&gt;
*bantime = 604800 (correspond à 1 semaine)&lt;br /&gt;
&lt;br /&gt;
Cela signifie que si une adresse IP se trompe 3 fois en 1 journée (86400s) elle se fait bannir pendant 1 semaine (604800s).&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul permet de trouver le nombre maximal de tentatives durant une année:&lt;br /&gt;
&lt;br /&gt;
365 jours / 7 jours par semaine * 3 tentatives = 156 essais, ce qui reste raisonnable. &lt;br /&gt;
&lt;br /&gt;
Si le pirate possède un [http://fr.wikipedia.org/wiki/Botnet botnet], il faut bien sûr multiplier ce nombre par le nombre de machines dans le botnet...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Attention : fail2ban parcours les logs de connexion pour connaître le numéro de la tentative, ce qui a pour conséquence, si le &#039;&#039;findtime&#039;&#039; est grand, de prendre un certain temps...&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Jail pour SSH ==&lt;br /&gt;
Il suffit d&#039;ajouter la ligne &#039;&#039;enabled=true&#039;&#039; dans la section à activer !&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[sshd]&lt;br /&gt;
&lt;br /&gt;
# To use more aggressive sshd modes set filter parameter &amp;quot;mode&amp;quot; in jail.local:&lt;br /&gt;
# normal (default), ddos, extra or aggressive (combines all).&lt;br /&gt;
# See &amp;quot;tests/files/logs/sshd&amp;quot; or &amp;quot;filter.d/sshd.conf&amp;quot; for usage example and details.&lt;br /&gt;
#mode   = normal&lt;br /&gt;
enabled = true&lt;br /&gt;
port    = ssh&lt;br /&gt;
logpath = %(sshd_log)s&lt;br /&gt;
backend = %(sshd_backend)s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Configuration spécifique =&lt;br /&gt;
== Jail pour PVEPROXY ==&lt;br /&gt;
Pveproxy écoute sur le port 8006 et ne fonctionne pas exactement comme un serveur [[HTTPD | Apache httpd]] qui mettrait ces logs dans le fichier &#039;&#039;error_log&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Nous allons mettre cette configuration spécifique dans le fichier &#039;&#039;/etc/fail2ban/jail.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[proxmox]&lt;br /&gt;
enabled = true&lt;br /&gt;
port = https,http,8006&lt;br /&gt;
filter = proxmox&lt;br /&gt;
backend = systemd&lt;br /&gt;
maxretry = 5&lt;br /&gt;
findtime = 1d&lt;br /&gt;
bantime = 1w&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le backend utilisé est systemd, exactement comme si vous utilisiez la commande :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Filtre pour PVEPROXY ==&lt;br /&gt;
Il ne nous reste plus qu&#039;à spécifier le filtre &#039;&#039;proxmox&#039;&#039; dans le fichier &#039;&#039;/etc/fail2ban/filter.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=&amp;lt;HOST&amp;gt; user=.* msg=.*&lt;br /&gt;
ignoreregex =&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Tests =&lt;br /&gt;
Il faut maintenant tester le filtre et pour ça on peut utiliser un partage de connexion et réaliser le nombre d&#039;échecs spécifié par la directive &amp;quot;maxretry&amp;quot; (ici 3) :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed:	0&lt;br /&gt;
|  |- Total failed:	3&lt;br /&gt;
|  `- Journal matches:	_SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned:	1&lt;br /&gt;
   |- Total banned:	1&lt;br /&gt;
   `- Banned IP list:	37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On voit bien l&#039;IP 37.167.23.159 qui est bannie !&lt;br /&gt;
N&#039;oubliez pas de l&#039;ajouter à &#039;&#039;ignoreip&#039;&#039; dans le fichier &#039;&#039;jails.local&#039;&#039; ou de faire &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client unban 37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Démarrage et enregistrement dans le chargeur de démarrage =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start fail2ban.service&lt;br /&gt;
# systemctl enable fail2ban.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Vous pouvez maintenant démarrer fail2ban&lt;br /&gt;
&lt;br /&gt;
= Proxification=&lt;br /&gt;
Lorsque votre serveur Proxmox se trouve derrière un reverse-proxy (Apache, Nginx, Traefik, ...), au niveau 3 OSI, l&#039;adresse IP du client est remplacée par celle du proxy et le serveur utilise l&#039;entêtes &#039;&#039;X-Forwarded-For&#039;&#039; ou &#039;&#039;X-Real-IP&#039;&#039; pour transporter l&#039;adresse du client &lt;br /&gt;
[[Fichier:Reverse proxy proxmox.png|700px|centré]]&lt;br /&gt;
Dans cette exemple:&lt;br /&gt;
* le nom de domaine utilisé est &#039;&#039;&#039;pve.tala-informatique.fr&#039;&#039;&#039;&lt;br /&gt;
* l&#039;adresse du proxy est &#039;&#039;&#039;192.168.4.100&#039;&#039;&#039;&lt;br /&gt;
* l&#039;adresse du serveur Proxmox est &#039;&#039;&#039;192.168.4.1&#039;&#039;&#039;&lt;br /&gt;
== Configuration du reverse-proxy ==&lt;br /&gt;
Sur votre reverse-proxy Apache, vous devriez avoir une configuration qui ressemble à ça:&lt;br /&gt;
&amp;lt;source lang=apache&amp;gt;&lt;br /&gt;
MDomain pve.tala-informatique.fr&lt;br /&gt;
&lt;br /&gt;
&amp;lt;VirtualHost *:80&amp;gt;&lt;br /&gt;
    ServerName pve.tala-informatique.fr&lt;br /&gt;
    Redirect / https://pve.tala-informatique.fr/&lt;br /&gt;
&amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;VirtualHost *:443&amp;gt;&lt;br /&gt;
    ServerName pve.tala-informatique.fr&lt;br /&gt;
    &lt;br /&gt;
    SSLEngine on&lt;br /&gt;
    SSLProxyEngine on&lt;br /&gt;
    SSLProxyVerify none &lt;br /&gt;
    SSLProxyCheckPeerCN off&lt;br /&gt;
    SSLProxyCheckPeerName off&lt;br /&gt;
    &lt;br /&gt;
    ProxyRequests off&lt;br /&gt;
    ProxyPreserveHost On&lt;br /&gt;
    &lt;br /&gt;
    RewriteEngine on&lt;br /&gt;
    RewriteCond %{HTTP:Connection} Upgrade [NC]&lt;br /&gt;
    RewriteCond %{HTTP:Upgrade} websocket [NC]&lt;br /&gt;
    RewriteRule ^/?(.*) wss://192.168.4.1:8006/$1 [P,L]&lt;br /&gt;
&lt;br /&gt;
    ProxyPass / https://192.168.4.1:8006/ flushpackets=On connectiontimeout=300 timeout=300&lt;br /&gt;
    ProxyPassReverse / https://192.168.4.1:8006/&lt;br /&gt;
    ProxyTimeout     600&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La première ligne renvoie à la configuration de mod_md abordée dans cette [[Httpd_certificate_security#Let&#039;s_Encrypt |article]] et permet l&#039;obtention du certificat SSL auprès de [https://letsencrypt.org Let&#039;s encrypt]&lt;br /&gt;
&amp;lt;source lang=apache&amp;gt;&lt;br /&gt;
MDomain pve.tala-informatique.fr&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le bloc suivant permet de [[Httpd_redirect_reverse-proxy_mod-rewrite#http_→_https | renvoyer les utilisateurs]] se présentant sur le port 80 vers le port 443&lt;br /&gt;
&amp;lt;source lang=apache&amp;gt;&lt;br /&gt;
&amp;lt;VirtualHost *:80&amp;gt;&lt;br /&gt;
    ServerName pve.tala-informatique.fr&lt;br /&gt;
    Redirect / https://pve.tala-informatique.fr/&lt;br /&gt;
&amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dans le bloc &#039;&#039;443&#039;&#039;, on est obligé de désactiver les vérifications SSL parce que le certificat du serveur Proxmox est autosigné (donc pas de cadenas vert), ce qui pousse Apache à bloquer la connexion si on ne désactive pas ces vérifications&lt;br /&gt;
&amp;lt;source lang=apache&amp;gt;&lt;br /&gt;
SSLProxyVerify none &lt;br /&gt;
SSLProxyCheckPeerCN off&lt;br /&gt;
SSLProxyCheckPeerName off&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
La réécriture d&#039;url doit être configuré pour prendre en compte les &#039;&#039;websockets sécurisées&#039;&#039; (wss) utilisées pour l&#039;affichage de l&#039;écran des machine ou conteneurs avec &#039;&#039;xterm.js&#039;&#039;&lt;br /&gt;
&amp;lt;source lang=apache&amp;gt;&lt;br /&gt;
RewriteEngine on&lt;br /&gt;
RewriteCond %{HTTP:Connection} Upgrade [NC]&lt;br /&gt;
RewriteCond %{HTTP:Upgrade} websocket [NC]&lt;br /&gt;
RewriteRule ^/?(.*) wss://192.168.4.1:8006/$1 [P,L]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Enfin on redirige les requêtes vers le serveur Proxmox en n&#039;oubliant pas de préciser le port 8006&lt;br /&gt;
&amp;lt;source lang=apache&amp;gt;&lt;br /&gt;
ProxyPass / https://192.168.4.1:8006/ flushpackets=On connectiontimeout=300 timeout=300&lt;br /&gt;
ProxyPassReverse / https://192.168.4.1:8006/&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le problème est que la seule adresse que fail2ban va voir apparaître dans les logs est celle du reverse-proxy (&#039;&#039;192.168.4.100&#039;&#039;) :&lt;br /&gt;
[[Fichier:Reverse proxy ip logs.png|600px|centré]]&lt;br /&gt;
Même si le filtre &#039;&#039;fail2ban&#039;&#039; est configuré pour utiliser la commande &#039;&#039;journactl&#039;&#039; sur le démon &#039;&#039;pvedaemon&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
les adresses viennent de pveproxy qui journalise tout dans &#039;&#039;/var/log/pveproxy/access.log&#039;&#039; et &#039;&#039;pvedaemon&#039;&#039; ne journalise que les échecs d&#039;authentification. &lt;br /&gt;
Il est donc plus simple de faire un &#039;&#039;tail&#039;&#039; ou un &#039;&#039;cat&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Que d&#039;utiliser &#039;&#039;journalctl&#039;&#039; pour voir les IPs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
Dec 14 10:43:01 labo unix_chkpwd[1326506]: password check failed for user (root)&lt;br /&gt;
Dec 14 10:43:01 labo IPCC.xs[1320783]: pam_unix(proxmox-ve-auth:auth): authentication failure; logname= uid=0 euid=0 tty= ruser= rhost=37.167.23.159  user=root&lt;br /&gt;
Dec 14 10:43:03 labo pvedaemon[1320783]: authentication failure; rhost=37.167.23.159 user=root@pam msg=Authentication failure&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Configuration de pveproxy ==&lt;br /&gt;
Si on veut voir l&#039;adresse du client, il faut dire au [https://fr.wikipedia.org/wiki/Daemon_(informatique)| démon] &#039;&#039;pveproxy&#039;&#039; d&#039;utiliser l&#039;une des deux entêtes précédentes ainsi que préciser l&#039;adresse du proxy. &lt;br /&gt;
&lt;br /&gt;
Préciser l&#039;adresse du proxy est essentiel pour que &#039;&#039;pveproxy&#039;&#039; n&#039;accepte de lire l&#039;adresse du client présente dans l&#039;entête &#039;&#039;&#039;uniquement&#039;&#039;&#039; si cela provient du proxy, qui est une machine de confiance. Le cas contraire, tout le monde pourrait ajouter une adresse IP dans l&#039;entête pour la faire bannir...&lt;br /&gt;
&lt;br /&gt;
Nous allons créer le fichier &#039;&#039;/etc/default/pveproxy&#039;&#039; avec les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Forwarded-For&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Real-IP&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_ALLOW_FROM=&amp;quot;192.168.4.100&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il faut maintenant redémarrer &#039;&#039;pveproxy&#039;&#039; pour que les changements s&#039;appliquent. Si vous êtes connecté via l&#039;interface web, cela va vous déconnecter, le temps que le démon redémarre, il faudra ensuite certainement rafraîchir la page web.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl restart pveproxy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à vérifier dans les logs si les bonnes adresses s&#039;affichent:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Si jamais ce n&#039;est pas le cas, poursuivez avec la modification du fichier &#039;&#039;AnyEvent.pm&#039;&#039;&lt;br /&gt;
== Modification de AnyEvent.pm ==&lt;br /&gt;
=== Application de la modification ===&lt;br /&gt;
Au jour d&#039;aujourd&#039;hui (13/12/25) la proxification ne fonctionne plus et il faut apporter une modification dans le fichier &#039;&#039;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&#039;&#039; pour que les bonnes adresses apparaissent !&lt;br /&gt;
En fonction des versions cette modification peut avoir lieu soit ligne &#039;&#039;&#039;1504&#039;&#039;&#039;, soit ligne &#039;&#039;&#039;1554&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Il faut repérer la fonction suivante:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
sub authenticate_and_handle_request {&lt;br /&gt;
    my ($self, $reqstate) = @_;&lt;br /&gt;
&lt;br /&gt;
    my $request = $reqstate-&amp;gt;{request};&lt;br /&gt;
    my $method = $request-&amp;gt;method();&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
C&#039;est un peu plus loin qu&#039;il faut insérer le code :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 ### INSERTION ICI ###&lt;br /&gt;
&lt;br /&gt;
    if ($self-&amp;gt;{spiceproxy}) {&lt;br /&gt;
        my $connect_str = $request-&amp;gt;header(&#039;Host&#039;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il faut modifier l&#039;attribut &#039;&#039;peer_host&#039;&#039; de l&#039;objet &#039;&#039;reqstate&#039;&#039; si l&#039;une des deux entêtes est présente :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if ($request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
} elsif ($request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Double IPv4 ou préfixe IPv6 ===&lt;br /&gt;
Après redémarrage, cela permet de voir l&#039;adresse du client dans les logs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/ext-all.js?ver=7.0.0 HTTP/1.1&amp;quot; 200 683505&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/js/u2f-api.js HTTP/1.1&amp;quot; 200 4898&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/resources HTTP/1.1&amp;quot; 200 1226&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/tasks HTTP/1.1&amp;quot; 200 1090&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /proxmoxlib.js?ver=v5.0.4-t1754316706 HTTP/1.1&amp;quot; 200 157086&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/theme-crisp/resources/theme-crisp-all_1.css HTTP/1.1&amp;quot; 200 32919&lt;br /&gt;
::ffff:192.168.20.22 - root@pam [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/nodes/labo/lxc/100/status/current HTTP/1.1&amp;quot; 200 523&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il nous reste un peu de nettoyage à faire, dans certains cas :&lt;br /&gt;
* l&#039;adresse apparaît non pas une fois mais deux, séparées par une virgule&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
37.167.182.207, 37.167.182.207&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* l&#039;adresse IPv4 (32 bits) est affichée dans sa représentation IPv6 (128 bits), avec le préfixe &#039;&#039;::ffff:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
::ffff:192.168.20.22&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On a deux possibilités pour faire le nettoyage :&lt;br /&gt;
*Soit on ajoute les lignes suivantes dans &#039;&#039;AnyEvent.pm&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if (index($reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
   # Remove trailing ip &lt;br /&gt;
   my @fields = split /,/, $reqstate-&amp;gt;{peer_host};&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $fields[0];&lt;br /&gt;
}&lt;br /&gt;
if($reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
   # Remove IPv6 subnet for IPv4&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $1;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*Soit on modifie le filtre /etc/fail2ban/filter.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=.*:?&amp;lt;HOST&amp;gt;,? user=.* msg=.*&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Automatisation ===&lt;br /&gt;
On peut automatiser le processus précédent avec le script suivant, que l&#039;on peut créer dans /root/remoteip_fix.sh :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=bash&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
ANYEVENT_PATH=&amp;quot;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&amp;quot;&lt;br /&gt;
ANYEVENT_REGEX=&#039;$self-&amp;gt;{spiceproxy}&#039;&lt;br /&gt;
TMP_FILE=&amp;quot;/tmp/AnyEvent.pm.tmp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if [ ! -f $ANYEVENT_PATH ]; then&lt;br /&gt;
  echo &amp;quot;$ANYEVENT_PATH does not exists !&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
if [ $(grep &#039;### BUGFIX REMOTE_IP FOR FAIL2BAN ###&#039; $ANYEVENT_PATH | wc -l) -eq 1 ]; then&lt;br /&gt;
  echo &amp;quot;AnyEvent.pm already patched !&amp;quot;&lt;br /&gt;
  exit 0&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
LINE_NUMBER_TOP=$(nl -ba $ANYEVENT_PATH | grep $ANYEVENT_REGEX | head -n 1 | awk -F &#039; &#039; &#039;{print $1}&#039;)&lt;br /&gt;
let LINE_NUMBER_TOP-=1&lt;br /&gt;
&lt;br /&gt;
if [ $LINE_NUMBER_TOP -lt 0 ]; then&lt;br /&gt;
  echo &amp;quot;Did not find the $ANYEVENT_REGEX expr in $ANYEVENT_PATH&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
echo -n &amp;quot;Applying bugfix: &amp;quot;&lt;br /&gt;
trap &amp;quot;rm -f $TMP_FILE&amp;quot; 0 1 2 5 13 15&lt;br /&gt;
head -n $LINE_NUMBER_TOP $ANYEVENT_PATH &amp;gt;$TMP_FILE&lt;br /&gt;
cat &amp;gt;&amp;gt;$TMP_FILE &amp;lt;&amp;lt;EOF&lt;br /&gt;
### BUGFIX REMOTE_IP FOR FAIL2BAN ###&lt;br /&gt;
    if (\$request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
    } elsif (\$request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
    }&lt;br /&gt;
    if (index(\$reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
        my @fields = split /,/, \$reqstate-&amp;gt;{peer_host};&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$fields[0];&lt;br /&gt;
    }&lt;br /&gt;
    if(\$reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
        # Remove IPv6 subnet for IPv4&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$1;&lt;br /&gt;
    }&lt;br /&gt;
#####################################&lt;br /&gt;
EOF&lt;br /&gt;
echo &amp;quot;$ANYEVENT_MODIF&amp;quot; &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cp $ANYEVENT_PATH $ANYEVENT_PATH.ori&lt;br /&gt;
LINE_NUMBER_BOTTOM=$(cat $ANYEVENT_PATH | wc -l)&lt;br /&gt;
let LINE_NUMBER_BOTTOM-=LINE_NUMBER_TOP&lt;br /&gt;
tail -n $LINE_NUMBER_BOTTOM $ANYEVENT_PATH &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cat $TMP_FILE &amp;gt;$ANYEVENT_PATH&lt;br /&gt;
rm -f $TMP_FILE&lt;br /&gt;
trap 0&lt;br /&gt;
echo &amp;quot;done.&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à le rendre exécutable et le lancer :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# chmod +x /root/remoteip_fix.sh&lt;br /&gt;
# /root/remoteip_fix.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne faudra pas oublier de redémarrer &#039;&#039;pveproxy&#039;&#039; pour appliquer les changements !&lt;br /&gt;
&lt;br /&gt;
== Comment bannir derrière un reverse-proxy ? ==&lt;br /&gt;
Maintenant que votre Proxmox est derrière un reverse-proxy, inutile de bannir les IP publiques avec iptables sur le serveur Proxmox, la seule IP visible est celle du reverse-proxy (dans cet exemple 192.168.4.100).&lt;br /&gt;
&lt;br /&gt;
La seule machine capable capable de bannir est le reverse-proxy, il faut donc lui transmettre les IP et nous allons faire ça en trois étapes:&lt;br /&gt;
* la première est de créer une &amp;quot;prison&amp;quot; proxmox sur le fail2ban présent sur le reverse-proxy&lt;br /&gt;
* la deuxième est l&#039;invention d&#039;une API pour fail2ban sur le reverse-proxy&lt;br /&gt;
* la troisième est la modification du comportement de fail2ban pour appeler cette API au lieu de modifier iptables&lt;br /&gt;
&lt;br /&gt;
=== Création d&#039;une prison sur le reverse-proxy ===&lt;br /&gt;
&lt;br /&gt;
Pour bannir nous allons créer une prison spécifique pour le / les serveurs Proxmox que nous allons appeler &#039;&#039;proxmox&#039;&#039; dans le fichier /etc/fail2ban/jail.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[proxmox]&lt;br /&gt;
enabled = true&lt;br /&gt;
port = https,http&lt;br /&gt;
filter = do-nothing&lt;br /&gt;
logpath = /dev/null&lt;br /&gt;
maxretry = 3&lt;br /&gt;
findtime = 1d&lt;br /&gt;
bantime = 1w&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
J&#039;attire votre attention sur les paramètres &#039;&#039;maxretry&#039;&#039;, &#039;&#039;findtime&#039;&#039; et &#039;&#039;bantime&#039;&#039; qui doivent concorder avec ceux du fail2ban de votre Proxmox. S&#039;il sont plus &#039;&#039;court&#039;&#039; sur le reverse-proxy, les IP seront libérées plus tôt à l&#039;inverse, plus long n&#039;est pas gênant, le fail2ban de votre Proxmox les libéreras avant celui du proxy.&lt;br /&gt;
&lt;br /&gt;
Vous avez remarquez le filtre &#039;&#039;do-nothing&#039;&#039; qu&#039;il nous reste à créer dans le fichier &#039;&#039;/etc/fail2ban/filter.d/do-nothing.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
&lt;br /&gt;
failregex = ^&amp;lt;HOST&amp;gt;$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Après redémarrage de fail2ban :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl restart fail2ban&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous devriez voir la prison&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status&lt;br /&gt;
Status&lt;br /&gt;
|- Number of jail:      2&lt;br /&gt;
`- Jail list:   proxmox, sshd&lt;br /&gt;
[root@proxy proxymox]# &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous pouvons maintenant passer à l&#039;API !&lt;br /&gt;
&lt;br /&gt;
=== Invention d&#039;une API pour fail2ban ===&lt;br /&gt;
&lt;br /&gt;
Toujours sur le reverse-proxy nous allons installer PHP pour créer un mini serveur qui répondra au urls suivantes:&lt;br /&gt;
* /ban/&amp;lt;ip&amp;gt; pour bannir&lt;br /&gt;
* /unban/&amp;lt;ip&amp;gt; pour lever le banissement&lt;br /&gt;
&lt;br /&gt;
Commençons par installer PHP:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# dnf -y install php-cli&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un répertoire &amp;quot;f2b-api&amp;quot; dans le dossier &amp;quot;opt&amp;quot; :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# mkdir /opt/f2b-api&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis créer un fichier &#039;&#039;f2b-api.php&#039;&#039; dans ce dossier:&lt;br /&gt;
&amp;lt;source lang=php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
main();&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        # On clean l&#039;uri du / de début&lt;br /&gt;
        $uri = ltrim($_SERVER[&#039;REQUEST_URI&#039;], &#039;/&#039;);&lt;br /&gt;
        # On éclate l&#039;uri en parties (action + ip)&lt;br /&gt;
        $parts = explode(&#039;/&#039;, $uri);&lt;br /&gt;
        # Récupération de l&#039;action dans une variable ou false si vide&lt;br /&gt;
        $action = empty($parts[0]) ? false : $parts[0];&lt;br /&gt;
        # Récupération de l&#039;ip dans une variable ou false si vide&lt;br /&gt;
        $ip = empty($parts[1]) ? false : $parts[1];&lt;br /&gt;
        if(!$action || !$ip){&lt;br /&gt;
                # Si action vide =&amp;gt; 400 Bad request&lt;br /&gt;
                http_response_code(400);&lt;br /&gt;
                die();&lt;br /&gt;
        }&lt;br /&gt;
        if(!in_array($action, [&#039;ban&#039;, &#039;unban&#039;])){&lt;br /&gt;
                # Si action pas dans la liste =&amp;gt; 400 Bad request&lt;br /&gt;
                http_response_code(400);&lt;br /&gt;
                die();&lt;br /&gt;
        }&lt;br /&gt;
        $cmd = &#039;&#039;;&lt;br /&gt;
        if($action == &#039;ban&#039;){&lt;br /&gt;
                $cmd = &#039;fail2ban-client set proxmox banip &#039; . $ip;&lt;br /&gt;
        } else if($action == &#039;unban&#039;){&lt;br /&gt;
                $cmd = &#039;fail2ban-client unban proxmox &#039; . $ip;&lt;br /&gt;
        }&lt;br /&gt;
        shell_exec($cmd);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
[[Fichier:Warning-icon.png|40px]]  Gardez en tête que ce code simpliste n&#039;est en aucun cas sécurisé et ne doit pas être accessible depuis Internet.&lt;br /&gt;
&lt;br /&gt;
Pour démarrer se code en mode serveur il suffit de taper la commande suivante:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# php -S 0.0.0.0:8080 -t /opt/f2b-api /opt/f2b-api/f2b-api.php&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous pouvez tester directement depuis un autre terminal en tapant les commandes:&lt;br /&gt;
* pour bannir :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# curl -X GET http://127.0.0.1:8080/ban/1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* pour dé-bannir :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# curl -X GET http://127.0.0.1:8080/unban/1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Et en vérifiant dans fail2ban:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed: 0&lt;br /&gt;
|  |- Total failed:     0&lt;br /&gt;
|  `- File list:        /dev/null&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned: 1&lt;br /&gt;
   |- Total banned:     10&lt;br /&gt;
   `- Banned IP list:   1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Nous n&#039;allons pas lancer nous même le serveur PHP, nous allons demander à SystemD de le faire et pour cela nous allons créer le fichier &#039;&#039;/opt/f2b-api/f2b-api.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=fail2ban API Server&lt;br /&gt;
After=network-online.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
UMask=007&lt;br /&gt;
ExecStart=php -S 0.0.0.0:8080 -t /opt/f2b-api /opt/f2b-api/f2b-api.php&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faut maintenant demander à SystemD de s&#039;occuper de notre service:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl link /opt/f2b-api/f2b-api.service&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Et de le lancer au démarrage du reverse-proxy:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl enable f2b-api --now&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous pouvons maintenant nous déplacer sur le serveur Proxmox pour modifier fail2ban !&lt;br /&gt;
&lt;br /&gt;
=== Modification des actions fail2ban ===&lt;br /&gt;
Sur le serveur Proxmox nous allons débrayer le comportement de base de fail2ban qui est de modifier iptables. pour cela nous alons créer le fichier &#039;&#039;/etc/fail2ban/action.d/f2b-api.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
actionstart =&lt;br /&gt;
actionstop =&lt;br /&gt;
actioncheck =&lt;br /&gt;
actionban = curl -X GET 192.168.4.100:8080/ban/&amp;lt;ip&amp;gt;&lt;br /&gt;
actionunban = curl -X GET 192.168.4.100:8080/unban/&amp;lt;ip&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Veuillez noter que:&lt;br /&gt;
* même si elles sont vide, les lignes &#039;&#039;actionstart&#039;&#039;, &#039;&#039;actionstop&#039;&#039; et &#039;&#039;actioncheck&#039;&#039; sont obligatoires !&lt;br /&gt;
* l&#039;adresse &#039;&#039;192.168.4.100&#039;&#039; doit être remplcée par celle de votre reverse-proxy&lt;br /&gt;
* &amp;lt;ip&amp;gt; est l&#039;expression utilisée par fail2ban et elle sera remplacée par l&#039;IP à bannir &lt;br /&gt;
&lt;br /&gt;
Pour ce fichier d&#039;action soit pris en compte, il faut modifier le fichier &#039;&#039;/etc/fail2ban/jail.d/proxmox.conf&#039;&#039; pour y ajouter:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
banaction = f2b-api&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne vous reste plus qu&#039;a redémarrer le service fai2ban sur le serveur Proxmox:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl restart fail2ban&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Et vous pouvez tester les commandes suivantes:&lt;br /&gt;
* pour bannir&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client set proxmox banip 1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* pour dé-bannir:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client unban proxmox 1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Et vérifier sur le reverse-proxy que les modification sont bien prises en compte:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed: 0&lt;br /&gt;
|  |- Total failed:     0&lt;br /&gt;
|  `- File list:        /dev/null&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned: 1&lt;br /&gt;
   |- Total banned:     10&lt;br /&gt;
   `- Banned IP list:   1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4420</id>
		<title>Proxmox fail2ban</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4420"/>
		<updated>2026-07-13T09:37:55Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Configuration du reverse-proxy */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
Proxmox utilise une interface web d&#039;administration qui utilise le port TCP 8006 et c&#039;est un vecteur possible d&#039;attaque par force brut. Nous allons donc &#039;&#039;dresser&#039;&#039; fail2ban pour agir en cas d&#039;attaque !&lt;br /&gt;
&lt;br /&gt;
Proxmox utilise Debian, nous allons principalement reproduire les étapes décrites dans le tutoriel de [[Sécuriser_un_service_avec_Fail2ban| Fail2ban pour Rocky]] et adapter à Debian.&lt;br /&gt;
&lt;br /&gt;
Avant d&#039;aller plus loin, assurez-vous d&#039;avoir correctement installé et configuré [[proxmox_iptables |iptables sur Proxmox]]&lt;br /&gt;
&lt;br /&gt;
= Installation =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt -y install fail2ban&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Configuration =&lt;br /&gt;
Tout d&#039;abord il faut copier le fichier &#039;&#039;/etc/fail2ban/jail.conf&#039;&#039; en &#039;&#039;/etc/fail2ban/jail.local&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dans ce fichier, on va s&#039;intéresser aux variables suivantes:&lt;br /&gt;
*ignoreip : correspond à la suite d&#039;adresses IP qui ne se feront jamais bannir;&lt;br /&gt;
*maxretry : correspond au nombre d&#039;essais;&lt;br /&gt;
*findtime : correspond à la période pendant laquelle les essais vont incrémenter maxretry;&lt;br /&gt;
*bantime  : correspond au temps où l&#039;adresse IP ne peut pas se connecter.&lt;br /&gt;
&lt;br /&gt;
= Configuration de base =&lt;br /&gt;
== Choix de la punition ==&lt;br /&gt;
Il faut choisir quelque chose de cohérent (une punition suffisante) pour ne pas permettre de se faire cracker son mot de passe:&lt;br /&gt;
*maxretry = 3&lt;br /&gt;
*findtime = 86400 (correspond à 1 journée)&lt;br /&gt;
*bantime = 604800 (correspond à 1 semaine)&lt;br /&gt;
&lt;br /&gt;
Cela signifie que si une adresse IP se trompe 3 fois en 1 journée (86400s) elle se fait bannir pendant 1 semaine (604800s).&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul permet de trouver le nombre maximal de tentatives durant une année:&lt;br /&gt;
&lt;br /&gt;
365 jours / 7 jours par semaine * 3 tentatives = 156 essais, ce qui reste raisonnable. &lt;br /&gt;
&lt;br /&gt;
Si le pirate possède un [http://fr.wikipedia.org/wiki/Botnet botnet], il faut bien sûr multiplier ce nombre par le nombre de machines dans le botnet...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Attention : fail2ban parcours les logs de connexion pour connaître le numéro de la tentative, ce qui a pour conséquence, si le &#039;&#039;findtime&#039;&#039; est grand, de prendre un certain temps...&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Jail pour SSH ==&lt;br /&gt;
Il suffit d&#039;ajouter la ligne &#039;&#039;enabled=true&#039;&#039; dans la section à activer !&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[sshd]&lt;br /&gt;
&lt;br /&gt;
# To use more aggressive sshd modes set filter parameter &amp;quot;mode&amp;quot; in jail.local:&lt;br /&gt;
# normal (default), ddos, extra or aggressive (combines all).&lt;br /&gt;
# See &amp;quot;tests/files/logs/sshd&amp;quot; or &amp;quot;filter.d/sshd.conf&amp;quot; for usage example and details.&lt;br /&gt;
#mode   = normal&lt;br /&gt;
enabled = true&lt;br /&gt;
port    = ssh&lt;br /&gt;
logpath = %(sshd_log)s&lt;br /&gt;
backend = %(sshd_backend)s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Configuration spécifique =&lt;br /&gt;
== Jail pour PVEPROXY ==&lt;br /&gt;
Pveproxy écoute sur le port 8006 et ne fonctionne pas exactement comme un serveur [[HTTPD | Apache httpd]] qui mettrait ces logs dans le fichier &#039;&#039;error_log&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Nous allons mettre cette configuration spécifique dans le fichier &#039;&#039;/etc/fail2ban/jail.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[proxmox]&lt;br /&gt;
enabled = true&lt;br /&gt;
port = https,http,8006&lt;br /&gt;
filter = proxmox&lt;br /&gt;
backend = systemd&lt;br /&gt;
maxretry = 5&lt;br /&gt;
findtime = 1d&lt;br /&gt;
bantime = 1w&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le backend utilisé est systemd, exactement comme si vous utilisiez la commande :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Filtre pour PVEPROXY ==&lt;br /&gt;
Il ne nous reste plus qu&#039;à spécifier le filtre &#039;&#039;proxmox&#039;&#039; dans le fichier &#039;&#039;/etc/fail2ban/filter.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=&amp;lt;HOST&amp;gt; user=.* msg=.*&lt;br /&gt;
ignoreregex =&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Tests =&lt;br /&gt;
Il faut maintenant tester le filtre et pour ça on peut utiliser un partage de connexion et réaliser le nombre d&#039;échecs spécifié par la directive &amp;quot;maxretry&amp;quot; (ici 3) :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed:	0&lt;br /&gt;
|  |- Total failed:	3&lt;br /&gt;
|  `- Journal matches:	_SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned:	1&lt;br /&gt;
   |- Total banned:	1&lt;br /&gt;
   `- Banned IP list:	37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On voit bien l&#039;IP 37.167.23.159 qui est bannie !&lt;br /&gt;
N&#039;oubliez pas de l&#039;ajouter à &#039;&#039;ignoreip&#039;&#039; dans le fichier &#039;&#039;jails.local&#039;&#039; ou de faire &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client unban 37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Démarrage et enregistrement dans le chargeur de démarrage =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start fail2ban.service&lt;br /&gt;
# systemctl enable fail2ban.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Vous pouvez maintenant démarrer fail2ban&lt;br /&gt;
&lt;br /&gt;
= Proxification=&lt;br /&gt;
Lorsque votre serveur Proxmox se trouve derrière un reverse-proxy (Apache, Nginx, Traefik, ...), au niveau 3 OSI, l&#039;adresse IP du client est remplacée par celle du proxy et le serveur utilise l&#039;entêtes &#039;&#039;X-Forwarded-For&#039;&#039; ou &#039;&#039;X-Real-IP&#039;&#039; pour transporter l&#039;adresse du client &lt;br /&gt;
[[Fichier:Reverse proxy proxmox.png|700px|centré]]&lt;br /&gt;
== Configuration du reverse-proxy ==&lt;br /&gt;
Sur votre reverse-proxy Apache, vous devriez avoir une configuration qui ressemble à ça:&lt;br /&gt;
&amp;lt;source lang=apache&amp;gt;&lt;br /&gt;
MDomain pve.tala-informatique.fr&lt;br /&gt;
&lt;br /&gt;
&amp;lt;VirtualHost *:80&amp;gt;&lt;br /&gt;
    ServerName pve.tala-informatique.fr&lt;br /&gt;
    Redirect / https://pve.tala-informatique.fr/&lt;br /&gt;
&amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;VirtualHost *:443&amp;gt;&lt;br /&gt;
    ServerName pve.tala-informatique.fr&lt;br /&gt;
    &lt;br /&gt;
    SSLEngine on&lt;br /&gt;
    SSLProxyEngine on&lt;br /&gt;
    SSLProxyVerify none &lt;br /&gt;
    SSLProxyCheckPeerCN off&lt;br /&gt;
    SSLProxyCheckPeerName off&lt;br /&gt;
    &lt;br /&gt;
    ProxyRequests off&lt;br /&gt;
    ProxyPreserveHost On&lt;br /&gt;
    &lt;br /&gt;
    RewriteEngine on&lt;br /&gt;
    RewriteCond %{HTTP:Connection} Upgrade [NC]&lt;br /&gt;
    RewriteCond %{HTTP:Upgrade} websocket [NC]&lt;br /&gt;
    RewriteRule ^/?(.*) wss://192.168.4.1:8006/$1 [P,L]&lt;br /&gt;
&lt;br /&gt;
    ProxyPass / https://192.168.4.1:8006/ flushpackets=On connectiontimeout=300 timeout=300&lt;br /&gt;
    ProxyPassReverse / https://192.168.4.1:8006/&lt;br /&gt;
    ProxyTimeout     600&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La première ligne renvoie à la configuration de mod_md abordée dans cette [[Httpd_certificate_security#Let&#039;s_Encrypt |article]] et permet l&#039;obtention du certificat SSL auprès de [https://letsencrypt.org Let&#039;s encrypt]&lt;br /&gt;
&amp;lt;source lang=apache&amp;gt;&lt;br /&gt;
MDomain pve.tala-informatique.fr&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le bloc suivant permet de [[Httpd_redirect_reverse-proxy_mod-rewrite#http_→_https | renvoyer les utilisateurs]] se présentant sur le port 80 vers le port 443&lt;br /&gt;
&amp;lt;source lang=apache&amp;gt;&lt;br /&gt;
&amp;lt;VirtualHost *:80&amp;gt;&lt;br /&gt;
    ServerName pve.tala-informatique.fr&lt;br /&gt;
    Redirect / https://pve.tala-informatique.fr/&lt;br /&gt;
&amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dans le bloc &#039;&#039;443&#039;&#039;, on est obligé de désactiver les vérifications SSL parce que le certificat du serveur Proxmox est autosigné (donc pas de cadenas vert), ce qui pousse Apache à bloquer la connexion si on ne désactive pas ces vérifications&lt;br /&gt;
&amp;lt;source lang=apache&amp;gt;&lt;br /&gt;
SSLProxyVerify none &lt;br /&gt;
SSLProxyCheckPeerCN off&lt;br /&gt;
SSLProxyCheckPeerName off&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
La réécriture d&#039;url doit être configuré pour prendre en compte les &#039;&#039;websockets sécurisées&#039;&#039; (wss) utilisées pour l&#039;affichage de l&#039;écran des machine ou conteneurs avec &#039;&#039;xterm.js&#039;&#039;&lt;br /&gt;
&amp;lt;source lang=apache&amp;gt;&lt;br /&gt;
RewriteEngine on&lt;br /&gt;
RewriteCond %{HTTP:Connection} Upgrade [NC]&lt;br /&gt;
RewriteCond %{HTTP:Upgrade} websocket [NC]&lt;br /&gt;
RewriteRule ^/?(.*) wss://192.168.4.1:8006/$1 [P,L]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Enfin on redirige les requêtes vers le serveur Proxmox en n&#039;oubliant pas de préciser le port 8006&lt;br /&gt;
&amp;lt;source lang=apache&amp;gt;&lt;br /&gt;
ProxyPass / https://192.168.4.1:8006/ flushpackets=On connectiontimeout=300 timeout=300&lt;br /&gt;
ProxyPassReverse / https://192.168.4.1:8006/&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le problème est que la seule adresse que fail2ban va voir apparaître dans les logs est celle du reverse-proxy (&#039;&#039;192.168.4.100&#039;&#039;) :&lt;br /&gt;
[[Fichier:Reverse proxy ip logs.png|600px|centré]]&lt;br /&gt;
Même si le filtre &#039;&#039;fail2ban&#039;&#039; est configuré pour utiliser la commande &#039;&#039;journactl&#039;&#039; sur le démon &#039;&#039;pvedaemon&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
les adresses viennent de pveproxy qui journalise tout dans &#039;&#039;/var/log/pveproxy/access.log&#039;&#039; et &#039;&#039;pvedaemon&#039;&#039; ne journalise que les échecs d&#039;authentification. &lt;br /&gt;
Il est donc plus simple de faire un &#039;&#039;tail&#039;&#039; ou un &#039;&#039;cat&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Que d&#039;utiliser &#039;&#039;journalctl&#039;&#039; pour voir les IPs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
Dec 14 10:43:01 labo unix_chkpwd[1326506]: password check failed for user (root)&lt;br /&gt;
Dec 14 10:43:01 labo IPCC.xs[1320783]: pam_unix(proxmox-ve-auth:auth): authentication failure; logname= uid=0 euid=0 tty= ruser= rhost=37.167.23.159  user=root&lt;br /&gt;
Dec 14 10:43:03 labo pvedaemon[1320783]: authentication failure; rhost=37.167.23.159 user=root@pam msg=Authentication failure&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Configuration de pveproxy ==&lt;br /&gt;
Si on veut voir l&#039;adresse du client, il faut dire au [https://fr.wikipedia.org/wiki/Daemon_(informatique)| démon] &#039;&#039;pveproxy&#039;&#039; d&#039;utiliser l&#039;une des deux entêtes précédentes ainsi que préciser l&#039;adresse du proxy. &lt;br /&gt;
&lt;br /&gt;
Préciser l&#039;adresse du proxy est essentiel pour que &#039;&#039;pveproxy&#039;&#039; n&#039;accepte de lire l&#039;adresse du client présente dans l&#039;entête &#039;&#039;&#039;uniquement&#039;&#039;&#039; si cela provient du proxy, qui est une machine de confiance. Le cas contraire, tout le monde pourrait ajouter une adresse IP dans l&#039;entête pour la faire bannir...&lt;br /&gt;
&lt;br /&gt;
Nous allons créer le fichier &#039;&#039;/etc/default/pveproxy&#039;&#039; avec les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Forwarded-For&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Real-IP&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_ALLOW_FROM=&amp;quot;192.168.4.100&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il faut maintenant redémarrer &#039;&#039;pveproxy&#039;&#039; pour que les changements s&#039;appliquent. Si vous êtes connecté via l&#039;interface web, cela va vous déconnecter, le temps que le démon redémarre, il faudra ensuite certainement rafraîchir la page web.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl restart pveproxy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à vérifier dans les logs si les bonnes adresses s&#039;affichent:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Si jamais ce n&#039;est pas le cas, poursuivez avec la modification du fichier &#039;&#039;AnyEvent.pm&#039;&#039;&lt;br /&gt;
== Modification de AnyEvent.pm ==&lt;br /&gt;
=== Application de la modification ===&lt;br /&gt;
Au jour d&#039;aujourd&#039;hui (13/12/25) la proxification ne fonctionne plus et il faut apporter une modification dans le fichier &#039;&#039;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&#039;&#039; pour que les bonnes adresses apparaissent !&lt;br /&gt;
En fonction des versions cette modification peut avoir lieu soit ligne &#039;&#039;&#039;1504&#039;&#039;&#039;, soit ligne &#039;&#039;&#039;1554&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Il faut repérer la fonction suivante:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
sub authenticate_and_handle_request {&lt;br /&gt;
    my ($self, $reqstate) = @_;&lt;br /&gt;
&lt;br /&gt;
    my $request = $reqstate-&amp;gt;{request};&lt;br /&gt;
    my $method = $request-&amp;gt;method();&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
C&#039;est un peu plus loin qu&#039;il faut insérer le code :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 ### INSERTION ICI ###&lt;br /&gt;
&lt;br /&gt;
    if ($self-&amp;gt;{spiceproxy}) {&lt;br /&gt;
        my $connect_str = $request-&amp;gt;header(&#039;Host&#039;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il faut modifier l&#039;attribut &#039;&#039;peer_host&#039;&#039; de l&#039;objet &#039;&#039;reqstate&#039;&#039; si l&#039;une des deux entêtes est présente :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if ($request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
} elsif ($request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Double IPv4 ou préfixe IPv6 ===&lt;br /&gt;
Après redémarrage, cela permet de voir l&#039;adresse du client dans les logs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/ext-all.js?ver=7.0.0 HTTP/1.1&amp;quot; 200 683505&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/js/u2f-api.js HTTP/1.1&amp;quot; 200 4898&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/resources HTTP/1.1&amp;quot; 200 1226&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/tasks HTTP/1.1&amp;quot; 200 1090&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /proxmoxlib.js?ver=v5.0.4-t1754316706 HTTP/1.1&amp;quot; 200 157086&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/theme-crisp/resources/theme-crisp-all_1.css HTTP/1.1&amp;quot; 200 32919&lt;br /&gt;
::ffff:192.168.20.22 - root@pam [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/nodes/labo/lxc/100/status/current HTTP/1.1&amp;quot; 200 523&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il nous reste un peu de nettoyage à faire, dans certains cas :&lt;br /&gt;
* l&#039;adresse apparaît non pas une fois mais deux, séparées par une virgule&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
37.167.182.207, 37.167.182.207&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* l&#039;adresse IPv4 (32 bits) est affichée dans sa représentation IPv6 (128 bits), avec le préfixe &#039;&#039;::ffff:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
::ffff:192.168.20.22&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On a deux possibilités pour faire le nettoyage :&lt;br /&gt;
*Soit on ajoute les lignes suivantes dans &#039;&#039;AnyEvent.pm&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if (index($reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
   # Remove trailing ip &lt;br /&gt;
   my @fields = split /,/, $reqstate-&amp;gt;{peer_host};&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $fields[0];&lt;br /&gt;
}&lt;br /&gt;
if($reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
   # Remove IPv6 subnet for IPv4&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $1;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*Soit on modifie le filtre /etc/fail2ban/filter.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=.*:?&amp;lt;HOST&amp;gt;,? user=.* msg=.*&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Automatisation ===&lt;br /&gt;
On peut automatiser le processus précédent avec le script suivant, que l&#039;on peut créer dans /root/remoteip_fix.sh :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=bash&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
ANYEVENT_PATH=&amp;quot;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&amp;quot;&lt;br /&gt;
ANYEVENT_REGEX=&#039;$self-&amp;gt;{spiceproxy}&#039;&lt;br /&gt;
TMP_FILE=&amp;quot;/tmp/AnyEvent.pm.tmp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if [ ! -f $ANYEVENT_PATH ]; then&lt;br /&gt;
  echo &amp;quot;$ANYEVENT_PATH does not exists !&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
if [ $(grep &#039;### BUGFIX REMOTE_IP FOR FAIL2BAN ###&#039; $ANYEVENT_PATH | wc -l) -eq 1 ]; then&lt;br /&gt;
  echo &amp;quot;AnyEvent.pm already patched !&amp;quot;&lt;br /&gt;
  exit 0&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
LINE_NUMBER_TOP=$(nl -ba $ANYEVENT_PATH | grep $ANYEVENT_REGEX | head -n 1 | awk -F &#039; &#039; &#039;{print $1}&#039;)&lt;br /&gt;
let LINE_NUMBER_TOP-=1&lt;br /&gt;
&lt;br /&gt;
if [ $LINE_NUMBER_TOP -lt 0 ]; then&lt;br /&gt;
  echo &amp;quot;Did not find the $ANYEVENT_REGEX expr in $ANYEVENT_PATH&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
echo -n &amp;quot;Applying bugfix: &amp;quot;&lt;br /&gt;
trap &amp;quot;rm -f $TMP_FILE&amp;quot; 0 1 2 5 13 15&lt;br /&gt;
head -n $LINE_NUMBER_TOP $ANYEVENT_PATH &amp;gt;$TMP_FILE&lt;br /&gt;
cat &amp;gt;&amp;gt;$TMP_FILE &amp;lt;&amp;lt;EOF&lt;br /&gt;
### BUGFIX REMOTE_IP FOR FAIL2BAN ###&lt;br /&gt;
    if (\$request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
    } elsif (\$request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
    }&lt;br /&gt;
    if (index(\$reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
        my @fields = split /,/, \$reqstate-&amp;gt;{peer_host};&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$fields[0];&lt;br /&gt;
    }&lt;br /&gt;
    if(\$reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
        # Remove IPv6 subnet for IPv4&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$1;&lt;br /&gt;
    }&lt;br /&gt;
#####################################&lt;br /&gt;
EOF&lt;br /&gt;
echo &amp;quot;$ANYEVENT_MODIF&amp;quot; &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cp $ANYEVENT_PATH $ANYEVENT_PATH.ori&lt;br /&gt;
LINE_NUMBER_BOTTOM=$(cat $ANYEVENT_PATH | wc -l)&lt;br /&gt;
let LINE_NUMBER_BOTTOM-=LINE_NUMBER_TOP&lt;br /&gt;
tail -n $LINE_NUMBER_BOTTOM $ANYEVENT_PATH &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cat $TMP_FILE &amp;gt;$ANYEVENT_PATH&lt;br /&gt;
rm -f $TMP_FILE&lt;br /&gt;
trap 0&lt;br /&gt;
echo &amp;quot;done.&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à le rendre exécutable et le lancer :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# chmod +x /root/remoteip_fix.sh&lt;br /&gt;
# /root/remoteip_fix.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne faudra pas oublier de redémarrer &#039;&#039;pveproxy&#039;&#039; pour appliquer les changements !&lt;br /&gt;
&lt;br /&gt;
== Comment bannir derrière un reverse-proxy ? ==&lt;br /&gt;
Maintenant que votre Proxmox est derrière un reverse-proxy, inutile de bannir les IP publiques avec iptables sur le serveur Proxmox, la seule IP visible est celle du reverse-proxy (dans cet exemple 192.168.4.100).&lt;br /&gt;
&lt;br /&gt;
La seule machine capable capable de bannir est le reverse-proxy, il faut donc lui transmettre les IP et nous allons faire ça en trois étapes:&lt;br /&gt;
* la première est de créer une &amp;quot;prison&amp;quot; proxmox sur le fail2ban présent sur le reverse-proxy&lt;br /&gt;
* la deuxième est l&#039;invention d&#039;une API pour fail2ban sur le reverse-proxy&lt;br /&gt;
* la troisième est la modification du comportement de fail2ban pour appeler cette API au lieu de modifier iptables&lt;br /&gt;
&lt;br /&gt;
=== Création d&#039;une prison sur le reverse-proxy ===&lt;br /&gt;
&lt;br /&gt;
Pour bannir nous allons créer une prison spécifique pour le / les serveurs Proxmox que nous allons appeler &#039;&#039;proxmox&#039;&#039; dans le fichier /etc/fail2ban/jail.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[proxmox]&lt;br /&gt;
enabled = true&lt;br /&gt;
port = https,http&lt;br /&gt;
filter = do-nothing&lt;br /&gt;
logpath = /dev/null&lt;br /&gt;
maxretry = 3&lt;br /&gt;
findtime = 1d&lt;br /&gt;
bantime = 1w&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
J&#039;attire votre attention sur les paramètres &#039;&#039;maxretry&#039;&#039;, &#039;&#039;findtime&#039;&#039; et &#039;&#039;bantime&#039;&#039; qui doivent concorder avec ceux du fail2ban de votre Proxmox. S&#039;il sont plus &#039;&#039;court&#039;&#039; sur le reverse-proxy, les IP seront libérées plus tôt à l&#039;inverse, plus long n&#039;est pas gênant, le fail2ban de votre Proxmox les libéreras avant celui du proxy.&lt;br /&gt;
&lt;br /&gt;
Vous avez remarquez le filtre &#039;&#039;do-nothing&#039;&#039; qu&#039;il nous reste à créer dans le fichier &#039;&#039;/etc/fail2ban/filter.d/do-nothing.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
&lt;br /&gt;
failregex = ^&amp;lt;HOST&amp;gt;$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Après redémarrage de fail2ban :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl restart fail2ban&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous devriez voir la prison&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status&lt;br /&gt;
Status&lt;br /&gt;
|- Number of jail:      2&lt;br /&gt;
`- Jail list:   proxmox, sshd&lt;br /&gt;
[root@proxy proxymox]# &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous pouvons maintenant passer à l&#039;API !&lt;br /&gt;
&lt;br /&gt;
=== Invention d&#039;une API pour fail2ban ===&lt;br /&gt;
&lt;br /&gt;
Toujours sur le reverse-proxy nous allons installer PHP pour créer un mini serveur qui répondra au urls suivantes:&lt;br /&gt;
* /ban/&amp;lt;ip&amp;gt; pour bannir&lt;br /&gt;
* /unban/&amp;lt;ip&amp;gt; pour lever le banissement&lt;br /&gt;
&lt;br /&gt;
Commençons par installer PHP:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# dnf -y install php-cli&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un répertoire &amp;quot;f2b-api&amp;quot; dans le dossier &amp;quot;opt&amp;quot; :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# mkdir /opt/f2b-api&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis créer un fichier &#039;&#039;f2b-api.php&#039;&#039; dans ce dossier:&lt;br /&gt;
&amp;lt;source lang=php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
main();&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        # On clean l&#039;uri du / de début&lt;br /&gt;
        $uri = ltrim($_SERVER[&#039;REQUEST_URI&#039;], &#039;/&#039;);&lt;br /&gt;
        # On éclate l&#039;uri en parties (action + ip)&lt;br /&gt;
        $parts = explode(&#039;/&#039;, $uri);&lt;br /&gt;
        # Récupération de l&#039;action dans une variable ou false si vide&lt;br /&gt;
        $action = empty($parts[0]) ? false : $parts[0];&lt;br /&gt;
        # Récupération de l&#039;ip dans une variable ou false si vide&lt;br /&gt;
        $ip = empty($parts[1]) ? false : $parts[1];&lt;br /&gt;
        if(!$action || !$ip){&lt;br /&gt;
                # Si action vide =&amp;gt; 400 Bad request&lt;br /&gt;
                http_response_code(400);&lt;br /&gt;
                die();&lt;br /&gt;
        }&lt;br /&gt;
        if(!in_array($action, [&#039;ban&#039;, &#039;unban&#039;])){&lt;br /&gt;
                # Si action pas dans la liste =&amp;gt; 400 Bad request&lt;br /&gt;
                http_response_code(400);&lt;br /&gt;
                die();&lt;br /&gt;
        }&lt;br /&gt;
        $cmd = &#039;&#039;;&lt;br /&gt;
        if($action == &#039;ban&#039;){&lt;br /&gt;
                $cmd = &#039;fail2ban-client set proxmox banip &#039; . $ip;&lt;br /&gt;
        } else if($action == &#039;unban&#039;){&lt;br /&gt;
                $cmd = &#039;fail2ban-client unban proxmox &#039; . $ip;&lt;br /&gt;
        }&lt;br /&gt;
        shell_exec($cmd);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
[[Fichier:Warning-icon.png|40px]]  Gardez en tête que ce code simpliste n&#039;est en aucun cas sécurisé et ne doit pas être accessible depuis Internet.&lt;br /&gt;
&lt;br /&gt;
Pour démarrer se code en mode serveur il suffit de taper la commande suivante:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# php -S 0.0.0.0:8080 -t /opt/f2b-api /opt/f2b-api/f2b-api.php&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous pouvez tester directement depuis un autre terminal en tapant les commandes:&lt;br /&gt;
* pour bannir :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# curl -X GET http://127.0.0.1:8080/ban/1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* pour dé-bannir :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# curl -X GET http://127.0.0.1:8080/unban/1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Et en vérifiant dans fail2ban:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed: 0&lt;br /&gt;
|  |- Total failed:     0&lt;br /&gt;
|  `- File list:        /dev/null&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned: 1&lt;br /&gt;
   |- Total banned:     10&lt;br /&gt;
   `- Banned IP list:   1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Nous n&#039;allons pas lancer nous même le serveur PHP, nous allons demander à SystemD de le faire et pour cela nous allons créer le fichier &#039;&#039;/opt/f2b-api/f2b-api.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=fail2ban API Server&lt;br /&gt;
After=network-online.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
UMask=007&lt;br /&gt;
ExecStart=php -S 0.0.0.0:8080 -t /opt/f2b-api /opt/f2b-api/f2b-api.php&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faut maintenant demander à SystemD de s&#039;occuper de notre service:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl link /opt/f2b-api/f2b-api.service&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Et de le lancer au démarrage du reverse-proxy:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl enable f2b-api --now&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous pouvons maintenant nous déplacer sur le serveur Proxmox pour modifier fail2ban !&lt;br /&gt;
&lt;br /&gt;
=== Modification des actions fail2ban ===&lt;br /&gt;
Sur le serveur Proxmox nous allons débrayer le comportement de base de fail2ban qui est de modifier iptables. pour cela nous alons créer le fichier &#039;&#039;/etc/fail2ban/action.d/f2b-api.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
actionstart =&lt;br /&gt;
actionstop =&lt;br /&gt;
actioncheck =&lt;br /&gt;
actionban = curl -X GET 192.168.4.100:8080/ban/&amp;lt;ip&amp;gt;&lt;br /&gt;
actionunban = curl -X GET 192.168.4.100:8080/unban/&amp;lt;ip&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Veuillez noter que:&lt;br /&gt;
* même si elles sont vide, les lignes &#039;&#039;actionstart&#039;&#039;, &#039;&#039;actionstop&#039;&#039; et &#039;&#039;actioncheck&#039;&#039; sont obligatoires !&lt;br /&gt;
* l&#039;adresse &#039;&#039;192.168.4.100&#039;&#039; doit être remplcée par celle de votre reverse-proxy&lt;br /&gt;
* &amp;lt;ip&amp;gt; est l&#039;expression utilisée par fail2ban et elle sera remplacée par l&#039;IP à bannir &lt;br /&gt;
&lt;br /&gt;
Pour ce fichier d&#039;action soit pris en compte, il faut modifier le fichier &#039;&#039;/etc/fail2ban/jail.d/proxmox.conf&#039;&#039; pour y ajouter:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
banaction = f2b-api&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne vous reste plus qu&#039;a redémarrer le service fai2ban sur le serveur Proxmox:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl restart fail2ban&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Et vous pouvez tester les commandes suivantes:&lt;br /&gt;
* pour bannir&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client set proxmox banip 1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* pour dé-bannir:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client unban proxmox 1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Et vérifier sur le reverse-proxy que les modification sont bien prises en compte:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed: 0&lt;br /&gt;
|  |- Total failed:     0&lt;br /&gt;
|  `- File list:        /dev/null&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned: 1&lt;br /&gt;
   |- Total banned:     10&lt;br /&gt;
   `- Banned IP list:   1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4419</id>
		<title>Proxmox fail2ban</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4419"/>
		<updated>2026-07-13T09:36:25Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Configuration du reverse-proxy */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
Proxmox utilise une interface web d&#039;administration qui utilise le port TCP 8006 et c&#039;est un vecteur possible d&#039;attaque par force brut. Nous allons donc &#039;&#039;dresser&#039;&#039; fail2ban pour agir en cas d&#039;attaque !&lt;br /&gt;
&lt;br /&gt;
Proxmox utilise Debian, nous allons principalement reproduire les étapes décrites dans le tutoriel de [[Sécuriser_un_service_avec_Fail2ban| Fail2ban pour Rocky]] et adapter à Debian.&lt;br /&gt;
&lt;br /&gt;
Avant d&#039;aller plus loin, assurez-vous d&#039;avoir correctement installé et configuré [[proxmox_iptables |iptables sur Proxmox]]&lt;br /&gt;
&lt;br /&gt;
= Installation =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt -y install fail2ban&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Configuration =&lt;br /&gt;
Tout d&#039;abord il faut copier le fichier &#039;&#039;/etc/fail2ban/jail.conf&#039;&#039; en &#039;&#039;/etc/fail2ban/jail.local&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dans ce fichier, on va s&#039;intéresser aux variables suivantes:&lt;br /&gt;
*ignoreip : correspond à la suite d&#039;adresses IP qui ne se feront jamais bannir;&lt;br /&gt;
*maxretry : correspond au nombre d&#039;essais;&lt;br /&gt;
*findtime : correspond à la période pendant laquelle les essais vont incrémenter maxretry;&lt;br /&gt;
*bantime  : correspond au temps où l&#039;adresse IP ne peut pas se connecter.&lt;br /&gt;
&lt;br /&gt;
= Configuration de base =&lt;br /&gt;
== Choix de la punition ==&lt;br /&gt;
Il faut choisir quelque chose de cohérent (une punition suffisante) pour ne pas permettre de se faire cracker son mot de passe:&lt;br /&gt;
*maxretry = 3&lt;br /&gt;
*findtime = 86400 (correspond à 1 journée)&lt;br /&gt;
*bantime = 604800 (correspond à 1 semaine)&lt;br /&gt;
&lt;br /&gt;
Cela signifie que si une adresse IP se trompe 3 fois en 1 journée (86400s) elle se fait bannir pendant 1 semaine (604800s).&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul permet de trouver le nombre maximal de tentatives durant une année:&lt;br /&gt;
&lt;br /&gt;
365 jours / 7 jours par semaine * 3 tentatives = 156 essais, ce qui reste raisonnable. &lt;br /&gt;
&lt;br /&gt;
Si le pirate possède un [http://fr.wikipedia.org/wiki/Botnet botnet], il faut bien sûr multiplier ce nombre par le nombre de machines dans le botnet...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Attention : fail2ban parcours les logs de connexion pour connaître le numéro de la tentative, ce qui a pour conséquence, si le &#039;&#039;findtime&#039;&#039; est grand, de prendre un certain temps...&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Jail pour SSH ==&lt;br /&gt;
Il suffit d&#039;ajouter la ligne &#039;&#039;enabled=true&#039;&#039; dans la section à activer !&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[sshd]&lt;br /&gt;
&lt;br /&gt;
# To use more aggressive sshd modes set filter parameter &amp;quot;mode&amp;quot; in jail.local:&lt;br /&gt;
# normal (default), ddos, extra or aggressive (combines all).&lt;br /&gt;
# See &amp;quot;tests/files/logs/sshd&amp;quot; or &amp;quot;filter.d/sshd.conf&amp;quot; for usage example and details.&lt;br /&gt;
#mode   = normal&lt;br /&gt;
enabled = true&lt;br /&gt;
port    = ssh&lt;br /&gt;
logpath = %(sshd_log)s&lt;br /&gt;
backend = %(sshd_backend)s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Configuration spécifique =&lt;br /&gt;
== Jail pour PVEPROXY ==&lt;br /&gt;
Pveproxy écoute sur le port 8006 et ne fonctionne pas exactement comme un serveur [[HTTPD | Apache httpd]] qui mettrait ces logs dans le fichier &#039;&#039;error_log&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Nous allons mettre cette configuration spécifique dans le fichier &#039;&#039;/etc/fail2ban/jail.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[proxmox]&lt;br /&gt;
enabled = true&lt;br /&gt;
port = https,http,8006&lt;br /&gt;
filter = proxmox&lt;br /&gt;
backend = systemd&lt;br /&gt;
maxretry = 5&lt;br /&gt;
findtime = 1d&lt;br /&gt;
bantime = 1w&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le backend utilisé est systemd, exactement comme si vous utilisiez la commande :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Filtre pour PVEPROXY ==&lt;br /&gt;
Il ne nous reste plus qu&#039;à spécifier le filtre &#039;&#039;proxmox&#039;&#039; dans le fichier &#039;&#039;/etc/fail2ban/filter.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=&amp;lt;HOST&amp;gt; user=.* msg=.*&lt;br /&gt;
ignoreregex =&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Tests =&lt;br /&gt;
Il faut maintenant tester le filtre et pour ça on peut utiliser un partage de connexion et réaliser le nombre d&#039;échecs spécifié par la directive &amp;quot;maxretry&amp;quot; (ici 3) :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed:	0&lt;br /&gt;
|  |- Total failed:	3&lt;br /&gt;
|  `- Journal matches:	_SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned:	1&lt;br /&gt;
   |- Total banned:	1&lt;br /&gt;
   `- Banned IP list:	37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On voit bien l&#039;IP 37.167.23.159 qui est bannie !&lt;br /&gt;
N&#039;oubliez pas de l&#039;ajouter à &#039;&#039;ignoreip&#039;&#039; dans le fichier &#039;&#039;jails.local&#039;&#039; ou de faire &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client unban 37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Démarrage et enregistrement dans le chargeur de démarrage =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start fail2ban.service&lt;br /&gt;
# systemctl enable fail2ban.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Vous pouvez maintenant démarrer fail2ban&lt;br /&gt;
&lt;br /&gt;
= Proxification=&lt;br /&gt;
Lorsque votre serveur Proxmox se trouve derrière un reverse-proxy (Apache, Nginx, Traefik, ...), au niveau 3 OSI, l&#039;adresse IP du client est remplacée par celle du proxy et le serveur utilise l&#039;entêtes &#039;&#039;X-Forwarded-For&#039;&#039; ou &#039;&#039;X-Real-IP&#039;&#039; pour transporter l&#039;adresse du client &lt;br /&gt;
[[Fichier:Reverse proxy proxmox.png|700px|centré]]&lt;br /&gt;
== Configuration du reverse-proxy ==&lt;br /&gt;
Sur votre reverse-proxy Apache, vous devriez avoir une configuration qui ressemble à ça:&lt;br /&gt;
&amp;lt;source lang=apache&amp;gt;&lt;br /&gt;
MDomain pve.tala-informatique.fr&lt;br /&gt;
&lt;br /&gt;
&amp;lt;VirtualHost *:80&amp;gt;&lt;br /&gt;
    ServerName pve.tala-informatique.fr&lt;br /&gt;
    Redirect / https://pve.tala-informatique.fr/&lt;br /&gt;
&amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;VirtualHost *:443&amp;gt;&lt;br /&gt;
    ServerName pve.tala-informatique.fr&lt;br /&gt;
    &lt;br /&gt;
    SSLEngine on&lt;br /&gt;
    SSLProxyEngine on&lt;br /&gt;
    SSLProxyVerify none &lt;br /&gt;
    SSLProxyCheckPeerCN off&lt;br /&gt;
    SSLProxyCheckPeerName off&lt;br /&gt;
    &lt;br /&gt;
    ProxyRequests off&lt;br /&gt;
    ProxyPreserveHost On&lt;br /&gt;
    &lt;br /&gt;
    RewriteEngine on&lt;br /&gt;
    RewriteCond %{HTTP:Connection} Upgrade [NC]&lt;br /&gt;
    RewriteCond %{HTTP:Upgrade} websocket [NC]&lt;br /&gt;
    RewriteRule ^/?(.*) wss://192.168.4.1:8006/$1 [P,L]&lt;br /&gt;
&lt;br /&gt;
    ProxyPass / https://192.168.4.1:8006/ flushpackets=On connectiontimeout=300 timeout=300&lt;br /&gt;
    ProxyPassReverse / https://192.168.4.1:8006/&lt;br /&gt;
    ProxyTimeout     600&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La première ligne renvoie à la configuration de [[Httpd_certificate_security#Let&#039;s_Encrypt |mod_md]] sur mon site et permet l&#039;obtention du certificat SSL auprès de [https://letsencrypt.org Let&#039;s encrypt]&lt;br /&gt;
&amp;lt;source lang=apache&amp;gt;&lt;br /&gt;
MDomain pve.tala-informatique.fr&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le bloc suivant permet de [[Httpd_redirect_reverse-proxy_mod-rewrite#http_→_https | renvoyer les utilisateurs]] se présentant sur le port 80 vers le port 443&lt;br /&gt;
&amp;lt;source lang=apache&amp;gt;&lt;br /&gt;
&amp;lt;VirtualHost *:80&amp;gt;&lt;br /&gt;
    ServerName pve.tala-informatique.fr&lt;br /&gt;
    Redirect / https://pve.tala-informatique.fr/&lt;br /&gt;
&amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dans le bloc &#039;&#039;443&#039;&#039;, on est obligé de désactiver les vérifications SSL parce que le certificat du serveur Proxmox est autosigné, ce qui pousse Apache à bloquer la connexion si on ne désactive pas les vérifications&lt;br /&gt;
&amp;lt;source lang=apache&amp;gt;&lt;br /&gt;
SSLProxyVerify none &lt;br /&gt;
SSLProxyCheckPeerCN off&lt;br /&gt;
SSLProxyCheckPeerName off&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
La réécriture d&#039;url doit être configuré pour prendre en compte les &#039;&#039;websockets sécurisées&#039;&#039; (wss) utilisées pour l&#039;affichage de l&#039;écran des machine ou conteneurs avec &#039;&#039;xterm.js&#039;&#039;&lt;br /&gt;
&amp;lt;source lang=apache&amp;gt;&lt;br /&gt;
RewriteEngine on&lt;br /&gt;
RewriteCond %{HTTP:Connection} Upgrade [NC]&lt;br /&gt;
RewriteCond %{HTTP:Upgrade} websocket [NC]&lt;br /&gt;
RewriteRule ^/?(.*) wss://192.168.4.1:8006/$1 [P,L]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Enfin on redirige les requêtes vers le serveur Proxmox en n&#039;oubliant pas de préciser le port 8006&lt;br /&gt;
&amp;lt;source lang=apache&amp;gt;&lt;br /&gt;
ProxyPass / https://192.168.4.1:8006/ flushpackets=On connectiontimeout=300 timeout=300&lt;br /&gt;
ProxyPassReverse / https://192.168.4.1:8006/&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le problème est que la seule adresse que fail2ban va voir apparaître dans les logs est celle du reverse-proxy (&#039;&#039;192.168.4.100&#039;&#039;) :&lt;br /&gt;
[[Fichier:Reverse proxy ip logs.png|600px|centré]]&lt;br /&gt;
Même si le filtre &#039;&#039;fail2ban&#039;&#039; est configuré pour utiliser la commande &#039;&#039;journactl&#039;&#039; sur le démon &#039;&#039;pvedaemon&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
les adresses viennent de pveproxy qui journalise tout dans &#039;&#039;/var/log/pveproxy/access.log&#039;&#039; et &#039;&#039;pvedaemon&#039;&#039; ne journalise que les échecs d&#039;authentification. &lt;br /&gt;
Il est donc plus simple de faire un &#039;&#039;tail&#039;&#039; ou un &#039;&#039;cat&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Que d&#039;utiliser &#039;&#039;journalctl&#039;&#039; pour voir les IPs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
Dec 14 10:43:01 labo unix_chkpwd[1326506]: password check failed for user (root)&lt;br /&gt;
Dec 14 10:43:01 labo IPCC.xs[1320783]: pam_unix(proxmox-ve-auth:auth): authentication failure; logname= uid=0 euid=0 tty= ruser= rhost=37.167.23.159  user=root&lt;br /&gt;
Dec 14 10:43:03 labo pvedaemon[1320783]: authentication failure; rhost=37.167.23.159 user=root@pam msg=Authentication failure&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Configuration de pveproxy ==&lt;br /&gt;
Si on veut voir l&#039;adresse du client, il faut dire au [https://fr.wikipedia.org/wiki/Daemon_(informatique)| démon] &#039;&#039;pveproxy&#039;&#039; d&#039;utiliser l&#039;une des deux entêtes précédentes ainsi que préciser l&#039;adresse du proxy. &lt;br /&gt;
&lt;br /&gt;
Préciser l&#039;adresse du proxy est essentiel pour que &#039;&#039;pveproxy&#039;&#039; n&#039;accepte de lire l&#039;adresse du client présente dans l&#039;entête &#039;&#039;&#039;uniquement&#039;&#039;&#039; si cela provient du proxy, qui est une machine de confiance. Le cas contraire, tout le monde pourrait ajouter une adresse IP dans l&#039;entête pour la faire bannir...&lt;br /&gt;
&lt;br /&gt;
Nous allons créer le fichier &#039;&#039;/etc/default/pveproxy&#039;&#039; avec les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Forwarded-For&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Real-IP&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_ALLOW_FROM=&amp;quot;192.168.4.100&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il faut maintenant redémarrer &#039;&#039;pveproxy&#039;&#039; pour que les changements s&#039;appliquent. Si vous êtes connecté via l&#039;interface web, cela va vous déconnecter, le temps que le démon redémarre, il faudra ensuite certainement rafraîchir la page web.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl restart pveproxy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à vérifier dans les logs si les bonnes adresses s&#039;affichent:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Si jamais ce n&#039;est pas le cas, poursuivez avec la modification du fichier &#039;&#039;AnyEvent.pm&#039;&#039;&lt;br /&gt;
== Modification de AnyEvent.pm ==&lt;br /&gt;
=== Application de la modification ===&lt;br /&gt;
Au jour d&#039;aujourd&#039;hui (13/12/25) la proxification ne fonctionne plus et il faut apporter une modification dans le fichier &#039;&#039;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&#039;&#039; pour que les bonnes adresses apparaissent !&lt;br /&gt;
En fonction des versions cette modification peut avoir lieu soit ligne &#039;&#039;&#039;1504&#039;&#039;&#039;, soit ligne &#039;&#039;&#039;1554&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Il faut repérer la fonction suivante:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
sub authenticate_and_handle_request {&lt;br /&gt;
    my ($self, $reqstate) = @_;&lt;br /&gt;
&lt;br /&gt;
    my $request = $reqstate-&amp;gt;{request};&lt;br /&gt;
    my $method = $request-&amp;gt;method();&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
C&#039;est un peu plus loin qu&#039;il faut insérer le code :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 ### INSERTION ICI ###&lt;br /&gt;
&lt;br /&gt;
    if ($self-&amp;gt;{spiceproxy}) {&lt;br /&gt;
        my $connect_str = $request-&amp;gt;header(&#039;Host&#039;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il faut modifier l&#039;attribut &#039;&#039;peer_host&#039;&#039; de l&#039;objet &#039;&#039;reqstate&#039;&#039; si l&#039;une des deux entêtes est présente :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if ($request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
} elsif ($request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Double IPv4 ou préfixe IPv6 ===&lt;br /&gt;
Après redémarrage, cela permet de voir l&#039;adresse du client dans les logs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/ext-all.js?ver=7.0.0 HTTP/1.1&amp;quot; 200 683505&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/js/u2f-api.js HTTP/1.1&amp;quot; 200 4898&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/resources HTTP/1.1&amp;quot; 200 1226&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/tasks HTTP/1.1&amp;quot; 200 1090&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /proxmoxlib.js?ver=v5.0.4-t1754316706 HTTP/1.1&amp;quot; 200 157086&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/theme-crisp/resources/theme-crisp-all_1.css HTTP/1.1&amp;quot; 200 32919&lt;br /&gt;
::ffff:192.168.20.22 - root@pam [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/nodes/labo/lxc/100/status/current HTTP/1.1&amp;quot; 200 523&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il nous reste un peu de nettoyage à faire, dans certains cas :&lt;br /&gt;
* l&#039;adresse apparaît non pas une fois mais deux, séparées par une virgule&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
37.167.182.207, 37.167.182.207&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* l&#039;adresse IPv4 (32 bits) est affichée dans sa représentation IPv6 (128 bits), avec le préfixe &#039;&#039;::ffff:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
::ffff:192.168.20.22&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On a deux possibilités pour faire le nettoyage :&lt;br /&gt;
*Soit on ajoute les lignes suivantes dans &#039;&#039;AnyEvent.pm&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if (index($reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
   # Remove trailing ip &lt;br /&gt;
   my @fields = split /,/, $reqstate-&amp;gt;{peer_host};&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $fields[0];&lt;br /&gt;
}&lt;br /&gt;
if($reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
   # Remove IPv6 subnet for IPv4&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $1;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*Soit on modifie le filtre /etc/fail2ban/filter.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=.*:?&amp;lt;HOST&amp;gt;,? user=.* msg=.*&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Automatisation ===&lt;br /&gt;
On peut automatiser le processus précédent avec le script suivant, que l&#039;on peut créer dans /root/remoteip_fix.sh :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=bash&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
ANYEVENT_PATH=&amp;quot;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&amp;quot;&lt;br /&gt;
ANYEVENT_REGEX=&#039;$self-&amp;gt;{spiceproxy}&#039;&lt;br /&gt;
TMP_FILE=&amp;quot;/tmp/AnyEvent.pm.tmp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if [ ! -f $ANYEVENT_PATH ]; then&lt;br /&gt;
  echo &amp;quot;$ANYEVENT_PATH does not exists !&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
if [ $(grep &#039;### BUGFIX REMOTE_IP FOR FAIL2BAN ###&#039; $ANYEVENT_PATH | wc -l) -eq 1 ]; then&lt;br /&gt;
  echo &amp;quot;AnyEvent.pm already patched !&amp;quot;&lt;br /&gt;
  exit 0&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
LINE_NUMBER_TOP=$(nl -ba $ANYEVENT_PATH | grep $ANYEVENT_REGEX | head -n 1 | awk -F &#039; &#039; &#039;{print $1}&#039;)&lt;br /&gt;
let LINE_NUMBER_TOP-=1&lt;br /&gt;
&lt;br /&gt;
if [ $LINE_NUMBER_TOP -lt 0 ]; then&lt;br /&gt;
  echo &amp;quot;Did not find the $ANYEVENT_REGEX expr in $ANYEVENT_PATH&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
echo -n &amp;quot;Applying bugfix: &amp;quot;&lt;br /&gt;
trap &amp;quot;rm -f $TMP_FILE&amp;quot; 0 1 2 5 13 15&lt;br /&gt;
head -n $LINE_NUMBER_TOP $ANYEVENT_PATH &amp;gt;$TMP_FILE&lt;br /&gt;
cat &amp;gt;&amp;gt;$TMP_FILE &amp;lt;&amp;lt;EOF&lt;br /&gt;
### BUGFIX REMOTE_IP FOR FAIL2BAN ###&lt;br /&gt;
    if (\$request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
    } elsif (\$request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
    }&lt;br /&gt;
    if (index(\$reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
        my @fields = split /,/, \$reqstate-&amp;gt;{peer_host};&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$fields[0];&lt;br /&gt;
    }&lt;br /&gt;
    if(\$reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
        # Remove IPv6 subnet for IPv4&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$1;&lt;br /&gt;
    }&lt;br /&gt;
#####################################&lt;br /&gt;
EOF&lt;br /&gt;
echo &amp;quot;$ANYEVENT_MODIF&amp;quot; &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cp $ANYEVENT_PATH $ANYEVENT_PATH.ori&lt;br /&gt;
LINE_NUMBER_BOTTOM=$(cat $ANYEVENT_PATH | wc -l)&lt;br /&gt;
let LINE_NUMBER_BOTTOM-=LINE_NUMBER_TOP&lt;br /&gt;
tail -n $LINE_NUMBER_BOTTOM $ANYEVENT_PATH &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cat $TMP_FILE &amp;gt;$ANYEVENT_PATH&lt;br /&gt;
rm -f $TMP_FILE&lt;br /&gt;
trap 0&lt;br /&gt;
echo &amp;quot;done.&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à le rendre exécutable et le lancer :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# chmod +x /root/remoteip_fix.sh&lt;br /&gt;
# /root/remoteip_fix.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne faudra pas oublier de redémarrer &#039;&#039;pveproxy&#039;&#039; pour appliquer les changements !&lt;br /&gt;
&lt;br /&gt;
== Comment bannir derrière un reverse-proxy ? ==&lt;br /&gt;
Maintenant que votre Proxmox est derrière un reverse-proxy, inutile de bannir les IP publiques avec iptables sur le serveur Proxmox, la seule IP visible est celle du reverse-proxy (dans cet exemple 192.168.4.100).&lt;br /&gt;
&lt;br /&gt;
La seule machine capable capable de bannir est le reverse-proxy, il faut donc lui transmettre les IP et nous allons faire ça en trois étapes:&lt;br /&gt;
* la première est de créer une &amp;quot;prison&amp;quot; proxmox sur le fail2ban présent sur le reverse-proxy&lt;br /&gt;
* la deuxième est l&#039;invention d&#039;une API pour fail2ban sur le reverse-proxy&lt;br /&gt;
* la troisième est la modification du comportement de fail2ban pour appeler cette API au lieu de modifier iptables&lt;br /&gt;
&lt;br /&gt;
=== Création d&#039;une prison sur le reverse-proxy ===&lt;br /&gt;
&lt;br /&gt;
Pour bannir nous allons créer une prison spécifique pour le / les serveurs Proxmox que nous allons appeler &#039;&#039;proxmox&#039;&#039; dans le fichier /etc/fail2ban/jail.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[proxmox]&lt;br /&gt;
enabled = true&lt;br /&gt;
port = https,http&lt;br /&gt;
filter = do-nothing&lt;br /&gt;
logpath = /dev/null&lt;br /&gt;
maxretry = 3&lt;br /&gt;
findtime = 1d&lt;br /&gt;
bantime = 1w&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
J&#039;attire votre attention sur les paramètres &#039;&#039;maxretry&#039;&#039;, &#039;&#039;findtime&#039;&#039; et &#039;&#039;bantime&#039;&#039; qui doivent concorder avec ceux du fail2ban de votre Proxmox. S&#039;il sont plus &#039;&#039;court&#039;&#039; sur le reverse-proxy, les IP seront libérées plus tôt à l&#039;inverse, plus long n&#039;est pas gênant, le fail2ban de votre Proxmox les libéreras avant celui du proxy.&lt;br /&gt;
&lt;br /&gt;
Vous avez remarquez le filtre &#039;&#039;do-nothing&#039;&#039; qu&#039;il nous reste à créer dans le fichier &#039;&#039;/etc/fail2ban/filter.d/do-nothing.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
&lt;br /&gt;
failregex = ^&amp;lt;HOST&amp;gt;$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Après redémarrage de fail2ban :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl restart fail2ban&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous devriez voir la prison&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status&lt;br /&gt;
Status&lt;br /&gt;
|- Number of jail:      2&lt;br /&gt;
`- Jail list:   proxmox, sshd&lt;br /&gt;
[root@proxy proxymox]# &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous pouvons maintenant passer à l&#039;API !&lt;br /&gt;
&lt;br /&gt;
=== Invention d&#039;une API pour fail2ban ===&lt;br /&gt;
&lt;br /&gt;
Toujours sur le reverse-proxy nous allons installer PHP pour créer un mini serveur qui répondra au urls suivantes:&lt;br /&gt;
* /ban/&amp;lt;ip&amp;gt; pour bannir&lt;br /&gt;
* /unban/&amp;lt;ip&amp;gt; pour lever le banissement&lt;br /&gt;
&lt;br /&gt;
Commençons par installer PHP:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# dnf -y install php-cli&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un répertoire &amp;quot;f2b-api&amp;quot; dans le dossier &amp;quot;opt&amp;quot; :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# mkdir /opt/f2b-api&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis créer un fichier &#039;&#039;f2b-api.php&#039;&#039; dans ce dossier:&lt;br /&gt;
&amp;lt;source lang=php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
main();&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        # On clean l&#039;uri du / de début&lt;br /&gt;
        $uri = ltrim($_SERVER[&#039;REQUEST_URI&#039;], &#039;/&#039;);&lt;br /&gt;
        # On éclate l&#039;uri en parties (action + ip)&lt;br /&gt;
        $parts = explode(&#039;/&#039;, $uri);&lt;br /&gt;
        # Récupération de l&#039;action dans une variable ou false si vide&lt;br /&gt;
        $action = empty($parts[0]) ? false : $parts[0];&lt;br /&gt;
        # Récupération de l&#039;ip dans une variable ou false si vide&lt;br /&gt;
        $ip = empty($parts[1]) ? false : $parts[1];&lt;br /&gt;
        if(!$action || !$ip){&lt;br /&gt;
                # Si action vide =&amp;gt; 400 Bad request&lt;br /&gt;
                http_response_code(400);&lt;br /&gt;
                die();&lt;br /&gt;
        }&lt;br /&gt;
        if(!in_array($action, [&#039;ban&#039;, &#039;unban&#039;])){&lt;br /&gt;
                # Si action pas dans la liste =&amp;gt; 400 Bad request&lt;br /&gt;
                http_response_code(400);&lt;br /&gt;
                die();&lt;br /&gt;
        }&lt;br /&gt;
        $cmd = &#039;&#039;;&lt;br /&gt;
        if($action == &#039;ban&#039;){&lt;br /&gt;
                $cmd = &#039;fail2ban-client set proxmox banip &#039; . $ip;&lt;br /&gt;
        } else if($action == &#039;unban&#039;){&lt;br /&gt;
                $cmd = &#039;fail2ban-client unban proxmox &#039; . $ip;&lt;br /&gt;
        }&lt;br /&gt;
        shell_exec($cmd);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
[[Fichier:Warning-icon.png|40px]]  Gardez en tête que ce code simpliste n&#039;est en aucun cas sécurisé et ne doit pas être accessible depuis Internet.&lt;br /&gt;
&lt;br /&gt;
Pour démarrer se code en mode serveur il suffit de taper la commande suivante:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# php -S 0.0.0.0:8080 -t /opt/f2b-api /opt/f2b-api/f2b-api.php&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous pouvez tester directement depuis un autre terminal en tapant les commandes:&lt;br /&gt;
* pour bannir :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# curl -X GET http://127.0.0.1:8080/ban/1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* pour dé-bannir :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# curl -X GET http://127.0.0.1:8080/unban/1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Et en vérifiant dans fail2ban:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed: 0&lt;br /&gt;
|  |- Total failed:     0&lt;br /&gt;
|  `- File list:        /dev/null&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned: 1&lt;br /&gt;
   |- Total banned:     10&lt;br /&gt;
   `- Banned IP list:   1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Nous n&#039;allons pas lancer nous même le serveur PHP, nous allons demander à SystemD de le faire et pour cela nous allons créer le fichier &#039;&#039;/opt/f2b-api/f2b-api.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=fail2ban API Server&lt;br /&gt;
After=network-online.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
UMask=007&lt;br /&gt;
ExecStart=php -S 0.0.0.0:8080 -t /opt/f2b-api /opt/f2b-api/f2b-api.php&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faut maintenant demander à SystemD de s&#039;occuper de notre service:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl link /opt/f2b-api/f2b-api.service&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Et de le lancer au démarrage du reverse-proxy:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl enable f2b-api --now&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous pouvons maintenant nous déplacer sur le serveur Proxmox pour modifier fail2ban !&lt;br /&gt;
&lt;br /&gt;
=== Modification des actions fail2ban ===&lt;br /&gt;
Sur le serveur Proxmox nous allons débrayer le comportement de base de fail2ban qui est de modifier iptables. pour cela nous alons créer le fichier &#039;&#039;/etc/fail2ban/action.d/f2b-api.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
actionstart =&lt;br /&gt;
actionstop =&lt;br /&gt;
actioncheck =&lt;br /&gt;
actionban = curl -X GET 192.168.4.100:8080/ban/&amp;lt;ip&amp;gt;&lt;br /&gt;
actionunban = curl -X GET 192.168.4.100:8080/unban/&amp;lt;ip&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Veuillez noter que:&lt;br /&gt;
* même si elles sont vide, les lignes &#039;&#039;actionstart&#039;&#039;, &#039;&#039;actionstop&#039;&#039; et &#039;&#039;actioncheck&#039;&#039; sont obligatoires !&lt;br /&gt;
* l&#039;adresse &#039;&#039;192.168.4.100&#039;&#039; doit être remplcée par celle de votre reverse-proxy&lt;br /&gt;
* &amp;lt;ip&amp;gt; est l&#039;expression utilisée par fail2ban et elle sera remplacée par l&#039;IP à bannir &lt;br /&gt;
&lt;br /&gt;
Pour ce fichier d&#039;action soit pris en compte, il faut modifier le fichier &#039;&#039;/etc/fail2ban/jail.d/proxmox.conf&#039;&#039; pour y ajouter:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
banaction = f2b-api&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne vous reste plus qu&#039;a redémarrer le service fai2ban sur le serveur Proxmox:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl restart fail2ban&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Et vous pouvez tester les commandes suivantes:&lt;br /&gt;
* pour bannir&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client set proxmox banip 1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* pour dé-bannir:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client unban proxmox 1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Et vérifier sur le reverse-proxy que les modification sont bien prises en compte:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed: 0&lt;br /&gt;
|  |- Total failed:     0&lt;br /&gt;
|  `- File list:        /dev/null&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned: 1&lt;br /&gt;
   |- Total banned:     10&lt;br /&gt;
   `- Banned IP list:   1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4418</id>
		<title>Proxmox fail2ban</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4418"/>
		<updated>2026-07-13T09:27:56Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Proxification */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
Proxmox utilise une interface web d&#039;administration qui utilise le port TCP 8006 et c&#039;est un vecteur possible d&#039;attaque par force brut. Nous allons donc &#039;&#039;dresser&#039;&#039; fail2ban pour agir en cas d&#039;attaque !&lt;br /&gt;
&lt;br /&gt;
Proxmox utilise Debian, nous allons principalement reproduire les étapes décrites dans le tutoriel de [[Sécuriser_un_service_avec_Fail2ban| Fail2ban pour Rocky]] et adapter à Debian.&lt;br /&gt;
&lt;br /&gt;
Avant d&#039;aller plus loin, assurez-vous d&#039;avoir correctement installé et configuré [[proxmox_iptables |iptables sur Proxmox]]&lt;br /&gt;
&lt;br /&gt;
= Installation =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt -y install fail2ban&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Configuration =&lt;br /&gt;
Tout d&#039;abord il faut copier le fichier &#039;&#039;/etc/fail2ban/jail.conf&#039;&#039; en &#039;&#039;/etc/fail2ban/jail.local&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dans ce fichier, on va s&#039;intéresser aux variables suivantes:&lt;br /&gt;
*ignoreip : correspond à la suite d&#039;adresses IP qui ne se feront jamais bannir;&lt;br /&gt;
*maxretry : correspond au nombre d&#039;essais;&lt;br /&gt;
*findtime : correspond à la période pendant laquelle les essais vont incrémenter maxretry;&lt;br /&gt;
*bantime  : correspond au temps où l&#039;adresse IP ne peut pas se connecter.&lt;br /&gt;
&lt;br /&gt;
= Configuration de base =&lt;br /&gt;
== Choix de la punition ==&lt;br /&gt;
Il faut choisir quelque chose de cohérent (une punition suffisante) pour ne pas permettre de se faire cracker son mot de passe:&lt;br /&gt;
*maxretry = 3&lt;br /&gt;
*findtime = 86400 (correspond à 1 journée)&lt;br /&gt;
*bantime = 604800 (correspond à 1 semaine)&lt;br /&gt;
&lt;br /&gt;
Cela signifie que si une adresse IP se trompe 3 fois en 1 journée (86400s) elle se fait bannir pendant 1 semaine (604800s).&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul permet de trouver le nombre maximal de tentatives durant une année:&lt;br /&gt;
&lt;br /&gt;
365 jours / 7 jours par semaine * 3 tentatives = 156 essais, ce qui reste raisonnable. &lt;br /&gt;
&lt;br /&gt;
Si le pirate possède un [http://fr.wikipedia.org/wiki/Botnet botnet], il faut bien sûr multiplier ce nombre par le nombre de machines dans le botnet...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Attention : fail2ban parcours les logs de connexion pour connaître le numéro de la tentative, ce qui a pour conséquence, si le &#039;&#039;findtime&#039;&#039; est grand, de prendre un certain temps...&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Jail pour SSH ==&lt;br /&gt;
Il suffit d&#039;ajouter la ligne &#039;&#039;enabled=true&#039;&#039; dans la section à activer !&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[sshd]&lt;br /&gt;
&lt;br /&gt;
# To use more aggressive sshd modes set filter parameter &amp;quot;mode&amp;quot; in jail.local:&lt;br /&gt;
# normal (default), ddos, extra or aggressive (combines all).&lt;br /&gt;
# See &amp;quot;tests/files/logs/sshd&amp;quot; or &amp;quot;filter.d/sshd.conf&amp;quot; for usage example and details.&lt;br /&gt;
#mode   = normal&lt;br /&gt;
enabled = true&lt;br /&gt;
port    = ssh&lt;br /&gt;
logpath = %(sshd_log)s&lt;br /&gt;
backend = %(sshd_backend)s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Configuration spécifique =&lt;br /&gt;
== Jail pour PVEPROXY ==&lt;br /&gt;
Pveproxy écoute sur le port 8006 et ne fonctionne pas exactement comme un serveur [[HTTPD | Apache httpd]] qui mettrait ces logs dans le fichier &#039;&#039;error_log&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Nous allons mettre cette configuration spécifique dans le fichier &#039;&#039;/etc/fail2ban/jail.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[proxmox]&lt;br /&gt;
enabled = true&lt;br /&gt;
port = https,http,8006&lt;br /&gt;
filter = proxmox&lt;br /&gt;
backend = systemd&lt;br /&gt;
maxretry = 5&lt;br /&gt;
findtime = 1d&lt;br /&gt;
bantime = 1w&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le backend utilisé est systemd, exactement comme si vous utilisiez la commande :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Filtre pour PVEPROXY ==&lt;br /&gt;
Il ne nous reste plus qu&#039;à spécifier le filtre &#039;&#039;proxmox&#039;&#039; dans le fichier &#039;&#039;/etc/fail2ban/filter.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=&amp;lt;HOST&amp;gt; user=.* msg=.*&lt;br /&gt;
ignoreregex =&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Tests =&lt;br /&gt;
Il faut maintenant tester le filtre et pour ça on peut utiliser un partage de connexion et réaliser le nombre d&#039;échecs spécifié par la directive &amp;quot;maxretry&amp;quot; (ici 3) :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed:	0&lt;br /&gt;
|  |- Total failed:	3&lt;br /&gt;
|  `- Journal matches:	_SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned:	1&lt;br /&gt;
   |- Total banned:	1&lt;br /&gt;
   `- Banned IP list:	37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On voit bien l&#039;IP 37.167.23.159 qui est bannie !&lt;br /&gt;
N&#039;oubliez pas de l&#039;ajouter à &#039;&#039;ignoreip&#039;&#039; dans le fichier &#039;&#039;jails.local&#039;&#039; ou de faire &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client unban 37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Démarrage et enregistrement dans le chargeur de démarrage =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start fail2ban.service&lt;br /&gt;
# systemctl enable fail2ban.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Vous pouvez maintenant démarrer fail2ban&lt;br /&gt;
&lt;br /&gt;
= Proxification=&lt;br /&gt;
Lorsque votre serveur Proxmox se trouve derrière un reverse-proxy (Apache, Nginx, Traefik, ...), au niveau 3 OSI, l&#039;adresse IP du client est remplacée par celle du proxy et le serveur utilise l&#039;entêtes &#039;&#039;X-Forwarded-For&#039;&#039; ou &#039;&#039;X-Real-IP&#039;&#039; pour transporter l&#039;adresse du client &lt;br /&gt;
[[Fichier:Reverse proxy proxmox.png|700px|centré]]&lt;br /&gt;
== Configuration du reverse-proxy ==&lt;br /&gt;
Sur votre reverse-proxy Apache, vous devriez avoir une configuration qui ressemble à ça:&lt;br /&gt;
&amp;lt;source lang=apache&amp;gt;&lt;br /&gt;
MDomain pve.tala-informatique.fr&lt;br /&gt;
&lt;br /&gt;
&amp;lt;VirtualHost *:80&amp;gt;&lt;br /&gt;
    ServerName pve.tala-informatique.fr&lt;br /&gt;
    Redirect / https://pve.tala-informatique.fr/&lt;br /&gt;
&amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;VirtualHost *:443&amp;gt;&lt;br /&gt;
    ServerName pve.tala-informatique.fr&lt;br /&gt;
    &lt;br /&gt;
    SSLEngine on&lt;br /&gt;
    SSLProxyEngine on&lt;br /&gt;
    SSLProxyVerify none &lt;br /&gt;
    SSLProxyCheckPeerCN off&lt;br /&gt;
    SSLProxyCheckPeerName off&lt;br /&gt;
    &lt;br /&gt;
    ProxyRequests off&lt;br /&gt;
    ProxyPreserveHost On&lt;br /&gt;
    &lt;br /&gt;
    RewriteEngine on&lt;br /&gt;
    RewriteCond %{HTTP:Connection} Upgrade [NC]&lt;br /&gt;
    RewriteCond %{HTTP:Upgrade} websocket [NC]&lt;br /&gt;
    RewriteRule ^/?(.*) wss://192.168.4.1:8006/$1 [P,L]&lt;br /&gt;
&lt;br /&gt;
    ProxyPass / https://192.168.4.1:8006/ flushpackets=On connectiontimeout=300 timeout=300&lt;br /&gt;
    ProxyPassReverse / https://192.168.4.1:8006/&lt;br /&gt;
    ProxyTimeout     600&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La première ligne renvoie à la configuration de mod_md et permet l&#039;obtention du certificat SSL auprès de [https://letsencrypt.org Let&#039;s encrypt]&lt;br /&gt;
&lt;br /&gt;
Le problème est que la seule adresse que fail2ban va voir apparaître dans les logs est celle du reverse-proxy (&#039;&#039;192.168.4.100&#039;&#039;) :&lt;br /&gt;
[[Fichier:Reverse proxy ip logs.png|600px|centré]]&lt;br /&gt;
Même si le filtre &#039;&#039;fail2ban&#039;&#039; est configuré pour utiliser la commande &#039;&#039;journactl&#039;&#039; sur le démon &#039;&#039;pvedaemon&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
les adresses viennent de pveproxy qui journalise tout dans &#039;&#039;/var/log/pveproxy/access.log&#039;&#039; et &#039;&#039;pvedaemon&#039;&#039; ne journalise que les échecs d&#039;authentification. &lt;br /&gt;
Il est donc plus simple de faire un &#039;&#039;tail&#039;&#039; ou un &#039;&#039;cat&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Que d&#039;utiliser &#039;&#039;journalctl&#039;&#039; pour voir les IPs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
Dec 14 10:43:01 labo unix_chkpwd[1326506]: password check failed for user (root)&lt;br /&gt;
Dec 14 10:43:01 labo IPCC.xs[1320783]: pam_unix(proxmox-ve-auth:auth): authentication failure; logname= uid=0 euid=0 tty= ruser= rhost=37.167.23.159  user=root&lt;br /&gt;
Dec 14 10:43:03 labo pvedaemon[1320783]: authentication failure; rhost=37.167.23.159 user=root@pam msg=Authentication failure&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Configuration de pveproxy ==&lt;br /&gt;
Si on veut voir l&#039;adresse du client, il faut dire au [https://fr.wikipedia.org/wiki/Daemon_(informatique)| démon] &#039;&#039;pveproxy&#039;&#039; d&#039;utiliser l&#039;une des deux entêtes précédentes ainsi que préciser l&#039;adresse du proxy. &lt;br /&gt;
&lt;br /&gt;
Préciser l&#039;adresse du proxy est essentiel pour que &#039;&#039;pveproxy&#039;&#039; n&#039;accepte de lire l&#039;adresse du client présente dans l&#039;entête &#039;&#039;&#039;uniquement&#039;&#039;&#039; si cela provient du proxy, qui est une machine de confiance. Le cas contraire, tout le monde pourrait ajouter une adresse IP dans l&#039;entête pour la faire bannir...&lt;br /&gt;
&lt;br /&gt;
Nous allons créer le fichier &#039;&#039;/etc/default/pveproxy&#039;&#039; avec les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Forwarded-For&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Real-IP&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_ALLOW_FROM=&amp;quot;192.168.4.100&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il faut maintenant redémarrer &#039;&#039;pveproxy&#039;&#039; pour que les changements s&#039;appliquent. Si vous êtes connecté via l&#039;interface web, cela va vous déconnecter, le temps que le démon redémarre, il faudra ensuite certainement rafraîchir la page web.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl restart pveproxy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à vérifier dans les logs si les bonnes adresses s&#039;affichent:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Si jamais ce n&#039;est pas le cas, poursuivez avec la modification du fichier &#039;&#039;AnyEvent.pm&#039;&#039;&lt;br /&gt;
== Modification de AnyEvent.pm ==&lt;br /&gt;
=== Application de la modification ===&lt;br /&gt;
Au jour d&#039;aujourd&#039;hui (13/12/25) la proxification ne fonctionne plus et il faut apporter une modification dans le fichier &#039;&#039;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&#039;&#039; pour que les bonnes adresses apparaissent !&lt;br /&gt;
En fonction des versions cette modification peut avoir lieu soit ligne &#039;&#039;&#039;1504&#039;&#039;&#039;, soit ligne &#039;&#039;&#039;1554&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Il faut repérer la fonction suivante:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
sub authenticate_and_handle_request {&lt;br /&gt;
    my ($self, $reqstate) = @_;&lt;br /&gt;
&lt;br /&gt;
    my $request = $reqstate-&amp;gt;{request};&lt;br /&gt;
    my $method = $request-&amp;gt;method();&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
C&#039;est un peu plus loin qu&#039;il faut insérer le code :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 ### INSERTION ICI ###&lt;br /&gt;
&lt;br /&gt;
    if ($self-&amp;gt;{spiceproxy}) {&lt;br /&gt;
        my $connect_str = $request-&amp;gt;header(&#039;Host&#039;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il faut modifier l&#039;attribut &#039;&#039;peer_host&#039;&#039; de l&#039;objet &#039;&#039;reqstate&#039;&#039; si l&#039;une des deux entêtes est présente :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if ($request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
} elsif ($request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Double IPv4 ou préfixe IPv6 ===&lt;br /&gt;
Après redémarrage, cela permet de voir l&#039;adresse du client dans les logs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/ext-all.js?ver=7.0.0 HTTP/1.1&amp;quot; 200 683505&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/js/u2f-api.js HTTP/1.1&amp;quot; 200 4898&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/resources HTTP/1.1&amp;quot; 200 1226&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/tasks HTTP/1.1&amp;quot; 200 1090&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /proxmoxlib.js?ver=v5.0.4-t1754316706 HTTP/1.1&amp;quot; 200 157086&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/theme-crisp/resources/theme-crisp-all_1.css HTTP/1.1&amp;quot; 200 32919&lt;br /&gt;
::ffff:192.168.20.22 - root@pam [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/nodes/labo/lxc/100/status/current HTTP/1.1&amp;quot; 200 523&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il nous reste un peu de nettoyage à faire, dans certains cas :&lt;br /&gt;
* l&#039;adresse apparaît non pas une fois mais deux, séparées par une virgule&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
37.167.182.207, 37.167.182.207&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* l&#039;adresse IPv4 (32 bits) est affichée dans sa représentation IPv6 (128 bits), avec le préfixe &#039;&#039;::ffff:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
::ffff:192.168.20.22&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On a deux possibilités pour faire le nettoyage :&lt;br /&gt;
*Soit on ajoute les lignes suivantes dans &#039;&#039;AnyEvent.pm&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if (index($reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
   # Remove trailing ip &lt;br /&gt;
   my @fields = split /,/, $reqstate-&amp;gt;{peer_host};&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $fields[0];&lt;br /&gt;
}&lt;br /&gt;
if($reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
   # Remove IPv6 subnet for IPv4&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $1;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*Soit on modifie le filtre /etc/fail2ban/filter.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=.*:?&amp;lt;HOST&amp;gt;,? user=.* msg=.*&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Automatisation ===&lt;br /&gt;
On peut automatiser le processus précédent avec le script suivant, que l&#039;on peut créer dans /root/remoteip_fix.sh :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=bash&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
ANYEVENT_PATH=&amp;quot;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&amp;quot;&lt;br /&gt;
ANYEVENT_REGEX=&#039;$self-&amp;gt;{spiceproxy}&#039;&lt;br /&gt;
TMP_FILE=&amp;quot;/tmp/AnyEvent.pm.tmp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if [ ! -f $ANYEVENT_PATH ]; then&lt;br /&gt;
  echo &amp;quot;$ANYEVENT_PATH does not exists !&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
if [ $(grep &#039;### BUGFIX REMOTE_IP FOR FAIL2BAN ###&#039; $ANYEVENT_PATH | wc -l) -eq 1 ]; then&lt;br /&gt;
  echo &amp;quot;AnyEvent.pm already patched !&amp;quot;&lt;br /&gt;
  exit 0&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
LINE_NUMBER_TOP=$(nl -ba $ANYEVENT_PATH | grep $ANYEVENT_REGEX | head -n 1 | awk -F &#039; &#039; &#039;{print $1}&#039;)&lt;br /&gt;
let LINE_NUMBER_TOP-=1&lt;br /&gt;
&lt;br /&gt;
if [ $LINE_NUMBER_TOP -lt 0 ]; then&lt;br /&gt;
  echo &amp;quot;Did not find the $ANYEVENT_REGEX expr in $ANYEVENT_PATH&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
echo -n &amp;quot;Applying bugfix: &amp;quot;&lt;br /&gt;
trap &amp;quot;rm -f $TMP_FILE&amp;quot; 0 1 2 5 13 15&lt;br /&gt;
head -n $LINE_NUMBER_TOP $ANYEVENT_PATH &amp;gt;$TMP_FILE&lt;br /&gt;
cat &amp;gt;&amp;gt;$TMP_FILE &amp;lt;&amp;lt;EOF&lt;br /&gt;
### BUGFIX REMOTE_IP FOR FAIL2BAN ###&lt;br /&gt;
    if (\$request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
    } elsif (\$request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
    }&lt;br /&gt;
    if (index(\$reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
        my @fields = split /,/, \$reqstate-&amp;gt;{peer_host};&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$fields[0];&lt;br /&gt;
    }&lt;br /&gt;
    if(\$reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
        # Remove IPv6 subnet for IPv4&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$1;&lt;br /&gt;
    }&lt;br /&gt;
#####################################&lt;br /&gt;
EOF&lt;br /&gt;
echo &amp;quot;$ANYEVENT_MODIF&amp;quot; &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cp $ANYEVENT_PATH $ANYEVENT_PATH.ori&lt;br /&gt;
LINE_NUMBER_BOTTOM=$(cat $ANYEVENT_PATH | wc -l)&lt;br /&gt;
let LINE_NUMBER_BOTTOM-=LINE_NUMBER_TOP&lt;br /&gt;
tail -n $LINE_NUMBER_BOTTOM $ANYEVENT_PATH &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cat $TMP_FILE &amp;gt;$ANYEVENT_PATH&lt;br /&gt;
rm -f $TMP_FILE&lt;br /&gt;
trap 0&lt;br /&gt;
echo &amp;quot;done.&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à le rendre exécutable et le lancer :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# chmod +x /root/remoteip_fix.sh&lt;br /&gt;
# /root/remoteip_fix.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne faudra pas oublier de redémarrer &#039;&#039;pveproxy&#039;&#039; pour appliquer les changements !&lt;br /&gt;
&lt;br /&gt;
== Comment bannir derrière un reverse-proxy ? ==&lt;br /&gt;
Maintenant que votre Proxmox est derrière un reverse-proxy, inutile de bannir les IP publiques avec iptables sur le serveur Proxmox, la seule IP visible est celle du reverse-proxy (dans cet exemple 192.168.4.100).&lt;br /&gt;
&lt;br /&gt;
La seule machine capable capable de bannir est le reverse-proxy, il faut donc lui transmettre les IP et nous allons faire ça en trois étapes:&lt;br /&gt;
* la première est de créer une &amp;quot;prison&amp;quot; proxmox sur le fail2ban présent sur le reverse-proxy&lt;br /&gt;
* la deuxième est l&#039;invention d&#039;une API pour fail2ban sur le reverse-proxy&lt;br /&gt;
* la troisième est la modification du comportement de fail2ban pour appeler cette API au lieu de modifier iptables&lt;br /&gt;
&lt;br /&gt;
=== Création d&#039;une prison sur le reverse-proxy ===&lt;br /&gt;
&lt;br /&gt;
Pour bannir nous allons créer une prison spécifique pour le / les serveurs Proxmox que nous allons appeler &#039;&#039;proxmox&#039;&#039; dans le fichier /etc/fail2ban/jail.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[proxmox]&lt;br /&gt;
enabled = true&lt;br /&gt;
port = https,http&lt;br /&gt;
filter = do-nothing&lt;br /&gt;
logpath = /dev/null&lt;br /&gt;
maxretry = 3&lt;br /&gt;
findtime = 1d&lt;br /&gt;
bantime = 1w&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
J&#039;attire votre attention sur les paramètres &#039;&#039;maxretry&#039;&#039;, &#039;&#039;findtime&#039;&#039; et &#039;&#039;bantime&#039;&#039; qui doivent concorder avec ceux du fail2ban de votre Proxmox. S&#039;il sont plus &#039;&#039;court&#039;&#039; sur le reverse-proxy, les IP seront libérées plus tôt à l&#039;inverse, plus long n&#039;est pas gênant, le fail2ban de votre Proxmox les libéreras avant celui du proxy.&lt;br /&gt;
&lt;br /&gt;
Vous avez remarquez le filtre &#039;&#039;do-nothing&#039;&#039; qu&#039;il nous reste à créer dans le fichier &#039;&#039;/etc/fail2ban/filter.d/do-nothing.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
&lt;br /&gt;
failregex = ^&amp;lt;HOST&amp;gt;$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Après redémarrage de fail2ban :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl restart fail2ban&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous devriez voir la prison&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status&lt;br /&gt;
Status&lt;br /&gt;
|- Number of jail:      2&lt;br /&gt;
`- Jail list:   proxmox, sshd&lt;br /&gt;
[root@proxy proxymox]# &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous pouvons maintenant passer à l&#039;API !&lt;br /&gt;
&lt;br /&gt;
=== Invention d&#039;une API pour fail2ban ===&lt;br /&gt;
&lt;br /&gt;
Toujours sur le reverse-proxy nous allons installer PHP pour créer un mini serveur qui répondra au urls suivantes:&lt;br /&gt;
* /ban/&amp;lt;ip&amp;gt; pour bannir&lt;br /&gt;
* /unban/&amp;lt;ip&amp;gt; pour lever le banissement&lt;br /&gt;
&lt;br /&gt;
Commençons par installer PHP:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# dnf -y install php-cli&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un répertoire &amp;quot;f2b-api&amp;quot; dans le dossier &amp;quot;opt&amp;quot; :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# mkdir /opt/f2b-api&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis créer un fichier &#039;&#039;f2b-api.php&#039;&#039; dans ce dossier:&lt;br /&gt;
&amp;lt;source lang=php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
main();&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        # On clean l&#039;uri du / de début&lt;br /&gt;
        $uri = ltrim($_SERVER[&#039;REQUEST_URI&#039;], &#039;/&#039;);&lt;br /&gt;
        # On éclate l&#039;uri en parties (action + ip)&lt;br /&gt;
        $parts = explode(&#039;/&#039;, $uri);&lt;br /&gt;
        # Récupération de l&#039;action dans une variable ou false si vide&lt;br /&gt;
        $action = empty($parts[0]) ? false : $parts[0];&lt;br /&gt;
        # Récupération de l&#039;ip dans une variable ou false si vide&lt;br /&gt;
        $ip = empty($parts[1]) ? false : $parts[1];&lt;br /&gt;
        if(!$action || !$ip){&lt;br /&gt;
                # Si action vide =&amp;gt; 400 Bad request&lt;br /&gt;
                http_response_code(400);&lt;br /&gt;
                die();&lt;br /&gt;
        }&lt;br /&gt;
        if(!in_array($action, [&#039;ban&#039;, &#039;unban&#039;])){&lt;br /&gt;
                # Si action pas dans la liste =&amp;gt; 400 Bad request&lt;br /&gt;
                http_response_code(400);&lt;br /&gt;
                die();&lt;br /&gt;
        }&lt;br /&gt;
        $cmd = &#039;&#039;;&lt;br /&gt;
        if($action == &#039;ban&#039;){&lt;br /&gt;
                $cmd = &#039;fail2ban-client set proxmox banip &#039; . $ip;&lt;br /&gt;
        } else if($action == &#039;unban&#039;){&lt;br /&gt;
                $cmd = &#039;fail2ban-client unban proxmox &#039; . $ip;&lt;br /&gt;
        }&lt;br /&gt;
        shell_exec($cmd);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
[[Fichier:Warning-icon.png|40px]]  Gardez en tête que ce code simpliste n&#039;est en aucun cas sécurisé et ne doit pas être accessible depuis Internet.&lt;br /&gt;
&lt;br /&gt;
Pour démarrer se code en mode serveur il suffit de taper la commande suivante:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# php -S 0.0.0.0:8080 -t /opt/f2b-api /opt/f2b-api/f2b-api.php&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous pouvez tester directement depuis un autre terminal en tapant les commandes:&lt;br /&gt;
* pour bannir :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# curl -X GET http://127.0.0.1:8080/ban/1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* pour dé-bannir :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# curl -X GET http://127.0.0.1:8080/unban/1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Et en vérifiant dans fail2ban:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed: 0&lt;br /&gt;
|  |- Total failed:     0&lt;br /&gt;
|  `- File list:        /dev/null&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned: 1&lt;br /&gt;
   |- Total banned:     10&lt;br /&gt;
   `- Banned IP list:   1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Nous n&#039;allons pas lancer nous même le serveur PHP, nous allons demander à SystemD de le faire et pour cela nous allons créer le fichier &#039;&#039;/opt/f2b-api/f2b-api.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=fail2ban API Server&lt;br /&gt;
After=network-online.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
UMask=007&lt;br /&gt;
ExecStart=php -S 0.0.0.0:8080 -t /opt/f2b-api /opt/f2b-api/f2b-api.php&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faut maintenant demander à SystemD de s&#039;occuper de notre service:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl link /opt/f2b-api/f2b-api.service&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Et de le lancer au démarrage du reverse-proxy:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl enable f2b-api --now&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous pouvons maintenant nous déplacer sur le serveur Proxmox pour modifier fail2ban !&lt;br /&gt;
&lt;br /&gt;
=== Modification des actions fail2ban ===&lt;br /&gt;
Sur le serveur Proxmox nous allons débrayer le comportement de base de fail2ban qui est de modifier iptables. pour cela nous alons créer le fichier &#039;&#039;/etc/fail2ban/action.d/f2b-api.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
actionstart =&lt;br /&gt;
actionstop =&lt;br /&gt;
actioncheck =&lt;br /&gt;
actionban = curl -X GET 192.168.4.100:8080/ban/&amp;lt;ip&amp;gt;&lt;br /&gt;
actionunban = curl -X GET 192.168.4.100:8080/unban/&amp;lt;ip&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Veuillez noter que:&lt;br /&gt;
* même si elles sont vide, les lignes &#039;&#039;actionstart&#039;&#039;, &#039;&#039;actionstop&#039;&#039; et &#039;&#039;actioncheck&#039;&#039; sont obligatoires !&lt;br /&gt;
* l&#039;adresse &#039;&#039;192.168.4.100&#039;&#039; doit être remplcée par celle de votre reverse-proxy&lt;br /&gt;
* &amp;lt;ip&amp;gt; est l&#039;expression utilisée par fail2ban et elle sera remplacée par l&#039;IP à bannir &lt;br /&gt;
&lt;br /&gt;
Pour ce fichier d&#039;action soit pris en compte, il faut modifier le fichier &#039;&#039;/etc/fail2ban/jail.d/proxmox.conf&#039;&#039; pour y ajouter:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
banaction = f2b-api&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne vous reste plus qu&#039;a redémarrer le service fai2ban sur le serveur Proxmox:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl restart fail2ban&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Et vous pouvez tester les commandes suivantes:&lt;br /&gt;
* pour bannir&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client set proxmox banip 1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* pour dé-bannir:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client unban proxmox 1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Et vérifier sur le reverse-proxy que les modification sont bien prises en compte:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed: 0&lt;br /&gt;
|  |- Total failed:     0&lt;br /&gt;
|  `- File list:        /dev/null&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned: 1&lt;br /&gt;
   |- Total banned:     10&lt;br /&gt;
   `- Banned IP list:   1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4417</id>
		<title>Proxmox fail2ban</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4417"/>
		<updated>2026-07-11T17:08:38Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Invention d&amp;#039;une API pour fail2ban */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
Proxmox utilise une interface web d&#039;administration qui utilise le port TCP 8006 et c&#039;est un vecteur possible d&#039;attaque par force brut. Nous allons donc &#039;&#039;dresser&#039;&#039; fail2ban pour agir en cas d&#039;attaque !&lt;br /&gt;
&lt;br /&gt;
Proxmox utilise Debian, nous allons principalement reproduire les étapes décrites dans le tutoriel de [[Sécuriser_un_service_avec_Fail2ban| Fail2ban pour Rocky]] et adapter à Debian.&lt;br /&gt;
&lt;br /&gt;
Avant d&#039;aller plus loin, assurez-vous d&#039;avoir correctement installé et configuré [[proxmox_iptables |iptables sur Proxmox]]&lt;br /&gt;
&lt;br /&gt;
= Installation =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt -y install fail2ban&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Configuration =&lt;br /&gt;
Tout d&#039;abord il faut copier le fichier &#039;&#039;/etc/fail2ban/jail.conf&#039;&#039; en &#039;&#039;/etc/fail2ban/jail.local&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dans ce fichier, on va s&#039;intéresser aux variables suivantes:&lt;br /&gt;
*ignoreip : correspond à la suite d&#039;adresses IP qui ne se feront jamais bannir;&lt;br /&gt;
*maxretry : correspond au nombre d&#039;essais;&lt;br /&gt;
*findtime : correspond à la période pendant laquelle les essais vont incrémenter maxretry;&lt;br /&gt;
*bantime  : correspond au temps où l&#039;adresse IP ne peut pas se connecter.&lt;br /&gt;
&lt;br /&gt;
= Configuration de base =&lt;br /&gt;
== Choix de la punition ==&lt;br /&gt;
Il faut choisir quelque chose de cohérent (une punition suffisante) pour ne pas permettre de se faire cracker son mot de passe:&lt;br /&gt;
*maxretry = 3&lt;br /&gt;
*findtime = 86400 (correspond à 1 journée)&lt;br /&gt;
*bantime = 604800 (correspond à 1 semaine)&lt;br /&gt;
&lt;br /&gt;
Cela signifie que si une adresse IP se trompe 3 fois en 1 journée (86400s) elle se fait bannir pendant 1 semaine (604800s).&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul permet de trouver le nombre maximal de tentatives durant une année:&lt;br /&gt;
&lt;br /&gt;
365 jours / 7 jours par semaine * 3 tentatives = 156 essais, ce qui reste raisonnable. &lt;br /&gt;
&lt;br /&gt;
Si le pirate possède un [http://fr.wikipedia.org/wiki/Botnet botnet], il faut bien sûr multiplier ce nombre par le nombre de machines dans le botnet...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Attention : fail2ban parcours les logs de connexion pour connaître le numéro de la tentative, ce qui a pour conséquence, si le &#039;&#039;findtime&#039;&#039; est grand, de prendre un certain temps...&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Jail pour SSH ==&lt;br /&gt;
Il suffit d&#039;ajouter la ligne &#039;&#039;enabled=true&#039;&#039; dans la section à activer !&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[sshd]&lt;br /&gt;
&lt;br /&gt;
# To use more aggressive sshd modes set filter parameter &amp;quot;mode&amp;quot; in jail.local:&lt;br /&gt;
# normal (default), ddos, extra or aggressive (combines all).&lt;br /&gt;
# See &amp;quot;tests/files/logs/sshd&amp;quot; or &amp;quot;filter.d/sshd.conf&amp;quot; for usage example and details.&lt;br /&gt;
#mode   = normal&lt;br /&gt;
enabled = true&lt;br /&gt;
port    = ssh&lt;br /&gt;
logpath = %(sshd_log)s&lt;br /&gt;
backend = %(sshd_backend)s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Configuration spécifique =&lt;br /&gt;
== Jail pour PVEPROXY ==&lt;br /&gt;
Pveproxy écoute sur le port 8006 et ne fonctionne pas exactement comme un serveur [[HTTPD | Apache httpd]] qui mettrait ces logs dans le fichier &#039;&#039;error_log&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Nous allons mettre cette configuration spécifique dans le fichier &#039;&#039;/etc/fail2ban/jail.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[proxmox]&lt;br /&gt;
enabled = true&lt;br /&gt;
port = https,http,8006&lt;br /&gt;
filter = proxmox&lt;br /&gt;
backend = systemd&lt;br /&gt;
maxretry = 5&lt;br /&gt;
findtime = 1d&lt;br /&gt;
bantime = 1w&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le backend utilisé est systemd, exactement comme si vous utilisiez la commande :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Filtre pour PVEPROXY ==&lt;br /&gt;
Il ne nous reste plus qu&#039;à spécifier le filtre &#039;&#039;proxmox&#039;&#039; dans le fichier &#039;&#039;/etc/fail2ban/filter.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=&amp;lt;HOST&amp;gt; user=.* msg=.*&lt;br /&gt;
ignoreregex =&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Tests =&lt;br /&gt;
Il faut maintenant tester le filtre et pour ça on peut utiliser un partage de connexion et réaliser le nombre d&#039;échecs spécifié par la directive &amp;quot;maxretry&amp;quot; (ici 3) :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed:	0&lt;br /&gt;
|  |- Total failed:	3&lt;br /&gt;
|  `- Journal matches:	_SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned:	1&lt;br /&gt;
   |- Total banned:	1&lt;br /&gt;
   `- Banned IP list:	37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On voit bien l&#039;IP 37.167.23.159 qui est bannie !&lt;br /&gt;
N&#039;oubliez pas de l&#039;ajouter à &#039;&#039;ignoreip&#039;&#039; dans le fichier &#039;&#039;jails.local&#039;&#039; ou de faire &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client unban 37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Démarrage et enregistrement dans le chargeur de démarrage =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start fail2ban.service&lt;br /&gt;
# systemctl enable fail2ban.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Vous pouvez maintenant démarrer fail2ban&lt;br /&gt;
&lt;br /&gt;
= Proxification=&lt;br /&gt;
Lorsque votre serveur Proxmox se trouve derrière un reverse-proxy (Apache, Nginx, Traefik, ...), au niveau 3 OSI, l&#039;adresse IP du client est remplacée par celle du proxy et le serveur utilise l&#039;entêtes &#039;&#039;X-Forwarded-For&#039;&#039; ou &#039;&#039;X-Real-IP&#039;&#039; pour transporter l&#039;adresse du client &lt;br /&gt;
[[Fichier:Reverse proxy proxmox.png|700px|centré]]&lt;br /&gt;
Le problème est que la seule adresse que fail2ban va voir apparaître dans les logs est celle du reverse-proxy (&#039;&#039;192.168.4.100&#039;&#039;) :&lt;br /&gt;
[[Fichier:Reverse proxy ip logs.png|600px|centré]]&lt;br /&gt;
Même si le filtre &#039;&#039;fail2ban&#039;&#039; est configuré pour utiliser la commande &#039;&#039;journactl&#039;&#039; sur le démon &#039;&#039;pvedaemon&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
les adresses viennent de pveproxy qui journalise tout dans &#039;&#039;/var/log/pveproxy/access.log&#039;&#039; et &#039;&#039;pvedaemon&#039;&#039; ne journalise que les échecs d&#039;authentification. &lt;br /&gt;
Il est donc plus simple de faire un &#039;&#039;tail&#039;&#039; ou un &#039;&#039;cat&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Que d&#039;utiliser &#039;&#039;journalctl&#039;&#039; pour voir les IPs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
Dec 14 10:43:01 labo unix_chkpwd[1326506]: password check failed for user (root)&lt;br /&gt;
Dec 14 10:43:01 labo IPCC.xs[1320783]: pam_unix(proxmox-ve-auth:auth): authentication failure; logname= uid=0 euid=0 tty= ruser= rhost=37.167.23.159  user=root&lt;br /&gt;
Dec 14 10:43:03 labo pvedaemon[1320783]: authentication failure; rhost=37.167.23.159 user=root@pam msg=Authentication failure&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Configuration de pveproxy ==&lt;br /&gt;
Si on veut voir l&#039;adresse du client, il faut dire au [https://fr.wikipedia.org/wiki/Daemon_(informatique)| démon] &#039;&#039;pveproxy&#039;&#039; d&#039;utiliser l&#039;une des deux entêtes précédentes ainsi que préciser l&#039;adresse du proxy. &lt;br /&gt;
&lt;br /&gt;
Préciser l&#039;adresse du proxy est essentiel pour que &#039;&#039;pveproxy&#039;&#039; n&#039;accepte de lire l&#039;adresse du client présente dans l&#039;entête &#039;&#039;&#039;uniquement&#039;&#039;&#039; si cela provient du proxy, qui est une machine de confiance. Le cas contraire, tout le monde pourrait ajouter une adresse IP dans l&#039;entête pour la faire bannir...&lt;br /&gt;
&lt;br /&gt;
Nous allons créer le fichier &#039;&#039;/etc/default/pveproxy&#039;&#039; avec les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Forwarded-For&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Real-IP&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_ALLOW_FROM=&amp;quot;192.168.4.100&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il faut maintenant redémarrer &#039;&#039;pveproxy&#039;&#039; pour que les changements s&#039;appliquent. Si vous êtes connecté via l&#039;interface web, cela va vous déconnecter, le temps que le démon redémarre, il faudra ensuite certainement rafraîchir la page web.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl restart pveproxy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à vérifier dans les logs si les bonnes adresses s&#039;affichent:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Si jamais ce n&#039;est pas le cas, poursuivez avec la modification du fichier &#039;&#039;AnyEvent.pm&#039;&#039;&lt;br /&gt;
== Modification de AnyEvent.pm ==&lt;br /&gt;
=== Application de la modification ===&lt;br /&gt;
Au jour d&#039;aujourd&#039;hui (13/12/25) la proxification ne fonctionne plus et il faut apporter une modification dans le fichier &#039;&#039;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&#039;&#039; pour que les bonnes adresses apparaissent !&lt;br /&gt;
En fonction des versions cette modification peut avoir lieu soit ligne &#039;&#039;&#039;1504&#039;&#039;&#039;, soit ligne &#039;&#039;&#039;1554&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Il faut repérer la fonction suivante:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
sub authenticate_and_handle_request {&lt;br /&gt;
    my ($self, $reqstate) = @_;&lt;br /&gt;
&lt;br /&gt;
    my $request = $reqstate-&amp;gt;{request};&lt;br /&gt;
    my $method = $request-&amp;gt;method();&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
C&#039;est un peu plus loin qu&#039;il faut insérer le code :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 ### INSERTION ICI ###&lt;br /&gt;
&lt;br /&gt;
    if ($self-&amp;gt;{spiceproxy}) {&lt;br /&gt;
        my $connect_str = $request-&amp;gt;header(&#039;Host&#039;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il faut modifier l&#039;attribut &#039;&#039;peer_host&#039;&#039; de l&#039;objet &#039;&#039;reqstate&#039;&#039; si l&#039;une des deux entêtes est présente :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if ($request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
} elsif ($request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Double IPv4 ou préfixe IPv6 ===&lt;br /&gt;
Après redémarrage, cela permet de voir l&#039;adresse du client dans les logs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/ext-all.js?ver=7.0.0 HTTP/1.1&amp;quot; 200 683505&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/js/u2f-api.js HTTP/1.1&amp;quot; 200 4898&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/resources HTTP/1.1&amp;quot; 200 1226&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/tasks HTTP/1.1&amp;quot; 200 1090&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /proxmoxlib.js?ver=v5.0.4-t1754316706 HTTP/1.1&amp;quot; 200 157086&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/theme-crisp/resources/theme-crisp-all_1.css HTTP/1.1&amp;quot; 200 32919&lt;br /&gt;
::ffff:192.168.20.22 - root@pam [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/nodes/labo/lxc/100/status/current HTTP/1.1&amp;quot; 200 523&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il nous reste un peu de nettoyage à faire, dans certains cas :&lt;br /&gt;
* l&#039;adresse apparaît non pas une fois mais deux, séparées par une virgule&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
37.167.182.207, 37.167.182.207&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* l&#039;adresse IPv4 (32 bits) est affichée dans sa représentation IPv6 (128 bits), avec le préfixe &#039;&#039;::ffff:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
::ffff:192.168.20.22&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On a deux possibilités pour faire le nettoyage :&lt;br /&gt;
*Soit on ajoute les lignes suivantes dans &#039;&#039;AnyEvent.pm&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if (index($reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
   # Remove trailing ip &lt;br /&gt;
   my @fields = split /,/, $reqstate-&amp;gt;{peer_host};&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $fields[0];&lt;br /&gt;
}&lt;br /&gt;
if($reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
   # Remove IPv6 subnet for IPv4&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $1;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*Soit on modifie le filtre /etc/fail2ban/filter.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=.*:?&amp;lt;HOST&amp;gt;,? user=.* msg=.*&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Automatisation ===&lt;br /&gt;
On peut automatiser le processus précédent avec le script suivant, que l&#039;on peut créer dans /root/remoteip_fix.sh :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=bash&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
ANYEVENT_PATH=&amp;quot;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&amp;quot;&lt;br /&gt;
ANYEVENT_REGEX=&#039;$self-&amp;gt;{spiceproxy}&#039;&lt;br /&gt;
TMP_FILE=&amp;quot;/tmp/AnyEvent.pm.tmp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if [ ! -f $ANYEVENT_PATH ]; then&lt;br /&gt;
  echo &amp;quot;$ANYEVENT_PATH does not exists !&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
if [ $(grep &#039;### BUGFIX REMOTE_IP FOR FAIL2BAN ###&#039; $ANYEVENT_PATH | wc -l) -eq 1 ]; then&lt;br /&gt;
  echo &amp;quot;AnyEvent.pm already patched !&amp;quot;&lt;br /&gt;
  exit 0&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
LINE_NUMBER_TOP=$(nl -ba $ANYEVENT_PATH | grep $ANYEVENT_REGEX | head -n 1 | awk -F &#039; &#039; &#039;{print $1}&#039;)&lt;br /&gt;
let LINE_NUMBER_TOP-=1&lt;br /&gt;
&lt;br /&gt;
if [ $LINE_NUMBER_TOP -lt 0 ]; then&lt;br /&gt;
  echo &amp;quot;Did not find the $ANYEVENT_REGEX expr in $ANYEVENT_PATH&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
echo -n &amp;quot;Applying bugfix: &amp;quot;&lt;br /&gt;
trap &amp;quot;rm -f $TMP_FILE&amp;quot; 0 1 2 5 13 15&lt;br /&gt;
head -n $LINE_NUMBER_TOP $ANYEVENT_PATH &amp;gt;$TMP_FILE&lt;br /&gt;
cat &amp;gt;&amp;gt;$TMP_FILE &amp;lt;&amp;lt;EOF&lt;br /&gt;
### BUGFIX REMOTE_IP FOR FAIL2BAN ###&lt;br /&gt;
    if (\$request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
    } elsif (\$request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
    }&lt;br /&gt;
    if (index(\$reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
        my @fields = split /,/, \$reqstate-&amp;gt;{peer_host};&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$fields[0];&lt;br /&gt;
    }&lt;br /&gt;
    if(\$reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
        # Remove IPv6 subnet for IPv4&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$1;&lt;br /&gt;
    }&lt;br /&gt;
#####################################&lt;br /&gt;
EOF&lt;br /&gt;
echo &amp;quot;$ANYEVENT_MODIF&amp;quot; &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cp $ANYEVENT_PATH $ANYEVENT_PATH.ori&lt;br /&gt;
LINE_NUMBER_BOTTOM=$(cat $ANYEVENT_PATH | wc -l)&lt;br /&gt;
let LINE_NUMBER_BOTTOM-=LINE_NUMBER_TOP&lt;br /&gt;
tail -n $LINE_NUMBER_BOTTOM $ANYEVENT_PATH &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cat $TMP_FILE &amp;gt;$ANYEVENT_PATH&lt;br /&gt;
rm -f $TMP_FILE&lt;br /&gt;
trap 0&lt;br /&gt;
echo &amp;quot;done.&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à le rendre exécutable et le lancer :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# chmod +x /root/remoteip_fix.sh&lt;br /&gt;
# /root/remoteip_fix.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne faudra pas oublier de redémarrer &#039;&#039;pveproxy&#039;&#039; pour appliquer les changements !&lt;br /&gt;
&lt;br /&gt;
== Comment bannir derrière un reverse-proxy ? ==&lt;br /&gt;
Maintenant que votre Proxmox est derrière un reverse-proxy, inutile de bannir les IP publiques avec iptables sur le serveur Proxmox, la seule IP visible est celle du reverse-proxy (dans cet exemple 192.168.4.100).&lt;br /&gt;
&lt;br /&gt;
La seule machine capable capable de bannir est le reverse-proxy, il faut donc lui transmettre les IP et nous allons faire ça en trois étapes:&lt;br /&gt;
* la première est de créer une &amp;quot;prison&amp;quot; proxmox sur le fail2ban présent sur le reverse-proxy&lt;br /&gt;
* la deuxième est l&#039;invention d&#039;une API pour fail2ban sur le reverse-proxy&lt;br /&gt;
* la troisième est la modification du comportement de fail2ban pour appeler cette API au lieu de modifier iptables&lt;br /&gt;
&lt;br /&gt;
=== Création d&#039;une prison sur le reverse-proxy ===&lt;br /&gt;
&lt;br /&gt;
Pour bannir nous allons créer une prison spécifique pour le / les serveurs Proxmox que nous allons appeler &#039;&#039;proxmox&#039;&#039; dans le fichier /etc/fail2ban/jail.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[proxmox]&lt;br /&gt;
enabled = true&lt;br /&gt;
port = https,http&lt;br /&gt;
filter = do-nothing&lt;br /&gt;
logpath = /dev/null&lt;br /&gt;
maxretry = 3&lt;br /&gt;
findtime = 1d&lt;br /&gt;
bantime = 1w&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
J&#039;attire votre attention sur les paramètres &#039;&#039;maxretry&#039;&#039;, &#039;&#039;findtime&#039;&#039; et &#039;&#039;bantime&#039;&#039; qui doivent concorder avec ceux du fail2ban de votre Proxmox. S&#039;il sont plus &#039;&#039;court&#039;&#039; sur le reverse-proxy, les IP seront libérées plus tôt à l&#039;inverse, plus long n&#039;est pas gênant, le fail2ban de votre Proxmox les libéreras avant celui du proxy.&lt;br /&gt;
&lt;br /&gt;
Vous avez remarquez le filtre &#039;&#039;do-nothing&#039;&#039; qu&#039;il nous reste à créer dans le fichier &#039;&#039;/etc/fail2ban/filter.d/do-nothing.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
&lt;br /&gt;
failregex = ^&amp;lt;HOST&amp;gt;$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Après redémarrage de fail2ban :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl restart fail2ban&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous devriez voir la prison&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status&lt;br /&gt;
Status&lt;br /&gt;
|- Number of jail:      2&lt;br /&gt;
`- Jail list:   proxmox, sshd&lt;br /&gt;
[root@proxy proxymox]# &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous pouvons maintenant passer à l&#039;API !&lt;br /&gt;
&lt;br /&gt;
=== Invention d&#039;une API pour fail2ban ===&lt;br /&gt;
&lt;br /&gt;
Toujours sur le reverse-proxy nous allons installer PHP pour créer un mini serveur qui répondra au urls suivantes:&lt;br /&gt;
* /ban/&amp;lt;ip&amp;gt; pour bannir&lt;br /&gt;
* /unban/&amp;lt;ip&amp;gt; pour lever le banissement&lt;br /&gt;
&lt;br /&gt;
Commençons par installer PHP:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# dnf -y install php-cli&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un répertoire &amp;quot;f2b-api&amp;quot; dans le dossier &amp;quot;opt&amp;quot; :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# mkdir /opt/f2b-api&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis créer un fichier &#039;&#039;f2b-api.php&#039;&#039; dans ce dossier:&lt;br /&gt;
&amp;lt;source lang=php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
main();&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        # On clean l&#039;uri du / de début&lt;br /&gt;
        $uri = ltrim($_SERVER[&#039;REQUEST_URI&#039;], &#039;/&#039;);&lt;br /&gt;
        # On éclate l&#039;uri en parties (action + ip)&lt;br /&gt;
        $parts = explode(&#039;/&#039;, $uri);&lt;br /&gt;
        # Récupération de l&#039;action dans une variable ou false si vide&lt;br /&gt;
        $action = empty($parts[0]) ? false : $parts[0];&lt;br /&gt;
        # Récupération de l&#039;ip dans une variable ou false si vide&lt;br /&gt;
        $ip = empty($parts[1]) ? false : $parts[1];&lt;br /&gt;
        if(!$action || !$ip){&lt;br /&gt;
                # Si action vide =&amp;gt; 400 Bad request&lt;br /&gt;
                http_response_code(400);&lt;br /&gt;
                die();&lt;br /&gt;
        }&lt;br /&gt;
        if(!in_array($action, [&#039;ban&#039;, &#039;unban&#039;])){&lt;br /&gt;
                # Si action pas dans la liste =&amp;gt; 400 Bad request&lt;br /&gt;
                http_response_code(400);&lt;br /&gt;
                die();&lt;br /&gt;
        }&lt;br /&gt;
        $cmd = &#039;&#039;;&lt;br /&gt;
        if($action == &#039;ban&#039;){&lt;br /&gt;
                $cmd = &#039;fail2ban-client set proxmox banip &#039; . $ip;&lt;br /&gt;
        } else if($action == &#039;unban&#039;){&lt;br /&gt;
                $cmd = &#039;fail2ban-client unban proxmox &#039; . $ip;&lt;br /&gt;
        }&lt;br /&gt;
        shell_exec($cmd);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
[[Fichier:Warning-icon.png|40px]]  Gardez en tête que ce code simpliste n&#039;est en aucun cas sécurisé et ne doit pas être accessible depuis Internet.&lt;br /&gt;
&lt;br /&gt;
Pour démarrer se code en mode serveur il suffit de taper la commande suivante:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# php -S 0.0.0.0:8080 -t /opt/f2b-api /opt/f2b-api/f2b-api.php&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous pouvez tester directement depuis un autre terminal en tapant les commandes:&lt;br /&gt;
* pour bannir :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# curl -X GET http://127.0.0.1:8080/ban/1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* pour dé-bannir :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# curl -X GET http://127.0.0.1:8080/unban/1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Et en vérifiant dans fail2ban:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed: 0&lt;br /&gt;
|  |- Total failed:     0&lt;br /&gt;
|  `- File list:        /dev/null&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned: 1&lt;br /&gt;
   |- Total banned:     10&lt;br /&gt;
   `- Banned IP list:   1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Nous n&#039;allons pas lancer nous même le serveur PHP, nous allons demander à SystemD de le faire et pour cela nous allons créer le fichier &#039;&#039;/opt/f2b-api/f2b-api.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=fail2ban API Server&lt;br /&gt;
After=network-online.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
UMask=007&lt;br /&gt;
ExecStart=php -S 0.0.0.0:8080 -t /opt/f2b-api /opt/f2b-api/f2b-api.php&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faut maintenant demander à SystemD de s&#039;occuper de notre service:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl link /opt/f2b-api/f2b-api.service&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Et de le lancer au démarrage du reverse-proxy:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl enable f2b-api --now&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous pouvons maintenant nous déplacer sur le serveur Proxmox pour modifier fail2ban !&lt;br /&gt;
&lt;br /&gt;
=== Modification des actions fail2ban ===&lt;br /&gt;
Sur le serveur Proxmox nous allons débrayer le comportement de base de fail2ban qui est de modifier iptables. pour cela nous alons créer le fichier &#039;&#039;/etc/fail2ban/action.d/f2b-api.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
actionstart =&lt;br /&gt;
actionstop =&lt;br /&gt;
actioncheck =&lt;br /&gt;
actionban = curl -X GET 192.168.4.100:8080/ban/&amp;lt;ip&amp;gt;&lt;br /&gt;
actionunban = curl -X GET 192.168.4.100:8080/unban/&amp;lt;ip&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Veuillez noter que:&lt;br /&gt;
* même si elles sont vide, les lignes &#039;&#039;actionstart&#039;&#039;, &#039;&#039;actionstop&#039;&#039; et &#039;&#039;actioncheck&#039;&#039; sont obligatoires !&lt;br /&gt;
* l&#039;adresse &#039;&#039;192.168.4.100&#039;&#039; doit être remplcée par celle de votre reverse-proxy&lt;br /&gt;
* &amp;lt;ip&amp;gt; est l&#039;expression utilisée par fail2ban et elle sera remplacée par l&#039;IP à bannir &lt;br /&gt;
&lt;br /&gt;
Pour ce fichier d&#039;action soit pris en compte, il faut modifier le fichier &#039;&#039;/etc/fail2ban/jail.d/proxmox.conf&#039;&#039; pour y ajouter:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
banaction = f2b-api&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne vous reste plus qu&#039;a redémarrer le service fai2ban sur le serveur Proxmox:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl restart fail2ban&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Et vous pouvez tester les commandes suivantes:&lt;br /&gt;
* pour bannir&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client set proxmox banip 1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* pour dé-bannir:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client unban proxmox 1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Et vérifier sur le reverse-proxy que les modification sont bien prises en compte:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed: 0&lt;br /&gt;
|  |- Total failed:     0&lt;br /&gt;
|  `- File list:        /dev/null&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned: 1&lt;br /&gt;
   |- Total banned:     10&lt;br /&gt;
   `- Banned IP list:   1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4416</id>
		<title>Proxmox fail2ban</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4416"/>
		<updated>2026-07-11T16:53:03Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Modification des actions fail2ban */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
Proxmox utilise une interface web d&#039;administration qui utilise le port TCP 8006 et c&#039;est un vecteur possible d&#039;attaque par force brut. Nous allons donc &#039;&#039;dresser&#039;&#039; fail2ban pour agir en cas d&#039;attaque !&lt;br /&gt;
&lt;br /&gt;
Proxmox utilise Debian, nous allons principalement reproduire les étapes décrites dans le tutoriel de [[Sécuriser_un_service_avec_Fail2ban| Fail2ban pour Rocky]] et adapter à Debian.&lt;br /&gt;
&lt;br /&gt;
Avant d&#039;aller plus loin, assurez-vous d&#039;avoir correctement installé et configuré [[proxmox_iptables |iptables sur Proxmox]]&lt;br /&gt;
&lt;br /&gt;
= Installation =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt -y install fail2ban&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Configuration =&lt;br /&gt;
Tout d&#039;abord il faut copier le fichier &#039;&#039;/etc/fail2ban/jail.conf&#039;&#039; en &#039;&#039;/etc/fail2ban/jail.local&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dans ce fichier, on va s&#039;intéresser aux variables suivantes:&lt;br /&gt;
*ignoreip : correspond à la suite d&#039;adresses IP qui ne se feront jamais bannir;&lt;br /&gt;
*maxretry : correspond au nombre d&#039;essais;&lt;br /&gt;
*findtime : correspond à la période pendant laquelle les essais vont incrémenter maxretry;&lt;br /&gt;
*bantime  : correspond au temps où l&#039;adresse IP ne peut pas se connecter.&lt;br /&gt;
&lt;br /&gt;
= Configuration de base =&lt;br /&gt;
== Choix de la punition ==&lt;br /&gt;
Il faut choisir quelque chose de cohérent (une punition suffisante) pour ne pas permettre de se faire cracker son mot de passe:&lt;br /&gt;
*maxretry = 3&lt;br /&gt;
*findtime = 86400 (correspond à 1 journée)&lt;br /&gt;
*bantime = 604800 (correspond à 1 semaine)&lt;br /&gt;
&lt;br /&gt;
Cela signifie que si une adresse IP se trompe 3 fois en 1 journée (86400s) elle se fait bannir pendant 1 semaine (604800s).&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul permet de trouver le nombre maximal de tentatives durant une année:&lt;br /&gt;
&lt;br /&gt;
365 jours / 7 jours par semaine * 3 tentatives = 156 essais, ce qui reste raisonnable. &lt;br /&gt;
&lt;br /&gt;
Si le pirate possède un [http://fr.wikipedia.org/wiki/Botnet botnet], il faut bien sûr multiplier ce nombre par le nombre de machines dans le botnet...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Attention : fail2ban parcours les logs de connexion pour connaître le numéro de la tentative, ce qui a pour conséquence, si le &#039;&#039;findtime&#039;&#039; est grand, de prendre un certain temps...&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Jail pour SSH ==&lt;br /&gt;
Il suffit d&#039;ajouter la ligne &#039;&#039;enabled=true&#039;&#039; dans la section à activer !&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[sshd]&lt;br /&gt;
&lt;br /&gt;
# To use more aggressive sshd modes set filter parameter &amp;quot;mode&amp;quot; in jail.local:&lt;br /&gt;
# normal (default), ddos, extra or aggressive (combines all).&lt;br /&gt;
# See &amp;quot;tests/files/logs/sshd&amp;quot; or &amp;quot;filter.d/sshd.conf&amp;quot; for usage example and details.&lt;br /&gt;
#mode   = normal&lt;br /&gt;
enabled = true&lt;br /&gt;
port    = ssh&lt;br /&gt;
logpath = %(sshd_log)s&lt;br /&gt;
backend = %(sshd_backend)s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Configuration spécifique =&lt;br /&gt;
== Jail pour PVEPROXY ==&lt;br /&gt;
Pveproxy écoute sur le port 8006 et ne fonctionne pas exactement comme un serveur [[HTTPD | Apache httpd]] qui mettrait ces logs dans le fichier &#039;&#039;error_log&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Nous allons mettre cette configuration spécifique dans le fichier &#039;&#039;/etc/fail2ban/jail.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[proxmox]&lt;br /&gt;
enabled = true&lt;br /&gt;
port = https,http,8006&lt;br /&gt;
filter = proxmox&lt;br /&gt;
backend = systemd&lt;br /&gt;
maxretry = 5&lt;br /&gt;
findtime = 1d&lt;br /&gt;
bantime = 1w&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le backend utilisé est systemd, exactement comme si vous utilisiez la commande :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Filtre pour PVEPROXY ==&lt;br /&gt;
Il ne nous reste plus qu&#039;à spécifier le filtre &#039;&#039;proxmox&#039;&#039; dans le fichier &#039;&#039;/etc/fail2ban/filter.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=&amp;lt;HOST&amp;gt; user=.* msg=.*&lt;br /&gt;
ignoreregex =&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Tests =&lt;br /&gt;
Il faut maintenant tester le filtre et pour ça on peut utiliser un partage de connexion et réaliser le nombre d&#039;échecs spécifié par la directive &amp;quot;maxretry&amp;quot; (ici 3) :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed:	0&lt;br /&gt;
|  |- Total failed:	3&lt;br /&gt;
|  `- Journal matches:	_SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned:	1&lt;br /&gt;
   |- Total banned:	1&lt;br /&gt;
   `- Banned IP list:	37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On voit bien l&#039;IP 37.167.23.159 qui est bannie !&lt;br /&gt;
N&#039;oubliez pas de l&#039;ajouter à &#039;&#039;ignoreip&#039;&#039; dans le fichier &#039;&#039;jails.local&#039;&#039; ou de faire &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client unban 37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Démarrage et enregistrement dans le chargeur de démarrage =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start fail2ban.service&lt;br /&gt;
# systemctl enable fail2ban.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Vous pouvez maintenant démarrer fail2ban&lt;br /&gt;
&lt;br /&gt;
= Proxification=&lt;br /&gt;
Lorsque votre serveur Proxmox se trouve derrière un reverse-proxy (Apache, Nginx, Traefik, ...), au niveau 3 OSI, l&#039;adresse IP du client est remplacée par celle du proxy et le serveur utilise l&#039;entêtes &#039;&#039;X-Forwarded-For&#039;&#039; ou &#039;&#039;X-Real-IP&#039;&#039; pour transporter l&#039;adresse du client &lt;br /&gt;
[[Fichier:Reverse proxy proxmox.png|700px|centré]]&lt;br /&gt;
Le problème est que la seule adresse que fail2ban va voir apparaître dans les logs est celle du reverse-proxy (&#039;&#039;192.168.4.100&#039;&#039;) :&lt;br /&gt;
[[Fichier:Reverse proxy ip logs.png|600px|centré]]&lt;br /&gt;
Même si le filtre &#039;&#039;fail2ban&#039;&#039; est configuré pour utiliser la commande &#039;&#039;journactl&#039;&#039; sur le démon &#039;&#039;pvedaemon&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
les adresses viennent de pveproxy qui journalise tout dans &#039;&#039;/var/log/pveproxy/access.log&#039;&#039; et &#039;&#039;pvedaemon&#039;&#039; ne journalise que les échecs d&#039;authentification. &lt;br /&gt;
Il est donc plus simple de faire un &#039;&#039;tail&#039;&#039; ou un &#039;&#039;cat&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Que d&#039;utiliser &#039;&#039;journalctl&#039;&#039; pour voir les IPs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
Dec 14 10:43:01 labo unix_chkpwd[1326506]: password check failed for user (root)&lt;br /&gt;
Dec 14 10:43:01 labo IPCC.xs[1320783]: pam_unix(proxmox-ve-auth:auth): authentication failure; logname= uid=0 euid=0 tty= ruser= rhost=37.167.23.159  user=root&lt;br /&gt;
Dec 14 10:43:03 labo pvedaemon[1320783]: authentication failure; rhost=37.167.23.159 user=root@pam msg=Authentication failure&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Configuration de pveproxy ==&lt;br /&gt;
Si on veut voir l&#039;adresse du client, il faut dire au [https://fr.wikipedia.org/wiki/Daemon_(informatique)| démon] &#039;&#039;pveproxy&#039;&#039; d&#039;utiliser l&#039;une des deux entêtes précédentes ainsi que préciser l&#039;adresse du proxy. &lt;br /&gt;
&lt;br /&gt;
Préciser l&#039;adresse du proxy est essentiel pour que &#039;&#039;pveproxy&#039;&#039; n&#039;accepte de lire l&#039;adresse du client présente dans l&#039;entête &#039;&#039;&#039;uniquement&#039;&#039;&#039; si cela provient du proxy, qui est une machine de confiance. Le cas contraire, tout le monde pourrait ajouter une adresse IP dans l&#039;entête pour la faire bannir...&lt;br /&gt;
&lt;br /&gt;
Nous allons créer le fichier &#039;&#039;/etc/default/pveproxy&#039;&#039; avec les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Forwarded-For&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Real-IP&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_ALLOW_FROM=&amp;quot;192.168.4.100&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il faut maintenant redémarrer &#039;&#039;pveproxy&#039;&#039; pour que les changements s&#039;appliquent. Si vous êtes connecté via l&#039;interface web, cela va vous déconnecter, le temps que le démon redémarre, il faudra ensuite certainement rafraîchir la page web.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl restart pveproxy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à vérifier dans les logs si les bonnes adresses s&#039;affichent:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Si jamais ce n&#039;est pas le cas, poursuivez avec la modification du fichier &#039;&#039;AnyEvent.pm&#039;&#039;&lt;br /&gt;
== Modification de AnyEvent.pm ==&lt;br /&gt;
=== Application de la modification ===&lt;br /&gt;
Au jour d&#039;aujourd&#039;hui (13/12/25) la proxification ne fonctionne plus et il faut apporter une modification dans le fichier &#039;&#039;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&#039;&#039; pour que les bonnes adresses apparaissent !&lt;br /&gt;
En fonction des versions cette modification peut avoir lieu soit ligne &#039;&#039;&#039;1504&#039;&#039;&#039;, soit ligne &#039;&#039;&#039;1554&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Il faut repérer la fonction suivante:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
sub authenticate_and_handle_request {&lt;br /&gt;
    my ($self, $reqstate) = @_;&lt;br /&gt;
&lt;br /&gt;
    my $request = $reqstate-&amp;gt;{request};&lt;br /&gt;
    my $method = $request-&amp;gt;method();&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
C&#039;est un peu plus loin qu&#039;il faut insérer le code :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 ### INSERTION ICI ###&lt;br /&gt;
&lt;br /&gt;
    if ($self-&amp;gt;{spiceproxy}) {&lt;br /&gt;
        my $connect_str = $request-&amp;gt;header(&#039;Host&#039;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il faut modifier l&#039;attribut &#039;&#039;peer_host&#039;&#039; de l&#039;objet &#039;&#039;reqstate&#039;&#039; si l&#039;une des deux entêtes est présente :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if ($request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
} elsif ($request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Double IPv4 ou préfixe IPv6 ===&lt;br /&gt;
Après redémarrage, cela permet de voir l&#039;adresse du client dans les logs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/ext-all.js?ver=7.0.0 HTTP/1.1&amp;quot; 200 683505&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/js/u2f-api.js HTTP/1.1&amp;quot; 200 4898&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/resources HTTP/1.1&amp;quot; 200 1226&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/tasks HTTP/1.1&amp;quot; 200 1090&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /proxmoxlib.js?ver=v5.0.4-t1754316706 HTTP/1.1&amp;quot; 200 157086&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/theme-crisp/resources/theme-crisp-all_1.css HTTP/1.1&amp;quot; 200 32919&lt;br /&gt;
::ffff:192.168.20.22 - root@pam [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/nodes/labo/lxc/100/status/current HTTP/1.1&amp;quot; 200 523&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il nous reste un peu de nettoyage à faire, dans certains cas :&lt;br /&gt;
* l&#039;adresse apparaît non pas une fois mais deux, séparées par une virgule&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
37.167.182.207, 37.167.182.207&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* l&#039;adresse IPv4 (32 bits) est affichée dans sa représentation IPv6 (128 bits), avec le préfixe &#039;&#039;::ffff:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
::ffff:192.168.20.22&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On a deux possibilités pour faire le nettoyage :&lt;br /&gt;
*Soit on ajoute les lignes suivantes dans &#039;&#039;AnyEvent.pm&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if (index($reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
   # Remove trailing ip &lt;br /&gt;
   my @fields = split /,/, $reqstate-&amp;gt;{peer_host};&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $fields[0];&lt;br /&gt;
}&lt;br /&gt;
if($reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
   # Remove IPv6 subnet for IPv4&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $1;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*Soit on modifie le filtre /etc/fail2ban/filter.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=.*:?&amp;lt;HOST&amp;gt;,? user=.* msg=.*&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Automatisation ===&lt;br /&gt;
On peut automatiser le processus précédent avec le script suivant, que l&#039;on peut créer dans /root/remoteip_fix.sh :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=bash&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
ANYEVENT_PATH=&amp;quot;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&amp;quot;&lt;br /&gt;
ANYEVENT_REGEX=&#039;$self-&amp;gt;{spiceproxy}&#039;&lt;br /&gt;
TMP_FILE=&amp;quot;/tmp/AnyEvent.pm.tmp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if [ ! -f $ANYEVENT_PATH ]; then&lt;br /&gt;
  echo &amp;quot;$ANYEVENT_PATH does not exists !&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
if [ $(grep &#039;### BUGFIX REMOTE_IP FOR FAIL2BAN ###&#039; $ANYEVENT_PATH | wc -l) -eq 1 ]; then&lt;br /&gt;
  echo &amp;quot;AnyEvent.pm already patched !&amp;quot;&lt;br /&gt;
  exit 0&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
LINE_NUMBER_TOP=$(nl -ba $ANYEVENT_PATH | grep $ANYEVENT_REGEX | head -n 1 | awk -F &#039; &#039; &#039;{print $1}&#039;)&lt;br /&gt;
let LINE_NUMBER_TOP-=1&lt;br /&gt;
&lt;br /&gt;
if [ $LINE_NUMBER_TOP -lt 0 ]; then&lt;br /&gt;
  echo &amp;quot;Did not find the $ANYEVENT_REGEX expr in $ANYEVENT_PATH&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
echo -n &amp;quot;Applying bugfix: &amp;quot;&lt;br /&gt;
trap &amp;quot;rm -f $TMP_FILE&amp;quot; 0 1 2 5 13 15&lt;br /&gt;
head -n $LINE_NUMBER_TOP $ANYEVENT_PATH &amp;gt;$TMP_FILE&lt;br /&gt;
cat &amp;gt;&amp;gt;$TMP_FILE &amp;lt;&amp;lt;EOF&lt;br /&gt;
### BUGFIX REMOTE_IP FOR FAIL2BAN ###&lt;br /&gt;
    if (\$request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
    } elsif (\$request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
    }&lt;br /&gt;
    if (index(\$reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
        my @fields = split /,/, \$reqstate-&amp;gt;{peer_host};&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$fields[0];&lt;br /&gt;
    }&lt;br /&gt;
    if(\$reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
        # Remove IPv6 subnet for IPv4&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$1;&lt;br /&gt;
    }&lt;br /&gt;
#####################################&lt;br /&gt;
EOF&lt;br /&gt;
echo &amp;quot;$ANYEVENT_MODIF&amp;quot; &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cp $ANYEVENT_PATH $ANYEVENT_PATH.ori&lt;br /&gt;
LINE_NUMBER_BOTTOM=$(cat $ANYEVENT_PATH | wc -l)&lt;br /&gt;
let LINE_NUMBER_BOTTOM-=LINE_NUMBER_TOP&lt;br /&gt;
tail -n $LINE_NUMBER_BOTTOM $ANYEVENT_PATH &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cat $TMP_FILE &amp;gt;$ANYEVENT_PATH&lt;br /&gt;
rm -f $TMP_FILE&lt;br /&gt;
trap 0&lt;br /&gt;
echo &amp;quot;done.&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à le rendre exécutable et le lancer :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# chmod +x /root/remoteip_fix.sh&lt;br /&gt;
# /root/remoteip_fix.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne faudra pas oublier de redémarrer &#039;&#039;pveproxy&#039;&#039; pour appliquer les changements !&lt;br /&gt;
&lt;br /&gt;
== Comment bannir derrière un reverse-proxy ? ==&lt;br /&gt;
Maintenant que votre Proxmox est derrière un reverse-proxy, inutile de bannir les IP publiques avec iptables sur le serveur Proxmox, la seule IP visible est celle du reverse-proxy (dans cet exemple 192.168.4.100).&lt;br /&gt;
&lt;br /&gt;
La seule machine capable capable de bannir est le reverse-proxy, il faut donc lui transmettre les IP et nous allons faire ça en trois étapes:&lt;br /&gt;
* la première est de créer une &amp;quot;prison&amp;quot; proxmox sur le fail2ban présent sur le reverse-proxy&lt;br /&gt;
* la deuxième est l&#039;invention d&#039;une API pour fail2ban sur le reverse-proxy&lt;br /&gt;
* la troisième est la modification du comportement de fail2ban pour appeler cette API au lieu de modifier iptables&lt;br /&gt;
&lt;br /&gt;
=== Création d&#039;une prison sur le reverse-proxy ===&lt;br /&gt;
&lt;br /&gt;
Pour bannir nous allons créer une prison spécifique pour le / les serveurs Proxmox que nous allons appeler &#039;&#039;proxmox&#039;&#039; dans le fichier /etc/fail2ban/jail.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[proxmox]&lt;br /&gt;
enabled = true&lt;br /&gt;
port = https,http&lt;br /&gt;
filter = do-nothing&lt;br /&gt;
logpath = /dev/null&lt;br /&gt;
maxretry = 3&lt;br /&gt;
findtime = 1d&lt;br /&gt;
bantime = 1w&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
J&#039;attire votre attention sur les paramètres &#039;&#039;maxretry&#039;&#039;, &#039;&#039;findtime&#039;&#039; et &#039;&#039;bantime&#039;&#039; qui doivent concorder avec ceux du fail2ban de votre Proxmox. S&#039;il sont plus &#039;&#039;court&#039;&#039; sur le reverse-proxy, les IP seront libérées plus tôt à l&#039;inverse, plus long n&#039;est pas gênant, le fail2ban de votre Proxmox les libéreras avant celui du proxy.&lt;br /&gt;
&lt;br /&gt;
Vous avez remarquez le filtre &#039;&#039;do-nothing&#039;&#039; qu&#039;il nous reste à créer dans le fichier &#039;&#039;/etc/fail2ban/filter.d/do-nothing.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
&lt;br /&gt;
failregex = ^&amp;lt;HOST&amp;gt;$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Après redémarrage de fail2ban :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl restart fail2ban&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous devriez voir la prison&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status&lt;br /&gt;
Status&lt;br /&gt;
|- Number of jail:      2&lt;br /&gt;
`- Jail list:   proxmox, sshd&lt;br /&gt;
[root@proxy proxymox]# &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous pouvons maintenant passer à l&#039;API !&lt;br /&gt;
&lt;br /&gt;
=== Invention d&#039;une API pour fail2ban ===&lt;br /&gt;
&lt;br /&gt;
Toujours sur le reverse-proxy nous allons installer PHP pour créer un mini serveur qui répondra au urls suivantes:&lt;br /&gt;
* /ban/&amp;lt;ip&amp;gt; pour bannir&lt;br /&gt;
* /unban/&amp;lt;ip&amp;gt; pour lever le banissement&lt;br /&gt;
&lt;br /&gt;
Commençons par installer PHP:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# dnf -y install php-cli&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un répertoire &amp;quot;f2b-api&amp;quot; dans le dossier &amp;quot;opt&amp;quot; :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# mkdir /opt/f2b-api&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis créer un fichier &#039;&#039;f2b-api.php&#039;&#039; dans ce dossier:&lt;br /&gt;
&amp;lt;source lang=php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
main();&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        # On clean l&#039;uri du / de début&lt;br /&gt;
        $uri = ltrim($_SERVER[&#039;REQUEST_URI&#039;], &#039;/&#039;);&lt;br /&gt;
        # On éclate l&#039;uri en parties (action + ip)&lt;br /&gt;
        $parts = explode(&#039;/&#039;, $uri);&lt;br /&gt;
        # Récupération de l&#039;action dans une variable ou false si vide&lt;br /&gt;
        $action = empty($parts[0]) ? false : $parts[0];&lt;br /&gt;
        # Récupération de l&#039;ip dans une variable ou false si vide&lt;br /&gt;
        $ip = empty($parts[1]) ? false : $parts[1];&lt;br /&gt;
        if(!$action || !$ip){&lt;br /&gt;
                # Si action vide =&amp;gt; 400 Bad request&lt;br /&gt;
                http_response_code(400);&lt;br /&gt;
                die();&lt;br /&gt;
        }&lt;br /&gt;
        if(!in_array($action, [&#039;ban&#039;, &#039;unban&#039;])){&lt;br /&gt;
                # Si action pas dans la liste =&amp;gt; 400 Bad request&lt;br /&gt;
                http_response_code(400);&lt;br /&gt;
                die();&lt;br /&gt;
        }&lt;br /&gt;
        $cmd = &#039;&#039;;&lt;br /&gt;
        if($action == &#039;ban&#039;){&lt;br /&gt;
                $cmd = &#039;fail2ban-client set proxmox banip &#039; . $ip;&lt;br /&gt;
        } else if($action == &#039;unban&#039;){&lt;br /&gt;
                $cmd = &#039;fail2ban-client unban proxmox &#039; . $ip;&lt;br /&gt;
        }&lt;br /&gt;
        shell_exec($cmd);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;amp;#9888; Gardez en tête que ce code simpliste n&#039;est en aucun cas sécurisé et ne doit pas être accessible depuis Internet.&lt;br /&gt;
&lt;br /&gt;
Pour démarrer se code en mode serveur il suffit de taper la commande suivante:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# php -S 0.0.0.0:8080 -t /opt/f2b-api /opt/f2b-api/f2b-api.php&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous pouvez tester directement depuis un autre terminal en tapant les commandes:&lt;br /&gt;
* pour bannir :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# curl -X GET http://127.0.0.1:8080/ban/1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* pour dé-bannir :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# curl -X GET http://127.0.0.1:8080/unban/1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Et en vérifiant dans fail2ban:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed: 0&lt;br /&gt;
|  |- Total failed:     0&lt;br /&gt;
|  `- File list:        /dev/null&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned: 1&lt;br /&gt;
   |- Total banned:     10&lt;br /&gt;
   `- Banned IP list:   1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Nous n&#039;allons pas lancer nous même le serveur PHP, nous allons demander à SystemD de le faire et pour cela nous allons créer le fichier &#039;&#039;/opt/f2b-api/f2b-api.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=fail2ban API Server&lt;br /&gt;
After=network-online.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
UMask=007&lt;br /&gt;
ExecStart=php -S 0.0.0.0:8080 -t /opt/f2b-api /opt/f2b-api/f2b-api.php&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faut maintenant demander à SystemD de s&#039;occuper de notre service:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl link /opt/f2b-api/f2b-api.service&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Et de le lancer au démarrage du reverse-proxy:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl enable f2b-api --now&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous pouvons maintenant nous déplacer sur le serveur Proxmox pour modifier fail2ban !&lt;br /&gt;
&lt;br /&gt;
=== Modification des actions fail2ban ===&lt;br /&gt;
Sur le serveur Proxmox nous allons débrayer le comportement de base de fail2ban qui est de modifier iptables. pour cela nous alons créer le fichier &#039;&#039;/etc/fail2ban/action.d/f2b-api.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
actionstart =&lt;br /&gt;
actionstop =&lt;br /&gt;
actioncheck =&lt;br /&gt;
actionban = curl -X GET 192.168.4.100:8080/ban/&amp;lt;ip&amp;gt;&lt;br /&gt;
actionunban = curl -X GET 192.168.4.100:8080/unban/&amp;lt;ip&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Veuillez noter que:&lt;br /&gt;
* même si elles sont vide, les lignes &#039;&#039;actionstart&#039;&#039;, &#039;&#039;actionstop&#039;&#039; et &#039;&#039;actioncheck&#039;&#039; sont obligatoires !&lt;br /&gt;
* l&#039;adresse &#039;&#039;192.168.4.100&#039;&#039; doit être remplcée par celle de votre reverse-proxy&lt;br /&gt;
* &amp;lt;ip&amp;gt; est l&#039;expression utilisée par fail2ban et elle sera remplacée par l&#039;IP à bannir &lt;br /&gt;
&lt;br /&gt;
Pour ce fichier d&#039;action soit pris en compte, il faut modifier le fichier &#039;&#039;/etc/fail2ban/jail.d/proxmox.conf&#039;&#039; pour y ajouter:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
banaction = f2b-api&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne vous reste plus qu&#039;a redémarrer le service fai2ban sur le serveur Proxmox:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl restart fail2ban&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Et vous pouvez tester les commandes suivantes:&lt;br /&gt;
* pour bannir&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client set proxmox banip 1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* pour dé-bannir:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client unban proxmox 1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Et vérifier sur le reverse-proxy que les modification sont bien prises en compte:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed: 0&lt;br /&gt;
|  |- Total failed:     0&lt;br /&gt;
|  `- File list:        /dev/null&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned: 1&lt;br /&gt;
   |- Total banned:     10&lt;br /&gt;
   `- Banned IP list:   1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4415</id>
		<title>Proxmox fail2ban</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4415"/>
		<updated>2026-07-11T16:52:36Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Modification des actions fail2ban */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
Proxmox utilise une interface web d&#039;administration qui utilise le port TCP 8006 et c&#039;est un vecteur possible d&#039;attaque par force brut. Nous allons donc &#039;&#039;dresser&#039;&#039; fail2ban pour agir en cas d&#039;attaque !&lt;br /&gt;
&lt;br /&gt;
Proxmox utilise Debian, nous allons principalement reproduire les étapes décrites dans le tutoriel de [[Sécuriser_un_service_avec_Fail2ban| Fail2ban pour Rocky]] et adapter à Debian.&lt;br /&gt;
&lt;br /&gt;
Avant d&#039;aller plus loin, assurez-vous d&#039;avoir correctement installé et configuré [[proxmox_iptables |iptables sur Proxmox]]&lt;br /&gt;
&lt;br /&gt;
= Installation =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt -y install fail2ban&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Configuration =&lt;br /&gt;
Tout d&#039;abord il faut copier le fichier &#039;&#039;/etc/fail2ban/jail.conf&#039;&#039; en &#039;&#039;/etc/fail2ban/jail.local&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dans ce fichier, on va s&#039;intéresser aux variables suivantes:&lt;br /&gt;
*ignoreip : correspond à la suite d&#039;adresses IP qui ne se feront jamais bannir;&lt;br /&gt;
*maxretry : correspond au nombre d&#039;essais;&lt;br /&gt;
*findtime : correspond à la période pendant laquelle les essais vont incrémenter maxretry;&lt;br /&gt;
*bantime  : correspond au temps où l&#039;adresse IP ne peut pas se connecter.&lt;br /&gt;
&lt;br /&gt;
= Configuration de base =&lt;br /&gt;
== Choix de la punition ==&lt;br /&gt;
Il faut choisir quelque chose de cohérent (une punition suffisante) pour ne pas permettre de se faire cracker son mot de passe:&lt;br /&gt;
*maxretry = 3&lt;br /&gt;
*findtime = 86400 (correspond à 1 journée)&lt;br /&gt;
*bantime = 604800 (correspond à 1 semaine)&lt;br /&gt;
&lt;br /&gt;
Cela signifie que si une adresse IP se trompe 3 fois en 1 journée (86400s) elle se fait bannir pendant 1 semaine (604800s).&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul permet de trouver le nombre maximal de tentatives durant une année:&lt;br /&gt;
&lt;br /&gt;
365 jours / 7 jours par semaine * 3 tentatives = 156 essais, ce qui reste raisonnable. &lt;br /&gt;
&lt;br /&gt;
Si le pirate possède un [http://fr.wikipedia.org/wiki/Botnet botnet], il faut bien sûr multiplier ce nombre par le nombre de machines dans le botnet...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Attention : fail2ban parcours les logs de connexion pour connaître le numéro de la tentative, ce qui a pour conséquence, si le &#039;&#039;findtime&#039;&#039; est grand, de prendre un certain temps...&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Jail pour SSH ==&lt;br /&gt;
Il suffit d&#039;ajouter la ligne &#039;&#039;enabled=true&#039;&#039; dans la section à activer !&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[sshd]&lt;br /&gt;
&lt;br /&gt;
# To use more aggressive sshd modes set filter parameter &amp;quot;mode&amp;quot; in jail.local:&lt;br /&gt;
# normal (default), ddos, extra or aggressive (combines all).&lt;br /&gt;
# See &amp;quot;tests/files/logs/sshd&amp;quot; or &amp;quot;filter.d/sshd.conf&amp;quot; for usage example and details.&lt;br /&gt;
#mode   = normal&lt;br /&gt;
enabled = true&lt;br /&gt;
port    = ssh&lt;br /&gt;
logpath = %(sshd_log)s&lt;br /&gt;
backend = %(sshd_backend)s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Configuration spécifique =&lt;br /&gt;
== Jail pour PVEPROXY ==&lt;br /&gt;
Pveproxy écoute sur le port 8006 et ne fonctionne pas exactement comme un serveur [[HTTPD | Apache httpd]] qui mettrait ces logs dans le fichier &#039;&#039;error_log&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Nous allons mettre cette configuration spécifique dans le fichier &#039;&#039;/etc/fail2ban/jail.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[proxmox]&lt;br /&gt;
enabled = true&lt;br /&gt;
port = https,http,8006&lt;br /&gt;
filter = proxmox&lt;br /&gt;
backend = systemd&lt;br /&gt;
maxretry = 5&lt;br /&gt;
findtime = 1d&lt;br /&gt;
bantime = 1w&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le backend utilisé est systemd, exactement comme si vous utilisiez la commande :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Filtre pour PVEPROXY ==&lt;br /&gt;
Il ne nous reste plus qu&#039;à spécifier le filtre &#039;&#039;proxmox&#039;&#039; dans le fichier &#039;&#039;/etc/fail2ban/filter.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=&amp;lt;HOST&amp;gt; user=.* msg=.*&lt;br /&gt;
ignoreregex =&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Tests =&lt;br /&gt;
Il faut maintenant tester le filtre et pour ça on peut utiliser un partage de connexion et réaliser le nombre d&#039;échecs spécifié par la directive &amp;quot;maxretry&amp;quot; (ici 3) :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed:	0&lt;br /&gt;
|  |- Total failed:	3&lt;br /&gt;
|  `- Journal matches:	_SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned:	1&lt;br /&gt;
   |- Total banned:	1&lt;br /&gt;
   `- Banned IP list:	37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On voit bien l&#039;IP 37.167.23.159 qui est bannie !&lt;br /&gt;
N&#039;oubliez pas de l&#039;ajouter à &#039;&#039;ignoreip&#039;&#039; dans le fichier &#039;&#039;jails.local&#039;&#039; ou de faire &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client unban 37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Démarrage et enregistrement dans le chargeur de démarrage =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start fail2ban.service&lt;br /&gt;
# systemctl enable fail2ban.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Vous pouvez maintenant démarrer fail2ban&lt;br /&gt;
&lt;br /&gt;
= Proxification=&lt;br /&gt;
Lorsque votre serveur Proxmox se trouve derrière un reverse-proxy (Apache, Nginx, Traefik, ...), au niveau 3 OSI, l&#039;adresse IP du client est remplacée par celle du proxy et le serveur utilise l&#039;entêtes &#039;&#039;X-Forwarded-For&#039;&#039; ou &#039;&#039;X-Real-IP&#039;&#039; pour transporter l&#039;adresse du client &lt;br /&gt;
[[Fichier:Reverse proxy proxmox.png|700px|centré]]&lt;br /&gt;
Le problème est que la seule adresse que fail2ban va voir apparaître dans les logs est celle du reverse-proxy (&#039;&#039;192.168.4.100&#039;&#039;) :&lt;br /&gt;
[[Fichier:Reverse proxy ip logs.png|600px|centré]]&lt;br /&gt;
Même si le filtre &#039;&#039;fail2ban&#039;&#039; est configuré pour utiliser la commande &#039;&#039;journactl&#039;&#039; sur le démon &#039;&#039;pvedaemon&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
les adresses viennent de pveproxy qui journalise tout dans &#039;&#039;/var/log/pveproxy/access.log&#039;&#039; et &#039;&#039;pvedaemon&#039;&#039; ne journalise que les échecs d&#039;authentification. &lt;br /&gt;
Il est donc plus simple de faire un &#039;&#039;tail&#039;&#039; ou un &#039;&#039;cat&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Que d&#039;utiliser &#039;&#039;journalctl&#039;&#039; pour voir les IPs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
Dec 14 10:43:01 labo unix_chkpwd[1326506]: password check failed for user (root)&lt;br /&gt;
Dec 14 10:43:01 labo IPCC.xs[1320783]: pam_unix(proxmox-ve-auth:auth): authentication failure; logname= uid=0 euid=0 tty= ruser= rhost=37.167.23.159  user=root&lt;br /&gt;
Dec 14 10:43:03 labo pvedaemon[1320783]: authentication failure; rhost=37.167.23.159 user=root@pam msg=Authentication failure&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Configuration de pveproxy ==&lt;br /&gt;
Si on veut voir l&#039;adresse du client, il faut dire au [https://fr.wikipedia.org/wiki/Daemon_(informatique)| démon] &#039;&#039;pveproxy&#039;&#039; d&#039;utiliser l&#039;une des deux entêtes précédentes ainsi que préciser l&#039;adresse du proxy. &lt;br /&gt;
&lt;br /&gt;
Préciser l&#039;adresse du proxy est essentiel pour que &#039;&#039;pveproxy&#039;&#039; n&#039;accepte de lire l&#039;adresse du client présente dans l&#039;entête &#039;&#039;&#039;uniquement&#039;&#039;&#039; si cela provient du proxy, qui est une machine de confiance. Le cas contraire, tout le monde pourrait ajouter une adresse IP dans l&#039;entête pour la faire bannir...&lt;br /&gt;
&lt;br /&gt;
Nous allons créer le fichier &#039;&#039;/etc/default/pveproxy&#039;&#039; avec les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Forwarded-For&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Real-IP&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_ALLOW_FROM=&amp;quot;192.168.4.100&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il faut maintenant redémarrer &#039;&#039;pveproxy&#039;&#039; pour que les changements s&#039;appliquent. Si vous êtes connecté via l&#039;interface web, cela va vous déconnecter, le temps que le démon redémarre, il faudra ensuite certainement rafraîchir la page web.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl restart pveproxy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à vérifier dans les logs si les bonnes adresses s&#039;affichent:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Si jamais ce n&#039;est pas le cas, poursuivez avec la modification du fichier &#039;&#039;AnyEvent.pm&#039;&#039;&lt;br /&gt;
== Modification de AnyEvent.pm ==&lt;br /&gt;
=== Application de la modification ===&lt;br /&gt;
Au jour d&#039;aujourd&#039;hui (13/12/25) la proxification ne fonctionne plus et il faut apporter une modification dans le fichier &#039;&#039;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&#039;&#039; pour que les bonnes adresses apparaissent !&lt;br /&gt;
En fonction des versions cette modification peut avoir lieu soit ligne &#039;&#039;&#039;1504&#039;&#039;&#039;, soit ligne &#039;&#039;&#039;1554&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Il faut repérer la fonction suivante:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
sub authenticate_and_handle_request {&lt;br /&gt;
    my ($self, $reqstate) = @_;&lt;br /&gt;
&lt;br /&gt;
    my $request = $reqstate-&amp;gt;{request};&lt;br /&gt;
    my $method = $request-&amp;gt;method();&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
C&#039;est un peu plus loin qu&#039;il faut insérer le code :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 ### INSERTION ICI ###&lt;br /&gt;
&lt;br /&gt;
    if ($self-&amp;gt;{spiceproxy}) {&lt;br /&gt;
        my $connect_str = $request-&amp;gt;header(&#039;Host&#039;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il faut modifier l&#039;attribut &#039;&#039;peer_host&#039;&#039; de l&#039;objet &#039;&#039;reqstate&#039;&#039; si l&#039;une des deux entêtes est présente :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if ($request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
} elsif ($request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Double IPv4 ou préfixe IPv6 ===&lt;br /&gt;
Après redémarrage, cela permet de voir l&#039;adresse du client dans les logs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/ext-all.js?ver=7.0.0 HTTP/1.1&amp;quot; 200 683505&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/js/u2f-api.js HTTP/1.1&amp;quot; 200 4898&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/resources HTTP/1.1&amp;quot; 200 1226&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/tasks HTTP/1.1&amp;quot; 200 1090&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /proxmoxlib.js?ver=v5.0.4-t1754316706 HTTP/1.1&amp;quot; 200 157086&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/theme-crisp/resources/theme-crisp-all_1.css HTTP/1.1&amp;quot; 200 32919&lt;br /&gt;
::ffff:192.168.20.22 - root@pam [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/nodes/labo/lxc/100/status/current HTTP/1.1&amp;quot; 200 523&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il nous reste un peu de nettoyage à faire, dans certains cas :&lt;br /&gt;
* l&#039;adresse apparaît non pas une fois mais deux, séparées par une virgule&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
37.167.182.207, 37.167.182.207&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* l&#039;adresse IPv4 (32 bits) est affichée dans sa représentation IPv6 (128 bits), avec le préfixe &#039;&#039;::ffff:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
::ffff:192.168.20.22&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On a deux possibilités pour faire le nettoyage :&lt;br /&gt;
*Soit on ajoute les lignes suivantes dans &#039;&#039;AnyEvent.pm&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if (index($reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
   # Remove trailing ip &lt;br /&gt;
   my @fields = split /,/, $reqstate-&amp;gt;{peer_host};&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $fields[0];&lt;br /&gt;
}&lt;br /&gt;
if($reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
   # Remove IPv6 subnet for IPv4&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $1;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*Soit on modifie le filtre /etc/fail2ban/filter.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=.*:?&amp;lt;HOST&amp;gt;,? user=.* msg=.*&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Automatisation ===&lt;br /&gt;
On peut automatiser le processus précédent avec le script suivant, que l&#039;on peut créer dans /root/remoteip_fix.sh :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=bash&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
ANYEVENT_PATH=&amp;quot;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&amp;quot;&lt;br /&gt;
ANYEVENT_REGEX=&#039;$self-&amp;gt;{spiceproxy}&#039;&lt;br /&gt;
TMP_FILE=&amp;quot;/tmp/AnyEvent.pm.tmp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if [ ! -f $ANYEVENT_PATH ]; then&lt;br /&gt;
  echo &amp;quot;$ANYEVENT_PATH does not exists !&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
if [ $(grep &#039;### BUGFIX REMOTE_IP FOR FAIL2BAN ###&#039; $ANYEVENT_PATH | wc -l) -eq 1 ]; then&lt;br /&gt;
  echo &amp;quot;AnyEvent.pm already patched !&amp;quot;&lt;br /&gt;
  exit 0&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
LINE_NUMBER_TOP=$(nl -ba $ANYEVENT_PATH | grep $ANYEVENT_REGEX | head -n 1 | awk -F &#039; &#039; &#039;{print $1}&#039;)&lt;br /&gt;
let LINE_NUMBER_TOP-=1&lt;br /&gt;
&lt;br /&gt;
if [ $LINE_NUMBER_TOP -lt 0 ]; then&lt;br /&gt;
  echo &amp;quot;Did not find the $ANYEVENT_REGEX expr in $ANYEVENT_PATH&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
echo -n &amp;quot;Applying bugfix: &amp;quot;&lt;br /&gt;
trap &amp;quot;rm -f $TMP_FILE&amp;quot; 0 1 2 5 13 15&lt;br /&gt;
head -n $LINE_NUMBER_TOP $ANYEVENT_PATH &amp;gt;$TMP_FILE&lt;br /&gt;
cat &amp;gt;&amp;gt;$TMP_FILE &amp;lt;&amp;lt;EOF&lt;br /&gt;
### BUGFIX REMOTE_IP FOR FAIL2BAN ###&lt;br /&gt;
    if (\$request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
    } elsif (\$request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
    }&lt;br /&gt;
    if (index(\$reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
        my @fields = split /,/, \$reqstate-&amp;gt;{peer_host};&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$fields[0];&lt;br /&gt;
    }&lt;br /&gt;
    if(\$reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
        # Remove IPv6 subnet for IPv4&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$1;&lt;br /&gt;
    }&lt;br /&gt;
#####################################&lt;br /&gt;
EOF&lt;br /&gt;
echo &amp;quot;$ANYEVENT_MODIF&amp;quot; &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cp $ANYEVENT_PATH $ANYEVENT_PATH.ori&lt;br /&gt;
LINE_NUMBER_BOTTOM=$(cat $ANYEVENT_PATH | wc -l)&lt;br /&gt;
let LINE_NUMBER_BOTTOM-=LINE_NUMBER_TOP&lt;br /&gt;
tail -n $LINE_NUMBER_BOTTOM $ANYEVENT_PATH &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cat $TMP_FILE &amp;gt;$ANYEVENT_PATH&lt;br /&gt;
rm -f $TMP_FILE&lt;br /&gt;
trap 0&lt;br /&gt;
echo &amp;quot;done.&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à le rendre exécutable et le lancer :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# chmod +x /root/remoteip_fix.sh&lt;br /&gt;
# /root/remoteip_fix.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne faudra pas oublier de redémarrer &#039;&#039;pveproxy&#039;&#039; pour appliquer les changements !&lt;br /&gt;
&lt;br /&gt;
== Comment bannir derrière un reverse-proxy ? ==&lt;br /&gt;
Maintenant que votre Proxmox est derrière un reverse-proxy, inutile de bannir les IP publiques avec iptables sur le serveur Proxmox, la seule IP visible est celle du reverse-proxy (dans cet exemple 192.168.4.100).&lt;br /&gt;
&lt;br /&gt;
La seule machine capable capable de bannir est le reverse-proxy, il faut donc lui transmettre les IP et nous allons faire ça en trois étapes:&lt;br /&gt;
* la première est de créer une &amp;quot;prison&amp;quot; proxmox sur le fail2ban présent sur le reverse-proxy&lt;br /&gt;
* la deuxième est l&#039;invention d&#039;une API pour fail2ban sur le reverse-proxy&lt;br /&gt;
* la troisième est la modification du comportement de fail2ban pour appeler cette API au lieu de modifier iptables&lt;br /&gt;
&lt;br /&gt;
=== Création d&#039;une prison sur le reverse-proxy ===&lt;br /&gt;
&lt;br /&gt;
Pour bannir nous allons créer une prison spécifique pour le / les serveurs Proxmox que nous allons appeler &#039;&#039;proxmox&#039;&#039; dans le fichier /etc/fail2ban/jail.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[proxmox]&lt;br /&gt;
enabled = true&lt;br /&gt;
port = https,http&lt;br /&gt;
filter = do-nothing&lt;br /&gt;
logpath = /dev/null&lt;br /&gt;
maxretry = 3&lt;br /&gt;
findtime = 1d&lt;br /&gt;
bantime = 1w&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
J&#039;attire votre attention sur les paramètres &#039;&#039;maxretry&#039;&#039;, &#039;&#039;findtime&#039;&#039; et &#039;&#039;bantime&#039;&#039; qui doivent concorder avec ceux du fail2ban de votre Proxmox. S&#039;il sont plus &#039;&#039;court&#039;&#039; sur le reverse-proxy, les IP seront libérées plus tôt à l&#039;inverse, plus long n&#039;est pas gênant, le fail2ban de votre Proxmox les libéreras avant celui du proxy.&lt;br /&gt;
&lt;br /&gt;
Vous avez remarquez le filtre &#039;&#039;do-nothing&#039;&#039; qu&#039;il nous reste à créer dans le fichier &#039;&#039;/etc/fail2ban/filter.d/do-nothing.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
&lt;br /&gt;
failregex = ^&amp;lt;HOST&amp;gt;$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Après redémarrage de fail2ban :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl restart fail2ban&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous devriez voir la prison&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status&lt;br /&gt;
Status&lt;br /&gt;
|- Number of jail:      2&lt;br /&gt;
`- Jail list:   proxmox, sshd&lt;br /&gt;
[root@proxy proxymox]# &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous pouvons maintenant passer à l&#039;API !&lt;br /&gt;
&lt;br /&gt;
=== Invention d&#039;une API pour fail2ban ===&lt;br /&gt;
&lt;br /&gt;
Toujours sur le reverse-proxy nous allons installer PHP pour créer un mini serveur qui répondra au urls suivantes:&lt;br /&gt;
* /ban/&amp;lt;ip&amp;gt; pour bannir&lt;br /&gt;
* /unban/&amp;lt;ip&amp;gt; pour lever le banissement&lt;br /&gt;
&lt;br /&gt;
Commençons par installer PHP:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# dnf -y install php-cli&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un répertoire &amp;quot;f2b-api&amp;quot; dans le dossier &amp;quot;opt&amp;quot; :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# mkdir /opt/f2b-api&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis créer un fichier &#039;&#039;f2b-api.php&#039;&#039; dans ce dossier:&lt;br /&gt;
&amp;lt;source lang=php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
main();&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        # On clean l&#039;uri du / de début&lt;br /&gt;
        $uri = ltrim($_SERVER[&#039;REQUEST_URI&#039;], &#039;/&#039;);&lt;br /&gt;
        # On éclate l&#039;uri en parties (action + ip)&lt;br /&gt;
        $parts = explode(&#039;/&#039;, $uri);&lt;br /&gt;
        # Récupération de l&#039;action dans une variable ou false si vide&lt;br /&gt;
        $action = empty($parts[0]) ? false : $parts[0];&lt;br /&gt;
        # Récupération de l&#039;ip dans une variable ou false si vide&lt;br /&gt;
        $ip = empty($parts[1]) ? false : $parts[1];&lt;br /&gt;
        if(!$action || !$ip){&lt;br /&gt;
                # Si action vide =&amp;gt; 400 Bad request&lt;br /&gt;
                http_response_code(400);&lt;br /&gt;
                die();&lt;br /&gt;
        }&lt;br /&gt;
        if(!in_array($action, [&#039;ban&#039;, &#039;unban&#039;])){&lt;br /&gt;
                # Si action pas dans la liste =&amp;gt; 400 Bad request&lt;br /&gt;
                http_response_code(400);&lt;br /&gt;
                die();&lt;br /&gt;
        }&lt;br /&gt;
        $cmd = &#039;&#039;;&lt;br /&gt;
        if($action == &#039;ban&#039;){&lt;br /&gt;
                $cmd = &#039;fail2ban-client set proxmox banip &#039; . $ip;&lt;br /&gt;
        } else if($action == &#039;unban&#039;){&lt;br /&gt;
                $cmd = &#039;fail2ban-client unban proxmox &#039; . $ip;&lt;br /&gt;
        }&lt;br /&gt;
        shell_exec($cmd);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;amp;#9888; Gardez en tête que ce code simpliste n&#039;est en aucun cas sécurisé et ne doit pas être accessible depuis Internet.&lt;br /&gt;
&lt;br /&gt;
Pour démarrer se code en mode serveur il suffit de taper la commande suivante:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# php -S 0.0.0.0:8080 -t /opt/f2b-api /opt/f2b-api/f2b-api.php&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous pouvez tester directement depuis un autre terminal en tapant les commandes:&lt;br /&gt;
* pour bannir :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# curl -X GET http://127.0.0.1:8080/ban/1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* pour dé-bannir :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# curl -X GET http://127.0.0.1:8080/unban/1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Et en vérifiant dans fail2ban:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed: 0&lt;br /&gt;
|  |- Total failed:     0&lt;br /&gt;
|  `- File list:        /dev/null&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned: 1&lt;br /&gt;
   |- Total banned:     10&lt;br /&gt;
   `- Banned IP list:   1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Nous n&#039;allons pas lancer nous même le serveur PHP, nous allons demander à SystemD de le faire et pour cela nous allons créer le fichier &#039;&#039;/opt/f2b-api/f2b-api.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=fail2ban API Server&lt;br /&gt;
After=network-online.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
UMask=007&lt;br /&gt;
ExecStart=php -S 0.0.0.0:8080 -t /opt/f2b-api /opt/f2b-api/f2b-api.php&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faut maintenant demander à SystemD de s&#039;occuper de notre service:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl link /opt/f2b-api/f2b-api.service&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Et de le lancer au démarrage du reverse-proxy:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl enable f2b-api --now&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous pouvons maintenant nous déplacer sur le serveur Proxmox pour modifier fail2ban !&lt;br /&gt;
&lt;br /&gt;
=== Modification des actions fail2ban ===&lt;br /&gt;
Sur le serveur Proxmox nous allons débrayer le comportement de base de fail2ban qui est de modifier iptables. pour cela nous alons créer le fichier &#039;&#039;/etc/fail2ban/action.d/f2b-api.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
actionstart =&lt;br /&gt;
actionstop =&lt;br /&gt;
actioncheck =&lt;br /&gt;
actionban = curl -X GET 192.168.4.100:8080/ban/&amp;lt;ip&amp;gt;&lt;br /&gt;
actionunban = curl -X GET 192.168.4.100:8080/unban/&amp;lt;ip&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Veuillez noter que:&lt;br /&gt;
* même si elles sont vide, les lignes &#039;&#039;actionstart&#039;&#039;, &#039;&#039;actionstop&#039;&#039; et &#039;&#039;actioncheck&#039;&#039; sont obligatoires !&lt;br /&gt;
* l&#039;adresse &#039;&#039;192.168.4.100&#039;&#039; doit être remplcée par celle de votre reverse-proxy&lt;br /&gt;
* &amp;lt;ip&amp;gt; est l&#039;expression utilisée par fail2ban et elle sera remplacée par l&#039;IP à bannir &lt;br /&gt;
&lt;br /&gt;
Pour ce fichier d&#039;action soit pris en compte, il faut modifier le fichier &#039;&#039;/etc/fail2ban/jail.d/proxmox.conf&#039;&#039; pour y ajouter:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
banaction = f2b-api&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne vous reste plus qu&#039;a redémarrer le service fai2ban sur le serveur Proxmox:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl restart fail2ban&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Et vous pouvez tester les commandes suivantes:&lt;br /&gt;
* pour bannir&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client set proxmox banip 1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* pour dé-bannir:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client unban proxmox 1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Et vérifier sur le reverse-proxy que les modification sont bien prises en compte:&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4414</id>
		<title>Proxmox fail2ban</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4414"/>
		<updated>2026-07-11T16:50:54Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Modification des actions fail2ban */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
Proxmox utilise une interface web d&#039;administration qui utilise le port TCP 8006 et c&#039;est un vecteur possible d&#039;attaque par force brut. Nous allons donc &#039;&#039;dresser&#039;&#039; fail2ban pour agir en cas d&#039;attaque !&lt;br /&gt;
&lt;br /&gt;
Proxmox utilise Debian, nous allons principalement reproduire les étapes décrites dans le tutoriel de [[Sécuriser_un_service_avec_Fail2ban| Fail2ban pour Rocky]] et adapter à Debian.&lt;br /&gt;
&lt;br /&gt;
Avant d&#039;aller plus loin, assurez-vous d&#039;avoir correctement installé et configuré [[proxmox_iptables |iptables sur Proxmox]]&lt;br /&gt;
&lt;br /&gt;
= Installation =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt -y install fail2ban&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Configuration =&lt;br /&gt;
Tout d&#039;abord il faut copier le fichier &#039;&#039;/etc/fail2ban/jail.conf&#039;&#039; en &#039;&#039;/etc/fail2ban/jail.local&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dans ce fichier, on va s&#039;intéresser aux variables suivantes:&lt;br /&gt;
*ignoreip : correspond à la suite d&#039;adresses IP qui ne se feront jamais bannir;&lt;br /&gt;
*maxretry : correspond au nombre d&#039;essais;&lt;br /&gt;
*findtime : correspond à la période pendant laquelle les essais vont incrémenter maxretry;&lt;br /&gt;
*bantime  : correspond au temps où l&#039;adresse IP ne peut pas se connecter.&lt;br /&gt;
&lt;br /&gt;
= Configuration de base =&lt;br /&gt;
== Choix de la punition ==&lt;br /&gt;
Il faut choisir quelque chose de cohérent (une punition suffisante) pour ne pas permettre de se faire cracker son mot de passe:&lt;br /&gt;
*maxretry = 3&lt;br /&gt;
*findtime = 86400 (correspond à 1 journée)&lt;br /&gt;
*bantime = 604800 (correspond à 1 semaine)&lt;br /&gt;
&lt;br /&gt;
Cela signifie que si une adresse IP se trompe 3 fois en 1 journée (86400s) elle se fait bannir pendant 1 semaine (604800s).&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul permet de trouver le nombre maximal de tentatives durant une année:&lt;br /&gt;
&lt;br /&gt;
365 jours / 7 jours par semaine * 3 tentatives = 156 essais, ce qui reste raisonnable. &lt;br /&gt;
&lt;br /&gt;
Si le pirate possède un [http://fr.wikipedia.org/wiki/Botnet botnet], il faut bien sûr multiplier ce nombre par le nombre de machines dans le botnet...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Attention : fail2ban parcours les logs de connexion pour connaître le numéro de la tentative, ce qui a pour conséquence, si le &#039;&#039;findtime&#039;&#039; est grand, de prendre un certain temps...&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Jail pour SSH ==&lt;br /&gt;
Il suffit d&#039;ajouter la ligne &#039;&#039;enabled=true&#039;&#039; dans la section à activer !&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[sshd]&lt;br /&gt;
&lt;br /&gt;
# To use more aggressive sshd modes set filter parameter &amp;quot;mode&amp;quot; in jail.local:&lt;br /&gt;
# normal (default), ddos, extra or aggressive (combines all).&lt;br /&gt;
# See &amp;quot;tests/files/logs/sshd&amp;quot; or &amp;quot;filter.d/sshd.conf&amp;quot; for usage example and details.&lt;br /&gt;
#mode   = normal&lt;br /&gt;
enabled = true&lt;br /&gt;
port    = ssh&lt;br /&gt;
logpath = %(sshd_log)s&lt;br /&gt;
backend = %(sshd_backend)s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Configuration spécifique =&lt;br /&gt;
== Jail pour PVEPROXY ==&lt;br /&gt;
Pveproxy écoute sur le port 8006 et ne fonctionne pas exactement comme un serveur [[HTTPD | Apache httpd]] qui mettrait ces logs dans le fichier &#039;&#039;error_log&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Nous allons mettre cette configuration spécifique dans le fichier &#039;&#039;/etc/fail2ban/jail.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[proxmox]&lt;br /&gt;
enabled = true&lt;br /&gt;
port = https,http,8006&lt;br /&gt;
filter = proxmox&lt;br /&gt;
backend = systemd&lt;br /&gt;
maxretry = 5&lt;br /&gt;
findtime = 1d&lt;br /&gt;
bantime = 1w&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le backend utilisé est systemd, exactement comme si vous utilisiez la commande :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Filtre pour PVEPROXY ==&lt;br /&gt;
Il ne nous reste plus qu&#039;à spécifier le filtre &#039;&#039;proxmox&#039;&#039; dans le fichier &#039;&#039;/etc/fail2ban/filter.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=&amp;lt;HOST&amp;gt; user=.* msg=.*&lt;br /&gt;
ignoreregex =&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Tests =&lt;br /&gt;
Il faut maintenant tester le filtre et pour ça on peut utiliser un partage de connexion et réaliser le nombre d&#039;échecs spécifié par la directive &amp;quot;maxretry&amp;quot; (ici 3) :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed:	0&lt;br /&gt;
|  |- Total failed:	3&lt;br /&gt;
|  `- Journal matches:	_SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned:	1&lt;br /&gt;
   |- Total banned:	1&lt;br /&gt;
   `- Banned IP list:	37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On voit bien l&#039;IP 37.167.23.159 qui est bannie !&lt;br /&gt;
N&#039;oubliez pas de l&#039;ajouter à &#039;&#039;ignoreip&#039;&#039; dans le fichier &#039;&#039;jails.local&#039;&#039; ou de faire &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client unban 37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Démarrage et enregistrement dans le chargeur de démarrage =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start fail2ban.service&lt;br /&gt;
# systemctl enable fail2ban.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Vous pouvez maintenant démarrer fail2ban&lt;br /&gt;
&lt;br /&gt;
= Proxification=&lt;br /&gt;
Lorsque votre serveur Proxmox se trouve derrière un reverse-proxy (Apache, Nginx, Traefik, ...), au niveau 3 OSI, l&#039;adresse IP du client est remplacée par celle du proxy et le serveur utilise l&#039;entêtes &#039;&#039;X-Forwarded-For&#039;&#039; ou &#039;&#039;X-Real-IP&#039;&#039; pour transporter l&#039;adresse du client &lt;br /&gt;
[[Fichier:Reverse proxy proxmox.png|700px|centré]]&lt;br /&gt;
Le problème est que la seule adresse que fail2ban va voir apparaître dans les logs est celle du reverse-proxy (&#039;&#039;192.168.4.100&#039;&#039;) :&lt;br /&gt;
[[Fichier:Reverse proxy ip logs.png|600px|centré]]&lt;br /&gt;
Même si le filtre &#039;&#039;fail2ban&#039;&#039; est configuré pour utiliser la commande &#039;&#039;journactl&#039;&#039; sur le démon &#039;&#039;pvedaemon&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
les adresses viennent de pveproxy qui journalise tout dans &#039;&#039;/var/log/pveproxy/access.log&#039;&#039; et &#039;&#039;pvedaemon&#039;&#039; ne journalise que les échecs d&#039;authentification. &lt;br /&gt;
Il est donc plus simple de faire un &#039;&#039;tail&#039;&#039; ou un &#039;&#039;cat&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Que d&#039;utiliser &#039;&#039;journalctl&#039;&#039; pour voir les IPs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
Dec 14 10:43:01 labo unix_chkpwd[1326506]: password check failed for user (root)&lt;br /&gt;
Dec 14 10:43:01 labo IPCC.xs[1320783]: pam_unix(proxmox-ve-auth:auth): authentication failure; logname= uid=0 euid=0 tty= ruser= rhost=37.167.23.159  user=root&lt;br /&gt;
Dec 14 10:43:03 labo pvedaemon[1320783]: authentication failure; rhost=37.167.23.159 user=root@pam msg=Authentication failure&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Configuration de pveproxy ==&lt;br /&gt;
Si on veut voir l&#039;adresse du client, il faut dire au [https://fr.wikipedia.org/wiki/Daemon_(informatique)| démon] &#039;&#039;pveproxy&#039;&#039; d&#039;utiliser l&#039;une des deux entêtes précédentes ainsi que préciser l&#039;adresse du proxy. &lt;br /&gt;
&lt;br /&gt;
Préciser l&#039;adresse du proxy est essentiel pour que &#039;&#039;pveproxy&#039;&#039; n&#039;accepte de lire l&#039;adresse du client présente dans l&#039;entête &#039;&#039;&#039;uniquement&#039;&#039;&#039; si cela provient du proxy, qui est une machine de confiance. Le cas contraire, tout le monde pourrait ajouter une adresse IP dans l&#039;entête pour la faire bannir...&lt;br /&gt;
&lt;br /&gt;
Nous allons créer le fichier &#039;&#039;/etc/default/pveproxy&#039;&#039; avec les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Forwarded-For&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Real-IP&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_ALLOW_FROM=&amp;quot;192.168.4.100&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il faut maintenant redémarrer &#039;&#039;pveproxy&#039;&#039; pour que les changements s&#039;appliquent. Si vous êtes connecté via l&#039;interface web, cela va vous déconnecter, le temps que le démon redémarre, il faudra ensuite certainement rafraîchir la page web.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl restart pveproxy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à vérifier dans les logs si les bonnes adresses s&#039;affichent:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Si jamais ce n&#039;est pas le cas, poursuivez avec la modification du fichier &#039;&#039;AnyEvent.pm&#039;&#039;&lt;br /&gt;
== Modification de AnyEvent.pm ==&lt;br /&gt;
=== Application de la modification ===&lt;br /&gt;
Au jour d&#039;aujourd&#039;hui (13/12/25) la proxification ne fonctionne plus et il faut apporter une modification dans le fichier &#039;&#039;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&#039;&#039; pour que les bonnes adresses apparaissent !&lt;br /&gt;
En fonction des versions cette modification peut avoir lieu soit ligne &#039;&#039;&#039;1504&#039;&#039;&#039;, soit ligne &#039;&#039;&#039;1554&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Il faut repérer la fonction suivante:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
sub authenticate_and_handle_request {&lt;br /&gt;
    my ($self, $reqstate) = @_;&lt;br /&gt;
&lt;br /&gt;
    my $request = $reqstate-&amp;gt;{request};&lt;br /&gt;
    my $method = $request-&amp;gt;method();&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
C&#039;est un peu plus loin qu&#039;il faut insérer le code :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 ### INSERTION ICI ###&lt;br /&gt;
&lt;br /&gt;
    if ($self-&amp;gt;{spiceproxy}) {&lt;br /&gt;
        my $connect_str = $request-&amp;gt;header(&#039;Host&#039;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il faut modifier l&#039;attribut &#039;&#039;peer_host&#039;&#039; de l&#039;objet &#039;&#039;reqstate&#039;&#039; si l&#039;une des deux entêtes est présente :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if ($request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
} elsif ($request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Double IPv4 ou préfixe IPv6 ===&lt;br /&gt;
Après redémarrage, cela permet de voir l&#039;adresse du client dans les logs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/ext-all.js?ver=7.0.0 HTTP/1.1&amp;quot; 200 683505&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/js/u2f-api.js HTTP/1.1&amp;quot; 200 4898&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/resources HTTP/1.1&amp;quot; 200 1226&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/tasks HTTP/1.1&amp;quot; 200 1090&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /proxmoxlib.js?ver=v5.0.4-t1754316706 HTTP/1.1&amp;quot; 200 157086&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/theme-crisp/resources/theme-crisp-all_1.css HTTP/1.1&amp;quot; 200 32919&lt;br /&gt;
::ffff:192.168.20.22 - root@pam [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/nodes/labo/lxc/100/status/current HTTP/1.1&amp;quot; 200 523&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il nous reste un peu de nettoyage à faire, dans certains cas :&lt;br /&gt;
* l&#039;adresse apparaît non pas une fois mais deux, séparées par une virgule&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
37.167.182.207, 37.167.182.207&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* l&#039;adresse IPv4 (32 bits) est affichée dans sa représentation IPv6 (128 bits), avec le préfixe &#039;&#039;::ffff:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
::ffff:192.168.20.22&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On a deux possibilités pour faire le nettoyage :&lt;br /&gt;
*Soit on ajoute les lignes suivantes dans &#039;&#039;AnyEvent.pm&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if (index($reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
   # Remove trailing ip &lt;br /&gt;
   my @fields = split /,/, $reqstate-&amp;gt;{peer_host};&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $fields[0];&lt;br /&gt;
}&lt;br /&gt;
if($reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
   # Remove IPv6 subnet for IPv4&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $1;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*Soit on modifie le filtre /etc/fail2ban/filter.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=.*:?&amp;lt;HOST&amp;gt;,? user=.* msg=.*&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Automatisation ===&lt;br /&gt;
On peut automatiser le processus précédent avec le script suivant, que l&#039;on peut créer dans /root/remoteip_fix.sh :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=bash&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
ANYEVENT_PATH=&amp;quot;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&amp;quot;&lt;br /&gt;
ANYEVENT_REGEX=&#039;$self-&amp;gt;{spiceproxy}&#039;&lt;br /&gt;
TMP_FILE=&amp;quot;/tmp/AnyEvent.pm.tmp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if [ ! -f $ANYEVENT_PATH ]; then&lt;br /&gt;
  echo &amp;quot;$ANYEVENT_PATH does not exists !&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
if [ $(grep &#039;### BUGFIX REMOTE_IP FOR FAIL2BAN ###&#039; $ANYEVENT_PATH | wc -l) -eq 1 ]; then&lt;br /&gt;
  echo &amp;quot;AnyEvent.pm already patched !&amp;quot;&lt;br /&gt;
  exit 0&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
LINE_NUMBER_TOP=$(nl -ba $ANYEVENT_PATH | grep $ANYEVENT_REGEX | head -n 1 | awk -F &#039; &#039; &#039;{print $1}&#039;)&lt;br /&gt;
let LINE_NUMBER_TOP-=1&lt;br /&gt;
&lt;br /&gt;
if [ $LINE_NUMBER_TOP -lt 0 ]; then&lt;br /&gt;
  echo &amp;quot;Did not find the $ANYEVENT_REGEX expr in $ANYEVENT_PATH&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
echo -n &amp;quot;Applying bugfix: &amp;quot;&lt;br /&gt;
trap &amp;quot;rm -f $TMP_FILE&amp;quot; 0 1 2 5 13 15&lt;br /&gt;
head -n $LINE_NUMBER_TOP $ANYEVENT_PATH &amp;gt;$TMP_FILE&lt;br /&gt;
cat &amp;gt;&amp;gt;$TMP_FILE &amp;lt;&amp;lt;EOF&lt;br /&gt;
### BUGFIX REMOTE_IP FOR FAIL2BAN ###&lt;br /&gt;
    if (\$request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
    } elsif (\$request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
    }&lt;br /&gt;
    if (index(\$reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
        my @fields = split /,/, \$reqstate-&amp;gt;{peer_host};&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$fields[0];&lt;br /&gt;
    }&lt;br /&gt;
    if(\$reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
        # Remove IPv6 subnet for IPv4&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$1;&lt;br /&gt;
    }&lt;br /&gt;
#####################################&lt;br /&gt;
EOF&lt;br /&gt;
echo &amp;quot;$ANYEVENT_MODIF&amp;quot; &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cp $ANYEVENT_PATH $ANYEVENT_PATH.ori&lt;br /&gt;
LINE_NUMBER_BOTTOM=$(cat $ANYEVENT_PATH | wc -l)&lt;br /&gt;
let LINE_NUMBER_BOTTOM-=LINE_NUMBER_TOP&lt;br /&gt;
tail -n $LINE_NUMBER_BOTTOM $ANYEVENT_PATH &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cat $TMP_FILE &amp;gt;$ANYEVENT_PATH&lt;br /&gt;
rm -f $TMP_FILE&lt;br /&gt;
trap 0&lt;br /&gt;
echo &amp;quot;done.&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à le rendre exécutable et le lancer :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# chmod +x /root/remoteip_fix.sh&lt;br /&gt;
# /root/remoteip_fix.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne faudra pas oublier de redémarrer &#039;&#039;pveproxy&#039;&#039; pour appliquer les changements !&lt;br /&gt;
&lt;br /&gt;
== Comment bannir derrière un reverse-proxy ? ==&lt;br /&gt;
Maintenant que votre Proxmox est derrière un reverse-proxy, inutile de bannir les IP publiques avec iptables sur le serveur Proxmox, la seule IP visible est celle du reverse-proxy (dans cet exemple 192.168.4.100).&lt;br /&gt;
&lt;br /&gt;
La seule machine capable capable de bannir est le reverse-proxy, il faut donc lui transmettre les IP et nous allons faire ça en trois étapes:&lt;br /&gt;
* la première est de créer une &amp;quot;prison&amp;quot; proxmox sur le fail2ban présent sur le reverse-proxy&lt;br /&gt;
* la deuxième est l&#039;invention d&#039;une API pour fail2ban sur le reverse-proxy&lt;br /&gt;
* la troisième est la modification du comportement de fail2ban pour appeler cette API au lieu de modifier iptables&lt;br /&gt;
&lt;br /&gt;
=== Création d&#039;une prison sur le reverse-proxy ===&lt;br /&gt;
&lt;br /&gt;
Pour bannir nous allons créer une prison spécifique pour le / les serveurs Proxmox que nous allons appeler &#039;&#039;proxmox&#039;&#039; dans le fichier /etc/fail2ban/jail.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[proxmox]&lt;br /&gt;
enabled = true&lt;br /&gt;
port = https,http&lt;br /&gt;
filter = do-nothing&lt;br /&gt;
logpath = /dev/null&lt;br /&gt;
maxretry = 3&lt;br /&gt;
findtime = 1d&lt;br /&gt;
bantime = 1w&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
J&#039;attire votre attention sur les paramètres &#039;&#039;maxretry&#039;&#039;, &#039;&#039;findtime&#039;&#039; et &#039;&#039;bantime&#039;&#039; qui doivent concorder avec ceux du fail2ban de votre Proxmox. S&#039;il sont plus &#039;&#039;court&#039;&#039; sur le reverse-proxy, les IP seront libérées plus tôt à l&#039;inverse, plus long n&#039;est pas gênant, le fail2ban de votre Proxmox les libéreras avant celui du proxy.&lt;br /&gt;
&lt;br /&gt;
Vous avez remarquez le filtre &#039;&#039;do-nothing&#039;&#039; qu&#039;il nous reste à créer dans le fichier &#039;&#039;/etc/fail2ban/filter.d/do-nothing.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
&lt;br /&gt;
failregex = ^&amp;lt;HOST&amp;gt;$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Après redémarrage de fail2ban :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl restart fail2ban&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous devriez voir la prison&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status&lt;br /&gt;
Status&lt;br /&gt;
|- Number of jail:      2&lt;br /&gt;
`- Jail list:   proxmox, sshd&lt;br /&gt;
[root@proxy proxymox]# &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous pouvons maintenant passer à l&#039;API !&lt;br /&gt;
&lt;br /&gt;
=== Invention d&#039;une API pour fail2ban ===&lt;br /&gt;
&lt;br /&gt;
Toujours sur le reverse-proxy nous allons installer PHP pour créer un mini serveur qui répondra au urls suivantes:&lt;br /&gt;
* /ban/&amp;lt;ip&amp;gt; pour bannir&lt;br /&gt;
* /unban/&amp;lt;ip&amp;gt; pour lever le banissement&lt;br /&gt;
&lt;br /&gt;
Commençons par installer PHP:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# dnf -y install php-cli&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un répertoire &amp;quot;f2b-api&amp;quot; dans le dossier &amp;quot;opt&amp;quot; :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# mkdir /opt/f2b-api&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis créer un fichier &#039;&#039;f2b-api.php&#039;&#039; dans ce dossier:&lt;br /&gt;
&amp;lt;source lang=php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
main();&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        # On clean l&#039;uri du / de début&lt;br /&gt;
        $uri = ltrim($_SERVER[&#039;REQUEST_URI&#039;], &#039;/&#039;);&lt;br /&gt;
        # On éclate l&#039;uri en parties (action + ip)&lt;br /&gt;
        $parts = explode(&#039;/&#039;, $uri);&lt;br /&gt;
        # Récupération de l&#039;action dans une variable ou false si vide&lt;br /&gt;
        $action = empty($parts[0]) ? false : $parts[0];&lt;br /&gt;
        # Récupération de l&#039;ip dans une variable ou false si vide&lt;br /&gt;
        $ip = empty($parts[1]) ? false : $parts[1];&lt;br /&gt;
        if(!$action || !$ip){&lt;br /&gt;
                # Si action vide =&amp;gt; 400 Bad request&lt;br /&gt;
                http_response_code(400);&lt;br /&gt;
                die();&lt;br /&gt;
        }&lt;br /&gt;
        if(!in_array($action, [&#039;ban&#039;, &#039;unban&#039;])){&lt;br /&gt;
                # Si action pas dans la liste =&amp;gt; 400 Bad request&lt;br /&gt;
                http_response_code(400);&lt;br /&gt;
                die();&lt;br /&gt;
        }&lt;br /&gt;
        $cmd = &#039;&#039;;&lt;br /&gt;
        if($action == &#039;ban&#039;){&lt;br /&gt;
                $cmd = &#039;fail2ban-client set proxmox banip &#039; . $ip;&lt;br /&gt;
        } else if($action == &#039;unban&#039;){&lt;br /&gt;
                $cmd = &#039;fail2ban-client unban proxmox &#039; . $ip;&lt;br /&gt;
        }&lt;br /&gt;
        shell_exec($cmd);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;amp;#9888; Gardez en tête que ce code simpliste n&#039;est en aucun cas sécurisé et ne doit pas être accessible depuis Internet.&lt;br /&gt;
&lt;br /&gt;
Pour démarrer se code en mode serveur il suffit de taper la commande suivante:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# php -S 0.0.0.0:8080 -t /opt/f2b-api /opt/f2b-api/f2b-api.php&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous pouvez tester directement depuis un autre terminal en tapant les commandes:&lt;br /&gt;
* pour bannir :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# curl -X GET http://127.0.0.1:8080/ban/1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* pour dé-bannir :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# curl -X GET http://127.0.0.1:8080/unban/1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Et en vérifiant dans fail2ban:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed: 0&lt;br /&gt;
|  |- Total failed:     0&lt;br /&gt;
|  `- File list:        /dev/null&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned: 1&lt;br /&gt;
   |- Total banned:     10&lt;br /&gt;
   `- Banned IP list:   1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Nous n&#039;allons pas lancer nous même le serveur PHP, nous allons demander à SystemD de le faire et pour cela nous allons créer le fichier &#039;&#039;/opt/f2b-api/f2b-api.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=fail2ban API Server&lt;br /&gt;
After=network-online.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
UMask=007&lt;br /&gt;
ExecStart=php -S 0.0.0.0:8080 -t /opt/f2b-api /opt/f2b-api/f2b-api.php&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faut maintenant demander à SystemD de s&#039;occuper de notre service:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl link /opt/f2b-api/f2b-api.service&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Et de le lancer au démarrage du reverse-proxy:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl enable f2b-api --now&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous pouvons maintenant nous déplacer sur le serveur Proxmox pour modifier fail2ban !&lt;br /&gt;
&lt;br /&gt;
=== Modification des actions fail2ban ===&lt;br /&gt;
Sur le serveur Proxmox nous allons débrayer le comportement de base de fail2ban qui est de modifier iptables. pour cela nous alons créer le fichier &#039;&#039;/etc/fail2ban/action.d/f2b-api.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
actionstart =&lt;br /&gt;
actionstop =&lt;br /&gt;
actioncheck =&lt;br /&gt;
actionban = curl -X GET 192.168.4.100:8080/ban/&amp;lt;ip&amp;gt;&lt;br /&gt;
actionunban = curl -X GET 192.168.4.100:8080/unban/&amp;lt;ip&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Veuillez noter que:&lt;br /&gt;
* même si elles sont vide, les lignes &#039;&#039;actionstart&#039;&#039;, &#039;&#039;actionstop&#039;&#039; et &#039;&#039;actioncheck&#039;&#039; sont obligatoires !&lt;br /&gt;
* l&#039;adresse &#039;&#039;192.168.4.100&#039;&#039; doit être remplcée par celle de votre reverse-proxy&lt;br /&gt;
* &amp;lt;ip&amp;gt; est l&#039;expression utilisée par fail2ban et elle sera remplacée par l&#039;IP à bannir &lt;br /&gt;
&lt;br /&gt;
Pour ce fichier d&#039;action soit pris en compte, il faut modifier le fichier &#039;&#039;/etc/fail2ban/jail.d/proxmox.conf&#039;&#039; pour y ajouter:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
banaction = f2b-api&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne vous reste plus qu&#039;a redémarrer le service fai2ban sur le serveur Proxmox:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl restart fail2ban&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Et vous pouvez tester les commandes suivantes:&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4413</id>
		<title>Proxmox fail2ban</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4413"/>
		<updated>2026-07-11T16:50:10Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Modification des actions fail2ban */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
Proxmox utilise une interface web d&#039;administration qui utilise le port TCP 8006 et c&#039;est un vecteur possible d&#039;attaque par force brut. Nous allons donc &#039;&#039;dresser&#039;&#039; fail2ban pour agir en cas d&#039;attaque !&lt;br /&gt;
&lt;br /&gt;
Proxmox utilise Debian, nous allons principalement reproduire les étapes décrites dans le tutoriel de [[Sécuriser_un_service_avec_Fail2ban| Fail2ban pour Rocky]] et adapter à Debian.&lt;br /&gt;
&lt;br /&gt;
Avant d&#039;aller plus loin, assurez-vous d&#039;avoir correctement installé et configuré [[proxmox_iptables |iptables sur Proxmox]]&lt;br /&gt;
&lt;br /&gt;
= Installation =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt -y install fail2ban&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Configuration =&lt;br /&gt;
Tout d&#039;abord il faut copier le fichier &#039;&#039;/etc/fail2ban/jail.conf&#039;&#039; en &#039;&#039;/etc/fail2ban/jail.local&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dans ce fichier, on va s&#039;intéresser aux variables suivantes:&lt;br /&gt;
*ignoreip : correspond à la suite d&#039;adresses IP qui ne se feront jamais bannir;&lt;br /&gt;
*maxretry : correspond au nombre d&#039;essais;&lt;br /&gt;
*findtime : correspond à la période pendant laquelle les essais vont incrémenter maxretry;&lt;br /&gt;
*bantime  : correspond au temps où l&#039;adresse IP ne peut pas se connecter.&lt;br /&gt;
&lt;br /&gt;
= Configuration de base =&lt;br /&gt;
== Choix de la punition ==&lt;br /&gt;
Il faut choisir quelque chose de cohérent (une punition suffisante) pour ne pas permettre de se faire cracker son mot de passe:&lt;br /&gt;
*maxretry = 3&lt;br /&gt;
*findtime = 86400 (correspond à 1 journée)&lt;br /&gt;
*bantime = 604800 (correspond à 1 semaine)&lt;br /&gt;
&lt;br /&gt;
Cela signifie que si une adresse IP se trompe 3 fois en 1 journée (86400s) elle se fait bannir pendant 1 semaine (604800s).&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul permet de trouver le nombre maximal de tentatives durant une année:&lt;br /&gt;
&lt;br /&gt;
365 jours / 7 jours par semaine * 3 tentatives = 156 essais, ce qui reste raisonnable. &lt;br /&gt;
&lt;br /&gt;
Si le pirate possède un [http://fr.wikipedia.org/wiki/Botnet botnet], il faut bien sûr multiplier ce nombre par le nombre de machines dans le botnet...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Attention : fail2ban parcours les logs de connexion pour connaître le numéro de la tentative, ce qui a pour conséquence, si le &#039;&#039;findtime&#039;&#039; est grand, de prendre un certain temps...&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Jail pour SSH ==&lt;br /&gt;
Il suffit d&#039;ajouter la ligne &#039;&#039;enabled=true&#039;&#039; dans la section à activer !&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[sshd]&lt;br /&gt;
&lt;br /&gt;
# To use more aggressive sshd modes set filter parameter &amp;quot;mode&amp;quot; in jail.local:&lt;br /&gt;
# normal (default), ddos, extra or aggressive (combines all).&lt;br /&gt;
# See &amp;quot;tests/files/logs/sshd&amp;quot; or &amp;quot;filter.d/sshd.conf&amp;quot; for usage example and details.&lt;br /&gt;
#mode   = normal&lt;br /&gt;
enabled = true&lt;br /&gt;
port    = ssh&lt;br /&gt;
logpath = %(sshd_log)s&lt;br /&gt;
backend = %(sshd_backend)s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Configuration spécifique =&lt;br /&gt;
== Jail pour PVEPROXY ==&lt;br /&gt;
Pveproxy écoute sur le port 8006 et ne fonctionne pas exactement comme un serveur [[HTTPD | Apache httpd]] qui mettrait ces logs dans le fichier &#039;&#039;error_log&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Nous allons mettre cette configuration spécifique dans le fichier &#039;&#039;/etc/fail2ban/jail.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[proxmox]&lt;br /&gt;
enabled = true&lt;br /&gt;
port = https,http,8006&lt;br /&gt;
filter = proxmox&lt;br /&gt;
backend = systemd&lt;br /&gt;
maxretry = 5&lt;br /&gt;
findtime = 1d&lt;br /&gt;
bantime = 1w&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le backend utilisé est systemd, exactement comme si vous utilisiez la commande :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Filtre pour PVEPROXY ==&lt;br /&gt;
Il ne nous reste plus qu&#039;à spécifier le filtre &#039;&#039;proxmox&#039;&#039; dans le fichier &#039;&#039;/etc/fail2ban/filter.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=&amp;lt;HOST&amp;gt; user=.* msg=.*&lt;br /&gt;
ignoreregex =&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Tests =&lt;br /&gt;
Il faut maintenant tester le filtre et pour ça on peut utiliser un partage de connexion et réaliser le nombre d&#039;échecs spécifié par la directive &amp;quot;maxretry&amp;quot; (ici 3) :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed:	0&lt;br /&gt;
|  |- Total failed:	3&lt;br /&gt;
|  `- Journal matches:	_SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned:	1&lt;br /&gt;
   |- Total banned:	1&lt;br /&gt;
   `- Banned IP list:	37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On voit bien l&#039;IP 37.167.23.159 qui est bannie !&lt;br /&gt;
N&#039;oubliez pas de l&#039;ajouter à &#039;&#039;ignoreip&#039;&#039; dans le fichier &#039;&#039;jails.local&#039;&#039; ou de faire &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client unban 37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Démarrage et enregistrement dans le chargeur de démarrage =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start fail2ban.service&lt;br /&gt;
# systemctl enable fail2ban.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Vous pouvez maintenant démarrer fail2ban&lt;br /&gt;
&lt;br /&gt;
= Proxification=&lt;br /&gt;
Lorsque votre serveur Proxmox se trouve derrière un reverse-proxy (Apache, Nginx, Traefik, ...), au niveau 3 OSI, l&#039;adresse IP du client est remplacée par celle du proxy et le serveur utilise l&#039;entêtes &#039;&#039;X-Forwarded-For&#039;&#039; ou &#039;&#039;X-Real-IP&#039;&#039; pour transporter l&#039;adresse du client &lt;br /&gt;
[[Fichier:Reverse proxy proxmox.png|700px|centré]]&lt;br /&gt;
Le problème est que la seule adresse que fail2ban va voir apparaître dans les logs est celle du reverse-proxy (&#039;&#039;192.168.4.100&#039;&#039;) :&lt;br /&gt;
[[Fichier:Reverse proxy ip logs.png|600px|centré]]&lt;br /&gt;
Même si le filtre &#039;&#039;fail2ban&#039;&#039; est configuré pour utiliser la commande &#039;&#039;journactl&#039;&#039; sur le démon &#039;&#039;pvedaemon&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
les adresses viennent de pveproxy qui journalise tout dans &#039;&#039;/var/log/pveproxy/access.log&#039;&#039; et &#039;&#039;pvedaemon&#039;&#039; ne journalise que les échecs d&#039;authentification. &lt;br /&gt;
Il est donc plus simple de faire un &#039;&#039;tail&#039;&#039; ou un &#039;&#039;cat&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Que d&#039;utiliser &#039;&#039;journalctl&#039;&#039; pour voir les IPs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
Dec 14 10:43:01 labo unix_chkpwd[1326506]: password check failed for user (root)&lt;br /&gt;
Dec 14 10:43:01 labo IPCC.xs[1320783]: pam_unix(proxmox-ve-auth:auth): authentication failure; logname= uid=0 euid=0 tty= ruser= rhost=37.167.23.159  user=root&lt;br /&gt;
Dec 14 10:43:03 labo pvedaemon[1320783]: authentication failure; rhost=37.167.23.159 user=root@pam msg=Authentication failure&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Configuration de pveproxy ==&lt;br /&gt;
Si on veut voir l&#039;adresse du client, il faut dire au [https://fr.wikipedia.org/wiki/Daemon_(informatique)| démon] &#039;&#039;pveproxy&#039;&#039; d&#039;utiliser l&#039;une des deux entêtes précédentes ainsi que préciser l&#039;adresse du proxy. &lt;br /&gt;
&lt;br /&gt;
Préciser l&#039;adresse du proxy est essentiel pour que &#039;&#039;pveproxy&#039;&#039; n&#039;accepte de lire l&#039;adresse du client présente dans l&#039;entête &#039;&#039;&#039;uniquement&#039;&#039;&#039; si cela provient du proxy, qui est une machine de confiance. Le cas contraire, tout le monde pourrait ajouter une adresse IP dans l&#039;entête pour la faire bannir...&lt;br /&gt;
&lt;br /&gt;
Nous allons créer le fichier &#039;&#039;/etc/default/pveproxy&#039;&#039; avec les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Forwarded-For&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Real-IP&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_ALLOW_FROM=&amp;quot;192.168.4.100&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il faut maintenant redémarrer &#039;&#039;pveproxy&#039;&#039; pour que les changements s&#039;appliquent. Si vous êtes connecté via l&#039;interface web, cela va vous déconnecter, le temps que le démon redémarre, il faudra ensuite certainement rafraîchir la page web.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl restart pveproxy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à vérifier dans les logs si les bonnes adresses s&#039;affichent:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Si jamais ce n&#039;est pas le cas, poursuivez avec la modification du fichier &#039;&#039;AnyEvent.pm&#039;&#039;&lt;br /&gt;
== Modification de AnyEvent.pm ==&lt;br /&gt;
=== Application de la modification ===&lt;br /&gt;
Au jour d&#039;aujourd&#039;hui (13/12/25) la proxification ne fonctionne plus et il faut apporter une modification dans le fichier &#039;&#039;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&#039;&#039; pour que les bonnes adresses apparaissent !&lt;br /&gt;
En fonction des versions cette modification peut avoir lieu soit ligne &#039;&#039;&#039;1504&#039;&#039;&#039;, soit ligne &#039;&#039;&#039;1554&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Il faut repérer la fonction suivante:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
sub authenticate_and_handle_request {&lt;br /&gt;
    my ($self, $reqstate) = @_;&lt;br /&gt;
&lt;br /&gt;
    my $request = $reqstate-&amp;gt;{request};&lt;br /&gt;
    my $method = $request-&amp;gt;method();&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
C&#039;est un peu plus loin qu&#039;il faut insérer le code :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 ### INSERTION ICI ###&lt;br /&gt;
&lt;br /&gt;
    if ($self-&amp;gt;{spiceproxy}) {&lt;br /&gt;
        my $connect_str = $request-&amp;gt;header(&#039;Host&#039;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il faut modifier l&#039;attribut &#039;&#039;peer_host&#039;&#039; de l&#039;objet &#039;&#039;reqstate&#039;&#039; si l&#039;une des deux entêtes est présente :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if ($request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
} elsif ($request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Double IPv4 ou préfixe IPv6 ===&lt;br /&gt;
Après redémarrage, cela permet de voir l&#039;adresse du client dans les logs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/ext-all.js?ver=7.0.0 HTTP/1.1&amp;quot; 200 683505&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/js/u2f-api.js HTTP/1.1&amp;quot; 200 4898&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/resources HTTP/1.1&amp;quot; 200 1226&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/tasks HTTP/1.1&amp;quot; 200 1090&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /proxmoxlib.js?ver=v5.0.4-t1754316706 HTTP/1.1&amp;quot; 200 157086&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/theme-crisp/resources/theme-crisp-all_1.css HTTP/1.1&amp;quot; 200 32919&lt;br /&gt;
::ffff:192.168.20.22 - root@pam [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/nodes/labo/lxc/100/status/current HTTP/1.1&amp;quot; 200 523&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il nous reste un peu de nettoyage à faire, dans certains cas :&lt;br /&gt;
* l&#039;adresse apparaît non pas une fois mais deux, séparées par une virgule&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
37.167.182.207, 37.167.182.207&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* l&#039;adresse IPv4 (32 bits) est affichée dans sa représentation IPv6 (128 bits), avec le préfixe &#039;&#039;::ffff:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
::ffff:192.168.20.22&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On a deux possibilités pour faire le nettoyage :&lt;br /&gt;
*Soit on ajoute les lignes suivantes dans &#039;&#039;AnyEvent.pm&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if (index($reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
   # Remove trailing ip &lt;br /&gt;
   my @fields = split /,/, $reqstate-&amp;gt;{peer_host};&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $fields[0];&lt;br /&gt;
}&lt;br /&gt;
if($reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
   # Remove IPv6 subnet for IPv4&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $1;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*Soit on modifie le filtre /etc/fail2ban/filter.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=.*:?&amp;lt;HOST&amp;gt;,? user=.* msg=.*&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Automatisation ===&lt;br /&gt;
On peut automatiser le processus précédent avec le script suivant, que l&#039;on peut créer dans /root/remoteip_fix.sh :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=bash&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
ANYEVENT_PATH=&amp;quot;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&amp;quot;&lt;br /&gt;
ANYEVENT_REGEX=&#039;$self-&amp;gt;{spiceproxy}&#039;&lt;br /&gt;
TMP_FILE=&amp;quot;/tmp/AnyEvent.pm.tmp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if [ ! -f $ANYEVENT_PATH ]; then&lt;br /&gt;
  echo &amp;quot;$ANYEVENT_PATH does not exists !&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
if [ $(grep &#039;### BUGFIX REMOTE_IP FOR FAIL2BAN ###&#039; $ANYEVENT_PATH | wc -l) -eq 1 ]; then&lt;br /&gt;
  echo &amp;quot;AnyEvent.pm already patched !&amp;quot;&lt;br /&gt;
  exit 0&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
LINE_NUMBER_TOP=$(nl -ba $ANYEVENT_PATH | grep $ANYEVENT_REGEX | head -n 1 | awk -F &#039; &#039; &#039;{print $1}&#039;)&lt;br /&gt;
let LINE_NUMBER_TOP-=1&lt;br /&gt;
&lt;br /&gt;
if [ $LINE_NUMBER_TOP -lt 0 ]; then&lt;br /&gt;
  echo &amp;quot;Did not find the $ANYEVENT_REGEX expr in $ANYEVENT_PATH&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
echo -n &amp;quot;Applying bugfix: &amp;quot;&lt;br /&gt;
trap &amp;quot;rm -f $TMP_FILE&amp;quot; 0 1 2 5 13 15&lt;br /&gt;
head -n $LINE_NUMBER_TOP $ANYEVENT_PATH &amp;gt;$TMP_FILE&lt;br /&gt;
cat &amp;gt;&amp;gt;$TMP_FILE &amp;lt;&amp;lt;EOF&lt;br /&gt;
### BUGFIX REMOTE_IP FOR FAIL2BAN ###&lt;br /&gt;
    if (\$request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
    } elsif (\$request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
    }&lt;br /&gt;
    if (index(\$reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
        my @fields = split /,/, \$reqstate-&amp;gt;{peer_host};&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$fields[0];&lt;br /&gt;
    }&lt;br /&gt;
    if(\$reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
        # Remove IPv6 subnet for IPv4&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$1;&lt;br /&gt;
    }&lt;br /&gt;
#####################################&lt;br /&gt;
EOF&lt;br /&gt;
echo &amp;quot;$ANYEVENT_MODIF&amp;quot; &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cp $ANYEVENT_PATH $ANYEVENT_PATH.ori&lt;br /&gt;
LINE_NUMBER_BOTTOM=$(cat $ANYEVENT_PATH | wc -l)&lt;br /&gt;
let LINE_NUMBER_BOTTOM-=LINE_NUMBER_TOP&lt;br /&gt;
tail -n $LINE_NUMBER_BOTTOM $ANYEVENT_PATH &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cat $TMP_FILE &amp;gt;$ANYEVENT_PATH&lt;br /&gt;
rm -f $TMP_FILE&lt;br /&gt;
trap 0&lt;br /&gt;
echo &amp;quot;done.&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à le rendre exécutable et le lancer :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# chmod +x /root/remoteip_fix.sh&lt;br /&gt;
# /root/remoteip_fix.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne faudra pas oublier de redémarrer &#039;&#039;pveproxy&#039;&#039; pour appliquer les changements !&lt;br /&gt;
&lt;br /&gt;
== Comment bannir derrière un reverse-proxy ? ==&lt;br /&gt;
Maintenant que votre Proxmox est derrière un reverse-proxy, inutile de bannir les IP publiques avec iptables sur le serveur Proxmox, la seule IP visible est celle du reverse-proxy (dans cet exemple 192.168.4.100).&lt;br /&gt;
&lt;br /&gt;
La seule machine capable capable de bannir est le reverse-proxy, il faut donc lui transmettre les IP et nous allons faire ça en trois étapes:&lt;br /&gt;
* la première est de créer une &amp;quot;prison&amp;quot; proxmox sur le fail2ban présent sur le reverse-proxy&lt;br /&gt;
* la deuxième est l&#039;invention d&#039;une API pour fail2ban sur le reverse-proxy&lt;br /&gt;
* la troisième est la modification du comportement de fail2ban pour appeler cette API au lieu de modifier iptables&lt;br /&gt;
&lt;br /&gt;
=== Création d&#039;une prison sur le reverse-proxy ===&lt;br /&gt;
&lt;br /&gt;
Pour bannir nous allons créer une prison spécifique pour le / les serveurs Proxmox que nous allons appeler &#039;&#039;proxmox&#039;&#039; dans le fichier /etc/fail2ban/jail.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[proxmox]&lt;br /&gt;
enabled = true&lt;br /&gt;
port = https,http&lt;br /&gt;
filter = do-nothing&lt;br /&gt;
logpath = /dev/null&lt;br /&gt;
maxretry = 3&lt;br /&gt;
findtime = 1d&lt;br /&gt;
bantime = 1w&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
J&#039;attire votre attention sur les paramètres &#039;&#039;maxretry&#039;&#039;, &#039;&#039;findtime&#039;&#039; et &#039;&#039;bantime&#039;&#039; qui doivent concorder avec ceux du fail2ban de votre Proxmox. S&#039;il sont plus &#039;&#039;court&#039;&#039; sur le reverse-proxy, les IP seront libérées plus tôt à l&#039;inverse, plus long n&#039;est pas gênant, le fail2ban de votre Proxmox les libéreras avant celui du proxy.&lt;br /&gt;
&lt;br /&gt;
Vous avez remarquez le filtre &#039;&#039;do-nothing&#039;&#039; qu&#039;il nous reste à créer dans le fichier &#039;&#039;/etc/fail2ban/filter.d/do-nothing.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
&lt;br /&gt;
failregex = ^&amp;lt;HOST&amp;gt;$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Après redémarrage de fail2ban :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl restart fail2ban&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous devriez voir la prison&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status&lt;br /&gt;
Status&lt;br /&gt;
|- Number of jail:      2&lt;br /&gt;
`- Jail list:   proxmox, sshd&lt;br /&gt;
[root@proxy proxymox]# &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous pouvons maintenant passer à l&#039;API !&lt;br /&gt;
&lt;br /&gt;
=== Invention d&#039;une API pour fail2ban ===&lt;br /&gt;
&lt;br /&gt;
Toujours sur le reverse-proxy nous allons installer PHP pour créer un mini serveur qui répondra au urls suivantes:&lt;br /&gt;
* /ban/&amp;lt;ip&amp;gt; pour bannir&lt;br /&gt;
* /unban/&amp;lt;ip&amp;gt; pour lever le banissement&lt;br /&gt;
&lt;br /&gt;
Commençons par installer PHP:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# dnf -y install php-cli&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un répertoire &amp;quot;f2b-api&amp;quot; dans le dossier &amp;quot;opt&amp;quot; :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# mkdir /opt/f2b-api&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis créer un fichier &#039;&#039;f2b-api.php&#039;&#039; dans ce dossier:&lt;br /&gt;
&amp;lt;source lang=php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
main();&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        # On clean l&#039;uri du / de début&lt;br /&gt;
        $uri = ltrim($_SERVER[&#039;REQUEST_URI&#039;], &#039;/&#039;);&lt;br /&gt;
        # On éclate l&#039;uri en parties (action + ip)&lt;br /&gt;
        $parts = explode(&#039;/&#039;, $uri);&lt;br /&gt;
        # Récupération de l&#039;action dans une variable ou false si vide&lt;br /&gt;
        $action = empty($parts[0]) ? false : $parts[0];&lt;br /&gt;
        # Récupération de l&#039;ip dans une variable ou false si vide&lt;br /&gt;
        $ip = empty($parts[1]) ? false : $parts[1];&lt;br /&gt;
        if(!$action || !$ip){&lt;br /&gt;
                # Si action vide =&amp;gt; 400 Bad request&lt;br /&gt;
                http_response_code(400);&lt;br /&gt;
                die();&lt;br /&gt;
        }&lt;br /&gt;
        if(!in_array($action, [&#039;ban&#039;, &#039;unban&#039;])){&lt;br /&gt;
                # Si action pas dans la liste =&amp;gt; 400 Bad request&lt;br /&gt;
                http_response_code(400);&lt;br /&gt;
                die();&lt;br /&gt;
        }&lt;br /&gt;
        $cmd = &#039;&#039;;&lt;br /&gt;
        if($action == &#039;ban&#039;){&lt;br /&gt;
                $cmd = &#039;fail2ban-client set proxmox banip &#039; . $ip;&lt;br /&gt;
        } else if($action == &#039;unban&#039;){&lt;br /&gt;
                $cmd = &#039;fail2ban-client unban proxmox &#039; . $ip;&lt;br /&gt;
        }&lt;br /&gt;
        shell_exec($cmd);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;amp;#9888; Gardez en tête que ce code simpliste n&#039;est en aucun cas sécurisé et ne doit pas être accessible depuis Internet.&lt;br /&gt;
&lt;br /&gt;
Pour démarrer se code en mode serveur il suffit de taper la commande suivante:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# php -S 0.0.0.0:8080 -t /opt/f2b-api /opt/f2b-api/f2b-api.php&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous pouvez tester directement depuis un autre terminal en tapant les commandes:&lt;br /&gt;
* pour bannir :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# curl -X GET http://127.0.0.1:8080/ban/1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* pour dé-bannir :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# curl -X GET http://127.0.0.1:8080/unban/1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Et en vérifiant dans fail2ban:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed: 0&lt;br /&gt;
|  |- Total failed:     0&lt;br /&gt;
|  `- File list:        /dev/null&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned: 1&lt;br /&gt;
   |- Total banned:     10&lt;br /&gt;
   `- Banned IP list:   1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Nous n&#039;allons pas lancer nous même le serveur PHP, nous allons demander à SystemD de le faire et pour cela nous allons créer le fichier &#039;&#039;/opt/f2b-api/f2b-api.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=fail2ban API Server&lt;br /&gt;
After=network-online.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
UMask=007&lt;br /&gt;
ExecStart=php -S 0.0.0.0:8080 -t /opt/f2b-api /opt/f2b-api/f2b-api.php&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faut maintenant demander à SystemD de s&#039;occuper de notre service:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl link /opt/f2b-api/f2b-api.service&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Et de le lancer au démarrage du reverse-proxy:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl enable f2b-api --now&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous pouvons maintenant nous déplacer sur le serveur Proxmox pour modifier fail2ban !&lt;br /&gt;
&lt;br /&gt;
=== Modification des actions fail2ban ===&lt;br /&gt;
Sur le serveur Proxmox nous allons débrayer le comportement de base de fail2ban qui est de modifier iptables. pour cela nous alons créer le fichier &#039;&#039;/etc/fail2ban/action.d/f2b-api.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
actionstart =&lt;br /&gt;
actionstop =&lt;br /&gt;
actioncheck =&lt;br /&gt;
actionban = curl -X GET 192.168.4.100:8080/ban/&amp;lt;ip&amp;gt;&lt;br /&gt;
actionunban = curl -X GET 192.168.4.100:8080/unban/&amp;lt;ip&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Veuillez noter que:&lt;br /&gt;
* même si elles sont vide, les lignes &#039;&#039;actionstart&#039;&#039;, &#039;&#039;actionstop&#039;&#039; et &#039;&#039;actioncheck&#039;&#039; sont obligatoires !&lt;br /&gt;
* l&#039;adresse &#039;&#039;192.168.4.100&#039;&#039; doit être remplcée par celle de votre reverse-proxy&lt;br /&gt;
* &amp;lt;ip&amp;gt; est l&#039;expression utilisée par fail2ban et elle sera remplacée par l&#039;IP à bannir &lt;br /&gt;
&lt;br /&gt;
Pour ce fichier d&#039;action soit pris en compte, il faut modifier le fichier &#039;&#039;/etc/fail2ban/jail.d/proxmox.conf&#039;&#039; pour y ajouter:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
banaction = f2b-api&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne vous reste plus qu&#039;a redémarrer le service fai2ban sur le serveur Proxmox:&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4412</id>
		<title>Proxmox fail2ban</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4412"/>
		<updated>2026-07-11T16:37:15Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Invention d&amp;#039;une API pour fail2ban */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
Proxmox utilise une interface web d&#039;administration qui utilise le port TCP 8006 et c&#039;est un vecteur possible d&#039;attaque par force brut. Nous allons donc &#039;&#039;dresser&#039;&#039; fail2ban pour agir en cas d&#039;attaque !&lt;br /&gt;
&lt;br /&gt;
Proxmox utilise Debian, nous allons principalement reproduire les étapes décrites dans le tutoriel de [[Sécuriser_un_service_avec_Fail2ban| Fail2ban pour Rocky]] et adapter à Debian.&lt;br /&gt;
&lt;br /&gt;
Avant d&#039;aller plus loin, assurez-vous d&#039;avoir correctement installé et configuré [[proxmox_iptables |iptables sur Proxmox]]&lt;br /&gt;
&lt;br /&gt;
= Installation =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt -y install fail2ban&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Configuration =&lt;br /&gt;
Tout d&#039;abord il faut copier le fichier &#039;&#039;/etc/fail2ban/jail.conf&#039;&#039; en &#039;&#039;/etc/fail2ban/jail.local&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dans ce fichier, on va s&#039;intéresser aux variables suivantes:&lt;br /&gt;
*ignoreip : correspond à la suite d&#039;adresses IP qui ne se feront jamais bannir;&lt;br /&gt;
*maxretry : correspond au nombre d&#039;essais;&lt;br /&gt;
*findtime : correspond à la période pendant laquelle les essais vont incrémenter maxretry;&lt;br /&gt;
*bantime  : correspond au temps où l&#039;adresse IP ne peut pas se connecter.&lt;br /&gt;
&lt;br /&gt;
= Configuration de base =&lt;br /&gt;
== Choix de la punition ==&lt;br /&gt;
Il faut choisir quelque chose de cohérent (une punition suffisante) pour ne pas permettre de se faire cracker son mot de passe:&lt;br /&gt;
*maxretry = 3&lt;br /&gt;
*findtime = 86400 (correspond à 1 journée)&lt;br /&gt;
*bantime = 604800 (correspond à 1 semaine)&lt;br /&gt;
&lt;br /&gt;
Cela signifie que si une adresse IP se trompe 3 fois en 1 journée (86400s) elle se fait bannir pendant 1 semaine (604800s).&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul permet de trouver le nombre maximal de tentatives durant une année:&lt;br /&gt;
&lt;br /&gt;
365 jours / 7 jours par semaine * 3 tentatives = 156 essais, ce qui reste raisonnable. &lt;br /&gt;
&lt;br /&gt;
Si le pirate possède un [http://fr.wikipedia.org/wiki/Botnet botnet], il faut bien sûr multiplier ce nombre par le nombre de machines dans le botnet...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Attention : fail2ban parcours les logs de connexion pour connaître le numéro de la tentative, ce qui a pour conséquence, si le &#039;&#039;findtime&#039;&#039; est grand, de prendre un certain temps...&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Jail pour SSH ==&lt;br /&gt;
Il suffit d&#039;ajouter la ligne &#039;&#039;enabled=true&#039;&#039; dans la section à activer !&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[sshd]&lt;br /&gt;
&lt;br /&gt;
# To use more aggressive sshd modes set filter parameter &amp;quot;mode&amp;quot; in jail.local:&lt;br /&gt;
# normal (default), ddos, extra or aggressive (combines all).&lt;br /&gt;
# See &amp;quot;tests/files/logs/sshd&amp;quot; or &amp;quot;filter.d/sshd.conf&amp;quot; for usage example and details.&lt;br /&gt;
#mode   = normal&lt;br /&gt;
enabled = true&lt;br /&gt;
port    = ssh&lt;br /&gt;
logpath = %(sshd_log)s&lt;br /&gt;
backend = %(sshd_backend)s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Configuration spécifique =&lt;br /&gt;
== Jail pour PVEPROXY ==&lt;br /&gt;
Pveproxy écoute sur le port 8006 et ne fonctionne pas exactement comme un serveur [[HTTPD | Apache httpd]] qui mettrait ces logs dans le fichier &#039;&#039;error_log&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Nous allons mettre cette configuration spécifique dans le fichier &#039;&#039;/etc/fail2ban/jail.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[proxmox]&lt;br /&gt;
enabled = true&lt;br /&gt;
port = https,http,8006&lt;br /&gt;
filter = proxmox&lt;br /&gt;
backend = systemd&lt;br /&gt;
maxretry = 5&lt;br /&gt;
findtime = 1d&lt;br /&gt;
bantime = 1w&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le backend utilisé est systemd, exactement comme si vous utilisiez la commande :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Filtre pour PVEPROXY ==&lt;br /&gt;
Il ne nous reste plus qu&#039;à spécifier le filtre &#039;&#039;proxmox&#039;&#039; dans le fichier &#039;&#039;/etc/fail2ban/filter.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=&amp;lt;HOST&amp;gt; user=.* msg=.*&lt;br /&gt;
ignoreregex =&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Tests =&lt;br /&gt;
Il faut maintenant tester le filtre et pour ça on peut utiliser un partage de connexion et réaliser le nombre d&#039;échecs spécifié par la directive &amp;quot;maxretry&amp;quot; (ici 3) :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed:	0&lt;br /&gt;
|  |- Total failed:	3&lt;br /&gt;
|  `- Journal matches:	_SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned:	1&lt;br /&gt;
   |- Total banned:	1&lt;br /&gt;
   `- Banned IP list:	37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On voit bien l&#039;IP 37.167.23.159 qui est bannie !&lt;br /&gt;
N&#039;oubliez pas de l&#039;ajouter à &#039;&#039;ignoreip&#039;&#039; dans le fichier &#039;&#039;jails.local&#039;&#039; ou de faire &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client unban 37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Démarrage et enregistrement dans le chargeur de démarrage =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start fail2ban.service&lt;br /&gt;
# systemctl enable fail2ban.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Vous pouvez maintenant démarrer fail2ban&lt;br /&gt;
&lt;br /&gt;
= Proxification=&lt;br /&gt;
Lorsque votre serveur Proxmox se trouve derrière un reverse-proxy (Apache, Nginx, Traefik, ...), au niveau 3 OSI, l&#039;adresse IP du client est remplacée par celle du proxy et le serveur utilise l&#039;entêtes &#039;&#039;X-Forwarded-For&#039;&#039; ou &#039;&#039;X-Real-IP&#039;&#039; pour transporter l&#039;adresse du client &lt;br /&gt;
[[Fichier:Reverse proxy proxmox.png|700px|centré]]&lt;br /&gt;
Le problème est que la seule adresse que fail2ban va voir apparaître dans les logs est celle du reverse-proxy (&#039;&#039;192.168.4.100&#039;&#039;) :&lt;br /&gt;
[[Fichier:Reverse proxy ip logs.png|600px|centré]]&lt;br /&gt;
Même si le filtre &#039;&#039;fail2ban&#039;&#039; est configuré pour utiliser la commande &#039;&#039;journactl&#039;&#039; sur le démon &#039;&#039;pvedaemon&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
les adresses viennent de pveproxy qui journalise tout dans &#039;&#039;/var/log/pveproxy/access.log&#039;&#039; et &#039;&#039;pvedaemon&#039;&#039; ne journalise que les échecs d&#039;authentification. &lt;br /&gt;
Il est donc plus simple de faire un &#039;&#039;tail&#039;&#039; ou un &#039;&#039;cat&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Que d&#039;utiliser &#039;&#039;journalctl&#039;&#039; pour voir les IPs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
Dec 14 10:43:01 labo unix_chkpwd[1326506]: password check failed for user (root)&lt;br /&gt;
Dec 14 10:43:01 labo IPCC.xs[1320783]: pam_unix(proxmox-ve-auth:auth): authentication failure; logname= uid=0 euid=0 tty= ruser= rhost=37.167.23.159  user=root&lt;br /&gt;
Dec 14 10:43:03 labo pvedaemon[1320783]: authentication failure; rhost=37.167.23.159 user=root@pam msg=Authentication failure&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Configuration de pveproxy ==&lt;br /&gt;
Si on veut voir l&#039;adresse du client, il faut dire au [https://fr.wikipedia.org/wiki/Daemon_(informatique)| démon] &#039;&#039;pveproxy&#039;&#039; d&#039;utiliser l&#039;une des deux entêtes précédentes ainsi que préciser l&#039;adresse du proxy. &lt;br /&gt;
&lt;br /&gt;
Préciser l&#039;adresse du proxy est essentiel pour que &#039;&#039;pveproxy&#039;&#039; n&#039;accepte de lire l&#039;adresse du client présente dans l&#039;entête &#039;&#039;&#039;uniquement&#039;&#039;&#039; si cela provient du proxy, qui est une machine de confiance. Le cas contraire, tout le monde pourrait ajouter une adresse IP dans l&#039;entête pour la faire bannir...&lt;br /&gt;
&lt;br /&gt;
Nous allons créer le fichier &#039;&#039;/etc/default/pveproxy&#039;&#039; avec les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Forwarded-For&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Real-IP&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_ALLOW_FROM=&amp;quot;192.168.4.100&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il faut maintenant redémarrer &#039;&#039;pveproxy&#039;&#039; pour que les changements s&#039;appliquent. Si vous êtes connecté via l&#039;interface web, cela va vous déconnecter, le temps que le démon redémarre, il faudra ensuite certainement rafraîchir la page web.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl restart pveproxy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à vérifier dans les logs si les bonnes adresses s&#039;affichent:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Si jamais ce n&#039;est pas le cas, poursuivez avec la modification du fichier &#039;&#039;AnyEvent.pm&#039;&#039;&lt;br /&gt;
== Modification de AnyEvent.pm ==&lt;br /&gt;
=== Application de la modification ===&lt;br /&gt;
Au jour d&#039;aujourd&#039;hui (13/12/25) la proxification ne fonctionne plus et il faut apporter une modification dans le fichier &#039;&#039;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&#039;&#039; pour que les bonnes adresses apparaissent !&lt;br /&gt;
En fonction des versions cette modification peut avoir lieu soit ligne &#039;&#039;&#039;1504&#039;&#039;&#039;, soit ligne &#039;&#039;&#039;1554&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Il faut repérer la fonction suivante:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
sub authenticate_and_handle_request {&lt;br /&gt;
    my ($self, $reqstate) = @_;&lt;br /&gt;
&lt;br /&gt;
    my $request = $reqstate-&amp;gt;{request};&lt;br /&gt;
    my $method = $request-&amp;gt;method();&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
C&#039;est un peu plus loin qu&#039;il faut insérer le code :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 ### INSERTION ICI ###&lt;br /&gt;
&lt;br /&gt;
    if ($self-&amp;gt;{spiceproxy}) {&lt;br /&gt;
        my $connect_str = $request-&amp;gt;header(&#039;Host&#039;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il faut modifier l&#039;attribut &#039;&#039;peer_host&#039;&#039; de l&#039;objet &#039;&#039;reqstate&#039;&#039; si l&#039;une des deux entêtes est présente :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if ($request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
} elsif ($request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Double IPv4 ou préfixe IPv6 ===&lt;br /&gt;
Après redémarrage, cela permet de voir l&#039;adresse du client dans les logs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/ext-all.js?ver=7.0.0 HTTP/1.1&amp;quot; 200 683505&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/js/u2f-api.js HTTP/1.1&amp;quot; 200 4898&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/resources HTTP/1.1&amp;quot; 200 1226&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/tasks HTTP/1.1&amp;quot; 200 1090&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /proxmoxlib.js?ver=v5.0.4-t1754316706 HTTP/1.1&amp;quot; 200 157086&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/theme-crisp/resources/theme-crisp-all_1.css HTTP/1.1&amp;quot; 200 32919&lt;br /&gt;
::ffff:192.168.20.22 - root@pam [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/nodes/labo/lxc/100/status/current HTTP/1.1&amp;quot; 200 523&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il nous reste un peu de nettoyage à faire, dans certains cas :&lt;br /&gt;
* l&#039;adresse apparaît non pas une fois mais deux, séparées par une virgule&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
37.167.182.207, 37.167.182.207&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* l&#039;adresse IPv4 (32 bits) est affichée dans sa représentation IPv6 (128 bits), avec le préfixe &#039;&#039;::ffff:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
::ffff:192.168.20.22&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On a deux possibilités pour faire le nettoyage :&lt;br /&gt;
*Soit on ajoute les lignes suivantes dans &#039;&#039;AnyEvent.pm&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if (index($reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
   # Remove trailing ip &lt;br /&gt;
   my @fields = split /,/, $reqstate-&amp;gt;{peer_host};&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $fields[0];&lt;br /&gt;
}&lt;br /&gt;
if($reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
   # Remove IPv6 subnet for IPv4&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $1;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*Soit on modifie le filtre /etc/fail2ban/filter.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=.*:?&amp;lt;HOST&amp;gt;,? user=.* msg=.*&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Automatisation ===&lt;br /&gt;
On peut automatiser le processus précédent avec le script suivant, que l&#039;on peut créer dans /root/remoteip_fix.sh :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=bash&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
ANYEVENT_PATH=&amp;quot;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&amp;quot;&lt;br /&gt;
ANYEVENT_REGEX=&#039;$self-&amp;gt;{spiceproxy}&#039;&lt;br /&gt;
TMP_FILE=&amp;quot;/tmp/AnyEvent.pm.tmp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if [ ! -f $ANYEVENT_PATH ]; then&lt;br /&gt;
  echo &amp;quot;$ANYEVENT_PATH does not exists !&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
if [ $(grep &#039;### BUGFIX REMOTE_IP FOR FAIL2BAN ###&#039; $ANYEVENT_PATH | wc -l) -eq 1 ]; then&lt;br /&gt;
  echo &amp;quot;AnyEvent.pm already patched !&amp;quot;&lt;br /&gt;
  exit 0&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
LINE_NUMBER_TOP=$(nl -ba $ANYEVENT_PATH | grep $ANYEVENT_REGEX | head -n 1 | awk -F &#039; &#039; &#039;{print $1}&#039;)&lt;br /&gt;
let LINE_NUMBER_TOP-=1&lt;br /&gt;
&lt;br /&gt;
if [ $LINE_NUMBER_TOP -lt 0 ]; then&lt;br /&gt;
  echo &amp;quot;Did not find the $ANYEVENT_REGEX expr in $ANYEVENT_PATH&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
echo -n &amp;quot;Applying bugfix: &amp;quot;&lt;br /&gt;
trap &amp;quot;rm -f $TMP_FILE&amp;quot; 0 1 2 5 13 15&lt;br /&gt;
head -n $LINE_NUMBER_TOP $ANYEVENT_PATH &amp;gt;$TMP_FILE&lt;br /&gt;
cat &amp;gt;&amp;gt;$TMP_FILE &amp;lt;&amp;lt;EOF&lt;br /&gt;
### BUGFIX REMOTE_IP FOR FAIL2BAN ###&lt;br /&gt;
    if (\$request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
    } elsif (\$request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
    }&lt;br /&gt;
    if (index(\$reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
        my @fields = split /,/, \$reqstate-&amp;gt;{peer_host};&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$fields[0];&lt;br /&gt;
    }&lt;br /&gt;
    if(\$reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
        # Remove IPv6 subnet for IPv4&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$1;&lt;br /&gt;
    }&lt;br /&gt;
#####################################&lt;br /&gt;
EOF&lt;br /&gt;
echo &amp;quot;$ANYEVENT_MODIF&amp;quot; &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cp $ANYEVENT_PATH $ANYEVENT_PATH.ori&lt;br /&gt;
LINE_NUMBER_BOTTOM=$(cat $ANYEVENT_PATH | wc -l)&lt;br /&gt;
let LINE_NUMBER_BOTTOM-=LINE_NUMBER_TOP&lt;br /&gt;
tail -n $LINE_NUMBER_BOTTOM $ANYEVENT_PATH &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cat $TMP_FILE &amp;gt;$ANYEVENT_PATH&lt;br /&gt;
rm -f $TMP_FILE&lt;br /&gt;
trap 0&lt;br /&gt;
echo &amp;quot;done.&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à le rendre exécutable et le lancer :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# chmod +x /root/remoteip_fix.sh&lt;br /&gt;
# /root/remoteip_fix.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne faudra pas oublier de redémarrer &#039;&#039;pveproxy&#039;&#039; pour appliquer les changements !&lt;br /&gt;
&lt;br /&gt;
== Comment bannir derrière un reverse-proxy ? ==&lt;br /&gt;
Maintenant que votre Proxmox est derrière un reverse-proxy, inutile de bannir les IP publiques avec iptables sur le serveur Proxmox, la seule IP visible est celle du reverse-proxy (dans cet exemple 192.168.4.100).&lt;br /&gt;
&lt;br /&gt;
La seule machine capable capable de bannir est le reverse-proxy, il faut donc lui transmettre les IP et nous allons faire ça en trois étapes:&lt;br /&gt;
* la première est de créer une &amp;quot;prison&amp;quot; proxmox sur le fail2ban présent sur le reverse-proxy&lt;br /&gt;
* la deuxième est l&#039;invention d&#039;une API pour fail2ban sur le reverse-proxy&lt;br /&gt;
* la troisième est la modification du comportement de fail2ban pour appeler cette API au lieu de modifier iptables&lt;br /&gt;
&lt;br /&gt;
=== Création d&#039;une prison sur le reverse-proxy ===&lt;br /&gt;
&lt;br /&gt;
Pour bannir nous allons créer une prison spécifique pour le / les serveurs Proxmox que nous allons appeler &#039;&#039;proxmox&#039;&#039; dans le fichier /etc/fail2ban/jail.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[proxmox]&lt;br /&gt;
enabled = true&lt;br /&gt;
port = https,http&lt;br /&gt;
filter = do-nothing&lt;br /&gt;
logpath = /dev/null&lt;br /&gt;
maxretry = 3&lt;br /&gt;
findtime = 1d&lt;br /&gt;
bantime = 1w&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
J&#039;attire votre attention sur les paramètres &#039;&#039;maxretry&#039;&#039;, &#039;&#039;findtime&#039;&#039; et &#039;&#039;bantime&#039;&#039; qui doivent concorder avec ceux du fail2ban de votre Proxmox. S&#039;il sont plus &#039;&#039;court&#039;&#039; sur le reverse-proxy, les IP seront libérées plus tôt à l&#039;inverse, plus long n&#039;est pas gênant, le fail2ban de votre Proxmox les libéreras avant celui du proxy.&lt;br /&gt;
&lt;br /&gt;
Vous avez remarquez le filtre &#039;&#039;do-nothing&#039;&#039; qu&#039;il nous reste à créer dans le fichier &#039;&#039;/etc/fail2ban/filter.d/do-nothing.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
&lt;br /&gt;
failregex = ^&amp;lt;HOST&amp;gt;$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Après redémarrage de fail2ban :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl restart fail2ban&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous devriez voir la prison&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status&lt;br /&gt;
Status&lt;br /&gt;
|- Number of jail:      2&lt;br /&gt;
`- Jail list:   proxmox, sshd&lt;br /&gt;
[root@proxy proxymox]# &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous pouvons maintenant passer à l&#039;API !&lt;br /&gt;
&lt;br /&gt;
=== Invention d&#039;une API pour fail2ban ===&lt;br /&gt;
&lt;br /&gt;
Toujours sur le reverse-proxy nous allons installer PHP pour créer un mini serveur qui répondra au urls suivantes:&lt;br /&gt;
* /ban/&amp;lt;ip&amp;gt; pour bannir&lt;br /&gt;
* /unban/&amp;lt;ip&amp;gt; pour lever le banissement&lt;br /&gt;
&lt;br /&gt;
Commençons par installer PHP:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# dnf -y install php-cli&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un répertoire &amp;quot;f2b-api&amp;quot; dans le dossier &amp;quot;opt&amp;quot; :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# mkdir /opt/f2b-api&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis créer un fichier &#039;&#039;f2b-api.php&#039;&#039; dans ce dossier:&lt;br /&gt;
&amp;lt;source lang=php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
main();&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        # On clean l&#039;uri du / de début&lt;br /&gt;
        $uri = ltrim($_SERVER[&#039;REQUEST_URI&#039;], &#039;/&#039;);&lt;br /&gt;
        # On éclate l&#039;uri en parties (action + ip)&lt;br /&gt;
        $parts = explode(&#039;/&#039;, $uri);&lt;br /&gt;
        # Récupération de l&#039;action dans une variable ou false si vide&lt;br /&gt;
        $action = empty($parts[0]) ? false : $parts[0];&lt;br /&gt;
        # Récupération de l&#039;ip dans une variable ou false si vide&lt;br /&gt;
        $ip = empty($parts[1]) ? false : $parts[1];&lt;br /&gt;
        if(!$action || !$ip){&lt;br /&gt;
                # Si action vide =&amp;gt; 400 Bad request&lt;br /&gt;
                http_response_code(400);&lt;br /&gt;
                die();&lt;br /&gt;
        }&lt;br /&gt;
        if(!in_array($action, [&#039;ban&#039;, &#039;unban&#039;])){&lt;br /&gt;
                # Si action pas dans la liste =&amp;gt; 400 Bad request&lt;br /&gt;
                http_response_code(400);&lt;br /&gt;
                die();&lt;br /&gt;
        }&lt;br /&gt;
        $cmd = &#039;&#039;;&lt;br /&gt;
        if($action == &#039;ban&#039;){&lt;br /&gt;
                $cmd = &#039;fail2ban-client set proxmox banip &#039; . $ip;&lt;br /&gt;
        } else if($action == &#039;unban&#039;){&lt;br /&gt;
                $cmd = &#039;fail2ban-client unban proxmox &#039; . $ip;&lt;br /&gt;
        }&lt;br /&gt;
        shell_exec($cmd);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;amp;#9888; Gardez en tête que ce code simpliste n&#039;est en aucun cas sécurisé et ne doit pas être accessible depuis Internet.&lt;br /&gt;
&lt;br /&gt;
Pour démarrer se code en mode serveur il suffit de taper la commande suivante:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# php -S 0.0.0.0:8080 -t /opt/f2b-api /opt/f2b-api/f2b-api.php&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous pouvez tester directement depuis un autre terminal en tapant les commandes:&lt;br /&gt;
* pour bannir :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# curl -X GET http://127.0.0.1:8080/ban/1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* pour dé-bannir :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# curl -X GET http://127.0.0.1:8080/unban/1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Et en vérifiant dans fail2ban:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed: 0&lt;br /&gt;
|  |- Total failed:     0&lt;br /&gt;
|  `- File list:        /dev/null&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned: 1&lt;br /&gt;
   |- Total banned:     10&lt;br /&gt;
   `- Banned IP list:   1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Nous n&#039;allons pas lancer nous même le serveur PHP, nous allons demander à SystemD de le faire et pour cela nous allons créer le fichier &#039;&#039;/opt/f2b-api/f2b-api.service&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=fail2ban API Server&lt;br /&gt;
After=network-online.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
UMask=007&lt;br /&gt;
ExecStart=php -S 0.0.0.0:8080 -t /opt/f2b-api /opt/f2b-api/f2b-api.php&lt;br /&gt;
Restart=on-failure&lt;br /&gt;
TimeoutStopSec=300&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faut maintenant demander à SystemD de s&#039;occuper de notre service:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl link /opt/f2b-api/f2b-api.service&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Et de le lancer au démarrage du reverse-proxy:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl enable f2b-api --now&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous pouvons maintenant nous déplacer sur le serveur Proxmox pour modifier fail2ban !&lt;br /&gt;
&lt;br /&gt;
=== Modification des actions fail2ban ===&lt;br /&gt;
Sur le serveur Proxmox nous allons débrayer le comportement de base de fail2ban qui est de modifier iptables. pour cela nous alons créer le fichier &#039;&#039;/etc/fail2ban/action.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
actionstart =&lt;br /&gt;
actionstop =&lt;br /&gt;
actioncheck =&lt;br /&gt;
actionban = curl -X GET 192.168.4.100:8080/ban/&amp;lt;ip&amp;gt;&lt;br /&gt;
actionunban = curl -X GET 192.168.4.100:8080/unban/&amp;lt;ip&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Remplacer l&#039;adresse &#039;&#039;192.168.4.100&#039;&#039; par celle de votre reverse-proxy&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4411</id>
		<title>Proxmox fail2ban</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4411"/>
		<updated>2026-07-11T16:31:12Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Invention d&amp;#039;une API pour fail2ban */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
Proxmox utilise une interface web d&#039;administration qui utilise le port TCP 8006 et c&#039;est un vecteur possible d&#039;attaque par force brut. Nous allons donc &#039;&#039;dresser&#039;&#039; fail2ban pour agir en cas d&#039;attaque !&lt;br /&gt;
&lt;br /&gt;
Proxmox utilise Debian, nous allons principalement reproduire les étapes décrites dans le tutoriel de [[Sécuriser_un_service_avec_Fail2ban| Fail2ban pour Rocky]] et adapter à Debian.&lt;br /&gt;
&lt;br /&gt;
Avant d&#039;aller plus loin, assurez-vous d&#039;avoir correctement installé et configuré [[proxmox_iptables |iptables sur Proxmox]]&lt;br /&gt;
&lt;br /&gt;
= Installation =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt -y install fail2ban&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Configuration =&lt;br /&gt;
Tout d&#039;abord il faut copier le fichier &#039;&#039;/etc/fail2ban/jail.conf&#039;&#039; en &#039;&#039;/etc/fail2ban/jail.local&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dans ce fichier, on va s&#039;intéresser aux variables suivantes:&lt;br /&gt;
*ignoreip : correspond à la suite d&#039;adresses IP qui ne se feront jamais bannir;&lt;br /&gt;
*maxretry : correspond au nombre d&#039;essais;&lt;br /&gt;
*findtime : correspond à la période pendant laquelle les essais vont incrémenter maxretry;&lt;br /&gt;
*bantime  : correspond au temps où l&#039;adresse IP ne peut pas se connecter.&lt;br /&gt;
&lt;br /&gt;
= Configuration de base =&lt;br /&gt;
== Choix de la punition ==&lt;br /&gt;
Il faut choisir quelque chose de cohérent (une punition suffisante) pour ne pas permettre de se faire cracker son mot de passe:&lt;br /&gt;
*maxretry = 3&lt;br /&gt;
*findtime = 86400 (correspond à 1 journée)&lt;br /&gt;
*bantime = 604800 (correspond à 1 semaine)&lt;br /&gt;
&lt;br /&gt;
Cela signifie que si une adresse IP se trompe 3 fois en 1 journée (86400s) elle se fait bannir pendant 1 semaine (604800s).&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul permet de trouver le nombre maximal de tentatives durant une année:&lt;br /&gt;
&lt;br /&gt;
365 jours / 7 jours par semaine * 3 tentatives = 156 essais, ce qui reste raisonnable. &lt;br /&gt;
&lt;br /&gt;
Si le pirate possède un [http://fr.wikipedia.org/wiki/Botnet botnet], il faut bien sûr multiplier ce nombre par le nombre de machines dans le botnet...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Attention : fail2ban parcours les logs de connexion pour connaître le numéro de la tentative, ce qui a pour conséquence, si le &#039;&#039;findtime&#039;&#039; est grand, de prendre un certain temps...&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Jail pour SSH ==&lt;br /&gt;
Il suffit d&#039;ajouter la ligne &#039;&#039;enabled=true&#039;&#039; dans la section à activer !&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[sshd]&lt;br /&gt;
&lt;br /&gt;
# To use more aggressive sshd modes set filter parameter &amp;quot;mode&amp;quot; in jail.local:&lt;br /&gt;
# normal (default), ddos, extra or aggressive (combines all).&lt;br /&gt;
# See &amp;quot;tests/files/logs/sshd&amp;quot; or &amp;quot;filter.d/sshd.conf&amp;quot; for usage example and details.&lt;br /&gt;
#mode   = normal&lt;br /&gt;
enabled = true&lt;br /&gt;
port    = ssh&lt;br /&gt;
logpath = %(sshd_log)s&lt;br /&gt;
backend = %(sshd_backend)s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Configuration spécifique =&lt;br /&gt;
== Jail pour PVEPROXY ==&lt;br /&gt;
Pveproxy écoute sur le port 8006 et ne fonctionne pas exactement comme un serveur [[HTTPD | Apache httpd]] qui mettrait ces logs dans le fichier &#039;&#039;error_log&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Nous allons mettre cette configuration spécifique dans le fichier &#039;&#039;/etc/fail2ban/jail.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[proxmox]&lt;br /&gt;
enabled = true&lt;br /&gt;
port = https,http,8006&lt;br /&gt;
filter = proxmox&lt;br /&gt;
backend = systemd&lt;br /&gt;
maxretry = 5&lt;br /&gt;
findtime = 1d&lt;br /&gt;
bantime = 1w&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le backend utilisé est systemd, exactement comme si vous utilisiez la commande :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Filtre pour PVEPROXY ==&lt;br /&gt;
Il ne nous reste plus qu&#039;à spécifier le filtre &#039;&#039;proxmox&#039;&#039; dans le fichier &#039;&#039;/etc/fail2ban/filter.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=&amp;lt;HOST&amp;gt; user=.* msg=.*&lt;br /&gt;
ignoreregex =&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Tests =&lt;br /&gt;
Il faut maintenant tester le filtre et pour ça on peut utiliser un partage de connexion et réaliser le nombre d&#039;échecs spécifié par la directive &amp;quot;maxretry&amp;quot; (ici 3) :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed:	0&lt;br /&gt;
|  |- Total failed:	3&lt;br /&gt;
|  `- Journal matches:	_SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned:	1&lt;br /&gt;
   |- Total banned:	1&lt;br /&gt;
   `- Banned IP list:	37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On voit bien l&#039;IP 37.167.23.159 qui est bannie !&lt;br /&gt;
N&#039;oubliez pas de l&#039;ajouter à &#039;&#039;ignoreip&#039;&#039; dans le fichier &#039;&#039;jails.local&#039;&#039; ou de faire &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client unban 37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Démarrage et enregistrement dans le chargeur de démarrage =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start fail2ban.service&lt;br /&gt;
# systemctl enable fail2ban.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Vous pouvez maintenant démarrer fail2ban&lt;br /&gt;
&lt;br /&gt;
= Proxification=&lt;br /&gt;
Lorsque votre serveur Proxmox se trouve derrière un reverse-proxy (Apache, Nginx, Traefik, ...), au niveau 3 OSI, l&#039;adresse IP du client est remplacée par celle du proxy et le serveur utilise l&#039;entêtes &#039;&#039;X-Forwarded-For&#039;&#039; ou &#039;&#039;X-Real-IP&#039;&#039; pour transporter l&#039;adresse du client &lt;br /&gt;
[[Fichier:Reverse proxy proxmox.png|700px|centré]]&lt;br /&gt;
Le problème est que la seule adresse que fail2ban va voir apparaître dans les logs est celle du reverse-proxy (&#039;&#039;192.168.4.100&#039;&#039;) :&lt;br /&gt;
[[Fichier:Reverse proxy ip logs.png|600px|centré]]&lt;br /&gt;
Même si le filtre &#039;&#039;fail2ban&#039;&#039; est configuré pour utiliser la commande &#039;&#039;journactl&#039;&#039; sur le démon &#039;&#039;pvedaemon&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
les adresses viennent de pveproxy qui journalise tout dans &#039;&#039;/var/log/pveproxy/access.log&#039;&#039; et &#039;&#039;pvedaemon&#039;&#039; ne journalise que les échecs d&#039;authentification. &lt;br /&gt;
Il est donc plus simple de faire un &#039;&#039;tail&#039;&#039; ou un &#039;&#039;cat&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Que d&#039;utiliser &#039;&#039;journalctl&#039;&#039; pour voir les IPs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
Dec 14 10:43:01 labo unix_chkpwd[1326506]: password check failed for user (root)&lt;br /&gt;
Dec 14 10:43:01 labo IPCC.xs[1320783]: pam_unix(proxmox-ve-auth:auth): authentication failure; logname= uid=0 euid=0 tty= ruser= rhost=37.167.23.159  user=root&lt;br /&gt;
Dec 14 10:43:03 labo pvedaemon[1320783]: authentication failure; rhost=37.167.23.159 user=root@pam msg=Authentication failure&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Configuration de pveproxy ==&lt;br /&gt;
Si on veut voir l&#039;adresse du client, il faut dire au [https://fr.wikipedia.org/wiki/Daemon_(informatique)| démon] &#039;&#039;pveproxy&#039;&#039; d&#039;utiliser l&#039;une des deux entêtes précédentes ainsi que préciser l&#039;adresse du proxy. &lt;br /&gt;
&lt;br /&gt;
Préciser l&#039;adresse du proxy est essentiel pour que &#039;&#039;pveproxy&#039;&#039; n&#039;accepte de lire l&#039;adresse du client présente dans l&#039;entête &#039;&#039;&#039;uniquement&#039;&#039;&#039; si cela provient du proxy, qui est une machine de confiance. Le cas contraire, tout le monde pourrait ajouter une adresse IP dans l&#039;entête pour la faire bannir...&lt;br /&gt;
&lt;br /&gt;
Nous allons créer le fichier &#039;&#039;/etc/default/pveproxy&#039;&#039; avec les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Forwarded-For&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Real-IP&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_ALLOW_FROM=&amp;quot;192.168.4.100&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il faut maintenant redémarrer &#039;&#039;pveproxy&#039;&#039; pour que les changements s&#039;appliquent. Si vous êtes connecté via l&#039;interface web, cela va vous déconnecter, le temps que le démon redémarre, il faudra ensuite certainement rafraîchir la page web.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl restart pveproxy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à vérifier dans les logs si les bonnes adresses s&#039;affichent:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Si jamais ce n&#039;est pas le cas, poursuivez avec la modification du fichier &#039;&#039;AnyEvent.pm&#039;&#039;&lt;br /&gt;
== Modification de AnyEvent.pm ==&lt;br /&gt;
=== Application de la modification ===&lt;br /&gt;
Au jour d&#039;aujourd&#039;hui (13/12/25) la proxification ne fonctionne plus et il faut apporter une modification dans le fichier &#039;&#039;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&#039;&#039; pour que les bonnes adresses apparaissent !&lt;br /&gt;
En fonction des versions cette modification peut avoir lieu soit ligne &#039;&#039;&#039;1504&#039;&#039;&#039;, soit ligne &#039;&#039;&#039;1554&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Il faut repérer la fonction suivante:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
sub authenticate_and_handle_request {&lt;br /&gt;
    my ($self, $reqstate) = @_;&lt;br /&gt;
&lt;br /&gt;
    my $request = $reqstate-&amp;gt;{request};&lt;br /&gt;
    my $method = $request-&amp;gt;method();&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
C&#039;est un peu plus loin qu&#039;il faut insérer le code :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 ### INSERTION ICI ###&lt;br /&gt;
&lt;br /&gt;
    if ($self-&amp;gt;{spiceproxy}) {&lt;br /&gt;
        my $connect_str = $request-&amp;gt;header(&#039;Host&#039;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il faut modifier l&#039;attribut &#039;&#039;peer_host&#039;&#039; de l&#039;objet &#039;&#039;reqstate&#039;&#039; si l&#039;une des deux entêtes est présente :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if ($request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
} elsif ($request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Double IPv4 ou préfixe IPv6 ===&lt;br /&gt;
Après redémarrage, cela permet de voir l&#039;adresse du client dans les logs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/ext-all.js?ver=7.0.0 HTTP/1.1&amp;quot; 200 683505&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/js/u2f-api.js HTTP/1.1&amp;quot; 200 4898&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/resources HTTP/1.1&amp;quot; 200 1226&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/tasks HTTP/1.1&amp;quot; 200 1090&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /proxmoxlib.js?ver=v5.0.4-t1754316706 HTTP/1.1&amp;quot; 200 157086&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/theme-crisp/resources/theme-crisp-all_1.css HTTP/1.1&amp;quot; 200 32919&lt;br /&gt;
::ffff:192.168.20.22 - root@pam [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/nodes/labo/lxc/100/status/current HTTP/1.1&amp;quot; 200 523&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il nous reste un peu de nettoyage à faire, dans certains cas :&lt;br /&gt;
* l&#039;adresse apparaît non pas une fois mais deux, séparées par une virgule&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
37.167.182.207, 37.167.182.207&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* l&#039;adresse IPv4 (32 bits) est affichée dans sa représentation IPv6 (128 bits), avec le préfixe &#039;&#039;::ffff:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
::ffff:192.168.20.22&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On a deux possibilités pour faire le nettoyage :&lt;br /&gt;
*Soit on ajoute les lignes suivantes dans &#039;&#039;AnyEvent.pm&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if (index($reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
   # Remove trailing ip &lt;br /&gt;
   my @fields = split /,/, $reqstate-&amp;gt;{peer_host};&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $fields[0];&lt;br /&gt;
}&lt;br /&gt;
if($reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
   # Remove IPv6 subnet for IPv4&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $1;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*Soit on modifie le filtre /etc/fail2ban/filter.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=.*:?&amp;lt;HOST&amp;gt;,? user=.* msg=.*&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Automatisation ===&lt;br /&gt;
On peut automatiser le processus précédent avec le script suivant, que l&#039;on peut créer dans /root/remoteip_fix.sh :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=bash&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
ANYEVENT_PATH=&amp;quot;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&amp;quot;&lt;br /&gt;
ANYEVENT_REGEX=&#039;$self-&amp;gt;{spiceproxy}&#039;&lt;br /&gt;
TMP_FILE=&amp;quot;/tmp/AnyEvent.pm.tmp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if [ ! -f $ANYEVENT_PATH ]; then&lt;br /&gt;
  echo &amp;quot;$ANYEVENT_PATH does not exists !&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
if [ $(grep &#039;### BUGFIX REMOTE_IP FOR FAIL2BAN ###&#039; $ANYEVENT_PATH | wc -l) -eq 1 ]; then&lt;br /&gt;
  echo &amp;quot;AnyEvent.pm already patched !&amp;quot;&lt;br /&gt;
  exit 0&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
LINE_NUMBER_TOP=$(nl -ba $ANYEVENT_PATH | grep $ANYEVENT_REGEX | head -n 1 | awk -F &#039; &#039; &#039;{print $1}&#039;)&lt;br /&gt;
let LINE_NUMBER_TOP-=1&lt;br /&gt;
&lt;br /&gt;
if [ $LINE_NUMBER_TOP -lt 0 ]; then&lt;br /&gt;
  echo &amp;quot;Did not find the $ANYEVENT_REGEX expr in $ANYEVENT_PATH&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
echo -n &amp;quot;Applying bugfix: &amp;quot;&lt;br /&gt;
trap &amp;quot;rm -f $TMP_FILE&amp;quot; 0 1 2 5 13 15&lt;br /&gt;
head -n $LINE_NUMBER_TOP $ANYEVENT_PATH &amp;gt;$TMP_FILE&lt;br /&gt;
cat &amp;gt;&amp;gt;$TMP_FILE &amp;lt;&amp;lt;EOF&lt;br /&gt;
### BUGFIX REMOTE_IP FOR FAIL2BAN ###&lt;br /&gt;
    if (\$request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
    } elsif (\$request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
    }&lt;br /&gt;
    if (index(\$reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
        my @fields = split /,/, \$reqstate-&amp;gt;{peer_host};&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$fields[0];&lt;br /&gt;
    }&lt;br /&gt;
    if(\$reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
        # Remove IPv6 subnet for IPv4&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$1;&lt;br /&gt;
    }&lt;br /&gt;
#####################################&lt;br /&gt;
EOF&lt;br /&gt;
echo &amp;quot;$ANYEVENT_MODIF&amp;quot; &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cp $ANYEVENT_PATH $ANYEVENT_PATH.ori&lt;br /&gt;
LINE_NUMBER_BOTTOM=$(cat $ANYEVENT_PATH | wc -l)&lt;br /&gt;
let LINE_NUMBER_BOTTOM-=LINE_NUMBER_TOP&lt;br /&gt;
tail -n $LINE_NUMBER_BOTTOM $ANYEVENT_PATH &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cat $TMP_FILE &amp;gt;$ANYEVENT_PATH&lt;br /&gt;
rm -f $TMP_FILE&lt;br /&gt;
trap 0&lt;br /&gt;
echo &amp;quot;done.&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à le rendre exécutable et le lancer :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# chmod +x /root/remoteip_fix.sh&lt;br /&gt;
# /root/remoteip_fix.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne faudra pas oublier de redémarrer &#039;&#039;pveproxy&#039;&#039; pour appliquer les changements !&lt;br /&gt;
&lt;br /&gt;
== Comment bannir derrière un reverse-proxy ? ==&lt;br /&gt;
Maintenant que votre Proxmox est derrière un reverse-proxy, inutile de bannir les IP publiques avec iptables sur le serveur Proxmox, la seule IP visible est celle du reverse-proxy (dans cet exemple 192.168.4.100).&lt;br /&gt;
&lt;br /&gt;
La seule machine capable capable de bannir est le reverse-proxy, il faut donc lui transmettre les IP et nous allons faire ça en trois étapes:&lt;br /&gt;
* la première est de créer une &amp;quot;prison&amp;quot; proxmox sur le fail2ban présent sur le reverse-proxy&lt;br /&gt;
* la deuxième est l&#039;invention d&#039;une API pour fail2ban sur le reverse-proxy&lt;br /&gt;
* la troisième est la modification du comportement de fail2ban pour appeler cette API au lieu de modifier iptables&lt;br /&gt;
&lt;br /&gt;
=== Création d&#039;une prison sur le reverse-proxy ===&lt;br /&gt;
&lt;br /&gt;
Pour bannir nous allons créer une prison spécifique pour le / les serveurs Proxmox que nous allons appeler &#039;&#039;proxmox&#039;&#039; dans le fichier /etc/fail2ban/jail.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[proxmox]&lt;br /&gt;
enabled = true&lt;br /&gt;
port = https,http&lt;br /&gt;
filter = do-nothing&lt;br /&gt;
logpath = /dev/null&lt;br /&gt;
maxretry = 3&lt;br /&gt;
findtime = 1d&lt;br /&gt;
bantime = 1w&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
J&#039;attire votre attention sur les paramètres &#039;&#039;maxretry&#039;&#039;, &#039;&#039;findtime&#039;&#039; et &#039;&#039;bantime&#039;&#039; qui doivent concorder avec ceux du fail2ban de votre Proxmox. S&#039;il sont plus &#039;&#039;court&#039;&#039; sur le reverse-proxy, les IP seront libérées plus tôt à l&#039;inverse, plus long n&#039;est pas gênant, le fail2ban de votre Proxmox les libéreras avant celui du proxy.&lt;br /&gt;
&lt;br /&gt;
Vous avez remarquez le filtre &#039;&#039;do-nothing&#039;&#039; qu&#039;il nous reste à créer dans le fichier &#039;&#039;/etc/fail2ban/filter.d/do-nothing.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
&lt;br /&gt;
failregex = ^&amp;lt;HOST&amp;gt;$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Après redémarrage de fail2ban :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl restart fail2ban&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous devriez voir la prison&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status&lt;br /&gt;
Status&lt;br /&gt;
|- Number of jail:      2&lt;br /&gt;
`- Jail list:   proxmox, sshd&lt;br /&gt;
[root@proxy proxymox]# &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous pouvons maintenant passer à l&#039;API !&lt;br /&gt;
&lt;br /&gt;
=== Invention d&#039;une API pour fail2ban ===&lt;br /&gt;
&lt;br /&gt;
Toujours sur le reverse-proxy nous allons installer PHP pour créer un mini serveur qui répondra au urls suivantes:&lt;br /&gt;
* /ban/&amp;lt;ip&amp;gt; pour bannir&lt;br /&gt;
* /unban/&amp;lt;ip&amp;gt; pour lever le banissement&lt;br /&gt;
&lt;br /&gt;
Commençons par installer PHP:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# dnf -y install php-cli&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un répertoire &amp;quot;f2b-api&amp;quot; dans le dossier &amp;quot;opt&amp;quot; :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# mkdir /opt/f2b-api&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis créer un fichier &#039;&#039;f2b-api.php&#039;&#039; dans ce dossier:&lt;br /&gt;
&amp;lt;source lang=php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
main();&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        # On clean l&#039;uri du / de début&lt;br /&gt;
        $uri = ltrim($_SERVER[&#039;REQUEST_URI&#039;], &#039;/&#039;);&lt;br /&gt;
        # On éclate l&#039;uri en parties (action + ip)&lt;br /&gt;
        $parts = explode(&#039;/&#039;, $uri);&lt;br /&gt;
        # Récupération de l&#039;action dans une variable ou false si vide&lt;br /&gt;
        $action = empty($parts[0]) ? false : $parts[0];&lt;br /&gt;
        # Récupération de l&#039;ip dans une variable ou false si vide&lt;br /&gt;
        $ip = empty($parts[1]) ? false : $parts[1];&lt;br /&gt;
        if(!$action || !$ip){&lt;br /&gt;
                # Si action vide =&amp;gt; 400 Bad request&lt;br /&gt;
                http_response_code(400);&lt;br /&gt;
                die();&lt;br /&gt;
        }&lt;br /&gt;
        if(!in_array($action, [&#039;ban&#039;, &#039;unban&#039;])){&lt;br /&gt;
                # Si action pas dans la liste =&amp;gt; 400 Bad request&lt;br /&gt;
                http_response_code(400);&lt;br /&gt;
                die();&lt;br /&gt;
        }&lt;br /&gt;
        $cmd = &#039;&#039;;&lt;br /&gt;
        if($action == &#039;ban&#039;){&lt;br /&gt;
                $cmd = &#039;fail2ban-client set proxmox banip &#039; . $ip;&lt;br /&gt;
        } else if($action == &#039;unban&#039;){&lt;br /&gt;
                $cmd = &#039;fail2ban-client unban proxmox &#039; . $ip;&lt;br /&gt;
        }&lt;br /&gt;
        shell_exec($cmd);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;amp;#9888; Gardez en tête que ce code simpliste n&#039;est en aucun cas sécurisé et ne doit pas être accessible depuis Internet.&lt;br /&gt;
&lt;br /&gt;
Pour démarrer se code en mode serveur il suffit de taper la commande suivante:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# php -S 0.0.0.0:8080 -t /opt/f2b-api /opt/f2b-api/index.php&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous pouvez tester directement depuis un autre terminal en tapant les commandes:&lt;br /&gt;
* pour bannir :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# curl -X GET http://127.0.0.1/ban/1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* pour dé-bannir :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# curl -X GET http://127.0.0.1/unban/1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Et en vérifiant dans fail2ban:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed: 0&lt;br /&gt;
|  |- Total failed:     0&lt;br /&gt;
|  `- File list:        /dev/null&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned: 1&lt;br /&gt;
   |- Total banned:     10&lt;br /&gt;
   `- Banned IP list:   1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4410</id>
		<title>Proxmox fail2ban</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4410"/>
		<updated>2026-07-11T16:30:50Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Invention d&amp;#039;une API pour fail2ban */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
Proxmox utilise une interface web d&#039;administration qui utilise le port TCP 8006 et c&#039;est un vecteur possible d&#039;attaque par force brut. Nous allons donc &#039;&#039;dresser&#039;&#039; fail2ban pour agir en cas d&#039;attaque !&lt;br /&gt;
&lt;br /&gt;
Proxmox utilise Debian, nous allons principalement reproduire les étapes décrites dans le tutoriel de [[Sécuriser_un_service_avec_Fail2ban| Fail2ban pour Rocky]] et adapter à Debian.&lt;br /&gt;
&lt;br /&gt;
Avant d&#039;aller plus loin, assurez-vous d&#039;avoir correctement installé et configuré [[proxmox_iptables |iptables sur Proxmox]]&lt;br /&gt;
&lt;br /&gt;
= Installation =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt -y install fail2ban&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Configuration =&lt;br /&gt;
Tout d&#039;abord il faut copier le fichier &#039;&#039;/etc/fail2ban/jail.conf&#039;&#039; en &#039;&#039;/etc/fail2ban/jail.local&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dans ce fichier, on va s&#039;intéresser aux variables suivantes:&lt;br /&gt;
*ignoreip : correspond à la suite d&#039;adresses IP qui ne se feront jamais bannir;&lt;br /&gt;
*maxretry : correspond au nombre d&#039;essais;&lt;br /&gt;
*findtime : correspond à la période pendant laquelle les essais vont incrémenter maxretry;&lt;br /&gt;
*bantime  : correspond au temps où l&#039;adresse IP ne peut pas se connecter.&lt;br /&gt;
&lt;br /&gt;
= Configuration de base =&lt;br /&gt;
== Choix de la punition ==&lt;br /&gt;
Il faut choisir quelque chose de cohérent (une punition suffisante) pour ne pas permettre de se faire cracker son mot de passe:&lt;br /&gt;
*maxretry = 3&lt;br /&gt;
*findtime = 86400 (correspond à 1 journée)&lt;br /&gt;
*bantime = 604800 (correspond à 1 semaine)&lt;br /&gt;
&lt;br /&gt;
Cela signifie que si une adresse IP se trompe 3 fois en 1 journée (86400s) elle se fait bannir pendant 1 semaine (604800s).&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul permet de trouver le nombre maximal de tentatives durant une année:&lt;br /&gt;
&lt;br /&gt;
365 jours / 7 jours par semaine * 3 tentatives = 156 essais, ce qui reste raisonnable. &lt;br /&gt;
&lt;br /&gt;
Si le pirate possède un [http://fr.wikipedia.org/wiki/Botnet botnet], il faut bien sûr multiplier ce nombre par le nombre de machines dans le botnet...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Attention : fail2ban parcours les logs de connexion pour connaître le numéro de la tentative, ce qui a pour conséquence, si le &#039;&#039;findtime&#039;&#039; est grand, de prendre un certain temps...&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Jail pour SSH ==&lt;br /&gt;
Il suffit d&#039;ajouter la ligne &#039;&#039;enabled=true&#039;&#039; dans la section à activer !&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[sshd]&lt;br /&gt;
&lt;br /&gt;
# To use more aggressive sshd modes set filter parameter &amp;quot;mode&amp;quot; in jail.local:&lt;br /&gt;
# normal (default), ddos, extra or aggressive (combines all).&lt;br /&gt;
# See &amp;quot;tests/files/logs/sshd&amp;quot; or &amp;quot;filter.d/sshd.conf&amp;quot; for usage example and details.&lt;br /&gt;
#mode   = normal&lt;br /&gt;
enabled = true&lt;br /&gt;
port    = ssh&lt;br /&gt;
logpath = %(sshd_log)s&lt;br /&gt;
backend = %(sshd_backend)s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Configuration spécifique =&lt;br /&gt;
== Jail pour PVEPROXY ==&lt;br /&gt;
Pveproxy écoute sur le port 8006 et ne fonctionne pas exactement comme un serveur [[HTTPD | Apache httpd]] qui mettrait ces logs dans le fichier &#039;&#039;error_log&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Nous allons mettre cette configuration spécifique dans le fichier &#039;&#039;/etc/fail2ban/jail.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[proxmox]&lt;br /&gt;
enabled = true&lt;br /&gt;
port = https,http,8006&lt;br /&gt;
filter = proxmox&lt;br /&gt;
backend = systemd&lt;br /&gt;
maxretry = 5&lt;br /&gt;
findtime = 1d&lt;br /&gt;
bantime = 1w&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le backend utilisé est systemd, exactement comme si vous utilisiez la commande :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Filtre pour PVEPROXY ==&lt;br /&gt;
Il ne nous reste plus qu&#039;à spécifier le filtre &#039;&#039;proxmox&#039;&#039; dans le fichier &#039;&#039;/etc/fail2ban/filter.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=&amp;lt;HOST&amp;gt; user=.* msg=.*&lt;br /&gt;
ignoreregex =&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Tests =&lt;br /&gt;
Il faut maintenant tester le filtre et pour ça on peut utiliser un partage de connexion et réaliser le nombre d&#039;échecs spécifié par la directive &amp;quot;maxretry&amp;quot; (ici 3) :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed:	0&lt;br /&gt;
|  |- Total failed:	3&lt;br /&gt;
|  `- Journal matches:	_SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned:	1&lt;br /&gt;
   |- Total banned:	1&lt;br /&gt;
   `- Banned IP list:	37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On voit bien l&#039;IP 37.167.23.159 qui est bannie !&lt;br /&gt;
N&#039;oubliez pas de l&#039;ajouter à &#039;&#039;ignoreip&#039;&#039; dans le fichier &#039;&#039;jails.local&#039;&#039; ou de faire &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client unban 37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Démarrage et enregistrement dans le chargeur de démarrage =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start fail2ban.service&lt;br /&gt;
# systemctl enable fail2ban.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Vous pouvez maintenant démarrer fail2ban&lt;br /&gt;
&lt;br /&gt;
= Proxification=&lt;br /&gt;
Lorsque votre serveur Proxmox se trouve derrière un reverse-proxy (Apache, Nginx, Traefik, ...), au niveau 3 OSI, l&#039;adresse IP du client est remplacée par celle du proxy et le serveur utilise l&#039;entêtes &#039;&#039;X-Forwarded-For&#039;&#039; ou &#039;&#039;X-Real-IP&#039;&#039; pour transporter l&#039;adresse du client &lt;br /&gt;
[[Fichier:Reverse proxy proxmox.png|700px|centré]]&lt;br /&gt;
Le problème est que la seule adresse que fail2ban va voir apparaître dans les logs est celle du reverse-proxy (&#039;&#039;192.168.4.100&#039;&#039;) :&lt;br /&gt;
[[Fichier:Reverse proxy ip logs.png|600px|centré]]&lt;br /&gt;
Même si le filtre &#039;&#039;fail2ban&#039;&#039; est configuré pour utiliser la commande &#039;&#039;journactl&#039;&#039; sur le démon &#039;&#039;pvedaemon&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
les adresses viennent de pveproxy qui journalise tout dans &#039;&#039;/var/log/pveproxy/access.log&#039;&#039; et &#039;&#039;pvedaemon&#039;&#039; ne journalise que les échecs d&#039;authentification. &lt;br /&gt;
Il est donc plus simple de faire un &#039;&#039;tail&#039;&#039; ou un &#039;&#039;cat&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Que d&#039;utiliser &#039;&#039;journalctl&#039;&#039; pour voir les IPs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
Dec 14 10:43:01 labo unix_chkpwd[1326506]: password check failed for user (root)&lt;br /&gt;
Dec 14 10:43:01 labo IPCC.xs[1320783]: pam_unix(proxmox-ve-auth:auth): authentication failure; logname= uid=0 euid=0 tty= ruser= rhost=37.167.23.159  user=root&lt;br /&gt;
Dec 14 10:43:03 labo pvedaemon[1320783]: authentication failure; rhost=37.167.23.159 user=root@pam msg=Authentication failure&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Configuration de pveproxy ==&lt;br /&gt;
Si on veut voir l&#039;adresse du client, il faut dire au [https://fr.wikipedia.org/wiki/Daemon_(informatique)| démon] &#039;&#039;pveproxy&#039;&#039; d&#039;utiliser l&#039;une des deux entêtes précédentes ainsi que préciser l&#039;adresse du proxy. &lt;br /&gt;
&lt;br /&gt;
Préciser l&#039;adresse du proxy est essentiel pour que &#039;&#039;pveproxy&#039;&#039; n&#039;accepte de lire l&#039;adresse du client présente dans l&#039;entête &#039;&#039;&#039;uniquement&#039;&#039;&#039; si cela provient du proxy, qui est une machine de confiance. Le cas contraire, tout le monde pourrait ajouter une adresse IP dans l&#039;entête pour la faire bannir...&lt;br /&gt;
&lt;br /&gt;
Nous allons créer le fichier &#039;&#039;/etc/default/pveproxy&#039;&#039; avec les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Forwarded-For&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Real-IP&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_ALLOW_FROM=&amp;quot;192.168.4.100&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il faut maintenant redémarrer &#039;&#039;pveproxy&#039;&#039; pour que les changements s&#039;appliquent. Si vous êtes connecté via l&#039;interface web, cela va vous déconnecter, le temps que le démon redémarre, il faudra ensuite certainement rafraîchir la page web.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl restart pveproxy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à vérifier dans les logs si les bonnes adresses s&#039;affichent:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Si jamais ce n&#039;est pas le cas, poursuivez avec la modification du fichier &#039;&#039;AnyEvent.pm&#039;&#039;&lt;br /&gt;
== Modification de AnyEvent.pm ==&lt;br /&gt;
=== Application de la modification ===&lt;br /&gt;
Au jour d&#039;aujourd&#039;hui (13/12/25) la proxification ne fonctionne plus et il faut apporter une modification dans le fichier &#039;&#039;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&#039;&#039; pour que les bonnes adresses apparaissent !&lt;br /&gt;
En fonction des versions cette modification peut avoir lieu soit ligne &#039;&#039;&#039;1504&#039;&#039;&#039;, soit ligne &#039;&#039;&#039;1554&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Il faut repérer la fonction suivante:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
sub authenticate_and_handle_request {&lt;br /&gt;
    my ($self, $reqstate) = @_;&lt;br /&gt;
&lt;br /&gt;
    my $request = $reqstate-&amp;gt;{request};&lt;br /&gt;
    my $method = $request-&amp;gt;method();&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
C&#039;est un peu plus loin qu&#039;il faut insérer le code :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 ### INSERTION ICI ###&lt;br /&gt;
&lt;br /&gt;
    if ($self-&amp;gt;{spiceproxy}) {&lt;br /&gt;
        my $connect_str = $request-&amp;gt;header(&#039;Host&#039;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il faut modifier l&#039;attribut &#039;&#039;peer_host&#039;&#039; de l&#039;objet &#039;&#039;reqstate&#039;&#039; si l&#039;une des deux entêtes est présente :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if ($request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
} elsif ($request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Double IPv4 ou préfixe IPv6 ===&lt;br /&gt;
Après redémarrage, cela permet de voir l&#039;adresse du client dans les logs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/ext-all.js?ver=7.0.0 HTTP/1.1&amp;quot; 200 683505&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/js/u2f-api.js HTTP/1.1&amp;quot; 200 4898&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/resources HTTP/1.1&amp;quot; 200 1226&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/tasks HTTP/1.1&amp;quot; 200 1090&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /proxmoxlib.js?ver=v5.0.4-t1754316706 HTTP/1.1&amp;quot; 200 157086&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/theme-crisp/resources/theme-crisp-all_1.css HTTP/1.1&amp;quot; 200 32919&lt;br /&gt;
::ffff:192.168.20.22 - root@pam [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/nodes/labo/lxc/100/status/current HTTP/1.1&amp;quot; 200 523&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il nous reste un peu de nettoyage à faire, dans certains cas :&lt;br /&gt;
* l&#039;adresse apparaît non pas une fois mais deux, séparées par une virgule&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
37.167.182.207, 37.167.182.207&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* l&#039;adresse IPv4 (32 bits) est affichée dans sa représentation IPv6 (128 bits), avec le préfixe &#039;&#039;::ffff:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
::ffff:192.168.20.22&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On a deux possibilités pour faire le nettoyage :&lt;br /&gt;
*Soit on ajoute les lignes suivantes dans &#039;&#039;AnyEvent.pm&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if (index($reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
   # Remove trailing ip &lt;br /&gt;
   my @fields = split /,/, $reqstate-&amp;gt;{peer_host};&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $fields[0];&lt;br /&gt;
}&lt;br /&gt;
if($reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
   # Remove IPv6 subnet for IPv4&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $1;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*Soit on modifie le filtre /etc/fail2ban/filter.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=.*:?&amp;lt;HOST&amp;gt;,? user=.* msg=.*&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Automatisation ===&lt;br /&gt;
On peut automatiser le processus précédent avec le script suivant, que l&#039;on peut créer dans /root/remoteip_fix.sh :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=bash&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
ANYEVENT_PATH=&amp;quot;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&amp;quot;&lt;br /&gt;
ANYEVENT_REGEX=&#039;$self-&amp;gt;{spiceproxy}&#039;&lt;br /&gt;
TMP_FILE=&amp;quot;/tmp/AnyEvent.pm.tmp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if [ ! -f $ANYEVENT_PATH ]; then&lt;br /&gt;
  echo &amp;quot;$ANYEVENT_PATH does not exists !&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
if [ $(grep &#039;### BUGFIX REMOTE_IP FOR FAIL2BAN ###&#039; $ANYEVENT_PATH | wc -l) -eq 1 ]; then&lt;br /&gt;
  echo &amp;quot;AnyEvent.pm already patched !&amp;quot;&lt;br /&gt;
  exit 0&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
LINE_NUMBER_TOP=$(nl -ba $ANYEVENT_PATH | grep $ANYEVENT_REGEX | head -n 1 | awk -F &#039; &#039; &#039;{print $1}&#039;)&lt;br /&gt;
let LINE_NUMBER_TOP-=1&lt;br /&gt;
&lt;br /&gt;
if [ $LINE_NUMBER_TOP -lt 0 ]; then&lt;br /&gt;
  echo &amp;quot;Did not find the $ANYEVENT_REGEX expr in $ANYEVENT_PATH&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
echo -n &amp;quot;Applying bugfix: &amp;quot;&lt;br /&gt;
trap &amp;quot;rm -f $TMP_FILE&amp;quot; 0 1 2 5 13 15&lt;br /&gt;
head -n $LINE_NUMBER_TOP $ANYEVENT_PATH &amp;gt;$TMP_FILE&lt;br /&gt;
cat &amp;gt;&amp;gt;$TMP_FILE &amp;lt;&amp;lt;EOF&lt;br /&gt;
### BUGFIX REMOTE_IP FOR FAIL2BAN ###&lt;br /&gt;
    if (\$request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
    } elsif (\$request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
    }&lt;br /&gt;
    if (index(\$reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
        my @fields = split /,/, \$reqstate-&amp;gt;{peer_host};&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$fields[0];&lt;br /&gt;
    }&lt;br /&gt;
    if(\$reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
        # Remove IPv6 subnet for IPv4&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$1;&lt;br /&gt;
    }&lt;br /&gt;
#####################################&lt;br /&gt;
EOF&lt;br /&gt;
echo &amp;quot;$ANYEVENT_MODIF&amp;quot; &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cp $ANYEVENT_PATH $ANYEVENT_PATH.ori&lt;br /&gt;
LINE_NUMBER_BOTTOM=$(cat $ANYEVENT_PATH | wc -l)&lt;br /&gt;
let LINE_NUMBER_BOTTOM-=LINE_NUMBER_TOP&lt;br /&gt;
tail -n $LINE_NUMBER_BOTTOM $ANYEVENT_PATH &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cat $TMP_FILE &amp;gt;$ANYEVENT_PATH&lt;br /&gt;
rm -f $TMP_FILE&lt;br /&gt;
trap 0&lt;br /&gt;
echo &amp;quot;done.&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à le rendre exécutable et le lancer :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# chmod +x /root/remoteip_fix.sh&lt;br /&gt;
# /root/remoteip_fix.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne faudra pas oublier de redémarrer &#039;&#039;pveproxy&#039;&#039; pour appliquer les changements !&lt;br /&gt;
&lt;br /&gt;
== Comment bannir derrière un reverse-proxy ? ==&lt;br /&gt;
Maintenant que votre Proxmox est derrière un reverse-proxy, inutile de bannir les IP publiques avec iptables sur le serveur Proxmox, la seule IP visible est celle du reverse-proxy (dans cet exemple 192.168.4.100).&lt;br /&gt;
&lt;br /&gt;
La seule machine capable capable de bannir est le reverse-proxy, il faut donc lui transmettre les IP et nous allons faire ça en trois étapes:&lt;br /&gt;
* la première est de créer une &amp;quot;prison&amp;quot; proxmox sur le fail2ban présent sur le reverse-proxy&lt;br /&gt;
* la deuxième est l&#039;invention d&#039;une API pour fail2ban sur le reverse-proxy&lt;br /&gt;
* la troisième est la modification du comportement de fail2ban pour appeler cette API au lieu de modifier iptables&lt;br /&gt;
&lt;br /&gt;
=== Création d&#039;une prison sur le reverse-proxy ===&lt;br /&gt;
&lt;br /&gt;
Pour bannir nous allons créer une prison spécifique pour le / les serveurs Proxmox que nous allons appeler &#039;&#039;proxmox&#039;&#039; dans le fichier /etc/fail2ban/jail.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[proxmox]&lt;br /&gt;
enabled = true&lt;br /&gt;
port = https,http&lt;br /&gt;
filter = do-nothing&lt;br /&gt;
logpath = /dev/null&lt;br /&gt;
maxretry = 3&lt;br /&gt;
findtime = 1d&lt;br /&gt;
bantime = 1w&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
J&#039;attire votre attention sur les paramètres &#039;&#039;maxretry&#039;&#039;, &#039;&#039;findtime&#039;&#039; et &#039;&#039;bantime&#039;&#039; qui doivent concorder avec ceux du fail2ban de votre Proxmox. S&#039;il sont plus &#039;&#039;court&#039;&#039; sur le reverse-proxy, les IP seront libérées plus tôt à l&#039;inverse, plus long n&#039;est pas gênant, le fail2ban de votre Proxmox les libéreras avant celui du proxy.&lt;br /&gt;
&lt;br /&gt;
Vous avez remarquez le filtre &#039;&#039;do-nothing&#039;&#039; qu&#039;il nous reste à créer dans le fichier &#039;&#039;/etc/fail2ban/filter.d/do-nothing.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
&lt;br /&gt;
failregex = ^&amp;lt;HOST&amp;gt;$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Après redémarrage de fail2ban :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl restart fail2ban&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous devriez voir la prison&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status&lt;br /&gt;
Status&lt;br /&gt;
|- Number of jail:      2&lt;br /&gt;
`- Jail list:   proxmox, sshd&lt;br /&gt;
[root@proxy proxymox]# &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous pouvons maintenant passer à l&#039;API !&lt;br /&gt;
&lt;br /&gt;
=== Invention d&#039;une API pour fail2ban ===&lt;br /&gt;
&lt;br /&gt;
Toujours sur le reverse-proxy nous allons installer PHP pour créer un mini serveur qui répondra au urls suivantes:&lt;br /&gt;
* /ban/&amp;lt;ip&amp;gt; pour bannir&lt;br /&gt;
* /unban/&amp;lt;ip&amp;gt; pour lever le banissement&lt;br /&gt;
&lt;br /&gt;
Commençons par installer PHP:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# dnf -y install php-cli&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un répertoire &amp;quot;f2b-api&amp;quot; dans le dossier &amp;quot;opt&amp;quot; :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# mkdir /opt/f2b-api&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis créer un fichier &#039;&#039;f2b-api.php&#039;&#039; dans ce dossier:&lt;br /&gt;
&amp;lt;source lang=php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
main();&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        # On clean l&#039;uri du / de début&lt;br /&gt;
        $uri = ltrim($_SERVER[&#039;REQUEST_URI&#039;], &#039;/&#039;);&lt;br /&gt;
        # On éclate l&#039;uri en parties (action + ip)&lt;br /&gt;
        $parts = explode(&#039;/&#039;, $uri);&lt;br /&gt;
        # Récupération de l&#039;action dans une variable ou false si vide&lt;br /&gt;
        $action = empty($parts[0]) ? false : $parts[0];&lt;br /&gt;
        # Récupération de l&#039;ip dans une variable ou false si vide&lt;br /&gt;
        $ip = empty($parts[1]) ? false : $parts[1];&lt;br /&gt;
        if(!$action || !$ip){&lt;br /&gt;
                # Si action vide =&amp;gt; 400 Bad request&lt;br /&gt;
                http_response_code(400);&lt;br /&gt;
                die();&lt;br /&gt;
        }&lt;br /&gt;
        if(!in_array($action, [&#039;ban&#039;, &#039;unban&#039;])){&lt;br /&gt;
                # Si action pas dans la liste =&amp;gt; 400 Bad request&lt;br /&gt;
                http_response_code(400);&lt;br /&gt;
                die();&lt;br /&gt;
        }&lt;br /&gt;
        $cmd = &#039;&#039;;&lt;br /&gt;
        if($action == &#039;ban&#039;){&lt;br /&gt;
                $cmd = &#039;fail2ban-client set proxmox banip &#039; . $ip;&lt;br /&gt;
        } else if($action == &#039;unban&#039;){&lt;br /&gt;
                $cmd = &#039;fail2ban-client unban proxmox &#039; . $ip;&lt;br /&gt;
        }&lt;br /&gt;
        shell_exec($cmd);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;amp;#9888; Gardez en tête que ce code simpliste n&#039;est en aucun cas sécurisé et ne doit pas être accessible depuis Internet.&lt;br /&gt;
&lt;br /&gt;
Pour démarrer se code en mode serveur il suffit de taper la commande suivante:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# php -S 0.0.0.0:8080 -t /opt/f2b-api /opt/f2b-api/index.php&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous pouvez tester directement depuis un autre terminal en tapant les commandes:&lt;br /&gt;
* pour bannir :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# curl -X GET http://127.0.0.1/ban/@ip&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* pour dé-bannir :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# curl -X GET http://127.0.0.1/unban/@ip&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Et en vérifiant dans fail2ban:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed: 0&lt;br /&gt;
|  |- Total failed:     0&lt;br /&gt;
|  `- File list:        /dev/null&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned: 1&lt;br /&gt;
   |- Total banned:     10&lt;br /&gt;
   `- Banned IP list:   1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4409</id>
		<title>Proxmox fail2ban</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4409"/>
		<updated>2026-07-11T16:29:51Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Invention d&amp;#039;une API pour fail2ban */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
Proxmox utilise une interface web d&#039;administration qui utilise le port TCP 8006 et c&#039;est un vecteur possible d&#039;attaque par force brut. Nous allons donc &#039;&#039;dresser&#039;&#039; fail2ban pour agir en cas d&#039;attaque !&lt;br /&gt;
&lt;br /&gt;
Proxmox utilise Debian, nous allons principalement reproduire les étapes décrites dans le tutoriel de [[Sécuriser_un_service_avec_Fail2ban| Fail2ban pour Rocky]] et adapter à Debian.&lt;br /&gt;
&lt;br /&gt;
Avant d&#039;aller plus loin, assurez-vous d&#039;avoir correctement installé et configuré [[proxmox_iptables |iptables sur Proxmox]]&lt;br /&gt;
&lt;br /&gt;
= Installation =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt -y install fail2ban&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Configuration =&lt;br /&gt;
Tout d&#039;abord il faut copier le fichier &#039;&#039;/etc/fail2ban/jail.conf&#039;&#039; en &#039;&#039;/etc/fail2ban/jail.local&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dans ce fichier, on va s&#039;intéresser aux variables suivantes:&lt;br /&gt;
*ignoreip : correspond à la suite d&#039;adresses IP qui ne se feront jamais bannir;&lt;br /&gt;
*maxretry : correspond au nombre d&#039;essais;&lt;br /&gt;
*findtime : correspond à la période pendant laquelle les essais vont incrémenter maxretry;&lt;br /&gt;
*bantime  : correspond au temps où l&#039;adresse IP ne peut pas se connecter.&lt;br /&gt;
&lt;br /&gt;
= Configuration de base =&lt;br /&gt;
== Choix de la punition ==&lt;br /&gt;
Il faut choisir quelque chose de cohérent (une punition suffisante) pour ne pas permettre de se faire cracker son mot de passe:&lt;br /&gt;
*maxretry = 3&lt;br /&gt;
*findtime = 86400 (correspond à 1 journée)&lt;br /&gt;
*bantime = 604800 (correspond à 1 semaine)&lt;br /&gt;
&lt;br /&gt;
Cela signifie que si une adresse IP se trompe 3 fois en 1 journée (86400s) elle se fait bannir pendant 1 semaine (604800s).&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul permet de trouver le nombre maximal de tentatives durant une année:&lt;br /&gt;
&lt;br /&gt;
365 jours / 7 jours par semaine * 3 tentatives = 156 essais, ce qui reste raisonnable. &lt;br /&gt;
&lt;br /&gt;
Si le pirate possède un [http://fr.wikipedia.org/wiki/Botnet botnet], il faut bien sûr multiplier ce nombre par le nombre de machines dans le botnet...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Attention : fail2ban parcours les logs de connexion pour connaître le numéro de la tentative, ce qui a pour conséquence, si le &#039;&#039;findtime&#039;&#039; est grand, de prendre un certain temps...&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Jail pour SSH ==&lt;br /&gt;
Il suffit d&#039;ajouter la ligne &#039;&#039;enabled=true&#039;&#039; dans la section à activer !&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[sshd]&lt;br /&gt;
&lt;br /&gt;
# To use more aggressive sshd modes set filter parameter &amp;quot;mode&amp;quot; in jail.local:&lt;br /&gt;
# normal (default), ddos, extra or aggressive (combines all).&lt;br /&gt;
# See &amp;quot;tests/files/logs/sshd&amp;quot; or &amp;quot;filter.d/sshd.conf&amp;quot; for usage example and details.&lt;br /&gt;
#mode   = normal&lt;br /&gt;
enabled = true&lt;br /&gt;
port    = ssh&lt;br /&gt;
logpath = %(sshd_log)s&lt;br /&gt;
backend = %(sshd_backend)s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Configuration spécifique =&lt;br /&gt;
== Jail pour PVEPROXY ==&lt;br /&gt;
Pveproxy écoute sur le port 8006 et ne fonctionne pas exactement comme un serveur [[HTTPD | Apache httpd]] qui mettrait ces logs dans le fichier &#039;&#039;error_log&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Nous allons mettre cette configuration spécifique dans le fichier &#039;&#039;/etc/fail2ban/jail.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[proxmox]&lt;br /&gt;
enabled = true&lt;br /&gt;
port = https,http,8006&lt;br /&gt;
filter = proxmox&lt;br /&gt;
backend = systemd&lt;br /&gt;
maxretry = 5&lt;br /&gt;
findtime = 1d&lt;br /&gt;
bantime = 1w&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le backend utilisé est systemd, exactement comme si vous utilisiez la commande :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Filtre pour PVEPROXY ==&lt;br /&gt;
Il ne nous reste plus qu&#039;à spécifier le filtre &#039;&#039;proxmox&#039;&#039; dans le fichier &#039;&#039;/etc/fail2ban/filter.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=&amp;lt;HOST&amp;gt; user=.* msg=.*&lt;br /&gt;
ignoreregex =&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Tests =&lt;br /&gt;
Il faut maintenant tester le filtre et pour ça on peut utiliser un partage de connexion et réaliser le nombre d&#039;échecs spécifié par la directive &amp;quot;maxretry&amp;quot; (ici 3) :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed:	0&lt;br /&gt;
|  |- Total failed:	3&lt;br /&gt;
|  `- Journal matches:	_SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned:	1&lt;br /&gt;
   |- Total banned:	1&lt;br /&gt;
   `- Banned IP list:	37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On voit bien l&#039;IP 37.167.23.159 qui est bannie !&lt;br /&gt;
N&#039;oubliez pas de l&#039;ajouter à &#039;&#039;ignoreip&#039;&#039; dans le fichier &#039;&#039;jails.local&#039;&#039; ou de faire &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client unban 37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Démarrage et enregistrement dans le chargeur de démarrage =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start fail2ban.service&lt;br /&gt;
# systemctl enable fail2ban.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Vous pouvez maintenant démarrer fail2ban&lt;br /&gt;
&lt;br /&gt;
= Proxification=&lt;br /&gt;
Lorsque votre serveur Proxmox se trouve derrière un reverse-proxy (Apache, Nginx, Traefik, ...), au niveau 3 OSI, l&#039;adresse IP du client est remplacée par celle du proxy et le serveur utilise l&#039;entêtes &#039;&#039;X-Forwarded-For&#039;&#039; ou &#039;&#039;X-Real-IP&#039;&#039; pour transporter l&#039;adresse du client &lt;br /&gt;
[[Fichier:Reverse proxy proxmox.png|700px|centré]]&lt;br /&gt;
Le problème est que la seule adresse que fail2ban va voir apparaître dans les logs est celle du reverse-proxy (&#039;&#039;192.168.4.100&#039;&#039;) :&lt;br /&gt;
[[Fichier:Reverse proxy ip logs.png|600px|centré]]&lt;br /&gt;
Même si le filtre &#039;&#039;fail2ban&#039;&#039; est configuré pour utiliser la commande &#039;&#039;journactl&#039;&#039; sur le démon &#039;&#039;pvedaemon&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
les adresses viennent de pveproxy qui journalise tout dans &#039;&#039;/var/log/pveproxy/access.log&#039;&#039; et &#039;&#039;pvedaemon&#039;&#039; ne journalise que les échecs d&#039;authentification. &lt;br /&gt;
Il est donc plus simple de faire un &#039;&#039;tail&#039;&#039; ou un &#039;&#039;cat&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Que d&#039;utiliser &#039;&#039;journalctl&#039;&#039; pour voir les IPs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
Dec 14 10:43:01 labo unix_chkpwd[1326506]: password check failed for user (root)&lt;br /&gt;
Dec 14 10:43:01 labo IPCC.xs[1320783]: pam_unix(proxmox-ve-auth:auth): authentication failure; logname= uid=0 euid=0 tty= ruser= rhost=37.167.23.159  user=root&lt;br /&gt;
Dec 14 10:43:03 labo pvedaemon[1320783]: authentication failure; rhost=37.167.23.159 user=root@pam msg=Authentication failure&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Configuration de pveproxy ==&lt;br /&gt;
Si on veut voir l&#039;adresse du client, il faut dire au [https://fr.wikipedia.org/wiki/Daemon_(informatique)| démon] &#039;&#039;pveproxy&#039;&#039; d&#039;utiliser l&#039;une des deux entêtes précédentes ainsi que préciser l&#039;adresse du proxy. &lt;br /&gt;
&lt;br /&gt;
Préciser l&#039;adresse du proxy est essentiel pour que &#039;&#039;pveproxy&#039;&#039; n&#039;accepte de lire l&#039;adresse du client présente dans l&#039;entête &#039;&#039;&#039;uniquement&#039;&#039;&#039; si cela provient du proxy, qui est une machine de confiance. Le cas contraire, tout le monde pourrait ajouter une adresse IP dans l&#039;entête pour la faire bannir...&lt;br /&gt;
&lt;br /&gt;
Nous allons créer le fichier &#039;&#039;/etc/default/pveproxy&#039;&#039; avec les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Forwarded-For&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Real-IP&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_ALLOW_FROM=&amp;quot;192.168.4.100&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il faut maintenant redémarrer &#039;&#039;pveproxy&#039;&#039; pour que les changements s&#039;appliquent. Si vous êtes connecté via l&#039;interface web, cela va vous déconnecter, le temps que le démon redémarre, il faudra ensuite certainement rafraîchir la page web.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl restart pveproxy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à vérifier dans les logs si les bonnes adresses s&#039;affichent:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Si jamais ce n&#039;est pas le cas, poursuivez avec la modification du fichier &#039;&#039;AnyEvent.pm&#039;&#039;&lt;br /&gt;
== Modification de AnyEvent.pm ==&lt;br /&gt;
=== Application de la modification ===&lt;br /&gt;
Au jour d&#039;aujourd&#039;hui (13/12/25) la proxification ne fonctionne plus et il faut apporter une modification dans le fichier &#039;&#039;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&#039;&#039; pour que les bonnes adresses apparaissent !&lt;br /&gt;
En fonction des versions cette modification peut avoir lieu soit ligne &#039;&#039;&#039;1504&#039;&#039;&#039;, soit ligne &#039;&#039;&#039;1554&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Il faut repérer la fonction suivante:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
sub authenticate_and_handle_request {&lt;br /&gt;
    my ($self, $reqstate) = @_;&lt;br /&gt;
&lt;br /&gt;
    my $request = $reqstate-&amp;gt;{request};&lt;br /&gt;
    my $method = $request-&amp;gt;method();&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
C&#039;est un peu plus loin qu&#039;il faut insérer le code :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 ### INSERTION ICI ###&lt;br /&gt;
&lt;br /&gt;
    if ($self-&amp;gt;{spiceproxy}) {&lt;br /&gt;
        my $connect_str = $request-&amp;gt;header(&#039;Host&#039;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il faut modifier l&#039;attribut &#039;&#039;peer_host&#039;&#039; de l&#039;objet &#039;&#039;reqstate&#039;&#039; si l&#039;une des deux entêtes est présente :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if ($request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
} elsif ($request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Double IPv4 ou préfixe IPv6 ===&lt;br /&gt;
Après redémarrage, cela permet de voir l&#039;adresse du client dans les logs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/ext-all.js?ver=7.0.0 HTTP/1.1&amp;quot; 200 683505&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/js/u2f-api.js HTTP/1.1&amp;quot; 200 4898&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/resources HTTP/1.1&amp;quot; 200 1226&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/tasks HTTP/1.1&amp;quot; 200 1090&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /proxmoxlib.js?ver=v5.0.4-t1754316706 HTTP/1.1&amp;quot; 200 157086&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/theme-crisp/resources/theme-crisp-all_1.css HTTP/1.1&amp;quot; 200 32919&lt;br /&gt;
::ffff:192.168.20.22 - root@pam [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/nodes/labo/lxc/100/status/current HTTP/1.1&amp;quot; 200 523&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il nous reste un peu de nettoyage à faire, dans certains cas :&lt;br /&gt;
* l&#039;adresse apparaît non pas une fois mais deux, séparées par une virgule&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
37.167.182.207, 37.167.182.207&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* l&#039;adresse IPv4 (32 bits) est affichée dans sa représentation IPv6 (128 bits), avec le préfixe &#039;&#039;::ffff:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
::ffff:192.168.20.22&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On a deux possibilités pour faire le nettoyage :&lt;br /&gt;
*Soit on ajoute les lignes suivantes dans &#039;&#039;AnyEvent.pm&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if (index($reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
   # Remove trailing ip &lt;br /&gt;
   my @fields = split /,/, $reqstate-&amp;gt;{peer_host};&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $fields[0];&lt;br /&gt;
}&lt;br /&gt;
if($reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
   # Remove IPv6 subnet for IPv4&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $1;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*Soit on modifie le filtre /etc/fail2ban/filter.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=.*:?&amp;lt;HOST&amp;gt;,? user=.* msg=.*&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Automatisation ===&lt;br /&gt;
On peut automatiser le processus précédent avec le script suivant, que l&#039;on peut créer dans /root/remoteip_fix.sh :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=bash&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
ANYEVENT_PATH=&amp;quot;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&amp;quot;&lt;br /&gt;
ANYEVENT_REGEX=&#039;$self-&amp;gt;{spiceproxy}&#039;&lt;br /&gt;
TMP_FILE=&amp;quot;/tmp/AnyEvent.pm.tmp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if [ ! -f $ANYEVENT_PATH ]; then&lt;br /&gt;
  echo &amp;quot;$ANYEVENT_PATH does not exists !&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
if [ $(grep &#039;### BUGFIX REMOTE_IP FOR FAIL2BAN ###&#039; $ANYEVENT_PATH | wc -l) -eq 1 ]; then&lt;br /&gt;
  echo &amp;quot;AnyEvent.pm already patched !&amp;quot;&lt;br /&gt;
  exit 0&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
LINE_NUMBER_TOP=$(nl -ba $ANYEVENT_PATH | grep $ANYEVENT_REGEX | head -n 1 | awk -F &#039; &#039; &#039;{print $1}&#039;)&lt;br /&gt;
let LINE_NUMBER_TOP-=1&lt;br /&gt;
&lt;br /&gt;
if [ $LINE_NUMBER_TOP -lt 0 ]; then&lt;br /&gt;
  echo &amp;quot;Did not find the $ANYEVENT_REGEX expr in $ANYEVENT_PATH&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
echo -n &amp;quot;Applying bugfix: &amp;quot;&lt;br /&gt;
trap &amp;quot;rm -f $TMP_FILE&amp;quot; 0 1 2 5 13 15&lt;br /&gt;
head -n $LINE_NUMBER_TOP $ANYEVENT_PATH &amp;gt;$TMP_FILE&lt;br /&gt;
cat &amp;gt;&amp;gt;$TMP_FILE &amp;lt;&amp;lt;EOF&lt;br /&gt;
### BUGFIX REMOTE_IP FOR FAIL2BAN ###&lt;br /&gt;
    if (\$request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
    } elsif (\$request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
    }&lt;br /&gt;
    if (index(\$reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
        my @fields = split /,/, \$reqstate-&amp;gt;{peer_host};&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$fields[0];&lt;br /&gt;
    }&lt;br /&gt;
    if(\$reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
        # Remove IPv6 subnet for IPv4&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$1;&lt;br /&gt;
    }&lt;br /&gt;
#####################################&lt;br /&gt;
EOF&lt;br /&gt;
echo &amp;quot;$ANYEVENT_MODIF&amp;quot; &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cp $ANYEVENT_PATH $ANYEVENT_PATH.ori&lt;br /&gt;
LINE_NUMBER_BOTTOM=$(cat $ANYEVENT_PATH | wc -l)&lt;br /&gt;
let LINE_NUMBER_BOTTOM-=LINE_NUMBER_TOP&lt;br /&gt;
tail -n $LINE_NUMBER_BOTTOM $ANYEVENT_PATH &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cat $TMP_FILE &amp;gt;$ANYEVENT_PATH&lt;br /&gt;
rm -f $TMP_FILE&lt;br /&gt;
trap 0&lt;br /&gt;
echo &amp;quot;done.&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à le rendre exécutable et le lancer :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# chmod +x /root/remoteip_fix.sh&lt;br /&gt;
# /root/remoteip_fix.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne faudra pas oublier de redémarrer &#039;&#039;pveproxy&#039;&#039; pour appliquer les changements !&lt;br /&gt;
&lt;br /&gt;
== Comment bannir derrière un reverse-proxy ? ==&lt;br /&gt;
Maintenant que votre Proxmox est derrière un reverse-proxy, inutile de bannir les IP publiques avec iptables sur le serveur Proxmox, la seule IP visible est celle du reverse-proxy (dans cet exemple 192.168.4.100).&lt;br /&gt;
&lt;br /&gt;
La seule machine capable capable de bannir est le reverse-proxy, il faut donc lui transmettre les IP et nous allons faire ça en trois étapes:&lt;br /&gt;
* la première est de créer une &amp;quot;prison&amp;quot; proxmox sur le fail2ban présent sur le reverse-proxy&lt;br /&gt;
* la deuxième est l&#039;invention d&#039;une API pour fail2ban sur le reverse-proxy&lt;br /&gt;
* la troisième est la modification du comportement de fail2ban pour appeler cette API au lieu de modifier iptables&lt;br /&gt;
&lt;br /&gt;
=== Création d&#039;une prison sur le reverse-proxy ===&lt;br /&gt;
&lt;br /&gt;
Pour bannir nous allons créer une prison spécifique pour le / les serveurs Proxmox que nous allons appeler &#039;&#039;proxmox&#039;&#039; dans le fichier /etc/fail2ban/jail.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[proxmox]&lt;br /&gt;
enabled = true&lt;br /&gt;
port = https,http&lt;br /&gt;
filter = do-nothing&lt;br /&gt;
logpath = /dev/null&lt;br /&gt;
maxretry = 3&lt;br /&gt;
findtime = 1d&lt;br /&gt;
bantime = 1w&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
J&#039;attire votre attention sur les paramètres &#039;&#039;maxretry&#039;&#039;, &#039;&#039;findtime&#039;&#039; et &#039;&#039;bantime&#039;&#039; qui doivent concorder avec ceux du fail2ban de votre Proxmox. S&#039;il sont plus &#039;&#039;court&#039;&#039; sur le reverse-proxy, les IP seront libérées plus tôt à l&#039;inverse, plus long n&#039;est pas gênant, le fail2ban de votre Proxmox les libéreras avant celui du proxy.&lt;br /&gt;
&lt;br /&gt;
Vous avez remarquez le filtre &#039;&#039;do-nothing&#039;&#039; qu&#039;il nous reste à créer dans le fichier &#039;&#039;/etc/fail2ban/filter.d/do-nothing.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
&lt;br /&gt;
failregex = ^&amp;lt;HOST&amp;gt;$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Après redémarrage de fail2ban :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl restart fail2ban&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous devriez voir la prison&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status&lt;br /&gt;
Status&lt;br /&gt;
|- Number of jail:      2&lt;br /&gt;
`- Jail list:   proxmox, sshd&lt;br /&gt;
[root@proxy proxymox]# &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous pouvons maintenant passer à l&#039;API !&lt;br /&gt;
&lt;br /&gt;
=== Invention d&#039;une API pour fail2ban ===&lt;br /&gt;
&lt;br /&gt;
Toujours sur le reverse-proxy nous allons installer PHP pour créer un mini serveur qui répondra au urls suivantes:&lt;br /&gt;
* /ban/&amp;lt;ip&amp;gt; pour bannir&lt;br /&gt;
* /unban/&amp;lt;ip&amp;gt; pour lever le banissement&lt;br /&gt;
&lt;br /&gt;
Commençons par installer PHP:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# dnf -y install php-cli&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un répertoire &amp;quot;f2b-api&amp;quot; dans le dossier &amp;quot;opt&amp;quot; :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# mkdir /opt/f2b-api&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis créer un fichier &#039;&#039;f2b-api.php&#039;&#039; dans ce dossier:&lt;br /&gt;
&amp;lt;source lang=php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
main();&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        # On clean l&#039;uri du / de début&lt;br /&gt;
        $uri = ltrim($_SERVER[&#039;REQUEST_URI&#039;], &#039;/&#039;);&lt;br /&gt;
        # On éclate l&#039;uri en parties (action + ip)&lt;br /&gt;
        $parts = explode(&#039;/&#039;, $uri);&lt;br /&gt;
        # Récupération de l&#039;action dans une variable ou false si vide&lt;br /&gt;
        $action = empty($parts[0]) ? false : $parts[0];&lt;br /&gt;
        # Récupération de l&#039;ip dans une variable ou false si vide&lt;br /&gt;
        $ip = empty($parts[1]) ? false : $parts[1];&lt;br /&gt;
        if(!$action || !$ip){&lt;br /&gt;
                # Si action vide =&amp;gt; 400 Bad request&lt;br /&gt;
                http_response_code(400);&lt;br /&gt;
                die();&lt;br /&gt;
        }&lt;br /&gt;
        if(!in_array($action, [&#039;ban&#039;, &#039;unban&#039;])){&lt;br /&gt;
                # Si action pas dans la liste =&amp;gt; 400 Bad request&lt;br /&gt;
                http_response_code(400);&lt;br /&gt;
                die();&lt;br /&gt;
        }&lt;br /&gt;
        $cmd = &#039;&#039;;&lt;br /&gt;
        if($action == &#039;ban&#039;){&lt;br /&gt;
                $cmd = &#039;fail2ban-client set proxmox banip &#039; . $ip;&lt;br /&gt;
        } else if($action == &#039;unban&#039;){&lt;br /&gt;
                $cmd = &#039;fail2ban-client unban proxmox &#039; . $ip;&lt;br /&gt;
        }&lt;br /&gt;
        shell_exec($cmd);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;amp;#9888; Gardez en tête que ce code simpliste n&#039;est en aucun cas sécurisé et ne doit pas être accessible depuis Internet.&lt;br /&gt;
&lt;br /&gt;
Pour démarrer se code en mode serveur il suffit de taper la commande suivante:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# php -S 0.0.0.0:8080 -t /opt/f2b-api /opt/f2b-api/index.php&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous pouvez tester directement depuis un autre terminal en tapant les commandes:&lt;br /&gt;
* pour bannir :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# curl -X GET http://127.0.0.1/ban/@ip&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* pour dé-bannir :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# curl -X GET http://127.0.0.1/unban/@ip&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Et en vérifiant dans fail2ban:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# curl -X GET http://127.0.0.1/unban/@ip&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4408</id>
		<title>Proxmox fail2ban</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4408"/>
		<updated>2026-07-11T16:29:37Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Création d&amp;#039;une prison sur le reverse-proxy */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
Proxmox utilise une interface web d&#039;administration qui utilise le port TCP 8006 et c&#039;est un vecteur possible d&#039;attaque par force brut. Nous allons donc &#039;&#039;dresser&#039;&#039; fail2ban pour agir en cas d&#039;attaque !&lt;br /&gt;
&lt;br /&gt;
Proxmox utilise Debian, nous allons principalement reproduire les étapes décrites dans le tutoriel de [[Sécuriser_un_service_avec_Fail2ban| Fail2ban pour Rocky]] et adapter à Debian.&lt;br /&gt;
&lt;br /&gt;
Avant d&#039;aller plus loin, assurez-vous d&#039;avoir correctement installé et configuré [[proxmox_iptables |iptables sur Proxmox]]&lt;br /&gt;
&lt;br /&gt;
= Installation =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt -y install fail2ban&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Configuration =&lt;br /&gt;
Tout d&#039;abord il faut copier le fichier &#039;&#039;/etc/fail2ban/jail.conf&#039;&#039; en &#039;&#039;/etc/fail2ban/jail.local&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dans ce fichier, on va s&#039;intéresser aux variables suivantes:&lt;br /&gt;
*ignoreip : correspond à la suite d&#039;adresses IP qui ne se feront jamais bannir;&lt;br /&gt;
*maxretry : correspond au nombre d&#039;essais;&lt;br /&gt;
*findtime : correspond à la période pendant laquelle les essais vont incrémenter maxretry;&lt;br /&gt;
*bantime  : correspond au temps où l&#039;adresse IP ne peut pas se connecter.&lt;br /&gt;
&lt;br /&gt;
= Configuration de base =&lt;br /&gt;
== Choix de la punition ==&lt;br /&gt;
Il faut choisir quelque chose de cohérent (une punition suffisante) pour ne pas permettre de se faire cracker son mot de passe:&lt;br /&gt;
*maxretry = 3&lt;br /&gt;
*findtime = 86400 (correspond à 1 journée)&lt;br /&gt;
*bantime = 604800 (correspond à 1 semaine)&lt;br /&gt;
&lt;br /&gt;
Cela signifie que si une adresse IP se trompe 3 fois en 1 journée (86400s) elle se fait bannir pendant 1 semaine (604800s).&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul permet de trouver le nombre maximal de tentatives durant une année:&lt;br /&gt;
&lt;br /&gt;
365 jours / 7 jours par semaine * 3 tentatives = 156 essais, ce qui reste raisonnable. &lt;br /&gt;
&lt;br /&gt;
Si le pirate possède un [http://fr.wikipedia.org/wiki/Botnet botnet], il faut bien sûr multiplier ce nombre par le nombre de machines dans le botnet...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Attention : fail2ban parcours les logs de connexion pour connaître le numéro de la tentative, ce qui a pour conséquence, si le &#039;&#039;findtime&#039;&#039; est grand, de prendre un certain temps...&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Jail pour SSH ==&lt;br /&gt;
Il suffit d&#039;ajouter la ligne &#039;&#039;enabled=true&#039;&#039; dans la section à activer !&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[sshd]&lt;br /&gt;
&lt;br /&gt;
# To use more aggressive sshd modes set filter parameter &amp;quot;mode&amp;quot; in jail.local:&lt;br /&gt;
# normal (default), ddos, extra or aggressive (combines all).&lt;br /&gt;
# See &amp;quot;tests/files/logs/sshd&amp;quot; or &amp;quot;filter.d/sshd.conf&amp;quot; for usage example and details.&lt;br /&gt;
#mode   = normal&lt;br /&gt;
enabled = true&lt;br /&gt;
port    = ssh&lt;br /&gt;
logpath = %(sshd_log)s&lt;br /&gt;
backend = %(sshd_backend)s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Configuration spécifique =&lt;br /&gt;
== Jail pour PVEPROXY ==&lt;br /&gt;
Pveproxy écoute sur le port 8006 et ne fonctionne pas exactement comme un serveur [[HTTPD | Apache httpd]] qui mettrait ces logs dans le fichier &#039;&#039;error_log&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Nous allons mettre cette configuration spécifique dans le fichier &#039;&#039;/etc/fail2ban/jail.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[proxmox]&lt;br /&gt;
enabled = true&lt;br /&gt;
port = https,http,8006&lt;br /&gt;
filter = proxmox&lt;br /&gt;
backend = systemd&lt;br /&gt;
maxretry = 5&lt;br /&gt;
findtime = 1d&lt;br /&gt;
bantime = 1w&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le backend utilisé est systemd, exactement comme si vous utilisiez la commande :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Filtre pour PVEPROXY ==&lt;br /&gt;
Il ne nous reste plus qu&#039;à spécifier le filtre &#039;&#039;proxmox&#039;&#039; dans le fichier &#039;&#039;/etc/fail2ban/filter.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=&amp;lt;HOST&amp;gt; user=.* msg=.*&lt;br /&gt;
ignoreregex =&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Tests =&lt;br /&gt;
Il faut maintenant tester le filtre et pour ça on peut utiliser un partage de connexion et réaliser le nombre d&#039;échecs spécifié par la directive &amp;quot;maxretry&amp;quot; (ici 3) :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed:	0&lt;br /&gt;
|  |- Total failed:	3&lt;br /&gt;
|  `- Journal matches:	_SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned:	1&lt;br /&gt;
   |- Total banned:	1&lt;br /&gt;
   `- Banned IP list:	37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On voit bien l&#039;IP 37.167.23.159 qui est bannie !&lt;br /&gt;
N&#039;oubliez pas de l&#039;ajouter à &#039;&#039;ignoreip&#039;&#039; dans le fichier &#039;&#039;jails.local&#039;&#039; ou de faire &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client unban 37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Démarrage et enregistrement dans le chargeur de démarrage =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start fail2ban.service&lt;br /&gt;
# systemctl enable fail2ban.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Vous pouvez maintenant démarrer fail2ban&lt;br /&gt;
&lt;br /&gt;
= Proxification=&lt;br /&gt;
Lorsque votre serveur Proxmox se trouve derrière un reverse-proxy (Apache, Nginx, Traefik, ...), au niveau 3 OSI, l&#039;adresse IP du client est remplacée par celle du proxy et le serveur utilise l&#039;entêtes &#039;&#039;X-Forwarded-For&#039;&#039; ou &#039;&#039;X-Real-IP&#039;&#039; pour transporter l&#039;adresse du client &lt;br /&gt;
[[Fichier:Reverse proxy proxmox.png|700px|centré]]&lt;br /&gt;
Le problème est que la seule adresse que fail2ban va voir apparaître dans les logs est celle du reverse-proxy (&#039;&#039;192.168.4.100&#039;&#039;) :&lt;br /&gt;
[[Fichier:Reverse proxy ip logs.png|600px|centré]]&lt;br /&gt;
Même si le filtre &#039;&#039;fail2ban&#039;&#039; est configuré pour utiliser la commande &#039;&#039;journactl&#039;&#039; sur le démon &#039;&#039;pvedaemon&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
les adresses viennent de pveproxy qui journalise tout dans &#039;&#039;/var/log/pveproxy/access.log&#039;&#039; et &#039;&#039;pvedaemon&#039;&#039; ne journalise que les échecs d&#039;authentification. &lt;br /&gt;
Il est donc plus simple de faire un &#039;&#039;tail&#039;&#039; ou un &#039;&#039;cat&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Que d&#039;utiliser &#039;&#039;journalctl&#039;&#039; pour voir les IPs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
Dec 14 10:43:01 labo unix_chkpwd[1326506]: password check failed for user (root)&lt;br /&gt;
Dec 14 10:43:01 labo IPCC.xs[1320783]: pam_unix(proxmox-ve-auth:auth): authentication failure; logname= uid=0 euid=0 tty= ruser= rhost=37.167.23.159  user=root&lt;br /&gt;
Dec 14 10:43:03 labo pvedaemon[1320783]: authentication failure; rhost=37.167.23.159 user=root@pam msg=Authentication failure&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Configuration de pveproxy ==&lt;br /&gt;
Si on veut voir l&#039;adresse du client, il faut dire au [https://fr.wikipedia.org/wiki/Daemon_(informatique)| démon] &#039;&#039;pveproxy&#039;&#039; d&#039;utiliser l&#039;une des deux entêtes précédentes ainsi que préciser l&#039;adresse du proxy. &lt;br /&gt;
&lt;br /&gt;
Préciser l&#039;adresse du proxy est essentiel pour que &#039;&#039;pveproxy&#039;&#039; n&#039;accepte de lire l&#039;adresse du client présente dans l&#039;entête &#039;&#039;&#039;uniquement&#039;&#039;&#039; si cela provient du proxy, qui est une machine de confiance. Le cas contraire, tout le monde pourrait ajouter une adresse IP dans l&#039;entête pour la faire bannir...&lt;br /&gt;
&lt;br /&gt;
Nous allons créer le fichier &#039;&#039;/etc/default/pveproxy&#039;&#039; avec les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Forwarded-For&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Real-IP&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_ALLOW_FROM=&amp;quot;192.168.4.100&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il faut maintenant redémarrer &#039;&#039;pveproxy&#039;&#039; pour que les changements s&#039;appliquent. Si vous êtes connecté via l&#039;interface web, cela va vous déconnecter, le temps que le démon redémarre, il faudra ensuite certainement rafraîchir la page web.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl restart pveproxy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à vérifier dans les logs si les bonnes adresses s&#039;affichent:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Si jamais ce n&#039;est pas le cas, poursuivez avec la modification du fichier &#039;&#039;AnyEvent.pm&#039;&#039;&lt;br /&gt;
== Modification de AnyEvent.pm ==&lt;br /&gt;
=== Application de la modification ===&lt;br /&gt;
Au jour d&#039;aujourd&#039;hui (13/12/25) la proxification ne fonctionne plus et il faut apporter une modification dans le fichier &#039;&#039;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&#039;&#039; pour que les bonnes adresses apparaissent !&lt;br /&gt;
En fonction des versions cette modification peut avoir lieu soit ligne &#039;&#039;&#039;1504&#039;&#039;&#039;, soit ligne &#039;&#039;&#039;1554&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Il faut repérer la fonction suivante:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
sub authenticate_and_handle_request {&lt;br /&gt;
    my ($self, $reqstate) = @_;&lt;br /&gt;
&lt;br /&gt;
    my $request = $reqstate-&amp;gt;{request};&lt;br /&gt;
    my $method = $request-&amp;gt;method();&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
C&#039;est un peu plus loin qu&#039;il faut insérer le code :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 ### INSERTION ICI ###&lt;br /&gt;
&lt;br /&gt;
    if ($self-&amp;gt;{spiceproxy}) {&lt;br /&gt;
        my $connect_str = $request-&amp;gt;header(&#039;Host&#039;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il faut modifier l&#039;attribut &#039;&#039;peer_host&#039;&#039; de l&#039;objet &#039;&#039;reqstate&#039;&#039; si l&#039;une des deux entêtes est présente :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if ($request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
} elsif ($request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Double IPv4 ou préfixe IPv6 ===&lt;br /&gt;
Après redémarrage, cela permet de voir l&#039;adresse du client dans les logs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/ext-all.js?ver=7.0.0 HTTP/1.1&amp;quot; 200 683505&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/js/u2f-api.js HTTP/1.1&amp;quot; 200 4898&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/resources HTTP/1.1&amp;quot; 200 1226&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/tasks HTTP/1.1&amp;quot; 200 1090&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /proxmoxlib.js?ver=v5.0.4-t1754316706 HTTP/1.1&amp;quot; 200 157086&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/theme-crisp/resources/theme-crisp-all_1.css HTTP/1.1&amp;quot; 200 32919&lt;br /&gt;
::ffff:192.168.20.22 - root@pam [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/nodes/labo/lxc/100/status/current HTTP/1.1&amp;quot; 200 523&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il nous reste un peu de nettoyage à faire, dans certains cas :&lt;br /&gt;
* l&#039;adresse apparaît non pas une fois mais deux, séparées par une virgule&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
37.167.182.207, 37.167.182.207&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* l&#039;adresse IPv4 (32 bits) est affichée dans sa représentation IPv6 (128 bits), avec le préfixe &#039;&#039;::ffff:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
::ffff:192.168.20.22&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On a deux possibilités pour faire le nettoyage :&lt;br /&gt;
*Soit on ajoute les lignes suivantes dans &#039;&#039;AnyEvent.pm&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if (index($reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
   # Remove trailing ip &lt;br /&gt;
   my @fields = split /,/, $reqstate-&amp;gt;{peer_host};&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $fields[0];&lt;br /&gt;
}&lt;br /&gt;
if($reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
   # Remove IPv6 subnet for IPv4&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $1;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*Soit on modifie le filtre /etc/fail2ban/filter.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=.*:?&amp;lt;HOST&amp;gt;,? user=.* msg=.*&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Automatisation ===&lt;br /&gt;
On peut automatiser le processus précédent avec le script suivant, que l&#039;on peut créer dans /root/remoteip_fix.sh :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=bash&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
ANYEVENT_PATH=&amp;quot;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&amp;quot;&lt;br /&gt;
ANYEVENT_REGEX=&#039;$self-&amp;gt;{spiceproxy}&#039;&lt;br /&gt;
TMP_FILE=&amp;quot;/tmp/AnyEvent.pm.tmp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if [ ! -f $ANYEVENT_PATH ]; then&lt;br /&gt;
  echo &amp;quot;$ANYEVENT_PATH does not exists !&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
if [ $(grep &#039;### BUGFIX REMOTE_IP FOR FAIL2BAN ###&#039; $ANYEVENT_PATH | wc -l) -eq 1 ]; then&lt;br /&gt;
  echo &amp;quot;AnyEvent.pm already patched !&amp;quot;&lt;br /&gt;
  exit 0&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
LINE_NUMBER_TOP=$(nl -ba $ANYEVENT_PATH | grep $ANYEVENT_REGEX | head -n 1 | awk -F &#039; &#039; &#039;{print $1}&#039;)&lt;br /&gt;
let LINE_NUMBER_TOP-=1&lt;br /&gt;
&lt;br /&gt;
if [ $LINE_NUMBER_TOP -lt 0 ]; then&lt;br /&gt;
  echo &amp;quot;Did not find the $ANYEVENT_REGEX expr in $ANYEVENT_PATH&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
echo -n &amp;quot;Applying bugfix: &amp;quot;&lt;br /&gt;
trap &amp;quot;rm -f $TMP_FILE&amp;quot; 0 1 2 5 13 15&lt;br /&gt;
head -n $LINE_NUMBER_TOP $ANYEVENT_PATH &amp;gt;$TMP_FILE&lt;br /&gt;
cat &amp;gt;&amp;gt;$TMP_FILE &amp;lt;&amp;lt;EOF&lt;br /&gt;
### BUGFIX REMOTE_IP FOR FAIL2BAN ###&lt;br /&gt;
    if (\$request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
    } elsif (\$request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
    }&lt;br /&gt;
    if (index(\$reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
        my @fields = split /,/, \$reqstate-&amp;gt;{peer_host};&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$fields[0];&lt;br /&gt;
    }&lt;br /&gt;
    if(\$reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
        # Remove IPv6 subnet for IPv4&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$1;&lt;br /&gt;
    }&lt;br /&gt;
#####################################&lt;br /&gt;
EOF&lt;br /&gt;
echo &amp;quot;$ANYEVENT_MODIF&amp;quot; &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cp $ANYEVENT_PATH $ANYEVENT_PATH.ori&lt;br /&gt;
LINE_NUMBER_BOTTOM=$(cat $ANYEVENT_PATH | wc -l)&lt;br /&gt;
let LINE_NUMBER_BOTTOM-=LINE_NUMBER_TOP&lt;br /&gt;
tail -n $LINE_NUMBER_BOTTOM $ANYEVENT_PATH &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cat $TMP_FILE &amp;gt;$ANYEVENT_PATH&lt;br /&gt;
rm -f $TMP_FILE&lt;br /&gt;
trap 0&lt;br /&gt;
echo &amp;quot;done.&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à le rendre exécutable et le lancer :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# chmod +x /root/remoteip_fix.sh&lt;br /&gt;
# /root/remoteip_fix.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne faudra pas oublier de redémarrer &#039;&#039;pveproxy&#039;&#039; pour appliquer les changements !&lt;br /&gt;
&lt;br /&gt;
== Comment bannir derrière un reverse-proxy ? ==&lt;br /&gt;
Maintenant que votre Proxmox est derrière un reverse-proxy, inutile de bannir les IP publiques avec iptables sur le serveur Proxmox, la seule IP visible est celle du reverse-proxy (dans cet exemple 192.168.4.100).&lt;br /&gt;
&lt;br /&gt;
La seule machine capable capable de bannir est le reverse-proxy, il faut donc lui transmettre les IP et nous allons faire ça en trois étapes:&lt;br /&gt;
* la première est de créer une &amp;quot;prison&amp;quot; proxmox sur le fail2ban présent sur le reverse-proxy&lt;br /&gt;
* la deuxième est l&#039;invention d&#039;une API pour fail2ban sur le reverse-proxy&lt;br /&gt;
* la troisième est la modification du comportement de fail2ban pour appeler cette API au lieu de modifier iptables&lt;br /&gt;
&lt;br /&gt;
=== Création d&#039;une prison sur le reverse-proxy ===&lt;br /&gt;
&lt;br /&gt;
Pour bannir nous allons créer une prison spécifique pour le / les serveurs Proxmox que nous allons appeler &#039;&#039;proxmox&#039;&#039; dans le fichier /etc/fail2ban/jail.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[proxmox]&lt;br /&gt;
enabled = true&lt;br /&gt;
port = https,http&lt;br /&gt;
filter = do-nothing&lt;br /&gt;
logpath = /dev/null&lt;br /&gt;
maxretry = 3&lt;br /&gt;
findtime = 1d&lt;br /&gt;
bantime = 1w&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
J&#039;attire votre attention sur les paramètres &#039;&#039;maxretry&#039;&#039;, &#039;&#039;findtime&#039;&#039; et &#039;&#039;bantime&#039;&#039; qui doivent concorder avec ceux du fail2ban de votre Proxmox. S&#039;il sont plus &#039;&#039;court&#039;&#039; sur le reverse-proxy, les IP seront libérées plus tôt à l&#039;inverse, plus long n&#039;est pas gênant, le fail2ban de votre Proxmox les libéreras avant celui du proxy.&lt;br /&gt;
&lt;br /&gt;
Vous avez remarquez le filtre &#039;&#039;do-nothing&#039;&#039; qu&#039;il nous reste à créer dans le fichier &#039;&#039;/etc/fail2ban/filter.d/do-nothing.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
&lt;br /&gt;
failregex = ^&amp;lt;HOST&amp;gt;$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Après redémarrage de fail2ban :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# systemctl restart fail2ban&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous devriez voir la prison&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# fail2ban-client status&lt;br /&gt;
Status&lt;br /&gt;
|- Number of jail:      2&lt;br /&gt;
`- Jail list:   proxmox, sshd&lt;br /&gt;
[root@proxy proxymox]# &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous pouvons maintenant passer à l&#039;API !&lt;br /&gt;
&lt;br /&gt;
=== Invention d&#039;une API pour fail2ban ===&lt;br /&gt;
&lt;br /&gt;
Sur le reverse-proxy nous allons installer PHP pour créer un mini serveur qui répondra au urls suivantes:&lt;br /&gt;
* /ban/&amp;lt;ip&amp;gt; pour bannir&lt;br /&gt;
* /unban/&amp;lt;ip&amp;gt; pour lever le banissement&lt;br /&gt;
&lt;br /&gt;
Commençons par installer PHP:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# dnf -y install php-cli&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un répertoire &amp;quot;f2b-api&amp;quot; dans le dossier &amp;quot;opt&amp;quot; :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# mkdir /opt/f2b-api&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis créer un fichier &#039;&#039;f2b-api.php&#039;&#039; dans ce dossier:&lt;br /&gt;
&amp;lt;source lang=php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
main();&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        # On clean l&#039;uri du / de début&lt;br /&gt;
        $uri = ltrim($_SERVER[&#039;REQUEST_URI&#039;], &#039;/&#039;);&lt;br /&gt;
        # On éclate l&#039;uri en parties (action + ip)&lt;br /&gt;
        $parts = explode(&#039;/&#039;, $uri);&lt;br /&gt;
        # Récupération de l&#039;action dans une variable ou false si vide&lt;br /&gt;
        $action = empty($parts[0]) ? false : $parts[0];&lt;br /&gt;
        # Récupération de l&#039;ip dans une variable ou false si vide&lt;br /&gt;
        $ip = empty($parts[1]) ? false : $parts[1];&lt;br /&gt;
        if(!$action || !$ip){&lt;br /&gt;
                # Si action vide =&amp;gt; 400 Bad request&lt;br /&gt;
                http_response_code(400);&lt;br /&gt;
                die();&lt;br /&gt;
        }&lt;br /&gt;
        if(!in_array($action, [&#039;ban&#039;, &#039;unban&#039;])){&lt;br /&gt;
                # Si action pas dans la liste =&amp;gt; 400 Bad request&lt;br /&gt;
                http_response_code(400);&lt;br /&gt;
                die();&lt;br /&gt;
        }&lt;br /&gt;
        $cmd = &#039;&#039;;&lt;br /&gt;
        if($action == &#039;ban&#039;){&lt;br /&gt;
                $cmd = &#039;fail2ban-client set proxmox banip &#039; . $ip;&lt;br /&gt;
        } else if($action == &#039;unban&#039;){&lt;br /&gt;
                $cmd = &#039;fail2ban-client unban proxmox &#039; . $ip;&lt;br /&gt;
        }&lt;br /&gt;
        shell_exec($cmd);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;amp;#9888; Gardez en tête que ce code simpliste n&#039;est en aucun cas sécurisé et ne doit pas être accessible depuis Internet.&lt;br /&gt;
&lt;br /&gt;
Pour démarrer se code en mode serveur il suffit de taper la commande suivante:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# php -S 0.0.0.0:8080 -t /opt/f2b-api /opt/f2b-api/index.php&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous pouvez tester directement depuis un autre terminal en tapant les commandes:&lt;br /&gt;
* pour bannir :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# curl -X GET http://127.0.0.1/ban/@ip&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* pour dé-bannir :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# curl -X GET http://127.0.0.1/unban/@ip&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Et en vérifiant dans fail2ban:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# curl -X GET http://127.0.0.1/unban/@ip&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4407</id>
		<title>Proxmox fail2ban</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4407"/>
		<updated>2026-07-11T16:27:51Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
Proxmox utilise une interface web d&#039;administration qui utilise le port TCP 8006 et c&#039;est un vecteur possible d&#039;attaque par force brut. Nous allons donc &#039;&#039;dresser&#039;&#039; fail2ban pour agir en cas d&#039;attaque !&lt;br /&gt;
&lt;br /&gt;
Proxmox utilise Debian, nous allons principalement reproduire les étapes décrites dans le tutoriel de [[Sécuriser_un_service_avec_Fail2ban| Fail2ban pour Rocky]] et adapter à Debian.&lt;br /&gt;
&lt;br /&gt;
Avant d&#039;aller plus loin, assurez-vous d&#039;avoir correctement installé et configuré [[proxmox_iptables |iptables sur Proxmox]]&lt;br /&gt;
&lt;br /&gt;
= Installation =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt -y install fail2ban&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Configuration =&lt;br /&gt;
Tout d&#039;abord il faut copier le fichier &#039;&#039;/etc/fail2ban/jail.conf&#039;&#039; en &#039;&#039;/etc/fail2ban/jail.local&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dans ce fichier, on va s&#039;intéresser aux variables suivantes:&lt;br /&gt;
*ignoreip : correspond à la suite d&#039;adresses IP qui ne se feront jamais bannir;&lt;br /&gt;
*maxretry : correspond au nombre d&#039;essais;&lt;br /&gt;
*findtime : correspond à la période pendant laquelle les essais vont incrémenter maxretry;&lt;br /&gt;
*bantime  : correspond au temps où l&#039;adresse IP ne peut pas se connecter.&lt;br /&gt;
&lt;br /&gt;
= Configuration de base =&lt;br /&gt;
== Choix de la punition ==&lt;br /&gt;
Il faut choisir quelque chose de cohérent (une punition suffisante) pour ne pas permettre de se faire cracker son mot de passe:&lt;br /&gt;
*maxretry = 3&lt;br /&gt;
*findtime = 86400 (correspond à 1 journée)&lt;br /&gt;
*bantime = 604800 (correspond à 1 semaine)&lt;br /&gt;
&lt;br /&gt;
Cela signifie que si une adresse IP se trompe 3 fois en 1 journée (86400s) elle se fait bannir pendant 1 semaine (604800s).&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul permet de trouver le nombre maximal de tentatives durant une année:&lt;br /&gt;
&lt;br /&gt;
365 jours / 7 jours par semaine * 3 tentatives = 156 essais, ce qui reste raisonnable. &lt;br /&gt;
&lt;br /&gt;
Si le pirate possède un [http://fr.wikipedia.org/wiki/Botnet botnet], il faut bien sûr multiplier ce nombre par le nombre de machines dans le botnet...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Attention : fail2ban parcours les logs de connexion pour connaître le numéro de la tentative, ce qui a pour conséquence, si le &#039;&#039;findtime&#039;&#039; est grand, de prendre un certain temps...&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Jail pour SSH ==&lt;br /&gt;
Il suffit d&#039;ajouter la ligne &#039;&#039;enabled=true&#039;&#039; dans la section à activer !&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[sshd]&lt;br /&gt;
&lt;br /&gt;
# To use more aggressive sshd modes set filter parameter &amp;quot;mode&amp;quot; in jail.local:&lt;br /&gt;
# normal (default), ddos, extra or aggressive (combines all).&lt;br /&gt;
# See &amp;quot;tests/files/logs/sshd&amp;quot; or &amp;quot;filter.d/sshd.conf&amp;quot; for usage example and details.&lt;br /&gt;
#mode   = normal&lt;br /&gt;
enabled = true&lt;br /&gt;
port    = ssh&lt;br /&gt;
logpath = %(sshd_log)s&lt;br /&gt;
backend = %(sshd_backend)s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Configuration spécifique =&lt;br /&gt;
== Jail pour PVEPROXY ==&lt;br /&gt;
Pveproxy écoute sur le port 8006 et ne fonctionne pas exactement comme un serveur [[HTTPD | Apache httpd]] qui mettrait ces logs dans le fichier &#039;&#039;error_log&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Nous allons mettre cette configuration spécifique dans le fichier &#039;&#039;/etc/fail2ban/jail.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[proxmox]&lt;br /&gt;
enabled = true&lt;br /&gt;
port = https,http,8006&lt;br /&gt;
filter = proxmox&lt;br /&gt;
backend = systemd&lt;br /&gt;
maxretry = 5&lt;br /&gt;
findtime = 1d&lt;br /&gt;
bantime = 1w&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le backend utilisé est systemd, exactement comme si vous utilisiez la commande :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Filtre pour PVEPROXY ==&lt;br /&gt;
Il ne nous reste plus qu&#039;à spécifier le filtre &#039;&#039;proxmox&#039;&#039; dans le fichier &#039;&#039;/etc/fail2ban/filter.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=&amp;lt;HOST&amp;gt; user=.* msg=.*&lt;br /&gt;
ignoreregex =&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Tests =&lt;br /&gt;
Il faut maintenant tester le filtre et pour ça on peut utiliser un partage de connexion et réaliser le nombre d&#039;échecs spécifié par la directive &amp;quot;maxretry&amp;quot; (ici 3) :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed:	0&lt;br /&gt;
|  |- Total failed:	3&lt;br /&gt;
|  `- Journal matches:	_SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned:	1&lt;br /&gt;
   |- Total banned:	1&lt;br /&gt;
   `- Banned IP list:	37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On voit bien l&#039;IP 37.167.23.159 qui est bannie !&lt;br /&gt;
N&#039;oubliez pas de l&#039;ajouter à &#039;&#039;ignoreip&#039;&#039; dans le fichier &#039;&#039;jails.local&#039;&#039; ou de faire &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client unban 37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Démarrage et enregistrement dans le chargeur de démarrage =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start fail2ban.service&lt;br /&gt;
# systemctl enable fail2ban.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Vous pouvez maintenant démarrer fail2ban&lt;br /&gt;
&lt;br /&gt;
= Proxification=&lt;br /&gt;
Lorsque votre serveur Proxmox se trouve derrière un reverse-proxy (Apache, Nginx, Traefik, ...), au niveau 3 OSI, l&#039;adresse IP du client est remplacée par celle du proxy et le serveur utilise l&#039;entêtes &#039;&#039;X-Forwarded-For&#039;&#039; ou &#039;&#039;X-Real-IP&#039;&#039; pour transporter l&#039;adresse du client &lt;br /&gt;
[[Fichier:Reverse proxy proxmox.png|700px|centré]]&lt;br /&gt;
Le problème est que la seule adresse que fail2ban va voir apparaître dans les logs est celle du reverse-proxy (&#039;&#039;192.168.4.100&#039;&#039;) :&lt;br /&gt;
[[Fichier:Reverse proxy ip logs.png|600px|centré]]&lt;br /&gt;
Même si le filtre &#039;&#039;fail2ban&#039;&#039; est configuré pour utiliser la commande &#039;&#039;journactl&#039;&#039; sur le démon &#039;&#039;pvedaemon&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
les adresses viennent de pveproxy qui journalise tout dans &#039;&#039;/var/log/pveproxy/access.log&#039;&#039; et &#039;&#039;pvedaemon&#039;&#039; ne journalise que les échecs d&#039;authentification. &lt;br /&gt;
Il est donc plus simple de faire un &#039;&#039;tail&#039;&#039; ou un &#039;&#039;cat&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Que d&#039;utiliser &#039;&#039;journalctl&#039;&#039; pour voir les IPs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
Dec 14 10:43:01 labo unix_chkpwd[1326506]: password check failed for user (root)&lt;br /&gt;
Dec 14 10:43:01 labo IPCC.xs[1320783]: pam_unix(proxmox-ve-auth:auth): authentication failure; logname= uid=0 euid=0 tty= ruser= rhost=37.167.23.159  user=root&lt;br /&gt;
Dec 14 10:43:03 labo pvedaemon[1320783]: authentication failure; rhost=37.167.23.159 user=root@pam msg=Authentication failure&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Configuration de pveproxy ==&lt;br /&gt;
Si on veut voir l&#039;adresse du client, il faut dire au [https://fr.wikipedia.org/wiki/Daemon_(informatique)| démon] &#039;&#039;pveproxy&#039;&#039; d&#039;utiliser l&#039;une des deux entêtes précédentes ainsi que préciser l&#039;adresse du proxy. &lt;br /&gt;
&lt;br /&gt;
Préciser l&#039;adresse du proxy est essentiel pour que &#039;&#039;pveproxy&#039;&#039; n&#039;accepte de lire l&#039;adresse du client présente dans l&#039;entête &#039;&#039;&#039;uniquement&#039;&#039;&#039; si cela provient du proxy, qui est une machine de confiance. Le cas contraire, tout le monde pourrait ajouter une adresse IP dans l&#039;entête pour la faire bannir...&lt;br /&gt;
&lt;br /&gt;
Nous allons créer le fichier &#039;&#039;/etc/default/pveproxy&#039;&#039; avec les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Forwarded-For&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Real-IP&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_ALLOW_FROM=&amp;quot;192.168.4.100&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il faut maintenant redémarrer &#039;&#039;pveproxy&#039;&#039; pour que les changements s&#039;appliquent. Si vous êtes connecté via l&#039;interface web, cela va vous déconnecter, le temps que le démon redémarre, il faudra ensuite certainement rafraîchir la page web.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl restart pveproxy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à vérifier dans les logs si les bonnes adresses s&#039;affichent:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Si jamais ce n&#039;est pas le cas, poursuivez avec la modification du fichier &#039;&#039;AnyEvent.pm&#039;&#039;&lt;br /&gt;
== Modification de AnyEvent.pm ==&lt;br /&gt;
=== Application de la modification ===&lt;br /&gt;
Au jour d&#039;aujourd&#039;hui (13/12/25) la proxification ne fonctionne plus et il faut apporter une modification dans le fichier &#039;&#039;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&#039;&#039; pour que les bonnes adresses apparaissent !&lt;br /&gt;
En fonction des versions cette modification peut avoir lieu soit ligne &#039;&#039;&#039;1504&#039;&#039;&#039;, soit ligne &#039;&#039;&#039;1554&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Il faut repérer la fonction suivante:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
sub authenticate_and_handle_request {&lt;br /&gt;
    my ($self, $reqstate) = @_;&lt;br /&gt;
&lt;br /&gt;
    my $request = $reqstate-&amp;gt;{request};&lt;br /&gt;
    my $method = $request-&amp;gt;method();&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
C&#039;est un peu plus loin qu&#039;il faut insérer le code :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 ### INSERTION ICI ###&lt;br /&gt;
&lt;br /&gt;
    if ($self-&amp;gt;{spiceproxy}) {&lt;br /&gt;
        my $connect_str = $request-&amp;gt;header(&#039;Host&#039;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il faut modifier l&#039;attribut &#039;&#039;peer_host&#039;&#039; de l&#039;objet &#039;&#039;reqstate&#039;&#039; si l&#039;une des deux entêtes est présente :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if ($request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
} elsif ($request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Double IPv4 ou préfixe IPv6 ===&lt;br /&gt;
Après redémarrage, cela permet de voir l&#039;adresse du client dans les logs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/ext-all.js?ver=7.0.0 HTTP/1.1&amp;quot; 200 683505&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/js/u2f-api.js HTTP/1.1&amp;quot; 200 4898&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/resources HTTP/1.1&amp;quot; 200 1226&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/tasks HTTP/1.1&amp;quot; 200 1090&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /proxmoxlib.js?ver=v5.0.4-t1754316706 HTTP/1.1&amp;quot; 200 157086&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/theme-crisp/resources/theme-crisp-all_1.css HTTP/1.1&amp;quot; 200 32919&lt;br /&gt;
::ffff:192.168.20.22 - root@pam [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/nodes/labo/lxc/100/status/current HTTP/1.1&amp;quot; 200 523&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il nous reste un peu de nettoyage à faire, dans certains cas :&lt;br /&gt;
* l&#039;adresse apparaît non pas une fois mais deux, séparées par une virgule&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
37.167.182.207, 37.167.182.207&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* l&#039;adresse IPv4 (32 bits) est affichée dans sa représentation IPv6 (128 bits), avec le préfixe &#039;&#039;::ffff:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
::ffff:192.168.20.22&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On a deux possibilités pour faire le nettoyage :&lt;br /&gt;
*Soit on ajoute les lignes suivantes dans &#039;&#039;AnyEvent.pm&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if (index($reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
   # Remove trailing ip &lt;br /&gt;
   my @fields = split /,/, $reqstate-&amp;gt;{peer_host};&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $fields[0];&lt;br /&gt;
}&lt;br /&gt;
if($reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
   # Remove IPv6 subnet for IPv4&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $1;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*Soit on modifie le filtre /etc/fail2ban/filter.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=.*:?&amp;lt;HOST&amp;gt;,? user=.* msg=.*&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Automatisation ===&lt;br /&gt;
On peut automatiser le processus précédent avec le script suivant, que l&#039;on peut créer dans /root/remoteip_fix.sh :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=bash&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
ANYEVENT_PATH=&amp;quot;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&amp;quot;&lt;br /&gt;
ANYEVENT_REGEX=&#039;$self-&amp;gt;{spiceproxy}&#039;&lt;br /&gt;
TMP_FILE=&amp;quot;/tmp/AnyEvent.pm.tmp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if [ ! -f $ANYEVENT_PATH ]; then&lt;br /&gt;
  echo &amp;quot;$ANYEVENT_PATH does not exists !&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
if [ $(grep &#039;### BUGFIX REMOTE_IP FOR FAIL2BAN ###&#039; $ANYEVENT_PATH | wc -l) -eq 1 ]; then&lt;br /&gt;
  echo &amp;quot;AnyEvent.pm already patched !&amp;quot;&lt;br /&gt;
  exit 0&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
LINE_NUMBER_TOP=$(nl -ba $ANYEVENT_PATH | grep $ANYEVENT_REGEX | head -n 1 | awk -F &#039; &#039; &#039;{print $1}&#039;)&lt;br /&gt;
let LINE_NUMBER_TOP-=1&lt;br /&gt;
&lt;br /&gt;
if [ $LINE_NUMBER_TOP -lt 0 ]; then&lt;br /&gt;
  echo &amp;quot;Did not find the $ANYEVENT_REGEX expr in $ANYEVENT_PATH&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
echo -n &amp;quot;Applying bugfix: &amp;quot;&lt;br /&gt;
trap &amp;quot;rm -f $TMP_FILE&amp;quot; 0 1 2 5 13 15&lt;br /&gt;
head -n $LINE_NUMBER_TOP $ANYEVENT_PATH &amp;gt;$TMP_FILE&lt;br /&gt;
cat &amp;gt;&amp;gt;$TMP_FILE &amp;lt;&amp;lt;EOF&lt;br /&gt;
### BUGFIX REMOTE_IP FOR FAIL2BAN ###&lt;br /&gt;
    if (\$request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
    } elsif (\$request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
    }&lt;br /&gt;
    if (index(\$reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
        my @fields = split /,/, \$reqstate-&amp;gt;{peer_host};&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$fields[0];&lt;br /&gt;
    }&lt;br /&gt;
    if(\$reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
        # Remove IPv6 subnet for IPv4&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$1;&lt;br /&gt;
    }&lt;br /&gt;
#####################################&lt;br /&gt;
EOF&lt;br /&gt;
echo &amp;quot;$ANYEVENT_MODIF&amp;quot; &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cp $ANYEVENT_PATH $ANYEVENT_PATH.ori&lt;br /&gt;
LINE_NUMBER_BOTTOM=$(cat $ANYEVENT_PATH | wc -l)&lt;br /&gt;
let LINE_NUMBER_BOTTOM-=LINE_NUMBER_TOP&lt;br /&gt;
tail -n $LINE_NUMBER_BOTTOM $ANYEVENT_PATH &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cat $TMP_FILE &amp;gt;$ANYEVENT_PATH&lt;br /&gt;
rm -f $TMP_FILE&lt;br /&gt;
trap 0&lt;br /&gt;
echo &amp;quot;done.&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à le rendre exécutable et le lancer :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# chmod +x /root/remoteip_fix.sh&lt;br /&gt;
# /root/remoteip_fix.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne faudra pas oublier de redémarrer &#039;&#039;pveproxy&#039;&#039; pour appliquer les changements !&lt;br /&gt;
&lt;br /&gt;
== Comment bannir derrière un reverse-proxy ? ==&lt;br /&gt;
Maintenant que votre Proxmox est derrière un reverse-proxy, inutile de bannir les IP publiques avec iptables sur le serveur Proxmox, la seule IP visible est celle du reverse-proxy (dans cet exemple 192.168.4.100).&lt;br /&gt;
&lt;br /&gt;
La seule machine capable capable de bannir est le reverse-proxy, il faut donc lui transmettre les IP et nous allons faire ça en trois étapes:&lt;br /&gt;
* la première est de créer une &amp;quot;prison&amp;quot; proxmox sur le fail2ban présent sur le reverse-proxy&lt;br /&gt;
* la deuxième est l&#039;invention d&#039;une API pour fail2ban sur le reverse-proxy&lt;br /&gt;
* la troisième est la modification du comportement de fail2ban pour appeler cette API au lieu de modifier iptables&lt;br /&gt;
&lt;br /&gt;
=== Création d&#039;une prison sur le reverse-proxy ===&lt;br /&gt;
&lt;br /&gt;
Pour bannir nous allons créer une prison spécifique pour le / les serveurs Proxmox que nous allons appeler &#039;&#039;proxmox&#039;&#039; dans le fichier /etc/fail2ban/jail.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[proxmox]&lt;br /&gt;
enabled = true&lt;br /&gt;
port = https,http&lt;br /&gt;
filter = do-nothing&lt;br /&gt;
logpath = /dev/null&lt;br /&gt;
maxretry = 3&lt;br /&gt;
findtime = 1d&lt;br /&gt;
bantime = 1w&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
J&#039;attire votre attention sur les paramètres &#039;&#039;maxretry&#039;&#039;, &#039;&#039;findtime&#039;&#039; et &#039;&#039;bantime&#039;&#039; qui doivent concorder avec ceux du fail2ban de votre Proxmox. S&#039;il sont plus &#039;&#039;court&#039;&#039; sur le reverse-proxy, les IP seront libérées plus tôt à l&#039;inverse, plus long n&#039;est pas gênant, le fail2ban de votre Proxmox les libéreras avant celui du proxy.&lt;br /&gt;
&lt;br /&gt;
Vous avez remarquez le filtre &#039;&#039;do-nothing&#039;&#039; qu&#039;il nous reste à créer dans le fichier &#039;&#039;/etc/fail2ban/filter.d/do-nothing.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
&lt;br /&gt;
failregex = ^&amp;lt;HOST&amp;gt;$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Invention d&#039;une API pour fail2ban ===&lt;br /&gt;
&lt;br /&gt;
Sur le reverse-proxy nous allons installer PHP pour créer un mini serveur qui répondra au urls suivantes:&lt;br /&gt;
* /ban/&amp;lt;ip&amp;gt; pour bannir&lt;br /&gt;
* /unban/&amp;lt;ip&amp;gt; pour lever le banissement&lt;br /&gt;
&lt;br /&gt;
Commençons par installer PHP:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# dnf -y install php-cli&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un répertoire &amp;quot;f2b-api&amp;quot; dans le dossier &amp;quot;opt&amp;quot; :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# mkdir /opt/f2b-api&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis créer un fichier &#039;&#039;f2b-api.php&#039;&#039; dans ce dossier:&lt;br /&gt;
&amp;lt;source lang=php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
main();&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        # On clean l&#039;uri du / de début&lt;br /&gt;
        $uri = ltrim($_SERVER[&#039;REQUEST_URI&#039;], &#039;/&#039;);&lt;br /&gt;
        # On éclate l&#039;uri en parties (action + ip)&lt;br /&gt;
        $parts = explode(&#039;/&#039;, $uri);&lt;br /&gt;
        # Récupération de l&#039;action dans une variable ou false si vide&lt;br /&gt;
        $action = empty($parts[0]) ? false : $parts[0];&lt;br /&gt;
        # Récupération de l&#039;ip dans une variable ou false si vide&lt;br /&gt;
        $ip = empty($parts[1]) ? false : $parts[1];&lt;br /&gt;
        if(!$action || !$ip){&lt;br /&gt;
                # Si action vide =&amp;gt; 400 Bad request&lt;br /&gt;
                http_response_code(400);&lt;br /&gt;
                die();&lt;br /&gt;
        }&lt;br /&gt;
        if(!in_array($action, [&#039;ban&#039;, &#039;unban&#039;])){&lt;br /&gt;
                # Si action pas dans la liste =&amp;gt; 400 Bad request&lt;br /&gt;
                http_response_code(400);&lt;br /&gt;
                die();&lt;br /&gt;
        }&lt;br /&gt;
        $cmd = &#039;&#039;;&lt;br /&gt;
        if($action == &#039;ban&#039;){&lt;br /&gt;
                $cmd = &#039;fail2ban-client set proxmox banip &#039; . $ip;&lt;br /&gt;
        } else if($action == &#039;unban&#039;){&lt;br /&gt;
                $cmd = &#039;fail2ban-client unban proxmox &#039; . $ip;&lt;br /&gt;
        }&lt;br /&gt;
        shell_exec($cmd);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;amp;#9888; Gardez en tête que ce code simpliste n&#039;est en aucun cas sécurisé et ne doit pas être accessible depuis Internet.&lt;br /&gt;
&lt;br /&gt;
Pour démarrer se code en mode serveur il suffit de taper la commande suivante:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# php -S 0.0.0.0:8080 -t /opt/f2b-api /opt/f2b-api/index.php&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous pouvez tester directement depuis un autre terminal en tapant les commandes:&lt;br /&gt;
* pour bannir :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# curl -X GET http://127.0.0.1/ban/@ip&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* pour dé-bannir :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# curl -X GET http://127.0.0.1/unban/@ip&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Et en vérifiant dans fail2ban:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# curl -X GET http://127.0.0.1/unban/@ip&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4406</id>
		<title>Proxmox fail2ban</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4406"/>
		<updated>2026-07-11T15:37:47Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Automatisation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
Proxmox utilise une interface web d&#039;administration qui utilise le port TCP 8006 et c&#039;est un vecteur possible d&#039;attaque par force brut. Nous allons donc &#039;&#039;dresser&#039;&#039; fail2ban pour agir en cas d&#039;attaque !&lt;br /&gt;
&lt;br /&gt;
Proxmox utilise Debian, nous allons principalement reproduire les étapes décrites dans le tutoriel de [[Sécuriser_un_service_avec_Fail2ban| Fail2ban pour Rocky]] et adapter à Debian.&lt;br /&gt;
&lt;br /&gt;
Avant d&#039;aller plus loin, assurez-vous d&#039;avoir correctement installé et configuré [[proxmox_iptables |iptables sur Proxmox]]&lt;br /&gt;
&lt;br /&gt;
= Installation =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt -y install fail2ban&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Configuration =&lt;br /&gt;
Tout d&#039;abord il faut copier le fichier &#039;&#039;/etc/fail2ban/jail.conf&#039;&#039; en &#039;&#039;/etc/fail2ban/jail.local&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dans ce fichier, on va s&#039;intéresser aux variables suivantes:&lt;br /&gt;
*ignoreip : correspond à la suite d&#039;adresses IP qui ne se feront jamais bannir;&lt;br /&gt;
*maxretry : correspond au nombre d&#039;essais;&lt;br /&gt;
*findtime : correspond à la période pendant laquelle les essais vont incrémenter maxretry;&lt;br /&gt;
*bantime  : correspond au temps où l&#039;adresse IP ne peut pas se connecter.&lt;br /&gt;
&lt;br /&gt;
= Configuration de base =&lt;br /&gt;
== Choix de la punition ==&lt;br /&gt;
Il faut choisir quelque chose de cohérent (une punition suffisante) pour ne pas permettre de se faire cracker son mot de passe:&lt;br /&gt;
*maxretry = 3&lt;br /&gt;
*findtime = 86400 (correspond à 1 journée)&lt;br /&gt;
*bantime = 604800 (correspond à 1 semaine)&lt;br /&gt;
&lt;br /&gt;
Cela signifie que si une adresse IP se trompe 3 fois en 1 journée (86400s) elle se fait bannir pendant 1 semaine (604800s).&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul permet de trouver le nombre maximal de tentatives durant une année:&lt;br /&gt;
&lt;br /&gt;
365 jours / 7 jours par semaine * 3 tentatives = 156 essais, ce qui reste raisonnable. &lt;br /&gt;
&lt;br /&gt;
Si le pirate possède un [http://fr.wikipedia.org/wiki/Botnet botnet], il faut bien sûr multiplier ce nombre par le nombre de machines dans le botnet...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Attention : fail2ban parcours les logs de connexion pour connaître le numéro de la tentative, ce qui a pour conséquence, si le &#039;&#039;findtime&#039;&#039; est grand, de prendre un certain temps...&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Jail pour SSH ==&lt;br /&gt;
Il suffit d&#039;ajouter la ligne &#039;&#039;enabled=true&#039;&#039; dans la section à activer !&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[sshd]&lt;br /&gt;
&lt;br /&gt;
# To use more aggressive sshd modes set filter parameter &amp;quot;mode&amp;quot; in jail.local:&lt;br /&gt;
# normal (default), ddos, extra or aggressive (combines all).&lt;br /&gt;
# See &amp;quot;tests/files/logs/sshd&amp;quot; or &amp;quot;filter.d/sshd.conf&amp;quot; for usage example and details.&lt;br /&gt;
#mode   = normal&lt;br /&gt;
enabled = true&lt;br /&gt;
port    = ssh&lt;br /&gt;
logpath = %(sshd_log)s&lt;br /&gt;
backend = %(sshd_backend)s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Configuration spécifique =&lt;br /&gt;
== Jail pour PVEPROXY ==&lt;br /&gt;
Pveproxy écoute sur le port 8006 et ne fonctionne pas exactement comme un serveur [[HTTPD | Apache httpd]] qui mettrait ces logs dans le fichier &#039;&#039;error_log&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Nous allons mettre cette configuration spécifique dans le fichier &#039;&#039;/etc/fail2ban/jail.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[proxmox]&lt;br /&gt;
enabled = true&lt;br /&gt;
port = https,http,8006&lt;br /&gt;
filter = proxmox&lt;br /&gt;
backend = systemd&lt;br /&gt;
maxretry = 5&lt;br /&gt;
findtime = 1d&lt;br /&gt;
bantime = 1w&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le backend utilisé est systemd, exactement comme si vous utilisiez la commande :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Filtre pour PVEPROXY ==&lt;br /&gt;
Il ne nous reste plus qu&#039;à spécifier le filtre &#039;&#039;proxmox&#039;&#039; dans le fichier &#039;&#039;/etc/fail2ban/filter.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=&amp;lt;HOST&amp;gt; user=.* msg=.*&lt;br /&gt;
ignoreregex =&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Tests =&lt;br /&gt;
Il faut maintenant tester le filtre et pour ça on peut utiliser un partage de connexion et réaliser le nombre d&#039;échecs spécifié par la directive &amp;quot;maxretry&amp;quot; (ici 3) :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed:	0&lt;br /&gt;
|  |- Total failed:	3&lt;br /&gt;
|  `- Journal matches:	_SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned:	1&lt;br /&gt;
   |- Total banned:	1&lt;br /&gt;
   `- Banned IP list:	37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On voit bien l&#039;IP 37.167.23.159 qui est bannie !&lt;br /&gt;
N&#039;oubliez pas de l&#039;ajouter à &#039;&#039;ignoreip&#039;&#039; dans le fichier &#039;&#039;jails.local&#039;&#039; ou de faire &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client unban 37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Démarrage et enregistrement dans le chargeur de démarrage =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start fail2ban.service&lt;br /&gt;
# systemctl enable fail2ban.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Vous pouvez maintenant démarrer fail2ban&lt;br /&gt;
&lt;br /&gt;
= Proxification=&lt;br /&gt;
Lorsque votre serveur Proxmox se trouve derrière un reverse-proxy (Apache, Nginx, Traefik, ...), au niveau 3 OSI, l&#039;adresse IP du client est remplacée par celle du proxy et le serveur utilise l&#039;entêtes &#039;&#039;X-Forwarded-For&#039;&#039; ou &#039;&#039;X-Real-IP&#039;&#039; pour transporter l&#039;adresse du client &lt;br /&gt;
[[Fichier:Reverse proxy proxmox.png|700px|centré]]&lt;br /&gt;
Le problème est que la seule adresse que fail2ban va voir apparaître dans les logs est celle du reverse-proxy (&#039;&#039;192.168.4.100&#039;&#039;) :&lt;br /&gt;
[[Fichier:Reverse proxy ip logs.png|600px|centré]]&lt;br /&gt;
Même si le filtre &#039;&#039;fail2ban&#039;&#039; est configuré pour utiliser la commande &#039;&#039;journactl&#039;&#039; sur le démon &#039;&#039;pvedaemon&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
les adresses viennent de pveproxy qui journalise tout dans &#039;&#039;/var/log/pveproxy/access.log&#039;&#039; et &#039;&#039;pvedaemon&#039;&#039; ne journalise que les échecs d&#039;authentification. &lt;br /&gt;
Il est donc plus simple de faire un &#039;&#039;tail&#039;&#039; ou un &#039;&#039;cat&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Que d&#039;utiliser &#039;&#039;journalctl&#039;&#039; pour voir les IPs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
Dec 14 10:43:01 labo unix_chkpwd[1326506]: password check failed for user (root)&lt;br /&gt;
Dec 14 10:43:01 labo IPCC.xs[1320783]: pam_unix(proxmox-ve-auth:auth): authentication failure; logname= uid=0 euid=0 tty= ruser= rhost=37.167.23.159  user=root&lt;br /&gt;
Dec 14 10:43:03 labo pvedaemon[1320783]: authentication failure; rhost=37.167.23.159 user=root@pam msg=Authentication failure&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Configuration de pveproxy ==&lt;br /&gt;
Si on veut voir l&#039;adresse du client, il faut dire au [https://fr.wikipedia.org/wiki/Daemon_(informatique)| démon] &#039;&#039;pveproxy&#039;&#039; d&#039;utiliser l&#039;une des deux entêtes précédentes ainsi que préciser l&#039;adresse du proxy. &lt;br /&gt;
&lt;br /&gt;
Préciser l&#039;adresse du proxy est essentiel pour que &#039;&#039;pveproxy&#039;&#039; n&#039;accepte de lire l&#039;adresse du client présente dans l&#039;entête &#039;&#039;&#039;uniquement&#039;&#039;&#039; si cela provient du proxy, qui est une machine de confiance. Le cas contraire, tout le monde pourrait ajouter une adresse IP dans l&#039;entête pour la faire bannir...&lt;br /&gt;
&lt;br /&gt;
Nous allons créer le fichier &#039;&#039;/etc/default/pveproxy&#039;&#039; avec les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Forwarded-For&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Real-IP&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_ALLOW_FROM=&amp;quot;192.168.4.100&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il faut maintenant redémarrer &#039;&#039;pveproxy&#039;&#039; pour que les changements s&#039;appliquent. Si vous êtes connecté via l&#039;interface web, cela va vous déconnecter, le temps que le démon redémarre, il faudra ensuite certainement rafraîchir la page web.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl restart pveproxy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à vérifier dans les logs si les bonnes adresses s&#039;affichent:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Si jamais ce n&#039;est pas le cas, poursuivez avec la modification du fichier &#039;&#039;AnyEvent.pm&#039;&#039;&lt;br /&gt;
== Modification de AnyEvent.pm ==&lt;br /&gt;
=== Application de la modification ===&lt;br /&gt;
Au jour d&#039;aujourd&#039;hui (13/12/25) la proxification ne fonctionne plus et il faut apporter une modification dans le fichier &#039;&#039;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&#039;&#039; pour que les bonnes adresses apparaissent !&lt;br /&gt;
En fonction des versions cette modification peut avoir lieu soit ligne &#039;&#039;&#039;1504&#039;&#039;&#039;, soit ligne &#039;&#039;&#039;1554&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Il faut repérer la fonction suivante:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
sub authenticate_and_handle_request {&lt;br /&gt;
    my ($self, $reqstate) = @_;&lt;br /&gt;
&lt;br /&gt;
    my $request = $reqstate-&amp;gt;{request};&lt;br /&gt;
    my $method = $request-&amp;gt;method();&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
C&#039;est un peu plus loin qu&#039;il faut insérer le code :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 ### INSERTION ICI ###&lt;br /&gt;
&lt;br /&gt;
    if ($self-&amp;gt;{spiceproxy}) {&lt;br /&gt;
        my $connect_str = $request-&amp;gt;header(&#039;Host&#039;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il faut modifier l&#039;attribut &#039;&#039;peer_host&#039;&#039; de l&#039;objet &#039;&#039;reqstate&#039;&#039; si l&#039;une des deux entêtes est présente :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if ($request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
} elsif ($request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Double IPv4 ou préfixe IPv6 ===&lt;br /&gt;
Après redémarrage, cela permet de voir l&#039;adresse du client dans les logs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/ext-all.js?ver=7.0.0 HTTP/1.1&amp;quot; 200 683505&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/js/u2f-api.js HTTP/1.1&amp;quot; 200 4898&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/resources HTTP/1.1&amp;quot; 200 1226&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/tasks HTTP/1.1&amp;quot; 200 1090&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /proxmoxlib.js?ver=v5.0.4-t1754316706 HTTP/1.1&amp;quot; 200 157086&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/theme-crisp/resources/theme-crisp-all_1.css HTTP/1.1&amp;quot; 200 32919&lt;br /&gt;
::ffff:192.168.20.22 - root@pam [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/nodes/labo/lxc/100/status/current HTTP/1.1&amp;quot; 200 523&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il nous reste un peu de nettoyage à faire, dans certains cas :&lt;br /&gt;
* l&#039;adresse apparaît non pas une fois mais deux, séparées par une virgule&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
37.167.182.207, 37.167.182.207&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* l&#039;adresse IPv4 (32 bits) est affichée dans sa représentation IPv6 (128 bits), avec le préfixe &#039;&#039;::ffff:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
::ffff:192.168.20.22&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On a deux possibilités pour faire le nettoyage :&lt;br /&gt;
*Soit on ajoute les lignes suivantes dans &#039;&#039;AnyEvent.pm&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if (index($reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
   # Remove trailing ip &lt;br /&gt;
   my @fields = split /,/, $reqstate-&amp;gt;{peer_host};&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $fields[0];&lt;br /&gt;
}&lt;br /&gt;
if($reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
   # Remove IPv6 subnet for IPv4&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $1;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*Soit on modifie le filtre /etc/fail2ban/filter.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=.*:?&amp;lt;HOST&amp;gt;,? user=.* msg=.*&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Automatisation ===&lt;br /&gt;
On peut automatiser le processus précédent avec le script suivant, que l&#039;on peut créer dans /root/remoteip_fix.sh :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=bash&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
ANYEVENT_PATH=&amp;quot;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&amp;quot;&lt;br /&gt;
ANYEVENT_REGEX=&#039;$self-&amp;gt;{spiceproxy}&#039;&lt;br /&gt;
TMP_FILE=&amp;quot;/tmp/AnyEvent.pm.tmp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if [ ! -f $ANYEVENT_PATH ]; then&lt;br /&gt;
  echo &amp;quot;$ANYEVENT_PATH does not exists !&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
if [ $(grep &#039;### BUGFIX REMOTE_IP FOR FAIL2BAN ###&#039; $ANYEVENT_PATH | wc -l) -eq 1 ]; then&lt;br /&gt;
  echo &amp;quot;AnyEvent.pm already patched !&amp;quot;&lt;br /&gt;
  exit 0&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
LINE_NUMBER_TOP=$(nl -ba $ANYEVENT_PATH | grep $ANYEVENT_REGEX | head -n 1 | awk -F &#039; &#039; &#039;{print $1}&#039;)&lt;br /&gt;
let LINE_NUMBER_TOP-=1&lt;br /&gt;
&lt;br /&gt;
if [ $LINE_NUMBER_TOP -lt 0 ]; then&lt;br /&gt;
  echo &amp;quot;Did not find the $ANYEVENT_REGEX expr in $ANYEVENT_PATH&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
echo -n &amp;quot;Applying bugfix: &amp;quot;&lt;br /&gt;
trap &amp;quot;rm -f $TMP_FILE&amp;quot; 0 1 2 5 13 15&lt;br /&gt;
head -n $LINE_NUMBER_TOP $ANYEVENT_PATH &amp;gt;$TMP_FILE&lt;br /&gt;
cat &amp;gt;&amp;gt;$TMP_FILE &amp;lt;&amp;lt;EOF&lt;br /&gt;
### BUGFIX REMOTE_IP FOR FAIL2BAN ###&lt;br /&gt;
    if (\$request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
    } elsif (\$request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
    }&lt;br /&gt;
    if (index(\$reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
        my @fields = split /,/, \$reqstate-&amp;gt;{peer_host};&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$fields[0];&lt;br /&gt;
    }&lt;br /&gt;
    if(\$reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
        # Remove IPv6 subnet for IPv4&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$1;&lt;br /&gt;
    }&lt;br /&gt;
#####################################&lt;br /&gt;
EOF&lt;br /&gt;
echo &amp;quot;$ANYEVENT_MODIF&amp;quot; &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cp $ANYEVENT_PATH $ANYEVENT_PATH.ori&lt;br /&gt;
LINE_NUMBER_BOTTOM=$(cat $ANYEVENT_PATH | wc -l)&lt;br /&gt;
let LINE_NUMBER_BOTTOM-=LINE_NUMBER_TOP&lt;br /&gt;
tail -n $LINE_NUMBER_BOTTOM $ANYEVENT_PATH &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cat $TMP_FILE &amp;gt;$ANYEVENT_PATH&lt;br /&gt;
rm -f $TMP_FILE&lt;br /&gt;
trap 0&lt;br /&gt;
echo &amp;quot;done.&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à le rendre exécutable et le lancer :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# chmod +x /root/remoteip_fix.sh&lt;br /&gt;
# /root/remoteip_fix.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne faudra pas oublier de redémarrer &#039;&#039;pveproxy&#039;&#039; pour appliquer les changements !&lt;br /&gt;
&lt;br /&gt;
== Comment bannir ? ==&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Proxmox_first_start&amp;diff=4405</id>
		<title>Proxmox first start</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Proxmox_first_start&amp;diff=4405"/>
		<updated>2026-07-11T15:05:17Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Suppression du message d&amp;#039;abonnement */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
&lt;br /&gt;
Maintenant que votre serveur Proxmox est installé, nous allons effectuer quelques opérations de configuration de bases comme :&lt;br /&gt;
* la modification des dépôts&lt;br /&gt;
* la mise à jour&lt;br /&gt;
* la suppression du message d&#039;abonnement&lt;br /&gt;
* le nommage des cartes réseaux&lt;br /&gt;
* la personnalisation de l&#039;environnement&lt;br /&gt;
&lt;br /&gt;
= Modification des dépôts =&lt;br /&gt;
De base l&#039;équipe de Proxmox vous incite à prendre un abonnement pour profiter des mise à jours et fonctionnalités nécessaires dans un datacenter. &lt;br /&gt;
&lt;br /&gt;
[[Fichier:proxmox subscribe message.jpg|500px|centré]]&lt;br /&gt;
&lt;br /&gt;
Si comme moi, vous utilisez Proxmox dans le cadre d&#039;un homelab, pas besoin de payer, la version &#039;&#039;basic&#039;&#039; est largement suffisante.&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|align=left|&lt;br /&gt;
Cliquez sur l&#039;icône de votre serveur dans la barre à gauche&lt;br /&gt;
|width=10px|&lt;br /&gt;
|align=left|&lt;br /&gt;
Puis sur &#039;&#039;repositories&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox server menu left.jpg|350px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox repositories menu.jpg|150px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
On va dans un premier temps retirez les dépôts &#039;&#039;entreprise&#039;&#039; de Proxmox. Dès que vous voyez &#039;&#039;entreprise&#039;&#039; ou &#039;&#039;pve-entreprise&#039;&#039; dans la colonne &#039;&#039;Components&#039;&#039;, il y a de grande chance que le dépôt nécessite un abonnement.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proxmox repository remove.jpg|900px|centré]]&lt;br /&gt;
&lt;br /&gt;
* cliquez sur le dépôt &#039;&#039;ceph-squid&#039;&#039; puis sur le bouton &#039;&#039;disable&#039;&#039;&lt;br /&gt;
* cliquez sur le dépôt &#039;&#039;ceph-squid&#039;&#039; puis sur le bouton &#039;&#039;disable&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Une grosse croix rouge qui fait peur apparaît&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proxmox repository red corss.jpg|600px|centré]]&lt;br /&gt;
&lt;br /&gt;
Pas de panique, nous allons ajouter le dépôt gratuit pour avoir quand même quelques mise à jours.&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|align=left|&lt;br /&gt;
Cliquez sur &#039;&#039;add&#039;&#039;&lt;br /&gt;
|width=10px|&lt;br /&gt;
|align=left|&lt;br /&gt;
Puis sur &#039;&#039;No-Subscription&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox repository add.jpg|250px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox repositories no-subscription.jpg|500px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Ouf, la méchante croix rouge à disparue :)&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proxmox repositories no-subscription warning.jpg|500px|centré]]&lt;br /&gt;
&lt;br /&gt;
= Mise à jour =&lt;br /&gt;
&lt;br /&gt;
Pour rappel, le serveur que nous allons mettre à jour vient d&#039;être installé, et n&#039;est donc pas encore en utilisation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=color:red&amp;gt;Si vous avez des serveur en production, qui sont utilisés par des clients ou dans le cadre de processus internes à votre entreprise, s&#039;il vous plaît, ne mettez jamais, JAMAIS, jamais à jour ces serveurs.&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous n&#039;avez aucune idée des impacts sur les versions des logiciels et vous risquez, en mettant à jour, de créer une incompatibilité et de faire tomber en panne des logiciels ou applications qui fonctionnaient parfaitement.&lt;br /&gt;
&lt;br /&gt;
Les seules mise à jour que l&#039;on s&#039;autorise en production sont celles de sécurité qui servent à &#039;&#039;patcher&#039;&#039; une vulnérabilité. Et là encore, assurez-vous bien que rien ne va &#039;&#039;exploser&#039;&#039;. Si c&#039;est une machine virtuelle ou un conteneur, faites un snapshot ou une copie avant de procéder à la modification... surtout si c&#039;est un vendredi à 17h 😢&lt;br /&gt;
&lt;br /&gt;
Bon, vous êtes prévenu !&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|align=left|&lt;br /&gt;
Remontez d&#039;un cran sur le bouton &#039;&#039;Updates&#039;&#039;&lt;br /&gt;
|width=10px|&lt;br /&gt;
|align=left|&lt;br /&gt;
Puis cliquez sur &#039;&#039;Refresh&#039;&#039; pour mettre à jour la liste des paquetages disponibles&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox update button.jpg|150px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox update refresh.jpg|100px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|align=left|&lt;br /&gt;
Quand vous êtes prêt, cliquez sur &#039;&#039;Upgrade&#039;&#039;&lt;br /&gt;
|width=10px|&lt;br /&gt;
|align=left|&lt;br /&gt;
une fenêtre et démarrer le processus de mise à jour&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox upgrade button.jpg|150px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox update upgrade.jpg|600px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Suppression du message d&#039;abonnement =&lt;br /&gt;
Maintenant que les dépôt sont configuré et les mises à jour faites, on va désactiver ce message qui apparaît à chaque connexion au portail web de Proxmox.&lt;br /&gt;
[[Fichier:proxmox subscribe message.jpg|500px|centré]]&lt;br /&gt;
&lt;br /&gt;
Pour cela nous allons utiliser l&#039;activateur de &#039;&#039;Jamesits&#039;&#039; disponible sur son [https://github.com/Jamesits/pve-fake-subscription GitHub]&lt;br /&gt;
&lt;br /&gt;
Dans le menu de gauche, cliquez sur l’icône de votre serveur puis sur Shell&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox server menu left.jpg|350px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
&amp;amp;rarr;&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox shell button.jpg|200px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Une fois dans le terminal nous allons utiliser la commande &#039;&#039;wget&#039;&#039; pour télécharger le paquetage sur la machine:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# wget https://github.com/Jamesits/pve-fake-subscription/releases/download/v0.0.11/pve-fake-subscription_0.0.11+git-1_all.deb&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le lien précédent est à récupérer sur la page de téléchargement du projet, assurer-vous d&#039;y faire un tour pour vous assurer qu&#039;il est toujours bon.&lt;br /&gt;
&lt;br /&gt;
Il ne reste plus qu&#039;a l&#039;installer :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# dpkg -i pve-fake-subscription_0.0.11+git-1_all.deb&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il est recommandé de bloquer le site de vérification des clés en mettant une entrée factice dans le fichier &#039;&#039;hosts&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# echo &amp;quot;127.0.0.1 shop.maurer-it.com&amp;quot; &amp;gt;&amp;gt; /etc/hosts&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous pouvez vérifier que cela fonctionne en faisant un ping:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
root@pve-tuto:~# ping shop.maurer-it.com&lt;br /&gt;
PING shop.maurer-it.com (127.0.0.1) 56(84) bytes of data.&lt;br /&gt;
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=1 ttl=64 time=0.014 ms&lt;br /&gt;
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=2 ttl=64 time=0.010 ms&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier que le message à bien disparu, il vous suffit de vous déconnecter puis reconnecter !&lt;br /&gt;
&lt;br /&gt;
= Nommage des cartes réseaux =&lt;br /&gt;
&lt;br /&gt;
Lorsque vous ajoutez / retirez une carte sur un port PCI, les identifiants sont redistribués et cela va affecter le nom des cartes réseaux. Si la carte que vous utilisez pour vous connecter à votre serveur Proxmox (généralement sur le &#039;&#039;vmbr0&#039;&#039;) change de nom, vous perdez la connexion à votre serveur... Pas très pratique !&lt;br /&gt;
&lt;br /&gt;
Si vous avez une version supérieur à 9.2 et que vous avez suivie le tutoriel pour [[Proxmox_install | installer Proxmox]] vous avez déjà fixé le nom de votre carte de management, mais qu&#039;en est-il des autres ? Vous l&#039;aurez compris, il faut absolument fixer le noms des cartes pour éviter les surprises !&lt;br /&gt;
&lt;br /&gt;
Une fois vos [[Identify_your_nic | carte identifiées]], il ne vous reste plus qu&#039;à définir leur nom et pour cela je vous conseil d&#039;utiliser leur rôle:&lt;br /&gt;
* une carte connectée à une DMZ &amp;amp;rarr; dmz&lt;br /&gt;
* une carte connectée à un LAN &amp;amp;rarr; lan&lt;br /&gt;
* une carte connectée à une box &amp;amp;rarr; wan&lt;br /&gt;
&lt;br /&gt;
Si vous avez plusieurs cartes par rôle, utilisez des numéros: &#039;&#039;dmz0&#039;&#039;, &#039;&#039;dmz1&#039;&#039;, ...&lt;br /&gt;
&lt;br /&gt;
Pour fixer le nom on va suivre [[Ifcfg-ethX#Que_faire_si_ma_carte_n&#039;a_pas_le_bon_numéro_?? | le tutoriel sur udev]] et d&#039;abord identifier l&#039;adresse MAC de notre carte:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ip a&lt;br /&gt;
1: lo: &amp;lt;LOOPBACK,UP,LOWER_UP&amp;gt; mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000&lt;br /&gt;
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00&lt;br /&gt;
    inet 127.0.0.1/8 scope host lo&lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
    inet6 ::1/128 scope host noprefixroute &lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
2: enp0s0f0: &amp;lt;BROADCAST,MULTICAST&amp;gt; mtu 1500 qdisc noop state DOWN group default qlen 1000&lt;br /&gt;
    link/ether 24:12:4d:01:49:20 brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
3: enp0s0f1: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc mq master vmbr0 state UP group default qlen 1000&lt;br /&gt;
    link/ether 24:12:4d:01:49:21 brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
    altname enp3s0&lt;br /&gt;
4: vmbr0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc noqueue state UP group default qlen 1000&lt;br /&gt;
    link/ether 24:8a:07:f7:ce:9b brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
    inet 192.168.4.240/24 scope global vmbr0&lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
    inet6 fe80::268a:7ff:fef7:ce9b/64 scope link &lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On a donc:&lt;br /&gt;
* enp0s0f1 en management avec l&#039;adresse 24:12:4d:01:49:21&lt;br /&gt;
* enp0s0f1 connecté à une DMZ avec l&#039;adresse 24:12:4d:01:49:20&lt;br /&gt;
&lt;br /&gt;
Il ne nous reste plus qu&#039;a créez le fichier &#039;&#039;/etc/udev/rules.d/70-persistent-net.rules&#039;&#039; avec le contenu suivant:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# Carte Intel SFP+ management &lt;br /&gt;
SUBSYSTEM==&amp;quot;net&amp;quot;, ACTION==&amp;quot;add&amp;quot;, DRIVERS==&amp;quot;?*&amp;quot;, ATTR{address}==&amp;quot;24:12:4d:01:49:21&amp;quot;, ATTR{type}==&amp;quot;1&amp;quot;, KERNEL==&amp;quot;eth*&amp;quot;, NAME=&amp;quot;mgmt&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Carte Intel SFP+ DMZ&lt;br /&gt;
SUBSYSTEM==&amp;quot;net&amp;quot;, ACTION==&amp;quot;add&amp;quot;, DRIVERS==&amp;quot;?*&amp;quot;, ATTR{address}==&amp;quot;24:12:4d:01:49:21&amp;quot;, ATTR{type}==&amp;quot;1&amp;quot;, KERNEL==&amp;quot;eth*&amp;quot;, NAME=&amp;quot;dmz&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Si vous êtes à distance, n&#039;oubliez pas de modifier votre fichier &#039;&#039;/etc/network/interfaces&#039;&#039; avant de redémarrer:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
iface mgmt inet manual&lt;br /&gt;
iface dmz inet manual&lt;br /&gt;
&lt;br /&gt;
auto vmbr0&lt;br /&gt;
iface vmbr0 inet static&lt;br /&gt;
	address 192.168.1.1/24&lt;br /&gt;
	gateway 192.168.1.254&lt;br /&gt;
	bridge-ports mgmt&lt;br /&gt;
	bridge-stp off&lt;br /&gt;
	bridge-fd 0&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Personnalisation de l&#039;environnement =&lt;br /&gt;
&lt;br /&gt;
Comme Proxmox est fait sur une base de Debian, certaine commandes disponible sur Rocky risque de vous manquer !&lt;br /&gt;
&lt;br /&gt;
J&#039;aime bien faire un tour dans le fichier &#039;&#039;/root/.bashrc&#039;&#039; pour y ajouter à la fin les lignes suivantes:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
alias ll=&#039;ls -l&#039;&lt;br /&gt;
alias vi=vim.tiny&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Une fois vos modifications terminées, il ne vous reste plus qu&#039;a recharger le fichier &#039;&#039;.bashrc&#039;&#039;:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
#. .bashrc&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4404</id>
		<title>Proxmox fail2ban</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4404"/>
		<updated>2026-07-11T15:02:04Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Jail pour PVEPROXY */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
Proxmox utilise une interface web d&#039;administration qui utilise le port TCP 8006 et c&#039;est un vecteur possible d&#039;attaque par force brut. Nous allons donc &#039;&#039;dresser&#039;&#039; fail2ban pour agir en cas d&#039;attaque !&lt;br /&gt;
&lt;br /&gt;
Proxmox utilise Debian, nous allons principalement reproduire les étapes décrites dans le tutoriel de [[Sécuriser_un_service_avec_Fail2ban| Fail2ban pour Rocky]] et adapter à Debian.&lt;br /&gt;
&lt;br /&gt;
Avant d&#039;aller plus loin, assurez-vous d&#039;avoir correctement installé et configuré [[proxmox_iptables |iptables sur Proxmox]]&lt;br /&gt;
&lt;br /&gt;
= Installation =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt -y install fail2ban&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Configuration =&lt;br /&gt;
Tout d&#039;abord il faut copier le fichier &#039;&#039;/etc/fail2ban/jail.conf&#039;&#039; en &#039;&#039;/etc/fail2ban/jail.local&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dans ce fichier, on va s&#039;intéresser aux variables suivantes:&lt;br /&gt;
*ignoreip : correspond à la suite d&#039;adresses IP qui ne se feront jamais bannir;&lt;br /&gt;
*maxretry : correspond au nombre d&#039;essais;&lt;br /&gt;
*findtime : correspond à la période pendant laquelle les essais vont incrémenter maxretry;&lt;br /&gt;
*bantime  : correspond au temps où l&#039;adresse IP ne peut pas se connecter.&lt;br /&gt;
&lt;br /&gt;
= Configuration de base =&lt;br /&gt;
== Choix de la punition ==&lt;br /&gt;
Il faut choisir quelque chose de cohérent (une punition suffisante) pour ne pas permettre de se faire cracker son mot de passe:&lt;br /&gt;
*maxretry = 3&lt;br /&gt;
*findtime = 86400 (correspond à 1 journée)&lt;br /&gt;
*bantime = 604800 (correspond à 1 semaine)&lt;br /&gt;
&lt;br /&gt;
Cela signifie que si une adresse IP se trompe 3 fois en 1 journée (86400s) elle se fait bannir pendant 1 semaine (604800s).&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul permet de trouver le nombre maximal de tentatives durant une année:&lt;br /&gt;
&lt;br /&gt;
365 jours / 7 jours par semaine * 3 tentatives = 156 essais, ce qui reste raisonnable. &lt;br /&gt;
&lt;br /&gt;
Si le pirate possède un [http://fr.wikipedia.org/wiki/Botnet botnet], il faut bien sûr multiplier ce nombre par le nombre de machines dans le botnet...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Attention : fail2ban parcours les logs de connexion pour connaître le numéro de la tentative, ce qui a pour conséquence, si le &#039;&#039;findtime&#039;&#039; est grand, de prendre un certain temps...&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Jail pour SSH ==&lt;br /&gt;
Il suffit d&#039;ajouter la ligne &#039;&#039;enabled=true&#039;&#039; dans la section à activer !&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[sshd]&lt;br /&gt;
&lt;br /&gt;
# To use more aggressive sshd modes set filter parameter &amp;quot;mode&amp;quot; in jail.local:&lt;br /&gt;
# normal (default), ddos, extra or aggressive (combines all).&lt;br /&gt;
# See &amp;quot;tests/files/logs/sshd&amp;quot; or &amp;quot;filter.d/sshd.conf&amp;quot; for usage example and details.&lt;br /&gt;
#mode   = normal&lt;br /&gt;
enabled = true&lt;br /&gt;
port    = ssh&lt;br /&gt;
logpath = %(sshd_log)s&lt;br /&gt;
backend = %(sshd_backend)s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Configuration spécifique =&lt;br /&gt;
== Jail pour PVEPROXY ==&lt;br /&gt;
Pveproxy écoute sur le port 8006 et ne fonctionne pas exactement comme un serveur [[HTTPD | Apache httpd]] qui mettrait ces logs dans le fichier &#039;&#039;error_log&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Nous allons mettre cette configuration spécifique dans le fichier &#039;&#039;/etc/fail2ban/jail.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[proxmox]&lt;br /&gt;
enabled = true&lt;br /&gt;
port = https,http,8006&lt;br /&gt;
filter = proxmox&lt;br /&gt;
backend = systemd&lt;br /&gt;
maxretry = 5&lt;br /&gt;
findtime = 1d&lt;br /&gt;
bantime = 1w&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le backend utilisé est systemd, exactement comme si vous utilisiez la commande :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Filtre pour PVEPROXY ==&lt;br /&gt;
Il ne nous reste plus qu&#039;à spécifier le filtre &#039;&#039;proxmox&#039;&#039; dans le fichier &#039;&#039;/etc/fail2ban/filter.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=&amp;lt;HOST&amp;gt; user=.* msg=.*&lt;br /&gt;
ignoreregex =&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Tests =&lt;br /&gt;
Il faut maintenant tester le filtre et pour ça on peut utiliser un partage de connexion et réaliser le nombre d&#039;échecs spécifié par la directive &amp;quot;maxretry&amp;quot; (ici 3) :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed:	0&lt;br /&gt;
|  |- Total failed:	3&lt;br /&gt;
|  `- Journal matches:	_SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned:	1&lt;br /&gt;
   |- Total banned:	1&lt;br /&gt;
   `- Banned IP list:	37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On voit bien l&#039;IP 37.167.23.159 qui est bannie !&lt;br /&gt;
N&#039;oubliez pas de l&#039;ajouter à &#039;&#039;ignoreip&#039;&#039; dans le fichier &#039;&#039;jails.local&#039;&#039; ou de faire &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client unban 37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Démarrage et enregistrement dans le chargeur de démarrage =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start fail2ban.service&lt;br /&gt;
# systemctl enable fail2ban.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Vous pouvez maintenant démarrer fail2ban&lt;br /&gt;
&lt;br /&gt;
= Proxification=&lt;br /&gt;
Lorsque votre serveur Proxmox se trouve derrière un reverse-proxy (Apache, Nginx, Traefik, ...), au niveau 3 OSI, l&#039;adresse IP du client est remplacée par celle du proxy et le serveur utilise l&#039;entêtes &#039;&#039;X-Forwarded-For&#039;&#039; ou &#039;&#039;X-Real-IP&#039;&#039; pour transporter l&#039;adresse du client &lt;br /&gt;
[[Fichier:Reverse proxy proxmox.png|700px|centré]]&lt;br /&gt;
Le problème est que la seule adresse que fail2ban va voir apparaître dans les logs est celle du reverse-proxy (&#039;&#039;192.168.4.100&#039;&#039;) :&lt;br /&gt;
[[Fichier:Reverse proxy ip logs.png|600px|centré]]&lt;br /&gt;
Même si le filtre &#039;&#039;fail2ban&#039;&#039; est configuré pour utiliser la commande &#039;&#039;journactl&#039;&#039; sur le démon &#039;&#039;pvedaemon&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
les adresses viennent de pveproxy qui journalise tout dans &#039;&#039;/var/log/pveproxy/access.log&#039;&#039; et &#039;&#039;pvedaemon&#039;&#039; ne journalise que les échecs d&#039;authentification. &lt;br /&gt;
Il est donc plus simple de faire un &#039;&#039;tail&#039;&#039; ou un &#039;&#039;cat&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Que d&#039;utiliser &#039;&#039;journalctl&#039;&#039; pour voir les IPs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
Dec 14 10:43:01 labo unix_chkpwd[1326506]: password check failed for user (root)&lt;br /&gt;
Dec 14 10:43:01 labo IPCC.xs[1320783]: pam_unix(proxmox-ve-auth:auth): authentication failure; logname= uid=0 euid=0 tty= ruser= rhost=37.167.23.159  user=root&lt;br /&gt;
Dec 14 10:43:03 labo pvedaemon[1320783]: authentication failure; rhost=37.167.23.159 user=root@pam msg=Authentication failure&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Configuration de pveproxy ==&lt;br /&gt;
Si on veut voir l&#039;adresse du client, il faut dire au [https://fr.wikipedia.org/wiki/Daemon_(informatique)| démon] &#039;&#039;pveproxy&#039;&#039; d&#039;utiliser l&#039;une des deux entêtes précédentes ainsi que préciser l&#039;adresse du proxy. &lt;br /&gt;
&lt;br /&gt;
Préciser l&#039;adresse du proxy est essentiel pour que &#039;&#039;pveproxy&#039;&#039; n&#039;accepte de lire l&#039;adresse du client présente dans l&#039;entête &#039;&#039;&#039;uniquement&#039;&#039;&#039; si cela provient du proxy, qui est une machine de confiance. Le cas contraire, tout le monde pourrait ajouter une adresse IP dans l&#039;entête pour la faire bannir...&lt;br /&gt;
&lt;br /&gt;
Nous allons créer le fichier &#039;&#039;/etc/default/pveproxy&#039;&#039; avec les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Forwarded-For&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Real-IP&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_ALLOW_FROM=&amp;quot;192.168.4.100&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il faut maintenant redémarrer &#039;&#039;pveproxy&#039;&#039; pour que les changements s&#039;appliquent. Si vous êtes connecté via l&#039;interface web, cela va vous déconnecter, le temps que le démon redémarre, il faudra ensuite certainement rafraîchir la page web.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl restart pveproxy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à vérifier dans les logs si les bonnes adresses s&#039;affichent:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Si jamais ce n&#039;est pas le cas, poursuivez avec la modification du fichier &#039;&#039;AnyEvent.pm&#039;&#039;&lt;br /&gt;
== Modification de AnyEvent.pm ==&lt;br /&gt;
=== Application de la modification ===&lt;br /&gt;
Au jour d&#039;aujourd&#039;hui (13/12/25) la proxification ne fonctionne plus et il faut apporter une modification dans le fichier &#039;&#039;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&#039;&#039; pour que les bonnes adresses apparaissent !&lt;br /&gt;
En fonction des versions cette modification peut avoir lieu soit ligne &#039;&#039;&#039;1504&#039;&#039;&#039;, soit ligne &#039;&#039;&#039;1554&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Il faut repérer la fonction suivante:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
sub authenticate_and_handle_request {&lt;br /&gt;
    my ($self, $reqstate) = @_;&lt;br /&gt;
&lt;br /&gt;
    my $request = $reqstate-&amp;gt;{request};&lt;br /&gt;
    my $method = $request-&amp;gt;method();&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
C&#039;est un peu plus loin qu&#039;il faut insérer le code :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 ### INSERTION ICI ###&lt;br /&gt;
&lt;br /&gt;
    if ($self-&amp;gt;{spiceproxy}) {&lt;br /&gt;
        my $connect_str = $request-&amp;gt;header(&#039;Host&#039;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il faut modifier l&#039;attribut &#039;&#039;peer_host&#039;&#039; de l&#039;objet &#039;&#039;reqstate&#039;&#039; si l&#039;une des deux entêtes est présente :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if ($request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
} elsif ($request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Double IPv4 ou préfixe IPv6 ===&lt;br /&gt;
Après redémarrage, cela permet de voir l&#039;adresse du client dans les logs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/ext-all.js?ver=7.0.0 HTTP/1.1&amp;quot; 200 683505&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/js/u2f-api.js HTTP/1.1&amp;quot; 200 4898&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/resources HTTP/1.1&amp;quot; 200 1226&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/tasks HTTP/1.1&amp;quot; 200 1090&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /proxmoxlib.js?ver=v5.0.4-t1754316706 HTTP/1.1&amp;quot; 200 157086&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/theme-crisp/resources/theme-crisp-all_1.css HTTP/1.1&amp;quot; 200 32919&lt;br /&gt;
::ffff:192.168.20.22 - root@pam [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/nodes/labo/lxc/100/status/current HTTP/1.1&amp;quot; 200 523&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il nous reste un peu de nettoyage à faire, dans certains cas :&lt;br /&gt;
* l&#039;adresse apparaît non pas une fois mais deux, séparées par une virgule&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
37.167.182.207, 37.167.182.207&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* l&#039;adresse IPv4 (32 bits) est affichée dans sa représentation IPv6 (128 bits), avec le préfixe &#039;&#039;::ffff:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
::ffff:192.168.20.22&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On a deux possibilités pour faire le nettoyage :&lt;br /&gt;
*Soit on ajoute les lignes suivantes dans &#039;&#039;AnyEvent.pm&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if (index($reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
   # Remove trailing ip &lt;br /&gt;
   my @fields = split /,/, $reqstate-&amp;gt;{peer_host};&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $fields[0];&lt;br /&gt;
}&lt;br /&gt;
if($reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
   # Remove IPv6 subnet for IPv4&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $1;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*Soit on modifie le filtre /etc/fail2ban/filter.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=.*:?&amp;lt;HOST&amp;gt;,? user=.* msg=.*&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Automatisation ===&lt;br /&gt;
On peut automatiser le processus précédent avec le script suivant, que l&#039;on peut créer dans /root/remoteip_fix.sh :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=bash&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
ANYEVENT_PATH=&amp;quot;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&amp;quot;&lt;br /&gt;
ANYEVENT_REGEX=&#039;$self-&amp;gt;{spiceproxy}&#039;&lt;br /&gt;
TMP_FILE=&amp;quot;/tmp/AnyEvent.pm.tmp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if [ ! -f $ANYEVENT_PATH ]; then&lt;br /&gt;
  echo &amp;quot;$ANYEVENT_PATH does not exists !&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
if [ $(grep &#039;### BUGFIX REMOTE_IP FOR FAIL2BAN ###&#039; $ANYEVENT_PATH | wc -l) -eq 1 ]; then&lt;br /&gt;
  echo &amp;quot;AnyEvent.pm already patched !&amp;quot;&lt;br /&gt;
  exit 0&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
LINE_NUMBER_TOP=$(nl -ba $ANYEVENT_PATH | grep $ANYEVENT_REGEX | head -n 1 | awk -F &#039; &#039; &#039;{print $1}&#039;)&lt;br /&gt;
let LINE_NUMBER_TOP-=1&lt;br /&gt;
&lt;br /&gt;
if [ $LINE_NUMBER_TOP -lt 0 ]; then&lt;br /&gt;
  echo &amp;quot;Did not find the $ANYEVENT_REGEX expr in $ANYEVENT_PATH&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
echo -n &amp;quot;Applying bugfix: &amp;quot;&lt;br /&gt;
trap &amp;quot;rm -f $TMP_FILE&amp;quot; 0 1 2 5 13 15&lt;br /&gt;
head -n $LINE_NUMBER_TOP $ANYEVENT_PATH &amp;gt;$TMP_FILE&lt;br /&gt;
cat &amp;gt;&amp;gt;$TMP_FILE &amp;lt;&amp;lt;EOF&lt;br /&gt;
### BUGFIX REMOTE_IP FOR FAIL2BAN ###&lt;br /&gt;
    if (\$request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
    } elsif (\$request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
    }&lt;br /&gt;
    if (index(\$reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
        my @fields = split /,/, \$reqstate-&amp;gt;{peer_host};&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$fields[0];&lt;br /&gt;
    }&lt;br /&gt;
    if(\$reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
        # Remove IPv6 subnet for IPv4&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$1;&lt;br /&gt;
    }&lt;br /&gt;
#####################################&lt;br /&gt;
EOF&lt;br /&gt;
echo &amp;quot;$ANYEVENT_MODIF&amp;quot; &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cp $ANYEVENT_PATH $ANYEVENT_PATH.ori&lt;br /&gt;
LINE_NUMBER_BOTTOM=$(cat $ANYEVENT_PATH | wc -l)&lt;br /&gt;
let LINE_NUMBER_BOTTOM-=LINE_NUMBER_TOP&lt;br /&gt;
tail -n $LINE_NUMBER_BOTTOM $ANYEVENT_PATH &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cat $TMP_FILE &amp;gt;$ANYEVENT_PATH&lt;br /&gt;
rm -f $TMP_FILE&lt;br /&gt;
trap 0&lt;br /&gt;
echo &amp;quot;done.&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à le rendre exécutable et le lancer :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# chmod +x /root/remoteip_fix.sh&lt;br /&gt;
# /root/remoteip_fix.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne faudra pas oublier de redémarrer &#039;&#039;pveproxy&#039;&#039; pour appliquer les changements !&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=The_Linux_Craftsman&amp;diff=4403</id>
		<title>The Linux Craftsman</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=The_Linux_Craftsman&amp;diff=4403"/>
		<updated>2026-07-07T12:25:31Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* La pratique */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Ce wiki =&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
! Le contenu !! Public visé !! L&#039;auteur&lt;br /&gt;
|-valign=top&lt;br /&gt;
|width=&amp;quot;33%&amp;quot;|&lt;br /&gt;
Ce wiki propose des articles, cours, TPs et TDs sur des sujets gravitant autour des technologies du système d&#039;information, notamment sur le système Linux, sur la distribution CentOS et maintenant Rocky Linux.&lt;br /&gt;
&lt;br /&gt;
Vous y trouverez des articles traitant de la mise en place de services réseaux tels que DHCP et DNS mais également des articles sur la mise en place de pare-feu, site Web, etc... Il y a un peu de tout et je vous encourage à utiliser le champ de recherche pour trouver ce dont vous avez besoin.&lt;br /&gt;
|width=&amp;quot;33%&amp;quot;|&lt;br /&gt;
&lt;br /&gt;
Ce wiki s&#039;adresse principalement à mes élèves mais il peut également servir à des enseignants qui désirent monter leurs cours sans se &amp;quot;prendre la tête&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Tout est disponible sous [http://www.gnu.org/copyleft/fdl.html licence GNU Free Documentation License 1.3] ou ultérieure et vous pouvez récupérer les contenus et en faire ce que vous voulez !&lt;br /&gt;
|width=&amp;quot;33%&amp;quot;|&lt;br /&gt;
&lt;br /&gt;
Je m&#039;appelle Jean-Christophe FORTON et je suis professeur d&#039;informatique depuis 2011 mais cela n&#039;a pas toujours été mon métier, plus d&#039;info [[jcf|ici]]...&lt;br /&gt;
&lt;br /&gt;
N&#039;hésitez pas à faire un tour sur :&lt;br /&gt;
{|&lt;br /&gt;
|-valign=middle&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Image:Logo-YouTube-rouge.png|30px|link=https://www.youtube.com/@tala-informatique]]&lt;br /&gt;
|| ma chaîne Youtube pour découvrir mes aventures ou (re)visionner certains cours&lt;br /&gt;
|-valign=middle&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:Logo-Tipeee.png|27px|link=https://fr.tipeee.com/tala-informatique]]&lt;br /&gt;
||mon Tipeee pour me remercier&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Les cours =&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
! Système  !! Sécurité !! Réseaux !! Développement !! Général&lt;br /&gt;
|-valign=top&lt;br /&gt;
|width=&amp;quot;20%&amp;quot;|&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Architecture des ordinateurs&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[:Media:materiel.pdf|Le matériel]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Media:system_exploitation.pdf|Le système d&#039;exploitation]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Media:gestion_disques.pdf|La gestion des disques]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Media:sauvegarde.pdf|La sauvegarde]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Linux&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[:Media:intro_linux.pdf|Introduction au système Linux]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Media:tp_linux_commandes_de_bases.pdf|TP Linux : commandes de bases]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Active Directory&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[:Media:ad_intro.pdf|Les principes fondamentaux]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Media:ad_gpo.pdf|Gestion des stratégies]]&lt;br /&gt;
|width=&amp;quot;20%&amp;quot;|&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Réseaux&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[:Media:Les pare-feux.pdf|Les pare-feux]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Media:Les pare-feux_tech.pdf|Les pare-feux (fiche technique)]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Media:Les VPN.pdf|Les VPN]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Media:Haute_dispo.pdf|Haute disponibilité]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Media:sauvegarde_pca.pdf|La sauvegarde]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Sécurité des Systèmes d’Information&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[:Media:principes_SSI.pdf|Les principes fondamentaux]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Media:implémentation_concrete_SSI.pdf|Implémentation concrète de la sécurité]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Media:cryptographie.pdf|Cryptographie]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Media:TD1_SSI.pdf|TD1: Principes Fondamentaux]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Media:TP1_SSI.pdf|TP1: Écoute d&#039;une connexion]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Media:TP2_SSI.pdf|TP2: Chiffrement asymétrique avec PGP]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Web&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[:Media:apache server.pdf|Le serveur Apache]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Media:pilotage web bdd.pdf|Pilotage d&#039;une page web]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Media:web app security.pdf|Sécurité des applications Web]]&lt;br /&gt;
|width=&amp;quot;20%&amp;quot;|&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Modèle OSI&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
*[[:Media:OSI.pdf|Le modèle OSI en version cours]]&lt;br /&gt;
*[[:Media:OSI_Slides.pdf|Le modèle OSI en version slides]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;OSI 1 &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[:Media:Normes_cablages.pdf|Les normes de câblage]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;OSI 2&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[:Media:Ethernet-802.3.pdf|La norme Ethernet (802.3)]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Media:WiFi-802.11.pdf|La norme Wi-Fi (802.11)]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Media:Bridge.pdf|Les bridges]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Media:STP.pdf|Spanning Tree Protocol]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Media:VLAN.pdf|Les Vlans]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Routage&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[:Media:CIDR.pdf|Classless Inter-Domain Routing]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Media:resume_protocoles_vecteur_distance.pdf|Résumé sur les protocoles à vecteur de distance]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Media:EIGRP.pdf|Enhanced Interior Gateway Routing Protocol]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Media:OSPF.pdf|Open Shortest Path First]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Media:BGP.pdf|Border Gateway Protocol]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Services&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[:Media:DHCP.pdf|DHCP]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Media:DNS.pdf|DNS]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Media:SAMBA.pdf|Samba]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Qualité de service&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[:Media:QoS.pdf|La QoS]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Media:Iproute2_QoS.pdf|Iproute2 et la QoS]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Protocole&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[:Media:HTTP.pdf|HTTP]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Media:SNMP.pdf|SNMP]]&lt;br /&gt;
|width=&amp;quot;20%&amp;quot;|&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;L&#039;algorithmique&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[:Media:algo_intro.pdf|Introduction]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Media:algo_langage.pdf|Le Langage]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;SQL&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt; &lt;br /&gt;
[[:Media:conception_bdd.pdf|Conception de base de données]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Media:conception_bdd_simple.pdf|Conception de base de données (simplifié)]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Media:langage_de_requête.pdf|Langage de requête]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Langages du Web&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt; &lt;br /&gt;
[[:Media:HTML xHTML intro.pdf|Le langage HTML]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Media:css.pdf|Le langage CSS]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Media:javascript.pdf|Le langage JavaScript]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Media:php.pdf|Le langage PHP]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Langage bas niveau&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt; &lt;br /&gt;
[[:Media:C lang.pdf|Le langage C]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Architecture SOA&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt; &lt;br /&gt;
[[:Media:webservices.pdf|Les Web Services RESTful]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Informatique embarquée&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt; &lt;br /&gt;
[[:Media:arduino_avr.pdf|Arduino et AVR]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Media:IOT.pdf|L&#039;Internet des objets]]&lt;br /&gt;
|width=&amp;quot;20%&amp;quot;|&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Gestion&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt; &lt;br /&gt;
[[:Media:gestion_projet.pdf|Gestion de projet]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Bureautique&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt; &lt;br /&gt;
[[:Media:powerpoint.pdf|PowerPoint]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Media:excel.pdf|Excel]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Media:bdd_com.pdf|Les bases de données]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Histoire / évolutions&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt; &lt;br /&gt;
[[:Media:expertise_codage.pdf|Expertise codage]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= La pratique =&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
! Système !! Sécurité !! Réseaux !! Développement !! Embarquée !! Virtualisation&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=left width=&amp;quot;17%&amp;quot;|&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Installation / Migration&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[bootable_usb_ventoy| Clé bootable Ventoy]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Installation de CentOS| CentOS]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Installation de Rocky| Rocky]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[migration_centos8torocky8| CentOS 8 &amp;amp;rarr; Rocky 8]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[upgrade_rocky8to9| Rocky 8 &amp;amp;rarr; 9]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[WSL | WSL : Linux sur Windows 10]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Les basiques&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[Vi / Vim]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[linux_repository|Les dépots (EPEL, EL, ...)]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[cron| Gestionnaire des tâches: cron]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[rpm_yum| Gestionnaires de paquetages: RPM &amp;amp; YUM]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Les logs]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[users_groups|Utilisateurs et groupes]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Gestion des disques]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;SysVInit&amp;lt;br&amp;gt;CentOS &amp;amp;#8804; 6&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[Gestionnaire de démarrage|Gestionnaire de démarrage]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[start_stop_daemon|Création d&#039;un service]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[ntpd| L&#039;heure avec NTP]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;SystemD&amp;lt;br&amp;gt;CentOS &amp;amp;#8805; 7 / Rocky&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[systemctl|Systemctl]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[systemctl service|Création d&#039;un service]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[chrony|L&#039;heure avec Chrony]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Réseaux&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[identify_your_nic | Identifier ses cartes]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[ifcfg-ethX|Les interfaces réseaux]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[sysconfig-network|Les paramètres réseaux]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[resolv.conf|Configuration du client DNS]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Haute disponibilité&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[drbd|Réplication à chaud avec DRBD]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Multimédia&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[DLNA|Partage de contenu cross-platform avec DLNA]]&lt;br /&gt;
|width=&amp;quot;17%&amp;quot;|&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Réseaux&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Iptables]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Squid]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Media:Chillispot.pdf|Hotspot avec Chillispot]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Sécuriser un service avec Fail2ban]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;VPN&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[Openvpn]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Wireguard]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Système&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[SSH]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[SELinux]]&lt;br /&gt;
|align=left width=&amp;quot;16%&amp;quot;|&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Les commandes&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[tcpdump | tcpdump]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[iproute2 | ip]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;OSI 2&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[source routing|Le routage source]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[bridge|Les bridges]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[alias|Les alias]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[vlan|Les vlans]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[one-arm_router|La passerelle &#039;&#039;one-arm&#039;&#039;]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[transparent_firewall|Le proxy &#039;&#039;transparent&#039;&#039;]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;OSI 3+&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[DHCP]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[DNS]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Apache httpd&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[httpd_install_start| Installation et premier démarrage ]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[httpd_vhost| Déploiement d&#039;un hôte virtuel]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[httpd_htaccess | Le fichier .htaccess ]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[httpd_redirect_reverse-proxy_mod-rewrite| Redirections, réécriture d’URL (mod_rewrite)]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[httpd_certificate_security | Certificats et sécurité ]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Haute-disponibilité&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[Ucarp]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Services divers&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[SAMBA]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[xmpp | Serveur XMPP avec Ejabberd]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[vnc|Installer un serveur VNC]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Industrialisation&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[:Media:pxe.pdf|Monter un serveur PXE (pdf)]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[PXE|Monter un serveur PXE]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Supervision&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[Nagios| Nagios]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Cacti| Installer un serveur Cacti]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[SNMP | Utiliser SNMP]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Cisco ISR (routeur)&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[ISR-basics|Les bases]]&lt;br /&gt;
|align=left width=&amp;quot;17%&amp;quot;|&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Général&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[eclipse_install|Mise en place de l&#039;environnement de développement]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[svn|Serveur de version SVN]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;PHP, les basiques&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[php_httpd_install | Installation sous Linux]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[php_devel| Premier projet en &#039;&#039;PHP&#039;&#039;]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[php_algo|Un peu d&#039;algorithmique]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[php_object| Les objets]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[php_xdebug| Debugger avec &#039;&#039;Xdebug&#039;&#039;]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;PHP CLI&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[php_memcached| Memcached un serveur de cache]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[php_daemon | Écriture d&#039;un démon]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[php_socket | Utilisation des sockets]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;PHP CGI&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[php_$get_$post_$session| Passer des informations entres pages]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[php_pdo| Utiliser une base MySQL avec PDO]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[php_slim | Le framework SLIM]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;JS, les basiques&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[js_devel| Premier projet en &#039;&#039;JavaScript&#039;&#039;]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[js_algo| Un peu d&#039;algorithmique]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[js_object| Les objets]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;JS, les RIA (&#039;&#039;R&#039;&#039;ich &#039;&#039;I&#039;&#039;nternet &#039;&#039;A&#039;&#039;pplication)&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[js_AJAX| Client AJAX pour utiliser des Web Services]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[js_AJAX_auth | Authentification avec un client AJAX]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[js_AJAX_fetch_api | Découverte de l&#039;API &#039;&#039;fetch&#039;&#039;]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;C, les basiques&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[c_devel| Premier projet en &#039;&#039;C&#039;&#039;]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[c_devel_cross| Compilation croisée (Cross Compilation)]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[c_algo| Un peu d&#039;algorithmique]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;C, parallélisation&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[c_pthread| Les threads]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[c_fork| Les forks]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;C, IPC&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[c_pipe| Les tubes]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[c_semaphore| Les sémaphores]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[c_signals| Les signaux POSIX]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[c_socket| Les sockets]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;C, GP-GPU avec CUDA&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[cuda_install| Installation de CUDA]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[cuda_hello_world| Les concepts et bases]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Java, les basiques&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[java_devel| Premier projet en &#039;&#039;Java&#039;&#039;]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[java_jar|Mon premier objet]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[java_algo| Un peu d&#039;algorithmique]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Java, le web&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[java_servlet|Les Servlets]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[java_ws_restful| Web Service Restful]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Java, le stockage&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[java_mysql| Utiliser une base MySQL avec Java]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[java_memcached| Memcached un serveur de cache]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;SQL&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[sql_install| Installation d&#039;un SGBDR]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[SQL_import| Importation d&#039;une base de données]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Python&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[python_devel| Premier projet en &#039;&#039;Python&#039;&#039;]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[python_algo|Un peu d&#039;algorithmique]]&lt;br /&gt;
|align=left width=&amp;quot;16%&amp;quot;|&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Programmation&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[Arduino_Eclipse_sketch | Création d&#039;un projet sous Eclipse]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Arduino_sketch_writing | Écriture d&#039;un sketch]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[atmega328_registers | Manipulation de registres ]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[atmega328_timers | Les timers ]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Ports série&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[Arduino_CH340_driver_install | Installation du pilote CH340 (Serial TTL)]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Arduino_FTDI_driver_install | Installation du pilote FTDI(Serial TTL)]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Arduino_CP210X_driver_install | Installation du pilote CP210X(Serial TTL)]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Les cartes&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[arduino_diagram | Schémas des cartes Arduino]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[esp8266_diagram | Schémas des cartes ESP8266]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[esp32_diagram | Schémas des cartes ESP32]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[sbc_diagram | Schémas des SBC]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[µc_datasheet | Fiches techniques des microcontrôleurs]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Capteurs&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[Arduino_LDR | Luminosité avec une photorésistance]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Arduino_BH1750 | Luminosité avec le BH1750]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Arduino_DS18B20 | Température avec le DS18B20]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Arduino_LM35DZ | Température avec le LM35]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Arduino_DHT11 | Température et humidité avec le DHT11]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Arduino_BMP280 | Température, pression et altitude avec le BMP280]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Arduino_A3144 | Effet de Hall (magnétisme) avec le A3144 ]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Arduino_SR501 | Détection de mouvement avec le SR501 (PIR) ]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Arduino_soil_moisture | Capteur d&#039;humidité du sol ]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Communication sans-fil&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[Arduino_HC12 | Communication RF433 avec un HC12]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Arduino_NRF24L01 | Communication 2.4Ghz avec un NRF24L01]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Arduino_ESP05 | Communication Wi-Fi avec un ESP-05]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Shield Ethernet (W5100)&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[Arduino_W5100_intro | Présentation du shield]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Arduino_W5100_OSI3 | Configuration OSI 3]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Arduino_W5100_web_server | Utilisation du Shield Ethernet pour faire un serveur Web]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Composants et montages divers&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[ potentiometre | Potentiomètre ]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[ shift_register | Registre à décalage ]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[ Arduino_2axis_joystick_button | Joystick 2 axes avec bouton ]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[ Arduino_SD_CARD | Module pour cartes SD ]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;ESP8266 / ESP32&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[esp_ide_arduino | Cartes ESP et IDE Arduino]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[esp8266_wifi | Utilisation du WiFi ]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[esp8266_webserver | Utilisation du serveur web ]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[esp8266_udp_server | Serveur UDP ]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[esp8266_ntp_client | Client NTP ]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Media:esp8266_tp_meteo_dht11.pdf | TP station météo avec le DHT11 ]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Raspberry / Banana / Orange Pi&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[iso_install_sdcard | Installation d&#039;une image ]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[pi_java_install | Mise en place de Java ]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[sbc_qemu_emulation | Émulation avec Qemu ]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Linux sunxi armbian gpio | Manipulation des GPIO sous Linux]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Linux sunxi armbian w1 | Utilisation du protocole OneWire sous Linux]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Linux uart sunxi armbian | Utilisation du protocole UART sous Linux]]&lt;br /&gt;
|align=left width=&amp;quot;16%&amp;quot;|&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;VmWare&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[vmware_install | Installation ]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[vmware_network | La partie réseau ]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[vmware_create_vm | Création d&#039;une machine virtuelle ]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[vmware_debug_vm | Débogage réseau d&#039;une machine virtuelle]]&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Proxmox&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
[[proxmox_install | Installation ]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[proxmox_first_start | Premier démarrage ]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[proxmox_nic_name | Les interfaces réseaux ]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[proxmox_iptables | Utilisation d&#039;iptables ]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[proxmox_fail2ban | Fail2ban ]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;visibility:hidden&amp;quot;&amp;gt;&lt;br /&gt;
__TOC__&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
__NOTOC__&lt;br /&gt;
&lt;br /&gt;
[[index_detailed |  ]]&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Fichier:Intel_sfp%2B_nic4.jpg&amp;diff=4402</id>
		<title>Fichier:Intel sfp+ nic4.jpg</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Fichier:Intel_sfp%2B_nic4.jpg&amp;diff=4402"/>
		<updated>2026-07-01T10:32:22Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : Jc.forton a téléversé une nouvelle version de Fichier:Intel sfp+ nic4.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Identify_your_nic&amp;diff=4401</id>
		<title>Identify your nic</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Identify_your_nic&amp;diff=4401"/>
		<updated>2026-07-01T10:30:15Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Contrôle par l&amp;#039;état du lien */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
&lt;br /&gt;
Lorsque l&#039;on arrive sur une machine qui possède plusieurs cartes réseau, il est souvent difficile de faire le lien entre une carte logique (enp1s0, eno2, wl0, ...) et une carte physique et nous allons voir comment faire !&lt;br /&gt;
&lt;br /&gt;
= La logique =&lt;br /&gt;
&lt;br /&gt;
Les premières lettres correspondent au type de carte:&lt;br /&gt;
* en pour [https://fr.wikipedia.org/wiki/Ethernet Ethernet]&lt;br /&gt;
* wl pour [https://fr.wikipedia.org/wiki/Wi-Fi Wireless (Wi-Fi)]&lt;br /&gt;
* ib pour [https://fr.wikipedia.org/wiki/Bus_InfiniBand InfiniBand]&lt;br /&gt;
* sl pour [https://fr.wikipedia.org/wiki/Serial_Line_Internet_Protocol Serial Line IP]&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
Vient ensuite le type de connexion:&lt;br /&gt;
* &#039;&#039;o&#039;&#039; pour &#039;&#039;onboard&#039;&#039; ou intégré&lt;br /&gt;
* &#039;&#039;p&#039;&#039; pour &#039;&#039;pci&#039;&#039;, c&#039;est à dire une carte branché sur des [https://fr.wikipedia.org/wiki/PCI_Express lignes PCI] au processeur&lt;br /&gt;
&lt;br /&gt;
Dans le cas d&#039;une carte en PCI on poursuit avec le numéro du &#039;&#039;slot&#039;&#039; que l&#039;on peut assimiler au nombre de puces présente sur la carte.&lt;br /&gt;
Une carte possédant deux puces aura donc deux &#039;&#039;slot&#039;&#039; : &#039;&#039;s0&#039;&#039; et &#039;&#039;s1&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Et on termine avec la fonction que l&#039;on peut assimiler au nombre de ports par puce. Une puce possédant deux ports aura donc deux fonctions: &#039;&#039;f0&#039;&#039; et &#039;&#039;f1&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour résumer, les cartes intégrées possèdent des noms comme:&lt;br /&gt;
* &#039;&#039;eno0&#039;&#039;&lt;br /&gt;
* &#039;&#039;eno1&#039;&#039;&lt;br /&gt;
* ... &lt;br /&gt;
&lt;br /&gt;
Et les cartes en PCI des noms comme:&lt;br /&gt;
* &#039;&#039;enp0s0f1&#039;&#039;&lt;br /&gt;
* &#039;&#039;enp0s0f1&#039;&#039;&lt;br /&gt;
* &#039;&#039;enp1s0f0&#039;&#039;&lt;br /&gt;
* ...&lt;br /&gt;
= Connaître ces cartes =&lt;br /&gt;
&lt;br /&gt;
Pour démarrer le travail d&#039;identification, vous pouvez commencez par repérer le constructeur et / ou le modèle de puce utilisé, souvent mentionné:&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
Sur la boîte de votre carte mère...&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
ou bien dans son manuel...&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
ou dans l&#039;annonce si c&#039;est une carte PCI&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:motherboard box Z370.jpg|350px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:motherboard manual Z270.jpg|300px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:amazon mellanox connect-x3.jpg|400px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Identifiants PCI et prédictions =&lt;br /&gt;
&lt;br /&gt;
Il faut maintenant faire le parallèle avec les cartes afficher dans le terminal et pour ça nous allons utiliser la commande &#039;&#039;lspci&#039;&#039;:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# lspci | grep Ethernet&lt;br /&gt;
01:00.0 Ethernet controller: Mellanox Technologies MT27500 Family [ConnectX-3]&lt;br /&gt;
03:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8111/8168/8211/8411 PCI Express Gigabit Ethernet Controller (rev 15)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On voit que la carte Realtek RTL8111 (celle de la carte mère) possède l&#039;identifiant 03:00.0 et que la Mellanox l&#039;identifiant 01:00.0&lt;br /&gt;
&lt;br /&gt;
Il faut maintenant transposer ces identifiants en nom:&lt;br /&gt;
* le premier chiffre correspond a l&#039;identifiant PCI généré par le micrologiciel de la carte mère (p3 et p1)&lt;br /&gt;
* le deuxième correspond au &#039;&#039;slot&#039;&#039; (s0)&lt;br /&gt;
* le dernier à la fonction (f0)&lt;br /&gt;
&lt;br /&gt;
Un nom possible pour la carte Realtek pourrait être &#039;&#039;enp3s0f0&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Cependant, il est possible lorsque les cartes ne possèdent qu&#039;une fonction, d&#039;omettre celle-ci pour raccourcir le nom et notre carte pourrait donc s’appeler &#039;&#039;enp3s0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
On peut confirmer cela grâce à la commande &#039;&#039;ip&#039;&#039;:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ip a&lt;br /&gt;
1: lo: &amp;lt;LOOPBACK,UP,LOWER_UP&amp;gt; mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000&lt;br /&gt;
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00&lt;br /&gt;
    inet 127.0.0.1/8 scope host lo&lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
    inet6 ::1/128 scope host &lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
2: enp3s0: &amp;lt;NO-CARRIER,BROADCAST,MULTICAST,UP&amp;gt; mtu 1500 qdisc fq_codel state DOWN group default qlen 1000&lt;br /&gt;
    link/ether 30:9c:23:20:8c:dd brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
3: enp1s0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc mq state UP group default qlen 1000&lt;br /&gt;
    link/ether 24:8a:07:f7:bd:22 brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut en déduire que:&lt;br /&gt;
* la carte Realtek en gigabit possède l&#039;identifiant enp3s0 &lt;br /&gt;
* la carte Mellanox de 10 gigabit possède l&#039;identifiant enp1s0&lt;br /&gt;
&lt;br /&gt;
= Contrôle par le débit =&lt;br /&gt;
&lt;br /&gt;
Si vous avez toujours des doutes vous pouvez afficher le débit des cartes grâce à la commande &#039;&#039;ethtool&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
La Realtek aura un débit max de 1000&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
La Mellanox pourra monter à 10 Gigabit&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ethtool enp3s0&lt;br /&gt;
Settings for enp3s0:&lt;br /&gt;
	Supported ports: [ TP	 MII ]&lt;br /&gt;
	Supported link modes:   10baseT/Half 10baseT/Full&lt;br /&gt;
	                        100baseT/Half 100baseT/Full&lt;br /&gt;
	                        1000baseT/Full&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ethtool enp1s0&lt;br /&gt;
Settings for enp1s0:&lt;br /&gt;
	Supported ports: [ FIBRE ]&lt;br /&gt;
	Supported link modes:   1000baseX/Full&lt;br /&gt;
	                        10000baseCR/Full&lt;br /&gt;
	                        10000baseSR/Full&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Contrôle par l&#039;état du lien =&lt;br /&gt;
&lt;br /&gt;
Si vous possédez une carte avec plusieurs fonctions (ports), il vous reste à différencier les ports entres eux et pour ça nous allons utiliser l&#039;état des liens pour déterminer le numéro de chaque port.&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:intel sfp+ nic.jpg|350px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:intel sfp+ nic4.jpg|350px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Commencez par déconnecter chaque prises sauf une pour que toutes les ports soient dans un état bas ou &#039;&#039;down&#039;&#039; sauf un qui sera &#039;&#039;up&#039;&#039;:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ip a&lt;br /&gt;
...&lt;br /&gt;
3: enp1s0f0: &amp;lt;NO-CARRIER,BROADCAST,MULTICAST,UP&amp;gt; mtu 1500 qdisc mq state DOWN group default qlen 1000&lt;br /&gt;
    link/ether 24:8a:07:f7:bd:20 brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
4: enp1s0f1: &amp;lt;BROADCAST,MULTICAST,UP&amp;gt; mtu 1500 qdisc mq state UP group default qlen 1000&lt;br /&gt;
    link/ether 24:8a:07:f7:bd:21 brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous savez que le port connecté possède la fonction 1 (&#039;&#039;enp1s0f1&#039;&#039;) et celui débranché à la fonction 0 (&#039;&#039;enp1s0f0&#039;&#039;)&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Fichier:Intel_sfp%2B_nic4.jpg&amp;diff=4400</id>
		<title>Fichier:Intel sfp+ nic4.jpg</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Fichier:Intel_sfp%2B_nic4.jpg&amp;diff=4400"/>
		<updated>2026-07-01T10:30:08Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Fichier:Intel_sfp%2B_nic.jpg&amp;diff=4399</id>
		<title>Fichier:Intel sfp+ nic.jpg</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Fichier:Intel_sfp%2B_nic.jpg&amp;diff=4399"/>
		<updated>2026-07-01T10:28:36Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Identify_your_nic&amp;diff=4398</id>
		<title>Identify your nic</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Identify_your_nic&amp;diff=4398"/>
		<updated>2026-07-01T10:27:42Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Contrôle par l&amp;#039;état du lien */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
&lt;br /&gt;
Lorsque l&#039;on arrive sur une machine qui possède plusieurs cartes réseau, il est souvent difficile de faire le lien entre une carte logique (enp1s0, eno2, wl0, ...) et une carte physique et nous allons voir comment faire !&lt;br /&gt;
&lt;br /&gt;
= La logique =&lt;br /&gt;
&lt;br /&gt;
Les premières lettres correspondent au type de carte:&lt;br /&gt;
* en pour [https://fr.wikipedia.org/wiki/Ethernet Ethernet]&lt;br /&gt;
* wl pour [https://fr.wikipedia.org/wiki/Wi-Fi Wireless (Wi-Fi)]&lt;br /&gt;
* ib pour [https://fr.wikipedia.org/wiki/Bus_InfiniBand InfiniBand]&lt;br /&gt;
* sl pour [https://fr.wikipedia.org/wiki/Serial_Line_Internet_Protocol Serial Line IP]&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
Vient ensuite le type de connexion:&lt;br /&gt;
* &#039;&#039;o&#039;&#039; pour &#039;&#039;onboard&#039;&#039; ou intégré&lt;br /&gt;
* &#039;&#039;p&#039;&#039; pour &#039;&#039;pci&#039;&#039;, c&#039;est à dire une carte branché sur des [https://fr.wikipedia.org/wiki/PCI_Express lignes PCI] au processeur&lt;br /&gt;
&lt;br /&gt;
Dans le cas d&#039;une carte en PCI on poursuit avec le numéro du &#039;&#039;slot&#039;&#039; que l&#039;on peut assimiler au nombre de puces présente sur la carte.&lt;br /&gt;
Une carte possédant deux puces aura donc deux &#039;&#039;slot&#039;&#039; : &#039;&#039;s0&#039;&#039; et &#039;&#039;s1&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Et on termine avec la fonction que l&#039;on peut assimiler au nombre de ports par puce. Une puce possédant deux ports aura donc deux fonctions: &#039;&#039;f0&#039;&#039; et &#039;&#039;f1&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour résumer, les cartes intégrées possèdent des noms comme:&lt;br /&gt;
* &#039;&#039;eno0&#039;&#039;&lt;br /&gt;
* &#039;&#039;eno1&#039;&#039;&lt;br /&gt;
* ... &lt;br /&gt;
&lt;br /&gt;
Et les cartes en PCI des noms comme:&lt;br /&gt;
* &#039;&#039;enp0s0f1&#039;&#039;&lt;br /&gt;
* &#039;&#039;enp0s0f1&#039;&#039;&lt;br /&gt;
* &#039;&#039;enp1s0f0&#039;&#039;&lt;br /&gt;
* ...&lt;br /&gt;
= Connaître ces cartes =&lt;br /&gt;
&lt;br /&gt;
Pour démarrer le travail d&#039;identification, vous pouvez commencez par repérer le constructeur et / ou le modèle de puce utilisé, souvent mentionné:&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
Sur la boîte de votre carte mère...&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
ou bien dans son manuel...&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
ou dans l&#039;annonce si c&#039;est une carte PCI&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:motherboard box Z370.jpg|350px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:motherboard manual Z270.jpg|300px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:amazon mellanox connect-x3.jpg|400px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Identifiants PCI et prédictions =&lt;br /&gt;
&lt;br /&gt;
Il faut maintenant faire le parallèle avec les cartes afficher dans le terminal et pour ça nous allons utiliser la commande &#039;&#039;lspci&#039;&#039;:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# lspci | grep Ethernet&lt;br /&gt;
01:00.0 Ethernet controller: Mellanox Technologies MT27500 Family [ConnectX-3]&lt;br /&gt;
03:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8111/8168/8211/8411 PCI Express Gigabit Ethernet Controller (rev 15)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On voit que la carte Realtek RTL8111 (celle de la carte mère) possède l&#039;identifiant 03:00.0 et que la Mellanox l&#039;identifiant 01:00.0&lt;br /&gt;
&lt;br /&gt;
Il faut maintenant transposer ces identifiants en nom:&lt;br /&gt;
* le premier chiffre correspond a l&#039;identifiant PCI généré par le micrologiciel de la carte mère (p3 et p1)&lt;br /&gt;
* le deuxième correspond au &#039;&#039;slot&#039;&#039; (s0)&lt;br /&gt;
* le dernier à la fonction (f0)&lt;br /&gt;
&lt;br /&gt;
Un nom possible pour la carte Realtek pourrait être &#039;&#039;enp3s0f0&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Cependant, il est possible lorsque les cartes ne possèdent qu&#039;une fonction, d&#039;omettre celle-ci pour raccourcir le nom et notre carte pourrait donc s’appeler &#039;&#039;enp3s0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
On peut confirmer cela grâce à la commande &#039;&#039;ip&#039;&#039;:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ip a&lt;br /&gt;
1: lo: &amp;lt;LOOPBACK,UP,LOWER_UP&amp;gt; mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000&lt;br /&gt;
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00&lt;br /&gt;
    inet 127.0.0.1/8 scope host lo&lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
    inet6 ::1/128 scope host &lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
2: enp3s0: &amp;lt;NO-CARRIER,BROADCAST,MULTICAST,UP&amp;gt; mtu 1500 qdisc fq_codel state DOWN group default qlen 1000&lt;br /&gt;
    link/ether 30:9c:23:20:8c:dd brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
3: enp1s0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc mq state UP group default qlen 1000&lt;br /&gt;
    link/ether 24:8a:07:f7:bd:22 brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut en déduire que:&lt;br /&gt;
* la carte Realtek en gigabit possède l&#039;identifiant enp3s0 &lt;br /&gt;
* la carte Mellanox de 10 gigabit possède l&#039;identifiant enp1s0&lt;br /&gt;
&lt;br /&gt;
= Contrôle par le débit =&lt;br /&gt;
&lt;br /&gt;
Si vous avez toujours des doutes vous pouvez afficher le débit des cartes grâce à la commande &#039;&#039;ethtool&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
La Realtek aura un débit max de 1000&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
La Mellanox pourra monter à 10 Gigabit&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ethtool enp3s0&lt;br /&gt;
Settings for enp3s0:&lt;br /&gt;
	Supported ports: [ TP	 MII ]&lt;br /&gt;
	Supported link modes:   10baseT/Half 10baseT/Full&lt;br /&gt;
	                        100baseT/Half 100baseT/Full&lt;br /&gt;
	                        1000baseT/Full&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ethtool enp1s0&lt;br /&gt;
Settings for enp1s0:&lt;br /&gt;
	Supported ports: [ FIBRE ]&lt;br /&gt;
	Supported link modes:   1000baseX/Full&lt;br /&gt;
	                        10000baseCR/Full&lt;br /&gt;
	                        10000baseSR/Full&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Contrôle par l&#039;état du lien =&lt;br /&gt;
&lt;br /&gt;
Si vous possédez une carte avec plusieurs fonctions (ports), il vous reste à différencier les ports entres eux et pour ça nous allons utiliser l&#039;état des liens pour déterminer le numéro de chaque port.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:intel sfp+ nic.jpg|350px|centré]]&lt;br /&gt;
&lt;br /&gt;
Commencez par déconnecter chaque prises sauf une pour que toutes les ports soient dans un état bas ou &#039;&#039;down&#039;&#039; sauf un qui sera &#039;&#039;up&#039;&#039;:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ip a&lt;br /&gt;
...&lt;br /&gt;
3: enp1s0f0: &amp;lt;NO-CARRIER,BROADCAST,MULTICAST,UP&amp;gt; mtu 1500 qdisc mq state DOWN group default qlen 1000&lt;br /&gt;
    link/ether 24:8a:07:f7:bd:20 brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
4: enp1s0f1: &amp;lt;BROADCAST,MULTICAST,UP&amp;gt; mtu 1500 qdisc mq state UP group default qlen 1000&lt;br /&gt;
    link/ether 24:8a:07:f7:bd:21 brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous savez que le port connecté possède la fonction 1 (&#039;&#039;enp1s0f1&#039;&#039;) et celui débranché à la fonction 0 (&#039;&#039;enp1s0f0&#039;&#039;)&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4397</id>
		<title>Proxmox fail2ban</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4397"/>
		<updated>2026-06-30T15:58:54Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
Proxmox utilise une interface web d&#039;administration qui utilise le port TCP 8006 et c&#039;est un vecteur possible d&#039;attaque par force brut. Nous allons donc &#039;&#039;dresser&#039;&#039; fail2ban pour agir en cas d&#039;attaque !&lt;br /&gt;
&lt;br /&gt;
Proxmox utilise Debian, nous allons principalement reproduire les étapes décrites dans le tutoriel de [[Sécuriser_un_service_avec_Fail2ban| Fail2ban pour Rocky]] et adapter à Debian.&lt;br /&gt;
&lt;br /&gt;
Avant d&#039;aller plus loin, assurez-vous d&#039;avoir correctement installé et configuré [[proxmox_iptables |iptables sur Proxmox]]&lt;br /&gt;
&lt;br /&gt;
= Installation =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt -y install fail2ban&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Configuration =&lt;br /&gt;
Tout d&#039;abord il faut copier le fichier &#039;&#039;/etc/fail2ban/jail.conf&#039;&#039; en &#039;&#039;/etc/fail2ban/jail.local&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dans ce fichier, on va s&#039;intéresser aux variables suivantes:&lt;br /&gt;
*ignoreip : correspond à la suite d&#039;adresses IP qui ne se feront jamais bannir;&lt;br /&gt;
*maxretry : correspond au nombre d&#039;essais;&lt;br /&gt;
*findtime : correspond à la période pendant laquelle les essais vont incrémenter maxretry;&lt;br /&gt;
*bantime  : correspond au temps où l&#039;adresse IP ne peut pas se connecter.&lt;br /&gt;
&lt;br /&gt;
= Configuration de base =&lt;br /&gt;
== Choix de la punition ==&lt;br /&gt;
Il faut choisir quelque chose de cohérent (une punition suffisante) pour ne pas permettre de se faire cracker son mot de passe:&lt;br /&gt;
*maxretry = 3&lt;br /&gt;
*findtime = 86400 (correspond à 1 journée)&lt;br /&gt;
*bantime = 604800 (correspond à 1 semaine)&lt;br /&gt;
&lt;br /&gt;
Cela signifie que si une adresse IP se trompe 3 fois en 1 journée (86400s) elle se fait bannir pendant 1 semaine (604800s).&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul permet de trouver le nombre maximal de tentatives durant une année:&lt;br /&gt;
&lt;br /&gt;
365 jours / 7 jours par semaine * 3 tentatives = 156 essais, ce qui reste raisonnable. &lt;br /&gt;
&lt;br /&gt;
Si le pirate possède un [http://fr.wikipedia.org/wiki/Botnet botnet], il faut bien sûr multiplier ce nombre par le nombre de machines dans le botnet...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Attention : fail2ban parcours les logs de connexion pour connaître le numéro de la tentative, ce qui a pour conséquence, si le &#039;&#039;findtime&#039;&#039; est grand, de prendre un certain temps...&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Jail pour SSH ==&lt;br /&gt;
Il suffit d&#039;ajouter la ligne &#039;&#039;enabled=true&#039;&#039; dans la section à activer !&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[sshd]&lt;br /&gt;
&lt;br /&gt;
# To use more aggressive sshd modes set filter parameter &amp;quot;mode&amp;quot; in jail.local:&lt;br /&gt;
# normal (default), ddos, extra or aggressive (combines all).&lt;br /&gt;
# See &amp;quot;tests/files/logs/sshd&amp;quot; or &amp;quot;filter.d/sshd.conf&amp;quot; for usage example and details.&lt;br /&gt;
#mode   = normal&lt;br /&gt;
enabled = true&lt;br /&gt;
port    = ssh&lt;br /&gt;
logpath = %(sshd_log)s&lt;br /&gt;
backend = %(sshd_backend)s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Configuration spécifique =&lt;br /&gt;
== Jail pour PVEPROXY ==&lt;br /&gt;
Pveproxy écoute sur le port 8006 et ne fonctionne pas exactement comme un serveur [[HTTPD | Apache httpd]] qui mettrait ces logs dans le fichier &#039;&#039;error_log&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Nous allons mettre cette configuration spécifique dans le fichier &#039;&#039;/etc/fail2ban/jail.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[proxmox]&lt;br /&gt;
enabled = true&lt;br /&gt;
port = https,http,8006&lt;br /&gt;
filter = proxmox&lt;br /&gt;
backend = systemd&lt;br /&gt;
maxretry = 3&lt;br /&gt;
findtime = 2d&lt;br /&gt;
bantime = 1h&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le backend utilisé est systemd, exactement comme si vous utilisiez la commande :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Filtre pour PVEPROXY ==&lt;br /&gt;
Il ne nous reste plus qu&#039;à spécifier le filtre &#039;&#039;proxmox&#039;&#039; dans le fichier &#039;&#039;/etc/fail2ban/filter.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=&amp;lt;HOST&amp;gt; user=.* msg=.*&lt;br /&gt;
ignoreregex =&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Tests =&lt;br /&gt;
Il faut maintenant tester le filtre et pour ça on peut utiliser un partage de connexion et réaliser le nombre d&#039;échecs spécifié par la directive &amp;quot;maxretry&amp;quot; (ici 3) :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed:	0&lt;br /&gt;
|  |- Total failed:	3&lt;br /&gt;
|  `- Journal matches:	_SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned:	1&lt;br /&gt;
   |- Total banned:	1&lt;br /&gt;
   `- Banned IP list:	37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On voit bien l&#039;IP 37.167.23.159 qui est bannie !&lt;br /&gt;
N&#039;oubliez pas de l&#039;ajouter à &#039;&#039;ignoreip&#039;&#039; dans le fichier &#039;&#039;jails.local&#039;&#039; ou de faire &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client unban 37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Démarrage et enregistrement dans le chargeur de démarrage =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start fail2ban.service&lt;br /&gt;
# systemctl enable fail2ban.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Vous pouvez maintenant démarrer fail2ban&lt;br /&gt;
&lt;br /&gt;
= Proxification=&lt;br /&gt;
Lorsque votre serveur Proxmox se trouve derrière un reverse-proxy (Apache, Nginx, Traefik, ...), au niveau 3 OSI, l&#039;adresse IP du client est remplacée par celle du proxy et le serveur utilise l&#039;entêtes &#039;&#039;X-Forwarded-For&#039;&#039; ou &#039;&#039;X-Real-IP&#039;&#039; pour transporter l&#039;adresse du client &lt;br /&gt;
[[Fichier:Reverse proxy proxmox.png|700px|centré]]&lt;br /&gt;
Le problème est que la seule adresse que fail2ban va voir apparaître dans les logs est celle du reverse-proxy (&#039;&#039;192.168.4.100&#039;&#039;) :&lt;br /&gt;
[[Fichier:Reverse proxy ip logs.png|600px|centré]]&lt;br /&gt;
Même si le filtre &#039;&#039;fail2ban&#039;&#039; est configuré pour utiliser la commande &#039;&#039;journactl&#039;&#039; sur le démon &#039;&#039;pvedaemon&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
les adresses viennent de pveproxy qui journalise tout dans &#039;&#039;/var/log/pveproxy/access.log&#039;&#039; et &#039;&#039;pvedaemon&#039;&#039; ne journalise que les échecs d&#039;authentification. &lt;br /&gt;
Il est donc plus simple de faire un &#039;&#039;tail&#039;&#039; ou un &#039;&#039;cat&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Que d&#039;utiliser &#039;&#039;journalctl&#039;&#039; pour voir les IPs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
Dec 14 10:43:01 labo unix_chkpwd[1326506]: password check failed for user (root)&lt;br /&gt;
Dec 14 10:43:01 labo IPCC.xs[1320783]: pam_unix(proxmox-ve-auth:auth): authentication failure; logname= uid=0 euid=0 tty= ruser= rhost=37.167.23.159  user=root&lt;br /&gt;
Dec 14 10:43:03 labo pvedaemon[1320783]: authentication failure; rhost=37.167.23.159 user=root@pam msg=Authentication failure&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Configuration de pveproxy ==&lt;br /&gt;
Si on veut voir l&#039;adresse du client, il faut dire au [https://fr.wikipedia.org/wiki/Daemon_(informatique)| démon] &#039;&#039;pveproxy&#039;&#039; d&#039;utiliser l&#039;une des deux entêtes précédentes ainsi que préciser l&#039;adresse du proxy. &lt;br /&gt;
&lt;br /&gt;
Préciser l&#039;adresse du proxy est essentiel pour que &#039;&#039;pveproxy&#039;&#039; n&#039;accepte de lire l&#039;adresse du client présente dans l&#039;entête &#039;&#039;&#039;uniquement&#039;&#039;&#039; si cela provient du proxy, qui est une machine de confiance. Le cas contraire, tout le monde pourrait ajouter une adresse IP dans l&#039;entête pour la faire bannir...&lt;br /&gt;
&lt;br /&gt;
Nous allons créer le fichier &#039;&#039;/etc/default/pveproxy&#039;&#039; avec les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Forwarded-For&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Real-IP&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_ALLOW_FROM=&amp;quot;192.168.4.100&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il faut maintenant redémarrer &#039;&#039;pveproxy&#039;&#039; pour que les changements s&#039;appliquent. Si vous êtes connecté via l&#039;interface web, cela va vous déconnecter, le temps que le démon redémarre, il faudra ensuite certainement rafraîchir la page web.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl restart pveproxy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à vérifier dans les logs si les bonnes adresses s&#039;affichent:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Si jamais ce n&#039;est pas le cas, poursuivez avec la modification du fichier &#039;&#039;AnyEvent.pm&#039;&#039;&lt;br /&gt;
== Modification de AnyEvent.pm ==&lt;br /&gt;
=== Application de la modification ===&lt;br /&gt;
Au jour d&#039;aujourd&#039;hui (13/12/25) la proxification ne fonctionne plus et il faut apporter une modification dans le fichier &#039;&#039;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&#039;&#039; pour que les bonnes adresses apparaissent !&lt;br /&gt;
En fonction des versions cette modification peut avoir lieu soit ligne &#039;&#039;&#039;1504&#039;&#039;&#039;, soit ligne &#039;&#039;&#039;1554&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Il faut repérer la fonction suivante:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
sub authenticate_and_handle_request {&lt;br /&gt;
    my ($self, $reqstate) = @_;&lt;br /&gt;
&lt;br /&gt;
    my $request = $reqstate-&amp;gt;{request};&lt;br /&gt;
    my $method = $request-&amp;gt;method();&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
C&#039;est un peu plus loin qu&#039;il faut insérer le code :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 ### INSERTION ICI ###&lt;br /&gt;
&lt;br /&gt;
    if ($self-&amp;gt;{spiceproxy}) {&lt;br /&gt;
        my $connect_str = $request-&amp;gt;header(&#039;Host&#039;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il faut modifier l&#039;attribut &#039;&#039;peer_host&#039;&#039; de l&#039;objet &#039;&#039;reqstate&#039;&#039; si l&#039;une des deux entêtes est présente :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if ($request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
} elsif ($request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Double IPv4 ou préfixe IPv6 ===&lt;br /&gt;
Après redémarrage, cela permet de voir l&#039;adresse du client dans les logs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/ext-all.js?ver=7.0.0 HTTP/1.1&amp;quot; 200 683505&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/js/u2f-api.js HTTP/1.1&amp;quot; 200 4898&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/resources HTTP/1.1&amp;quot; 200 1226&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/tasks HTTP/1.1&amp;quot; 200 1090&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /proxmoxlib.js?ver=v5.0.4-t1754316706 HTTP/1.1&amp;quot; 200 157086&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/theme-crisp/resources/theme-crisp-all_1.css HTTP/1.1&amp;quot; 200 32919&lt;br /&gt;
::ffff:192.168.20.22 - root@pam [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/nodes/labo/lxc/100/status/current HTTP/1.1&amp;quot; 200 523&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il nous reste un peu de nettoyage à faire, dans certains cas :&lt;br /&gt;
* l&#039;adresse apparaît non pas une fois mais deux, séparées par une virgule&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
37.167.182.207, 37.167.182.207&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* l&#039;adresse IPv4 (32 bits) est affichée dans sa représentation IPv6 (128 bits), avec le préfixe &#039;&#039;::ffff:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
::ffff:192.168.20.22&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On a deux possibilités pour faire le nettoyage :&lt;br /&gt;
*Soit on ajoute les lignes suivantes dans &#039;&#039;AnyEvent.pm&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if (index($reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
   # Remove trailing ip &lt;br /&gt;
   my @fields = split /,/, $reqstate-&amp;gt;{peer_host};&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $fields[0];&lt;br /&gt;
}&lt;br /&gt;
if($reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
   # Remove IPv6 subnet for IPv4&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $1;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*Soit on modifie le filtre /etc/fail2ban/filter.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=.*:?&amp;lt;HOST&amp;gt;,? user=.* msg=.*&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Automatisation ===&lt;br /&gt;
On peut automatiser le processus précédent avec le script suivant, que l&#039;on peut créer dans /root/remoteip_fix.sh :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=bash&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
ANYEVENT_PATH=&amp;quot;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&amp;quot;&lt;br /&gt;
ANYEVENT_REGEX=&#039;$self-&amp;gt;{spiceproxy}&#039;&lt;br /&gt;
TMP_FILE=&amp;quot;/tmp/AnyEvent.pm.tmp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if [ ! -f $ANYEVENT_PATH ]; then&lt;br /&gt;
  echo &amp;quot;$ANYEVENT_PATH does not exists !&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
if [ $(grep &#039;### BUGFIX REMOTE_IP FOR FAIL2BAN ###&#039; $ANYEVENT_PATH | wc -l) -eq 1 ]; then&lt;br /&gt;
  echo &amp;quot;AnyEvent.pm already patched !&amp;quot;&lt;br /&gt;
  exit 0&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
LINE_NUMBER_TOP=$(nl -ba $ANYEVENT_PATH | grep $ANYEVENT_REGEX | head -n 1 | awk -F &#039; &#039; &#039;{print $1}&#039;)&lt;br /&gt;
let LINE_NUMBER_TOP-=1&lt;br /&gt;
&lt;br /&gt;
if [ $LINE_NUMBER_TOP -lt 0 ]; then&lt;br /&gt;
  echo &amp;quot;Did not find the $ANYEVENT_REGEX expr in $ANYEVENT_PATH&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
echo -n &amp;quot;Applying bugfix: &amp;quot;&lt;br /&gt;
trap &amp;quot;rm -f $TMP_FILE&amp;quot; 0 1 2 5 13 15&lt;br /&gt;
head -n $LINE_NUMBER_TOP $ANYEVENT_PATH &amp;gt;$TMP_FILE&lt;br /&gt;
cat &amp;gt;&amp;gt;$TMP_FILE &amp;lt;&amp;lt;EOF&lt;br /&gt;
### BUGFIX REMOTE_IP FOR FAIL2BAN ###&lt;br /&gt;
    if (\$request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
    } elsif (\$request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
    }&lt;br /&gt;
    if (index(\$reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
        my @fields = split /,/, \$reqstate-&amp;gt;{peer_host};&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$fields[0];&lt;br /&gt;
    }&lt;br /&gt;
    if(\$reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
        # Remove IPv6 subnet for IPv4&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$1;&lt;br /&gt;
    }&lt;br /&gt;
#####################################&lt;br /&gt;
EOF&lt;br /&gt;
echo &amp;quot;$ANYEVENT_MODIF&amp;quot; &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cp $ANYEVENT_PATH $ANYEVENT_PATH.ori&lt;br /&gt;
LINE_NUMBER_BOTTOM=$(cat $ANYEVENT_PATH | wc -l)&lt;br /&gt;
let LINE_NUMBER_BOTTOM-=LINE_NUMBER_TOP&lt;br /&gt;
tail -n $LINE_NUMBER_BOTTOM $ANYEVENT_PATH &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cat $TMP_FILE &amp;gt;$ANYEVENT_PATH&lt;br /&gt;
rm -f $TMP_FILE&lt;br /&gt;
trap 0&lt;br /&gt;
echo &amp;quot;done.&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à le rendre exécutable et le lancer :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# chmod +x /root/remoteip_fix.sh&lt;br /&gt;
# /root/remoteip_fix.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne faudra pas oublier de redémarrer &#039;&#039;pveproxy&#039;&#039; pour appliquer les changements !&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Proxmox_iptables&amp;diff=4396</id>
		<title>Proxmox iptables</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Proxmox_iptables&amp;diff=4396"/>
		<updated>2026-06-30T15:51:07Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Persistance */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
&lt;br /&gt;
Vous n&#039;êtes pas sans savoir qu&#039;iptables est une commande permettant configurer [https://fr.wikipedia.org/wiki/Netfilter &#039;&#039;netfilter&#039;&#039;] la partie du noyau chargé du filtrage réseau. Iptables est installé de base sur Proxmox mais, comme Proxmox hérite de Debian, aucune configuration n&#039;est faite et aucun moyen de charger la configuration n&#039;est présent...&lt;br /&gt;
&lt;br /&gt;
Si jamais vous voulez plus d&#039;information à ce sujet, je vous invite à lire le cours sur les [[:Media:Les pare-feux.pdf|pare-feux]] ou les différents articles traitant du sujet !&lt;br /&gt;
&lt;br /&gt;
Avant d&#039;aller plus loin, veuillez configurer des noms explicite sur vos [[Proxmox_first_start#Nommage_des_cartes_réseaux | interfaces réseaux]], dans cet article, l&#039;interface que nous allons sécuriser est l&#039;interface de management.&lt;br /&gt;
&lt;br /&gt;
= État des lieux =&lt;br /&gt;
&lt;br /&gt;
Vous pouvez voir la configuration en tapant la commande suivante:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# iptables -nvL&lt;br /&gt;
Chain INPUT (policy ACCEPT 8969 packets, 2422K bytes)&lt;br /&gt;
 pkts bytes target     prot opt in     out     source               destination         &lt;br /&gt;
&lt;br /&gt;
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)&lt;br /&gt;
 pkts bytes target     prot opt in     out     source               destination         &lt;br /&gt;
&lt;br /&gt;
Chain OUTPUT (policy ACCEPT 2885 packets, 1041K bytes)&lt;br /&gt;
 pkts bytes target     prot opt in     out     source               destination&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous pouvez constater que les polices sont sur &#039;&#039;ACCEPT&#039;&#039; et qu&#039;aucune règle n&#039;est présente dans la chaîne &#039;&#039;INPUT&#039;&#039;. C&#039;est ce que les experts appellent une configuration en mode &#039;&#039;&#039;passoire&#039;&#039;&#039; &amp;amp;#128514;&lt;br /&gt;
&lt;br /&gt;
= Application des règles =&lt;br /&gt;
&lt;br /&gt;
Nous allons paramétrer quelques règles de bases sur l&#039;interface &#039;&#039;vmbr0&#039;&#039; qui nous sert de management, les mêmes qui sont présentes sur une machine Rocky à l&#039;installation d&#039;iptables, à savoir :&lt;br /&gt;
* on autorise tout ce qui fait parti d&#039;une session déjà démarrée&lt;br /&gt;
* on autorise tout le trafique sur l&#039;interface de loopback&lt;br /&gt;
* on autorise les messages ICMP (ping)&lt;br /&gt;
* on autorise le SSH (TCP/22)&lt;br /&gt;
* on &#039;&#039;drop&#039;&#039; tout le reste du trafique entrant&lt;br /&gt;
* on &#039;&#039;drop&#039;&#039; tout le trafique traversant&lt;br /&gt;
&lt;br /&gt;
Et on oublie pas d&#039;ajouter aussi le port de PveProxy (l&#039;interface web) qui est le TCP/8006, ce qui nous donne:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
iptables -A INPUT -i vmbr0 -m state --state RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
iptables -A INPUT -i vmbr0 -p icmp -j ACCEPT&lt;br /&gt;
iptables -A INPUT -i lo -j ACCEPT&lt;br /&gt;
iptables -A INPUT -i vmbr0 -p tcp -m state --state NEW -m tcp --dport 8006 -j ACCEPT&lt;br /&gt;
iptables -A INPUT -i vmbr0 -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT&lt;br /&gt;
iptables -P INPUT DROP&lt;br /&gt;
iptables -P FORWARD DROP&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Si vous n&#039;utilisez pas d&#039;IPv6, autant tout bloquer:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
ip6tables -P INPUT DROP&lt;br /&gt;
ip6tables -P FORWARD DROP&lt;br /&gt;
ip6tables -P OUTPUT DROP&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Persistance =&lt;br /&gt;
&lt;br /&gt;
Maintenant que nous avons toutes nos règles, ils faut les faire persister au redémarrage du serveur et pour cela nous allons utiliser le paquetage &#039;&#039;iptables-persistent&#039;&#039;:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
apt -y install iptables-persistent&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Il vous propose de sauvegarder les règles IPv4 et IPv6 mais pour ceux qui auraient raté le message, vous pouvez toujours faire:&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|align=left|&lt;br /&gt;
Pour IPv4&lt;br /&gt;
|width=10px|&lt;br /&gt;
|align=left|&lt;br /&gt;
Pour IPv6&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
iptables-save &amp;gt; /etc/iptables/rules.v4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
ip6tables-save &amp;gt; /etc/iptables/rules.v6&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
On n&#039;oubliera pas d&#039;enregistrer le service au démarrage de la machine:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
systemctl enable netfilter-persistent&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Les autres interfaces =&lt;br /&gt;
&lt;br /&gt;
Si vous avez plusieurs cartes pour connecter vos conteneurs ou VM, vous ne devez avoir normalement qu&#039;une seule interface d&#039;administration. Cela veut dire que sur les autres interfaces il n&#039;y a pas de configuration IP, donc pas de trafique qui circule.&lt;br /&gt;
&lt;br /&gt;
Je vous invite à installer un pare-feu sur chaque conteneurs et VM pour plus de sécurité...&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Proxmox_iptables&amp;diff=4395</id>
		<title>Proxmox iptables</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Proxmox_iptables&amp;diff=4395"/>
		<updated>2026-06-30T15:39:32Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Persistance */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
&lt;br /&gt;
Vous n&#039;êtes pas sans savoir qu&#039;iptables est une commande permettant configurer [https://fr.wikipedia.org/wiki/Netfilter &#039;&#039;netfilter&#039;&#039;] la partie du noyau chargé du filtrage réseau. Iptables est installé de base sur Proxmox mais, comme Proxmox hérite de Debian, aucune configuration n&#039;est faite et aucun moyen de charger la configuration n&#039;est présent...&lt;br /&gt;
&lt;br /&gt;
Si jamais vous voulez plus d&#039;information à ce sujet, je vous invite à lire le cours sur les [[:Media:Les pare-feux.pdf|pare-feux]] ou les différents articles traitant du sujet !&lt;br /&gt;
&lt;br /&gt;
Avant d&#039;aller plus loin, veuillez configurer des noms explicite sur vos [[Proxmox_first_start#Nommage_des_cartes_réseaux | interfaces réseaux]], dans cet article, l&#039;interface que nous allons sécuriser est l&#039;interface de management.&lt;br /&gt;
&lt;br /&gt;
= État des lieux =&lt;br /&gt;
&lt;br /&gt;
Vous pouvez voir la configuration en tapant la commande suivante:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# iptables -nvL&lt;br /&gt;
Chain INPUT (policy ACCEPT 8969 packets, 2422K bytes)&lt;br /&gt;
 pkts bytes target     prot opt in     out     source               destination         &lt;br /&gt;
&lt;br /&gt;
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)&lt;br /&gt;
 pkts bytes target     prot opt in     out     source               destination         &lt;br /&gt;
&lt;br /&gt;
Chain OUTPUT (policy ACCEPT 2885 packets, 1041K bytes)&lt;br /&gt;
 pkts bytes target     prot opt in     out     source               destination&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous pouvez constater que les polices sont sur &#039;&#039;ACCEPT&#039;&#039; et qu&#039;aucune règle n&#039;est présente dans la chaîne &#039;&#039;INPUT&#039;&#039;. C&#039;est ce que les experts appellent une configuration en mode &#039;&#039;&#039;passoire&#039;&#039;&#039; &amp;amp;#128514;&lt;br /&gt;
&lt;br /&gt;
= Application des règles =&lt;br /&gt;
&lt;br /&gt;
Nous allons paramétrer quelques règles de bases sur l&#039;interface &#039;&#039;vmbr0&#039;&#039; qui nous sert de management, les mêmes qui sont présentes sur une machine Rocky à l&#039;installation d&#039;iptables, à savoir :&lt;br /&gt;
* on autorise tout ce qui fait parti d&#039;une session déjà démarrée&lt;br /&gt;
* on autorise tout le trafique sur l&#039;interface de loopback&lt;br /&gt;
* on autorise les messages ICMP (ping)&lt;br /&gt;
* on autorise le SSH (TCP/22)&lt;br /&gt;
* on &#039;&#039;drop&#039;&#039; tout le reste du trafique entrant&lt;br /&gt;
* on &#039;&#039;drop&#039;&#039; tout le trafique traversant&lt;br /&gt;
&lt;br /&gt;
Et on oublie pas d&#039;ajouter aussi le port de PveProxy (l&#039;interface web) qui est le TCP/8006, ce qui nous donne:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
iptables -A INPUT -i vmbr0 -m state --state RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
iptables -A INPUT -i vmbr0 -p icmp -j ACCEPT&lt;br /&gt;
iptables -A INPUT -i lo -j ACCEPT&lt;br /&gt;
iptables -A INPUT -i vmbr0 -p tcp -m state --state NEW -m tcp --dport 8006 -j ACCEPT&lt;br /&gt;
iptables -A INPUT -i vmbr0 -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT&lt;br /&gt;
iptables -P INPUT DROP&lt;br /&gt;
iptables -P FORWARD DROP&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Si vous n&#039;utilisez pas d&#039;IPv6, autant tout bloquer:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
ip6tables -P INPUT DROP&lt;br /&gt;
ip6tables -P FORWARD DROP&lt;br /&gt;
ip6tables -P OUTPUT DROP&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Persistance =&lt;br /&gt;
&lt;br /&gt;
Maintenant que nous avons toutes nos règles, ils faut les faire persister au redémarrage du serveur et pour cela nous allons utiliser le paquetage &#039;&#039;iptables-persistent&#039;&#039;:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
apt -y install iptables-persistent&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Il vous propose de sauvegarder les règles IPv4 et IPv6 mais pour ceux qui auraient raté le message, vous pouvez toujours faire:&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|align=left|&lt;br /&gt;
Pour IPv4&lt;br /&gt;
|width=10px|&lt;br /&gt;
|align=left|&lt;br /&gt;
Pour IPv6&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
iptables-save &amp;gt; /etc/iptables/rules.v4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
ip6tables-save &amp;gt; /etc/iptables/rules.v6&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
On n&#039;oubliera pas d&#039;enregistrer le service au démarrage de la machine:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
systemctl enable netfilter-persistent&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Proxmox_iptables&amp;diff=4394</id>
		<title>Proxmox iptables</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Proxmox_iptables&amp;diff=4394"/>
		<updated>2026-06-30T15:37:05Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Application des règles */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
&lt;br /&gt;
Vous n&#039;êtes pas sans savoir qu&#039;iptables est une commande permettant configurer [https://fr.wikipedia.org/wiki/Netfilter &#039;&#039;netfilter&#039;&#039;] la partie du noyau chargé du filtrage réseau. Iptables est installé de base sur Proxmox mais, comme Proxmox hérite de Debian, aucune configuration n&#039;est faite et aucun moyen de charger la configuration n&#039;est présent...&lt;br /&gt;
&lt;br /&gt;
Si jamais vous voulez plus d&#039;information à ce sujet, je vous invite à lire le cours sur les [[:Media:Les pare-feux.pdf|pare-feux]] ou les différents articles traitant du sujet !&lt;br /&gt;
&lt;br /&gt;
Avant d&#039;aller plus loin, veuillez configurer des noms explicite sur vos [[Proxmox_first_start#Nommage_des_cartes_réseaux | interfaces réseaux]], dans cet article, l&#039;interface que nous allons sécuriser est l&#039;interface de management.&lt;br /&gt;
&lt;br /&gt;
= État des lieux =&lt;br /&gt;
&lt;br /&gt;
Vous pouvez voir la configuration en tapant la commande suivante:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# iptables -nvL&lt;br /&gt;
Chain INPUT (policy ACCEPT 8969 packets, 2422K bytes)&lt;br /&gt;
 pkts bytes target     prot opt in     out     source               destination         &lt;br /&gt;
&lt;br /&gt;
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)&lt;br /&gt;
 pkts bytes target     prot opt in     out     source               destination         &lt;br /&gt;
&lt;br /&gt;
Chain OUTPUT (policy ACCEPT 2885 packets, 1041K bytes)&lt;br /&gt;
 pkts bytes target     prot opt in     out     source               destination&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous pouvez constater que les polices sont sur &#039;&#039;ACCEPT&#039;&#039; et qu&#039;aucune règle n&#039;est présente dans la chaîne &#039;&#039;INPUT&#039;&#039;. C&#039;est ce que les experts appellent une configuration en mode &#039;&#039;&#039;passoire&#039;&#039;&#039; &amp;amp;#128514;&lt;br /&gt;
&lt;br /&gt;
= Application des règles =&lt;br /&gt;
&lt;br /&gt;
Nous allons paramétrer quelques règles de bases sur l&#039;interface &#039;&#039;vmbr0&#039;&#039; qui nous sert de management, les mêmes qui sont présentes sur une machine Rocky à l&#039;installation d&#039;iptables, à savoir :&lt;br /&gt;
* on autorise tout ce qui fait parti d&#039;une session déjà démarrée&lt;br /&gt;
* on autorise tout le trafique sur l&#039;interface de loopback&lt;br /&gt;
* on autorise les messages ICMP (ping)&lt;br /&gt;
* on autorise le SSH (TCP/22)&lt;br /&gt;
* on &#039;&#039;drop&#039;&#039; tout le reste du trafique entrant&lt;br /&gt;
* on &#039;&#039;drop&#039;&#039; tout le trafique traversant&lt;br /&gt;
&lt;br /&gt;
Et on oublie pas d&#039;ajouter aussi le port de PveProxy (l&#039;interface web) qui est le TCP/8006, ce qui nous donne:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
iptables -A INPUT -i vmbr0 -m state --state RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
iptables -A INPUT -i vmbr0 -p icmp -j ACCEPT&lt;br /&gt;
iptables -A INPUT -i lo -j ACCEPT&lt;br /&gt;
iptables -A INPUT -i vmbr0 -p tcp -m state --state NEW -m tcp --dport 8006 -j ACCEPT&lt;br /&gt;
iptables -A INPUT -i vmbr0 -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT&lt;br /&gt;
iptables -P INPUT DROP&lt;br /&gt;
iptables -P FORWARD DROP&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Si vous n&#039;utilisez pas d&#039;IPv6, autant tout bloquer:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
ip6tables -P INPUT DROP&lt;br /&gt;
ip6tables -P FORWARD DROP&lt;br /&gt;
ip6tables -P OUTPUT DROP&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Persistance =&lt;br /&gt;
&lt;br /&gt;
Maintenant que nous avons toutes nos règles, ils faut les faire persister au redémarrage du serveur et pour cela nous allons utiliser le paquetage &#039;&#039;iptables-persistent&#039;&#039;:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
apt -y install iptables-persistent&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Il vous propose de sauvegarder les règles IPv4 et IPv6 mais pour ceux qui auraient raté le message, vous pouvez toujours faire:&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|align=left|&lt;br /&gt;
Pour IPv4&lt;br /&gt;
|width=10px|&lt;br /&gt;
|align=left|&lt;br /&gt;
Pour IPv6&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
iptables-save &amp;gt; /etc/iptables/rules.v4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
ip6tables-save &amp;gt; /etc/iptables/rules.v6&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Proxmox_iptables&amp;diff=4393</id>
		<title>Proxmox iptables</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Proxmox_iptables&amp;diff=4393"/>
		<updated>2026-06-30T15:35:50Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Application des règles */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
&lt;br /&gt;
Vous n&#039;êtes pas sans savoir qu&#039;iptables est une commande permettant configurer [https://fr.wikipedia.org/wiki/Netfilter &#039;&#039;netfilter&#039;&#039;] la partie du noyau chargé du filtrage réseau. Iptables est installé de base sur Proxmox mais, comme Proxmox hérite de Debian, aucune configuration n&#039;est faite et aucun moyen de charger la configuration n&#039;est présent...&lt;br /&gt;
&lt;br /&gt;
Si jamais vous voulez plus d&#039;information à ce sujet, je vous invite à lire le cours sur les [[:Media:Les pare-feux.pdf|pare-feux]] ou les différents articles traitant du sujet !&lt;br /&gt;
&lt;br /&gt;
Avant d&#039;aller plus loin, veuillez configurer des noms explicite sur vos [[Proxmox_first_start#Nommage_des_cartes_réseaux | interfaces réseaux]], dans cet article, l&#039;interface que nous allons sécuriser est l&#039;interface de management.&lt;br /&gt;
&lt;br /&gt;
= État des lieux =&lt;br /&gt;
&lt;br /&gt;
Vous pouvez voir la configuration en tapant la commande suivante:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# iptables -nvL&lt;br /&gt;
Chain INPUT (policy ACCEPT 8969 packets, 2422K bytes)&lt;br /&gt;
 pkts bytes target     prot opt in     out     source               destination         &lt;br /&gt;
&lt;br /&gt;
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)&lt;br /&gt;
 pkts bytes target     prot opt in     out     source               destination         &lt;br /&gt;
&lt;br /&gt;
Chain OUTPUT (policy ACCEPT 2885 packets, 1041K bytes)&lt;br /&gt;
 pkts bytes target     prot opt in     out     source               destination&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous pouvez constater que les polices sont sur &#039;&#039;ACCEPT&#039;&#039; et qu&#039;aucune règle n&#039;est présente dans la chaîne &#039;&#039;INPUT&#039;&#039;. C&#039;est ce que les experts appellent une configuration en mode &#039;&#039;&#039;passoire&#039;&#039;&#039; &amp;amp;#128514;&lt;br /&gt;
&lt;br /&gt;
= Application des règles =&lt;br /&gt;
&lt;br /&gt;
Nous allons paramétrer quelques règles de bases sur l&#039;interface &#039;&#039;vmbr0&#039;&#039; qui nous sert de management, les mêmes qui sont présentes sur une machine Rocky à l&#039;installation d&#039;iptables, à savoir :&lt;br /&gt;
* on autorise tout ce qui fait parti d&#039;une session déjà démarrée&lt;br /&gt;
* on autorise tout le trafique sur l&#039;interface de loopback&lt;br /&gt;
* on autorise les messages ICMP (ping)&lt;br /&gt;
* on autorise le SSH (TCP/22)&lt;br /&gt;
* on &#039;&#039;drop&#039;&#039; tout le reste du trafique entrant&lt;br /&gt;
* on &#039;&#039;drop&#039;&#039; tout le trafique traversant&lt;br /&gt;
&lt;br /&gt;
Et on oublie pas d&#039;ajouter aussi le port de PveProxy (l&#039;interface web) qui est le TCP/8006, ce qui nous donne:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
iptables -A INPUT -i vmbr0 -m state --state RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
iptables -A INPUT -i vmbr0 -p icmp -j ACCEPT&lt;br /&gt;
iptables -A INPUT -i lo -j ACCEPT&lt;br /&gt;
iptables -A INPUT -i vmbr0 -p tcp -m state --state NEW -m tcp --dport 8006 -j ACCEPT&lt;br /&gt;
iptables -A INPUT -i vmbr0 -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT&lt;br /&gt;
iptables -A INPUT -j DROP&lt;br /&gt;
iptables -A FORWARD -j DROP&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Si vous n&#039;utilisez pas d&#039;IPv6, autant tout bloquer:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
ip6tables -P INPUT DROP&lt;br /&gt;
ip6tables -P FORWARD DROP&lt;br /&gt;
ip6tables -P OUTPUT DROP&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Persistance =&lt;br /&gt;
&lt;br /&gt;
Maintenant que nous avons toutes nos règles, ils faut les faire persister au redémarrage du serveur et pour cela nous allons utiliser le paquetage &#039;&#039;iptables-persistent&#039;&#039;:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
apt -y install iptables-persistent&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Il vous propose de sauvegarder les règles IPv4 et IPv6 mais pour ceux qui auraient raté le message, vous pouvez toujours faire:&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|align=left|&lt;br /&gt;
Pour IPv4&lt;br /&gt;
|width=10px|&lt;br /&gt;
|align=left|&lt;br /&gt;
Pour IPv6&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
iptables-save &amp;gt; /etc/iptables/rules.v4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
ip6tables-save &amp;gt; /etc/iptables/rules.v6&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Proxmox_iptables&amp;diff=4392</id>
		<title>Proxmox iptables</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Proxmox_iptables&amp;diff=4392"/>
		<updated>2026-06-30T15:08:48Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Persistance */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
&lt;br /&gt;
Vous n&#039;êtes pas sans savoir qu&#039;iptables est une commande permettant configurer [https://fr.wikipedia.org/wiki/Netfilter &#039;&#039;netfilter&#039;&#039;] la partie du noyau chargé du filtrage réseau. Iptables est installé de base sur Proxmox mais, comme Proxmox hérite de Debian, aucune configuration n&#039;est faite et aucun moyen de charger la configuration n&#039;est présent...&lt;br /&gt;
&lt;br /&gt;
Si jamais vous voulez plus d&#039;information à ce sujet, je vous invite à lire le cours sur les [[:Media:Les pare-feux.pdf|pare-feux]] ou les différents articles traitant du sujet !&lt;br /&gt;
&lt;br /&gt;
Avant d&#039;aller plus loin, veuillez configurer des noms explicite sur vos [[Proxmox_first_start#Nommage_des_cartes_réseaux | interfaces réseaux]], dans cet article, l&#039;interface que nous allons sécuriser est l&#039;interface de management.&lt;br /&gt;
&lt;br /&gt;
= État des lieux =&lt;br /&gt;
&lt;br /&gt;
Vous pouvez voir la configuration en tapant la commande suivante:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# iptables -nvL&lt;br /&gt;
Chain INPUT (policy ACCEPT 8969 packets, 2422K bytes)&lt;br /&gt;
 pkts bytes target     prot opt in     out     source               destination         &lt;br /&gt;
&lt;br /&gt;
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)&lt;br /&gt;
 pkts bytes target     prot opt in     out     source               destination         &lt;br /&gt;
&lt;br /&gt;
Chain OUTPUT (policy ACCEPT 2885 packets, 1041K bytes)&lt;br /&gt;
 pkts bytes target     prot opt in     out     source               destination&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous pouvez constater que les polices sont sur &#039;&#039;ACCEPT&#039;&#039; et qu&#039;aucune règle n&#039;est présente dans la chaîne &#039;&#039;INPUT&#039;&#039;. C&#039;est ce que les experts appellent une configuration en mode &#039;&#039;&#039;passoire&#039;&#039;&#039; &amp;amp;#128514;&lt;br /&gt;
&lt;br /&gt;
= Application des règles =&lt;br /&gt;
&lt;br /&gt;
Nous allons paramétrer quelques règles de bases sur l&#039;interface &#039;&#039;vmbr0&#039;&#039; qui nous sert de management, les mêmes qui sont présentes sur une machine Rocky à l&#039;installation d&#039;iptables, à savoir :&lt;br /&gt;
* on autorise tout ce qui fait parti d&#039;une session déjà démarrée&lt;br /&gt;
* on autorise tout le trafique sur l&#039;interface de loopback&lt;br /&gt;
* on autorise les messages ICMP (ping)&lt;br /&gt;
* on autorise le SSH (TCP/22)&lt;br /&gt;
* on &#039;&#039;drop&#039;&#039; tout le reste&lt;br /&gt;
&lt;br /&gt;
Et on oublie pas d&#039;ajouter aussi le port de PveProxy (l&#039;interface web) qui est le TCP/8006, ce qui nous donne:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
iptables -A INPUT -i vmbr0 -m state --state RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
iptables -A INPUT -i vmbr0 -p icmp -j ACCEPT&lt;br /&gt;
iptables -A INPUT -i lo -j ACCEPT&lt;br /&gt;
iptables -A INPUT -i vmbr0 -p tcp -m state --state NEW -m tcp --dport 8006 -j ACCEPT&lt;br /&gt;
iptables -A INPUT -i vmbr0 -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT&lt;br /&gt;
iptables -A INPUT -j DROP&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Si vous n&#039;utilisez pas d&#039;IPv6, autant tout bloquer:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
ip6tables -P INPUT DROP&lt;br /&gt;
ip6tables -P FORWARD DROP&lt;br /&gt;
ip6tables -P OUTPUT DROP&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Persistance =&lt;br /&gt;
&lt;br /&gt;
Maintenant que nous avons toutes nos règles, ils faut les faire persister au redémarrage du serveur et pour cela nous allons utiliser le paquetage &#039;&#039;iptables-persistent&#039;&#039;:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
apt -y install iptables-persistent&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Il vous propose de sauvegarder les règles IPv4 et IPv6 mais pour ceux qui auraient raté le message, vous pouvez toujours faire:&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|align=left|&lt;br /&gt;
Pour IPv4&lt;br /&gt;
|width=10px|&lt;br /&gt;
|align=left|&lt;br /&gt;
Pour IPv6&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
iptables-save &amp;gt; /etc/iptables/rules.v4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
ip6tables-save &amp;gt; /etc/iptables/rules.v6&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Proxmox_iptables&amp;diff=4391</id>
		<title>Proxmox iptables</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Proxmox_iptables&amp;diff=4391"/>
		<updated>2026-06-30T15:07:17Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Application des règles */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
&lt;br /&gt;
Vous n&#039;êtes pas sans savoir qu&#039;iptables est une commande permettant configurer [https://fr.wikipedia.org/wiki/Netfilter &#039;&#039;netfilter&#039;&#039;] la partie du noyau chargé du filtrage réseau. Iptables est installé de base sur Proxmox mais, comme Proxmox hérite de Debian, aucune configuration n&#039;est faite et aucun moyen de charger la configuration n&#039;est présent...&lt;br /&gt;
&lt;br /&gt;
Si jamais vous voulez plus d&#039;information à ce sujet, je vous invite à lire le cours sur les [[:Media:Les pare-feux.pdf|pare-feux]] ou les différents articles traitant du sujet !&lt;br /&gt;
&lt;br /&gt;
Avant d&#039;aller plus loin, veuillez configurer des noms explicite sur vos [[Proxmox_first_start#Nommage_des_cartes_réseaux | interfaces réseaux]], dans cet article, l&#039;interface que nous allons sécuriser est l&#039;interface de management.&lt;br /&gt;
&lt;br /&gt;
= État des lieux =&lt;br /&gt;
&lt;br /&gt;
Vous pouvez voir la configuration en tapant la commande suivante:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# iptables -nvL&lt;br /&gt;
Chain INPUT (policy ACCEPT 8969 packets, 2422K bytes)&lt;br /&gt;
 pkts bytes target     prot opt in     out     source               destination         &lt;br /&gt;
&lt;br /&gt;
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)&lt;br /&gt;
 pkts bytes target     prot opt in     out     source               destination         &lt;br /&gt;
&lt;br /&gt;
Chain OUTPUT (policy ACCEPT 2885 packets, 1041K bytes)&lt;br /&gt;
 pkts bytes target     prot opt in     out     source               destination&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous pouvez constater que les polices sont sur &#039;&#039;ACCEPT&#039;&#039; et qu&#039;aucune règle n&#039;est présente dans la chaîne &#039;&#039;INPUT&#039;&#039;. C&#039;est ce que les experts appellent une configuration en mode &#039;&#039;&#039;passoire&#039;&#039;&#039; &amp;amp;#128514;&lt;br /&gt;
&lt;br /&gt;
= Application des règles =&lt;br /&gt;
&lt;br /&gt;
Nous allons paramétrer quelques règles de bases sur l&#039;interface &#039;&#039;vmbr0&#039;&#039; qui nous sert de management, les mêmes qui sont présentes sur une machine Rocky à l&#039;installation d&#039;iptables, à savoir :&lt;br /&gt;
* on autorise tout ce qui fait parti d&#039;une session déjà démarrée&lt;br /&gt;
* on autorise tout le trafique sur l&#039;interface de loopback&lt;br /&gt;
* on autorise les messages ICMP (ping)&lt;br /&gt;
* on autorise le SSH (TCP/22)&lt;br /&gt;
* on &#039;&#039;drop&#039;&#039; tout le reste&lt;br /&gt;
&lt;br /&gt;
Et on oublie pas d&#039;ajouter aussi le port de PveProxy (l&#039;interface web) qui est le TCP/8006, ce qui nous donne:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
iptables -A INPUT -i vmbr0 -m state --state RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
iptables -A INPUT -i vmbr0 -p icmp -j ACCEPT&lt;br /&gt;
iptables -A INPUT -i lo -j ACCEPT&lt;br /&gt;
iptables -A INPUT -i vmbr0 -p tcp -m state --state NEW -m tcp --dport 8006 -j ACCEPT&lt;br /&gt;
iptables -A INPUT -i vmbr0 -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT&lt;br /&gt;
iptables -A INPUT -j DROP&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Si vous n&#039;utilisez pas d&#039;IPv6, autant tout bloquer:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
ip6tables -P INPUT DROP&lt;br /&gt;
ip6tables -P FORWARD DROP&lt;br /&gt;
ip6tables -P OUTPUT DROP&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Persistance =&lt;br /&gt;
&lt;br /&gt;
Maintenant que nous avons toutes nos règles, ils faut les faire persister au redémarrage du serveur et pour cela nous allons utiliser le paquetage &#039;&#039;iptables-persistent&#039;&#039;:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
apt -y install iptables-persistent&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Il vous propose de sauvegarder les règles IPv4 et IPv6 mais pour ceux qui auraient raté le message, vous pouvez toujours faire:&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Proxmox_iptables&amp;diff=4390</id>
		<title>Proxmox iptables</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Proxmox_iptables&amp;diff=4390"/>
		<updated>2026-06-30T15:03:06Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Application des règles */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
&lt;br /&gt;
Vous n&#039;êtes pas sans savoir qu&#039;iptables est une commande permettant configurer [https://fr.wikipedia.org/wiki/Netfilter &#039;&#039;netfilter&#039;&#039;] la partie du noyau chargé du filtrage réseau. Iptables est installé de base sur Proxmox mais, comme Proxmox hérite de Debian, aucune configuration n&#039;est faite et aucun moyen de charger la configuration n&#039;est présent...&lt;br /&gt;
&lt;br /&gt;
Si jamais vous voulez plus d&#039;information à ce sujet, je vous invite à lire le cours sur les [[:Media:Les pare-feux.pdf|pare-feux]] ou les différents articles traitant du sujet !&lt;br /&gt;
&lt;br /&gt;
Avant d&#039;aller plus loin, veuillez configurer des noms explicite sur vos [[Proxmox_first_start#Nommage_des_cartes_réseaux | interfaces réseaux]], dans cet article, l&#039;interface que nous allons sécuriser est l&#039;interface de management.&lt;br /&gt;
&lt;br /&gt;
= État des lieux =&lt;br /&gt;
&lt;br /&gt;
Vous pouvez voir la configuration en tapant la commande suivante:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# iptables -nvL&lt;br /&gt;
Chain INPUT (policy ACCEPT 8969 packets, 2422K bytes)&lt;br /&gt;
 pkts bytes target     prot opt in     out     source               destination         &lt;br /&gt;
&lt;br /&gt;
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)&lt;br /&gt;
 pkts bytes target     prot opt in     out     source               destination         &lt;br /&gt;
&lt;br /&gt;
Chain OUTPUT (policy ACCEPT 2885 packets, 1041K bytes)&lt;br /&gt;
 pkts bytes target     prot opt in     out     source               destination&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous pouvez constater que les polices sont sur &#039;&#039;ACCEPT&#039;&#039; et qu&#039;aucune règle n&#039;est présente dans la chaîne &#039;&#039;INPUT&#039;&#039;. C&#039;est ce que les experts appellent une configuration en mode &#039;&#039;&#039;passoire&#039;&#039;&#039; &amp;amp;#128514;&lt;br /&gt;
&lt;br /&gt;
= Application des règles =&lt;br /&gt;
&lt;br /&gt;
Nous allons paramétrer quelques règles de bases sur l&#039;interface &#039;&#039;vmbr0&#039;&#039; qui nous sert de management, les mêmes qui sont présentes sur une machine Rocky à l&#039;installation d&#039;iptables, à savoir :&lt;br /&gt;
* on autorise tout ce qui fait parti d&#039;une session déjà démarrée&lt;br /&gt;
* on autorise tout le trafique sur l&#039;interface de loopback&lt;br /&gt;
* on autorise les messages ICMP (ping)&lt;br /&gt;
* on autorise le SSH (TCP/22)&lt;br /&gt;
* on &#039;&#039;drop&#039;&#039; tout le reste&lt;br /&gt;
&lt;br /&gt;
Et on oublie pas d&#039;ajouter aussi le port de PveProxy (l&#039;interface web) qui est le TCP/8006, ce qui nous donne:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
iptables -A INPUT -i vmbr0 -m state --state RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
iptables -A INPUT -i vmbr0 -p icmp -j ACCEPT&lt;br /&gt;
iptables -A INPUT -i lo -j ACCEPT&lt;br /&gt;
iptables -A INPUT -i vmbr0 -p tcp -m state --state NEW -m tcp --dport 8006 -j ACCEPT&lt;br /&gt;
iptables -A INPUT -i vmbr0 -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT&lt;br /&gt;
iptables -A INPUT -j DROP&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Si vous n&#039;utilisez pas d&#039;IPv6, autant tout bloquer:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
ip6tables -P INPUT DROP&lt;br /&gt;
ip6tables -P FORWARD DROP&lt;br /&gt;
ip6tables -P OUTPUT DROP&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Proxmox_iptables&amp;diff=4389</id>
		<title>Proxmox iptables</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Proxmox_iptables&amp;diff=4389"/>
		<updated>2026-06-30T15:01:14Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Application des règles */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
&lt;br /&gt;
Vous n&#039;êtes pas sans savoir qu&#039;iptables est une commande permettant configurer [https://fr.wikipedia.org/wiki/Netfilter &#039;&#039;netfilter&#039;&#039;] la partie du noyau chargé du filtrage réseau. Iptables est installé de base sur Proxmox mais, comme Proxmox hérite de Debian, aucune configuration n&#039;est faite et aucun moyen de charger la configuration n&#039;est présent...&lt;br /&gt;
&lt;br /&gt;
Si jamais vous voulez plus d&#039;information à ce sujet, je vous invite à lire le cours sur les [[:Media:Les pare-feux.pdf|pare-feux]] ou les différents articles traitant du sujet !&lt;br /&gt;
&lt;br /&gt;
Avant d&#039;aller plus loin, veuillez configurer des noms explicite sur vos [[Proxmox_first_start#Nommage_des_cartes_réseaux | interfaces réseaux]], dans cet article, l&#039;interface que nous allons sécuriser est l&#039;interface de management.&lt;br /&gt;
&lt;br /&gt;
= État des lieux =&lt;br /&gt;
&lt;br /&gt;
Vous pouvez voir la configuration en tapant la commande suivante:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# iptables -nvL&lt;br /&gt;
Chain INPUT (policy ACCEPT 8969 packets, 2422K bytes)&lt;br /&gt;
 pkts bytes target     prot opt in     out     source               destination         &lt;br /&gt;
&lt;br /&gt;
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)&lt;br /&gt;
 pkts bytes target     prot opt in     out     source               destination         &lt;br /&gt;
&lt;br /&gt;
Chain OUTPUT (policy ACCEPT 2885 packets, 1041K bytes)&lt;br /&gt;
 pkts bytes target     prot opt in     out     source               destination&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous pouvez constater que les polices sont sur &#039;&#039;ACCEPT&#039;&#039; et qu&#039;aucune règle n&#039;est présente dans la chaîne &#039;&#039;INPUT&#039;&#039;. C&#039;est ce que les experts appellent une configuration en mode &#039;&#039;&#039;passoire&#039;&#039;&#039; &amp;amp;#128514;&lt;br /&gt;
&lt;br /&gt;
= Application des règles =&lt;br /&gt;
&lt;br /&gt;
Nous allons paramétrer quelques règles de bases sur l&#039;interface vmbr0 qui nous sert de management, les mêmes qui sont présentes sur une machine Rocky à l&#039;installation d&#039;iptables, à savoir :&lt;br /&gt;
* on autorise tout ce qui fait parti d&#039;une session déjà démarrée&lt;br /&gt;
* on autorise tout le trafique sur l&#039;interface de loopback&lt;br /&gt;
* on autorise les messages ICMP (ping)&lt;br /&gt;
* on autorise le SSH (TCP/22)&lt;br /&gt;
* on &#039;&#039;drop&#039;&#039; tout le reste&lt;br /&gt;
&lt;br /&gt;
Et on oublie pas d&#039;ajouter aussi le port de PveProxy (l&#039;interface web) qui est le TCP/8006, ce qui nous donne:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
iptables -A INPUT -i vmbr0 -m state --state RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
iptables -A INPUT -i vmbr0 -p icmp -j ACCEPT&lt;br /&gt;
iptables -A INPUT -i lo -j ACCEPT&lt;br /&gt;
iptables -A INPUT -i vmbr0 -p tcp -m state --state NEW -m tcp --dport 8006 -j ACCEPT&lt;br /&gt;
iptables -A INPUT -i vmbr0 -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT&lt;br /&gt;
iptables -A INPUT -j DROP&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Proxmox_iptables&amp;diff=4388</id>
		<title>Proxmox iptables</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Proxmox_iptables&amp;diff=4388"/>
		<updated>2026-06-30T14:56:20Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : Page créée avec « = Introduction =  Vous n&amp;#039;êtes pas sans savoir qu&amp;#039;iptables est une commande permettant configurer [https://fr.wikipedia.org/wiki/Netfilter &amp;#039;&amp;#039;netfilter&amp;#039;&amp;#039;] la partie du noyau chargé du filtrage réseau. Iptables est installé de base sur Proxmox mais, comme Proxmox hérite de Debian, aucune configuration n&amp;#039;est faite et aucun moyen de charger la configuration n&amp;#039;est présent...  Si jamais vous voulez plus d&amp;#039;information à ce sujet, je vous invite à lire le cours su... »&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
&lt;br /&gt;
Vous n&#039;êtes pas sans savoir qu&#039;iptables est une commande permettant configurer [https://fr.wikipedia.org/wiki/Netfilter &#039;&#039;netfilter&#039;&#039;] la partie du noyau chargé du filtrage réseau. Iptables est installé de base sur Proxmox mais, comme Proxmox hérite de Debian, aucune configuration n&#039;est faite et aucun moyen de charger la configuration n&#039;est présent...&lt;br /&gt;
&lt;br /&gt;
Si jamais vous voulez plus d&#039;information à ce sujet, je vous invite à lire le cours sur les [[:Media:Les pare-feux.pdf|pare-feux]] ou les différents articles traitant du sujet !&lt;br /&gt;
&lt;br /&gt;
Avant d&#039;aller plus loin, veuillez configurer des noms explicite sur vos [[Proxmox_first_start#Nommage_des_cartes_réseaux | interfaces réseaux]], dans cet article, l&#039;interface que nous allons sécuriser est l&#039;interface de management.&lt;br /&gt;
&lt;br /&gt;
= État des lieux =&lt;br /&gt;
&lt;br /&gt;
Vous pouvez voir la configuration en tapant la commande suivante:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# iptables -nvL&lt;br /&gt;
Chain INPUT (policy ACCEPT 8969 packets, 2422K bytes)&lt;br /&gt;
 pkts bytes target     prot opt in     out     source               destination         &lt;br /&gt;
&lt;br /&gt;
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)&lt;br /&gt;
 pkts bytes target     prot opt in     out     source               destination         &lt;br /&gt;
&lt;br /&gt;
Chain OUTPUT (policy ACCEPT 2885 packets, 1041K bytes)&lt;br /&gt;
 pkts bytes target     prot opt in     out     source               destination&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous pouvez constater que les polices sont sur &#039;&#039;ACCEPT&#039;&#039; et qu&#039;aucune règle n&#039;est présente dans la chaîne &#039;&#039;INPUT&#039;&#039;. C&#039;est ce que les experts appellent une configuration en mode &#039;&#039;&#039;passoire&#039;&#039;&#039; &amp;amp;#128514;&lt;br /&gt;
&lt;br /&gt;
= Application des règles =&lt;br /&gt;
&lt;br /&gt;
Nous allons paramétrer quelques règles de bases, les mêmes qui sont présentes sur une machine Rocky de base à l&#039;installation d&#039;iptables, à savoir :&lt;br /&gt;
* on autorise tout ce qui fait parti d&#039;une session déjà démarrée&lt;br /&gt;
* on autorise tout le trafique sur l&#039;interface de loopback&lt;br /&gt;
* on autorise les messages ICMP (ping)&lt;br /&gt;
* on autorise le SSH (TCP/22)&lt;br /&gt;
* on &#039;&#039;drop&#039;&#039; tout le reste&lt;br /&gt;
&lt;br /&gt;
Et on oublie pas d&#039;ajouter aussi le port de PveProxy (l&#039;interface web), ce qui nous donne:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
# iptables -A INPUT -p icmp -j ACCEPT&lt;br /&gt;
# iptables -A INPUT -i lo -j ACCEPT&lt;br /&gt;
# iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 8006 -j ACCEPT&lt;br /&gt;
# iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT&lt;br /&gt;
# iptables -A INPUT -j DROP&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Proxmox_first_start&amp;diff=4387</id>
		<title>Proxmox first start</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Proxmox_first_start&amp;diff=4387"/>
		<updated>2026-06-30T14:28:36Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Nommage des cartes réseaux */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
&lt;br /&gt;
Maintenant que votre serveur Proxmox est installé, nous allons effectuer quelques opérations de configuration de bases comme :&lt;br /&gt;
* la modification des dépôts&lt;br /&gt;
* la mise à jour&lt;br /&gt;
* la suppression du message d&#039;abonnement&lt;br /&gt;
* le nommage des cartes réseaux&lt;br /&gt;
* la personnalisation de l&#039;environnement&lt;br /&gt;
&lt;br /&gt;
= Modification des dépôts =&lt;br /&gt;
De base l&#039;équipe de Proxmox vous incite à prendre un abonnement pour profiter des mise à jours et fonctionnalités nécessaires dans un datacenter. &lt;br /&gt;
&lt;br /&gt;
[[Fichier:proxmox subscribe message.jpg|500px|centré]]&lt;br /&gt;
&lt;br /&gt;
Si comme moi, vous utilisez Proxmox dans le cadre d&#039;un homelab, pas besoin de payer, la version &#039;&#039;basic&#039;&#039; est largement suffisante.&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|align=left|&lt;br /&gt;
Cliquez sur l&#039;icône de votre serveur dans la barre à gauche&lt;br /&gt;
|width=10px|&lt;br /&gt;
|align=left|&lt;br /&gt;
Puis sur &#039;&#039;repositories&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox server menu left.jpg|350px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox repositories menu.jpg|150px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
On va dans un premier temps retirez les dépôts &#039;&#039;entreprise&#039;&#039; de Proxmox. Dès que vous voyez &#039;&#039;entreprise&#039;&#039; ou &#039;&#039;pve-entreprise&#039;&#039; dans la colonne &#039;&#039;Components&#039;&#039;, il y a de grande chance que le dépôt nécessite un abonnement.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proxmox repository remove.jpg|900px|centré]]&lt;br /&gt;
&lt;br /&gt;
* cliquez sur le dépôt &#039;&#039;ceph-squid&#039;&#039; puis sur le bouton &#039;&#039;disable&#039;&#039;&lt;br /&gt;
* cliquez sur le dépôt &#039;&#039;ceph-squid&#039;&#039; puis sur le bouton &#039;&#039;disable&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Une grosse croix rouge qui fait peur apparaît&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proxmox repository red corss.jpg|600px|centré]]&lt;br /&gt;
&lt;br /&gt;
Pas de panique, nous allons ajouter le dépôt gratuit pour avoir quand même quelques mise à jours.&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|align=left|&lt;br /&gt;
Cliquez sur &#039;&#039;add&#039;&#039;&lt;br /&gt;
|width=10px|&lt;br /&gt;
|align=left|&lt;br /&gt;
Puis sur &#039;&#039;No-Subscription&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox repository add.jpg|250px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox repositories no-subscription.jpg|500px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Ouf, la méchante croix rouge à disparue :)&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proxmox repositories no-subscription warning.jpg|500px|centré]]&lt;br /&gt;
&lt;br /&gt;
= Mise à jour =&lt;br /&gt;
&lt;br /&gt;
Pour rappel, le serveur que nous allons mettre à jour vient d&#039;être installé, et n&#039;est donc pas encore en utilisation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=color:red&amp;gt;Si vous avez des serveur en production, qui sont utilisés par des clients ou dans le cadre de processus internes à votre entreprise, s&#039;il vous plaît, ne mettez jamais, JAMAIS, jamais à jour ces serveurs.&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous n&#039;avez aucune idée des impacts sur les versions des logiciels et vous risquez, en mettant à jour, de créer une incompatibilité et de faire tomber en panne des logiciels ou applications qui fonctionnaient parfaitement.&lt;br /&gt;
&lt;br /&gt;
Les seules mise à jour que l&#039;on s&#039;autorise en production sont celles de sécurité qui servent à &#039;&#039;patcher&#039;&#039; une vulnérabilité. Et là encore, assurez-vous bien que rien ne va &#039;&#039;exploser&#039;&#039;. Si c&#039;est une machine virtuelle ou un conteneur, faites un snapshot ou une copie avant de procéder à la modification... surtout si c&#039;est un vendredi à 17h 😢&lt;br /&gt;
&lt;br /&gt;
Bon, vous êtes prévenu !&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|align=left|&lt;br /&gt;
Remontez d&#039;un cran sur le bouton &#039;&#039;Updates&#039;&#039;&lt;br /&gt;
|width=10px|&lt;br /&gt;
|align=left|&lt;br /&gt;
Puis cliquez sur &#039;&#039;Refresh&#039;&#039; pour mettre à jour la liste des paquetages disponibles&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox update button.jpg|150px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox update refresh.jpg|100px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|align=left|&lt;br /&gt;
Quand vous êtes prêt, cliquez sur &#039;&#039;Upgrade&#039;&#039;&lt;br /&gt;
|width=10px|&lt;br /&gt;
|align=left|&lt;br /&gt;
une fenêtre et démarrer le processus de mise à jour&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox upgrade button.jpg|150px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox update upgrade.jpg|600px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Suppression du message d&#039;abonnement =&lt;br /&gt;
Maintenant que les dépôt sont configuré et les mises à jour faites, on va désactiver ce message qui apparaît à chaque connexion au portail web de Proxmox.&lt;br /&gt;
[[Fichier:proxmox subscribe message.jpg|500px|centré]]&lt;br /&gt;
&lt;br /&gt;
Pour cela nous allons utiliser l&#039;activateur de &#039;&#039;Jamesits&#039;&#039; disponible sur son [https://github.com/Jamesits/pve-fake-subscription GitHub]&lt;br /&gt;
&lt;br /&gt;
Dans le menu de gauche, cliquez sur l’icône de votre serveur puis sur Shell&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox server menu left.jpg|350px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
&amp;amp;rarr;&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox shell button.jpg|200px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Une fois dans le terminal nous allons utiliser la commande &#039;&#039;wget&#039;&#039; pour télécharger le paquetage sur la machine:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# wget https://github.com/Jamesits/pve-fake-subscription/releases/download/v0.0.11/pve-fake-subscription_0.0.11+git-1_all.deb&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le lien précédent est à récupérer sur la page de téléchargement du projet, assurer-vous d&#039;y faire un tour pour vous assurer qu&#039;il est toujours bon.&lt;br /&gt;
&lt;br /&gt;
Il ne reste plus qu&#039;a l&#039;installer :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# dpkg -i pve-fake-subscription_0.0.11+git-1_all.deb&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il est recommandé de bloquer le site de vérification des clés en mettant une entrée factice dans le fichier &#039;&#039;hosts&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# echo &amp;quot;127.0.0.1 shop.maurer-it.com&amp;quot; &amp;gt; /etc/hosts&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous pouvez vérifier que cela fonctionne en faisant un ping:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
root@pve-tuto:~# ping shop.maurer-it.com&lt;br /&gt;
PING shop.maurer-it.com (127.0.0.1) 56(84) bytes of data.&lt;br /&gt;
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=1 ttl=64 time=0.014 ms&lt;br /&gt;
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=2 ttl=64 time=0.010 ms&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier que le message à bien disparu, il vous suffit de vous déconnecter puis reconnecter !&lt;br /&gt;
&lt;br /&gt;
= Nommage des cartes réseaux =&lt;br /&gt;
&lt;br /&gt;
Lorsque vous ajoutez / retirez une carte sur un port PCI, les identifiants sont redistribués et cela va affecter le nom des cartes réseaux. Si la carte que vous utilisez pour vous connecter à votre serveur Proxmox (généralement sur le &#039;&#039;vmbr0&#039;&#039;) change de nom, vous perdez la connexion à votre serveur... Pas très pratique !&lt;br /&gt;
&lt;br /&gt;
Si vous avez une version supérieur à 9.2 et que vous avez suivie le tutoriel pour [[Proxmox_install | installer Proxmox]] vous avez déjà fixé le nom de votre carte de management, mais qu&#039;en est-il des autres ? Vous l&#039;aurez compris, il faut absolument fixer le noms des cartes pour éviter les surprises !&lt;br /&gt;
&lt;br /&gt;
Une fois vos [[Identify_your_nic | carte identifiées]], il ne vous reste plus qu&#039;à définir leur nom et pour cela je vous conseil d&#039;utiliser leur rôle:&lt;br /&gt;
* une carte connectée à une DMZ &amp;amp;rarr; dmz&lt;br /&gt;
* une carte connectée à un LAN &amp;amp;rarr; lan&lt;br /&gt;
* une carte connectée à une box &amp;amp;rarr; wan&lt;br /&gt;
&lt;br /&gt;
Si vous avez plusieurs cartes par rôle, utilisez des numéros: &#039;&#039;dmz0&#039;&#039;, &#039;&#039;dmz1&#039;&#039;, ...&lt;br /&gt;
&lt;br /&gt;
Pour fixer le nom on va suivre [[Ifcfg-ethX#Que_faire_si_ma_carte_n&#039;a_pas_le_bon_numéro_?? | le tutoriel sur udev]] et d&#039;abord identifier l&#039;adresse MAC de notre carte:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ip a&lt;br /&gt;
1: lo: &amp;lt;LOOPBACK,UP,LOWER_UP&amp;gt; mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000&lt;br /&gt;
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00&lt;br /&gt;
    inet 127.0.0.1/8 scope host lo&lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
    inet6 ::1/128 scope host noprefixroute &lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
2: enp0s0f0: &amp;lt;BROADCAST,MULTICAST&amp;gt; mtu 1500 qdisc noop state DOWN group default qlen 1000&lt;br /&gt;
    link/ether 24:12:4d:01:49:20 brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
3: enp0s0f1: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc mq master vmbr0 state UP group default qlen 1000&lt;br /&gt;
    link/ether 24:12:4d:01:49:21 brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
    altname enp3s0&lt;br /&gt;
4: vmbr0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc noqueue state UP group default qlen 1000&lt;br /&gt;
    link/ether 24:8a:07:f7:ce:9b brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
    inet 192.168.4.240/24 scope global vmbr0&lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
    inet6 fe80::268a:7ff:fef7:ce9b/64 scope link &lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On a donc:&lt;br /&gt;
* enp0s0f1 en management avec l&#039;adresse 24:12:4d:01:49:21&lt;br /&gt;
* enp0s0f1 connecté à une DMZ avec l&#039;adresse 24:12:4d:01:49:20&lt;br /&gt;
&lt;br /&gt;
Il ne nous reste plus qu&#039;a créez le fichier &#039;&#039;/etc/udev/rules.d/70-persistent-net.rules&#039;&#039; avec le contenu suivant:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# Carte Intel SFP+ management &lt;br /&gt;
SUBSYSTEM==&amp;quot;net&amp;quot;, ACTION==&amp;quot;add&amp;quot;, DRIVERS==&amp;quot;?*&amp;quot;, ATTR{address}==&amp;quot;24:12:4d:01:49:21&amp;quot;, ATTR{type}==&amp;quot;1&amp;quot;, KERNEL==&amp;quot;eth*&amp;quot;, NAME=&amp;quot;mgmt&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Carte Intel SFP+ DMZ&lt;br /&gt;
SUBSYSTEM==&amp;quot;net&amp;quot;, ACTION==&amp;quot;add&amp;quot;, DRIVERS==&amp;quot;?*&amp;quot;, ATTR{address}==&amp;quot;24:12:4d:01:49:21&amp;quot;, ATTR{type}==&amp;quot;1&amp;quot;, KERNEL==&amp;quot;eth*&amp;quot;, NAME=&amp;quot;dmz&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Si vous êtes à distance, n&#039;oubliez pas de modifier votre fichier &#039;&#039;/etc/network/interfaces&#039;&#039; avant de redémarrer:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
iface mgmt inet manual&lt;br /&gt;
iface dmz inet manual&lt;br /&gt;
&lt;br /&gt;
auto vmbr0&lt;br /&gt;
iface vmbr0 inet static&lt;br /&gt;
	address 192.168.1.1/24&lt;br /&gt;
	gateway 192.168.1.254&lt;br /&gt;
	bridge-ports mgmt&lt;br /&gt;
	bridge-stp off&lt;br /&gt;
	bridge-fd 0&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Personnalisation de l&#039;environnement =&lt;br /&gt;
&lt;br /&gt;
Comme Proxmox est fait sur une base de Debian, certaine commandes disponible sur Rocky risque de vous manquer !&lt;br /&gt;
&lt;br /&gt;
J&#039;aime bien faire un tour dans le fichier &#039;&#039;/root/.bashrc&#039;&#039; pour y ajouter à la fin les lignes suivantes:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
alias ll=&#039;ls -l&#039;&lt;br /&gt;
alias vi=vim.tiny&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Une fois vos modifications terminées, il ne vous reste plus qu&#039;a recharger le fichier &#039;&#039;.bashrc&#039;&#039;:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
#. .bashrc&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Proxmox_first_start&amp;diff=4386</id>
		<title>Proxmox first start</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Proxmox_first_start&amp;diff=4386"/>
		<updated>2026-06-30T14:24:34Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
&lt;br /&gt;
Maintenant que votre serveur Proxmox est installé, nous allons effectuer quelques opérations de configuration de bases comme :&lt;br /&gt;
* la modification des dépôts&lt;br /&gt;
* la mise à jour&lt;br /&gt;
* la suppression du message d&#039;abonnement&lt;br /&gt;
* le nommage des cartes réseaux&lt;br /&gt;
* la personnalisation de l&#039;environnement&lt;br /&gt;
&lt;br /&gt;
= Modification des dépôts =&lt;br /&gt;
De base l&#039;équipe de Proxmox vous incite à prendre un abonnement pour profiter des mise à jours et fonctionnalités nécessaires dans un datacenter. &lt;br /&gt;
&lt;br /&gt;
[[Fichier:proxmox subscribe message.jpg|500px|centré]]&lt;br /&gt;
&lt;br /&gt;
Si comme moi, vous utilisez Proxmox dans le cadre d&#039;un homelab, pas besoin de payer, la version &#039;&#039;basic&#039;&#039; est largement suffisante.&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|align=left|&lt;br /&gt;
Cliquez sur l&#039;icône de votre serveur dans la barre à gauche&lt;br /&gt;
|width=10px|&lt;br /&gt;
|align=left|&lt;br /&gt;
Puis sur &#039;&#039;repositories&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox server menu left.jpg|350px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox repositories menu.jpg|150px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
On va dans un premier temps retirez les dépôts &#039;&#039;entreprise&#039;&#039; de Proxmox. Dès que vous voyez &#039;&#039;entreprise&#039;&#039; ou &#039;&#039;pve-entreprise&#039;&#039; dans la colonne &#039;&#039;Components&#039;&#039;, il y a de grande chance que le dépôt nécessite un abonnement.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proxmox repository remove.jpg|900px|centré]]&lt;br /&gt;
&lt;br /&gt;
* cliquez sur le dépôt &#039;&#039;ceph-squid&#039;&#039; puis sur le bouton &#039;&#039;disable&#039;&#039;&lt;br /&gt;
* cliquez sur le dépôt &#039;&#039;ceph-squid&#039;&#039; puis sur le bouton &#039;&#039;disable&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Une grosse croix rouge qui fait peur apparaît&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proxmox repository red corss.jpg|600px|centré]]&lt;br /&gt;
&lt;br /&gt;
Pas de panique, nous allons ajouter le dépôt gratuit pour avoir quand même quelques mise à jours.&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|align=left|&lt;br /&gt;
Cliquez sur &#039;&#039;add&#039;&#039;&lt;br /&gt;
|width=10px|&lt;br /&gt;
|align=left|&lt;br /&gt;
Puis sur &#039;&#039;No-Subscription&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox repository add.jpg|250px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox repositories no-subscription.jpg|500px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Ouf, la méchante croix rouge à disparue :)&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proxmox repositories no-subscription warning.jpg|500px|centré]]&lt;br /&gt;
&lt;br /&gt;
= Mise à jour =&lt;br /&gt;
&lt;br /&gt;
Pour rappel, le serveur que nous allons mettre à jour vient d&#039;être installé, et n&#039;est donc pas encore en utilisation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=color:red&amp;gt;Si vous avez des serveur en production, qui sont utilisés par des clients ou dans le cadre de processus internes à votre entreprise, s&#039;il vous plaît, ne mettez jamais, JAMAIS, jamais à jour ces serveurs.&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous n&#039;avez aucune idée des impacts sur les versions des logiciels et vous risquez, en mettant à jour, de créer une incompatibilité et de faire tomber en panne des logiciels ou applications qui fonctionnaient parfaitement.&lt;br /&gt;
&lt;br /&gt;
Les seules mise à jour que l&#039;on s&#039;autorise en production sont celles de sécurité qui servent à &#039;&#039;patcher&#039;&#039; une vulnérabilité. Et là encore, assurez-vous bien que rien ne va &#039;&#039;exploser&#039;&#039;. Si c&#039;est une machine virtuelle ou un conteneur, faites un snapshot ou une copie avant de procéder à la modification... surtout si c&#039;est un vendredi à 17h 😢&lt;br /&gt;
&lt;br /&gt;
Bon, vous êtes prévenu !&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|align=left|&lt;br /&gt;
Remontez d&#039;un cran sur le bouton &#039;&#039;Updates&#039;&#039;&lt;br /&gt;
|width=10px|&lt;br /&gt;
|align=left|&lt;br /&gt;
Puis cliquez sur &#039;&#039;Refresh&#039;&#039; pour mettre à jour la liste des paquetages disponibles&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox update button.jpg|150px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox update refresh.jpg|100px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|align=left|&lt;br /&gt;
Quand vous êtes prêt, cliquez sur &#039;&#039;Upgrade&#039;&#039;&lt;br /&gt;
|width=10px|&lt;br /&gt;
|align=left|&lt;br /&gt;
une fenêtre et démarrer le processus de mise à jour&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox upgrade button.jpg|150px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox update upgrade.jpg|600px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Suppression du message d&#039;abonnement =&lt;br /&gt;
Maintenant que les dépôt sont configuré et les mises à jour faites, on va désactiver ce message qui apparaît à chaque connexion au portail web de Proxmox.&lt;br /&gt;
[[Fichier:proxmox subscribe message.jpg|500px|centré]]&lt;br /&gt;
&lt;br /&gt;
Pour cela nous allons utiliser l&#039;activateur de &#039;&#039;Jamesits&#039;&#039; disponible sur son [https://github.com/Jamesits/pve-fake-subscription GitHub]&lt;br /&gt;
&lt;br /&gt;
Dans le menu de gauche, cliquez sur l’icône de votre serveur puis sur Shell&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox server menu left.jpg|350px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
&amp;amp;rarr;&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox shell button.jpg|200px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Une fois dans le terminal nous allons utiliser la commande &#039;&#039;wget&#039;&#039; pour télécharger le paquetage sur la machine:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# wget https://github.com/Jamesits/pve-fake-subscription/releases/download/v0.0.11/pve-fake-subscription_0.0.11+git-1_all.deb&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le lien précédent est à récupérer sur la page de téléchargement du projet, assurer-vous d&#039;y faire un tour pour vous assurer qu&#039;il est toujours bon.&lt;br /&gt;
&lt;br /&gt;
Il ne reste plus qu&#039;a l&#039;installer :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# dpkg -i pve-fake-subscription_0.0.11+git-1_all.deb&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il est recommandé de bloquer le site de vérification des clés en mettant une entrée factice dans le fichier &#039;&#039;hosts&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# echo &amp;quot;127.0.0.1 shop.maurer-it.com&amp;quot; &amp;gt; /etc/hosts&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous pouvez vérifier que cela fonctionne en faisant un ping:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
root@pve-tuto:~# ping shop.maurer-it.com&lt;br /&gt;
PING shop.maurer-it.com (127.0.0.1) 56(84) bytes of data.&lt;br /&gt;
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=1 ttl=64 time=0.014 ms&lt;br /&gt;
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=2 ttl=64 time=0.010 ms&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier que le message à bien disparu, il vous suffit de vous déconnecter puis reconnecter !&lt;br /&gt;
&lt;br /&gt;
= Nommage des cartes réseaux =&lt;br /&gt;
&lt;br /&gt;
Lorsque vous ajoutez / retirez une carte sur un port PCI, les identifiants sont redistribués et cela va affecter le nom des cartes réseaux. Si la carte que vous utilisez pour vous connecter à votre serveur Proxmox (généralement sur le &#039;&#039;vmbr0&#039;&#039;) change de nom, vous perdez la connexion à votre serveur... Pas très pratique !&lt;br /&gt;
&lt;br /&gt;
Si vous avez une version supérieur à 9.2 et que vous avez suivie le tutoriel pour [[Proxmox_install | installer Proxmox]] vous avez déjà fixé le nom de votre carte de management, mais qu&#039;en est-il des autres ? Vous l&#039;aurez compris, il faut absolument fixer le noms des cartes pour éviter les surprises !&lt;br /&gt;
&lt;br /&gt;
Une fois vos [[Identify_your_nic | carte identifiées]], il ne vous reste plus qu&#039;à définir leur nom et pour cela je vous conseil d&#039;utiliser leur rôle:&lt;br /&gt;
* une carte connectée à une DMZ &amp;amp;rarr; dmz&lt;br /&gt;
* une carte connectée à un LAN &amp;amp;rarr; lan&lt;br /&gt;
* une carte connectée à une box &amp;amp;rarr; wan&lt;br /&gt;
&lt;br /&gt;
Si vous avez plusieurs cartes par rôle, utilisez des numéros: &#039;&#039;dmz0&#039;&#039;, &#039;&#039;dmz1&#039;&#039;, ...&lt;br /&gt;
&lt;br /&gt;
Pour fixer le nom on va suivre [[Ifcfg-ethX#Que_faire_si_ma_carte_n&#039;a_pas_le_bon_numéro_?? | le tutoriel sur udev]] et d&#039;abord identifier l&#039;adresse MAC de notre carte:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ip a&lt;br /&gt;
1: lo: &amp;lt;LOOPBACK,UP,LOWER_UP&amp;gt; mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000&lt;br /&gt;
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00&lt;br /&gt;
    inet 127.0.0.1/8 scope host lo&lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
    inet6 ::1/128 scope host noprefixroute &lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
2: enp0s0f0: &amp;lt;BROADCAST,MULTICAST&amp;gt; mtu 1500 qdisc noop state DOWN group default qlen 1000&lt;br /&gt;
    link/ether 24:12:4d:01:49:20 brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
3: enp0s0f1: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc mq master vmbr0 state UP group default qlen 1000&lt;br /&gt;
    link/ether 24:12:4d:01:49:21 brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
    altname enp3s0&lt;br /&gt;
4: vmbr0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc noqueue state UP group default qlen 1000&lt;br /&gt;
    link/ether 24:8a:07:f7:ce:9b brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
    inet 192.168.4.240/24 scope global vmbr0&lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
    inet6 fe80::268a:7ff:fef7:ce9b/64 scope link &lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On a donc:&lt;br /&gt;
* enp0s0f1 en management avec l&#039;adresse 24:12:4d:01:49:21&lt;br /&gt;
* enp0s0f1 connecté à une DMZ avec l&#039;adresse 24:12:4d:01:49:20&lt;br /&gt;
&lt;br /&gt;
Il ne nous reste plus qu&#039;a créez le fichier &#039;&#039;/etc/udev/rules.d/70-persistent-net.rules&#039;&#039; avec le contenu suivant:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# Carte Intel SFP+ management &lt;br /&gt;
SUBSYSTEM==&amp;quot;net&amp;quot;, ACTION==&amp;quot;add&amp;quot;, DRIVERS==&amp;quot;?*&amp;quot;, ATTR{address}==&amp;quot;24:12:4d:01:49:21&amp;quot;, ATTR{type}==&amp;quot;1&amp;quot;, KERNEL==&amp;quot;eth*&amp;quot;, NAME=&amp;quot;mgmt&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Carte Intel SFP+ DMZ&lt;br /&gt;
SUBSYSTEM==&amp;quot;net&amp;quot;, ACTION==&amp;quot;add&amp;quot;, DRIVERS==&amp;quot;?*&amp;quot;, ATTR{address}==&amp;quot;24:12:4d:01:49:21&amp;quot;, ATTR{type}==&amp;quot;1&amp;quot;, KERNEL==&amp;quot;eth*&amp;quot;, NAME=&amp;quot;dmz&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Si vous êtes à distance, n&#039;oubliez pas de modifier votre fichier &#039;&#039;/etc/network/interfaces&#039;&#039; avant de redémarrer:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
iface mgmt inet manual&lt;br /&gt;
iface dmz inet manual&lt;br /&gt;
&lt;br /&gt;
auto vmbr0&lt;br /&gt;
iface vmbr0 inet static&lt;br /&gt;
	address 192.168.1.1/24&lt;br /&gt;
	gateway 192.168.1.254&lt;br /&gt;
	bridge-ports mgmt&lt;br /&gt;
	bridge-stp off&lt;br /&gt;
	bridge-fd 0&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Proxmox_first_start&amp;diff=4385</id>
		<title>Proxmox first start</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Proxmox_first_start&amp;diff=4385"/>
		<updated>2026-06-30T14:17:44Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Suppression du message d&amp;#039;abonnement */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
&lt;br /&gt;
Maintenant que votre serveur Proxmox est installé, nous allons effectuer quelques opérations de configuration de bases comme :&lt;br /&gt;
* la modification des dépôts&lt;br /&gt;
* la mise à jour&lt;br /&gt;
* la suppression du message d&#039;abonnement&lt;br /&gt;
* le nommage des cartes réseaux&lt;br /&gt;
&lt;br /&gt;
= Modification des dépôts =&lt;br /&gt;
De base l&#039;équipe de Proxmox vous incite à prendre un abonnement pour profiter des mise à jours et fonctionnalités nécessaires dans un datacenter. &lt;br /&gt;
&lt;br /&gt;
[[Fichier:proxmox subscribe message.jpg|500px|centré]]&lt;br /&gt;
&lt;br /&gt;
Si comme moi, vous utilisez Proxmox dans le cadre d&#039;un homelab, pas besoin de payer, la version &#039;&#039;basic&#039;&#039; est largement suffisante.&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|align=left|&lt;br /&gt;
Cliquez sur l&#039;icône de votre serveur dans la barre à gauche&lt;br /&gt;
|width=10px|&lt;br /&gt;
|align=left|&lt;br /&gt;
Puis sur &#039;&#039;repositories&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox server menu left.jpg|350px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox repositories menu.jpg|150px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
On va dans un premier temps retirez les dépôts &#039;&#039;entreprise&#039;&#039; de Proxmox. Dès que vous voyez &#039;&#039;entreprise&#039;&#039; ou &#039;&#039;pve-entreprise&#039;&#039; dans la colonne &#039;&#039;Components&#039;&#039;, il y a de grande chance que le dépôt nécessite un abonnement.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proxmox repository remove.jpg|900px|centré]]&lt;br /&gt;
&lt;br /&gt;
* cliquez sur le dépôt &#039;&#039;ceph-squid&#039;&#039; puis sur le bouton &#039;&#039;disable&#039;&#039;&lt;br /&gt;
* cliquez sur le dépôt &#039;&#039;ceph-squid&#039;&#039; puis sur le bouton &#039;&#039;disable&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Une grosse croix rouge qui fait peur apparaît&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proxmox repository red corss.jpg|600px|centré]]&lt;br /&gt;
&lt;br /&gt;
Pas de panique, nous allons ajouter le dépôt gratuit pour avoir quand même quelques mise à jours.&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|align=left|&lt;br /&gt;
Cliquez sur &#039;&#039;add&#039;&#039;&lt;br /&gt;
|width=10px|&lt;br /&gt;
|align=left|&lt;br /&gt;
Puis sur &#039;&#039;No-Subscription&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox repository add.jpg|250px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox repositories no-subscription.jpg|500px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Ouf, la méchante croix rouge à disparue :)&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proxmox repositories no-subscription warning.jpg|500px|centré]]&lt;br /&gt;
&lt;br /&gt;
= Mise à jour =&lt;br /&gt;
&lt;br /&gt;
Pour rappel, le serveur que nous allons mettre à jour vient d&#039;être installé, et n&#039;est donc pas encore en utilisation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=color:red&amp;gt;Si vous avez des serveur en production, qui sont utilisés par des clients ou dans le cadre de processus internes à votre entreprise, s&#039;il vous plaît, ne mettez jamais, JAMAIS, jamais à jour ces serveurs.&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous n&#039;avez aucune idée des impacts sur les versions des logiciels et vous risquez, en mettant à jour, de créer une incompatibilité et de faire tomber en panne des logiciels ou applications qui fonctionnaient parfaitement.&lt;br /&gt;
&lt;br /&gt;
Les seules mise à jour que l&#039;on s&#039;autorise en production sont celles de sécurité qui servent à &#039;&#039;patcher&#039;&#039; une vulnérabilité. Et là encore, assurez-vous bien que rien ne va &#039;&#039;exploser&#039;&#039;. Si c&#039;est une machine virtuelle ou un conteneur, faites un snapshot ou une copie avant de procéder à la modification... surtout si c&#039;est un vendredi à 17h 😢&lt;br /&gt;
&lt;br /&gt;
Bon, vous êtes prévenu !&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|align=left|&lt;br /&gt;
Remontez d&#039;un cran sur le bouton &#039;&#039;Updates&#039;&#039;&lt;br /&gt;
|width=10px|&lt;br /&gt;
|align=left|&lt;br /&gt;
Puis cliquez sur &#039;&#039;Refresh&#039;&#039; pour mettre à jour la liste des paquetages disponibles&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox update button.jpg|150px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox update refresh.jpg|100px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|align=left|&lt;br /&gt;
Quand vous êtes prêt, cliquez sur &#039;&#039;Upgrade&#039;&#039;&lt;br /&gt;
|width=10px|&lt;br /&gt;
|align=left|&lt;br /&gt;
une fenêtre et démarrer le processus de mise à jour&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox upgrade button.jpg|150px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox update upgrade.jpg|600px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Suppression du message d&#039;abonnement =&lt;br /&gt;
Maintenant que les dépôt sont configuré et les mises à jour faites, on va désactiver ce message qui apparaît à chaque connexion au portail web de Proxmox.&lt;br /&gt;
[[Fichier:proxmox subscribe message.jpg|500px|centré]]&lt;br /&gt;
&lt;br /&gt;
Pour cela nous allons utiliser l&#039;activateur de &#039;&#039;Jamesits&#039;&#039; disponible sur son [https://github.com/Jamesits/pve-fake-subscription GitHub]&lt;br /&gt;
&lt;br /&gt;
Dans le menu de gauche, cliquez sur l’icône de votre serveur puis sur Shell&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox server menu left.jpg|350px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
&amp;amp;rarr;&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox shell button.jpg|200px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Une fois dans le terminal nous allons utiliser la commande &#039;&#039;wget&#039;&#039; pour télécharger le paquetage sur la machine:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# wget https://github.com/Jamesits/pve-fake-subscription/releases/download/v0.0.11/pve-fake-subscription_0.0.11+git-1_all.deb&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le lien précédent est à récupérer sur la page de téléchargement du projet, assurer-vous d&#039;y faire un tour pour vous assurer qu&#039;il est toujours bon.&lt;br /&gt;
&lt;br /&gt;
Il ne reste plus qu&#039;a l&#039;installer :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# dpkg -i pve-fake-subscription_0.0.11+git-1_all.deb&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il est recommandé de bloquer le site de vérification des clés en mettant une entrée factice dans le fichier &#039;&#039;hosts&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# echo &amp;quot;127.0.0.1 shop.maurer-it.com&amp;quot; &amp;gt; /etc/hosts&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous pouvez vérifier que cela fonctionne en faisant un ping:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
root@pve-tuto:~# ping shop.maurer-it.com&lt;br /&gt;
PING shop.maurer-it.com (127.0.0.1) 56(84) bytes of data.&lt;br /&gt;
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=1 ttl=64 time=0.014 ms&lt;br /&gt;
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=2 ttl=64 time=0.010 ms&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier que le message à bien disparu, il vous suffit de vous déconnecter puis reconnecter !&lt;br /&gt;
&lt;br /&gt;
= Nommage des cartes réseaux =&lt;br /&gt;
&lt;br /&gt;
Lorsque vous ajoutez / retirez une carte sur un port PCI, les identifiants sont redistribués et cela va affecter le nom des cartes réseaux. Si la carte que vous utilisez pour vous connecter à votre serveur Proxmox (généralement sur le &#039;&#039;vmbr0&#039;&#039;) change de nom, vous perdez la connexion à votre serveur... Pas très pratique !&lt;br /&gt;
&lt;br /&gt;
Si vous avez une version supérieur à 9.2 et que vous avez suivie le tutoriel pour [[Proxmox_install | installer Proxmox]] vous avez déjà fixé le nom de votre carte de management, mais qu&#039;en est-il des autres ? Vous l&#039;aurez compris, il faut absolument fixer le noms des cartes pour éviter les surprises !&lt;br /&gt;
&lt;br /&gt;
Une fois vos [[Identify_your_nic | carte identifiées]], il ne vous reste plus qu&#039;à définir leur nom et pour cela je vous conseil d&#039;utiliser leur rôle:&lt;br /&gt;
* une carte connectée à une DMZ &amp;amp;rarr; dmz&lt;br /&gt;
* une carte connectée à un LAN &amp;amp;rarr; lan&lt;br /&gt;
* une carte connectée à une box &amp;amp;rarr; wan&lt;br /&gt;
&lt;br /&gt;
Si vous avez plusieurs cartes par rôle, utilisez des numéros: &#039;&#039;dmz0&#039;&#039;, &#039;&#039;dmz1&#039;&#039;, ...&lt;br /&gt;
&lt;br /&gt;
Pour fixer le nom on va suivre [[Ifcfg-ethX#Que_faire_si_ma_carte_n&#039;a_pas_le_bon_numéro_?? | le tutoriel sur udev]] et d&#039;abord identifier l&#039;adresse MAC de notre carte:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ip a&lt;br /&gt;
1: lo: &amp;lt;LOOPBACK,UP,LOWER_UP&amp;gt; mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000&lt;br /&gt;
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00&lt;br /&gt;
    inet 127.0.0.1/8 scope host lo&lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
    inet6 ::1/128 scope host noprefixroute &lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
2: enp0s0f0: &amp;lt;BROADCAST,MULTICAST&amp;gt; mtu 1500 qdisc noop state DOWN group default qlen 1000&lt;br /&gt;
    link/ether 24:12:4d:01:49:20 brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
3: enp0s0f1: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc mq master vmbr0 state UP group default qlen 1000&lt;br /&gt;
    link/ether 24:12:4d:01:49:21 brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
    altname enp3s0&lt;br /&gt;
4: vmbr0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc noqueue state UP group default qlen 1000&lt;br /&gt;
    link/ether 24:8a:07:f7:ce:9b brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
    inet 192.168.4.240/24 scope global vmbr0&lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
    inet6 fe80::268a:7ff:fef7:ce9b/64 scope link &lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On a donc:&lt;br /&gt;
* enp0s0f1 en management avec l&#039;adresse 24:12:4d:01:49:21&lt;br /&gt;
* enp0s0f1 connecté à une DMZ avec l&#039;adresse 24:12:4d:01:49:20&lt;br /&gt;
&lt;br /&gt;
Il ne nous reste plus qu&#039;a créez le fichier &#039;&#039;/etc/udev/rules.d/70-persistent-net.rules&#039;&#039; avec le contenu suivant:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# Carte Intel SFP+ management &lt;br /&gt;
SUBSYSTEM==&amp;quot;net&amp;quot;, ACTION==&amp;quot;add&amp;quot;, DRIVERS==&amp;quot;?*&amp;quot;, ATTR{address}==&amp;quot;24:12:4d:01:49:21&amp;quot;, ATTR{type}==&amp;quot;1&amp;quot;, KERNEL==&amp;quot;eth*&amp;quot;, NAME=&amp;quot;mgmt&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Carte Intel SFP+ DMZ&lt;br /&gt;
SUBSYSTEM==&amp;quot;net&amp;quot;, ACTION==&amp;quot;add&amp;quot;, DRIVERS==&amp;quot;?*&amp;quot;, ATTR{address}==&amp;quot;24:12:4d:01:49:21&amp;quot;, ATTR{type}==&amp;quot;1&amp;quot;, KERNEL==&amp;quot;eth*&amp;quot;, NAME=&amp;quot;dmz&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Si vous êtes à distance, n&#039;oubliez pas de modifier votre fichier &#039;&#039;/etc/network/interfaces&#039;&#039; avant de redémarrer:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
iface mgmt inet manual&lt;br /&gt;
iface dmz inet manual&lt;br /&gt;
&lt;br /&gt;
auto vmbr0&lt;br /&gt;
iface vmbr0 inet static&lt;br /&gt;
	address 192.168.1.1/24&lt;br /&gt;
	gateway 192.168.1.254&lt;br /&gt;
	bridge-ports mgmt&lt;br /&gt;
	bridge-stp off&lt;br /&gt;
	bridge-fd 0&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Proxmox_first_start&amp;diff=4384</id>
		<title>Proxmox first start</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Proxmox_first_start&amp;diff=4384"/>
		<updated>2026-06-30T14:16:58Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Mise à jour */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
&lt;br /&gt;
Maintenant que votre serveur Proxmox est installé, nous allons effectuer quelques opérations de configuration de bases comme :&lt;br /&gt;
* la modification des dépôts&lt;br /&gt;
* la mise à jour&lt;br /&gt;
* la suppression du message d&#039;abonnement&lt;br /&gt;
* le nommage des cartes réseaux&lt;br /&gt;
&lt;br /&gt;
= Modification des dépôts =&lt;br /&gt;
De base l&#039;équipe de Proxmox vous incite à prendre un abonnement pour profiter des mise à jours et fonctionnalités nécessaires dans un datacenter. &lt;br /&gt;
&lt;br /&gt;
[[Fichier:proxmox subscribe message.jpg|500px|centré]]&lt;br /&gt;
&lt;br /&gt;
Si comme moi, vous utilisez Proxmox dans le cadre d&#039;un homelab, pas besoin de payer, la version &#039;&#039;basic&#039;&#039; est largement suffisante.&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|align=left|&lt;br /&gt;
Cliquez sur l&#039;icône de votre serveur dans la barre à gauche&lt;br /&gt;
|width=10px|&lt;br /&gt;
|align=left|&lt;br /&gt;
Puis sur &#039;&#039;repositories&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox server menu left.jpg|350px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox repositories menu.jpg|150px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
On va dans un premier temps retirez les dépôts &#039;&#039;entreprise&#039;&#039; de Proxmox. Dès que vous voyez &#039;&#039;entreprise&#039;&#039; ou &#039;&#039;pve-entreprise&#039;&#039; dans la colonne &#039;&#039;Components&#039;&#039;, il y a de grande chance que le dépôt nécessite un abonnement.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proxmox repository remove.jpg|900px|centré]]&lt;br /&gt;
&lt;br /&gt;
* cliquez sur le dépôt &#039;&#039;ceph-squid&#039;&#039; puis sur le bouton &#039;&#039;disable&#039;&#039;&lt;br /&gt;
* cliquez sur le dépôt &#039;&#039;ceph-squid&#039;&#039; puis sur le bouton &#039;&#039;disable&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Une grosse croix rouge qui fait peur apparaît&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proxmox repository red corss.jpg|600px|centré]]&lt;br /&gt;
&lt;br /&gt;
Pas de panique, nous allons ajouter le dépôt gratuit pour avoir quand même quelques mise à jours.&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|align=left|&lt;br /&gt;
Cliquez sur &#039;&#039;add&#039;&#039;&lt;br /&gt;
|width=10px|&lt;br /&gt;
|align=left|&lt;br /&gt;
Puis sur &#039;&#039;No-Subscription&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox repository add.jpg|250px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox repositories no-subscription.jpg|500px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Ouf, la méchante croix rouge à disparue :)&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proxmox repositories no-subscription warning.jpg|500px|centré]]&lt;br /&gt;
&lt;br /&gt;
= Mise à jour =&lt;br /&gt;
&lt;br /&gt;
Pour rappel, le serveur que nous allons mettre à jour vient d&#039;être installé, et n&#039;est donc pas encore en utilisation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=color:red&amp;gt;Si vous avez des serveur en production, qui sont utilisés par des clients ou dans le cadre de processus internes à votre entreprise, s&#039;il vous plaît, ne mettez jamais, JAMAIS, jamais à jour ces serveurs.&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous n&#039;avez aucune idée des impacts sur les versions des logiciels et vous risquez, en mettant à jour, de créer une incompatibilité et de faire tomber en panne des logiciels ou applications qui fonctionnaient parfaitement.&lt;br /&gt;
&lt;br /&gt;
Les seules mise à jour que l&#039;on s&#039;autorise en production sont celles de sécurité qui servent à &#039;&#039;patcher&#039;&#039; une vulnérabilité. Et là encore, assurez-vous bien que rien ne va &#039;&#039;exploser&#039;&#039;. Si c&#039;est une machine virtuelle ou un conteneur, faites un snapshot ou une copie avant de procéder à la modification... surtout si c&#039;est un vendredi à 17h 😢&lt;br /&gt;
&lt;br /&gt;
Bon, vous êtes prévenu !&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|align=left|&lt;br /&gt;
Remontez d&#039;un cran sur le bouton &#039;&#039;Updates&#039;&#039;&lt;br /&gt;
|width=10px|&lt;br /&gt;
|align=left|&lt;br /&gt;
Puis cliquez sur &#039;&#039;Refresh&#039;&#039; pour mettre à jour la liste des paquetages disponibles&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox update button.jpg|150px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox update refresh.jpg|100px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|align=left|&lt;br /&gt;
Quand vous êtes prêt, cliquez sur &#039;&#039;Upgrade&#039;&#039;&lt;br /&gt;
|width=10px|&lt;br /&gt;
|align=left|&lt;br /&gt;
une fenêtre et démarrer le processus de mise à jour&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox upgrade button.jpg|150px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox update upgrade.jpg|600px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Suppression du message d&#039;abonnement =&lt;br /&gt;
Maintenant que les dépôt sont configuré et les mises à jour faites, on va désactiver ce message qui apparaît à chaque connexion au portail web de Proxmox.&lt;br /&gt;
[[Fichier:proxmox subscribe message.jpg|500px|centré]]&lt;br /&gt;
&lt;br /&gt;
Pour cela nous allons utiliser l&#039;activateur de &#039;&#039;Jamesits&#039;&#039; disponible sur son [https://github.com/Jamesits/pve-fake-subscription GitHub]&lt;br /&gt;
&lt;br /&gt;
Dans le menu de gauche, cliquez sur l’icône de votre serveur puis sur Shell&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox server menu left.jpg|350px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
&amp;amp;rarr;&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox shell button.jpg|200px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Une fois dans le terminal nous allons utiliser la commande &#039;&#039;wget&#039;&#039; pour télécharger le paquetage sur la machine:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# wget https://github.com/Jamesits/pve-fake-subscription/releases/download/v0.0.11/pve-fake-subscription_0.0.11+git-1_all.deb&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le lien précédent est à récupérer sur la page de téléchargement du projet, assurer-vous d&#039;y faire un tour pour vous assurer que le lien est toujours bon.&lt;br /&gt;
&lt;br /&gt;
Il ne reste plus qu&#039;a l&#039;installer :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# dpkg -i pve-fake-subscription_0.0.11+git-1_all.deb&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il est recommandé de bloquer le site de vérification des clés en mettant une entrée factice dans le fichier &#039;&#039;hosts&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# echo &amp;quot;127.0.0.1 shop.maurer-it.com&amp;quot; &amp;gt; /etc/hosts&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous pouvez vérifier que cela fonctionne en faisant un ping:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
root@pve-tuto:~# ping shop.maurer-it.com&lt;br /&gt;
PING shop.maurer-it.com (127.0.0.1) 56(84) bytes of data.&lt;br /&gt;
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=1 ttl=64 time=0.014 ms&lt;br /&gt;
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=2 ttl=64 time=0.010 ms&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier que le message à bien disparu, il vous suffit de vous déconnecter puis reconnecter !&lt;br /&gt;
&lt;br /&gt;
= Nommage des cartes réseaux =&lt;br /&gt;
&lt;br /&gt;
Lorsque vous ajoutez / retirez une carte sur un port PCI, les identifiants sont redistribués et cela va affecter le nom des cartes réseaux. Si la carte que vous utilisez pour vous connecter à votre serveur Proxmox (généralement sur le &#039;&#039;vmbr0&#039;&#039;) change de nom, vous perdez la connexion à votre serveur... Pas très pratique !&lt;br /&gt;
&lt;br /&gt;
Si vous avez une version supérieur à 9.2 et que vous avez suivie le tutoriel pour [[Proxmox_install | installer Proxmox]] vous avez déjà fixé le nom de votre carte de management, mais qu&#039;en est-il des autres ? Vous l&#039;aurez compris, il faut absolument fixer le noms des cartes pour éviter les surprises !&lt;br /&gt;
&lt;br /&gt;
Une fois vos [[Identify_your_nic | carte identifiées]], il ne vous reste plus qu&#039;à définir leur nom et pour cela je vous conseil d&#039;utiliser leur rôle:&lt;br /&gt;
* une carte connectée à une DMZ &amp;amp;rarr; dmz&lt;br /&gt;
* une carte connectée à un LAN &amp;amp;rarr; lan&lt;br /&gt;
* une carte connectée à une box &amp;amp;rarr; wan&lt;br /&gt;
&lt;br /&gt;
Si vous avez plusieurs cartes par rôle, utilisez des numéros: &#039;&#039;dmz0&#039;&#039;, &#039;&#039;dmz1&#039;&#039;, ...&lt;br /&gt;
&lt;br /&gt;
Pour fixer le nom on va suivre [[Ifcfg-ethX#Que_faire_si_ma_carte_n&#039;a_pas_le_bon_numéro_?? | le tutoriel sur udev]] et d&#039;abord identifier l&#039;adresse MAC de notre carte:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ip a&lt;br /&gt;
1: lo: &amp;lt;LOOPBACK,UP,LOWER_UP&amp;gt; mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000&lt;br /&gt;
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00&lt;br /&gt;
    inet 127.0.0.1/8 scope host lo&lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
    inet6 ::1/128 scope host noprefixroute &lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
2: enp0s0f0: &amp;lt;BROADCAST,MULTICAST&amp;gt; mtu 1500 qdisc noop state DOWN group default qlen 1000&lt;br /&gt;
    link/ether 24:12:4d:01:49:20 brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
3: enp0s0f1: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc mq master vmbr0 state UP group default qlen 1000&lt;br /&gt;
    link/ether 24:12:4d:01:49:21 brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
    altname enp3s0&lt;br /&gt;
4: vmbr0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc noqueue state UP group default qlen 1000&lt;br /&gt;
    link/ether 24:8a:07:f7:ce:9b brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
    inet 192.168.4.240/24 scope global vmbr0&lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
    inet6 fe80::268a:7ff:fef7:ce9b/64 scope link &lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On a donc:&lt;br /&gt;
* enp0s0f1 en management avec l&#039;adresse 24:12:4d:01:49:21&lt;br /&gt;
* enp0s0f1 connecté à une DMZ avec l&#039;adresse 24:12:4d:01:49:20&lt;br /&gt;
&lt;br /&gt;
Il ne nous reste plus qu&#039;a créez le fichier &#039;&#039;/etc/udev/rules.d/70-persistent-net.rules&#039;&#039; avec le contenu suivant:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# Carte Intel SFP+ management &lt;br /&gt;
SUBSYSTEM==&amp;quot;net&amp;quot;, ACTION==&amp;quot;add&amp;quot;, DRIVERS==&amp;quot;?*&amp;quot;, ATTR{address}==&amp;quot;24:12:4d:01:49:21&amp;quot;, ATTR{type}==&amp;quot;1&amp;quot;, KERNEL==&amp;quot;eth*&amp;quot;, NAME=&amp;quot;mgmt&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Carte Intel SFP+ DMZ&lt;br /&gt;
SUBSYSTEM==&amp;quot;net&amp;quot;, ACTION==&amp;quot;add&amp;quot;, DRIVERS==&amp;quot;?*&amp;quot;, ATTR{address}==&amp;quot;24:12:4d:01:49:21&amp;quot;, ATTR{type}==&amp;quot;1&amp;quot;, KERNEL==&amp;quot;eth*&amp;quot;, NAME=&amp;quot;dmz&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Si vous êtes à distance, n&#039;oubliez pas de modifier votre fichier &#039;&#039;/etc/network/interfaces&#039;&#039; avant de redémarrer:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
iface mgmt inet manual&lt;br /&gt;
iface dmz inet manual&lt;br /&gt;
&lt;br /&gt;
auto vmbr0&lt;br /&gt;
iface vmbr0 inet static&lt;br /&gt;
	address 192.168.1.1/24&lt;br /&gt;
	gateway 192.168.1.254&lt;br /&gt;
	bridge-ports mgmt&lt;br /&gt;
	bridge-stp off&lt;br /&gt;
	bridge-fd 0&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4383</id>
		<title>Proxmox fail2ban</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Proxmox_fail2ban&amp;diff=4383"/>
		<updated>2026-06-30T11:27:29Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
Proxmox utilise une interface web d&#039;administration qui utilise le port TCP 8006 et c&#039;est un vecteur possible d&#039;attaque par force brut. Nous allons donc &#039;&#039;dresser&#039;&#039; fail2ban pour agir en cas d&#039;attaque !&lt;br /&gt;
&lt;br /&gt;
Proxmox utilise Debian, nous allons principalement reproduire les étapes décrites dans le tutoriel de [[Sécuriser_un_service_avec_Fail2ban| Fail2ban pour Rocky]] et adapter à Debian.&lt;br /&gt;
&lt;br /&gt;
= Installation =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# apt -y install fail2ban&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Configuration =&lt;br /&gt;
Tout d&#039;abord il faut copier le fichier &#039;&#039;/etc/fail2ban/jail.conf&#039;&#039; en &#039;&#039;/etc/fail2ban/jail.local&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dans ce fichier, on va s&#039;intéresser aux variables suivantes:&lt;br /&gt;
*ignoreip : correspond à la suite d&#039;adresses IP qui ne se feront jamais bannir;&lt;br /&gt;
*maxretry : correspond au nombre d&#039;essais;&lt;br /&gt;
*findtime : correspond à la période pendant laquelle les essais vont incrémenter maxretry;&lt;br /&gt;
*bantime  : correspond au temps où l&#039;adresse IP ne peut pas se connecter.&lt;br /&gt;
&lt;br /&gt;
= Configuration de base =&lt;br /&gt;
== Choix de la punition ==&lt;br /&gt;
Il faut choisir quelque chose de cohérent (une punition suffisante) pour ne pas permettre de se faire cracker son mot de passe:&lt;br /&gt;
*maxretry = 3&lt;br /&gt;
*findtime = 86400 (correspond à 1 journée)&lt;br /&gt;
*bantime = 604800 (correspond à 1 semaine)&lt;br /&gt;
&lt;br /&gt;
Cela signifie que si une adresse IP se trompe 3 fois en 1 journée (86400s) elle se fait bannir pendant 1 semaine (604800s).&lt;br /&gt;
&lt;br /&gt;
Un rapide calcul permet de trouver le nombre maximal de tentatives durant une année:&lt;br /&gt;
&lt;br /&gt;
365 jours / 7 jours par semaine * 3 tentatives = 156 essais, ce qui reste raisonnable. &lt;br /&gt;
&lt;br /&gt;
Si le pirate possède un [http://fr.wikipedia.org/wiki/Botnet botnet], il faut bien sûr multiplier ce nombre par le nombre de machines dans le botnet...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Attention : fail2ban parcours les logs de connexion pour connaître le numéro de la tentative, ce qui a pour conséquence, si le &#039;&#039;findtime&#039;&#039; est grand, de prendre un certain temps...&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Jail pour SSH ==&lt;br /&gt;
Il suffit d&#039;ajouter la ligne &#039;&#039;enabled=true&#039;&#039; dans la section à activer !&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[sshd]&lt;br /&gt;
&lt;br /&gt;
# To use more aggressive sshd modes set filter parameter &amp;quot;mode&amp;quot; in jail.local:&lt;br /&gt;
# normal (default), ddos, extra or aggressive (combines all).&lt;br /&gt;
# See &amp;quot;tests/files/logs/sshd&amp;quot; or &amp;quot;filter.d/sshd.conf&amp;quot; for usage example and details.&lt;br /&gt;
#mode   = normal&lt;br /&gt;
enabled = true&lt;br /&gt;
port    = ssh&lt;br /&gt;
logpath = %(sshd_log)s&lt;br /&gt;
backend = %(sshd_backend)s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Configuration spécifique =&lt;br /&gt;
== Jail pour PVEPROXY ==&lt;br /&gt;
Pveproxy écoute sur le port 8006 et ne fonctionne pas exactement comme un serveur [[HTTPD | Apache httpd]] qui mettrait ces logs dans le fichier &#039;&#039;error_log&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Nous allons mettre cette configuration spécifique dans le fichier &#039;&#039;/etc/fail2ban/jail.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[proxmox]&lt;br /&gt;
enabled = true&lt;br /&gt;
port = https,http,8006&lt;br /&gt;
filter = proxmox&lt;br /&gt;
backend = systemd&lt;br /&gt;
maxretry = 3&lt;br /&gt;
findtime = 2d&lt;br /&gt;
bantime = 1h&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le backend utilisé est systemd, exactement comme si vous utilisiez la commande :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Filtre pour PVEPROXY ==&lt;br /&gt;
Il ne nous reste plus qu&#039;à spécifier le filtre &#039;&#039;proxmox&#039;&#039; dans le fichier &#039;&#039;/etc/fail2ban/filter.d/proxmox.conf&#039;&#039; :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Definition]&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=&amp;lt;HOST&amp;gt; user=.* msg=.*&lt;br /&gt;
ignoreregex =&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
= Tests =&lt;br /&gt;
Il faut maintenant tester le filtre et pour ça on peut utiliser un partage de connexion et réaliser le nombre d&#039;échecs spécifié par la directive &amp;quot;maxretry&amp;quot; (ici 3) :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client status proxmox&lt;br /&gt;
Status for the jail: proxmox&lt;br /&gt;
|- Filter&lt;br /&gt;
|  |- Currently failed:	0&lt;br /&gt;
|  |- Total failed:	3&lt;br /&gt;
|  `- Journal matches:	_SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
`- Actions&lt;br /&gt;
   |- Currently banned:	1&lt;br /&gt;
   |- Total banned:	1&lt;br /&gt;
   `- Banned IP list:	37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
On voit bien l&#039;IP 37.167.23.159 qui est bannie !&lt;br /&gt;
N&#039;oubliez pas de l&#039;ajouter à &#039;&#039;ignoreip&#039;&#039; dans le fichier &#039;&#039;jails.local&#039;&#039; ou de faire &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# fail2ban-client unban 37.167.23.159&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Démarrage et enregistrement dans le chargeur de démarrage =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl start fail2ban.service&lt;br /&gt;
# systemctl enable fail2ban.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Vous pouvez maintenant démarrer fail2ban&lt;br /&gt;
&lt;br /&gt;
= Proxification=&lt;br /&gt;
Lorsque votre serveur Proxmox se trouve derrière un reverse-proxy (Apache, Nginx, Traefik, ...), au niveau 3 OSI, l&#039;adresse IP du client est remplacée par celle du proxy et le serveur utilise l&#039;entêtes &#039;&#039;X-Forwarded-For&#039;&#039; ou &#039;&#039;X-Real-IP&#039;&#039; pour transporter l&#039;adresse du client &lt;br /&gt;
[[Fichier:Reverse proxy proxmox.png|700px|centré]]&lt;br /&gt;
Le problème est que la seule adresse que fail2ban va voir apparaître dans les logs est celle du reverse-proxy (&#039;&#039;192.168.4.100&#039;&#039;) :&lt;br /&gt;
[[Fichier:Reverse proxy ip logs.png|600px|centré]]&lt;br /&gt;
Même si le filtre &#039;&#039;fail2ban&#039;&#039; est configuré pour utiliser la commande &#039;&#039;journactl&#039;&#039; sur le démon &#039;&#039;pvedaemon&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
journalmatch = _SYSTEMD_UNIT=pvedaemon.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
les adresses viennent de pveproxy qui journalise tout dans &#039;&#039;/var/log/pveproxy/access.log&#039;&#039; et &#039;&#039;pvedaemon&#039;&#039; ne journalise que les échecs d&#039;authentification. &lt;br /&gt;
Il est donc plus simple de faire un &#039;&#039;tail&#039;&#039; ou un &#039;&#039;cat&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Que d&#039;utiliser &#039;&#039;journalctl&#039;&#039; pour voir les IPs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# journalctl -fu pvedaemon&lt;br /&gt;
Dec 14 10:43:01 labo unix_chkpwd[1326506]: password check failed for user (root)&lt;br /&gt;
Dec 14 10:43:01 labo IPCC.xs[1320783]: pam_unix(proxmox-ve-auth:auth): authentication failure; logname= uid=0 euid=0 tty= ruser= rhost=37.167.23.159  user=root&lt;br /&gt;
Dec 14 10:43:03 labo pvedaemon[1320783]: authentication failure; rhost=37.167.23.159 user=root@pam msg=Authentication failure&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Configuration de pveproxy ==&lt;br /&gt;
Si on veut voir l&#039;adresse du client, il faut dire au [https://fr.wikipedia.org/wiki/Daemon_(informatique)| démon] &#039;&#039;pveproxy&#039;&#039; d&#039;utiliser l&#039;une des deux entêtes précédentes ainsi que préciser l&#039;adresse du proxy. &lt;br /&gt;
&lt;br /&gt;
Préciser l&#039;adresse du proxy est essentiel pour que &#039;&#039;pveproxy&#039;&#039; n&#039;accepte de lire l&#039;adresse du client présente dans l&#039;entête &#039;&#039;&#039;uniquement&#039;&#039;&#039; si cela provient du proxy, qui est une machine de confiance. Le cas contraire, tout le monde pourrait ajouter une adresse IP dans l&#039;entête pour la faire bannir...&lt;br /&gt;
&lt;br /&gt;
Nous allons créer le fichier &#039;&#039;/etc/default/pveproxy&#039;&#039; avec les lignes suivantes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Forwarded-For&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_HEADER=&amp;quot;X-Real-IP&amp;quot;&lt;br /&gt;
PROXY_REAL_IP_ALLOW_FROM=&amp;quot;192.168.4.100&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il faut maintenant redémarrer &#039;&#039;pveproxy&#039;&#039; pour que les changements s&#039;appliquent. Si vous êtes connecté via l&#039;interface web, cela va vous déconnecter, le temps que le démon redémarre, il faudra ensuite certainement rafraîchir la page web.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# systemctl restart pveproxy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à vérifier dans les logs si les bonnes adresses s&#039;affichent:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Si jamais ce n&#039;est pas le cas, poursuivez avec la modification du fichier &#039;&#039;AnyEvent.pm&#039;&#039;&lt;br /&gt;
== Modification de AnyEvent.pm ==&lt;br /&gt;
=== Application de la modification ===&lt;br /&gt;
Au jour d&#039;aujourd&#039;hui (13/12/25) la proxification ne fonctionne plus et il faut apporter une modification dans le fichier &#039;&#039;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&#039;&#039; pour que les bonnes adresses apparaissent !&lt;br /&gt;
En fonction des versions cette modification peut avoir lieu soit ligne &#039;&#039;&#039;1504&#039;&#039;&#039;, soit ligne &#039;&#039;&#039;1554&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Il faut repérer la fonction suivante:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
sub authenticate_and_handle_request {&lt;br /&gt;
    my ($self, $reqstate) = @_;&lt;br /&gt;
&lt;br /&gt;
    my $request = $reqstate-&amp;gt;{request};&lt;br /&gt;
    my $method = $request-&amp;gt;method();&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
C&#039;est un peu plus loin qu&#039;il faut insérer le code :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 ### INSERTION ICI ###&lt;br /&gt;
&lt;br /&gt;
    if ($self-&amp;gt;{spiceproxy}) {&lt;br /&gt;
        my $connect_str = $request-&amp;gt;header(&#039;Host&#039;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il faut modifier l&#039;attribut &#039;&#039;peer_host&#039;&#039; de l&#039;objet &#039;&#039;reqstate&#039;&#039; si l&#039;une des deux entêtes est présente :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if ($request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
} elsif ($request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Double IPv4 ou préfixe IPv6 ===&lt;br /&gt;
Après redémarrage, cela permet de voir l&#039;adresse du client dans les logs :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# tail -f /var/log/pveproxy/access.log&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/ext-all.js?ver=7.0.0 HTTP/1.1&amp;quot; 200 683505&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/js/u2f-api.js HTTP/1.1&amp;quot; 200 4898&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/resources HTTP/1.1&amp;quot; 200 1226&lt;br /&gt;
::ffff:192.168.20.22 - - [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/cluster/tasks HTTP/1.1&amp;quot; 200 1090&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /proxmoxlib.js?ver=v5.0.4-t1754316706 HTTP/1.1&amp;quot; 200 157086&lt;br /&gt;
37.167.182.207, 37.167.182.207 - - [13/12/2025:18:48:18 +0100] &amp;quot;GET /pve2/ext6/theme-crisp/resources/theme-crisp-all_1.css HTTP/1.1&amp;quot; 200 32919&lt;br /&gt;
::ffff:192.168.20.22 - root@pam [14/12/2025:09:34:42 +0100] &amp;quot;GET /api2/json/nodes/labo/lxc/100/status/current HTTP/1.1&amp;quot; 200 523&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il nous reste un peu de nettoyage à faire, dans certains cas :&lt;br /&gt;
* l&#039;adresse apparaît non pas une fois mais deux, séparées par une virgule&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
37.167.182.207, 37.167.182.207&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* l&#039;adresse IPv4 (32 bits) est affichée dans sa représentation IPv6 (128 bits), avec le préfixe &#039;&#039;::ffff:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
::ffff:192.168.20.22&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On a deux possibilités pour faire le nettoyage :&lt;br /&gt;
*Soit on ajoute les lignes suivantes dans &#039;&#039;AnyEvent.pm&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=perl&amp;gt;&lt;br /&gt;
if (index($reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
   # Remove trailing ip &lt;br /&gt;
   my @fields = split /,/, $reqstate-&amp;gt;{peer_host};&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $fields[0];&lt;br /&gt;
}&lt;br /&gt;
if($reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
   # Remove IPv6 subnet for IPv4&lt;br /&gt;
   $reqstate-&amp;gt;{peer_host} = $1;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*Soit on modifie le filtre /etc/fail2ban/filter.d/proxmox.conf :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
failregex = pvedaemon\[.*authentication failure; rhost=.*:?&amp;lt;HOST&amp;gt;,? user=.* msg=.*&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Automatisation ===&lt;br /&gt;
On peut automatiser le processus précédent avec le script suivant, que l&#039;on peut créer dans /root/remoteip_fix.sh :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=bash&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
ANYEVENT_PATH=&amp;quot;/usr/share/perl5/PVE/APIServer/AnyEvent.pm&amp;quot;&lt;br /&gt;
ANYEVENT_REGEX=&#039;$self-&amp;gt;{spiceproxy}&#039;&lt;br /&gt;
TMP_FILE=&amp;quot;/tmp/AnyEvent.pm.tmp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if [ ! -f $ANYEVENT_PATH ]; then&lt;br /&gt;
  echo &amp;quot;$ANYEVENT_PATH does not exists !&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
if [ $(grep &#039;### BUGFIX REMOTE_IP FOR FAIL2BAN ###&#039; $ANYEVENT_PATH | wc -l) -eq 1 ]; then&lt;br /&gt;
  echo &amp;quot;AnyEvent.pm already patched !&amp;quot;&lt;br /&gt;
  exit 0&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
LINE_NUMBER_TOP=$(nl -ba $ANYEVENT_PATH | grep $ANYEVENT_REGEX | head -n 1 | awk -F &#039; &#039; &#039;{print $1}&#039;)&lt;br /&gt;
let LINE_NUMBER_TOP-=1&lt;br /&gt;
&lt;br /&gt;
if [ $LINE_NUMBER_TOP -lt 0 ]; then&lt;br /&gt;
  echo &amp;quot;Did not find the $ANYEVENT_REGEX expr in $ANYEVENT_PATH&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
echo -n &amp;quot;Applying bugfix: &amp;quot;&lt;br /&gt;
trap &amp;quot;rm -f $TMP_FILE&amp;quot; 0 1 2 5 13 15&lt;br /&gt;
head -n $LINE_NUMBER_TOP $ANYEVENT_PATH &amp;gt;$TMP_FILE&lt;br /&gt;
cat &amp;gt;&amp;gt;$TMP_FILE &amp;lt;&amp;lt;EOF&lt;br /&gt;
### BUGFIX REMOTE_IP FOR FAIL2BAN ###&lt;br /&gt;
    if (\$request-&amp;gt;header(&#039;X-Forwarded-For&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Forwarded-For&#039;);&lt;br /&gt;
    } elsif (\$request-&amp;gt;header(&#039;X-Real-IP&#039;)) {&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$request-&amp;gt;header(&#039;X-Real-IP&#039;);&lt;br /&gt;
    }&lt;br /&gt;
    if (index(\$reqstate-&amp;gt;{peer_host}, &#039;,&#039;) != -1) {&lt;br /&gt;
        my @fields = split /,/, \$reqstate-&amp;gt;{peer_host};&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$fields[0];&lt;br /&gt;
    }&lt;br /&gt;
    if(\$reqstate-&amp;gt;{peer_host} =~ /.*\:([\d]*\..*)/) {&lt;br /&gt;
        # Remove IPv6 subnet for IPv4&lt;br /&gt;
        \$reqstate-&amp;gt;{peer_host} = \$1;&lt;br /&gt;
    }&lt;br /&gt;
#####################################&lt;br /&gt;
EOF&lt;br /&gt;
echo &amp;quot;$ANYEVENT_MODIF&amp;quot; &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cp $ANYEVENT_PATH $ANYEVENT_PATH.ori&lt;br /&gt;
LINE_NUMBER_BOTTOM=$(cat $ANYEVENT_PATH | wc -l)&lt;br /&gt;
let LINE_NUMBER_BOTTOM-=LINE_NUMBER_TOP&lt;br /&gt;
tail -n $LINE_NUMBER_BOTTOM $ANYEVENT_PATH &amp;gt;&amp;gt;$TMP_FILE&lt;br /&gt;
cat $TMP_FILE &amp;gt;$ANYEVENT_PATH&lt;br /&gt;
rm -f $TMP_FILE&lt;br /&gt;
trap 0&lt;br /&gt;
echo &amp;quot;done.&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Il ne reste plus qu&#039;à le rendre exécutable et le lancer :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# chmod +x /root/remoteip_fix.sh&lt;br /&gt;
# /root/remoteip_fix.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Il ne faudra pas oublier de redémarrer &#039;&#039;pveproxy&#039;&#039; pour appliquer les changements !&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Proxmox_first_start&amp;diff=4382</id>
		<title>Proxmox first start</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Proxmox_first_start&amp;diff=4382"/>
		<updated>2026-06-30T11:27:05Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Nommage des cartes réseaux */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
&lt;br /&gt;
Maintenant que votre serveur Proxmox est installé, nous allons effectuer quelques opérations de configuration de bases comme :&lt;br /&gt;
* la modification des dépôts&lt;br /&gt;
* la mise à jour&lt;br /&gt;
* la suppression du message d&#039;abonnement&lt;br /&gt;
* le nommage des cartes réseaux&lt;br /&gt;
&lt;br /&gt;
= Modification des dépôts =&lt;br /&gt;
De base l&#039;équipe de Proxmox vous incite à prendre un abonnement pour profiter des mise à jours et fonctionnalités nécessaires dans un datacenter. &lt;br /&gt;
&lt;br /&gt;
[[Fichier:proxmox subscribe message.jpg|500px|centré]]&lt;br /&gt;
&lt;br /&gt;
Si comme moi, vous utilisez Proxmox dans le cadre d&#039;un homelab, pas besoin de payer, la version &#039;&#039;basic&#039;&#039; est largement suffisante.&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|align=left|&lt;br /&gt;
Cliquez sur l&#039;icône de votre serveur dans la barre à gauche&lt;br /&gt;
|width=10px|&lt;br /&gt;
|align=left|&lt;br /&gt;
Puis sur &#039;&#039;repositories&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox server menu left.jpg|350px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox repositories menu.jpg|150px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
On va dans un premier temps retirez les dépôts &#039;&#039;entreprise&#039;&#039; de Proxmox. Dès que vous voyez &#039;&#039;entreprise&#039;&#039; ou &#039;&#039;pve-entreprise&#039;&#039; dans la colonne &#039;&#039;Components&#039;&#039;, il y a de grande chance que le dépôt nécessite un abonnement.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proxmox repository remove.jpg|900px|centré]]&lt;br /&gt;
&lt;br /&gt;
* cliquez sur le dépôt &#039;&#039;ceph-squid&#039;&#039; puis sur le bouton &#039;&#039;disable&#039;&#039;&lt;br /&gt;
* cliquez sur le dépôt &#039;&#039;ceph-squid&#039;&#039; puis sur le bouton &#039;&#039;disable&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Une grosse croix rouge qui fait peur apparaît&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proxmox repository red corss.jpg|600px|centré]]&lt;br /&gt;
&lt;br /&gt;
Pas de panique, nous allons ajouter le dépôt gratuit pour avoir quand même quelques mise à jours.&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|align=left|&lt;br /&gt;
Cliquez sur &#039;&#039;add&#039;&#039;&lt;br /&gt;
|width=10px|&lt;br /&gt;
|align=left|&lt;br /&gt;
Puis sur &#039;&#039;No-Subscription&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox repository add.jpg|250px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox repositories no-subscription.jpg|500px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Ouf, la méchante croix rouge à disparue :)&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proxmox repositories no-subscription warning.jpg|500px|centré]]&lt;br /&gt;
&lt;br /&gt;
= Mise à jour =&lt;br /&gt;
&lt;br /&gt;
Pour rappel, le serveur que nous allons mettre à jour vient d&#039;être installé, et n&#039;est donc pas encore en utilisation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=color:red&amp;gt;Si vous avez des serveur en production, qui sont utilisés par des clients ou dans le cadre de processus internes à votre entreprise, s&#039;il vous plaît, ne mettez jamais, JAMAIS, jamais à jour ces serveurs.&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous n&#039;avez aucune idée des impacts sur les versions des logiciels et vous risquez, en mettant à jour, de créer une incompatibilité et de faire tomber en panne des logiciels ou applications qui fonctionnaient parfaitement.&lt;br /&gt;
&lt;br /&gt;
Les seules mise à jour que l&#039;on s&#039;autorise en production sont celles de sécurité qui servent à &#039;&#039;patcher&#039;&#039; une vulnérabilité. Et là encore, assurez-vous bien que rien ne va &#039;&#039;exploser&#039;&#039;. Si c&#039;est une machine virtuelle ou un conteneur, faites un snapshot ou une copie avant de procéder à la modification... surtout si c&#039;est un vendredi à 17h 😢&lt;br /&gt;
&lt;br /&gt;
Bon, vous êtes prévenu !&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|align=left|&lt;br /&gt;
Remontez d&#039;un cran sur le bouton &#039;&#039;Updates&#039;&#039;&lt;br /&gt;
|width=10px|&lt;br /&gt;
|align=left|&lt;br /&gt;
Puis cliquez sur &#039;&#039;Refresh&#039;&#039; pour mettre à jour la liste des paquetages disponibles&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox update button.jpg|150px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox update refresh.jpg|100px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|align=left|&lt;br /&gt;
Quand vous êtes prêt, cliquez sur &#039;&#039;Upgrade&#039;&#039;&lt;br /&gt;
|width=10px|&lt;br /&gt;
|align=left|&lt;br /&gt;
une fenêtre et démarrer le processus de mise à jour&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox upgrade button.jpg|100px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox update upgrade.jpg|500px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Suppression du message d&#039;abonnement =&lt;br /&gt;
Maintenant que les dépôt sont configuré et les mises à jour faites, on va désactiver ce message qui apparaît à chaque connexion au portail web de Proxmox.&lt;br /&gt;
[[Fichier:proxmox subscribe message.jpg|500px|centré]]&lt;br /&gt;
&lt;br /&gt;
Pour cela nous allons utiliser l&#039;activateur de &#039;&#039;Jamesits&#039;&#039; disponible sur son [https://github.com/Jamesits/pve-fake-subscription GitHub]&lt;br /&gt;
&lt;br /&gt;
Dans le menu de gauche, cliquez sur l’icône de votre serveur puis sur Shell&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox server menu left.jpg|350px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
&amp;amp;rarr;&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox shell button.jpg|200px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Une fois dans le terminal nous allons utiliser la commande &#039;&#039;wget&#039;&#039; pour télécharger le paquetage sur la machine:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# wget https://github.com/Jamesits/pve-fake-subscription/releases/download/v0.0.11/pve-fake-subscription_0.0.11+git-1_all.deb&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le lien précédent est à récupérer sur la page de téléchargement du projet, assurer-vous d&#039;y faire un tour pour vous assurer que le lien est toujours bon.&lt;br /&gt;
&lt;br /&gt;
Il ne reste plus qu&#039;a l&#039;installer :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# dpkg -i pve-fake-subscription_0.0.11+git-1_all.deb&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il est recommandé de bloquer le site de vérification des clés en mettant une entrée factice dans le fichier &#039;&#039;hosts&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# echo &amp;quot;127.0.0.1 shop.maurer-it.com&amp;quot; &amp;gt; /etc/hosts&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous pouvez vérifier que cela fonctionne en faisant un ping:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
root@pve-tuto:~# ping shop.maurer-it.com&lt;br /&gt;
PING shop.maurer-it.com (127.0.0.1) 56(84) bytes of data.&lt;br /&gt;
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=1 ttl=64 time=0.014 ms&lt;br /&gt;
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=2 ttl=64 time=0.010 ms&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier que le message à bien disparu, il vous suffit de vous déconnecter puis reconnecter !&lt;br /&gt;
&lt;br /&gt;
= Nommage des cartes réseaux =&lt;br /&gt;
&lt;br /&gt;
Lorsque vous ajoutez / retirez une carte sur un port PCI, les identifiants sont redistribués et cela va affecter le nom des cartes réseaux. Si la carte que vous utilisez pour vous connecter à votre serveur Proxmox (généralement sur le &#039;&#039;vmbr0&#039;&#039;) change de nom, vous perdez la connexion à votre serveur... Pas très pratique !&lt;br /&gt;
&lt;br /&gt;
Si vous avez une version supérieur à 9.2 et que vous avez suivie le tutoriel pour [[Proxmox_install | installer Proxmox]] vous avez déjà fixé le nom de votre carte de management, mais qu&#039;en est-il des autres ? Vous l&#039;aurez compris, il faut absolument fixer le noms des cartes pour éviter les surprises !&lt;br /&gt;
&lt;br /&gt;
Une fois vos [[Identify_your_nic | carte identifiées]], il ne vous reste plus qu&#039;à définir leur nom et pour cela je vous conseil d&#039;utiliser leur rôle:&lt;br /&gt;
* une carte connectée à une DMZ &amp;amp;rarr; dmz&lt;br /&gt;
* une carte connectée à un LAN &amp;amp;rarr; lan&lt;br /&gt;
* une carte connectée à une box &amp;amp;rarr; wan&lt;br /&gt;
&lt;br /&gt;
Si vous avez plusieurs cartes par rôle, utilisez des numéros: &#039;&#039;dmz0&#039;&#039;, &#039;&#039;dmz1&#039;&#039;, ...&lt;br /&gt;
&lt;br /&gt;
Pour fixer le nom on va suivre [[Ifcfg-ethX#Que_faire_si_ma_carte_n&#039;a_pas_le_bon_numéro_?? | le tutoriel sur udev]] et d&#039;abord identifier l&#039;adresse MAC de notre carte:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ip a&lt;br /&gt;
1: lo: &amp;lt;LOOPBACK,UP,LOWER_UP&amp;gt; mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000&lt;br /&gt;
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00&lt;br /&gt;
    inet 127.0.0.1/8 scope host lo&lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
    inet6 ::1/128 scope host noprefixroute &lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
2: enp0s0f0: &amp;lt;BROADCAST,MULTICAST&amp;gt; mtu 1500 qdisc noop state DOWN group default qlen 1000&lt;br /&gt;
    link/ether 24:12:4d:01:49:20 brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
3: enp0s0f1: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc mq master vmbr0 state UP group default qlen 1000&lt;br /&gt;
    link/ether 24:12:4d:01:49:21 brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
    altname enp3s0&lt;br /&gt;
4: vmbr0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc noqueue state UP group default qlen 1000&lt;br /&gt;
    link/ether 24:8a:07:f7:ce:9b brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
    inet 192.168.4.240/24 scope global vmbr0&lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
    inet6 fe80::268a:7ff:fef7:ce9b/64 scope link &lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On a donc:&lt;br /&gt;
* enp0s0f1 en management avec l&#039;adresse 24:12:4d:01:49:21&lt;br /&gt;
* enp0s0f1 connecté à une DMZ avec l&#039;adresse 24:12:4d:01:49:20&lt;br /&gt;
&lt;br /&gt;
Il ne nous reste plus qu&#039;a créez le fichier &#039;&#039;/etc/udev/rules.d/70-persistent-net.rules&#039;&#039; avec le contenu suivant:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# Carte Intel SFP+ management &lt;br /&gt;
SUBSYSTEM==&amp;quot;net&amp;quot;, ACTION==&amp;quot;add&amp;quot;, DRIVERS==&amp;quot;?*&amp;quot;, ATTR{address}==&amp;quot;24:12:4d:01:49:21&amp;quot;, ATTR{type}==&amp;quot;1&amp;quot;, KERNEL==&amp;quot;eth*&amp;quot;, NAME=&amp;quot;mgmt&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Carte Intel SFP+ DMZ&lt;br /&gt;
SUBSYSTEM==&amp;quot;net&amp;quot;, ACTION==&amp;quot;add&amp;quot;, DRIVERS==&amp;quot;?*&amp;quot;, ATTR{address}==&amp;quot;24:12:4d:01:49:21&amp;quot;, ATTR{type}==&amp;quot;1&amp;quot;, KERNEL==&amp;quot;eth*&amp;quot;, NAME=&amp;quot;dmz&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Si vous êtes à distance, n&#039;oubliez pas de modifier votre fichier &#039;&#039;/etc/network/interfaces&#039;&#039; avant de redémarrer:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
iface mgmt inet manual&lt;br /&gt;
iface dmz inet manual&lt;br /&gt;
&lt;br /&gt;
auto vmbr0&lt;br /&gt;
iface vmbr0 inet static&lt;br /&gt;
	address 192.168.1.1/24&lt;br /&gt;
	gateway 192.168.1.254&lt;br /&gt;
	bridge-ports mgmt&lt;br /&gt;
	bridge-stp off&lt;br /&gt;
	bridge-fd 0&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Proxmox_first_start&amp;diff=4381</id>
		<title>Proxmox first start</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Proxmox_first_start&amp;diff=4381"/>
		<updated>2026-06-30T11:09:47Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Connaître ces cartes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
&lt;br /&gt;
Maintenant que votre serveur Proxmox est installé, nous allons effectuer quelques opérations de configuration de bases comme :&lt;br /&gt;
* la modification des dépôts&lt;br /&gt;
* la mise à jour&lt;br /&gt;
* la suppression du message d&#039;abonnement&lt;br /&gt;
* le nommage des cartes réseaux&lt;br /&gt;
&lt;br /&gt;
= Modification des dépôts =&lt;br /&gt;
De base l&#039;équipe de Proxmox vous incite à prendre un abonnement pour profiter des mise à jours et fonctionnalités nécessaires dans un datacenter. &lt;br /&gt;
&lt;br /&gt;
[[Fichier:proxmox subscribe message.jpg|500px|centré]]&lt;br /&gt;
&lt;br /&gt;
Si comme moi, vous utilisez Proxmox dans le cadre d&#039;un homelab, pas besoin de payer, la version &#039;&#039;basic&#039;&#039; est largement suffisante.&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|align=left|&lt;br /&gt;
Cliquez sur l&#039;icône de votre serveur dans la barre à gauche&lt;br /&gt;
|width=10px|&lt;br /&gt;
|align=left|&lt;br /&gt;
Puis sur &#039;&#039;repositories&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox server menu left.jpg|350px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox repositories menu.jpg|150px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
On va dans un premier temps retirez les dépôts &#039;&#039;entreprise&#039;&#039; de Proxmox. Dès que vous voyez &#039;&#039;entreprise&#039;&#039; ou &#039;&#039;pve-entreprise&#039;&#039; dans la colonne &#039;&#039;Components&#039;&#039;, il y a de grande chance que le dépôt nécessite un abonnement.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proxmox repository remove.jpg|900px|centré]]&lt;br /&gt;
&lt;br /&gt;
* cliquez sur le dépôt &#039;&#039;ceph-squid&#039;&#039; puis sur le bouton &#039;&#039;disable&#039;&#039;&lt;br /&gt;
* cliquez sur le dépôt &#039;&#039;ceph-squid&#039;&#039; puis sur le bouton &#039;&#039;disable&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Une grosse croix rouge qui fait peur apparaît&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proxmox repository red corss.jpg|600px|centré]]&lt;br /&gt;
&lt;br /&gt;
Pas de panique, nous allons ajouter le dépôt gratuit pour avoir quand même quelques mise à jours.&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|align=left|&lt;br /&gt;
Cliquez sur &#039;&#039;add&#039;&#039;&lt;br /&gt;
|width=10px|&lt;br /&gt;
|align=left|&lt;br /&gt;
Puis sur &#039;&#039;No-Subscription&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox repository add.jpg|250px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox repositories no-subscription.jpg|500px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Ouf, la méchante croix rouge à disparue :)&lt;br /&gt;
&lt;br /&gt;
[[Fichier:proxmox repositories no-subscription warning.jpg|500px|centré]]&lt;br /&gt;
&lt;br /&gt;
= Mise à jour =&lt;br /&gt;
&lt;br /&gt;
Pour rappel, le serveur que nous allons mettre à jour vient d&#039;être installé, et n&#039;est donc pas encore en utilisation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=color:red&amp;gt;Si vous avez des serveur en production, qui sont utilisés par des clients ou dans le cadre de processus internes à votre entreprise, s&#039;il vous plaît, ne mettez jamais, JAMAIS, jamais à jour ces serveurs.&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous n&#039;avez aucune idée des impacts sur les versions des logiciels et vous risquez, en mettant à jour, de créer une incompatibilité et de faire tomber en panne des logiciels ou applications qui fonctionnaient parfaitement.&lt;br /&gt;
&lt;br /&gt;
Les seules mise à jour que l&#039;on s&#039;autorise en production sont celles de sécurité qui servent à &#039;&#039;patcher&#039;&#039; une vulnérabilité. Et là encore, assurez-vous bien que rien ne va &#039;&#039;exploser&#039;&#039;. Si c&#039;est une machine virtuelle ou un conteneur, faites un snapshot ou une copie avant de procéder à la modification... surtout si c&#039;est un vendredi à 17h 😢&lt;br /&gt;
&lt;br /&gt;
Bon, vous êtes prévenu !&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|align=left|&lt;br /&gt;
Remontez d&#039;un cran sur le bouton &#039;&#039;Updates&#039;&#039;&lt;br /&gt;
|width=10px|&lt;br /&gt;
|align=left|&lt;br /&gt;
Puis cliquez sur &#039;&#039;Refresh&#039;&#039; pour mettre à jour la liste des paquetages disponibles&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox update button.jpg|150px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox update refresh.jpg|100px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|align=left|&lt;br /&gt;
Quand vous êtes prêt, cliquez sur &#039;&#039;Upgrade&#039;&#039;&lt;br /&gt;
|width=10px|&lt;br /&gt;
|align=left|&lt;br /&gt;
une fenêtre et démarrer le processus de mise à jour&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox upgrade button.jpg|100px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox update upgrade.jpg|500px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Suppression du message d&#039;abonnement =&lt;br /&gt;
Maintenant que les dépôt sont configuré et les mises à jour faites, on va désactiver ce message qui apparaît à chaque connexion au portail web de Proxmox.&lt;br /&gt;
[[Fichier:proxmox subscribe message.jpg|500px|centré]]&lt;br /&gt;
&lt;br /&gt;
Pour cela nous allons utiliser l&#039;activateur de &#039;&#039;Jamesits&#039;&#039; disponible sur son [https://github.com/Jamesits/pve-fake-subscription GitHub]&lt;br /&gt;
&lt;br /&gt;
Dans le menu de gauche, cliquez sur l’icône de votre serveur puis sur Shell&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox server menu left.jpg|350px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
&amp;amp;rarr;&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:proxmox shell button.jpg|200px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Une fois dans le terminal nous allons utiliser la commande &#039;&#039;wget&#039;&#039; pour télécharger le paquetage sur la machine:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# wget https://github.com/Jamesits/pve-fake-subscription/releases/download/v0.0.11/pve-fake-subscription_0.0.11+git-1_all.deb&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le lien précédent est à récupérer sur la page de téléchargement du projet, assurer-vous d&#039;y faire un tour pour vous assurer que le lien est toujours bon.&lt;br /&gt;
&lt;br /&gt;
Il ne reste plus qu&#039;a l&#039;installer :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# dpkg -i pve-fake-subscription_0.0.11+git-1_all.deb&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il est recommandé de bloquer le site de vérification des clés en mettant une entrée factice dans le fichier &#039;&#039;hosts&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# echo &amp;quot;127.0.0.1 shop.maurer-it.com&amp;quot; &amp;gt; /etc/hosts&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous pouvez vérifier que cela fonctionne en faisant un ping:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
root@pve-tuto:~# ping shop.maurer-it.com&lt;br /&gt;
PING shop.maurer-it.com (127.0.0.1) 56(84) bytes of data.&lt;br /&gt;
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=1 ttl=64 time=0.014 ms&lt;br /&gt;
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=2 ttl=64 time=0.010 ms&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour vérifier que le message à bien disparu, il vous suffit de vous déconnecter puis reconnecter !&lt;br /&gt;
&lt;br /&gt;
= Nommage des cartes réseaux =&lt;br /&gt;
== Concepts ==&lt;br /&gt;
Les cartes réseau ont un nommage bien spécifique en fonction de leur nature et de leur emplacement.&lt;br /&gt;
&lt;br /&gt;
Les cartes Ethernet commence par &#039;&#039;en&#039;&#039;, les carte Wi-Fi par &#039;&#039;wl&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Les carte réseau intégrée à lare carte-mère, on une grande chance de continuer avec un &#039;&#039;o&#039;&#039; alors que les cartes sur des ports PCI portent un &#039;&#039;p&#039;&#039;. Seulement ce n&#039;est pas toujours vrai, il nous faut un moyen simple de pouvoir les identifier !&lt;br /&gt;
&lt;br /&gt;
== Connaître ces cartes ==&lt;br /&gt;
&lt;br /&gt;
Lorsque vous ajoutez / retirez une carte sur un port PCI, les identifiants sont redistribués et cela va affecter le nom des cartes réseaux.&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Identify_your_nic&amp;diff=4380</id>
		<title>Identify your nic</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Identify_your_nic&amp;diff=4380"/>
		<updated>2026-06-30T11:09:04Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Contrôle par l&amp;#039;état du lien */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
&lt;br /&gt;
Lorsque l&#039;on arrive sur une machine qui possède plusieurs cartes réseau, il est souvent difficile de faire le lien entre une carte logique (enp1s0, eno2, wl0, ...) et une carte physique et nous allons voir comment faire !&lt;br /&gt;
&lt;br /&gt;
= La logique =&lt;br /&gt;
&lt;br /&gt;
Les premières lettres correspondent au type de carte:&lt;br /&gt;
* en pour [https://fr.wikipedia.org/wiki/Ethernet Ethernet]&lt;br /&gt;
* wl pour [https://fr.wikipedia.org/wiki/Wi-Fi Wireless (Wi-Fi)]&lt;br /&gt;
* ib pour [https://fr.wikipedia.org/wiki/Bus_InfiniBand InfiniBand]&lt;br /&gt;
* sl pour [https://fr.wikipedia.org/wiki/Serial_Line_Internet_Protocol Serial Line IP]&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
Vient ensuite le type de connexion:&lt;br /&gt;
* &#039;&#039;o&#039;&#039; pour &#039;&#039;onboard&#039;&#039; ou intégré&lt;br /&gt;
* &#039;&#039;p&#039;&#039; pour &#039;&#039;pci&#039;&#039;, c&#039;est à dire une carte branché sur des [https://fr.wikipedia.org/wiki/PCI_Express lignes PCI] au processeur&lt;br /&gt;
&lt;br /&gt;
Dans le cas d&#039;une carte en PCI on poursuit avec le numéro du &#039;&#039;slot&#039;&#039; que l&#039;on peut assimiler au nombre de puces présente sur la carte.&lt;br /&gt;
Une carte possédant deux puces aura donc deux &#039;&#039;slot&#039;&#039; : &#039;&#039;s0&#039;&#039; et &#039;&#039;s1&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Et on termine avec la fonction que l&#039;on peut assimiler au nombre de ports par puce. Une puce possédant deux ports aura donc deux fonctions: &#039;&#039;f0&#039;&#039; et &#039;&#039;f1&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour résumer, les cartes intégrées possèdent des noms comme:&lt;br /&gt;
* &#039;&#039;eno0&#039;&#039;&lt;br /&gt;
* &#039;&#039;eno1&#039;&#039;&lt;br /&gt;
* ... &lt;br /&gt;
&lt;br /&gt;
Et les cartes en PCI des noms comme:&lt;br /&gt;
* &#039;&#039;enp0s0f1&#039;&#039;&lt;br /&gt;
* &#039;&#039;enp0s0f1&#039;&#039;&lt;br /&gt;
* &#039;&#039;enp1s0f0&#039;&#039;&lt;br /&gt;
* ...&lt;br /&gt;
= Connaître ces cartes =&lt;br /&gt;
&lt;br /&gt;
Pour démarrer le travail d&#039;identification, vous pouvez commencez par repérer le constructeur et / ou le modèle de puce utilisé, souvent mentionné:&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
Sur la boîte de votre carte mère...&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
ou bien dans son manuel...&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
ou dans l&#039;annonce si c&#039;est une carte PCI&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:motherboard box Z370.jpg|350px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:motherboard manual Z270.jpg|300px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:amazon mellanox connect-x3.jpg|400px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Identifiants PCI et prédictions =&lt;br /&gt;
&lt;br /&gt;
Il faut maintenant faire le parallèle avec les cartes afficher dans le terminal et pour ça nous allons utiliser la commande &#039;&#039;lspci&#039;&#039;:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# lspci | grep Ethernet&lt;br /&gt;
01:00.0 Ethernet controller: Mellanox Technologies MT27500 Family [ConnectX-3]&lt;br /&gt;
03:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8111/8168/8211/8411 PCI Express Gigabit Ethernet Controller (rev 15)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On voit que la carte Realtek RTL8111 (celle de la carte mère) possède l&#039;identifiant 03:00.0 et que la Mellanox l&#039;identifiant 01:00.0&lt;br /&gt;
&lt;br /&gt;
Il faut maintenant transposer ces identifiants en nom:&lt;br /&gt;
* le premier chiffre correspond a l&#039;identifiant PCI généré par le micrologiciel de la carte mère (p3 et p1)&lt;br /&gt;
* le deuxième correspond au &#039;&#039;slot&#039;&#039; (s0)&lt;br /&gt;
* le dernier à la fonction (f0)&lt;br /&gt;
&lt;br /&gt;
Un nom possible pour la carte Realtek pourrait être &#039;&#039;enp3s0f0&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Cependant, il est possible lorsque les cartes ne possèdent qu&#039;une fonction, d&#039;omettre celle-ci pour raccourcir le nom et notre carte pourrait donc s’appeler &#039;&#039;enp3s0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
On peut confirmer cela grâce à la commande &#039;&#039;ip&#039;&#039;:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ip a&lt;br /&gt;
1: lo: &amp;lt;LOOPBACK,UP,LOWER_UP&amp;gt; mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000&lt;br /&gt;
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00&lt;br /&gt;
    inet 127.0.0.1/8 scope host lo&lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
    inet6 ::1/128 scope host &lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
2: enp3s0: &amp;lt;NO-CARRIER,BROADCAST,MULTICAST,UP&amp;gt; mtu 1500 qdisc fq_codel state DOWN group default qlen 1000&lt;br /&gt;
    link/ether 30:9c:23:20:8c:dd brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
3: enp1s0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc mq state UP group default qlen 1000&lt;br /&gt;
    link/ether 24:8a:07:f7:bd:22 brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut en déduire que:&lt;br /&gt;
* la carte Realtek en gigabit possède l&#039;identifiant enp3s0 &lt;br /&gt;
* la carte Mellanox de 10 gigabit possède l&#039;identifiant enp1s0&lt;br /&gt;
&lt;br /&gt;
= Contrôle par le débit =&lt;br /&gt;
&lt;br /&gt;
Si vous avez toujours des doutes vous pouvez afficher le débit des cartes grâce à la commande &#039;&#039;ethtool&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
La Realtek aura un débit max de 1000&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
La Mellanox pourra monter à 10 Gigabit&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ethtool enp3s0&lt;br /&gt;
Settings for enp3s0:&lt;br /&gt;
	Supported ports: [ TP	 MII ]&lt;br /&gt;
	Supported link modes:   10baseT/Half 10baseT/Full&lt;br /&gt;
	                        100baseT/Half 100baseT/Full&lt;br /&gt;
	                        1000baseT/Full&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ethtool enp1s0&lt;br /&gt;
Settings for enp1s0:&lt;br /&gt;
	Supported ports: [ FIBRE ]&lt;br /&gt;
	Supported link modes:   1000baseX/Full&lt;br /&gt;
	                        10000baseCR/Full&lt;br /&gt;
	                        10000baseSR/Full&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Contrôle par l&#039;état du lien =&lt;br /&gt;
&lt;br /&gt;
Si vous possédez une carte avec plusieurs fonctions (ports), il vous reste à différencier les ports entres eux et pour ça nous allons utiliser l&#039;état des liens pour déterminer le numéro de chaque port.&lt;br /&gt;
&lt;br /&gt;
Commencez par déconnecter chaque prises sauf une pour que toutes les ports soient dans un état bas ou &#039;&#039;down&#039;&#039; sauf un qui sera &#039;&#039;up&#039;&#039;:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ip a&lt;br /&gt;
...&lt;br /&gt;
3: enp1s0f0: &amp;lt;NO-CARRIER,BROADCAST,MULTICAST,UP&amp;gt; mtu 1500 qdisc mq state DOWN group default qlen 1000&lt;br /&gt;
    link/ether 24:8a:07:f7:bd:20 brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
4: enp1s0f1: &amp;lt;BROADCAST,MULTICAST,UP&amp;gt; mtu 1500 qdisc mq state UP group default qlen 1000&lt;br /&gt;
    link/ether 24:8a:07:f7:bd:21 brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vous savez que le port connecté possède la fonction 1 (&#039;&#039;enp1s0f1&#039;&#039;) et celui débranché à la fonction 0 (&#039;&#039;enp1s0f0&#039;&#039;)&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Identify_your_nic&amp;diff=4379</id>
		<title>Identify your nic</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Identify_your_nic&amp;diff=4379"/>
		<updated>2026-06-30T11:04:32Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Contrôle par l&amp;#039;état du lien */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
&lt;br /&gt;
Lorsque l&#039;on arrive sur une machine qui possède plusieurs cartes réseau, il est souvent difficile de faire le lien entre une carte logique (enp1s0, eno2, wl0, ...) et une carte physique et nous allons voir comment faire !&lt;br /&gt;
&lt;br /&gt;
= La logique =&lt;br /&gt;
&lt;br /&gt;
Les premières lettres correspondent au type de carte:&lt;br /&gt;
* en pour [https://fr.wikipedia.org/wiki/Ethernet Ethernet]&lt;br /&gt;
* wl pour [https://fr.wikipedia.org/wiki/Wi-Fi Wireless (Wi-Fi)]&lt;br /&gt;
* ib pour [https://fr.wikipedia.org/wiki/Bus_InfiniBand InfiniBand]&lt;br /&gt;
* sl pour [https://fr.wikipedia.org/wiki/Serial_Line_Internet_Protocol Serial Line IP]&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
Vient ensuite le type de connexion:&lt;br /&gt;
* &#039;&#039;o&#039;&#039; pour &#039;&#039;onboard&#039;&#039; ou intégré&lt;br /&gt;
* &#039;&#039;p&#039;&#039; pour &#039;&#039;pci&#039;&#039;, c&#039;est à dire une carte branché sur des [https://fr.wikipedia.org/wiki/PCI_Express lignes PCI] au processeur&lt;br /&gt;
&lt;br /&gt;
Dans le cas d&#039;une carte en PCI on poursuit avec le numéro du &#039;&#039;slot&#039;&#039; que l&#039;on peut assimiler au nombre de puces présente sur la carte.&lt;br /&gt;
Une carte possédant deux puces aura donc deux &#039;&#039;slot&#039;&#039; : &#039;&#039;s0&#039;&#039; et &#039;&#039;s1&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Et on termine avec la fonction que l&#039;on peut assimiler au nombre de ports par puce. Une puce possédant deux ports aura donc deux fonctions: &#039;&#039;f0&#039;&#039; et &#039;&#039;f1&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour résumer, les cartes intégrées possèdent des noms comme:&lt;br /&gt;
* &#039;&#039;eno0&#039;&#039;&lt;br /&gt;
* &#039;&#039;eno1&#039;&#039;&lt;br /&gt;
* ... &lt;br /&gt;
&lt;br /&gt;
Et les cartes en PCI des noms comme:&lt;br /&gt;
* &#039;&#039;enp0s0f1&#039;&#039;&lt;br /&gt;
* &#039;&#039;enp0s0f1&#039;&#039;&lt;br /&gt;
* &#039;&#039;enp1s0f0&#039;&#039;&lt;br /&gt;
* ...&lt;br /&gt;
= Connaître ces cartes =&lt;br /&gt;
&lt;br /&gt;
Pour démarrer le travail d&#039;identification, vous pouvez commencez par repérer le constructeur et / ou le modèle de puce utilisé, souvent mentionné:&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
Sur la boîte de votre carte mère...&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
ou bien dans son manuel...&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
ou dans l&#039;annonce si c&#039;est une carte PCI&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:motherboard box Z370.jpg|350px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:motherboard manual Z270.jpg|300px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:amazon mellanox connect-x3.jpg|400px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Identifiants PCI et prédictions =&lt;br /&gt;
&lt;br /&gt;
Il faut maintenant faire le parallèle avec les cartes afficher dans le terminal et pour ça nous allons utiliser la commande &#039;&#039;lspci&#039;&#039;:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# lspci | grep Ethernet&lt;br /&gt;
01:00.0 Ethernet controller: Mellanox Technologies MT27500 Family [ConnectX-3]&lt;br /&gt;
03:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8111/8168/8211/8411 PCI Express Gigabit Ethernet Controller (rev 15)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On voit que la carte Realtek RTL8111 (celle de la carte mère) possède l&#039;identifiant 03:00.0 et que la Mellanox l&#039;identifiant 01:00.0&lt;br /&gt;
&lt;br /&gt;
Il faut maintenant transposer ces identifiants en nom:&lt;br /&gt;
* le premier chiffre correspond a l&#039;identifiant PCI généré par le micrologiciel de la carte mère (p3 et p1)&lt;br /&gt;
* le deuxième correspond au &#039;&#039;slot&#039;&#039; (s0)&lt;br /&gt;
* le dernier à la fonction (f0)&lt;br /&gt;
&lt;br /&gt;
Un nom possible pour la carte Realtek pourrait être &#039;&#039;enp3s0f0&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Cependant, il est possible lorsque les cartes ne possèdent qu&#039;une fonction, d&#039;omettre celle-ci pour raccourcir le nom et notre carte pourrait donc s’appeler &#039;&#039;enp3s0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
On peut confirmer cela grâce à la commande &#039;&#039;ip&#039;&#039;:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ip a&lt;br /&gt;
1: lo: &amp;lt;LOOPBACK,UP,LOWER_UP&amp;gt; mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000&lt;br /&gt;
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00&lt;br /&gt;
    inet 127.0.0.1/8 scope host lo&lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
    inet6 ::1/128 scope host &lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
2: enp3s0: &amp;lt;NO-CARRIER,BROADCAST,MULTICAST,UP&amp;gt; mtu 1500 qdisc fq_codel state DOWN group default qlen 1000&lt;br /&gt;
    link/ether 30:9c:23:20:8c:dd brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
3: enp1s0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc mq state UP group default qlen 1000&lt;br /&gt;
    link/ether 24:8a:07:f7:bd:22 brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut en déduire que:&lt;br /&gt;
* la carte Realtek en gigabit possède l&#039;identifiant enp3s0 &lt;br /&gt;
* la carte Mellanox de 10 gigabit possède l&#039;identifiant enp1s0&lt;br /&gt;
&lt;br /&gt;
= Contrôle par le débit =&lt;br /&gt;
&lt;br /&gt;
Si vous avez toujours des doutes vous pouvez afficher le débit des cartes grâce à la commande &#039;&#039;ethtool&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
La Realtek aura un débit max de 1000&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
La Mellanox pourra monter à 10 Gigabit&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ethtool enp3s0&lt;br /&gt;
Settings for enp3s0:&lt;br /&gt;
	Supported ports: [ TP	 MII ]&lt;br /&gt;
	Supported link modes:   10baseT/Half 10baseT/Full&lt;br /&gt;
	                        100baseT/Half 100baseT/Full&lt;br /&gt;
	                        1000baseT/Full&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ethtool enp1s0&lt;br /&gt;
Settings for enp1s0:&lt;br /&gt;
	Supported ports: [ FIBRE ]&lt;br /&gt;
	Supported link modes:   1000baseX/Full&lt;br /&gt;
	                        10000baseCR/Full&lt;br /&gt;
	                        10000baseSR/Full&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Contrôle par l&#039;état du lien =&lt;br /&gt;
&lt;br /&gt;
Si vous possédez une carte avec plusieurs fonctions (ports), il vous reste à différencier les ports entres eux et pour ça nous allons utiliser l&#039;état des liens pour déterminer le numéro de chaque port.&lt;br /&gt;
&lt;br /&gt;
Commencez par retirer chaque prises pour que toutes les cartes soient dans un état bas ou &#039;&#039;down&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
La &lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
La Mellanox pourra monter à 10 Gigabit&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ethtool enp3s0&lt;br /&gt;
Settings for enp3s0:&lt;br /&gt;
	Supported ports: [ TP	 MII ]&lt;br /&gt;
	Supported link modes:   10baseT/Half 10baseT/Full&lt;br /&gt;
	                        100baseT/Half 100baseT/Full&lt;br /&gt;
	                        1000baseT/Full&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ethtool enp1s0&lt;br /&gt;
Settings for enp1s0:&lt;br /&gt;
	Supported ports: [ FIBRE ]&lt;br /&gt;
	Supported link modes:   1000baseX/Full&lt;br /&gt;
	                        10000baseCR/Full&lt;br /&gt;
	                        10000baseSR/Full&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
On va&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Identify_your_nic&amp;diff=4378</id>
		<title>Identify your nic</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Identify_your_nic&amp;diff=4378"/>
		<updated>2026-06-30T11:01:40Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Identifiants PCI et prédictions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
&lt;br /&gt;
Lorsque l&#039;on arrive sur une machine qui possède plusieurs cartes réseau, il est souvent difficile de faire le lien entre une carte logique (enp1s0, eno2, wl0, ...) et une carte physique et nous allons voir comment faire !&lt;br /&gt;
&lt;br /&gt;
= La logique =&lt;br /&gt;
&lt;br /&gt;
Les premières lettres correspondent au type de carte:&lt;br /&gt;
* en pour [https://fr.wikipedia.org/wiki/Ethernet Ethernet]&lt;br /&gt;
* wl pour [https://fr.wikipedia.org/wiki/Wi-Fi Wireless (Wi-Fi)]&lt;br /&gt;
* ib pour [https://fr.wikipedia.org/wiki/Bus_InfiniBand InfiniBand]&lt;br /&gt;
* sl pour [https://fr.wikipedia.org/wiki/Serial_Line_Internet_Protocol Serial Line IP]&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
Vient ensuite le type de connexion:&lt;br /&gt;
* &#039;&#039;o&#039;&#039; pour &#039;&#039;onboard&#039;&#039; ou intégré&lt;br /&gt;
* &#039;&#039;p&#039;&#039; pour &#039;&#039;pci&#039;&#039;, c&#039;est à dire une carte branché sur des [https://fr.wikipedia.org/wiki/PCI_Express lignes PCI] au processeur&lt;br /&gt;
&lt;br /&gt;
Dans le cas d&#039;une carte en PCI on poursuit avec le numéro du &#039;&#039;slot&#039;&#039; que l&#039;on peut assimiler au nombre de puces présente sur la carte.&lt;br /&gt;
Une carte possédant deux puces aura donc deux &#039;&#039;slot&#039;&#039; : &#039;&#039;s0&#039;&#039; et &#039;&#039;s1&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Et on termine avec la fonction que l&#039;on peut assimiler au nombre de ports par puce. Une puce possédant deux ports aura donc deux fonctions: &#039;&#039;f0&#039;&#039; et &#039;&#039;f1&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour résumer, les cartes intégrées possèdent des noms comme:&lt;br /&gt;
* &#039;&#039;eno0&#039;&#039;&lt;br /&gt;
* &#039;&#039;eno1&#039;&#039;&lt;br /&gt;
* ... &lt;br /&gt;
&lt;br /&gt;
Et les cartes en PCI des noms comme:&lt;br /&gt;
* &#039;&#039;enp0s0f1&#039;&#039;&lt;br /&gt;
* &#039;&#039;enp0s0f1&#039;&#039;&lt;br /&gt;
* &#039;&#039;enp1s0f0&#039;&#039;&lt;br /&gt;
* ...&lt;br /&gt;
= Connaître ces cartes =&lt;br /&gt;
&lt;br /&gt;
Pour démarrer le travail d&#039;identification, vous pouvez commencez par repérer le constructeur et / ou le modèle de puce utilisé, souvent mentionné:&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
Sur la boîte de votre carte mère...&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
ou bien dans son manuel...&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
ou dans l&#039;annonce si c&#039;est une carte PCI&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:motherboard box Z370.jpg|350px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:motherboard manual Z270.jpg|300px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:amazon mellanox connect-x3.jpg|400px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Identifiants PCI et prédictions =&lt;br /&gt;
&lt;br /&gt;
Il faut maintenant faire le parallèle avec les cartes afficher dans le terminal et pour ça nous allons utiliser la commande &#039;&#039;lspci&#039;&#039;:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# lspci | grep Ethernet&lt;br /&gt;
01:00.0 Ethernet controller: Mellanox Technologies MT27500 Family [ConnectX-3]&lt;br /&gt;
03:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8111/8168/8211/8411 PCI Express Gigabit Ethernet Controller (rev 15)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On voit que la carte Realtek RTL8111 (celle de la carte mère) possède l&#039;identifiant 03:00.0 et que la Mellanox l&#039;identifiant 01:00.0&lt;br /&gt;
&lt;br /&gt;
Il faut maintenant transposer ces identifiants en nom:&lt;br /&gt;
* le premier chiffre correspond a l&#039;identifiant PCI généré par le micrologiciel de la carte mère (p3 et p1)&lt;br /&gt;
* le deuxième correspond au &#039;&#039;slot&#039;&#039; (s0)&lt;br /&gt;
* le dernier à la fonction (f0)&lt;br /&gt;
&lt;br /&gt;
Un nom possible pour la carte Realtek pourrait être &#039;&#039;enp3s0f0&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Cependant, il est possible lorsque les cartes ne possèdent qu&#039;une fonction, d&#039;omettre celle-ci pour raccourcir le nom et notre carte pourrait donc s’appeler &#039;&#039;enp3s0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
On peut confirmer cela grâce à la commande &#039;&#039;ip&#039;&#039;:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ip a&lt;br /&gt;
1: lo: &amp;lt;LOOPBACK,UP,LOWER_UP&amp;gt; mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000&lt;br /&gt;
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00&lt;br /&gt;
    inet 127.0.0.1/8 scope host lo&lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
    inet6 ::1/128 scope host &lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
2: enp3s0: &amp;lt;NO-CARRIER,BROADCAST,MULTICAST,UP&amp;gt; mtu 1500 qdisc fq_codel state DOWN group default qlen 1000&lt;br /&gt;
    link/ether 30:9c:23:20:8c:dd brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
3: enp1s0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc mq state UP group default qlen 1000&lt;br /&gt;
    link/ether 24:8a:07:f7:bd:22 brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut en déduire que:&lt;br /&gt;
* la carte Realtek en gigabit possède l&#039;identifiant enp3s0 &lt;br /&gt;
* la carte Mellanox de 10 gigabit possède l&#039;identifiant enp1s0&lt;br /&gt;
&lt;br /&gt;
= Contrôle par le débit =&lt;br /&gt;
&lt;br /&gt;
Si vous avez toujours des doutes vous pouvez afficher le débit des cartes grâce à la commande &#039;&#039;ethtool&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
La Realtek aura un débit max de 1000&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
La Mellanox pourra monter à 10 Gigabit&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ethtool enp3s0&lt;br /&gt;
Settings for enp3s0:&lt;br /&gt;
	Supported ports: [ TP	 MII ]&lt;br /&gt;
	Supported link modes:   10baseT/Half 10baseT/Full&lt;br /&gt;
	                        100baseT/Half 100baseT/Full&lt;br /&gt;
	                        1000baseT/Full&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ethtool enp1s0&lt;br /&gt;
Settings for enp1s0:&lt;br /&gt;
	Supported ports: [ FIBRE ]&lt;br /&gt;
	Supported link modes:   1000baseX/Full&lt;br /&gt;
	                        10000baseCR/Full&lt;br /&gt;
	                        10000baseSR/Full&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Contrôle par l&#039;état du lien =&lt;br /&gt;
&lt;br /&gt;
Si vous possédez une carte avec plusieurs fonctions (ports), il vous reste à différencier les ports entres eux...&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
La &lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
La Mellanox pourra monter à 10 Gigabit&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ethtool enp3s0&lt;br /&gt;
Settings for enp3s0:&lt;br /&gt;
	Supported ports: [ TP	 MII ]&lt;br /&gt;
	Supported link modes:   10baseT/Half 10baseT/Full&lt;br /&gt;
	                        100baseT/Half 100baseT/Full&lt;br /&gt;
	                        1000baseT/Full&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ethtool enp1s0&lt;br /&gt;
Settings for enp1s0:&lt;br /&gt;
	Supported ports: [ FIBRE ]&lt;br /&gt;
	Supported link modes:   1000baseX/Full&lt;br /&gt;
	                        10000baseCR/Full&lt;br /&gt;
	                        10000baseSR/Full&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
On va&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Identify_your_nic&amp;diff=4377</id>
		<title>Identify your nic</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Identify_your_nic&amp;diff=4377"/>
		<updated>2026-06-30T11:00:34Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Identifiants PCI et prédictions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
&lt;br /&gt;
Lorsque l&#039;on arrive sur une machine qui possède plusieurs cartes réseau, il est souvent difficile de faire le lien entre une carte logique (enp1s0, eno2, wl0, ...) et une carte physique et nous allons voir comment faire !&lt;br /&gt;
&lt;br /&gt;
= La logique =&lt;br /&gt;
&lt;br /&gt;
Les premières lettres correspondent au type de carte:&lt;br /&gt;
* en pour [https://fr.wikipedia.org/wiki/Ethernet Ethernet]&lt;br /&gt;
* wl pour [https://fr.wikipedia.org/wiki/Wi-Fi Wireless (Wi-Fi)]&lt;br /&gt;
* ib pour [https://fr.wikipedia.org/wiki/Bus_InfiniBand InfiniBand]&lt;br /&gt;
* sl pour [https://fr.wikipedia.org/wiki/Serial_Line_Internet_Protocol Serial Line IP]&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
Vient ensuite le type de connexion:&lt;br /&gt;
* &#039;&#039;o&#039;&#039; pour &#039;&#039;onboard&#039;&#039; ou intégré&lt;br /&gt;
* &#039;&#039;p&#039;&#039; pour &#039;&#039;pci&#039;&#039;, c&#039;est à dire une carte branché sur des [https://fr.wikipedia.org/wiki/PCI_Express lignes PCI] au processeur&lt;br /&gt;
&lt;br /&gt;
Dans le cas d&#039;une carte en PCI on poursuit avec le numéro du &#039;&#039;slot&#039;&#039; que l&#039;on peut assimiler au nombre de puces présente sur la carte.&lt;br /&gt;
Une carte possédant deux puces aura donc deux &#039;&#039;slot&#039;&#039; : &#039;&#039;s0&#039;&#039; et &#039;&#039;s1&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Et on termine avec la fonction que l&#039;on peut assimiler au nombre de ports par puce. Une puce possédant deux ports aura donc deux fonctions: &#039;&#039;f0&#039;&#039; et &#039;&#039;f1&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour résumer, les cartes intégrées possèdent des noms comme:&lt;br /&gt;
* &#039;&#039;eno0&#039;&#039;&lt;br /&gt;
* &#039;&#039;eno1&#039;&#039;&lt;br /&gt;
* ... &lt;br /&gt;
&lt;br /&gt;
Et les cartes en PCI des noms comme:&lt;br /&gt;
* &#039;&#039;enp0s0f1&#039;&#039;&lt;br /&gt;
* &#039;&#039;enp0s0f1&#039;&#039;&lt;br /&gt;
* &#039;&#039;enp1s0f0&#039;&#039;&lt;br /&gt;
* ...&lt;br /&gt;
= Connaître ces cartes =&lt;br /&gt;
&lt;br /&gt;
Pour démarrer le travail d&#039;identification, vous pouvez commencez par repérer le constructeur et / ou le modèle de puce utilisé, souvent mentionné:&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
Sur la boîte de votre carte mère...&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
ou bien dans son manuel...&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
ou dans l&#039;annonce si c&#039;est une carte PCI&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:motherboard box Z370.jpg|350px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:motherboard manual Z270.jpg|300px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:amazon mellanox connect-x3.jpg|400px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Identifiants PCI et prédictions =&lt;br /&gt;
&lt;br /&gt;
Il faut maintenant faire le parallèle avec les cartes afficher dans le terminal et pour ça nous allons utiliser la commande &#039;&#039;lspci&#039;&#039;:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# lspci | grep Ethernet&lt;br /&gt;
01:00.0 Ethernet controller: Mellanox Technologies MT27500 Family [ConnectX-3]&lt;br /&gt;
03:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8111/8168/8211/8411 PCI Express Gigabit Ethernet Controller (rev 15)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On voit que la carte Realtek RTL8111 (celle de la carte mère) possède l&#039;identifiant 03:00.0 et que la Mellanox l&#039;identifiant 01:00.0&lt;br /&gt;
&lt;br /&gt;
Il faut maintenant transposer ces identifiants en nom:&lt;br /&gt;
* le premier chiffre correspond a l&#039;identifiant PCI généré par le micrologiciel de la carte mère (p3 et p1)&lt;br /&gt;
* le deuxième correspond au &#039;&#039;slot&#039;&#039; (s0)&lt;br /&gt;
* le dernier à la fonction (f0)&lt;br /&gt;
&lt;br /&gt;
Un nom possible pour la carte Realtek pourrait être &#039;&#039;enp3s0f0&#039;&#039;. Cependant, il est possible lorsque les cartes ne possèdent qu&#039;une fonction, d&#039;omettre celle-ci pour raccourcir le nom. &lt;br /&gt;
Notre carte pourrait donc s’appeler &#039;&#039;enp3s0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
On peut confirmer cela grâce à la commande &#039;&#039;ip&#039;&#039;:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ip a&lt;br /&gt;
1: lo: &amp;lt;LOOPBACK,UP,LOWER_UP&amp;gt; mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000&lt;br /&gt;
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00&lt;br /&gt;
    inet 127.0.0.1/8 scope host lo&lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
    inet6 ::1/128 scope host &lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
2: enp3s0: &amp;lt;NO-CARRIER,BROADCAST,MULTICAST,UP&amp;gt; mtu 1500 qdisc fq_codel state DOWN group default qlen 1000&lt;br /&gt;
    link/ether 30:9c:23:20:8c:dd brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
3: enp1s0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc mq state UP group default qlen 1000&lt;br /&gt;
    link/ether 24:8a:07:f7:bd:22 brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut en déduire que:&lt;br /&gt;
* la carte Realtek en gigabit possède l&#039;identifiant enp3s0 &lt;br /&gt;
* la carte Mellanox de 10 gigabit possède l&#039;identifiant enp1s0&lt;br /&gt;
&lt;br /&gt;
= Contrôle par le débit =&lt;br /&gt;
&lt;br /&gt;
Si vous avez toujours des doutes vous pouvez afficher le débit des cartes grâce à la commande &#039;&#039;ethtool&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
La Realtek aura un débit max de 1000&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
La Mellanox pourra monter à 10 Gigabit&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ethtool enp3s0&lt;br /&gt;
Settings for enp3s0:&lt;br /&gt;
	Supported ports: [ TP	 MII ]&lt;br /&gt;
	Supported link modes:   10baseT/Half 10baseT/Full&lt;br /&gt;
	                        100baseT/Half 100baseT/Full&lt;br /&gt;
	                        1000baseT/Full&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ethtool enp1s0&lt;br /&gt;
Settings for enp1s0:&lt;br /&gt;
	Supported ports: [ FIBRE ]&lt;br /&gt;
	Supported link modes:   1000baseX/Full&lt;br /&gt;
	                        10000baseCR/Full&lt;br /&gt;
	                        10000baseSR/Full&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Contrôle par l&#039;état du lien =&lt;br /&gt;
&lt;br /&gt;
Si vous possédez une carte avec plusieurs fonctions (ports), il vous reste à différencier les ports entres eux...&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
La &lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
La Mellanox pourra monter à 10 Gigabit&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ethtool enp3s0&lt;br /&gt;
Settings for enp3s0:&lt;br /&gt;
	Supported ports: [ TP	 MII ]&lt;br /&gt;
	Supported link modes:   10baseT/Half 10baseT/Full&lt;br /&gt;
	                        100baseT/Half 100baseT/Full&lt;br /&gt;
	                        1000baseT/Full&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ethtool enp1s0&lt;br /&gt;
Settings for enp1s0:&lt;br /&gt;
	Supported ports: [ FIBRE ]&lt;br /&gt;
	Supported link modes:   1000baseX/Full&lt;br /&gt;
	                        10000baseCR/Full&lt;br /&gt;
	                        10000baseSR/Full&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
On va&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Identify_your_nic&amp;diff=4376</id>
		<title>Identify your nic</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Identify_your_nic&amp;diff=4376"/>
		<updated>2026-06-30T11:00:17Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : /* Connaître ces cartes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
&lt;br /&gt;
Lorsque l&#039;on arrive sur une machine qui possède plusieurs cartes réseau, il est souvent difficile de faire le lien entre une carte logique (enp1s0, eno2, wl0, ...) et une carte physique et nous allons voir comment faire !&lt;br /&gt;
&lt;br /&gt;
= La logique =&lt;br /&gt;
&lt;br /&gt;
Les premières lettres correspondent au type de carte:&lt;br /&gt;
* en pour [https://fr.wikipedia.org/wiki/Ethernet Ethernet]&lt;br /&gt;
* wl pour [https://fr.wikipedia.org/wiki/Wi-Fi Wireless (Wi-Fi)]&lt;br /&gt;
* ib pour [https://fr.wikipedia.org/wiki/Bus_InfiniBand InfiniBand]&lt;br /&gt;
* sl pour [https://fr.wikipedia.org/wiki/Serial_Line_Internet_Protocol Serial Line IP]&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
Vient ensuite le type de connexion:&lt;br /&gt;
* &#039;&#039;o&#039;&#039; pour &#039;&#039;onboard&#039;&#039; ou intégré&lt;br /&gt;
* &#039;&#039;p&#039;&#039; pour &#039;&#039;pci&#039;&#039;, c&#039;est à dire une carte branché sur des [https://fr.wikipedia.org/wiki/PCI_Express lignes PCI] au processeur&lt;br /&gt;
&lt;br /&gt;
Dans le cas d&#039;une carte en PCI on poursuit avec le numéro du &#039;&#039;slot&#039;&#039; que l&#039;on peut assimiler au nombre de puces présente sur la carte.&lt;br /&gt;
Une carte possédant deux puces aura donc deux &#039;&#039;slot&#039;&#039; : &#039;&#039;s0&#039;&#039; et &#039;&#039;s1&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Et on termine avec la fonction que l&#039;on peut assimiler au nombre de ports par puce. Une puce possédant deux ports aura donc deux fonctions: &#039;&#039;f0&#039;&#039; et &#039;&#039;f1&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour résumer, les cartes intégrées possèdent des noms comme:&lt;br /&gt;
* &#039;&#039;eno0&#039;&#039;&lt;br /&gt;
* &#039;&#039;eno1&#039;&#039;&lt;br /&gt;
* ... &lt;br /&gt;
&lt;br /&gt;
Et les cartes en PCI des noms comme:&lt;br /&gt;
* &#039;&#039;enp0s0f1&#039;&#039;&lt;br /&gt;
* &#039;&#039;enp0s0f1&#039;&#039;&lt;br /&gt;
* &#039;&#039;enp1s0f0&#039;&#039;&lt;br /&gt;
* ...&lt;br /&gt;
= Connaître ces cartes =&lt;br /&gt;
&lt;br /&gt;
Pour démarrer le travail d&#039;identification, vous pouvez commencez par repérer le constructeur et / ou le modèle de puce utilisé, souvent mentionné:&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
Sur la boîte de votre carte mère...&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
ou bien dans son manuel...&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
ou dans l&#039;annonce si c&#039;est une carte PCI&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:motherboard box Z370.jpg|350px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:motherboard manual Z270.jpg|300px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:amazon mellanox connect-x3.jpg|400px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Identifiants PCI et prédictions =&lt;br /&gt;
&lt;br /&gt;
Il faut maintenant faire le parallèle avec les cartes afficher dans le terminal et pour ça nous allons utiliser la commande suivante:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# lspci | grep Ethernet&lt;br /&gt;
01:00.0 Ethernet controller: Mellanox Technologies MT27500 Family [ConnectX-3]&lt;br /&gt;
03:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8111/8168/8211/8411 PCI Express Gigabit Ethernet Controller (rev 15)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On voit que la carte Realtek RTL8111 (celle de la carte mère) possède l&#039;identifiant 03:00.0 et que la Mellanox l&#039;identifiant 01:00.0&lt;br /&gt;
&lt;br /&gt;
Il faut maintenant transposer ces identifiants en nom:&lt;br /&gt;
* le premier chiffre correspond a l&#039;identifiant PCI généré par le micrologiciel de la carte mère (p3 et p1)&lt;br /&gt;
* le deuxième correspond au &#039;&#039;slot&#039;&#039; (s0)&lt;br /&gt;
* le dernier à la fonction (f0)&lt;br /&gt;
&lt;br /&gt;
Un nom possible pour la carte Realtek pourrait être &#039;&#039;enp3s0f0&#039;&#039;. Cependant, il est possible lorsque les cartes ne possèdent qu&#039;une fonction, d&#039;omettre celle-ci pour raccourcir le nom. &lt;br /&gt;
Notre carte pourrait donc s’appeler &#039;&#039;enp3s0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
On peut confirmer cela grâce à la commande &#039;&#039;ip&#039;&#039;:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ip a&lt;br /&gt;
1: lo: &amp;lt;LOOPBACK,UP,LOWER_UP&amp;gt; mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000&lt;br /&gt;
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00&lt;br /&gt;
    inet 127.0.0.1/8 scope host lo&lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
    inet6 ::1/128 scope host &lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
2: enp3s0: &amp;lt;NO-CARRIER,BROADCAST,MULTICAST,UP&amp;gt; mtu 1500 qdisc fq_codel state DOWN group default qlen 1000&lt;br /&gt;
    link/ether 30:9c:23:20:8c:dd brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
3: enp1s0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc mq state UP group default qlen 1000&lt;br /&gt;
    link/ether 24:8a:07:f7:bd:22 brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut en déduire que:&lt;br /&gt;
* la carte Realtek en gigabit possède l&#039;identifiant enp3s0 &lt;br /&gt;
* la carte Mellanox de 10 gigabit possède l&#039;identifiant enp1s0&lt;br /&gt;
&lt;br /&gt;
= Contrôle par le débit =&lt;br /&gt;
&lt;br /&gt;
Si vous avez toujours des doutes vous pouvez afficher le débit des cartes grâce à la commande &#039;&#039;ethtool&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
La Realtek aura un débit max de 1000&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
La Mellanox pourra monter à 10 Gigabit&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ethtool enp3s0&lt;br /&gt;
Settings for enp3s0:&lt;br /&gt;
	Supported ports: [ TP	 MII ]&lt;br /&gt;
	Supported link modes:   10baseT/Half 10baseT/Full&lt;br /&gt;
	                        100baseT/Half 100baseT/Full&lt;br /&gt;
	                        1000baseT/Full&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ethtool enp1s0&lt;br /&gt;
Settings for enp1s0:&lt;br /&gt;
	Supported ports: [ FIBRE ]&lt;br /&gt;
	Supported link modes:   1000baseX/Full&lt;br /&gt;
	                        10000baseCR/Full&lt;br /&gt;
	                        10000baseSR/Full&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Contrôle par l&#039;état du lien =&lt;br /&gt;
&lt;br /&gt;
Si vous possédez une carte avec plusieurs fonctions (ports), il vous reste à différencier les ports entres eux...&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
La &lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
La Mellanox pourra monter à 10 Gigabit&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ethtool enp3s0&lt;br /&gt;
Settings for enp3s0:&lt;br /&gt;
	Supported ports: [ TP	 MII ]&lt;br /&gt;
	Supported link modes:   10baseT/Half 10baseT/Full&lt;br /&gt;
	                        100baseT/Half 100baseT/Full&lt;br /&gt;
	                        1000baseT/Full&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ethtool enp1s0&lt;br /&gt;
Settings for enp1s0:&lt;br /&gt;
	Supported ports: [ FIBRE ]&lt;br /&gt;
	Supported link modes:   1000baseX/Full&lt;br /&gt;
	                        10000baseCR/Full&lt;br /&gt;
	                        10000baseSR/Full&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
On va&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
	<entry>
		<id>https://tala-informatique.fr/index.php?title=Identify_your_nic&amp;diff=4375</id>
		<title>Identify your nic</title>
		<link rel="alternate" type="text/html" href="https://tala-informatique.fr/index.php?title=Identify_your_nic&amp;diff=4375"/>
		<updated>2026-06-30T10:59:22Z</updated>

		<summary type="html">&lt;p&gt;Jc.forton : Page créée avec « = Introduction =  Lorsque l&amp;#039;on arrive sur une machine qui possède plusieurs cartes réseau, il est souvent difficile de faire le lien entre une carte logique (enp1s0, eno2, wl0, ...) et une carte physique et nous allons voir comment faire !  = La logique =  Les premières lettres correspondent au type de carte: * en pour [https://fr.wikipedia.org/wiki/Ethernet Ethernet] * wl pour [https://fr.wikipedia.org/wiki/Wi-Fi Wireless (Wi-Fi)] * ib pour [https://fr.wikipe... »&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
&lt;br /&gt;
Lorsque l&#039;on arrive sur une machine qui possède plusieurs cartes réseau, il est souvent difficile de faire le lien entre une carte logique (enp1s0, eno2, wl0, ...) et une carte physique et nous allons voir comment faire !&lt;br /&gt;
&lt;br /&gt;
= La logique =&lt;br /&gt;
&lt;br /&gt;
Les premières lettres correspondent au type de carte:&lt;br /&gt;
* en pour [https://fr.wikipedia.org/wiki/Ethernet Ethernet]&lt;br /&gt;
* wl pour [https://fr.wikipedia.org/wiki/Wi-Fi Wireless (Wi-Fi)]&lt;br /&gt;
* ib pour [https://fr.wikipedia.org/wiki/Bus_InfiniBand InfiniBand]&lt;br /&gt;
* sl pour [https://fr.wikipedia.org/wiki/Serial_Line_Internet_Protocol Serial Line IP]&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
Vient ensuite le type de connexion:&lt;br /&gt;
* &#039;&#039;o&#039;&#039; pour &#039;&#039;onboard&#039;&#039; ou intégré&lt;br /&gt;
* &#039;&#039;p&#039;&#039; pour &#039;&#039;pci&#039;&#039;, c&#039;est à dire une carte branché sur des [https://fr.wikipedia.org/wiki/PCI_Express lignes PCI] au processeur&lt;br /&gt;
&lt;br /&gt;
Dans le cas d&#039;une carte en PCI on poursuit avec le numéro du &#039;&#039;slot&#039;&#039; que l&#039;on peut assimiler au nombre de puces présente sur la carte.&lt;br /&gt;
Une carte possédant deux puces aura donc deux &#039;&#039;slot&#039;&#039; : &#039;&#039;s0&#039;&#039; et &#039;&#039;s1&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Et on termine avec la fonction que l&#039;on peut assimiler au nombre de ports par puce. Une puce possédant deux ports aura donc deux fonctions: &#039;&#039;f0&#039;&#039; et &#039;&#039;f1&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour résumer, les cartes intégrées possèdent des noms comme:&lt;br /&gt;
* &#039;&#039;eno0&#039;&#039;&lt;br /&gt;
* &#039;&#039;eno1&#039;&#039;&lt;br /&gt;
* ... &lt;br /&gt;
&lt;br /&gt;
Et les cartes en PCI des noms comme:&lt;br /&gt;
* &#039;&#039;enp0s0f1&#039;&#039;&lt;br /&gt;
* &#039;&#039;enp0s0f1&#039;&#039;&lt;br /&gt;
* &#039;&#039;enp1s0f0&#039;&#039;&lt;br /&gt;
* ...&lt;br /&gt;
= Connaître ces cartes =&lt;br /&gt;
&lt;br /&gt;
Pour démarrer le travail d&#039;identification, vous pouvez commencez par repérer le constructeur et / ou le modèle de puce utilisé, souvent mentionné:&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
Sur la boîte de votre carte mère...&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
ou bien dans son manuel...&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
ou dans l&#039;annonce si c&#039;est une carte PCI&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:motherboard box Z370.jpg|400px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:motherboard manual Z270.jpg|350px|centré]]&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
[[Fichier:amazon mellanox connect-x3.jpg|400px|centré]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Identifiants PCI et prédictions =&lt;br /&gt;
&lt;br /&gt;
Il faut maintenant faire le parallèle avec les cartes afficher dans le terminal et pour ça nous allons utiliser la commande suivante:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# lspci | grep Ethernet&lt;br /&gt;
01:00.0 Ethernet controller: Mellanox Technologies MT27500 Family [ConnectX-3]&lt;br /&gt;
03:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8111/8168/8211/8411 PCI Express Gigabit Ethernet Controller (rev 15)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On voit que la carte Realtek RTL8111 (celle de la carte mère) possède l&#039;identifiant 03:00.0 et que la Mellanox l&#039;identifiant 01:00.0&lt;br /&gt;
&lt;br /&gt;
Il faut maintenant transposer ces identifiants en nom:&lt;br /&gt;
* le premier chiffre correspond a l&#039;identifiant PCI généré par le micrologiciel de la carte mère (p3 et p1)&lt;br /&gt;
* le deuxième correspond au &#039;&#039;slot&#039;&#039; (s0)&lt;br /&gt;
* le dernier à la fonction (f0)&lt;br /&gt;
&lt;br /&gt;
Un nom possible pour la carte Realtek pourrait être &#039;&#039;enp3s0f0&#039;&#039;. Cependant, il est possible lorsque les cartes ne possèdent qu&#039;une fonction, d&#039;omettre celle-ci pour raccourcir le nom. &lt;br /&gt;
Notre carte pourrait donc s’appeler &#039;&#039;enp3s0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
On peut confirmer cela grâce à la commande &#039;&#039;ip&#039;&#039;:&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ip a&lt;br /&gt;
1: lo: &amp;lt;LOOPBACK,UP,LOWER_UP&amp;gt; mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000&lt;br /&gt;
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00&lt;br /&gt;
    inet 127.0.0.1/8 scope host lo&lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
    inet6 ::1/128 scope host &lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
2: enp3s0: &amp;lt;NO-CARRIER,BROADCAST,MULTICAST,UP&amp;gt; mtu 1500 qdisc fq_codel state DOWN group default qlen 1000&lt;br /&gt;
    link/ether 30:9c:23:20:8c:dd brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
3: enp1s0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc mq state UP group default qlen 1000&lt;br /&gt;
    link/ether 24:8a:07:f7:bd:22 brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut en déduire que:&lt;br /&gt;
* la carte Realtek en gigabit possède l&#039;identifiant enp3s0 &lt;br /&gt;
* la carte Mellanox de 10 gigabit possède l&#039;identifiant enp1s0&lt;br /&gt;
&lt;br /&gt;
= Contrôle par le débit =&lt;br /&gt;
&lt;br /&gt;
Si vous avez toujours des doutes vous pouvez afficher le débit des cartes grâce à la commande &#039;&#039;ethtool&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
La Realtek aura un débit max de 1000&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
La Mellanox pourra monter à 10 Gigabit&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ethtool enp3s0&lt;br /&gt;
Settings for enp3s0:&lt;br /&gt;
	Supported ports: [ TP	 MII ]&lt;br /&gt;
	Supported link modes:   10baseT/Half 10baseT/Full&lt;br /&gt;
	                        100baseT/Half 100baseT/Full&lt;br /&gt;
	                        1000baseT/Full&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ethtool enp1s0&lt;br /&gt;
Settings for enp1s0:&lt;br /&gt;
	Supported ports: [ FIBRE ]&lt;br /&gt;
	Supported link modes:   1000baseX/Full&lt;br /&gt;
	                        10000baseCR/Full&lt;br /&gt;
	                        10000baseSR/Full&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Contrôle par l&#039;état du lien =&lt;br /&gt;
&lt;br /&gt;
Si vous possédez une carte avec plusieurs fonctions (ports), il vous reste à différencier les ports entres eux...&lt;br /&gt;
&lt;br /&gt;
{|align=center&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
La &lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
La Mellanox pourra monter à 10 Gigabit&lt;br /&gt;
|-&lt;br /&gt;
|valign=top|&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ethtool enp3s0&lt;br /&gt;
Settings for enp3s0:&lt;br /&gt;
	Supported ports: [ TP	 MII ]&lt;br /&gt;
	Supported link modes:   10baseT/Half 10baseT/Full&lt;br /&gt;
	                        100baseT/Half 100baseT/Full&lt;br /&gt;
	                        1000baseT/Full&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|width=10px|&lt;br /&gt;
|valign=top|&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
# ethtool enp1s0&lt;br /&gt;
Settings for enp1s0:&lt;br /&gt;
	Supported ports: [ FIBRE ]&lt;br /&gt;
	Supported link modes:   1000baseX/Full&lt;br /&gt;
	                        10000baseCR/Full&lt;br /&gt;
	                        10000baseSR/Full&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
On va&lt;/div&gt;</summary>
		<author><name>Jc.forton</name></author>
	</entry>
</feed>