Mastodon

Aachen Transparent!

Ich möchte Stadtpolitik in Aachen für alle verständlich machen. Mein aktuellstes Projekt aachen-transparent.de ermöglicht es, die öffentlichen Informationen aus dem städtischen Ratsinformationssystem modern und benutzerfreundlich aufzubereiten. Dazu habe ich das bereits existieren Open-Source Projekt Meine-Stadt-Transparent erweitert und für die Bedürfnisse in Aachen angepasst.

Screenshot von aachen-transparent.de

Aachen Transparent ist ein Projekt, dass ich ehrenamtlich im Rahmen des Open Data Labs Aachen ins Leben gerufen habe. Es versucht einige der Unzulänglichkeiten des Ratsinformationssystems der Stadt Aachen zu umgehen. Dazu nutzt es dessen öffentliche OParl Schnittstelle um die dort hinterlegten Informationen über eine moderne Oberfläche zugänglich zu machen.

Dies ist besonders deshalb von Interesse, da das Aachener Ratsinformationssystem leider keine Indexierung von Suchmaschinen wie Google zulässt und Bürger daher bisher nur die recht beschränkte Suchfunktion der AllRis Software nutzen konnten. Aachen Transparent unterstützt und fördert explizit die Indizierung aller Anträge, Dokumente, Tagesordnungspunkte und Beschlüsse durch gängige Suchmaschinen und stellt auch eine eigene Volltextsuche zu Verfügung.

Funktionalität

Durch Meine Stadt Transparent erfahren Bürgerinnen und Bürger, wer für sie im Stadtrat sitzt, wann der Stadtrat tagt und welche Themen besprochen werden. Da alle Dokumente räumlich auf einer Karte verortet werden, sind leicht jene Themen erkennbar, die sich auf das unmittelbare Lebensumfeld beziehen.

Großen Wert habe ich auf eine intuitive und flexible Suche gelegt: Mit einer zentralen Suche lässt sich die gesamte Seite – Sitzungsvorlagen, Tagesordnungen, uvm. – im Volltext durchsuchen, genauso wie gewählte Stadtratsmitglieder oder Ausschüsse. Um auch dauerhaft auf dem Laufenden zu bleiben, bietet „Aachen Transparent“ verschiedene Anschlusspunkte: Nutzer können sich E-Mail-Benachrichtigungen anlegen, die über neue Dokumente zu abonnierten Suchbegriffen informiere. Termine und Terminreihen lassen sich per iCal in eigene Kalendersysteme einbetten, die aktuellen Dokumente lassen sich auch im eigenen RSS-Reader lesen.

Aachen Transparent ist kein isoliertes System, sondern greift auf das existierende Ratsinformationssysteme der Stadt Aachen zurück, um von dort Daten automatisch zu beziehen und aufzubereiten. Die Verwaltung von Dokumenten erfolgt weiterhin über ein klassisches Ratsinformationssystem, zu dem Aachen Transparent eine moderne Oberfläche bietet.

Im Überblick

  • Volltextsuche durch alle Dokumente
  • Texterkennung in gescannten Dokumenten
  • Georeferenzierung von Dokumenten
  • iCal Kalender für Integration in Outlook, Google und andere Kalender
  • RSS Feeds für Ausschüsse und Personen
  • Abonnierbare Suchen mit E-Mail Benachrichtigungen und RSS Feeds

Geo-referenzierte Dokumente

Interessant ist auch die Verortung von Dokumenten und Anträgen. Aachen Transparent durchsucht alle indizierten Text auf Straßennamen im Aachener Stadtgebiet und nutzt diese zur Georeferenzierung. Wie im folgenden Bild zu sehen kann dadurch eine Karte generiert werden, welche einen Überblick über die aktuellen Themen in der Stadtpolitik gibt. Diese Georeferenzierung ist zudem auch über die Suchfunktion nutzbar, sodass z.B. eine Suche auf einen Stadtteil oder Straße eingeschränkt werden kann.

Verortung von Anträgen

Informationen zu Rats- und Ausschussmitgliedern

Desweiteren stellt Aachen Transparent eine Übersicht aller aktuellen Rats und Ausschussmitglieder bereit, die deren Mitgliedschaft in Ausschüssen zusammengefasst.

Personen Übersichtsseite

Offene Schnittstellen

Aachen Transparent unterstützt auch bereits existierende offene Schnittstellen um Daten aus dem Ratsinformationssystem auch über andere Kanäle zu verarbeiten.

