Borgbackup: it’s complicated

As I wrote in a previous article, I'm using Borgbackup to back up some servers and workstations. And most of the time it's going OK. Unfortunately, when it's not OK, it can be very (very) hard to recover. Spoiler alert: one of my backup repositories had a problem, it took me 16 days and 1131 connections to the repository to fix it.

Few weeks ago, I've noticed that the Borg repository for the backups of my MacBook Pro was holding way too many backups. The pruning process was not doing its job properly. So I’ve started to investigate, and discovered that every attempt to prune older backups failed.
Trying to check the repository failed too: every single time the connection was reset. Apparently the remote server was dropping the SSH connection after a while (between 20 and 90 minutes). Client-side the error message was Connection closed by remote host.
I started to wonder if the problem was the very large number of backups, so I tried to delete backups manually. Some of them were easy to delete but most of the older backups needed delete --force and even delete --force --force, which is pretty bad.
Basically, I destroyed two years worth of backups, but it was still impossible to check and repair the repository. Also, the use of --force and --force --force makes it impossible to reclaim the space until you repair the repository.

Digging in the (mis)direction of a connection problem I’ve tried everything I could. It failed every single time:

  • tune ClientAliveInterval and ClientAliveCountMax server-side
  • tune ServerAliveInterval and ServerAliveCountMax client side
  • using and not using multiplexed ssh connections
  • moving the client to another physical network
  • using caffeinate to launch the borg command
  • using Amphetamine
  • upgrading ssh on the client
  • upgrading borg
  • giving mosh a try (nope)
  • running ssh with -vvv
  • using ktrace server-side to find the cause

None of this helped at all. Not to find a cause, not to make it work properly.
Eventually I stumbled upon this blog post: Repair Badly Damaged Borg Repository.

The repair method described failed too:
- step check --repair --repository-only worked
- but check --repair --archives-only died with the same Connection closed by remote host.
As a workaround attempt I’ve scripted a loop that would do check --repair --archives-only on every archive individually (~630).
After 3 full days and more than 600Go transferred from the repo to the client, every archives were checked and none was faulty.
Next step was to attempt check --repair again on the whole repository. About 15 hours later the output was

2851697 orphaned objects found!
Archive consistency check complete, problems found.

Full working solution for me:

export BORG_CHECK_I_KNOW_WHAT_I_AM_DOING=YES 
borg check -p --repair --repository-only LOGIN@HOST:/path/to/repo
borg -p list LOGIN@HOST:/path/to/repo | awk '{print $1}' > listborg
cat listborg | while read i; do 
	borg -vp check --repair --archives-only LOGIN@HOST:/path/to/repo::$i
done
borg -p check --repair LOGIN@HOST:/path/to/repo

Final step was to reclaim space on the server with compact:

$ borg compact -p --verbose path/to/repo/
compaction freed about 376.22 GB repository space.

Boy that was painful!

I’m pretty sure it’s not really an ssh issue. Something is causing the connection to drop but I have ssh connections opened for days between that client and that server, so I guess ssh is not the problem here. Also, borgbackup’s github is loaded with issues about failing connections. In the end it boils down to:
- borg repositories can break badly without warning
- repairing a repo might not worth the bandwidth/CPU/IOs

Related posts

Recherche Administrateur/trice Systèmes

Au sein du Service Opérations de la DSI de l'Université Lyon 2, nous cherchons un ou une Administrateur/trice Systèmes pour renforcer notre équipe et nous aider à relever des défis au quotidien.
Lieu de travail : campus de Bron (arrêt de tram T2 Europe Université).

  • Vous habitez la région Lyonnaise ou êtes mobile ;
  • Vous êtes motivée par les enjeux de la gestion d’un parc de plus de 600 serveurs Linux RedHat/CentOS (70%), Windows, FreeBSD ;
  • Les problématiques d’une ferme de virtualisation multi-site avec balance de charge, PRA, sauvegardes croisées ne vous font pas peur ;
  • Les infrastructures à fort enjeu de disponibilité, les outils d’automatisation, de monitoring et les SIEM vous intéressent ;
  • Vous êtes passionnée par les problématiques système et souhaitez évoluer dans un environnement riche et varié ;
  • Vous êtes curieuse, très rigoureuse et vous avez le sens du service.

