Automating Debian Package Cleanup using a Python Script

If you’re using Debian as your operating system, you may have encountered the need to manage packages using the 'dpkg' command. Specifically, packages with the 'rc' (remove and configuration files) status can linger on your system, taking up space. Manually removing these packages can be time-consuming. In this blog post, I introduce a Python script that I developed to automate and simplify this process.

Background

In Debian, packages with the 'rc' status may occur when they have been previously removed but still leave configuration files on the system. To identify and remove such packages, the typical command used is:

dpkg -l | grep ^rc | awk {'print $2'} | xargs dpkg -P

This command filters out all packages with the 'rc' status from the list of installed packages and then removes them entirely.

The Python Script

The Python script I developed streamlines this process and provides some additional features. Here are the key functions of the script:

1. Lists packages with the „rc“ status

By calling the script without arguments or with the -l argument, you can display a list of packages with the 'rc' status:

./purgerc -l

The script shows all relevant packages that can be purged.

2. Removes packages with the „rc“ status

By calling the script with the -f argument, all packages with the 'rc' status are removed:

./purgerc -f

The script automatically executes the command

dpkg -l | grep ^rc | awk {'print $2'} | xargs dpkg -P

and removes the corresponding packages.

3. Summary of removed packages

After removal, the script provides an overview of the removed packages:

Packages removed successfully: 
package1
package2
...

4. Help message

By calling the script with the -h or -? argument, you receive a help message:

./purgerc -h

Usage and Security

To run the script, ensure that you have the necessary permissions to remove packages. This is typically achieved by using 'sudo'.

Please note that using 'shell=True' can pose certain security risks. In this case, since user input is not directly inserted into the command, it should be acceptable. If you still have concerns, consider alternative methods such as using 'subprocess.Popen' or breaking the command into separate calls.

With this Python script, the cleanup of Debian packages with the 'rc' status becomes more straightforward and user-friendly. It provides a structured way to view, remove packages, and receive a summary of the actions taken. Say goodbye to complex commands and automate this process with my helpful script.

The Script „purgerc“

#!/usr/bin/env python3
import subprocess
import sys
def list_rc_packages():
    try:
        # Run dpkg command to list packages with status "rc"
        result = subprocess.run(['dpkg', '-l'], capture_output=True, text=True, check=True)
        lines = result.stdout.split('\n')
        rc_packages = [line.split()[1] for line in lines if line.startswith('rc')]
        
        if rc_packages:
            print("These packages can be purged:")
            print('\n'.join(rc_packages))
        else:
            print("No packages available to be purged.")
    except subprocess.CalledProcessError as e:
        print(f"Error: {e}")
        sys.exit(1)
def remove_rc_packages():
    try:
        # Run dpkg command to list packages with status "rc" and remove them
        result = subprocess.run('dpkg -l | grep "^rc" | awk \'{print $2}\' | xargs dpkg -P', capture_output=True, text=True, shell=True, check=False)
        if result.returncode == 0:
            removed_packages = result.stdout.strip().split('\n')
            print("Packages removed successfully:")
            print('\n'.join(removed_packages))
        else:
            print("No packages available to be purged.")
    except subprocess.CalledProcessError as e:
        print(f"Error: {e}")
        sys.exit(1)
def print_usage():
    print("Usage:")
    print("  purgerc             : List packages with status 'rc'")
    print("  purgerc -l          : List packages with status 'rc'")
    print("  purgerc -f          : Purge packages with status 'rc'")
    print("  purgerc -h or -?    : Show this usage message")
def main():
    if len(sys.argv) == 1:
        list_rc_packages()
    elif len(sys.argv) == 2:
        if sys.argv[1] == '-l':
            list_rc_packages()
        elif sys.argv[1] == '-f':
            remove_rc_packages()
        elif sys.argv[1] in ['-h', '-?']:
            print_usage()
        else:
            print("Invalid argument. Use -h or -? for usage.")
            sys.exit(1)
    else:
        print("Invalid number of arguments. Use -h or -? for usage.")
        sys.exit(1)
if __name__ == "__main__":
    main()

Emotet Erkennung mit Icinga / Nagios und EmoCheck