So unterstützen wir z.B einen iCal Export des es ermöglicht Sitzungskalender in andere Kalendersoftware (z.B Outlook oder Android Kalender) zu integrieren und diese kontinuierlich zu synchronisieren.

Neue Anträge und Beschlusssachen können zudem über RSS Feeds abonniert werden. Interessant ist dabei auch die Möglichkeit individualisierte Feeds basierend auf Suchanfragen zu erstellen.

Häufige Fragen

Wer steckt hinter Aachen Transparent?

Aachen Transparent ist Angebot das auf ehrenamtlicher Basis von mir im Umfeld des Open Data Labs Aachen betrieben wird. Es ist daher kein offizielles Angebot der Stadt Aachen.

Kann ich Aachen Transparent auch in meiner Stadt/Gemeinde einsetzen?

Ja! Aachen Transparent basiert auf der Open Source Software Meine Stadt Transparent, die gemeinschaftlich von mehreren Open Data Labs und interessierten Privatpersonen entwickelt wird. Daher ist es prinzipiell auch möglich eine separate Instanz der Software für ihre Gemeinde aufzusetzen.

Aktuelle Statistiken aus Aachen

  • Dateien: 11.628
  • Sitzungen: 3.439
  • Gremien: 165
  • Vorlagen: 18.367
  • Personen: 1.370

(Stand: 2. August 2022)

A highly available WireGuard VPN setup

WireGuard is a communication protocol and free and open-source software that implements encrypted virtual private networks (VPNs), and was designed with the goals of ease of use, high speed performance, and low attack surface.

My Journey to WireGuard

I’ve been using it in my home lab setup since about 2020. When, in the end of 2021, it was finally merged into the Linux mainline with release 5.9, I started to replace my former Tinc-VPN setup with it. Tinc-VPN is another great open source VPN solution. Unfortunately, its development has stalled over the last years which motivated me to look for alternatives. In contrast to WireGuard, Tinc runs as a user-space daemon and uses tun/tap devices which adds a significant processing overhead. Like WireGuard, it is also using UDP for tunneling data, but falls back to TCP in situations where direct datagram connectivity is not feasible. Another big advantage of Tinc is its ability to form a mesh of nodes and to route traffic within it when direct P2P connections are not possible due to firewall restrictions. At the same time, this mesh is also used for facilitating direct connections by signaling endpoint addresses of NATed hosts.

Tinc’s mesh capability.

This mesh functionality made Tinc quite robust against the failure of single nodes as usually we could route traffic via other paths.

Highly Available WireGuard server setup

To counteract this shortcoming, this blog post will present a highly available WireGuard setup using the Virtual Router Redundancy Protocol (VRRP) as implemented by the keepalived daemon.

That said, it is worth noting that this setup does will not bring back some of the beloved features of Tinc. Both meshing, the peer and and endpoint discovery features of Tinc are currently and will never be supported by WireGuard. Jason A. Donenfeld the author of WireGuard focused the design of WireGuard on simplicity, performance and auditability. Hence advanced features like the ones mentioned will only be available to WireGuard by additional agents / daemons which control and configure WireGuard for you. Examples for such are Tailscale, Netmaker and Netbird.

The setup presented in this post is a so called active / standby configuration consisting of two almost equal configured Linux servers running both WireGuard and the keepalived daemon. As the name suggest only one of those two servers will by actively handling WireGuard tunneling traffic while the other one stands by for the event of a failure or maintenance of the active node.

VRRP Wireguard Setup

Requirements

Before get started some requirements for the setup:

  • 2 Servers running Linux 5.9 or newer.
  • A working Wireguard configuration.
  • A local L2 network segment two which both servers are connected.
  • Upstream connectivity without NATing via gateway connected to the network segment (usually provided by your internet or hosting provider).
  • An unused address to be used as Virtual IP (VIP) which roamed between the two servers by VRRP.

An important point is here the assumption that we are running both servers in the same switched network segment as this is a requirement for VRRP. We are also assuming that the upstream gateway performs no NATing. This guide covers only IPv6 addressing. However all steps can be also adapted or repeated for a dual stack or IPv4-only setup.

Detailed steps

