<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
 <channel>
   <title>Solene'%</title>
   <description></description>
   <link>https://dataswamp.org/~solene/</link>
   <atom:link href="https://dataswamp.org/~solene/rss.xml" rel="self" type="application/rss+xml" />
   <item>
 <title>How to trigger a command on Linux when disconnected from power</title>
 <description>
   <![CDATA[
<pre># Introduction

After thinking about BusKill product that triggers a command once the USB cord disconnects, I have been thinking at a simple alternative.

=> https://www.buskill.in BusKill official project website

When using a laptop connected to power most of the time, you may want it to power off once it gets disconnected, this can be really useful if you use it in a public area like a bar or a train.  The idea is to protect the laptop if it gets stolen while in use and unlocked.

Here is how to proceed on Linux, using a trigger on an udev rule looking for a change in the power_supply subsystem.

For OpenBSD users, it is possible to use apmd as I explained in this article:

=> https://dataswamp.org/~solene/2024-02-20-rarely-known-openbsd-features.html#_apmd_daemon_hooks => Rarely known OpenBSD features: apmd daemon hooks

In the example, the script will just power off the machine, it is up to you to do whatever you want like destroy the LUKS master key or trigger the coffee machine :D

# Setup

Create a file `/etc/udev/rules.d/disconnect.rules`, you can name it how you want as long as it ends with `.rules`:

```
SUBSYSTEM=="power_supply", ENV{POWER_SUPPLY_ONLINE}=="0", ENV{POWER_SUPPLY_TYPE}=="Mains", RUN+="/usr/local/bin/power_supply_off"
```

Create a file `/usr/local/bin/power_supply_off` that will be executed when you unplug the laptop:

```
#!/bin/sh
echo "Going off because power supply got disconnected" | systemd-cat
systemctl poweroff
```

This simple script will add an entry in journald before triggering the system shutdown.

Mark this script executable with:
```
chmod +x /usr/local/bin/power_supply_off
```

Reload udev rules using the following commands:

```
udevadm control --reload-rules
udevadm trigger
```

# Testing

If you unplug your laptop power, it should power off, you should find an entry in the logs.

If nothing happens, looks at systemd logs to see if something is wrong in udev, like a syntax error in the file you created or an incorrect path for the script.

# Script ideas

Depending on your needs, here is a list of actions the script could do, from gentle to hardcore:

* Lock user sessions
* Hibernate
* Proper shutdown
* Instant power off (through sysrq)
* Destroy LUKS master key to make LUKS volume unrecoverable + Instant power off

# Conclusion

While BusKill is an effective / unusual product that is certainly useful for a niche, protecting a running laptop against thieves is an extra layer when being outside.

Obviously, this use case works only when the laptop is connected to power.
</pre>
   ]]>
 </description>
 <guid>gopher://dataswamp.org:70/1/~solene/article-linux-killswitch-on-power-disconnect</guid>
 <link>gopher://dataswamp.org:70/1/~solene/article-linux-killswitch-on-power-disconnect</link>
 <pubDate>Sat, 31 May 2025 00:00:00 GMT</pubDate>
</item>
<item>
 <title>PDF bruteforce tool to recover locked files</title>
 <description>
   <![CDATA[
<pre># Introduction

Today, I had to open a password protected PDF (medical report), unfortunately it is a few years old document and I did not remember the password format (usually something based on named and birthdate -_-).

I found a nice tool that can try a lot of combinations, and it is even better as if you know a bit the password format you can easily generate tested patterns.

=> https://github.com/mufeedvh/pdfrip pdfrip GitHub page

# Usage

The project page offers binaries for some operating systems, but you can compile it using cargo.

The documentation on the project's README is quite clear and easy to understand.  It is possible to generate some simple patterns, try all combinations of random characters or use a dictionary (some tools exists to generate a dictionary).

Inside a virtual machine with 4 vCPU, I was able to achieve 36 000 checks per second, on baremetal I expect this to be a higher.
</pre>
   ]]>
 </description>
 <guid>gopher://dataswamp.org:70/1/~solene/article-test-pdf-passwords</guid>
 <link>gopher://dataswamp.org:70/1/~solene/article-test-pdf-passwords</link>
 <pubDate>Sun, 09 Mar 2025 00:00:00 GMT</pubDate>
