Introduction
VyOS est le routeur central du homelab. Il assure le routage inter-VLAN, le firewalling zone-based et l'hébergement de services critiques via des containers Podman intégrés nativement au système.
Cet article détaille l'architecture réseau, la gestion des zones firewall, le fonctionnement des containers et les bonnes pratiques opérationnelles.
Architecture zone-based
Le firewall VyOS utilise un modèle zone-based avec politique default-deny. Chaque interface (physique, VLAN ou bridge container) est assignée à une zone. Le trafic entre zones n'est autorisé que par des chaînes nommées explicites.
21 zones firewall
Le routeur gère 21 zones distinctes :
- wan : interface WAN (trafic Internet)
- lan : VLAN administration
- iot : VLAN objets connectés (IoT)
- servers : VLAN serveurs de production
- k8s : VLAN cluster Kubernetes
- bind9 : container DNS autoritatif
- webproxy : container Squid transparent proxy
- haproxy : container reverse-proxy TLS
- suricata : container IPS inline
- clamav : container antivirus
- cicap : container ICAP connector
- kuma : container monitoring Uptime Kuma
- Et d'autres zones spécialisées (VPN, management, DMZ...)
Chaque paire de zones possède une chaîne firewall dédiée avec un nommage cohérent : Zone-source-to-Zone-dest (ex: Iot-to-Webproxy).
Diagramme des zones
flowchart TB
WAN((WAN)) --> VyOS["VyOS Firewall<br/>21 zones - default deny"]
VyOS --> LAN["LAN"]
VyOS --> K3s["K3s"]
VyOS --> IoT["IoT"]
VyOS --> Mgmt["Management"]
VyOS --> Mail["Mail"]
subgraph pods["Containers Podman"]
BIND9["BIND9 DNS"]
Squid["Squid Proxy"]
HAP["HAProxy TLS"]
Suri["Suricata IPS"]
Clam["ClamAV"]
Kuma["Uptime Kuma"]
end
VyOS --> BIND9
VyOS --> Squid
VyOS --> HAP
VyOS --> Suri
Containers Podman
VyOS intègre Podman nativement dans sa configuration (set container name ...). Les containers sont gérés comme des services systemd (vyos-container-name``).
Services déployés
| Container | Image | Réseau | Rôle |
|---|---|---|---|
| bind9 | bind9-hardened:9.20.24 | 172.20.2.0/24 | DNS autoritatif + forwarder |
| squid | squid-hardened:7.5 | 172.20.0.0/24 | Proxy transparent (TPROXY) |
| clamav | clamav-hardened:1.4.2 | 172.20.0.0/24 | Antivirus daemon |
| c-icap | c-icap-hardened:0.6.4 | 172.20.0.0/24 | ICAP connector Squid↔ClamAV |
| haproxy | haproxy:latest | 172.20.1.0/24 | Reverse-proxy TLS (frontend) |
| suricata | suricata-hardened:8.0.5 | host network | IPS inline NFQUEUE |
| uptime-kuma | uptime-kuma:2 | 172.20.3.0/24 | Monitoring HTTP/TCP/DNS |
Réseau dédié par service
Chaque groupe de containers possède son propre bridge réseau Podman. Cette isolation garantit que :
- Les containers ne communiquent entre eux que via les règles firewall
- Chaque réseau est assigné à sa propre zone firewall
- Les address-groups contrôlent finement les IP autorisées
Interception DNAT
DNS (rule 534)
Le trafic DNS sortant de certaines zones (IoT, containers) est intercepté par une règle DNAT qui redirige vers le container BIND9 :
set nat destination rule 534 description 'DNS interception'
set nat destination rule 534 inbound-interface group 'dnat-dns'
set nat destination rule 534 protocol 'tcp_udp'
set nat destination rule 534 destination port '53'
set nat destination rule 534 translation address '172.20.2.10'
Cette interception garantit que tous les clients utilisent le même cache DNS (important pour la cohérence CDN avec le proxy transparent).
Proxy transparent (PBR)
Le VLAN IoT utilise le Policy-Based Routing (table 100) pour rediriger le trafic HTTP/HTTPS vers Squid :
- Les paquets marqués sont routés vers le container Squid
- Un service systemd
squid-redirectinjecte des règles nft REDIRECT dans le namespace réseau du container (80→3129, 443→3131) - Squid fait peek+splice sur le port 3131 pour l'interception HTTPS
Suricata IPS inline
Le container Suricata opère en mode NFQUEUE sur le trafic WAN entrant/sortant. Il nécessite allow-host-networks car NFQUEUE exige le network namespace de l'hôte.
L'option --queue-bypass agit comme failsafe natif : si le container est arrêté, le trafic passe sans inspection plutôt que d'être bloqué.
Voir l'article dédié : Suricata IPS inline NFQUEUE sur VyOS
Gestion de la configuration
Ansible vyos-backup.yaml
La configuration VyOS est sauvegardée et versionnée automatiquement via un playbook Ansible dédié :
- Export du
config.bootcomplet - Commit git automatique si des changements sont détectés
- Historique consultable des modifications
Commit et nftables
Le commit VyOS avec 130+ chaînes nftables prend 2 à 3 minutes. C'est normal et attendu — ne pas interrompre le processus.
Gotchas opérationnels
Ne jamais utiliser podman ni sudo
Regles absolues :
- Ne JAMAIS utiliser
podman stop/start/restartsur VyOS. La commandepodman stopsupprime le container (gere par systemd). Apres unpodman stop, le container n existe plus. - Ne JAMAIS utiliser
sudosur VyOS. Cela casse les permissions du config tree (unionfs passe en uid=0).
Pour redemarrer un container, utiliser la commande operationnelle VyOS native :
restart container
<nom>
Exemple : restart container bind9, restart container squid
Cette commande passe par le wrapper VyOS qui gere proprement le cycle de vie via systemd.
Commit timeout
Avec 130+ chaînes nftables, un commit prend 2-3 minutes. Le processus est normal — ne pas interrompre même si le terminal semble figé.
Netavark masquerade
Podman Netavark masquerade toutes les connexions sortantes des containers. L'IP source vue par les services externes est celle du gateway du bridge (ex: l'IP VyOS du réseau container), pas l'IP du container lui-même. Cela complique le tracing dans les logs — utiliser des identifiants applicatifs (hostnames syslog, headers HTTP) plutôt que les IP source.
Sessions SSH et vyatta-cfg-cmd-wrapper
Pour appliquer des commandes set depuis SSH non-interactif :
- Toujours sourcer
/etc/default/vyattaavant d'utiliser le wrapper - Regrouper
begin+set+commit+save+enddans un seul heredoc SSH
Sans le sourcing, les validateurs numériques/IP échouent silencieusement.
Conclusion
VyOS offre une plateforme unique combinant routage, firewalling zone-based et orchestration de containers — le tout géré via une configuration déclarative versionnable. L'intégration native de Podman évite la complexité d'un orchestrateur séparé tout en maintenant une isolation réseau stricte entre les services.
Laisser un commentaire