Neulich wurde bei Heise (https://heise.de/-4652554) über ein interessantes Tool berichtet, mit dem geprüft werden kann, ob ein PC bereits mit der Schadsoftware „Emotet“ infiziert ist. Dies erledigt das Tool „EmoCheck“ (https://github.com/JPCERTCC/EmoCheck/releases) indem es den Rechner auf Prozesse untersucht, die typisch für eine Emotet-Infektion sind. In dem Artikel wird darauf hingewiesen, dass sich ein mit Emotet infizierter Rechner nicht zwangsläufig sofort auffällig verhält. In dem genannten Artikel heißt es: „[…] typischerweise vergehen zwischen der ersten Emotet-Infektion in einem Firmennetz und dem Verteilen des Erpressungs-Trojaners Ryuk ein bis zwei Wochen.“

Es gibt einige Diskussionen über die Funktionsweise dieses Tools. So regt sich einiges an Kritik am Umstand, dass EmoCheck nach statischen Prozessnamen sucht. Ich teile diese Bedenken dahingehend, dass Emotet seinen Prozessen jederzeit anderslautende Namen geben könnte. Allerdings bin ich der Meinung, dass dieses Werkzeug einen installierten Virenschutz sicherlich sinnvoll ergänzen kann und es in Anbetracht des doch erheblichen Schadenpotentials von Emotet sicherlich nicht schlecht ist, sich nur auf einen Prüfmechanismus zu verlassen.

In diesem Artikel beschreibe ich, wie man das Monitoringsystem Icinga bzw. Nagios in Verbindung mit EmoCheck nutzen kann um in einem Unternehmensnetz Emotet-Infektionen frühzeitig erkennen zu können und sich gegebenenfalls aktiv warnen zu lassen.

./libexec/check_emotet
#!/usr/bin/perl
use strict;
use warnings;
use File::Copy;

binmode STDOUT, ":utf8";
use utf8;
use JSON;

use experimental qw( switch );
use feature qw(switch say);

# Declare infection pointer
my $infected = 0;
my $infected_host = "";
my $dir = '/opt/emocheck';

foreach my $fp (glob("$dir/*.json")){
        my $json;
        {
                local $/; # This enables 'slurp' mode
                open my $fh, "<", $fp;
                $json = <$fh>;
                close $fh;
        }
        my $data = decode_json($json);
        if ($data->{'is_infected'} eq 'yes'){
                # Infection found! Set $infected to 1 and set/concatenate affected hostnames delimited by '|'
                $infected = 1;
                if ($infected_host eq ""){
                        $infected_host = $data->{'hostname'};
                }else{
                        $infected_host .= "/" . $data->{'hostname'};
                }
        }
        move($fp, $dir. "/processed");
}

given ($infected) {
    chomp($infected);
    when ($infected lt '1') { print "OK - No infection found."; exit(0);      }
    when ($infected eq '1') { print "CRITICAL - One or more infections suspected. ($infected_host)"; exit(2); }
    default { print "UNKNOWN - $infected of disk space used."; exit(3); }
}

@echo off
.\emocheck_x64 /quiet /json /output \\icinga\emocheck

checkcommands.cfg
define command {
                command_name                          check_emotet
                command_line                          $USER1$/check_emotet
}

advanced_services.cfg
define service {
                service_description                   Check Emotet Infection
                max_check_attempts                    1
                first_notification_delay              0
                notification_interval                 0
                notification_options                  c,r
                notifications_enabled                 1
                event_handler_enabled                 1
                check_command                         check_emotet!
                check_period                          24x7
                notification_period                   24x7
                host_name                             icinga.mein.netz
                contact_groups                        +admins,ProductionAdmins
                use                                   generic-service
}

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run]
"emocheck"="C:\\Program Files\\Emocheck\\emocheck_x64.exe /quiet /json /output \\\\icinga\\emocheck"

Suchgeschwindigkeit in Roundcube erhöhen

Mal so nebenbei eine schnelle Lösung für ein nerviges Problem mit Roundcube.

Ich persönlich nutze hauptsächlich den Roundcube Webmailer. Er ist sehr flexibel, überall nutzbar und „eigentlich“ auch recht schnell. Mein Postfach habe ich mittels Ordnern strukturiert, die Datenmenge ist mit ca. 5 GB beachtlich.

Warum aber „eigentlich“ schnell? Sofern man Mails liest, schreibt und versendet ist der Webmailer wahrlich schnell. Benutzt man jedoch die Suchfunktion von Roundcube ist es mit der Geschwindigkeit schnell vorbei. Dies ging bei meinen System soweit, dass der Apache Webserver gelegentlich einen Fehler 500 zurückgab. Die Ursache war, dass der entsprechende PHP-Prozess in ein Timeout gelaufen war.

Wenn ich etwas such, dann erledigte ich dies bislang zumeist über den Mozilla Thunderbird Mailclient. Da dieser einen lokalen Suchindex aufbaut, bekommt man hier extrem schnell die gewünschten Suchergebnisse präsentiert. Was zuhause gut funktioniert, war mit Roundcube eben bisher ein wirkliches Problem.

Eine logische Erklärung brachte mir ein Beitrag im Plesk-Forum. Sobald man in Dovecot die Volltextsuche aktiviert, läuft die Suche mit bisher ungeahnter Geschwindigkeit. Hier die Lösung:

