Description
V’Ger est le projet de serveur de publication sur le protocol Gemini, écrit en C. Écrit pour OpenBSD, il bénéficie des mesures de protections, liées à pledge(4) et unveil(4).
Dans cet article, nous aborderons l’installation et la configuration de ce service. Puis nous verrons comment configurer relayd ou nginx en tant que proxy relais ; et nous finirons par quelques règles pour Packet-Filter.
OpenBSD : 6.9 → 7.4
- Auteure du projet V’Ger : Solène Rapenne
- Disponible en tant que paquet : https://openports.pl/path/net/vger
- URL du dépôt Git : https://tildegit.org/solene/vger
Installation
Puisque V’Ger est disponible dans les ports, installez le paquet vger.
Autrement vous pouvez toujours l’installer depuis le dépôt Git… mais là, je vous renvoie à la documention du dépôt.
Configuration
Pré-requis :
- changez les termes ‘addresse_ipv4’, ‘addresse_ipv6’ et ’nom_domaine’, par ce qui correspond à votre contexte de serveur !
Utilisateur dédié _vger
Créons en tout premier un utilisateur dédié, nommé _vger :
$ doas useradd -d /var/gemini -s /sbin/nologin _vger
(dans la documentation officielle, le nom de l’utilisateur est _gemini).
Système
Il nous faut créer le répertoire /var/gemini
puis appliquer les droits
à l’utilisateur dédié :
$ doas mkdir -p /var/gemini/nom_domaine
$ doas chown -R _vger /var/gemini
inetd
- Fichier de configuraton :
/etc/inetd.conf
Le service inetd est chargé de l’écoute active sur l’interface localhost puis appelle le binaire vger pour délivrer le contenu.
Configurons maintenant le service inetd :
1965 stream tcp nowait _vger /usr/local/bin/vger vger -d /var/gemini -v
1965 stream tcp6 nowait _vger /usr/local/bin/vger vger -d /var/gemini -v
- le port d’écoute est le 1965 - (dans la documentation officielle, le port par défaut est 11965).
- géré par l’utilisateur _vger, appelant le binaire
vger
.
⇒ activons et démarrons le service :
$ doas rcctl enable inetd && doas rcctl start inetd
certificats SSL
Cet article ne présente pas comment obtenir les certificats SSL, mais vous pouvez les obtenir, soit depuis le client acme secure, natif sous OpenBSD, soit à partir du paquet certbot.
En premier, il semble nécessaire de créer le répertoire private
dans /etc/ssl
.
$ doas mkdir -p /etc/ssl/private
acme
La documentation officielle informe de lier les certificats SSL, générés par le client sécurisé acme sous OpenBSD.
Si c’est votre cas :
$ doas ln -s /etc/ssl/acme/cert.pem /etc/ssl/nom_domaine.crt
$ doas ln -s /etc/ssl/acme/private/privkey.pem /etc/ssl/private/nom_domaine.key
certbot
Dans mon contexte de serveur, les certificats sont générés par le client certbot, disponible officiellement dans les ports. Une fois les certificats générés par certbot, les liens symboliques à créer sont de cette forme :
$ doas ln -s /etc/letsencrypt/live/nom_domaine/cert.pem /etc/ssl/nom_domaine.crt
$ doas ln -s /etc/letsencrypt/live/nom_domaine/privkey.pem /etc/ssl/private/nom_domaine.key
relayd
- Fichier de configuration :
/etc/relayd.conf
- chmod 0600 !
relayd est le service de relais-proxy natif sous OpenBSD.
La configuration du service relayd peut se faire ainsi - dans cet exemple, à la fois pour Ipv4|6 - :
log connection
table <localhost> { 127.0.0.1, ::1 }
tcp protocol "gemini" {
tls keypair nom_domaine
}
relay "gemini" {
listen on nom_domaine port 1965 tls
protocol "gemini"
forward to <localhost> port 1965
}
⇒ Vérification de la configuration :
$ doas relayd -n
host_dns: nom_domaine resolves to more than 1 hosts
configuration OK
⇒ activons et démarrons le service :
$ doas rcctl enable relayd && doas rcctl start relayd
nginx
- Fichier de configuration :
/etc/nginx.conf
nginx peut lui aussi servir de proxy relais, en lieu et place de relayd ; mais il est nécessaire d’installer en plus le paquet nginx-stream.
Puis il faut modifier la configuration pour y ajouter, en début de fichier,
avant la directive http
:
load_module "modules/ngx_stream_module.so";
Ensuite, il est nécessaire de rajouter les déclarations suivantes en utilisant
la directive stream
:
stream {
log_format basic '$remote_addr $upstream_addr [$time_local] '
'$protocol $status $bytes_sent $bytes_received '
'$session_time';
access_log logs/nom_domaine/access.gemini.log basic;
upstream backend_ipv4 {
hash $remote_addr consistent;
server 127.0.0.1:1965;
}
upstream backend_ipv6 {
hash $remote_addr consistent;
server [::1]:1965;
}
map $server_addr $backend {
addresse_ipv4 backend_ipv4;
addresse_ipv6 backend_ipv6;
}
server {
listen addresse_ipv4:1965 ssl;
listen [addresse_ipv6]:1965 ssl;
ssl_certificate /etc/letsencrypt/live/nom_domaine/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/nom_domaine/privkey.pem;
ssl_ciphers TLS-CHACHA20-POLY1305-SHA256:TLS-AES-256-GCM-SHA384:TLS-AES-128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_ecdh_curve X25519:P-521:P-384:P-256;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1.3 TLSv1.2;
proxy_pass $backend;
}
}
Quelques petites explications :
-
en rapport avec les directives
listen
, si vous ne déclarez pas l’adresse IP correspondante, tel quelisten 1965 ssl;
, il faudra impérativement rediriger le port sur un autre numéro de port puis reconfigurerinetd.conf
pour qu’il écoute sur ce même autre numéro de port. En effet, si l’adresse IP d’écoute n’est pas spécifiée dans la directivelisten
, nginx cherchera à écouter sur toutes les interfaces réseaux configurées et ne pourra redémarrer car inetd écoute déjà sur l’interface localhost. -
deux directives
upstream
sont déclarées, chacune pour gérer correctement le protocole IPv4 ou IPv6, et sont mappées pour n’avoir qu’un seul proxy à appeler. -
un dernier mot, concernant les directives
ssl_ciphers
,ssl_ecdh_curve
,ssl_prefer_server_ciphers
, etssl_protocols
, elles ne sont pas strictement nécessaires mais utiles pour renforcer les préférences d’utilisation.ssl_protocols
permet de prioriser la version de TLS, sachant que :
Servers MUST use TLS version 1.2 or higher and SHOULD use TLS version 1.3 or higher.
PF
Voici un exemple de règles minimalistes à ajouter à PF :
host = adresse_ipv4
host6 = adresse_ipv6
pass in quick on egress proto tcp from any to { $host $host6 } port 1965
Pensez à recharger le jeu de règles par PF :
$ doas pfctl -f /etc/pf.conf
Voilà !
Il ne vous reste plus qu’à créer votre premier fichier index.gmi
et les
suivants et les déposer dans le répertoire correspondant à votre répertoire
de publication… en n’oubliant pas de poser les droits de l’utilisateur
dédié dessus.
Surveillance
Mais qui surveille ?
⇒ L’activité est enregistrée dans les deux logs ‘daemon’ et ‘messages’.
$ grep vger /var/log/messages
May 1 10:54:28 sh1 useradd[86659]: new group added: name=_vger, gid=1011
May 1 10:54:28 sh1 useradd[86659]: new user added: name=_vger, uid=1011, gid=1011, home=/var/gemini, shell=/sbin/nologin
May 1 12:09:53 sh1 vger: request gemini://huc.fr.eu.org/
May 1 13:00:59 sh1 vger: request gemini://huc.fr.eu.org/
⇒ Il est possible de surveiller l’activité de l’utilisateur _vger avec - mais dans ce cas, franchement peu utile :
top -U _vger
fstat -u _vger -n
ps aux -U _vger
Dépannage
⇒ Pour vérifier que le service inetd écoute en local, il est possible de lui envoyer la requête suivante :
$ printf '%s\r\n' "gemini://huc.fr.eu.org" | vger -v -d /var/gemini
20 text/gemini;
# huc.fr.eu.org|gemini
(…)
- Si la réponse est similaire, c’est que vger écoute bien en local !
- Si vous avez pour réponse
telnet: Unable to connect to remote host: Connection refused
, c’est certainement soit que le serviceinetd
ne peut répondre - est-il actif ? ou qu’il y a un problème dans sa configuration. Vérifiez !
⇒ Vérifier que le port 1965 soit ouvert en écoute sur vos adresses IP :
$ netstat -an | grep 1965
tcp 0 0 *.1965 *.* LISTEN
tcp 0 0 46.23.90.29.1965 *.* LISTEN
tcp6 0 0 2a03:6000:6e65:6.1965 *.* LISTEN
tcp6 0 0 *.1965 *.* LISTEN
⇒ Pour finir, vous pouvez vérifier avec l’outil telnet
sur le port 1965,
en local et depuis une autre machine que le service écoute.
Documentations
- l’article de Solène à-propos de Nginx as a TCP/UDP relay - en anglais
- la documentation du protocol Gemini : https://gemini.circumlunar.space/docs/ - en anglais
- Readme du paquet certbot
Manpages
- pledge(4) , unveil(4)
- une fois installé le manpage :
man 8 vger
- le fichier pkg-readme dans
/usr/local/share/doc/pkg-readmes/vger