</item>
<item>
 <title>Blog activity for 2025</title>
 <description>
   <![CDATA[
<pre># Introduction

Hello, you may have wondered why the blog has not been really active this year, let's talk about it :-)

# Retrospective

## Patreon

First, I decided to stop the Patreon page for multiple reasons.  It was an interesting experimentation and helped me a lot in 2023 and a part of 2024 as I went freelance and did not earn much money.  Now, the business is running fine and prefer my former patrons to support someone else more active / who need money.

The way I implemented Patreon support was like this: people supporting me financially had access to blog posts a 2 or 3 days earlier than the public release, the point was to give them a little something for their support without creating a paywall for some content.  I think it worked quite well in that regard.  A side effect of the "early access publishing" was that, almost every time, I used this extra delay to add more content / fix issues that I did not think about when writing.  As a reminder, I usually just write then proofread quickly and publish.

Having people paying money to have early access to my blog posts created some kind of expectations from them in my mind, so I tried to raise the level higher in terms of content at the point that I came to procrastinate because "this blog post will not be interesting enough" or "this will just take too long to write, I'm bored".  My writing cadence got delayed, I was able to sustain once a week at first then moved to twice a month.  I have no idea if readers had "expectations", but I imagined it and acted like if it was a thing.

For each blog post I was publishing, this also created extra work for me:

* publish in early access
* write short news about it on Patreon
* wait a few days and republish not in early access

It is not much more work, but this was still more work to think and schedule.

Cherry on the cake, Patreon was already bloated when I started using it, but it has been more and more aggressive in terms of marketing and selling features, which disgusted me at some point.  I was not using all of this, but I felt bad to have people supporting me having to deal with it.

I used Patreon to publish a "I stop Patreon support but the blog continues" news, but it seems it is poorly handled on Patreon when you freeze a creator's page as subscribers are not able to see anything anymore once you put on freeze?!  Sorry for the lack of news, I thought it was working fine :/

## Different contribution place

The blog started and has lived as the place where I shared my knowledge during my continuous learning journey.  The thing is I learn less nowadays and more complicated knowledge that is hard to share, because it is super niche and certainly not fascinating to most, and because sharing it correctly may be hard.

Most of the blog is about OpenBSD, there were no community place to share it, so I self-hosted it.  Then, I started to write about NixOS and got invited by the people I worked with at that time (at Tweag company) to contribute to NixOS documentation, this made sense after all to not write something only me can update and which can not be fixed by others.  I did it a bit, but also continued my blog in parallel to share experience and ideas, not really "documentation".

Now I am using Qubes OS daily, for more than a year, I wrote a bit about it, but I started to contribute actively to community guides handled on the project's forum.  As a result, this made less content to publish on the blog because it just makes sense to centralize all the documentation in one place that is manageable by a team instead of here.

I spent a lot of time contributing to Qubes OS community guides, mostly about networking/VPN, and early 2025 I officially joined Qubes OS core team as a documentation maintainer (concretely, this gives commit rights on some repositories that are website/documentation related).  Qubes OS team is super nice, and the way the work is handled is cool, I will spend a lot of contribution time there (there is a huge backlog of changes to review first), still less time and incentive to write here.

## New real job and new place

As stated earlier, I finally found a work place that I enjoy and can keep me busy, my last two employers were not really able to figure how to use my weird skill set.  I had a lot of time to kill during work in the previous years, so time to experiment and write, I just have a lot less time now because I am really busy at work doing cool things.

My family moved to a new place in 2024 as well, there is a lot of work and gardening to handle, so after this and job work, I just do not have many things to share about on the blog at the moment.

# Conclusion

The blog is not dead, I think I will be able to resume activity soon now I turned the page on Patreon and identified why I was not writing here (I like writing here!).

I have a backlog of ideas, I also may write simpler blog posts when I would like to share an idea or a cool project without having to cover it entirely.

Thank you everyone for your support!
</pre>
   ]]>
 </description>
 <guid>gopher://dataswamp.org:70/1/~solene/article-2025-news</guid>
 <link>gopher://dataswamp.org:70/1/~solene/article-2025-news</link>
 <pubDate>Sun, 16 Feb 2025 00:00:00 GMT</pubDate>