Si vous vous reconnaissez dans ce profil, contactez-moi !

terminal - édition d'un script shell

Édition d'un script shell dans le terminal

Related posts

Moving to Borgbackup

I used to have a quite complicated backup setup, involving macOS Time Machine, rsync, shell scripts, ZFS snapshots, pefs, local disks, a server on the LAN, and a server 450 km away. It was working great but I've felt like I could use a unified system that I could share across every systems and that would allow me to encrypt data at rest.
Pure ZFS was a no-go: snapshot send/receive is very nice but it lacks encryption for data at rest (transfer is protected by SSH encryption) and macOS doesn't support ZFS. Rsync is portable but does not offer encryption either. Storing data in a pefs vault is complicated and works only on FreeBSD.
After a while, I've decided that I want to be able to store my encrypted data on any LAN/WAN device I own and somewhere on the cloud of a service provider. I've read about BorgBackup, checked its documentation, found a Borg repository hosting provider with a nice offer, and decided to give it a try.

This is how I've started to use Borg with hosting provider BorgBase.

Borg is quite simple, even though it does look complicated when you begin. BorgBase helps a lot, because you are guided all along from ssh key management to creation of your first backup. They will also help automating backups with a almost-ready-to-use borgmatic config file.

Borg is secure: it encrypts data before sending them over the wire. Everything travels inside an SSH tunnel. So it's perfectly safe to use Borg in order to send your backups away in the cloud. The remote end of the SSH tunnel must have Borg installed too.

Borg is (quite) fast: it compresses and dedup data before sending. Only the first backup is a full one, every other backup will send and store only changed files or part of files.

Borg is cross-plateform enough: it works on any recent/supported macOS/BSD/Linux.

Borg is not for the faint heart: it's still command line, it's ssh keys to manage, it's really not the average joe backup tool. As rsync.net puts it: "You're here because you're an expert".

In the end, the only thing I'm going to regret about my former home-made backup system was that I could just browse/access/read/retrieve the content of any file in a backup with just ssh, which was very handy. With Borg this ease of use is gone, I'll have to restore a file if I want to access it.

I won't detail every nuts and bolts of Borg, lots of documentation exists for that. I would like to address a more organizational problem: doing backups is a must, but being able to leverage those backups is often overlooked.
I backup 3 machines with borg: A (workstation), B (home server), C (distant server). I've setup borgmatic jobs to backup A, B and C once a day to BorgBase cloud. Each job uses a dedicated SSH key and user account, a dedicated Repository key, a dedicated passphrase. I've also created similar jobs to backup A on B, A on C, B on C (but not Beyoncé).
Once you are confident that every important piece of data is properly backed up (borg/borgmatic job definition), you must make sure you are capable of retrieving it. It means even if a disaster occurs, you have in a safe place:

  • every repository URIs
  • every user accounts
  • every SSH keys
  • every repository keys
  • every passphrases

Any good password manager can store this. It's even better if it's hosted (1password, dashlane, lastpass, etc.) so that it doesn't disappear in the same disaster that swallowed your data. Printing can be an option, but I would not recommend it for keys, unless you can encode them as QRCodes for fast conversion to digital format.

You must check from time to time that your backups are OK, for example by restoring a random file in /tmp and compare to current file on disk. You must also attempt a restoration on a different system, to make sure you can properly access the repository and retrieve files on a fresh/blank system. You can for example create a bootable USB drive with BSD/Linux and borg installed to have a handy recovery setup ready to use in case of emergency.

Consider your threat model, YMMV, happy Borg-ing.

Related posts

Cartographie de l’utilisation d’un clavier