Here are some of the specifics for my setup which need to be adapted by you:

  • Server Key (same use by both servers)
    • Private: YIEDx+A2ONo5+uv3mrk/p7ileL3T5QQ8hleQK0IYEEI=
    • Public: XGubrkGtuECdvoykKeUiNMigk2onfLCPfEo9Im+vmx8=
  • Peer Key (In this example we only have a single peer)
    • Private: OIbpWVIVVBOtWfwkmXkFRN7Q/jBdfYtsGt7j97aHx1Q=
    • Public: 3NGl6gTOGs6ai0RE91VmVFgF+N4gw1EBG11KOeiKJAg=
  • Public Server Subnet: 2001:DB8:1::/64
    • Gateway: 2001:DB8:1::1
    • Virtual IP: 2001:DB8:1::2
    • Server A: 2001:DB8:1:::3
    • Server B: 2001:DB8:1::4
  • WireGuard Tunnel Subnet: 2001:DB8:2::1/64
    • Server: 2001:DB8:2::1 (same used by both servers)
    • Peer: 2001:DB8:2::2
  • Interface names
    • Wireguard: wg1
    • Upstream: eno1

1. Prepare servers

We start of preparing the two servers by installing WireGuard and keepalived:

sudo apt install keepalived wireguard-tools iproute2

Next we configure a WireGuard interface on both servers using exactly the same configuration file at /etc/wireguard/wg1.conf:

[Interface]
Address = 2001:DB8:2::1/64
PrivateKey = YIEDx+A2ONo5+uv3mrk/p7ileL3T5QQ8hleQK0IYEEI=
ListenPort = 51800

[Peer]
PublicKey = 3NGl6gTOGs6ai0RE91VmVFgF+N4gw1EBG11KOeiKJAg=
AllowedIPs = 2001:DB8:2::2/128
PersistentKeepalive = 25

Similarly, a reciprocal configuration file is needed on the client side which skip here for brevity. Before proceeding, we activate the interface on both servers:

systemctl enable --now wg-quick@wg1

wg show wg1 # Check if interface is up

2. Configuring Keepalived

Create a configuration file for keepalived at /etc/keepalived/keepalived.conf

global_defs {
    enable_script_security
    script_user root
}

# Check if the server the WireGuard interface configured
vrrp_script check_wg {
    script "/usr/bin/wg show wg1"
    user root
}

vrrp_instance wg_v6 {
    interface eno1
    virtual_router_id 52
    notify /usr/local/bin/keepalived-wg.sh

    state BACKUP # use BACKUP for Server B
    priority 99 # use 100 for Server B

    virtual_ipaddress {
	2001:DB8:1::1/64
    }

    track_script {
        check_wg
    }
}

Create a notification script for keepalived at /usr/local/bin/keepalived-wg.sh

#!/bin/bash

TYPE=$1
NAME=$2
STATE=$3
PRIO=$4

WGIF=wg1

case ${STATE} in
	MASTER)
		ip link set up dev ${WGIF}
		;;

	BACKUP|FAULT|STOP|DELETED)
		ip link set down dev ${WGIF}
		;;

	*)
		echo "unknown state"
		exit 1
esac

Now start the keepalived daemon:

chmod +x /usr/local/bin/keepalived-wg.sh
systemctl enable --now keepalived

4. Testing the fail over

In our configuration, Server A has a higher VRRP priority and as such will be preferred if both servers are healthy. To test our setup, we simply bring down the WireGuard interface on Server A and observe how the VIP gets moved to Server B. From the WireGuard peers perspective not much changes. In fact no connections will be dropped during the fail-over. Internally, the clients WireGuard interface renegotiate the handshake. However, that step is actually not observable by the user.

Run the following commands on Server A while alongside test the connectivity from the client side through the tunnel via ping -i0.2 2001:DB8:2::1:

# Check that keepalived has moved the VIP to interface eno1
ip addr show dev eno1

# Bring down the Wireguard interface
wg-quick down wg1

# Keepalived should now have moved the VIP to Server B
ip addr show dev eno1

Going further

In my personal network, I operate a Interior Gateway Protocol (IGP) to dynamically route traffic within and also towards other networks. Common IGPs are OSPF, ISIS or BGP. In my specific case, both Servers A & B run the Bird2 routing daemon with interior and exterior BGP sessions.

So how does the WireGuard HA setup interoperates with my interior routing? Quite well actually. As my notify script (keepalive-wg.sh) will automatically bring up/down the interface, the routes attached to the interface will be picked up by Bird’s direct protocol.

I am also planning to extend my WireGuard agent ɯice to support the synchronization of WireGuard interface configurations between multiple servers.