</item>
<item>
 <title>Introduction to GrapheneOS</title>
 <description>
   <![CDATA[
<pre># Introduction

This blog post is an introduction to the smartphone and security oriented operating system GrapheneOS.

=> https://grapheneos.org/ GrapheneOS official project web page

Thanks to my patrons support, last week I have been able to replace my 6.5 years old BQ Aquaris X which has been successfully running Lineage OS all that time, by a Google Pixel 8a now running GrapheneOS.

Introducing GrapheneOS is a daunting task, I will do my best to present you the basics information you need to understand if it might be useful for you, and let a link to the project FAQ which contains a lot of valuable technical explanations I do not want to repeat here.

=> https://grapheneos.org/faq GrapheneOS FAQ

# What is GrapheneOS?

GrapheneOS (written GOS from now on) is an Android based operating system that focuses security.  It is only compatible with Google Pixel devices for multiple reasons: availability of hardware security components, long term support (series 8 and 9 are supported at least 7 years after release) and the hardware has a good quality / price ratio.

The goal of GOS is to provide users a lot more control about what their smartphone is doing.  A main profile is used by default (the owner profile), but users are encouraged to do all their activities in a separate profile (or multiples profiles).  This may remind you about Qubes OS workflow, although it does not translate entirely here.  Profiles can not communicate between each others, encryption is done per profile, and some permissions can be assigned per profile (installing apps, running applications in background when a profile is not used, using the SIM...).  This is really effective for privacy or security reasons (or both), you can have a different VPN per profile if you want, or use a different Google Play login, different applications sets, whatever!  The best feature here in my opinion is the ability to completely stop a profile so you are sure it does not run anything in the background once you exit it.

When you make a new profile, it is important to understand it is like booting your phone again, the first log-in with the profile you will be asked questions like if you started the system for the first time.  All settings have the defaults values, and any change is limited to the profile only, this includes ringtones, sound, default apps, themes…  Switching between profile is a bit painful, you need to get the top to bottom dropdown menu at full size, then tap the bottom right corner icon and choose the profile you want to switch to, and tap the PIN of that profile.  Only the owner profile can toggle important settings like 4G/5G network, or do SIM operations and other "lower level" settings.

GOS has a focus on privacy, but let the user in charge.  Google Play and Google Play Services can be installed in one click from a dedicated GOS app store which is limited to GOS apps only, as you are supposed to install apps from Google Play, F-droid or Accrescent.  Applications can be installed in a single profile, but can also be installed in the owner profile which lets you copy it to other profiles.  This is actually how I do, I install all apps in the user profile, I always uncheck the "network permission" so they just can't do anything, and then I copy them to profiles where I will use it for real.  There is no good or bad approach, this fits your need in terms of usability, privacy and security.

Just to make sure it is clear, it is possible to use GOS totally Google free, but if you want to use Google services, it is made super easy to do so.  Google Play could be used in a dedicated profile if you ever need it once.

# Installation and updates

The installation was really simple as it can be done from the web page (from a Linux, Windows or macOS system), by just clicking buttons in the correct order from the installation page.  The image integrity check can be done AFTER installation, thanks to the TPM features in the phone which guarantees the boot of valid software only, which will allow you to generate a proof of boot that is basically a post-install checksum. (More explanations in GOS website).  The whole process took approximately 15 minutes between plugging the phone to my computer and using the phone.

It is possible to install from the command line, I did not test it.

Updates are 100% over-the-air (OTA), which mean the system is able to download updates over network.  This is rather practical as you never need to do any adb command to push a new image, which have always been a stressful experience for me when using smartphones.  GOS automatically download base system updates and offer you to reboot to install it, while GOS apps will just be downloaded and update in place.  This is a huge difference from LineageOS which always required to manually download new builds, and applications updates were parts of the big image update.

# Permission management

A cool thing with GOS is the tight controls offered over applications.  First, this is done by profile, so if you use the same app in two profiles, you can give different permissions, and secondly, GOS allows you to define a scope to some permissions.  For example, if an application requires storage permission, you can list which paths are allowed, if it requires contacts access, you can give a list of contacts entries (or empty).

GOS Google Play installation (which is not installed by default) is sand-boxed to restrict what it can do, they also succeeded at sand-boxing Android Auto. (More details in the FAQ).  I have a dedicated Android Auto profile, the setup was easy thanks to the FAQ has a lot of permissions must be manually given for it to work.

GOS does not allow you to become root on your phone though, it just gives you more control through permissions and profiles.

# Performance

I did not try CPU/GPU intensive tasks for now, but there should be almost no visible performance penalty when using GOS.  There are many extra security features enabled which may lead to a few percent of extra CPU usage, but there are no benchmark and the few reviews of people who played high demanding video games on their phone did not notice any performance change.

# Security

GOS website has a long and well detailed list of hardening done over the stock Android code, you can read about them on the following link.

=> https://grapheneos.org/features#exploit-protection GrapheneOS website: Exploitation Protection

# My workflow

As an example, here is how I configured my device, this is not the only way to proceed, so I just share it to give the readers an idea of what it looks like for me:

* my owner profile has Google Play installed used to install most apps.  All apps are installed there with no network permission, then I copy them to the profile that will use the applications.
* a profile that looks like what I was doing in my previous phone: allowed to phone/SMS, web browser, IM apps, TOTP app.
* a profile for multimedia where I store music files, run audio players and use Android Auto.  Profile is not allowed to run in background.
* a profile for games (local and cloud).  Profile is not allowed to run in background.
* a "other" profile used to run crappy apps.  Profile is not allowed to run in background.
* a profile for each of my clients, so I can store any authentication app (TOTP, Microsoft authenticator, whatever), use any app required.  Profile is not allowed to run in background.
* a guest profile that can be used if I need to lend my phone to someone if they want to do something like look up something on the Internet.  This profile always starts freshly reset.

After a long week of use, I came up with this.  At first, I had a separate profile for TOTP, but having to switch back and forth to it a dozen time a day was creating too much friction.

# The device itself

I chose to buy a Google Pixel 8a 128 GB as it was the cheapest of the 8 and 9 series which have a 7 years support, but also got a huge CPU upgrade compared to the 7 series.  The device could be bought at 300€ on second hand market and 400€ brand new.

The 120 Hz OLED screen is a blast!  Colors are good, black is truly black (hence dark themes for OLED reduce battery usage and looks really great) and it is super smooth.

There is no SD card support, which is pretty sad especially since almost every Android smartphone support this, I guess they just want you to pay more for storage.  I am fine with 128 GB though, I do not store much data on my smartphone, but being able to extend it would have been nice.

The camera is OK, I am not using it a lot and I have no comparison, from reviews I have read they were saying it is just average.

Wi-Fi 6 works really fine (latency, packet loss, range and bandwidth) although I have no way to verify its maximum bandwidth because it is faster than my gigabit wired network.

The battery lasts long, I use my smartphone a bit more now, the battery approximately drops by 20% for a day of usage.  I did not test charge speed.

# Conclusion

I am really happy with GrapheneOS, I finally feel in control of my smartphone and I never considered it a safe device before.  I never really used an Android ROM from a manufacturer or iOS, I bet they can provide a better user experience, but they can not provide anything like GrapheneOS.

LineageOS was actually ok on my former BQ Aquaris X, but there were often regressions, and it did not provide anything special in terms of features, except it was still having updates for my old phone.  GrapheneOS on the other hand provides a whole new experience, that may be what you are looking for.

This system is not for everyone!  If you are happy with your current Android, do not bother buying a Google Pixel to try GOS.

# Going further

The stock Android version supports profiles (this can be enabled in system -> users -> allow multiple users), but there is no way to restrict what profiles can do, it seems they are all administrators.  I have been using this on our Android tablet at home, it is available on every Android phone as well.  I am not sure if it can be used as a security feature as this.
</pre>
   ]]>
 </description>
 <guid>gopher://dataswamp.org:70/1/~solene/article-intro-to-grapheneos</guid>
 <link>gopher://dataswamp.org:70/1/~solene/article-intro-to-grapheneos</link>
 <pubDate>Tue, 14 Jan 2025 00:00:00 GMT</pubDate>
