Knockd est un outil de "portknocking":
Si un motif réseau spécifique est détecté, il peut exécuter des actions pré-déterminées
Prenons l'exemple suivant, adapté de la manpage de knockd:
[opencloseSSH]
sequence = 2222:tcp,3333:tcp,4444:tcp
seq_timeout = 15
tcpflags = syn
start_command = /usr/sbin/iptables -A INPUT -s %IP% -p tcp --syn -j ACCEPT
Cette configuration permet d'ajouter une rêgle de firewall pour l'IP source externe qui aura généré la séquence réseau (détectée sur l'interface du serveur)
Dans ce cas, la séquence de déclenchement est la suivante:
- Connexion TCP port 2222
- Connexion TCP 3333
- Connexion TCP 4444
(En réalisé, ce ne sont pas des connexions TCP établies, mais simplement un packet SYN)
Ca serait vachement bien si knockd pouvait maintenant piloter le filtrage IP de caddy.
Nous allons voir comment.
L'interface API de caddy
Caddy dispose d'une API pour interagir dynamiquement sur sa configuration.
La configuration suivante permet d'activer cette interface d'admin sur une socket unix:
{
admin "unix//run/caddy/admin.socket" {
origins myadmin
}
}
Avec cette configuration, il est possible de lancer des commandes curl pour consulter la configuration:
# curl -s --unix-socket /run/caddy/admin.socket http://myadmin/config/apps/http/servers
{
"srv0": {
"listen": [
":443"
],
...
Un appel a l'API en GET permet de lire la configuration.
Et un appel POST permet de modifier cette configuration.
Filtrage IP dans caddy
A présent, voyons comment protéger notre virtual server avec les directives client_ip et handle:e
https://mon.beau.serveur.com:443 {
# IPs autorisées
@allowed {
client_ip 33.32.31.30
}
# Gestion du site pour les ip autorisées
handle @allowed {
reverse_proxy 1.2.3.4:443 {
}
}
# Gestion du site pour les ip(s) non déclarées
handle {
respond "Access denied" 403
}
}
Dans cet exemple, nous déclarons que l'ip 33.32.31.30 fait partie du 'groupe' @allowed, et pourra accéder aux site 1.2.3.4:443 en mode reverse proxy.
Pour les autres, il y aura une erreur HTTP 403
Interaction knockd et caddy
La configuration knockd suivante permettra de lancer une commande de mise à jour de la configuration Caddy.
[options]
logfile = /var/log/knockd.log
[allowedIPS]
sequence = 2222:udp,3333:tcp,4444:udp
seq_timeout = 10
command = curl -s --unix-socket /run/caddy/admin.socket -X POST -H "Content-Type: application/json" -d '{"ranges": ["%IP%"]}' 'http://myadmin/config/apps/http/servers/srv0/routes/2/handle/0/routes/1/match/0/client_ip'
tcpflags = syn
Testons cette configuration:
# Configuration de base au démarage du serveur.
# L'API nous retourne bien l'unique IP déclarée comme autorisée dans la configuation
server $ curl -s --unix-socket /run/caddy/admin.socket 'http://myadmin/config/apps/http/servers/srv0/routes/2/handle/0/routes/1/match/0/client_ip/ranges' | jq
[
"33.32.31.30"
]
# Netcat permet de générer la séquence réseau (portknocking) et déclencher les commandes associées
laptop (130.33.45.32) $ for i in 10000 10001 1023; do nc -w 1 -v monserveur $i; done
server $ curl -s --unix-socket /run/caddy/admin.socket 'http://myadmin/config/apps/http/servers/srv0/routes/2/handle/0/routes/1/match/0/client_ip/ranges' | jq
[
"130.33.45.32"
]
=> L'ip a bien été actualisée dans la configuration de caddy
Remarques:
Le portknocking ne doit pas être l'unique moyen de sécuriser votre serveur.
Il constitue un premier niveau de protection, mais repose uniquement sur la confidentialité de la séquence de déclenchement.
Vous pourrez ajouter, en complément, une authentification par certificats ou avec un MFA.