# CLAUDE.md — Optimisation réseau Linux (TCP BBR, NIC, Apache, ProFTPD)
Contexte de référence pour le tuning réseau sur Debian/Ubuntu : BBR, ring buffers NIC,
socket buffers ProFTPD/Apache, TLS session cache et OCSP Stapling.
---
## Section 1 : Diagnostic débit
Avant de toucher quoi que ce soit, mesurer et localiser le goulot.
```bash
# Identifier l'interface réseau
ip link show
# ou
ip -brief link show
# Vitesse négociée et état de la liaison
ethtool eth0 # ou enp2s0f0, ens3, etc.
# Speed: 1000Mb/s
# Duplex: Full
# Link detected: yes
# Statistiques NIC : drops ring buffer
ethtool -S eth0 | grep -i -E "drop|miss|error|overflow"
# rx_missed_errors, rx_fifo_errors, rx_over_errors → drops ring buffer
# tx_fifo_errors → drops ring buffer TX
# Statistiques TCP kernel
ss -s
# Retransmissions, connexions en attente
# Compteurs TCP détaillés (pertes, retrans, cwnd drops)
netstat -s | grep -i -E "retransmit|failed|reset|timeout"
# Quel algorithme de congestion est actif
sysctl net.ipv4.tcp_congestion_control
# → cubic (mauvais) ou bbr (bon)
# Modules disponibles
sysctl net.ipv4.tcp_available_congestion_control
# → reno cubic bbr
# Test débit SFTP simple (nécessite un fichier de test)
dd if=/dev/zero of=/tmp/testfile bs=1M count=1024
time sftp user@serveur <<< $'put /tmp/testfile /tmp/testfile'
# Test débit HTTP avec curl
curl -o /dev/null -w "%{speed_download}\n" https://votre-domaine.com/gros-fichier.bin
# Observer les connexions TCP actives et leur état cwnd
ss -tin sport = :22 # SFTP (passe par SSH)
# cwnd: valeur courante de la fenêtre de congestion
```
---
## Section 2 : TCP BBR et sysctl
Fichier `/etc/sysctl.d/99-bbr.conf` — configuration complète :
```bash
# Algorithme de contrôle de congestion
# BBR (Google, 2016) : basé sur mesure de débit + RTT, ne réagit pas aux pertes
# CUBIC (défaut) : réduit cwnd de 50% à chaque perte détectée → mauvais sur liens modernes
net.ipv4.tcp_congestion_control = bbr
# Désactiver le slow start après inactivité
# Par défaut : Linux remet cwnd à 10 après idle. Pénalise les sessions SFTP interactives
# (chaque nouveau transfert après navigation repart en slow start)
net.ipv4.tcp_slow_start_after_idle = 0
# Ne pas réutiliser les métriques TCP des sessions précédentes
# Évite d'hériter d'une cwnd dégradée d'une session antérieure problématique
net.ipv4.tcp_no_metrics_save = 1
# TCP Fast Open client + serveur
# Économise 1 RTT sur les reconnexions en incluant des données dans le SYN
# 1 = client, 2 = serveur, 3 = les deux
net.ipv4.tcp_fastopen = 3
# MTU Path Discovery si ICMP bloqué
# Certains pare-feux bloquent les messages ICMP "fragmentation needed"
# → TCP ne sait pas que les paquets sont trop grands → stalls
# tcp_mtu_probing = 1 active la découverte MTU par TCP lui-même
net.ipv4.tcp_mtu_probing = 1
# Buffer d'écriture TCP [min, default, max] en octets
# min : 4 KB (valeur minimale garantie par socket)
# default : 256 KB (taille initiale du buffer send)
# max : 16 MB (plafond — kernel ajuste dynamiquement entre default et max)
net.ipv4.tcp_wmem = 4096 262144 16777216
# Queue de paquets NIC avant traitement kernel
# À 1 Gbit/s : ~83 000 paquets/s → queue de 5000 entrées évite les drops
# si le kernel est temporairement occupé (interruptions, scheduling)
net.core.netdev_max_backlog = 5000
# Paquets traités par cycle NAPI (New API)
# NAPI = mécanisme d'interruption différée pour les NIC haute performance
# budget = 600 : traiter jusqu'à 600 paquets avant de rendre la main
net.core.netdev_budget = 600
```
Appliquer et vérifier :
```bash
# Charger immédiatement (persistant via le fichier .conf)
sysctl -p /etc/sysctl.d/99-bbr.conf
# Vérifications
sysctl net.ipv4.tcp_congestion_control
# → net.ipv4.tcp_congestion_control = bbr
sysctl net.ipv4.tcp_wmem
# → net.ipv4.tcp_wmem = 4096 262144 16777216
# Si BBR n'est pas disponible : charger le module
lsmod | grep bbr
modprobe tcp_bbr
echo "tcp_bbr" >> /etc/modules-load.d/bbr.conf
```
---
## Section 3 : NIC ring buffers
Le ring buffer NIC est la zone mémoire entre la carte réseau et le kernel.
Si elle sature, les paquets sont dropped silencieusement — CUBIC s'effondre, BBR sous-performe.
```bash
# Vérifier l'état actuel
ethtool -g enp2s0f0
# Ring parameters for enp2s0f0:
# Pre-set maximums:
# RX: 4096
# TX: 4096
# Current hardware settings:
# RX: 256 ← trop petit pour 1 Gbit/s
# TX: 256
# Appliquer (immédiat, non persistant)
ethtool -G enp2s0f0 rx 4096 tx 4096
# Vérifier
ethtool -g enp2s0f0 | grep -A5 "Current hardware"
# RX: 4096
# TX: 4096
# Observer les drops en temps réel
watch -n1 "ethtool -S enp2s0f0 | grep -i -E 'drop|miss|fifo'"
```
Persistance dans `/etc/network/interfaces` :
```
# Exemple de bloc iface complet
auto enp2s0f0
iface enp2s0f0 inet static
address 192.168.1.10/24
gateway 192.168.1.1
dns-nameservers 8.8.8.8
dns-search example.com
post-up ethtool -G enp2s0f0 rx 4096 tx 4096
```
Remarques :
- Le nom d'interface varie : `eth0`, `enp2s0f0`, `ens3`... vérifier avec `ip link show`
- Les maximums NIC dépendent du hardware — `ethtool -g` affiche les limites réelles
- Sur les VPS/cloud, les ring buffers sont souvent virtualisés et peuvent ne pas être configurables
---
## Section 4 : ProFTPD socket buffers
Les socket buffers contrôlent la quantité de données que le kernel peut tenir en transit
par connexion TCP, côté applicatif. ProFTPD utilise les défauts système (~87 KB) sauf configuration explicite.
Dans `/etc/proftpd/proftpd.conf`, après `UseSendFile on` :
```apacheconf
# rcvbuf : buffer de réception (données entrantes — uploads)
# sndbuf : buffer d'envoi (données sortantes — downloads)
# 1048576 = 1 MB
SocketOptions rcvbuf 1048576 sndbuf 1048576
```
```bash
# Tester la config avant rechargement
proftpd --configtest
# Recharger
systemctl reload proftpd
# Vérifier que ProFTPD applique bien les valeurs socket
# (nécessite une session SFTP active)
ss -tn dst <ip-client> | grep :22
# sndbuf et rcvbuf visibles dans ss -tm (man ss)
```
---
## Section 5 : Apache SendBufferSize + TLS session cache + OCSP Stapling
### Apache SendBufferSize
Dans `/etc/apache2/apache2.conf` (niveau global, hors VirtualHost) :
```apacheconf
# Buffer d'envoi TCP pour les connexions HTTP
# Sans ce paramètre : valeur système (~87 KB)
# 1048576 = 1 MB
SendBufferSize 1048576
```
### TLS session cache
Dans `/etc/apache2/mods-enabled/ssl.conf` :
```apacheconf
# Cache de sessions TLS en mémoire partagée
# shmcb = shared memory circular buffer
# ${APACHE_RUN_DIR}/ssl_scache = chemin du fichier mémoire partagée
# (10485760) = 10 MB → environ 40 000 sessions simultanées
SSLSessionCache shmcb:${APACHE_RUN_DIR}/ssl_scache(10485760)
# Durée de vie d'une session en cache : 3600 secondes (1 heure)
SSLSessionCacheTimeout 3600
```
### OCSP Stapling
```apacheconf
# Activer le stapling OCSP
# Apache précharge et met en cache la réponse OCSP de l'AC
# → incluse dans le handshake TLS, le client n'a pas besoin de contacter l'AC
SSLUseStapling on
# Cache OCSP en mémoire partagée : 2 MB
SSLStaplingCache shmcb:/var/run/apache2/ssl_stapling(2097152)
# Ne pas renvoyer les erreurs OCSP upstream au client
# Si l'AC est temporairement injoignable, Apache continue sans stapling
# (comportement sécurisé en production)
SSLStaplingReturnResponderErrors off
```
```bash
# Tester la config
apache2ctl configtest
# Recharger
systemctl reload apache2
# Vérifier le stapling
openssl s_client -connect votre-domaine.com:443 -status < /dev/null 2>&1 | grep -A3 "OCSP"
# → OCSP Response Status: successful (0x0)
# Vérifier la reprise de session TLS
openssl s_client -connect votre-domaine.com:443 -reconnect 2>&1 | grep "Reused"
# → Reused, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
```
---
## Section 6 : Vérifications post-déploiement
Checklist complète après application de l'ensemble des optimisations.
```bash
# === BBR ===
sysctl net.ipv4.tcp_congestion_control
# attendu → bbr
sysctl net.ipv4.tcp_slow_start_after_idle
# attendu → 0
sysctl net.ipv4.tcp_wmem
# attendu → 4096 262144 16777216
# === Ring buffers NIC ===
ethtool -g enp2s0f0 | grep -A5 "Current hardware settings"
# attendu → RX: 4096, TX: 4096
# Pas de drops actifs
ethtool -S enp2s0f0 | grep -i -E "drop|miss|fifo" | grep -v " 0$"
# attendu → vide (ou compteurs stables)
# === Statistiques TCP ===
ss -s
# Observer : retransmissions, established, time-wait
# Compteurs de retransmissions
netstat -s | grep -i retransmit
# Idéalement faible par rapport au trafic total
# === ProFTPD ===
proftpd --configtest 2>&1 | grep -i "socket\|error"
systemctl is-active proftpd
# → active
# === Apache ===
apache2ctl configtest
# → Syntax OK
apache2ctl -t -D DUMP_RUN_CFG 2>&1 | grep -i "sendbuffer\|sslsession"
# === TLS ===
# OCSP Stapling
openssl s_client -connect votre-domaine.com:443 -status < /dev/null 2>&1 | \
grep -E "OCSP Response Status|nextUpdate"
# → OCSP Response Status: successful (0x0)
# Session resumption (reconnect 5 fois)
openssl s_client -connect votre-domaine.com:443 -reconnect 2>&1 | grep -c "Reused"
# → 4 (4 reconnexions sur 5 ont repris la session)
# === Test débit SFTP ===
dd if=/dev/zero of=/tmp/testfile bs=1M count=512
time sftp user@serveur <<< $'put /tmp/testfile /tmp/testfile'
# Comparer avec la valeur avant optimisation
# === Monitoring ongoing ===
# Drops NIC toutes les 10 secondes
watch -n10 "ethtool -S enp2s0f0 | grep -i -E 'drop|miss' | awk '\$2>0'"
# Connexions TCP actives avec cwnd
ss -tin | grep -E "cwnd|rto|rtt"
```