</item>
<item>
 <title>Systemd journald cheatsheet</title>
 <description>
   <![CDATA[
<pre># Introduction

This blog post is part of a series that will be about Systemd ecosystem, today's focus is on journaling.

Systemd got a regrettable reputation since its arrival mid 2010.  I think this is due to Systemd being radically different than traditional tooling, and people got lost without a chance to be noticed beforehand they would have to deal with it.  The transition was maybe rushed a bit with a half-baked product, in addition to the fact users had to learn new paradigms and tooling to operate their computer.

Nowadays, Systemd is working well, and there are serious non-Systemd alternatives, so everyone should be happy. :)

# Introduction to journald

Journald is the logging system that was created as part of Systemd.  It handles logs created by all Systemd units.  A huge difference compared to the traditional logs is that there is a single journal file acting as a database to store all the data.  If you want to read logs, you need to use `journalctl` command to extract data from the database as it is not plain text.

Most of the time journald logs data from units by reading their standard error and output, but it is possible to send data to journald directly.

On the command line, you can use `systemd-cat` to run a program or pipe data to it to send them to logs.

=> https://www.man7.org/linux/man-pages/man1/systemd-cat.1.html systemd-cat man page

# Journalctl 101

Here is a list of the most common cases you will encounter:

* View new logs live: `journalctl -f`
* View last 2000 lines of logs: `journalctl -n 2000`
* Restrict logs to a given unit: `journalctl -u nginx.service`
* Pattern matching: `journalctl -g somepattern`
* Filter by date (since): `journalctl --since="10 minutes ago"` or `journalctl --since="1 hour ago"` or `journalctl --since=2024-12-01`
* Filter by date (range): `journalctl --since="today" --until="1 hour ago"` or `journalctl --since="2024-12-01 12:30:00" --until="2024-12-01 16:00:00"`
* Filter logs since boot: `journalctl -b`
* Filter logs to previous (n-1) boot: `journalctl -b -1`
* Switch date time output to UTC: `journalctl --utc`

You can use multiple parameters at the same time:

* Last 200 lines of logs of nginx since current boot: `journalctl -n 200 -u nginx -b`
* Live display of nginx logs files matching "wp-content": `journalctl -f -g wg-content -u nginx`

=> https://www.man7.org/linux/man-pages/man1/journalctl.1.html journalctl man page

# Send logs to syslog

If you want to bypass journald and send all messages to syslog to handle your logs with it, you can edit the file `/etc/systemd/journald.conf` to add the line `ForwardToSyslog=Yes`.

This will make journald relay all incoming messages to syslog, so you can process your logs as you want.

Restart journald service: `systemctl restart systemd-journal.service`

=> https://www.man7.org/linux/man-pages/man8/systemd-journald.service.8.html systemd-journald man page
=> https://www.man7.org/linux/man-pages/man5/journald.conf.5.html journald.conf man page

# Journald entries metadata

Journalctl contains a lot more information than just the log line (raw content).  Traditional syslog files contain the date and time, maybe the hostname, and the log message.

This is just for information, only system administrators will ever need to dig through this, it is important to know it exists in case you need it.

## Example

Here is what journald stores for each line (pretty printed from json output), using samba server as an example.

```
# journalctl -u smbd -o json -n 1 | jq
{
 "_EXE": "/usr/libexec/samba/rpcd_winreg",
 "_CMDLINE": "/usr/libexec/samba/rpcd_winreg --configfile=/etc/samba/smb.conf --worker-group=4 --worker-index=5 --debuglevel=0",
 "_RUNTIME_SCOPE": "system",
 "__MONOTONIC_TIMESTAMP": "749298223244",
 "_SYSTEMD_SLICE": "system.slice",
 "MESSAGE": "  Copyright Andrew Tridgell and the Samba Team 1992-2023",
 "_MACHINE_ID": "f23c6ba22f8e02aaa8a9722df464cae3",
 "_SYSTEMD_INVOCATION_ID": "86f0f618c0b7dedee832aef6b28156e7",
 "_BOOT_ID": "42d47e1b9a109551eaf1bc82bd242aef",
 "_GID": "0",
 "PRIORITY": "5",
 "SYSLOG_IDENTIFIER": "rpcd_winreg",
 "SYSLOG_TIMESTAMP": "Dec 19 11:00:03 ",
 "SYSLOG_RAW": "<29>Dec 19 11:00:03 rpcd_winreg[4142801]:   Copyright Andrew Tridgell and the Samba Team 1992-2023\n",
 "_CAP_EFFECTIVE": "1ffffffffff",
 "_SYSTEMD_UNIT": "smbd.service",
 "_PID": "4142801",
 "_HOSTNAME": "pelleteuse",
 "_SYSTEMD_CGROUP": "/system.slice/smbd.service",
 "_UID": "0",
 "SYSLOG_PID": "4142801",
 "_TRANSPORT": "syslog",
 "__REALTIME_TIMESTAMP": "1734606003126791",
 "__CURSOR": "s=1ab47d484c31144909c90b4b97f3061d;i=bcdb43;b=42d47e1b9a109551eaf1bc82bd242aef;m=ae75a7888c;t=6299d6ea44207;x=8d7340882cc85cab",
 "_SOURCE_REALTIME_TIMESTAMP": "1734606003126496",
 "SYSLOG_FACILITY": "3",
 "__SEQNUM": "12376899",
 "_COMM": "rpcd_winreg",
 "__SEQNUM_ID": "1ab47d484c31144909c90b4b97f3061d",
 "_SELINUX_CONTEXT": "unconfined\n"
}
```

The "real" log line is the value of `SYSLOG_RAW`, everything else is created by journald when it receives the information.

## Filter

As the logs can be extracted in JSON format, it becomes easy to parse them properly using any programming language able to deserialize JSON data, this is far more robust than piping lines to AWK / grep, although it can work "most of the time" (until it does not due to a weird input).

On the command line, you can query/filter such logs using `jq` which is a bit the awk of JSON.  For instance, if I output all the logs of "today" to filter lines generated by the binary `/usr/sbin/sshd`, I can use this:

```
journalctl --since="today" -o json | jq -s '.[] | select(._EXE == "/usr/sbin/sshd")'
```

This command line will report each line of logs where "_EXE" field is exactly "/usr/sbin/sshd" and all the metadata.  This kind of data can be useful when you need to filter tightly for a problem or a security incident.

The example above was made easy as it is a bit silly in its form: filtering on SSH server can be done with `journalctl -u sshd.service --since=today`.

# Conclusion

Journald is a powerful logging system, journalctl provides a single entry point to extract and filter logs in a unified system.

With journald, it became easy to read logs of multiple services over a time range, and log rotation is now a problem of the past for me.
</pre>
   ]]>
 </description>
 <guid>gopher://dataswamp.org:70/1/~solene/article-systemd-journald-cheatsheet</guid>
 <link>gopher://dataswamp.org:70/1/~solene/article-systemd-journald-cheatsheet</link>
 <pubDate>Wed, 25 Dec 2024 00:00:00 GMT</pubDate>