Il y a quelques temps je me suis mis en tête d'investir dans des claviers mécaniques de bonne facture. L'exercice va se solder notamment par l'achat d'un Vortex ViBE sur lequel il manque pas mal de touches par rapport à un clavier étendu grand public.
J'ai donc voulu faire un état des lieux de mon utilisation actuelle du clavier étendu dans mes activités privées et professionnelles, raison pour laquelle j'ai investi dans un enregistreur de frappes clavier.
Après environ 3,5 jours d'utilisation de ce keylogger j'ai obtenu un fichier de ~55000 "touches pressées".
J'ai plusieurs options pour exploiter ce fichier : un compte-rendu statistique en chiffres et graphiques ou une cartographie visuelle (heatmap). J'ai choisi la cartographie dans un premier temps pour sa lisibilité immédiate. C'est par contre une option complexe à mettre en œuvre. Il existe différentes pistes pour réaliser une heatmap de clavier sur la base d'un texte fourni par l'utilisateur, mais toutes celles que j'ai trouvées utilisent un clavier réduit et ne proposent pas la disposition AZERTY.
La seule piste viable était donc de trouver une solution libre et ouverte, dans un langage que je comprenne a minima, de sorte que je puisse modifier le programme pour l'adapter à un clavier étendu en français.
J'ai jeté mon dévolu sur Tapmap, petit programme codé en Python 3. La première étape a été de valider que le programme fonctionne sur mon PC sous FreeBSD, après une installation via pip install --user pour épargner mon système. Le test avec un jeu de données bidons ayant été concluant, le plus gros du travail restait à faire. Avant d'attaquer la modification du code de l'application pour étendre la liste des caractères pris en charge j'ai remplacé le fichier keyboard.png représentant un clavier qwerty court par un clavier azerty étendu. Par chance le clavier initial est de marque Apple, ci-bien qu'il est exactement superposable à une image de mon propre clavier. Cela évite d'avoir à refaire toute la correspondance entre un caractère et ses coordonnées physiques sur l'image du clavier. Attention, l'image du clavier doit être en PNG avec une couche alpha, sinon le logiciel ne pourra pas lui superposer la heatmap.
À partir de là il reste le plus dur : faire correspondre chaque caractère enregistré par le keylogger à une zone de pixel sur l'image du clavier. Le programme tapmap est très simple : pour chaque caractère présent dans le fichier en entrée, il cherche une correspondance dans un tableau de coordonnées. Cela impose que chaque caractère qu'on veut représenter soit décrit de manière unique dans la table de correspondance, et que chaque touche qu'on souhaite représenter soit codée par un caractère unique.
De ce constat découlent deux problèmes : le 1 en haut à gauche du clavier doit être traité différemment du 1 du pavé numérique, les codes multi-caractères enregistrés par le keylogger doivent être convertis en caractères uniques. Par exemple quand le keylogger enregistre [1N] il indique que le 1 du pavé numérique a été tapé, quand il enregistre [Sh]1 il indique que la touche majuscule a été pressée pour taper le chiffre 1 en haut à gauche du clavier. Dans le même esprit [Alt][Sh]° représente le caractère ] obtenu par pression sur les touches alt-maj-) du clavier.
Pour palier ces deux problèmes d'un seul coup j'ai converti l'ensemble des codes spécifiques en caractères spéciaux (des lettres grecques en majorité). Ainsi le 1 du pavé numérique ([1N]) devient ρ, le 0 ([0N]) devient π, etc. Via un script shell (juste une grosse commande sed) je transforme le fichier du keylogger en fichier utilisable par tapmap où chaque caractère représente de manière univoque une touche du clavier.
Par de nombreux tests successifs la table de correspondance entre caractères et emplacements sur l'image est complétée avec les spécificités du clavier Apple français, et les touches supplémentaires du clavier étendu. Au final, j'obtiens ces résultats comme synthèse de mes ~55K touches enregistrées :