Background

Surprisingly, the setup works by using Keepalived and does not require any iptables or nftables magic to rewrite source IP addresses. I’ve seen some people mentioning that SNAT/DNAT would be required to convince WireGuard to use the virtual IP instead of the server addresses. However, in my experience this was not necessary.

Another concern has been that the backup Wireguard interface still might attempt to establish a handshake with its peers. This would quite certainly interfere with the handshakes originated by the current master server. However, also this has not been proven to be the case. I assume the fact that our notify script brings down the WireGuard interface on the backup server causes them to cease all communication with its peers.

GoSƐ – A terascale file-uploader

GoSƐ is a modern and scalable file-uploader focusing on scalability and simplicity. It is a little hobby project I’ve been working on over the last weekends.

The only requirement for GoSƐ is a S3 storage backend which allows to it to scale horizontally without the need for additional databases or caches. Uploaded files a divided into equally sized chunks which are hashed with a MD5 digest in the browser for upload. This allows GoSƐ to skip chunks which already exist. Seamless resumption of interrupted uploads and storage savings are the consequence.

And either way both upload and downloads are always directed directly at the S3 server so GoSƐ only sees a few small HTTP requests instead of the bulk of the data. Behind the scenes, GoSƐ uses many of the more advanced S3 features like Multi-part Uploads and Pre-signed Requests to make this happen.

Users have a few options to select between multiple pre-configured S3 buckets/servers or enable browser & mail notifications about completed uploads. A customisable retention / expiration time for each upload is also selectable by the user and implemented by S3 life-cycle policies. Optionally, users can also opt-in to use an external service to shorten the URL of the uploaded file.

Currently a single concurrent upload of a single file is supported. Users can observe the progress via a table of details statistics, a progress-bar and a chart showing the current transfer speed.

GoSƐ aims at keeping its deployment simple and by bundling both front- & backend components in a single binary or Docker image. GoSƐ has been tested with AWS S3, Ceph’s RadosGW and Minio. Pre-built binaries and Docker images of GoSƐ are available for all major operating systems and architectures at the release page.

GoSƐ is open-source software licensed under the Apache 2.0 license.

Live Demo

Screencast

Features

  • De-duplication of uploaded files based on their content-hash
    • Uploads of existing files will complete in no-time without re-upload
  • S3 Multi-part uploads
    • Resumption of interrupted uploads
  • Drag & Drop of files
  • Browser notifications about failed & completed uploads
  • User-provided object expiration/retention time
  • Copy URL of uploaded file to clip-board
  • Detailed transfer statistics and progress-bar / chart
  • Installation via single binary or container
    • JS/HTML/CSS Frontend is bundled into binary
  • Scalable to multiple replicas
    • All state is kept in the S3 storage backend
    • No other database or cache is required
  • Direct up & download to Amazon S3 via presigned-URLs
    • Gose deployment does not see an significant traffic
  • UTF-8 filenames
  • Multiple user-selectable buckets / servers
  • Optional link shortening via an external service
  • Optional notification about new uploads via shoutrrr
    • Mail notifications to user-provided recipient
  • Cross-platform support:
    • Operating systems: Windows, macOS, Linux, BSD
    • Architectures: arm64, amd64, armv7, i386

Roadmap

I consider the current state of GoSƐ to be production ready. Its basic functionality is complete. However, there are still some ideas which I would like to work on in the future:

Also checkout the GitHub Issue Tracker for a detailed overview.

Running a Xilinx hw_server as Docker Container

This article describes the necessary steps to run a Xilinx hw_server as a Docker container.

Xilinx’s hw_server is a command line utility which handles JTAG communication between a Xilinx FPGA board and usually the Vivado IDE. It can be used to configure the FPGA bitstream, connect to the embedded logic analyzer cores (ILA) or perform debugging of processor cores via GDB and the Xilinx System Debugger (XSDB). The hw_server is usually used when those tasks shall performed remotely as the connection between Vivado or XSDB is established via TCP connection and allows us to run it on a remote system.

Running the hw_server as a Docker container has the benefit that its installation is simplified to starting a Docker container by running:

docker run --restart unless-stopped --privileged --volume /dev/bus/usb:/dev/bus/usb --publish 3121:3121 --detach ghcr.io/stv0g/hw_server:v2021.2

It also allows us to run the hw_server on architectures which are not natively supported by Xilinx such as the commonly used Aarch / ARM64 and ARMv7 architectures found in Raspberry Pis.