</item>
<item>
 <title>Presentation of Pi-hole</title>
 <description>
   <![CDATA[
<pre># Introduction

This blog post is about the project Pi-hole, a libre software suite to monitor and filter DNS requests over a local network.

=> https://pi-hole.net/ Pi-hole official project page

Pi-hole is Linux based, it is a collection of components and configuration that can be installed on Linux, or be used from a Raspberry PI image ready to write on a flash memory.

=> static/img/pihole-startrek.png The top of Pi-hole dashboard display, star trek skin

# Features

Most of Pi-hole configuration happens on a clear web interface (which is available with a star trek skin by the way), but there is also a command line utility and a telnet API if you need to automate some tasks.

## Filtering

The most basic feature of Pi-hole is filtering DNS requests.  While it comes with a default block list from the Internet, you can add custom lists using their URLs, the import supports multiple formats as long as you tell Pi-hole which format to use for each source.

Filtering can be done for all queries, although you can create groups that will not be filtered and assign LAN hosts that will belong to this group, in some situation there are hosts you may not want to filter.

The resolving can be done using big upstream DNS servers (Cloudflare, Google, OpenDNS, Quad9 ...), but also custom servers.  It is possible to configure a recursive resolver by installing unbound locally.

=> https://docs.pi-hole.net/guides/dns/unbound/ Pi-hole documentation: how to install and configure unbound

## Dashboard

A nice dashboard allows you to see all queries with the following information:

* date
* client IP / host
* domain in the query
* result (allowed, blocked)

It can be useful to understand what is happening if a website is not working, but also see how much queries are blocked.

It is possible to choose the privacy level of logging, because you may only want to have statistics about numbers of queries allowed / blocked and not want to know who asked what (this may also be illegal to monitor this on your LAN).

=> https://docs.pi-hole.net/ftldns/privacylevels/ Documentation about privacy levels

## Audit log

In addition to lists, the audit log will display two columns with the 10 most allowed / blocked domains appearing in queries, that were not curated through the audit log.

Each line in the "allowed" column have a "blacklist" and "audit" buttons.  The former will add the domain to the internal blacklist while the latter will just acknowledge this domain and remove it from the audit log.  If you click on audit, it means "I agree with this domain being allowed".

The column with blocked queries will show a "Whitelist" and "Audit" buttons that can be used to definitely allow a domain or just acknowledge that it's blocked.

Once you added a domain to a list or clicked on audit, it got removed from the displayed list, and you can continue to manually review the new top 10 domains.

## Disable blocking

There is a feature to temporarily disable blocking for 10 seconds, 30 seconds, 5 minutes, indefinitely or a custom time.  This can be useful if you have an important website that misbehave and want to be sure the DNS filtering is not involved.

## Local hostnames

It is possible to add custom hostnames that resolve to whatever IP you want, this makes easy to give nice names to your machines on your LAN.  There is nothing really fancy, but the web ui makes it easy to handle this task.

## Extra features

Pi-hole can provide a DHCP server to your LAN, has self diagnosis, easy configuration backup / restore.  Maybe more features I did not see or never used.

# Conclusion

While Pi-hole requires more work than configuring unbound on your local LAN and feed it with a block list, it provides a lot more features, flexibility and insights about your DNS than unbound.

Pi-hole works perfectly fine on low end hardware, it uses very little resources despite all its features.

# Going further

I am currently running Pi-hole as a container with podman, from an unpriviliged user.  This setup is out of scope, but I may write about it later (or if people ask for it) as it required some quirks due to replying to UDP packets through the local NAT, and the use of the port 53 (which is restricted to root, usually).
</pre>
   ]]>
 </description>
 <guid>gopher://dataswamp.org:70/1/~solene/article-pi-hole</guid>
 <link>gopher://dataswamp.org:70/1/~solene/article-pi-hole</link>
 <pubDate>Sat, 21 Dec 2024 00:00:00 GMT</pubDate>