En fonction du choix de gradient de couleurs la lisibilité est très variable, le second rendu permet par exemple de distinguer bien plus de nuances que les deux autres puisqu'on y aperçoit même les frappes sur le pavé numérique.
En supprimant du fichier source tous les caractères qui ne représentent pas des chiffres il devient possible de comparer l'utilisation du pavé numérique avec l'utilisation des chiffres du haut du clavier :

Dans mon cas le petit doigt de la main gauche appuie sur "maj" et l'index et le majeur atteignent les chiffres de 1 à 5, alors que la main droite se reporte spontanément sur le pavé numérique, que j'utilise aussi systématiquement pour poser des calculs ou taper des adresses IP.

Related posts

Install Fast Incident Response (FIR) on FreeBSD

FIR login screen FIR is a web application designed by CERT Société Générale. It's coded in Python and uses Django.

Installation as documented uses Nginx and pip, two tools I'm not using. I already run several Apache servers, and I do prefer relying on pkg for software installation. For me, pip is more a developer tool: very convenient with virtualenv but not what I would use for production.
If you want to use pip, just go with the official documentation :)

So on a FreeBSD 11.2-RELEASE server, you need to install all required packages. Be careful, py27-MySQLdb uses mysql56-server, not mysql57-server, and FIR works with Python 2.7, not 3.x (as far as I can say).

$ sudo pkg install gettext mysql56-server py27-pip py27-virtualenv git apache24 uwsgi py27-MySQLdb py27-django py27-cssselect py27-django-filter py27-djangorestframework py27-flup6 py27-gunicorn py27-lxml py27-markdown py27-pymongo py27-pyquery py27-dateutil py27-pytz py27-six py27-django-treebeard py27-markdown2 py27-bleach py27-python-gettext

Add those lines to /etc/rc.conf:

mysql_enable="yes"
uwsgi_enable="yes"
apache24_enable="yes"

The requirement list includes dj-database-url and whitenoise, but I was not able to find them in FreeBSD's packages. I've just ignored them and everything seems to work fine.
If needed, sudo pip install… should do the trick.

Follow the documentation:
- configure MySQL
- install FIR without virtualenv (in /usr/local/www for example)
- create and tune production.py
- create installed_apps.txt (you do want the plugins)
- create tables in the db
- create the admin user
- populate the db
- collect static files

On FreeBSD we run uwsgi as a service, under uwsgi UID. So chown must reflect that:

$ sudo chown uwsgi logs/errors.log uploads
$ sudo chmod 750 logs/errors.log uploads

Skip the uWSGI section of the documentation. Instead, create config file for uwsgi with this content:

$ cat /usr/local/etc/uwsgi/uwsgi.ini
[uwsgi]
chdir = /usr/local/www/FIR
module = fir.wsgi

You can now start the service:

$ sudo service uwsgi start

Then, skip the nginx part, and go configure Apache:

- load proxy_module and proxy_uwsgi_module in httpd.conf
- add the following to the relevant part of Apache configuration:

# FIR
ProxyPass /FIR unix:/tmp/uwsgi.sock|uwsgi://usr/local/www/FIR
Alias /files/ /usr/local/www/FIR/files/
Alias /static/ /usr/local/www/FIR/static/
<Directory /usr/local/www/FIR/static>
	Require all granted
</Directory>
<Directory /usr/local/www/FIR/files>
	Require all granted
</Directory>

Restart Apache: you're all set, point your browser to https://your-server/FIR/

Related posts

My take on the MySpace dump

About a year ago, a full MySpace data breach dump surfaced on the average-Joe Internet. This huge dump (15 GiB compressed) is very interesting because many user accounts have two different password hashes. The first hash is non-salted, and represents a lower-cased, striped to 10 characters, version of the user original password. The second hash, not always present, is salted, and represents the full original user password.
Hence, the dump content can be summarized by this :

id : email : id/username : sha1(strtolower(substr($pass, 0, 9))) : sha1($id . $pass) 

It contains about 116.8 million unique unsalted sha1 hashes, and about 68.5 million salted sha1 hashes.