This is enabled by Dockers support for running container images for non-native architectures. I am using the aptman/qus image to setup this user-mode emulation. qemu-user-static (qus) is a compilation of utilities, examples and references to build and execute OCI images (aka docker images) for foreign architectures using QEMU’s user-mode emulation.

Run the following commands to run the hw_server on a embedded device:

# Install docker
sudo apt-get update && sudo apt-get upgrade
curl -sSL https://get.docker.com | sh

# Start Docker
sudo systemctl enable --now docker

# Enable qemu-user emulation support for running amd64 Docker images
# *Note:* only required if your system arch is not amd64!
docker run --rm --privileged aptman/qus -s -- -p x86_64

# Run the hw_server
docker run --restart unless-stopped --privileged --volume /dev/bus/usb:/dev/bus/usb --publish 3121:3121 --detach ghcr.io/stv0g/hw_server:v2021.2

This setup has been tested with a Raspberry Pi 4 running the new 64-bit Debian Bullseye Raspberry Pi OS.

The pre-built Docker image for the hw_server of Vivado 2021.2 is available via ghcr.io/stv0g/hw_server:v2021.2.

Detailed instructions can be found in the following Git repo: https://github.com/stv0g/xilinx-hw-server-docker.

Use Yubikey and Password-store for Ansible credentials

I spent some time over the last months to improve the security of servers and passwords. In doing so, I started to orchestrate my servers using a configuration management tool called Ansible. This allows me to spin-up fresh servers in a few seconds and to get rid of year-old, polluted and insecure system images.

ansible_loves_yubico

My ’single password for everything‘ has been replaced by a new password policy which enforces individual passwords for every single service. This was easier than I previously expected:

To unlock the ‚paranoid‘ level, I additionally purchased a Yubikey Neo token to handle the decryption of my login credentials in tamper-proof hardware.
pass‚ is just a small shell script to glue several existing Unix tools together: Bash, pwgen, Git, xclip & GnuPG (obeying the Unix philosophy). The passwords are stored in simple text files which are encrypted by PGP and stored in a directory structure which is managed in a Git repository.

IMG_20150526_121142
Yubikey Neo und Neo-n

There are already a tons of tutorials which present the tools I describes above. I do not want to repeat all that stuff. So, this post is dedicated to solve some smaller issues I encountered:

Use One-Time passwords across multiple servers

The Yubikey Neo can do much more than decrypting static passwords via GnuPG:

  • Generate passwords:
    • fixed string (insecure!)
    • with Yubico OTP algorithm
    • with OATH-HOTP algorithm
  • Do challenge response authentication
    • via FIDO’s U2F standard
    • with HMAC-SHA1 algorithm
    • with Yubico OTP algorithm

Some third-party services already support FIDO U2F standard or traditional OATH-{H,T}OTP TFA, like used by the Google authenticator app. I suggest to have a look at: https://twofactorauth.org/.

For private servers there are several PAM modules available to integrate OTP’s or Challenge Response (CR) methods. Unfortunately, support for CR is not widespread across different SSH- and mail clients.

So, you want to use OTP’s which leds to another problem: OTP’s rely on a synchronized counter between the hardware token and the server. Once you use multiple servers, those must be synchronized as well. I’m using a central Radius server to facilitate this.

Integrate ‚pass‘ into your Ansible workflow

Ansible uses SSH and Python scripts to manage several remote machines in parallel. You must use key-based SSH authentication, because you do not want to type every password manually! Additionally you need to get super user privileges for most of your administrative tasks on the remote machine.

The SSH authentication is handled by gpg-agents ‚–enable-ssh-support‘ option and a PGP key on your token.

To get super user privileges, I use the following variable declaration my Ansible „group_vars/all“ file:
---
ansible_sudo_pass: "{{ lookup('pipe', 'pass servers/' + inventory_hostname) }}"

There is a separate root password for every server (e.g. „pass servers/lian.0l.de“). I wrote some ansible roles to easily and periodically roll those passwords.

Integrate ‚pass‘ into OS X

There are already several plugins and extensions to intergrate the ‚pass‘ password store into other Programs like Firefox and Android.

pass_osx_prompt
A prompt for the password you want

I added support for OS X by writing a small AppleScript which can be found here: https://github.com/zx2c4/password-store/blob/master/contrib/pass.applescript

pass_osx_notification
A notification with countdown