</item>
<item>
 <title>Getting started to write firewall rules</title>
 <description>
   <![CDATA[
<pre># Introduction

This blog post is about designing firewall rules, not focusing on a specific operating system.

The idea came after I made a mistake on my test network where I exposed LAN services to the Internet after setting up a VPN with a static IPv4 on it due to too simplistic firewall rules.  While discussing this topic on Mastodon, some mentioned they never know where to start when writing firewall rules.

# Firewall rules ordering

Firewall rules are evaluated one by one, and the evaluation order matters.

Some firewall use a "first match" type, where the first rule matching a packet is the rule that is applied.  Other firewalls are of type "last match", where the last matching rule is the one applied.

# Block everything

The first step when writing firewall rules is to block all incoming and outgoing traffic.

There is no other way to correctly configure a firewall, if you plan to block all services you want to restrict and let the default allow rule do its job, you are doing it wrong.

# Identify flows to open

As all flows should be blocked by default, you have to list what should go through the firewall, inbound and outbound.

In most cases, you will want to allow outbound traffic, except if you have a specific environment on which you want to only allow outgoing traffic to a certain IP / port.

For inbound traffic, if you do not host any services, there are nothing to open.  Otherwise, make a list of TCP, UDP, or any other ports that should be reachable, and who should be allowed to reach it.

# Write the rules

When writing your rules, whether they are inbound or outbound, be explicit whenever possible about this:

* restrict to a network interface
* restrict the source addresses (maybe a peer, a LAN, or anyone?)
* restrict to required ports only

Eventually, in some situations you may want to filter by source and destination port at the same time.  This is usually useful when you have two servers communicating over a protocol enforcing both ports.

This is actually where I failed and exposed my LAN minecraft server to the wild.  After setting up a VPN with a static IPv4 address, I only had a "allow tcp/25565" rule on my firewall as I was relying on my ISP router to not forward traffic.  This rule was not effective once the traffic was received from the VPN, although it would have been filtrated when using a given network interface or a source network.

If you want to restrict the access of a critical service to a some user (1 or more), but that they do not have a static IP address, you should consider using a VPN for this service and restrict the access to the VPN interface only.

# Write comments and keep track of changes

Firewall rules will evolve over time, you may want to write for your future you why you added this or that rule.  Ideally, use a version control system on the firewall rules file, so you can easily revert changes or track history to understand a change.

# Do not lock yourself out

When applying the firewall rules the first time, you may have made a mistake and if it is on remote equipment with no (or complicated) physical access, it is important to prepare an escape.

There are different methods, the most simple is to run a command in a second terminal that sleeps for 30 seconds before resetting the firewall to a known state, you have to run this command just before loading the new rules.  So if you are locked out after applying, just wait 30 seconds to fix the rules.

# Add statistics and logging

If you want to monitor your firewall, consider adding counters to rules, it will tell you how many times it was evaluated/matched and how many packets and traffic went through.  With nftables on Linux they are named "counters", whereas OpenBSD packet filter names this "label".

It is also possible to log packets matching a rule, this can be useful to debug an issue on the firewall, or if you want to receive alerts in your logs when a rule is triggered.

# Conclusion

Writing firewall rules is not a hard task once you identified all flows.

While companies have to maintain flow tables, I do not think it can be useful for a personal network (your mileage may vary).
</pre>
   ]]>
 </description>
 <guid>gopher://dataswamp.org:70/1/~solene/article-writing-firewall-rules</guid>
 <link>gopher://dataswamp.org:70/1/~solene/article-writing-firewall-rules</link>
 <pubDate>Wed, 11 Dec 2024 00:00:00 GMT</pubDate>