Auf dem Mailserver die Datei /etc/dovecot/conf.d/99-fts.conf anlegen und mit folgendem Inhalt befüllen:

protocol imap {
mail_plugins = "quota imap_quota fts fts_squat"
}
plugin {
fts = squat
fts_squat = partial=4 full=10
fts_autoindex = yes
}

Danach den Dovecot-Prozess neu starten, das Mail-Log sicherheitshalber auf Fehler untersuchen und die nun deutlich verbesserte Suchgeschwindigkeit genießen.

Der Beitrag, dem ich diese Information entnommen habe, ist unter der URL https://support.plesk.com/hc/en-us/articles/115000532574-The-search-speed-is-slow-in-Roundcube zu finden.

Raspberry Pi – Kernel Upgraden/Downgraden

Wie in meinem Artikel Tvheadend – Aussetzer beim Streaming erwähnt, kann es unter bestimmten Umständen notwendig sein, den Raspberry Pi mit einem anderen, als dem in der jeweiligen Raspbian-Version enthaltenen Kernel zu betreiben. Bekanntschaft habe ich mit diesem Problem bereits im Zusammenhang mit Tvheadend und Node-Red gemacht.

Ich werde nun beschreiben, wie der Kernel up- oder downgegraded werden kann. Hierfür setze ich voraus, dass der Raspberry Pi unter Raspbian läuft. Zunächst sollte man (sofern noch nicht geschehen) herausfinden, welcher Kernel aktuell läuft. Mit dem Befehl

uname -r

wird die momentan laufende Kernel-Version angezeigt. In meinem Fall war dies die 4.9.70-v7+.

Möchte man nun ein Downgrade auf die Version 4.4.50-v7+ durchführen, muss man sich den git-Hash des entsprechenden Commits heraussuchen. Dies erledigt man im Git-Repository von Hexxeh unter der Adresse https://github.com/Hexxeh/rpi-firmware . Mit einem Klick auf den Knopf „<soundsoviele> Commits“ bekommt man eine Übersicht über alle vorhandenen Kernel-Versionen angezeigt.

Nun wird bis zur gewünschten Version herunter gescrollt. Relevant sind hier die Einträge „kernel: bump to x.x.xx“. Im rechten Bereich der Ansicht können wir den entsprechenden Hash in die Zwischenablage nehmen.

Um nun die eigentliche Installation der gewünschten Version vorzunehmen gehen wir wieder in die Console und geben nun (beispielsweise für die 4.4.50) folgenden Befehl ein:

rpi-update 52241088c1da59a359110d39c1875cda56496764

Nun läuft die Installation an, die den Kernel, die Kernelmodule und die Firmware-Files installiert.

Im Anschluß muss der Raspberry Pi neu gebootet werden.

 

 

Tvheadend – Aussetzer beim Streaming

Wie man Probleme mit Aussetzern bei Tvheadend bei der Nutzung auf dem Raspberry Pi löst, erkläre ich in diesem Beitrag. Ich werde hier keine Anleitung zur Einrichtung von LibreELEC, Kodi, Tvheadend, etc. bereitstellen, da das Internet voll solcher Anleitungen ist.

Vor einem guten Jahr habe ich meinen konventionellen SAT-Receiver, eine „Volksbox“, in Rente geschickt. Sie lief mir nicht stabil genug und war mir im Handling etwas, naja, unbequem. Ich bin verwöhnt von einer DreamBox 7025, die ich jahrelang genutzt habe.LibreELEC

