Avoir des mots de passe solides, c’est bien (et même indispensable), mais s’en souvenir… c’est dur. On serait tenté de tout enregistré dans son navigateur, avec un mot de passe maître pour stocker les mots de passe de façon chiffrée mais… Firefox par exemple a un système de chiffrement par mot de passe maître tout pourri.
Il existe un paquet de gestionnaire de mot de passe libre. Évacuons tous ceux basé sur KeePass ou ses successeurs : pour utiliser ses mots de passe sur un autre PC ou sur son téléphone, il faut synchroniser le fichier contenant les mots de passe et s’il y a un souci de synchro et que le fichier se retrouve corrompu… paf, pastèque !.
J’ai essayé Passbolt ou encore l’application Passman de Nextcloud mais quand j’utilisais la sécurité maximale qu’ils proposent… mon Firefox plantait (oui, quand on me propose des réglages de parano, je les utilise). Sans compter qu’ils ne proposent pas d’appli Android.
Et puis, j’ai testé Bitwarden. Et c’est pas mal du tout, mais… c’est du C# et ça utilise une base de données SQL Server. Deux trucs Microsoft.
Bon, passant outre mon aversion, j’ai testé. Dans du Docker (quand je vous dis que je suis passé outre mon aversion !). C’était pas mal du tout.
Mais en voulant tester le partage de mot de passe, j’ai rencontré une limitation : pour créer une organisation (un groupe de personnes qui se partagent des mots de passe) de plus de deux personnes, il faut payer, même quand on héberge soi-même le serveur Bitwarden. Pourquoi pas. C’est un business model comme un autre (mais bon, grmpf).
Par contre, les tarifs, c’est un très gros grmpf : 3 dollars par utilisateur et par mois. Cela ferait 3$ * 35 personnes * 12 mois = 1 260$ par an. Y a un autre plan qui pourrait convenir, qui nous reviendrait à 780$ par an. C’est quand même pas négligeable alors qu’on hébergerait nous-même le service.
J’avais laissé tombé quand ces derniers jours, une implémentation en Rust de Bitwarden est passée dans ma timeline Mastodon : https://github.com/dani-garcia/bitwarden_rs. Et celle-ci n’a pas la limitation sur les équipes (mais il encourage à donner des sous au projet upstream).
J’ai d’abord testé avec le container Docker fourni par le développeur puis j’ai tenté la compilation pour voir si ça passait, et ça passe crème !
La grosse différence, outre la non-limitation des organisations, c’est que la base de données est, pour l’instant, SQLite. Ce qui peut avoir des conséquences sur les performances lorsque la base est très sollicitée.
Bref, voyons comment compiler et installer cette version de Bitwarden en Rust.
Compilation
On va avoir besoin des backports Debian pour installer npm
(pour compiler l’interface web) :
echo "deb http://ftp.debian.org/debian stretch-backports main" | sudo tee /etc/apt/sources.list.d/backports.list
sudo apt update
Installation des dépendances :
sudo apt install pkg-config libssl-dev
sudo apt install -t stretch-backports npm
Installation de rustup, qui nous fournira le compilateur Rust :
curl https://sh.rustup.rs -sSf > rustup.sh
On n’exécute pas direct un script tiré du web ! On regarde d’abord s’il ne va pas faire de saloperies :
vi rustup.sh
On le rend exécutable :
chmod +x rustup.sh
On installe le compilateur Rust (il sera dans notre $HOME
) :
./rustup.sh --default-host x86_64-unknown-linux-gnu --default-toolchain nightly
On source un fichier qui nous permet de l’appeler
source $HOME/.cargo/env
Gagnons du temps en clonant le projet bitwarden_rs et l’interface web (qu’il faut compiler aussi) en même temps .
git clone https://github.com/dani-garcia/bitwarden_rs
git clone https://github.com/bitwarden/web.git web-vault
Compilation de Bitwarden_rs :
cd bitwarden_rs
cargo build --release
Le résultat de la compilation est dans bitwarden_rs/target/release/
.
Compilation de l’interface web :
cd ../web-vault
# On se positionne sur le dernier tag en date
git checkout "$(git tag | tail -n1)"
# Un petit patch pour que ça fonctionne avec notre installation
wget https://raw.githubusercontent.com/dani-garcia/bw_web_builds/master/patches/v2.8.0.patch
# On vérifie le patch
cat v2.8.0.patch
git apply v2.8.0.patch
npm run sub:init
npm install
npm run dist
ATTENTION : on m’a dit que la compilation de l’interface web prenait 1,5Gio de RAM, assurez-vous que vous en avez assez de libre.
Et on copie l’interface web dans le dossier où attend le résultat de la compilation de bitwarden_rs :
cp -a build/ ../bitwarden_rs/target/release/web-vault/
Installation
On va installer Bitwarden_rs dans /opt/bitwarden
et on le fera tourner avec l’utilisateur www-data
:
cd ..
sudo rsync -a --info=progress2 bitwarden_rs/target/release/ /opt/bitwarden/
chown -R www-data: /opt/bitwarden
Puis on va créer un service systemd
, /etc/systemd/system/bitwarden.service
:
[Unit]
Description=Bitwarden Server (Rust Edition)
Documentation=https://github.com/dani-garcia/bitwarden_rs
After=network.target
[Service]
# The user/group bitwarden_rs is run under. the working directory (see below) should allow write and read access to this user/group
User=www-data
Group=www-data
# The location of the .env file for configuration
EnvironmentFile=/etc/bitwarden_rs.env
# The location of the compiled binary
ExecStart=/opt/bitwarden/bitwarden_rs
# Set reasonable connection and process limits
LimitNOFILE=1048576
LimitNPROC=64
# Isolate bitwarden_rs from the rest of the system
PrivateTmp=true
PrivateDevices=true
ProtectHome=true
ProtectSystem=strict
# Only allow writes to the following directory and set it to the working directory (user and password data are stored here)
WorkingDirectory=/opt/bitwarden/
ReadWriteDirectories=/opt/bitwarden/
[Install]
WantedBy=multi-user.target
Pour l’interface d’administration, on va créer un token avec :
openssl rand -base64 48
La configuration se fait via des variables d’environnement qu’on va mettre dans /etc/bitwarden_rs.env
:
SIGNUPS_ALLOWED=false
WEBSOCKET_ENABLED=true
ADMIN_TOKEN=Un token généré avec `openssl rand -base64 48`
ROCKET_ADDRESS=127.0.0.1
WEBSOCKET_ADDRESS=127.0.0.1
SMTP_HOST=127.0.0.1
SMTP_FROM=
bi*******@ex*****.org
SMTP_PORT=25
SMTP_SSL=false
Vous remarquerez que je dis à Bitwarden d’envoyer les mails via le serveur SMTP local. À vous de faire en sorte qu’il fonctionne. Allez voir le wiki du projet pour voir quelles variables vous pourriez ajouter, enlever, modifier…
Puis :
sudo systemctl daemon-reload
sudo systemctl enable bitwarden
sudo systemctl start bitwarden
sudo systemctl status bitwarden
Nginx
On installe Nginx s’il n’est pas déjà installé :
sudo apt install nginx
Configuration du virtualhost :
server {
listen 80;
listen [::]:80;
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name bitwarden.example.org;
access_log /var/log/nginx/bitwarden.access.log;
error_log /var/log/nginx/bitwarden.error.log;
ssl_certificate /etc/letsencrypt/live/bitwarden.example.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/bitwarden.example.org/privkey.pem;
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:5m;
ssl_prefer_server_ciphers On;
ssl_protocols TLSv1.2;
ssl_ciphers 'EECDH+aRSA+AESGCM:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH:+CAMELLIA256:+AES256:+CAMELLIA128:+AES128:+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:!ECDSA';
ssl_dhparam /etc/ssl/private/dhparam4096.pem;
add_header Strict-Transport-Security max-age=15768000; # six months
gzip off;
if ($https != 'on') {
rewrite ^/(.*)$ https://bitwarden.example.org/$1 permanent;
}
root /var/www/html;
# Allow large attachments
client_max_body_size 128M;
location ^~ '/.well-known/acme-challenge' {
default_type "text/plain";
root /var/www/certbot;
}
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://127.0.0.1:8000;
}
location /notifications/hub {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://127.0.0.1:3012;
}
location /notifications/hub/negotiate {
proxy_pass http://127.0.0.1:8000;
}
}
Pour créer /etc/ssl/private/dhparam4096.pem
:
sudo openssl dhparam -out /etc/ssl/private/dhparam4096.pem 4096
Pour le certificat Let’s Encrypt, on commente le brol relatif à ssl
puis :
sudo nginx -t && sudo nginx -s reload
sudo apt install certbot
sudo mkdir /var/www/certbot/
certbot certonly --rsa-key-size 4096 --webroot -w /var/www/certbot/ --agree-tos --text --renew-hook "/usr/sbin/nginx -s reload" -d bitwarden.example.org
Une fois qu’on a le certificat, on décommente le brol ssl
puis :
sudo nginx -t && sudo nginx -s reload
Sauvegarde
Créer le script de sauvegarde /opt/backup_bitwarden.sh
:
#!/bin/bash
function bwbackup {
DATE=$(date '+%a%H')
# Database
if [[ ! -d /opt/backup_bitwarden/sqlite-backup/ ]]
then
mkdir -p /opt/backup_bitwarden/sqlite-backup/
fi
echo ".backup /opt/backup_bitwarden/sqlite-backup/db.${DATE}.sqlite3" | sqlite3 /opt/bitwarden/data/db.sqlite3 2>> /opt/backup_bitwarden/backup.log
if [[ "$?" -ne "0" ]]
then
echo "Something went wrong with bitwarden database backup, please see /opt/backup_bitwarden/backup.log on verity" | mail -s "Bitwarden database backup"
yo*********@ma**.org
bwbackup
fi
# Files
if [[ ! -d /opt/backup_bitwarden/files-backup/ ]]
then
mkdir -p /opt/backup_bitwarden/files-backup/
fi
rsync -a --delete --exclude db.sqlite3 /opt/bitwarden/data/ /opt/backup_bitwarden/files-backup/$DATE/ 2>> /opt/backup_bitwarden/backup.log
if [[ "$?" -ne "0" ]]
then
echo "Something went wrong with bitwarden files backup, please see /opt/backup_bitwarden/backup.log on verity" | mail -s "Bitwarden files backup"
yo*********@ma**.org
bwbackup
fi
}
bwbackup
Puis :
sudo chmod +x /opt/backup_bitwarden.sh
sudo mkdir /opt/backup_bitwarden
sudo chown www-data: /opt/backup_bitwarden
sudo apt install sqlite3
Puis, dans le cron de l’utilisateur www-data
:
42 4 * * * /opt/backup_bitwarden.sh
Logs
J’aime bien avoir mes logs dans un dossier dédié pour ce genre de service.
Dans /etc/rsyslog.d/bitwarden.conf
:
if $programname == 'bitwarden_rs' then /var/log/bitwarden/bitwarden.log
if $programname == 'bitwarden_rs' then ~
Dans /etc/logrotate.d/bitwarden
:
/var/log/bitwarden/bitwarden.log
{
rotate 52
dateext
weekly
missingok
notifempty
compress
sharedscripts
postrotate
invoke-rc.d rsyslog rotate > /dev/null
endscript
}
Puis :
sudo mkdir /var/log/bitwarden
sudo chown root:adm /var/log/bitwarden
sudo service rsyslog restart
Fail2ban
Un fail2ban qui surveille les logs, ça permet de bloquer les petits malins qui font du bruteforce
Dans /etc/fail2ban/filter.d/bitwarden.conf
:
[INCLUDES]
before = common.conf
[Definition]
failregex = ^.*Username or password is incorrect\. Try again\. IP: <HOST>\. Username:.*$
ignoreregex =
Dans /etc/fail2ban/jail.d/bitwarden.local
:
[bitwarden]
enabled = true
port = 80,443
filter = bitwarden
action = iptables-allports[name=bitwarden]
logpath = /var/log/bitwarden/bitwarden.log
maxretry = 3
bantime = 14400
findtime = 14400
Pour la page d’admin, dans /etc/fail2ban/filter.d/bitwarden-admin.conf
:
[INCLUDES]
before = common.conf
[Definition]
failregex = ^.*Unauthorized Error: Invalid admin token\. IP: <HOST>.*$
ignoreregex =
Dans /etc/fail2ban/jail.d/bitwarden-admin.local
:
[bitwarden-admin]
enabled = true
port = 80,443
filter = bitwarden-admin
action = iptables-allports[name=bitwarden]
logpath = /var/log/bitwarden/bitwarden.log
maxretry = 3
bantime = 14400
findtime = 14400
Finalement :
sudo service fail2ban restart
Conclusion
Voilà, vous devriez avoir un serveur Bitwarden_rs fonctionnel. Plus qu’à aller sur l’interface web que vous venez de mettre en place ou télécharger les clients et à les utiliser !
Pour importer vos mots de passe de Firefox, il faut passer par une application pour les exporter, puis aller dans les outils de votre client (ou de l’interface web).