</item>
<item>
 <title>Why I stopped using OpenBSD</title>
 <description>
   <![CDATA[
<pre># Introduction

Last month, I decided to leave the OpenBSD team as I have not been using OpenBSD myself for a while.  A lot of people asked me why I stopped using OpenBSD, although I have been advocating it for a while.  Let me share my thoughts.

First, I like OpenBSD, it has values, and it is important that it exists.  It just does not fit all needs, it does not fit mine anymore.

# Issues

Here is a short list of problems that, while bearable when taken individually, they summed up to a point I had to move away from OpenBSD.

## Hardware compatibility

* no Bluetooth support
* limited game pad support (not supported by all programs, not all game pad will work)
* battery life / heat / power usage (OpenBSD draws more power than alternatives, by a good margin)

## Software compatibility

As part of staying relevant on the DevOps market, I need to experiment and learn with a lot of stuff, this includes OCI containers, but also machine learning and some weird technologies.  Running virtual machines on OpenBSD is really limited, running programs headless with one core and poor performance is not a good incentive to work at staying sharp.

As part of my consultancy work, I occasionally need to run proprietary crap, this is not an issue when running it in a VM, but I can not do that on OpenBSD without a huge headache and very bad performance.

## Reliability

I have grievances against OpenBSD file system.  Every time OpenBSD crash, and it happens very often for me when using it as a desktop, it ends with file corrupted or lost files.  This is just not something I can accept.

Of course, it may be some hardware compatibility issue, I never have issues on an old ThinkPad T400, but I got various lock up, freeze or kernel panic on the following machines:

* ThinkPad X395
* ThinkPad t470
* ThinkPad t480
* ryzen 5600X + AMD GPU (desktop)

Would you like to keep using an operating system that daily eat your data?  I don't.  Maybe I am doing something weirds, I don't know, I have never been able to pinpoint why I got so many crashes although everyone else seem to have a stable experience with OpenBSD.

# Moving to Linux

I moved from OpenBSD to Qubes OS for almost everything (except playing video games) on which I run Fedora virtual machines (approximately 20 VM simultaneously in average).  This provides me better security than OpenBSD could provide me as I am able to separate every context into different spaces, this is absolutely hardcore for most users, but I just can't go back to a traditional system after this.

=> https://dataswamp.org/~solene/2023-06-17-qubes-os-why.html Earlier blog post: Why one would use Qubes OS?

In addition, I have learned the following Linux features and became really happy of it:

* namespaces: being able to reduce the scope of a process is incredibly powerful, this is something that exists in Linux since a very long time, this is also the foundation for running containers, it is way better than chroots.
* cgroups: this is the name of the kernel subsystem that is responsible for resource accounting, with it, it is possible to get access to accurate and reliable monitoring.  It is possible to know how much network, i/o, CPU or memory have been used by a process.  From an operator point of view, it is really valuable to know exactly what is consuming resources when looking at the metrics.  Where on OpenBSD you can notice a CPU spike at some timestamp, on Linux you would be able to know which user used the CPU.
* systemd: journald, timers and scripting possibilities.  I need to write a blog post about this, systemd is clearly disruptive, but it provides many good features.  I understand it can make some people angry as they have to learn how to use it.  The man pages are good though.
* swap compression: this feature allows me to push my hardware to its limit, with lz4 compression algorithm, it is easy to get access to **extremely** fast swap paid with some memory.  The compression ratio is usually 3:1 or 4:1 which is pretty good.
* modern storage backend: between LVM, btrfs and ZFS, there are super nice things to achieve depending on the hardware, for maximum performance / reliability and scalability.  I love transparent compression as I can just store more data on my hardware. (when it's compressible of course).
* flatpak: I really like software distribution done with flatpak, packages are all running in their own namespace, they can't access all the file system, you can roll back to a previous version, and do some interesting stuff
* auditd: this is a must-have for secure environments, it allows logging all accesses matching some rules (like when was accessed this arbitrary file, when that file is modified, etc...).  This does not even exist in OpenBSD (maybe if you can run ktrace on pid 1 you could do something?).  This kind of feature is a basic requirement for many qualified secure environments.
* SELinux: although many people disable it immediately after the first time it gets on their way (without digging further), this is a very powerful security mechanism that mitigates entire classes of vulnerabilities.

When using a desktop for gaming, I found Fedora Silverblue to be a very solid system with reliable upgrades, good quality and a lot of software choice.

# Conclusion

I got too many issues with OpenBSD, I wanted to come back to it twice this year, but I just have lost 2 days of my life due to all the crashes eating data.  And when it was working fine, I was really frustrated by the performance and not being able to achieve the work I needed to do.

But as I said, I am glad people there are happy OpenBSD users who enjoy it and have a reliable system with it.  From the various talks I had with users, the most common (by far) positive fact that make OpenBSD good is that users can understand what is going on.  This is certainly a quality that can only be found in OpenBSD (maybe NetBSD too?).

I will continue to advocate OpenBSD for situations I think it is relevant, and I will continue to verify OpenBSD compatibility when contributing to open source software (last in date is Peergos).  This is something that matters a lot for me, in case I go back to OpenBSD :-)
</pre>
   ]]>
 </description>
 <guid>gopher://dataswamp.org:70/1/~solene/article-why-i-stopped-using-openbsd</guid>
 <link>gopher://dataswamp.org:70/1/~solene/article-why-i-stopped-using-openbsd</link>
 <pubDate>Mon, 18 Nov 2024 00:00:00 GMT</pubDate>
</item>
<item>
 <title>Self-hosted web browser bookmarks syncing</title>
 <description>
   <![CDATA[
<pre># Introduction

This blog post is about Floccus, a self-hosting web browser bookmarks and tabs syncing software.

What is cool with Floccus is that it works on major web browsers (Chromium, Google Chrome, Mozilla Firefox, Opera, Brave, Vivaldi and Microsoft Edge), allowing sharing bookmarks/tabs without depending on the web browser integrated feature, but it also supports multiple backends and also allow the sync file to be encrypted.

=> https://floccus.org/ Floccus official project website

The project is actively developed and maintained.

=> https://github.com/floccusaddon/floccus Floccus GitHub repository

If you want to share a bookmark folder with other people (relatives, a team at work), do not forget to make a dedicated account on the backend as the credentials will be shared.

# Features

* can sync bookmarks or tabs
* sync over WebDAV, Nextcloud, git, linkwarden and Google Drive
* (optional) encrypted file on the shared storage with WebDAV and Google Drive backends
* (optional) security to not sync if more than 50% of the bookmarks changed
* can sync a single bookmark directory
* sync one-way or two-ways
* non HTTP URLs can be saved when using WebDAV or Google Drive backends (ftp:, javascript, data:, chrome:)
* getting rid of Floccus is easy, it has an export feature, but you can also export your bookmarks

# Setup

There is not much to setup, but the process looks like this:

1. install the web browser extension (it is published on Chrome, Mozilla and Edge stores)
2. click on the Floccus icon and click on "Add a profile"
3. choose the backend
4. type credentials for the backend
5. configure the sync options you want
6. enjoy!

After you are done, repeat the process on another web browser if you want to enable sync, otherwise Floccus will "only" serve as a bookmark backup solution.

# Conclusion

It is the first bookmark sync solution I am happy with, it just works, supports end-to-end encryption, and does not force you to use the same web browser across all your devices.

Before this, I tried integrated web browser sync solutions, but self-hosting them was not always possible (or a terrible experience).  I gave a try to "bookmark managers" (linkding, buku, shiori), but whether in command line or with a web UI, I did not really like it as I found it rather impractical for daily use.  I just wanted to have my bookmarks stored in the browser, and be able to easily search/open them. Floccus does the job.
</pre>
   ]]>
 </description>
 <guid>gopher://dataswamp.org:70/1/~solene/article-selfhosted-bookmark-sync</guid>
 <link>gopher://dataswamp.org:70/1/~solene/article-selfhosted-bookmark-sync</link>
 <pubDate>Tue, 05 Nov 2024 00:00:00 GMT</pubDate>