Länger schon wollte ich mich mit Kodi beschäftigen – einem Mediacenter für Fernsehen und so ziemlich alle anderen medialen Anforderungen, die man sich vorstellen kann. Mit LibreELEC (https://libreelec.tv/) habe ich eine Lösung gefunden, die man nur auf die SD-Karte packen muss, diese Karte in den Raspberry Pi stecken, booten und los geht’s…

Einen geeigneten Raspberry Pi hatte ich zur gleichen Zeit zu einem guten Preis als Bundle (Raspberry + Gehäuse + Netzteil + SD-Karte) irgendwo im Netz gefunden und bestellt.

Möchte man nur Filme, die man auf einem NAS liegen hat, ansehen oder Online-Mediatheken diverser Fernsehsender nutzen, dann muss man nur noch die entsprechenden „Apps“ im LibreELEC-Image installieren und kann dann sofort diese Dienste nutzen. Möchte man zusätzlich Satelliten-TV nutzen, wird es etwas komplizierter, da man nun einen SAT-Receiver dazu bringen muss, den jeweiligen per Kodi gewählten Sender ins Netzwerk zu streamen.

Aufbau

Bei mir kommt folgende Hardware zum Einsatz:

  1. LG 42″ Fernseher mit u.A. HDMI-Anschluss
  2. Ein Raspberry Pi 3 mit 16 GB SD-Karte (libreELEC installiert), angeschlossen am Fernseher
  3. Ein Raspberry Pi 2 als zentraler Server für interne NextCloud, DHCP, DNS, Node-RED-Host, etc.
  4. Ein an den zentralen Raspberry Pi 2 angeschlossener USB-Satreceiver (TechnoTrend TT-connect S2-4600), Tvheadend

Tvheadend steuert den Satreceiver, stellt also den vom sog. PVR-Client auf der LibreELEC-Maschine angeforderten Transponder ein und streamt somit das entsprechende Programm über’s LAN zu Kodi schickt. Nach einem Problem mit der SD-Karte am zentralen Raspberry Pi 2 habe ich diese Maschine neu installiert. Fortan hatte ich Probleme – das Fernsehbild zeigte oft Klötzchen, blieb hängen, schien puffern zu müssen und hatte Ton-Ausfälle. Im Syslog fand ich plötzlich folgende Meldungen:

[codeblocks name=’codeblock_0′]

Diese „Continuity Counter Errors“ bereiteten mir wirklich Kopfzerbrechen. Die Last auf dem zentralen RPI hatte sich durch die Neuinstallation nicht vergrößert. Da ich die Schüssel nur mit einem sehr rudimentären Messgerät ausgerichtet hatte, bestellte ich sogar einen Fachbetrieb für SAT-Installationen um nachzumessen. Es sei alles perfekt eingestellt, bestätigte der Techniker, an der Ausrichtung der Schüssel konnte es also nicht liegen. Heute konnte ich nun das Problem eingrenzen und schließlich erfolgreich lösen.

Nach der Neuinstallation lief mein zentraler RPI mit dem Kernel v4.9.35. Unter der URL https://forum.libreelec.tv/thread/4235-dvb-issue-since-le-switched-to-kernel-4-9-x/?pageNo=2 erhielt ich den finalen Hinweis. Es handelt sich um ein bekanntes Fehlerbild, dass Tvheadend unter dem v4.9-Kernel dieses Verhalten zeigt. Ich habe nun den Kernel, wie in der genannten URL beschrieben, auf die v4.4 zurückgedreht, wodurch es nun wieder wunderbar funktioniert.

Node-RED – Installation unter Ubuntu

Was ist Node-RED?

Node-RED LogoNode-RED ist ein grafisches Entwicklungswerkzeug, dass vor allem von Leuten benutzt wird, die sich mit IoT (Internet of Things – Internet der Dinge) auseinandersetzen. In erster Linie kann Node-RED dafür genutzt werden, Geräte (sowohl netzwerkfähiges Equipment als auch Geräte, die seriell, per Bluetooth, 1-wire, i²c, etc. angebunden sind) miteinander zu vernetzen, Daten per Sensor oder aus Cloud-Diensten zu empfangen, auszuwerten und weiter zu verarbeiten. Node-RED bietet hierfür eine hervorragende grafische Oberfläche an um dies visuell zu erledigen. Hochinteressant ist die Möglichkeit, auf Ereignisse, die von bzw. durch ein angeschlossenes Gerät (oder einen eingebundenen Dienst) erzeugt werden, eine weitere Aktion auslösen zu können.

Weiterlesen

Eine eigene SSL Zertifizierungsstelle (Root CA) für die Nutzung im LAN erstellen – Teil II

Interne Zertifikate erzeugen

Im ersten Teil haben wir ein Root-Zertifikat für unsere eigene SSL Zertifizierungsstelle erzeugt. Wir sind nun in der Lage, nach Belieben SSL-Zertifikate zu erzeugen, denen unser Browser vertrauen wird (nachdem wir unsere Zertifizierungsstelle innerhalb unseres Netzwerks bekannt gemacht haben).
Wir werden uns nun Schritt für Schritt an die Erzeugung eines Zertifikates für einen Apache Webserver machen und uns ansehen, wie der Virtual Host konfiguriert werden muss.

Weiterlesen

Eine eigene SSL Zertifizierungsstelle (Root CA) für die Nutzung im LAN erstellen – Teil I

Vertrauenssache – Interne SSL-Zertifikate

Im LAN werden oftmals SSL-Zertifikate zur Nutzung verschiedener  Dienste benötigt. Oft bleibt hier nichts anderes übrig, als selbstsignierte Zertifikate zu verwenden. Diese Zertifikate erfüllen zwar aus technischer Sicht ihren Zweck, den Anwender bzw. Administrator stellen sie aber immer wieder vor lästige Probleme.

Weiterlesen