Of course, people who crack passwords will tell you that the unsalted hashes have no value, because then don't represent real user passwords. They are right. But when you crack those hashes you have a very interesting password candidate to crack the salted hashes. And this is very interesting!

After you cracked most of unsalted hashes, the question is: how do you proceed to crack their salted counterpart? Spoiler alert: hashcat on an Nvidia GTX 1080 is more than 200 times slower than John the Ripper on a single CPU core on this very particular job.

I'm a long time John the Ripper user (on CPU), and I'm pretty fan of it's intelligent design. Working on CPU requires wits and planing. And the more versatile your software is, the more efficient you can be. Hashcat sits on the other end of the spectrum: huge raw power thanks to GPU optimization. But it lacks the most sensible attack mode: "single".

Single mode works by computing password candidates from GECOS data like login, user name, email address, etc. So it makes sense to provide a full password file to JtR, instead of just naked hashes. These passwords metadata are very efficient when you want to create contextual password candidates.
The password retrieved from unsalted hash is more than a clue to retrieve its salted counterpart, in many case it's also the real user password. And when it's not, simple variations handled by mangling rules will do the trick.
You've probably guessed by now: I've created a file where password cracked from non-salted hashes are paired with the corresponding salted hash. The known password impersonate the user login, so that with proper tuning John the Ripper will try only this particular candidate against the corresponding salted hash.
Because of a bug in JtR, I was not able to use this attack on a huge file, I had to split it into small chucks. Nevertheless, I was able to retrieve 36708130 passwords in just 87 minutes. On a single CPU core.
In order to find those passwords with hashcat, I had to rely on a wordlist attack with on a GTX 1080. It took about 14 days to complete. No matter how fast your GPU is (about 1000 MH/s in that particular case), it will brainlessly try every single candidate on every single hash. Remember hashes are salted, so each one requires its own computation. If your file is 60M hashes long, then your GPU will only try 16.6 candidates per second (1000/60). It's very slow and inefficient.

Hashcat performance on a file containing 50% of total hashes.

Sometime, brain is better than raw power. Thank you John ;)

More on this topic:
https://hashes.org/forum/viewtopic.php?t=1715
http://cynosureprime.blogspot.fr/2016/07/myspace-hashes-length-10-and-beyond.html

Related posts

Self-hosted password manager: installing Passbolt on FreeBSD

Arthur Duarte CC-BY-SA-4.0

Arthur Duarte CC-BY-SA-4.0

Password managers, or password safes, are an important thing these days. With the constant pressure we (IT people) put our users under to setup a different password for every single registration/application/web site, it's the best, if not only, way to keep track of these secrets. On one hand, the isolated client-side software can be really powerful and/or well integrated with the OS or the software ecosystem of the user, but it lacks the modern touch of "cloud" that makes your data available anywhere and anytime. On the other hand, a full commercial package will come with client for every device you own, and a monthly fee for cloud synchronization, but you have absolutely no control over your data (just imagine that tomorrow the company you rely on goes bankrupt).
Better safe than sorry: I don't rely on cloud services. It comes at a cost, but it's quite rewarding to show the world another way exists.
Disclaimer: I don't give a sh*t about smartphones, so my needs are computer-centric.

In order to store passwords, and more generally speaking "secrets", in such a way that I can access them anywhere/anytime, I've tried Passbolt. Passbolt is an OpenSource self-hosted password manager, written in PHP/Javascript with a database back end. Hence, install and config are not for the average Joe. On the user side it's quite clean and surprisingly stable for alpha software. So once a LAMP admin has finished installing the server part, any non-skilled user can register and start storing passwords.

Enough chit-chat, let's install.

My initial setup was a vanilla FreeBSD 10.3 install, so I've had to make everything. I won't replay every single step here, especially on the configuration side.

Prerequisites:

pkg install apache24
pkg install mod_php56
pkg install php56-gd
pkg install pecl-memcached
pkg install mysql57-server
pkg install pecl-gnupg
pkg install git
pkg install php56-pdo_mysql
pkg install sudo
pkg install php56-openssl
pkg install php56-ctype
pkg install php56-filter