</item>
<item>
 <title>Using a dedicated administration workstation for my infrastructure</title>
 <description>
   <![CDATA[
<pre># Introduction

As I moved my infrastructure to a whole new architecture, I decided to only expose critical accesses to dedicated administration systems (I have just one).  That workstation is dedicated to my infrastructure administration, it can only connect to my servers over a VPN and can not reach the Internet.

This blog post explains why I am doing this, and gives a high level overview of the setup.  Implementation details are not fascinating as it only requires basics firewall, HTTP proxy and VPN configuration.

# The need

I wanted to have my regular computer not being able to handle any administration task, so I have a computer "like a regular person" without SSH keys, VPN and a password manager that does not mix personal credentials with administration credentials ...  To prevent credentials leaks or malware risks, it makes sense to uncouple the admin role from the "everything else" role.  So far, I have been using Qubes OS which helped me to do so at the software level, but I wanted to go further.

# Setup

This is a rather quick and simple explanation of what you have to do in order to set up a dedicated system for administration tasks.

## Workstation

The admin workstation I use is an old laptop, it only needs a web browser (except if you have no internal web services), a SSH client, and being able to connect to a VPN.  Almost any OS can do it, just pick the one you are the most conformable with, especially with regard to the firewall configuration.

The workstation has its own SSH key that is deployed on the servers.  It also has its own VPN to the infrastructure core.  And its own password manager.

Its firewall is configured to block all in and out traffic except the following:

* UDP traffic to allow WireGuard
* HTTP proxy address:port through WireGuard interface
* SSH through WireGuard

The HTTP proxy exposed on the infrastructure has a whitelist to allow some fqdn.  I actually want to use the admin workstation for some tasks, like managing my domains through my registrar web console.  Keeping the list as small as possible is important, you do not want to start using this workstation for browsing the web or reading emails.

On this machine, make sure to configure the system to use the HTTP proxy for updates and installing packages.  The difficulty of doing so will vary from an operating system to another.  While Debian required a single file in `/etc/apt/apt.conf.d/` to configure apt to use the HTTP proxy, OpenBSD needed both `http_proxy` and `https_proxy` environment variables, but some scripts needed to be patched as they do not use the variables, I had to check fw_update, pkg_add, sysupgrade and syspatch were all working.

Ideally, if you can afford it, configure a remote logging of this workstation logs to a central log server.  When available, `auditd` monitoring important files access/changes in `/etc` could give precious information.

## Servers

My SSH servers are only reachable through a VPN, I do not expose it publicly anymore.  And I do IP filtering over the VPN, so only the VPN clients that have a use to connect over SSH will be allowed to connect.

When I have some web interfaces for services like Minio, Pi-Hole and the monitoring dashboard, all of that is restricted to the admin workstations only.  Sometimes, you have the opportunity to separate the admin part by adding a HTTP filter on a `/admin/` URI, or if the service uses a different port for the admin and the service (like Minio).  When enabling a new service, you need to think about all the things you can restrict to the admin workstations only.

Depending on your infrastructure size and locations, you may want to use dedicated systems for SSH/VPN/HTTP proxy entry points, it is better if it is not shared with important services.

## File exchange

You will need to exchange data to the admin workstation (rarely the other way), I found nncp to be a good tool for that.  You can imagine a lot of different setup, but I recommend picking one that:

* does not require a daemon on the admin workstation: this does not increase the workstation attack surface
* allows encryption at rest: so you can easily use any deposit system for the data exchange
* is asynchronous: as a synchronous connection could be potentially dangerous because it establishes a link directly between the sender and the receiver

=> https://dataswamp.org/~solene/2024-10-04-secure-file-transfer-with-nncp.html Previous blog post: Secure file transfer with NNCP

# Conclusion

I learned about this method while reading ANSSI (French cybersecurity national agency) papers.  While it may sound extreme, it is a good practice I endorse.  This gives a use to old second hand hardware I own, and it improves my infrastructure security while giving me peace of mind.

=> https://cyber.gouv.fr/ ANSSI website (in French)

In addition, if you want to allow some people to work on your infrastructure (maybe you want to set up some infra for an association?), you already have the framework to restrict their scope and trace what they do.

Of course, the amount of complexity and resources you can throw at this is up to you, you could totally have a single server and lock most of its services behind a VPN and call it a day, or have multiple servers worldwide and use dedicated servers to enter their software defined network.

Last thing, make sure that you can bootstrap into your infrastructure if the only admin workstation is lost/destroyed.  Most of the time, you will have a physical/console access that is enough (make sure the password manager is reachable from the outside for this case).
</pre>
   ]]>
 </description>
 <guid>gopher://dataswamp.org:70/1/~solene/article-my-admin-workstation</guid>
 <link>gopher://dataswamp.org:70/1/~solene/article-my-admin-workstation</link>
 <pubDate>Wed, 23 Oct 2024 00:00:00 GMT</pubDate>
</item>

 </channel>
</rss>