Everything else should come as a dependency.

Tuning:

Apache must allow .htaccess, so you'll have to put an AllowOverride All somewhere in your configuration. You must also load the Rewrite module. Also, go now for SSL (letsencrypt is free and supported). Non-SSL install of Passbolt are for demo purpose only.
Apache will also need to execute gnupg commands, meaning the www user needs an extended $PATH. The Apache startup script provided on FreeBSD sources Apache environment variables from /usr/local/sbin/envvars and this very file sources every /usr/local/etc/apache24/envvars.d/*.env, so I've created mine:

$ cat /usr/local/etc/apache24/envvars.d/path.env
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/games:/usr/local/sbin:/usr/local/bin

You also need to tune your MySQL server. If you choose the 5.7, you must edit it's configuration. Just add the following line into [mysqld] section of /usr/local/etc/mysql/my.cnf:

sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'

This is due to a bug in Passbolt and could be useless in a not to distant future.

Install recipe:

You can now follow the install recipe at https://www.passbolt.com/help/tech/install.
Generating the GPG key is quite straightforward but you have to keep in mind that Apache's user (www) will need access to the keyring. So if you create this key and keyring with a different user, you'll have to mv and chown -R www the full .gnupg directory somewhere www can read it (outside DocumentRoot is perfectly fine).

Use git to retrieve the application code into appropriate path (according to your Apache config):

cd /usr/local/www
git clone https://github.com/passbolt/passbolt.git

Edit php files as per the documentation.

Beware the install script: make sure you chown -R www the whole passbolt directory before using cake install.
On FreeBSD you won't be able to use su to run the install script, because www's account is locked. You can use sudo instead:

sudo -u www app/Console/cake install --no-admin

Same for the admin account creation:

sudo -u www app/Console/cake passbolt register_user -u patpro@example.com -f Pat -l Pro -r admin

Follow the end of the install doc, and you should be ok. Install the Firefox passbolt extension into your browser, and point to your server.

I'm pretty happy with passbolt so far. I'll have to install a proper production server, with SSL and all, but features are very appealing, the passbolt team is nice and responsive, and the roadmap is loaded with killing features. Yeah BRING ME 2FA \o/.

Related posts

Escaping the Apple ecosystem: part 3

In part 2, I was able to create and use a Windows 7 VM with the Radeon R9 270x in passthrough. It works really great. But OSX and Linux where more difficult to play with.

List of virtual machines

List of virtual machines


Since then, I've made tremendous progress: I've managed to run an OSX 10.11.6 VM properly, but more importantly, I've managed to run my native Mac OS X 10.6.8 system as a VM, with the Mac's Radeon in passthrough.
I've removed my Mac OS X SSD and the Mac's graphics card from the Mac Pro tower, and installed them into the PC tower. Then I've created the VM for the 10.6.8 system, configured ESXi to use Mac's Radeon with VT-d, etc.
The only real problem here is that adding a PCI card into the PC tower makes PCI device numbers change: it breaks almost every passthrough already configured. I had to remake VT-d config for the Windows VM. Apart from that, it went smoothly.
Currently, I'm working on my native 10.6.8 system, that runs as a VM, and the Windows VM is playing my music (because the Realtek HD audio controller is dedicated to the Windows VM).
Moving from a Mac Pro with 4-core 2.8 GHz Xeon to a 6-core 3.5 GHz Core i7 really gives a boost to my old 10.6.8 system.

Running both OSes, the box is almost as silent as the Mac Pro while packing almost twice as more raw CPU power and 2.7x more GPU power.

The Mac Pro is now empty: no disks, no graphics card, and will probably go on sale soon.

to-do list:

  • secure the whole infrastructure ;
  • install 2nd-hand MSI R9 270x when it's delivered ;
  • properly setup Linux to use AMD graphics card.

I might also add few SSDs and a DVD burner before year's end.

Related posts