Red Hat Enterprise Linux 8 Update Kurs-Notizen

1 Informationen zum Kurs

2 CentOS vs. RedHat

3 KVM CentOS Installation

  • QEMU/KVM und den Virt-Manager installieren
dnf install qemu-kvm virt-manager
  • CentOS 8 Installationsmedium laden
curl -O http://192.168.1.131:8080/CentOS-8.1.1911-x86_64-dvd1.iso
  • CentOS 8 in einer virtuellen Maschine installieren
    • 1GB RAM
    • 2 CPUs
    • 20 GB Installations-Laufwerk
    • 5 x 1 GB Laufwerke konfigurieren
    • MACVTAP Netzwerk über Bridge
  • CentOS Installations Auswahl
    • Minimal Install
    • Zeitzone Europa/Berlin
    • Netzwerk aktivieren, Hostname "centos-vm.home.arpa", Adressen über DHCP
    • Benutzer "nutzerXX" anlegen

4 "yum4" Paketmanager (aka "dnf")

4.1 Konfiguration

  • die Konfiguration von dnf liegt unter /etc/dnf/dnf.conf.
  • die Repository-Konfigurationen liegen weiterhin unter /etc/yum.repos.d
# ls -l /etc/yum.repos.d/CentOS-*
-rw-r--r--. 1 root root  731 Jan  2 16:21 /etc/yum.repos.d/CentOS-AppStream.repo
-rw-r--r--. 1 root root  712 Jan  2 16:21 /etc/yum.repos.d/CentOS-Base.repo
-rw-r--r--. 1 root root  798 Jan  2 16:21 /etc/yum.repos.d/CentOS-centosplus.repo
-rw-r--r--. 1 root root 1043 Jan  2 16:21 /etc/yum.repos.d/CentOS-CR.repo
-rw-r--r--. 1 root root  668 Jan  2 16:21 /etc/yum.repos.d/CentOS-Debuginfo.repo
-rw-r--r--. 1 root root  756 Jan  2 16:21 /etc/yum.repos.d/CentOS-Extras.repo
-rw-r--r--. 1 root root  338 Jan  2 16:21 /etc/yum.repos.d/CentOS-fasttrack.repo
-rw-r--r--. 1 root root  738 Jan  2 16:21 /etc/yum.repos.d/CentOS-HA.repo
-rw-r--r--. 1 root root  928 Jan  2 16:21 /etc/yum.repos.d/CentOS-Media.repo
-rw-r--r--. 1 root root  736 Jan  2 16:21 /etc/yum.repos.d/CentOS-PowerTools.repo
-rw-r--r--. 1 root root 1382 Jan  2 16:21 /etc/yum.repos.d/CentOS-Sources.repo
-rw-r--r--. 1 root root   74 Jan  2 16:21 /etc/yum.repos.d/CentOS-Vault.repo
  • Interessante Optionen:
    • gpgkey_dns_verification=yes Prüfe neue GPG Schlüssel gegen die im DNS abgelegten GPG-Schlüssel. Benötigt libunbound und einen DNSSEC fähigen DNS-Resolver (z.B. systemd-resolved oder unbound)
    • install_weak_deps=False nun unbedingt notwendige Abhängigkeiten installieren, keine Empfehlungen (weniger Software auf einem Server = weniger Komplexität)
    • protected_packages=<liste-von-paketnamen> Pakete die nie deinstalliert werden sollen. Kann alternativ auch unter /etc/dnf/protected.d/*.conf konfiguriert werden
    • ip_resolve=IPv4|IPv6 über welches Protokoll sollen Domainnamen aufgelöst werden. Notwendig, wenn IPv4 oder IPv6 nur lokal im Netzwerk verfügbar sind
    • proxy=http://proxy.name/ Download über Web-Proxy-Server
    • assumeyes=True keine Benutzerinteraktion, immer "YES" als Antwort auf Fragen annehmen (wenn dnf hauptsächlich von Skripten benutzt wird)

4.2 Pakete installieren

  • aus den Repositories
# dnf install epel-release
  • aus Dateien im Dateisystem
# curl -O dnf install http://mirror.centos.org/centos-8/8.1.1911/extras/x86_64/os/Packages/epel-release-8-5.el8.noarch.rpm
# dnf install epel-release-8-5.el8.noarch.rpm
  • aus Dateien im Netz
dnf install http://mirror.centos.org/centos-8/8.1.1911/extras/x86_64/os/Packages/epel-release-8-5.el8.noarch.rpm
  • nach Paketen suchen
# dnf search <suchausdruck>
  • Beispielsuche
# dnf search "*golang*"
Last metadata expiration check: 0:25:35 ago on Sun 01 Mar 2020 10:17:51 PM CET.
========================================================== Name & Summary Matched: *golang* ==========================================================
golang-docs.noarch : Golang compiler docs
golang-bin.x86_64 : Golang core compiler tools
golang-src.noarch : Golang compiler source tree
golang-tests.noarch : Golang compiler tests for stdlib
golang-misc.noarch : Golang compiler miscellaneous sources
golang-race.x86_64 : Golang std library with -race enabled
=============================================================== Name Matched: *golang* ===============================================================
golang.x86_64 : The Go Programming Language
============================================================= Summary Matched: *golang* ==============================================================
go-srpm-macros.noarch : RPM macros for building Golang packages for various architectures

4.3 Updates

  • Liste der anstehenden Updates inkl. der Änderungen
# dnf check-update --changelog
  • Liste der Sicherheitsupdates
dnf updateinfo --security --sec-severity Important --list --available
  • Upgrade des Systems
dnf upgrade
  • Vollständiges Update des Systems (auch Downgrades und entfernen von nicht mehr verfügbaren Paketen)
# dnf distro-sync
  • Minimales Update (nur Sicherheitsupdates, keine weiteren neuen Paketversionen)
# dnf upgrade-minimal
  • Paket-Cache nach einer Installation / einem Update löschen (ggf. wichtig bei der Erstellung von VM/Container-Images)
# dnf clean packages

4.4 Paket Downgrade

dnf downgrade <paketname-inkl-version>

4.5 Paket deinstallieren

dnf remove <paketname>
  • Information über ein Paket abrufen
# dnf info hc-utils
Last metadata expiration check: 0:15:29 ago on Sun 01 Mar 2020 10:17:51 PM CET.
Installed Packages
Name         : hc-utils
Version      : 0.0.2
Release      : 1.el8
Architecture : noarch
Size         : 3.6 k
Source       : hc-utils-0.0.2-1.el8.src.rpm
Repository   : @System
From repo    : @commandline
Summary      : A set of utilities for Hetzner Cloud
URL          : https://github.com/hetznercloud/hc-utils
License      : MIT
Description  : hc-utils contains utilities to automatically configure
	     : Hetzner Cloud private network interfaces and block storage volumes
  • alle installierten Pakete auflisten
# dnf list --installed
  • Liste der installierten Pakete filtern
# dnf list --installed "python*"
  • welches Paket installiert eine Datei/ein Programm
# dnf provides /usr/bin/gzip
Last metadata expiration check: 0:19:31 ago on Sun 01 Mar 2020 10:17:51 PM CET.
gzip-1.9-9.el8.x86_64 : The GNU data compression program
Repo        : @System
Matched from:
Filename    : /usr/bin/gzip

gzip-1.9-9.el8.x86_64 : The GNU data compression program
Repo        : BaseOS
Matched from:
Filename    : /usr/bin/gzip

4.6 Paketgruppen

  • alle verfügbaren Paketgruppen auflisten
# dnf group list --available "*"
  • Detailinformationen zu Gruppen anzeigen
# dnf -v group info "*"
  • Gruppen-Pakete installieren
# dnf groupinstall "Virtualization Hypervisor"

4.7 DNF Historie

  • Liste der dnf Transaktionen (hier eine CentOS 8 Cloud Instanz bei Hetzner - Hetzner entfernt firewalld bei der Installation)
# dnf history
ID     | Command line             | Date and time    | Action(s)      | Altered
-------------------------------------------------------------------------------
     7 | install tmux emacs-nox   | 2020-03-01 21:50 | Install        |    8
     6 | update                   | 2020-03-01 21:45 | I, U           |  219 EE
     5 |                          | 2020-01-12 05:21 | Install        |    1
     4 |                          | 2020-01-12 05:21 | Install        |   30
     3 | -C -y remove firewalld - | 2020-01-12 05:20 | Removed        |   14 EE
     2 | -C -y remove linux-firmw | 2020-01-12 05:20 | Removed        |    1
     1 |                          | 2020-01-12 05:17 | Install        |  373 EE

  • Details einer Transaktion
# dnf history info 4
Transaction ID : 4
Begin time     : Sun 12 Jan 2020 05:21:37 AM CET
Begin rpmdb    : 355:a37d783b17077e589ca25c5c49f1c3794c5e85ae
End time       : Sun 12 Jan 2020 05:21:42 AM CET (5 seconds)
End rpmdb      : 385:f407d6d2a43ae4232fc41ac28286cd4d17dcf41b
User           : root <root>
Return-Code    : Success
Releasever     : 8
Command Line   :
Packages Altered:
    Install cloud-init-18.5-1.el8.4.noarch                       @AppStream
    Install cloud-utils-growpart-0.29-2.el8.noarch               @AppStream
    Install python3-babel-2.5.1-3.el8.noarch                     @AppStream
    Install python3-jinja2-2.10.1-2.el8_0.noarch                 @AppStream
    Install python3-jsonpatch-1.21-2.el8.noarch                  @AppStream
[...]
  • zu einem alten Transaktionsstand zurückkehren (Pakete der alten Versionen müssen noch verfügbar sein)
# dnf history rollback 5 | head -15
Last metadata expiration check: 0:10:05 ago on Sun 01 Mar 2020 10:17:51 PM CET.
Rollback to transaction 5, from Sun 12 Jan 2020 05:21:59 AM CET
  Undoing the following transactions: 6, 7, 8
    Upgraded NetworkManager-1:1.14.0-14.el8.x86_64                                    @@System
    Upgrade  NetworkManager-1:1.20.0-5.el8_1.x86_64                                   @BaseOS
    Upgraded NetworkManager-libnm-1:1.14.0-14.el8.x86_64                              @@System
    Upgrade  NetworkManager-libnm-1:1.20.0-5.el8_1.x86_64                             @BaseOS
    Upgraded NetworkManager-team-1:1.14.0-14.el8.x86_64                               @@System
    Upgrade  NetworkManager-team-1:1.20.0-5.el8_1.x86_64                              @BaseOS
    Upgraded NetworkManager-tui-1:1.14.0-14.el8.x86_64                                @@System
    Upgrade  NetworkManager-tui-1:1.20.0-5.el8_1.x86_64                               @BaseOS
    Install  alsa-lib-1.1.9-4.el8.x86_64                                              @AppStream
    Upgraded authselect-1.0-13.el8.x86_64                                             @@System
    Upgrade  authselect-1.1-2.el8.x86_64                                              @BaseOS
    Upgraded authselect-libs-1.0-13.el8.x86_64                                        @@System
  • eine einzelne Transaktion rückgängig machen
# dnf history undo 5
Last metadata expiration check: 0:14:55 ago on Sun 01 Mar 2020 10:17:51 PM CET.
Undoing transaction 5, from Sun 12 Jan 2020 05:21:59 AM CET
    Install hc-utils-0.0.2-1.el8.noarch @@commandline
Dependencies resolved.
======================================================================================================================================================
 Package                           Architecture                    Version                               Repository                              Size
======================================================================================================================================================
Removing:
 hc-utils                          noarch                          0.0.2-1.el8                           @@commandline                          3.6 k

Transaction Summary
======================================================================================================================================================
Remove  1 Package

Freed space: 3.6 k
Is this ok [y/N]:

4.8 DNF Alias Definitionen

  • Alias-Definitionen werden unter /etc/dnf/aliases.d/USER.conf abgelegt
  • Liste der Alias-Definitionen
# dnf alias list
  • neuen Alias definieren
# dnf alias add security-info="updateinfo --security --sec-severity Important --list --available"
# dnf security-info
  • Alias löschen
# dnf alias delete security-info

4.9 DNF Shell

  • die DNF Shell erlaubt es, mehrere Aktionen in eine Transaktion zusammenzufassen und dann gebündelt auszuführen
# dnf shell
> install ruby
> remove emacs-nox
> ts
=======================================================================================================================================
 Package                                 Architecture              Version                           Repository                   Size
=======================================================================================================================================
Installing:
 ruby                                    x86_64                    2.6.5-124.fc31                    updates                      42 k
Installing dependencies:
 ruby-libs                               x86_64                    2.6.5-124.fc31                    updates                     3.0 M
 rubygem-irb                             noarch                    1.0.0-124.fc31                    updates                      64 k
 rubygem-json                            x86_64                    2.2.0-201.fc31                    fedora                       57 k
 rubygem-psych                           x86_64                    3.1.0-124.fc31                    updates                      51 k
 rubypick                                noarch                    1.1.1-11.fc31                     fedora                      9.8 k
Installing weak dependencies:
 rubygem-bigdecimal                      x86_64                    1.4.1-124.fc31                    updates                      57 k
 rubygem-did_you_mean                    noarch                    1.3.0-124.fc31                    updates                      37 k
 rubygem-io-console                      x86_64                    0.4.7-124.fc31                    updates                      22 k
 rubygem-openssl                         x86_64                    2.1.2-124.fc31                    updates                     154 k
 rubygem-rdoc                            noarch                    6.1.2-124.fc31                    updates                     408 k
 rubygems                                noarch                    3.0.3-124.fc31                    updates                     247 k
Removing:
 emacs-nox                               x86_64                    1:26.3-1.fc31                     @updates                     38 M
[...]
> run
=======================================================================================================================================
 Package                                 Architecture              Version                           Repository                   Size
=======================================================================================================================================
Installing:
 ruby                                    x86_64                    2.6.5-124.fc31                    updates                      42 k
Installing dependencies:
 ruby-libs                               x86_64                    2.6.5-124.fc31                    updates                     3.0 M
 rubygem-irb                             noarch                    1.0.0-124.fc31                    updates                      64 k
[...]
> exit
Leaving Shell
#

4.10 Anwendungen selektiv aktualisieren mit "Application Streams"

# dnf module list <paketname>
  • Default-Version eines Pakets installieren
# dnf install @ruby
  • Version eines installieren Pakets wechseln
# dnf module reset <paketname>
# dnf module enable <paketname>:<version>
# dnf install @<paketname>:<version>/<profile>
  • Paket mit Version und Profil installieren
# dnf install @ruby:2.6/common
# ruby -v
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-linux]

4.11 Liste der Paketquellen (Repositories)

  • anzeigen aller verfügbaren Repository-Quellen inkl. des Status (aktiviert / deaktiviert)
# dnf repolist all

4.12 Quelltextpakete / Entwicklerpakete

  • einige Quelltext-Pakete oder Entwicklerpakete sind in das PowerTools Repository gewechselt. Werden Quelltext-Pakete nicht gefunden, so kann es helfen dieses Repository anzuschalten
    dnf config-manager --set-enabled PowerTools
    

4.13 DNF Plugins

  • Versionlock Plugin installieren
# dnf  install  'dnf-command(versionlock)'
  • Versionssperre für ein Paket einschalten
# dnf versionlock add nginx
Letzte Prüfung auf abgelaufene Metadaten: vor 0:01:16 am Mo 02 Mär 2020 13:53:52 CET.
Versionssperre wird hinzugefügt zu: nginx-1:1.14.1-9.module_el8.0.0+184+e34fea82.*
  • Liste der Versionslocks anzeigen
# dnf versionlock list
Letzte Prüfung auf abgelaufene Metadaten: vor 0:01:55 am Mo 02 Mär 2020 13:53:52 CET.
nginx-1:1.14.1-9.module_el8.0.0+184+e34fea82.*

5 Systemd-resolved und DNS-over-TLS

5.1 Grundlagen von systemd-resolved

  • RedHat EL 8 / CentOS 8 kommt mit einem DNSSEC und DNS-over-TLS fähigen DNS Stub-Resolver.
  • Dieser Stub-Resolver kann neben DNS auch Namensauflösung über
    • Multicast DNS (mDNS) und DNS Service Discovery (DNS-SD). Damit wird eine separate Implentation von mDNS/DNS-SD wie Avahi nicht mehr benötigt.
    • Namensauflösung über Link-Local-Multicast-Name-Resolution (LLMNR), eine serverloses Namensauflösungsprotokoll von Microsoft welches von Windows Systemen verwendet wird
  • Beim Einsatz als Server oder in sicherheitskritischen Installationen sollten mDNS und LLMNR ausgeschaltet werden. Über diese Protokolle können Angreifer recht einfach und unbemerkt Rechnerkommunikation umleiten.
  • Liste der von systemd-resolved unterstützen Protokolle
# resolvectl -p help
Known protocol types:
dns
llmnr
llmnr-ipv4
llmnr-ipv6
mdns
mdns-ipv4
mdns-ipv6
  • systemd-resolvd horcht auf der IPv4-Loopback-Adresse 127.0.0.53 Port 53/TCP.
  • anders als über die Datei /etc/resolv.conf welche immer systemweit Gültigkeit hat, kann per systemd-resolved die Namensauflösungskonfiguration pro Netzwerkschnittstelle individuell angepasst werden
  • systemd-resolved bekommt die Konfiguration der DNS-Server von DHCP, DHCPv6, IPv6 Router-Advertisements und/oder manueller Konfiguration.
  • Der Dienst systemd-resolved ist in einer Standard-Installation aktiv, wird aber nicht aktiv für die (DNS-) Namensauflösung benutzt, da in der Datei /etc/resolv.conf in der Regel die per DHCP / DHCPv6 verteilten DNS-Server eingetragen sind (oder manuell eingetragene DNS-Server dort verwendet werden).
# systemctl status systemd-resolved
● systemd-resolved.service - Network Name Resolution
   Loaded: loaded (/usr/lib/systemd/system/systemd-resolved.service; enabled; vendor preset: disabled)
   Active: active (running) since Sat 2020-02-29 03:59:50 UTC; 16h ago
     Docs: man:systemd-resolved.service(8)
	   https://www.freedesktop.org/wiki/Software/systemd/resolved
	   https://www.freedesktop.org/wiki/Software/systemd/writing-network-configuration-managers
	   https://www.freedesktop.org/wiki/Software/systemd/writing-resolver-clients
 Main PID: 5850 (systemd-resolve)
   Status: "Processing requests..."
    Tasks: 1 (limit: 4963)
   Memory: 3.8M
   CGroup: /system.slice/systemd-resolved.service
	   └─5850 /usr/lib/systemd/systemd-resolved

Feb 29 20:07:46 oe2.dane.onl systemd-resolved[5850]: DNSSEC validation failed for question _443._tcp.strotmann.de IN TLSA: no-signature

5.2 Verwaltungswerkzeug "resolvectl"

  • Das Verwaltungs-Werkzeug für diesen Dienst heisst resolveclt (früher unter Fedora systemd-resolve)
  • wird der Befehl resolvectl ohne Parameter aufgerufen, so wird die aktuelle Konfiguration ausgegeben
# resolvectl
Global
       LLMNR setting: yes
MulticastDNS setting: yes
  DNSOverTLS setting: no
      DNSSEC setting: allow-downgrade
    DNSSEC supported: yes
  Current DNS Server: 127.0.0.1
	 DNS Servers: 127.0.0.1
	  DNSSEC NTA: 10.in-addr.arpa
		      16.172.in-addr.arpa
		      168.192.in-addr.arpa
		      17.172.in-addr.arpa
		      18.172.in-addr.arpa
		      19.172.in-addr.arpa
		      20.172.in-addr.arpa
		      21.172.in-addr.arpa
		      22.172.in-addr.arpa
		      23.172.in-addr.arpa
		      24.172.in-addr.arpa
		      25.172.in-addr.arpa
		      26.172.in-addr.arpa
		      27.172.in-addr.arpa
		      28.172.in-addr.arpa
		      29.172.in-addr.arpa
		      30.172.in-addr.arpa
		      31.172.in-addr.arpa
		      corp
		      d.f.ip6.arpa
		      home
		      internal
		      intranet
		      lan
		      local
		      private
		      test

Link 9 (ip_vti0)
      Current Scopes: none
       LLMNR setting: yes
MulticastDNS setting: no
  DNSOverTLS setting: no
      DNSSEC setting: allow-downgrade
    DNSSEC supported: yes

Link 8 (vethf3dcc34d)
      Current Scopes: LLMNR/IPv6
       LLMNR setting: yes
MulticastDNS setting: no
  DNSOverTLS setting: no
      DNSSEC setting: allow-downgrade
    DNSSEC supported: yes

Link 6 (veth9bc877c5)
      Current Scopes: LLMNR/IPv6
       LLMNR setting: yes
MulticastDNS setting: no
  DNSOverTLS setting: no
      DNSSEC setting: allow-downgrade
    DNSSEC supported: yes

Link 2 (eth0)
      Current Scopes: DNS LLMNR/IPv4 LLMNR/IPv6
       LLMNR setting: yes
MulticastDNS setting: no
  DNSOverTLS setting: no
      DNSSEC setting: allow-downgrade
    DNSSEC supported: yes
  Current DNS Server: 127.0.0.1
	 DNS Servers: 127.0.0.1
	  DNS Domain: ~.
  • Mit resolvectl können Namensauflösungen über alle unterstützten Protokolle ausgeführt werden
# resolvectl query linuxhotel.de
linuxhotel.de: 2001:aa8:fffe:4::1:11%eth0
	       217.69.87.63%eth0

-- Information acquired via protocol DNS in 31.7ms.
-- Data is authenticated: yes
  • Namensauflösung kann auf IPv4 Adressen beschränkt werden
# resolvectl -4 linuxhotel.de
linuxhotel.de: 217.69.87.63

-- Information acquired via protocol DNS in 84.6ms.
-- Data is authenticated: yes
  • und auch auf IPv6 Adressen
# resolvectl -6 linuxhotel.de
linuxhotel.de: 2001:aa8:fffe:4::1:11

-- Information acquired via protocol DNS in 26.9ms.
-- Data is authenticated: yes
  • Die Statistik gibt Information, wieviele Namensauflösungsanfragen bearbeitet wurden, und wieviel Antworten aus dem (lokalen) Cache kamen, und die Rate der DNSSEC validierten Antworten.
# resolvectl statistics
DNSSEC supported by current servers: yes

Transactions
Current Transactions: 0
  Total Transactions: 24

Cache
  Current Cache Size: 0
	  Cache Hits: 0
	Cache Misses: 12

DNSSEC Verdicts
	      Secure: 12
	    Insecure: 0
	       Bogus: 0
       Indeterminate: 0
  • resolvectl hilft bei der Abfrage von speziellen DNS-Daten, wie DANE TLSA-Records, hier für eine Webseite
# resolvectl tlsa fedoraproject.org
_443._tcp.fedoraproject.org IN TLSA 0 0 1 19400be5b7a31fb733917700789d2f0a2471c0c9d506c0e504c06c16d7cb17c0
	-- Cert. usage: CA constraint
	-- Selector: Full Certificate
	-- Matching type: SHA-256

-- Information acquired via protocol DNS in 152.2ms.
-- Data is authenticated: yes
  • ein DANE/TLSA Record für einen Mailserver
# resolvectl tlsa mail.strotmann.de:25
_25._tcp.mail.strotmann.de IN TLSA 3 1 1 713404932d32e8488c26acb3e7e03d67d3cd7e8cc5bee59d6c4a5ca8b4a2edd0
	-- Cert. usage: Domain-issued certificate
	-- Selector: SubjectPublicKeyInfo
	-- Matching type: SHA-256 # interface eth0

-- Information acquired via protocol DNS in 35.0ms.
-- Data is authenticated: yes
  • Abfragen eines PGP/GPG Schlüssel aus dem Internet-DNS
# resolvectl openpgp cs@sys4.de

5.3 Konfiguration

  • Die Konfiguration von systemd-resolved liegt unter /etc/systemd/resolved.conf. Die auskommentierten Werte sind die Standard-Werte.
[Resolve]
#DNS=
#FallbackDNS=
#Domains=
#LLMNR=yes
#MulticastDNS=yes
#DNSSEC=allow-downgrade
#DNSOverTLS=no
#Cache=yes
#DNSStubListener=udp
  • mit dem Befehl dig (aus dem Paket bind-utils) kann der Dienst direkt auf der Adresse 127.0.0.53 angefragt werden:
# dig @127.0.0.53 linuxhotel.de +dnssec +multi

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.el8 <<>> @127.0.0.53 linuxhotel.de +dnssec +multi
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 33479
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 65494
;; QUESTION SECTION:
;linuxhotel.de.         IN A

;; ANSWER SECTION:
linuxhotel.de.          3045 IN A 217.69.87.63

;; Query time: 2 msec
;; SERVER: 127.0.0.53#53(127.0.0.53)
;; WHEN: Sat Feb 29 20:14:04 UTC 2020
;; MSG SIZE  rcvd: 58

5.4 Auflösung auf systemd-resolved umschalten

  • soll die Namensauflösung über systemd-resolved durchgeführt werden, so wird die DNS-Konfiguration im NetworkManager angepasst
  • Netzwerkkonfigurationen des Netzwerkmanagers auflisten
# nmcli con show
NAME         UUID                                  TYPE      DEVICE
System eth0  5fb06bd0-0bb0-7ffb-45f1-d6edd65f3e03  ethernet  eth0
cni-podman0  9a94e636-33c3-49e7-bdc4-eea2c44fe2a2  bridge    cni-podman0
  • DNS Konfiguration manuell auf die Loopback-Adressen (Unbound DNS-Resolver) festlegen
# nmcli con mod "System eth0" ipv4.ignore-auto-dns yes
# nmcli con mod "System eth0" ipv6.ignore-auto-dns yes
# nmcli con mod "System eth0" ipv4.dns "127.0.0.53"
  • Networkmanager Konfiguration neu ausrollen
# nmcli con down "System eth0" && nmcli con up "System eth0"
  • prüfen, das die Konfiguration erfolgreich übernommen wurde
# cat /etc/resolv.conf
nameserver 127.0.0.53
  • systemd-resolved unterstützt opportunistisches DNS-over-TLS: unterstützt der eingestellte DNS-Server DNS-over-TLS wird dieses benutzt. Tritt ein Fehler bei der DNS-over-TLS Kommunikation auf, so schaltet systemd-resolved sofort und ohne Meldung an den Benutzer auf unverschlüsseltes DNS (UDP/TCP) um. In späteren Versionen von systemd-resolved soll ein strict Modus möglich sein.
  • der/die DNS-Server für eine Schnittstelle kann temporär per resolvectl umgeschaltet werden, hier auf einen DNS-over-TLS Server:
resolvectl dnsovertls eth0 opportunistic
resolvectl dns eth0 5.45.107.88  # doh.defaultroutes.de
  • Nach dem Umschalten auf DNS-over-TLS sollten TLS-verschlüsselte Verbindungen auf Port 853 sichtbar sein
tcpdump -i eth0 -v port 853
  • unverschlüsselte Kommunikation auf Port 53 (UDP/TCP) sollte nun nicht mehr möglich sein.
tcpdump -i eth0 -v port 53

5.5 Fehlersuche

  • Den Inhalt des systemd-resolved Cache in das Journal ausgeben (Achtung: dies können sehr viele Daten sein!)
pkill -USR1 resolve
journalctl -u systemd-resolved

5.6 Aufgabe:

  • schalte die DNS-Auflösung per NetworkManager auf systemd-resolved um
  • Konfiguriere die DNS-Server 46.182.19.48 bzw. 2a02:2970:1002::18 (Digitalcourage) in der resolved.conf als primäre DNS Server
  • Teste die Namensauflösung für einige Domains
  • Schalte DNSSEC-Validierung für systemd-resolved an, teste die Domains notes.defaultroutes.de, fail03.dnssec.works und dane.onl auf DNSSEC Validierung
  • Schalte DNS-over-TLS für die DNS-Server ein. Prüfe mit tcpdump das keine DNS-Abfragen über Port 53 UDP/TCP laufen

6 Systemweite Krypto-Richtlinie

Richtlinie Krypto-Algorithmen
LEGACY enhält auch alte, potentiell unsichere Algorithmen wie RC4, 3DES, DSA, TLS 1.0/1.1
DEFAULT TLS 1.2/1.3, IKEv2 und SSH2, RSA und DH Keys > 2047bits
FUTURE kein SHA1 in Signatur Algorithmen, RSA und DH Keys > 3071bits
FIPS Kompatibilität zur FIPS140-2 Richtlinie
  • Krypt-Algorithmen die nicht in Red Hat 8 verfügbar sind:
    • DES (seit RHEL-7)
    • alle "export" Cypher-Suites (seit RHEL-7)
    • MD5 in Signatures (seit RHEL-7)
    • SSLv2 (seit RHEL-7)
    • SSLv3 (seit RHEL-8)
    • Alle ECC Kurven unter 224 bits (seit RHEL-6)
    • Alle Binär-Feld ECC Kurven (seit RHEL-6)
  • Anwendungen, welche unter Verwaltung der RedHat Krypto-Richtlinien stehen:
    • GnuTLS library (GNU Software wie Emacs)
    • OpenSSL library (viele Server wie NGINX oder Apache)
    • NSS library (Firefox Browser und andere Web-Software)
    • OpenJDK (Java-Server)
    • Libkrb5 (kerberos)
    • BIND 9 (DNS-Server)
    • OpenSSH
    • Libreswan (IPSec)
    • libssh
  • Konfigurationsdatei /etc/crypto-policies/config
  • derzeitige Richtlinie anzeigen
# update-crypto-policies --show
  • neue Richtlinie setzen (danach ist ein Neustart/Reboot des Systems notwendig, um die neue Konfiguration zu aktivieren)
# update-crypto-policies --set FUTURE
Setting system policy to FUTURE
Note: System-wide crypto policies are applied on application start-up.
It is recommended to restart the system for the change of policies
to fully take place.

7 Systemd Storage

7.1 Systemd und /etc/fstab

  • in der Datei /etc/fstab sind neue Optionen für Systemd verfügbar. Die Optionen x-systemd.requires und x-systemd.requires-mounts-for definieren Abhängigkeiten für Mount-Definitionen. Dies kann für Netzwerklaufwerke, Network-Based-Disk-Encryption, Stratis und andere Systeme verwendet werden
//host/share    /net/share        cifs   noauto,nofail,x-systemd.automount,x-systemd.requires=network-online.target,x-systemd.device-timeout=10,workgroup=workgroup,credentials=/foo/credentials    0 0
  • die Option x-systemd.mount-timeout kann benutzt werden um ein Timeout auf eine Mount-Operation zu definieren
  • die Option x-systemd.device-bound kann benutzt werden um eine Mount-Operation an ein Gerät zu binden. So kann z.B. ein Dateisystem auf einer DVD/BlueRay/CD-ROM automatisch ausgehangen werden, wenn das Medium ausgeworfen wird
  • die Optionen x-systemd.after und x-systemd.before können benutzt werden um explizit eine Reihenfolge der Mount-Aktion mit Systemd-Diensten oder Systemd-Mounts zu definieren
  • die Option x-systemd.makefs bewirkt das die Partition immer vor dem Mouten mit einem neuen Dateisystem formatiert wird. Das Formatieren wird an eine Systemd-Unit systemd-makefs@.service delegiert.
  • die Option x-systemd.growfs bewirkt das vor dem Einhängen das Dateisyste auf die Grösse des darunterliegenden Storage vergrössert wird (wenn möglich). Das Vergrössern des Dateisystemd wird an eine Systemd-Unit systemd-growfs@.service delegiert.

7.2 Einhängepunkt /efi

  • ist der Einhängepunkt /efi vorhanden, so wird die EFI-Partition dort eingehangen (vorher /boot). Somit können die EFI-Daten besser von anderen Boot-Daten unter /boot getrennt verwaltet werden

7.3 Befehl systemd-mount

  • der neue Befehl systemd-mount funktioniert wie der raditionelle mount Befehl, beachtet aber weitere Abhängigkeiten. So kann systemd-mount sicherstellen, das vor dem Anhängen eines Wechseldatenträger ein Filesystemcheck ausgeführt wird
systemd-mount /dev/sda1 /mnt
  • über die Option --owner kann der Benutzeraccount und die Benutzergruppe für ein Mount festgelegt werden
  • der Subbefehl --list zeigt alle verfügbaren Mount-Geräte an:
# systemd-mount --list
NODE      PATH                   MODEL                   WWN                TYPE  LABEL                      UUID
/dev/dm-0 n/a                    n/a                     n/a                btrfs data                       c2e4db24-56ec-4de6-b5b7-aa19808bb8cf
/dev/sda1 pci-0000:00:1f.2-ata-1 Samsung_SSD_860_QVO_1TB 0x5002538e701bd174 vfat  EFI\x20System\x20Partition 0DD0-646B
/dev/sda2 pci-0000:00:1f.2-ata-1 Samsung_SSD_860_QVO_1TB 0x5002538e701bd174 ext4  n/a                        8ce223b7-7f02-4b03-8c0b-fd2ea2621adc
/dev/sda3 pci-0000:00:1f.2-ata-1 Samsung_SSD_860_QVO_1TB 0x5002538e701bd174 xfs   n/a                        fae4a7d8-f5e2-48dc-b889-e3a8e3a33bf5
  • der Befehl systemd-umount kann benutzt werden, um Dateisysteme mit Abhängigkeiten (stoppen von Diensten, welche auf das Dateisystem zugreifen) auszuhängen

8 Festplatten (Storage) Verwaltung mit Stratis und VDO

8.1 Stratis

8.1.1 Vorsicht!

  • Stratis XFS-Dateisysteme nicht manuell per XFS Befehle verwalten (z.B. nicht neu Formatieren, Grösse ändern etc)
  • LVM Schicht nicht manuell verändern
  • Stratis erkennt keine Fehler auf der unterliegenden Storage-Hardware!
  • Stratis hat keine Checksummen auf Daten oder Metadaten!

8.1.2 Installation und Benutzung von Stratis

  • Stratis Pakete installieren
dnf install stratisd stratis-cli
  • den Stratis-Dienst starten
systemctl enable --now stratisd
  • einen neuen Stratis-Pool erstellen. Ein Pool kann meherer Stratis-Dateisysteme (XFS) beinhalten. Diese Dateisysteme teilen sich den freien Speicher im Pool. Ein Pool online kann vergrössert oder verkleinert werden. Hier wird ein Pool mit dem Namen data über die physischen Laufwerke vdb und vdc erstellt:
stratis pool create  data /dev/vdb /dev/vdc
  • Auflisten der verfügbaren Stratis-Pools:
# stratis pool list
Name  Total Physical Size  Total Physical Used
data                2 GiB               56 MiB
  • erstellen von Dateisystmen in einem Stratis-Pool. Hier werden zwei neue Dateisysteme (photos und documents) erstellt:
stratis filesystem create data photos
stratis filesystem create data documents
  • über Stratis verwaltete Dateisysteme anzeigen
# stratis filesystem list
Pool Name  Name    Used     Created            Device                UUID
data       photos  546 MiB  Feb 24 2020 21:49  /stratis/data/photos  29c72cac1ce047ca8044e94a2644bc9e
data       movies  546 MiB  Feb 24 2020 21:49  /stratis/data/documents  04024d2432354f08be67644792504b56
  • mounten der Stratis-Datisysteme und füllen mit Testdaten
mkdir /photos
mount /stratis/data/photos /photos
find /usr -name '*.jpg' -exec cp "{}" /photos/ \;
mkdir /documents
mount /stratis/data/documents /documents
find /usr -name '*.pdf' -exec cp "{}" /documents/ \;
  • Es wird nun (wenig) mehr Platz in den Dateisystemen verbraucht
 stratis filesystem list
Pool Name  Name       Used     Created            Device                   UUID
data       photos     546 MiB  Feb 24 2020 21:49  /stratis/data/photos     29c72cac1ce047ca8044e94a2644bc9e
data       documents  547 MiB  Feb 24 2020 21:54  /stratis/data/documents  11381dc972ca4566a9159daced8b0106
  • der Ausgabe von df (und ähnlichen Tools) ist bei Volume-Managed Dateisystemen (auch bei BTRFS und ZFS) nicht zu trauen:
# df -Th
Filesystem                                                                                      Type      Size  Used Avail Use% Mounted on
devtmpfs                                                                                        devtmpfs  647M     0  647M   0% /dev
tmpfs                                                                                           tmpfs     663M     0  663M   0% /dev/shm
tmpfs                                                                                           tmpfs     663M  8.8M  654M   2% /run
tmpfs                                                                                           tmpfs     663M     0  663M   0% /sys/fs/cgroup
/dev/mapper/rhel-root                                                                           xfs        17G  2.0G   15G  12% /
/dev/vda1                                                                                       xfs      1014M  229M  786M  23% /boot
tmpfs                                                                                           tmpfs     133M     0  133M   0% /run/user/0
tmpfs                                                                                           tmpfs     133M     0  133M   0% /run/user/1000
/dev/mapper/stratis-1-d7d6df772d1a462e8789b102c4d29fb1-thin-fs-29c72cac1ce047ca8044e94a2644bc9e xfs       1.0T  7.2G 1017G   1% /photos
/dev/mapper/stratis-1-d7d6df772d1a462e8789b102c4d29fb1-thin-fs-11381dc972ca4566a9159daced8b0106 xfs       1.0T  7.2G 1017G   1% /documents
  • einen neuen Snapshot (Clone) des Dateisystems photos unter dem neuen Namen backup erstellen
stratis filesystem snapshot data photos backup
  • es ist ein neues Dateisystem entstanden
# stratis filesystem list
Pool Name  Name       Used     Created            Device                   UUID
data       photos     546 MiB  Feb 24 2020 21:49  /stratis/data/photos     29c72cac1ce047ca8044e94a2644bc9e
data       documents  547 MiB  Feb 24 2020 21:54  /stratis/data/documents  11381dc972ca4566a9159daced8b0106
data       backup     546 MiB  Feb 24 2020 22:00  /stratis/data/backup     1f843ef9f5ad4943979fa06689edaeb0
  • lsblk zeigt die (low-level) Device-Mapper Struktur der Stratis Dateisysteme an. Stratis Dateisysteme und Pools sollten nicht mit den Low-Level Werkzeugen bearbeitet werden
# lsblk
NAME                                                                   MAJ:MIN RM  SIZE RO TYPE    MOUNTPOINT
sr0                                                                     11:0    1 1024M  0 rom
vda                                                                    252:0    0   20G  0 disk
├─vda1                                                                 252:1    0    1G  0 part    /boot
└─vda2                                                                 252:2    0   19G  0 part
  ├─rhel-root                                                          253:0    0   17G  0 lvm     /
  └─rhel-swap                                                          253:1    0    2G  0 lvm     [SWAP]
vdb                                                                    252:16   0    1G  0 disk
└─stratis-1-private-d7d6df772d1a462e8789b102c4d29fb1-physical-originsub
								       253:2    0    2G  0 stratis
  ├─stratis-1-private-d7d6df772d1a462e8789b102c4d29fb1-flex-thinmeta   253:3    0   16M  0 stratis
  │ └─stratis-1-private-d7d6df772d1a462e8789b102c4d29fb1-thinpool-pool 253:6    0    2G  0 stratis
  │   ├─stratis-1-d7d6df772d1a462e8789b102c4d29fb1-thin-fs-29c72cac1ce047ca8044e94a2644bc9e
  │   │                                                                253:7    0    1T  0 stratis /photos
  │   ├─stratis-1-d7d6df772d1a462e8789b102c4d29fb1-thin-fs-1f843ef9f5ad4943979fa06689edaeb0
  │   │                                                                253:8    0    1T  0 stratis
  │   └─stratis-1-d7d6df772d1a462e8789b102c4d29fb1-thin-fs-11381dc972ca4566a9159daced8b0106
  │                                                                    253:9    0    1T  0 stratis /documents
  ├─stratis-1-private-d7d6df772d1a462e8789b102c4d29fb1-flex-thindata   253:4    0    2G  0 stratis
  │ └─stratis-1-private-d7d6df772d1a462e8789b102c4d29fb1-thinpool-pool 253:6    0    2G  0 stratis
  │   ├─stratis-1-d7d6df772d1a462e8789b102c4d29fb1-thin-fs-29c72cac1ce047ca8044e94a2644bc9e
  │   │                                                                253:7    0    1T  0 stratis /photos
  │   ├─stratis-1-d7d6df772d1a462e8789b102c4d29fb1-thin-fs-1f843ef9f5ad4943979fa06689edaeb0
  │   │                                                                253:8    0    1T  0 stratis
  │   └─stratis-1-d7d6df772d1a462e8789b102c4d29fb1-thin-fs-11381dc972ca4566a9159daced8b0106
  │                                                                    253:9    0    1T  0 stratis /documents
  └─stratis-1-private-d7d6df772d1a462e8789b102c4d29fb1-flex-mdv        253:5    0   16M  0 stratis
vdc                                                                    252:32   0    1G  0 disk
└─stratis-1-private-d7d6df772d1a462e8789b102c4d29fb1-physical-originsub
								       253:2    0    2G  0 stratis
  ├─stratis-1-private-d7d6df772d1a462e8789b102c4d29fb1-flex-thinmeta   253:3    0   16M  0 stratis
  │ └─stratis-1-private-d7d6df772d1a462e8789b102c4d29fb1-thinpool-pool 253:6    0    2G  0 stratis
  │   ├─stratis-1-d7d6df772d1a462e8789b102c4d29fb1-thin-fs-29c72cac1ce047ca8044e94a2644bc9e
  │   │                                                                253:7    0    1T  0 stratis /photos  │   ├─stratis-1-d7d6df772d1a462e8789b102c4d29fb1-thin-fs-1f843ef9f5ad4943979fa06689edaeb0
  │   │                                                                253:8    0    1T  0 stratis
  │   └─stratis-1-d7d6df772d1a462e8789b102c4d29fb1-thin-fs-11381dc972ca4566a9159daced8b0106
  │                                                                    253:9    0    1T  0 stratis /documents
  ├─stratis-1-private-d7d6df772d1a462e8789b102c4d29fb1-flex-thindata   253:4    0    2G  0 stratis
  │ └─stratis-1-private-d7d6df772d1a462e8789b102c4d29fb1-thinpool-pool 253:6    0    2G  0 stratis
  │   ├─stratis-1-d7d6df772d1a462e8789b102c4d29fb1-thin-fs-29c72cac1ce047ca8044e94a2644bc9e
  │   │                                                                253:7    0    1T  0 stratis /photos
  │   ├─stratis-1-d7d6df772d1a462e8789b102c4d29fb1-thin-fs-1f843ef9f5ad4943979fa06689edaeb0
  │   │                                                                253:8    0    1T  0 stratis
  │   └─stratis-1-d7d6df772d1a462e8789b102c4d29fb1-thin-fs-11381dc972ca4566a9159daced8b0106
  │                                                                    253:9    0    1T  0 stratis /documents
  └─stratis-1-private-d7d6df772d1a462e8789b102c4d29fb1-flex-mdv        253:5    0   16M  0 stratis
vdd                                                                    252:48   0    1G  0 disk
  • ein neues physisches Medium dem Pool data hinzufügen
stratis pool add-data data /dev/vdd
  • Der Pool (und damit alle Dateisysteme im Pool) haben nun mehr Speicher zur Verfügung. Von der Verfügbarkeit ist ein Stratis-Pool über mehrere Platten wie ein RAID-0 (Striping) zu behandeln: wird eines zum Pool gehörenden Laufwerke defekt, so sind u.U. die gesamten Daten des Pool nicht mehr im Zugriff und verloren!
# stratis pool list
Name  Total Physical Size  Total Physical Used
data                3 GiB             1.66 GiB
  • werden Stratis-Laufwerke über die Datei /etc/fstab in das System eingebunden, so muss vorher der stratis Dienst gestartet worden sein. In der fstab kann dies über die Option x-systemd.requires=stratisd.service geschehen. Die UUID eines Stratis Dateisystems über die Befehle blkid ermitteln.
UUID=a1f0b64a-4ebb-4d4e-9543-b1d79f600283 /fs1 xfs defaults,x-systemd.requires=stratisd.service 0 0
  • Stratis-Befehle um die Bestandteile eines Stratis-Pools und -Dateisystems anzuzeigen
stratis blockdev
stratis pool
stratis filesystem

8.2 VDO - Virtual Data Optimizer

  • VDO bietet Komprimierung, Thin-Provisioning und De-Duplication
  • VDO kann zusammen mit LVM verwendet werden
  • Einsatzgebiete:
    • VDO und Virtualisierung/Container
    • VDO und Netzwerklaufwerke
    • VDO und Verschlüsselung (erst Verschlüsselung, dann VDO)
  • Kein Stratis auf VDO! (Thin auf Thin)
  • Hauptspeicher: 1 GB Basis für VDO, dann 1 GB pro 1 TB Storage deduplication
  • max 256TB Storage per VDO Volume
  • Platzverbrauch auf VDO Volume für Deduplication Index (0.1% - 25%)

8.2.2 VDO einrichten

  • Kernel-Modul und VDO Userland-Programme installieren
dnf install vdo kmod-kvdo
  • VDO ist ein Kernel-Modul un benötigt keinen Diest im Hintergrund
  • ein VDO Volume erstellen
# vdo create --name vdo-test --device=/dev/vde --vdoLogicalSize=100G
Creating VDO vdo-test
Starting VDO vdo-test
Starting compression on VDO vdo-test
VDO instance 0 volume is ready at /dev/mapper/vdo-test
  • VDO Volume mit XFS formatieren
# mkfs.xfs /dev/mapper/vdo-test
meta-data=/dev/mapper/vdo-test   isize=512    agcount=4, agsize=6553600 blks
	 =                       sectsz=4096  attr=2, projid32bit=1
	 =                       crc=1        finobt=1, sparse=1, rmapbt=0
	 =                       reflink=1
data     =                       bsize=4096   blocks=26214400, imaxpct=25
	 =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=12800, version=2
	 =                       sectsz=4096  sunit=1 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
  • das neue Dateisystem mounten. Auch bei VDO können wir den Angaben von df (und ähnlichen Befehlen und Programmen) nicht trauen
# mount /dev/mapper/vdo-test /mnt
# df -Th /mnt
Filesystem           Type  Size  Used Avail Use% Mounted on
/dev/mapper/vdo-test xfs   100G  747M  100G   1% /mnt

8.2.3 Aufgabe

9 Festplattenverschlüsselung mit LUKS2 und Network-Bound Disk Encryption (NBDE)

  • Network-Bound-Disk-Encryption (NBDE) ermöglicht eine Plattenverschlüsselung, bei der das Passwort/der Schlüssel zum Freischalten des Verschlüsselung über das Netzwerk übermittelt wird. Damit sind unbeaufsichtigte Reboots von Servern mit verschlüsselten Platten im Rechenzentrum möglich
  • NBDE besteht aus zwei Komponenten
    • TANG - die Server Komponente. Ein TANG Server kann Schlüssel für mehrere NBDE-Clients bereitstellen
    • CLEVIS - die Client Komponente. ClEVIS empfängt den Schlüssel vom TANG-Server und leitet diesen an LUKS (LUKS = Linux Unified Key Setup) weiter

9.2 NBDE (TANG) Server

  • die KVM VM klonen und auf dem Klon den TANG Server installieren
  • TANG Pakete installieren
dnf install tang policycoreutils-python-utils
  • TANG Socket-Unit aktivieren und den Socket in der Konfiguration anpassen
systemctl enable tangd.socket
systemctl edit tangd.socket
  • Wir möchten das unser TANG-Server auf Port 7500 horcht
[Socket]
ListenStream=
ListenStream=7500
  • Port 7500 im SELinux und in der Firewall freischalten
semanage port -a -t tangd_port_t -p tcp 7500
firewall-cmd --zone=public --add-port=7500/tcp --permanent
firewall-cmd --reload
  • Systemd-Konfigurationsänderungen laden und den TANG-Socket auf Port 7500 starten
systemctl daemon-reload
systemctl show tangd.socket -p Listen
systemctl start tangd.socket
  • die TANG Schlüssel werden automatisch beim ersten Start erstellt und liegen unter /var/db/tang
ls -l /var/db/tang/
  • Hashes der aktuellen Schlüssel des TANG-Servers anzeigen
# tang-show-keys 7500
McocO98JWjCSm7trnHKSCW6M9MQ
Xx6Fb3Jpg8Y9YV6hzkl5CrIxjc0
  • falls notwendig (z.B. für einen Key-Rollover), können neue Schlüssel auf dem TANG Server erstellt werden
/usr/libexec/tangd-keygen /var/db/tang

9.3 NBDE (CLEVIS) Client

  • wir arbeiten auf der anderen VM. Dieser VM vier Megabyte Hauptspeicher geben.
  • die Pakete für CLEVIS installieren
# dnf install clevis-luks clevis-dracut clevis
  • Partition für die Verschlüsselung vorbereiten
[root@redhat8 cas]# parted /dev/vde
GNU Parted 3.2
Using /dev/vde
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) p
Error: /dev/vdd: unrecognised disk label
Model: Virtio Block Device (virtblk)
Disk /dev/vde: 1074MB
Sector size (logical/physical): 512B/512B
Partition Table: unknown
Disk Flags:
(parted) mklabel gpt
(parted) mkpart
Partition name?  []? LUKS2
File system type?  [ext2]? XFS
Start? 4M
End? 100%
(parted) q
Information: You may need to update /etc/fstab.
  • Verschlüsselung auf dem Laufwerk vde1 initialisieren. Das Laufwerk ist noch nicht voll-verschlüsselt, die Verschlüsselung ist vorbereitet. Wir können später das Laufwerk schon produktiv nutzen während die Verschlüsselung abgeschlossen wird. Dieser Prozess braucht Zufallszahlen, welche in einer VM möglicherweise nicht in ausreichender Menge vorhanden sind. Die Installation des Entropie-Gatherin-Daemon haveged (aus den EPEL Repositories) in der VM kann helfen
# dnf install epel-release
# dnf install haveged
# systemctl enable --now haveged
# cryptsetup reencrypt --encrypt --init-only --reduce-device-size 32M /dev/vde1

WARNING!
========
This will overwrite data on LUKS2-temp-4c8e4a91-2e8b-4fb8-8a9c-271331c3405f.new irrevocably.

Are you sure? (Type uppercase yes): YES
Enter passphrase for LUKS2-temp-4c8e4a91-2e8b-4fb8-8a9c-271331c3405f.new:
Verify passphrase:
  • Verschlüsselte Partition freischalten
# cryptsetup open /dev/vde1 vde1_encrypted
Enter passphrase for /dev/vde1:
  • mit einem XFS-Dateisystem versehen und einhängen
# mkfs.xfs /dev/mapper/vde1_encrypted
# mkdir -p /mnt/vde1_encrypted
# mount /dev/mapper/vde1_encrypted /mnt/vde1_encrypted
  • Verschlüsselung vorsetzen. Das Laufwerk kann währenddessen benutzt werden
# cryptsetup reencrypt --resume-only /dev/vde1
  • Block-Geräte Ansicht des verschlüsselten Laufwerks
# lsblk
NAME               MAJ:MIN RM  SIZE RO TYPE  MOUNTPOINT
sr0                 11:0    1 1024M  0 rom
vda                252:0    0   20G  0 disk
|-vda1             252:1    0    1G  0 part  /boot
`-vda2             252:2    0   19G  0 part
  |-rhel-root      253:0    0   17G  0 lvm   /
  `-rhel-swap      253:1    0    2G  0 lvm   [SWAP]
vdb                252:16   0    1G  0 disk
vdc                252:32   0    1G  0 disk
vdd                252:64   0   20G  0 disk
vde                252:48   0    1G  0 disk
`-vde1             252:49   0 1019M  0 part
  `-vde1_encrypted 253:3    0  987M  0 crypt /mnt/vdd1_encrypted
`-vdo-test         253:2    0  100G  0 vdo
  • das kleine Kommandozeilenprogramm jq (JSON Query) hilft bei der Anzeige der Schlüssel des TANG-Servers (nützlich bei der Fehlersuche). Wir fragen per HTTP-Protokoll die Schlüssel und Signaturen des TANG-Servers ab
# dnf -y install jq
# curl --silent http://<IP-des-TANG-Servers>:7500/adv/ | jq
{
  "payload": "eyJrZXlzIjpbeyJhbGciOiJFQ01SIiwiY3J2IjoiUC01MjEiLCJrZXlfb3BzIjpbImRlcml2ZUtleSJdLCJrdHkiOiJFQyIsIngiOiJBRDlZLVNfY2NFTlNJQ2VIMDRxQUwydUpMVE9CTXNQemhVSUpQQlRYQUlBMHlVWWtKQUtMWjQtM0NmbGVuTVVXQ2hzMGFkakhEV0Znbzc0WHphaFZ0bk41IiwieSI6IkFmWlJTeFVTN05XUUZGTmRQSzRkQXpDbFhlVEpGY1RWYkNyZG1pd2pzQWFqVk1KcHVaUDNqN210QlBUQVFCUW1weGs0aGJpaWtON09RX1I0NDlfWWpXeFUifSx7ImFsZyI6IkVDTVIiLCJjcnYiOiJQLTUyMSIsImtleV9vcHMiOlsiZGVyaXZlS2V5Il0sImt0eSI6IkVDIiwieCI6IkFCd3BFbEQwVkhOYVJIVjdIcFpGVzFPZkJsUnlzYVY2Q3JkZnBiYVdlMlNHaUgzalQ2OFhYLUM0eFF2RHZlMUhaa25uWkpZZlVXQ21RSGN3UkJEclNBTjkiLCJ5IjoiQUhTYlBUYnA3Q1AxRUpmOFp2MlNGZ09tTmF5SmNQN1pRMW1BV3RKWnNESXl3MUxxM0NmZk1TXzJiVWZnY3hsN19GekFsb3VZMTBqUmFKTU9zdGpnazJyZiJ9LHsiYWxnIjoiRVM1MTIiLCJjcnYiOiJQLTUyMSIsImtleV9vcHMiOlsidmVyaWZ5Il0sImt0eSI6IkVDIiwieCI6IkFPeWliZ1ozc2VUT3BDSkU0VDBMeXZwOU5EZWlBaWdtRmpCejNzRjBEZnJURHpiWUlnZHVfZFcxTy1NaDVETlFUVGlFMml3UU5yVWFiT1hZR1RNVVhBc2siLCJ5IjoiQVlURmR4M1EzeWc5ZEtWc0d5dkRhcXFlTmxFQXJiQTBhRnRpYVpkaHdIdmdBbzRtb2NGa0VGTnBlT2twSGR3OU9zaXhhMVAyZkxuVmpnaVJac2NiR3lfNyJ9LHsiYWxnIjoiRVM1MTIiLCJjcnYiOiJQLTUyMSIsImtleV9vcHMiOlsidmVyaWZ5Il0sImt0eSI6IkVDIiwieCI6IkFhNlUwZU1yXzNBRGR6aTlESmVTaDNSdEhpV3YtaTRuU2s3ZXo3ZXFQMkFLWVI5VW42WDMyeUhvMktTNy00LV8zZlVydC04T2g5WFlEam1YTjFBdE1YdWciLCJ5IjoiQVhpOTA0S0VqLUNFSjRvOWdHM0hpS1pfVm5uazJmQVpYMFBSMWhDMC1IbWs2MnJLOERyQ1daZi1tUVRSa0cyWWdrNWh1ZXUzaE90ZHI0bUREUHFVcXloXyJ9XX0",
  "signatures": [
    {
      "protected": "eyJhbGciOiJFUzUxMiIsImN0eSI6Imp3ay1zZXQranNvbiJ9",
      "signature": "AShqBVyGOKewGvGV2KCPGTn1XZTbNTiH7g6y_kNri5inq067ol8CQ4uWIcPmyYziL1RDeAh5Iq_zpn4QXoZYTI-9AR43Qegnqoc5fl5G58SCj88833MvpiQ6jYkmyFN4rpROkv5OHnfUwPKm5zEuciZM1XaGTuAAIW0RSBtUyTUychvz"
    },
    {
      "protected": "eyJhbGciOiJFUzUxMiIsImN0eSI6Imp3ay1zZXQranNvbiJ9",
      "signature": "APuddB0W1vWIh_RrTi3ohojj9NOKuAC8NUlqCQH5YNfwvWEAEzlL7pWAySmNgpnLSjisBrIlRwt8XqzfTKnRlinxAI-gqLEcZ1lAiysHxbsbDo6jIDEK09hMGw4O7USDRcYrRFteW2rTwr7e6b-qXC1kRT9q3KKjmvFw1JWRsUppoWWL"
    }
  ]
}
  • nun binden wir die LUKS Verschlüsselung an den TANG-Server. Dabei wird der TANG-Schlüssel als weiterer Schlüssel dem verschlüsseltm Laufwerk hinzugefügt. Das Laufwerk lässt sich ohne Netzwerk noch mit der manuell vergebenen Passphrase entschlüsseln
# clevis luks bind -d /dev/vde1 tang '{"url":"http://<rechnername-oder-ip-des-tang-servers>:7500"}'
The advertisement contains the following signing keys:

McocO98JWjCSm7trnHKSCW6M9MQ
Xx6Fb3Jpg8Y9YV6hzkl5CrIxjc0

Do you wish to trust these keys? [ynYN] y
Enter existing LUKS password: XXXXXXXXXXX

Die Konfiguration des LUKS Volumes ausgaben

cryptsetup luksDump /dev/vde1
  • Die clevis-luks-askpass Path-Aktivierungs-Unit aktivieren. Diese Path-Unit überwacht Passwort-Anfragen beim Systemstart und leitet diese an den TANG-Server weiter
systemctl enable clevis-luks-askpass.path
  • Eintragen des verschlüsselten Volumes in die Datei /etc/crypttab. Wichtig ist hierbei die Option _netdev die dafür sorgt, das dieses Laufwerk erst eingebunden wird, wenn das Netzwerk verfügbar ist
# echo "vde1_encrypted   /dev/vde1 none _netdev" >> /etc/crypttab
  • Eintragen des Dateisystems in die /etc/fstab, auch hier wird die Option _netdev angegeben
echo "/dev/mapper/vde1_encrypted  /mnt/vde1_encrypted     xfs   _netdev  0 0" >> /etc/fstab
  • wir die Root-Partition des Linux verschlüsselt, so muss per dracut die INIT-Ramdisk des Linux-Systems neu erstellt werden, um sicherzustellen das die CLEVIS Komponenten schon beim Systemstart verfügbar sind
# dracut -fv --regenerate-all

9.4 Test

  • auf dem TANG-Server auf Port 7500 den Netzverkehr überwachen
# dnf -y install tcpdump
# tcpdump -v port 7500
  • den NBDE Client neu booten, das verschlüsselte Laufwerk sollte automatisch eingehangen werden

9.5 TANG High Availability

  • DNS Round-Robin (Achtung: funktioniert ggf. bei Maschinen mit IPv6 Stack nicht!)
  • TCP-Load-Balancer (HAProxy, relayd)
  • Clevis-Client an mehrere Tang-Server anmelden

10 eBPF/BCC

  • eBPF ist die extended Berkeley Packet Filter Virtuelle Maschine im Linux Kernel
  • BCC ist die BPF Compiler Collection, eine Sammlung von Tools und eBPF Programmen

10.1 BCC Übersicht

bcc_tracing_tools_2016-768x538.png

# dnf install bcc bcc-tools python3-bcc
  • die BCC Tools sind unter /usr/share/bcc/tools/ installiert, die meisten Tools sind per man Page dokumentiert (Name bcc-<tool>). Das Blog und das Buch von Brendan Gregg liefert weitere Informationen (siehe Referenzen).
ls -l /usr/share/bcc/tools/

10.2 BCC Tools

10.2.1 Netzwerk

  • tcplife - TCP Verbindungen mit PID, Prozessname, Quell- und Zieladressen, Ports, Bandbreite und Dauer
# ./tcplife
PID   COMM       LADDR           LPORT RADDR           RPORT TX_KB RX_KB MS
19338 dnf        2a01:4f8:c0c:7c3c::1 38048 2a05:d012:8b5:6503:9efb:5cad:348f:e826 80        0     0 34.30
19338 dnf        2a01:4f8:c0c:7c3c::1 58912 2a02:2e0:414:102:d::54 80        0   735 88.89
19653 wget       2a01:4f8:c0c:7c3c::1 39286 2001:aa8:fffe:4::1:11 443       0     5 18.92
19653 wget       2a01:4f8:c0c:7c3c::1 58746 2001:aa8:fffe:4::1:11 80        0     0 114.79
  • tcpaccept - ankommende TCP Verbindungen mit Prozessname und PID
# ./tcpaccept
PID    COMM         IP RADDR            LADDR            LPORT
0      swapper/0    6  ::               ::               9090
0      swapper/0    6  2a01:4f8:c0c:7c3c::1 2001:db8::1  9090
23620  pool         6  2a01:4f8:c0c:7c3c::1 2001:db8::1  9090
23614  cockpit-ws   6  2a01:4f8:c0c:7c3c::1 2001:db8::1  9090
0      swapper/0    6  2a01:4f8:c0c:7c3c::1 2001:db8::1  9090
  • tcpconnect - ausgehende TCP Verbindungen
# ./tcpconnect
PID    COMM         IP SADDR            DADDR            DPORT
23648  wget         6  2a01:4f8:c0c:7c3c::1 2a02:2e0:3fe:1001:302:: 80
23648  wget         6  2a01:4f8:c0c:7c3c::1 2a02:2e0:3fe:1001:7777:772e:2:85 443
[...]
  • tcpconnlat latenz von TCP Verbindungen
# ./tcpconnlat
PID    COMM         IP SADDR            DADDR            DPORT LAT(ms)
23658  wget         4  94.130.27.184    183.79.135.206   80    273.08
23658  wget         4  94.130.27.184    183.79.250.123   443   258.22
23659  wget         6  2a01:4f8:c0c:7c3c::1 2001:4998:c:1023::5 80    152.97
23659  wget         6  2a01:4f8:c0c:7c3c::1 2001:4998:c:1023::5 443   154.01
23659  wget         6  2a01:4f8:c0c:7c3c::1 2a00:1288:110:1c::3 443   39.31
23659  wget         6  2a01:4f8:c0c:7c3c::1 2a00:1288:110:1c::4 443   40.87
  • tcpdrop - Anzeige welche TCP Pakete/Segmente im Kernel verworfen werden (z.B. bei hoher Last)
  • tcpretrans - Zeigt TCP retransmissions
# ./tcpretrans
Tracing retransmits ... Hit Ctrl-C to end
TIME     PID    IP LADDR:LPORT          T> RADDR:RPORT          STATE
19:48:54 0      4  94.130.27.184:42852  R> 1.2.3.4:666          SYN_SENT
19:48:56 0      4  94.130.27.184:42852  R> 1.2.3.4:666          SYN_SENT
19:49:00 0      4  94.130.27.184:42852  R> 1.2.3.4:666          SYN_SENT
  • tcptop - TOP ähnliche Anzeige der TCP Verbindungen
19:52:32 loadavg: 0.21 0.10 0.10 3/118 24164


PID    COMM         LADDR6                           RADDR6                            RX_KB  TX_KB
24155  24155        2a01:4f8:c0c:7c3c::1:42382       2003:d1:3012::400:80                  1      0
3077   sshd         2a01:4f8:c0c:7c3c::1:65020       2a0f:6480:1:6:d1fe:9d10:62e7:6fe:55250      0      1
24155  24155        2a01:4f8:c0c:7c3c::1:38174       2a05:d012:8b5:6503:9efb:5cad:348f:e826:80      0      0
  • tcptracer - Trace von TCP Verbindungen
# ./tcptracer
Tracing TCP established connections. Ctrl-C to end.
T  PID    COMM             IP SADDR            DADDR            SPORT  DPORT
C  24196  dnf              4  94.130.27.184    85.236.43.108    52330  80
X  24196  dnf              4  94.130.27.184    85.236.43.108    52330  80
C  24196  dnf              4  94.130.27.184    212.224.83.174   48074  80
X  24196  dnf              4  94.130.27.184    212.224.83.174   48074  80
C  24196  dnf              4  94.130.27.184    67.219.148.138   35958  80
X  24196  dnf              4  94.130.27.184    67.219.148.138   35958  80
C  24196  dnf              4  94.130.27.184    185.41.106.155   43112  80
X  24196  dnf              4  94.130.27.184    185.41.106.155   43112  80
C  24196  dnf              4  94.130.27.184    35.180.43.213    48822  80
X  24196  dnf              4  94.130.27.184    35.180.43.213    48822  80
C  24196  dnf              4  94.130.27.184    217.243.224.144  34754  80
X  24196  dnf              4  94.130.27.184    217.243.224.144  34754  80
  • tcpstates - Zeigt die TCP States von Verbindungen
# ./tcpstates
SKADDR           C-PID C-COMM     LADDR           LPORT RADDR           RPORT OLDSTATE    -> NEWSTATE    MS
ffff9462b688df00 24206 dnf        94.130.27.184   0     147.75.83.237   80    CLOSE       -> SYN_SENT    0.000
ffff9462b688df00 0     swapper/0  94.130.27.184   0     147.75.83.237   80    SYN_SENT    -> ESTABLISHED 9.697
ffff9462b688df00 24206 dnf        94.130.27.184   0     147.75.83.237   80    ESTABLISHED -> FIN_WAIT1   28.749
ffff9462b688df00 24206 dnf        94.130.27.184   0     147.75.83.237   80    FIN_WAIT1   -> FIN_WAIT2   9.674
ffff9462b688df00 24206 dnf        94.130.27.184   0     147.75.83.237   80    FIN_WAIT2   -> CLOSE       0.026
ffff9462b688df00 24206 dnf        94.130.27.184   0     212.224.83.174  80    CLOSE       -> SYN_SENT    22.563
ffff9462b688df00 0     swapper/0  94.130.27.184   0     212.224.83.174  80    SYN_SENT    -> ESTABLISHED 3.928
ffff9462b688df00 24206 dnf        94.130.27.184   0     212.224.83.174  80    ESTABLISHED -> FIN_WAIT1   4.946
ffff9462b688df00 24206 dnf        94.130.27.184   0     212.224.83.174  80    FIN_WAIT1   -> FIN_WAIT2   3.746
ffff9462b688df00 24206 dnf        94.130.27.184   0     212.224.83.174  80    FIN_WAIT2   -> CLOSE       0.021
  • tcpsubnet - TCP Verbindungen per Subnet
# ./tcpsubnet -i 5 212.224.83.0/24
Tracing... Output every 5 secs. Hit Ctrl-C to end
[03/02/20 19:59:13]
212.224.83.0/24          179
[03/02/20 19:59:18]
[03/02/20 19:59:23]
[03/02/20 19:59:28]
212.224.83.0/24          179
[03/02/20 19:59:33]
212.224.83.0/24         2064
  • gethostlatency - Latenz der Namensauflösung
# ./gethostlatency
TIME      PID    COMM                  LATms HOST
20:16:28  24993  ping                   1.99 heise.de
20:16:37  24994  telnet                 1.81 strotmann.de
20:16:44  24995  telnet                12.13 mail.strotmann.de
20:16:56  24996  telnet               770.77 yahoo.co.kr
20:17:04  24997  telnet                 1.29 yahoo.co.kr

  • sslsniff - sniffing von TLS/SSL Verschlüsselten Daten (im Klartext)
# ./sslsniff
FUNC         TIME(s)            COMM             PID    LEN
WRITE/SEND   0.000000000        wget             25733  134
----- DATA -----
GET / HTTP/1.1
User-Agent: Wget/1.19.5 (linux-gnu)
Accept: */*
Accept-Encoding: identity
Host: foo.bar.de
Connection: Keep-Alive


----- END DATA -----

10.2.2 Dateisysstem

  • cachetop - Dateisystem Cache Effizienz
20:56:51 Buffers MB: 66 / Cached MB: 1245 / Sort: HITS / Order: ascending                                                              
PID      UID      CMD              HITS     MISSES   DIRTIES  READ_HIT%  WRITE_HIT%                                                    
   25800 root     cachetop                1        0        0     100.0%       0.0%                                                    
     433 root     jbd2/sda1-8            12       12       10       8.3%       8.3%                                                    
    3102 root     tmux: server           26        0        0     100.0%       0.0%                                                    
   25818 root     groff                 135        0        0     100.0%       0.0%                                                    
   25819 root     groff                 135        0        0     100.0%       0.0%                                                    
   25802 root     bash                  144        0        0     100.0%       0.0%                                                    
   25808 root     man                   149        0        0     100.0%       0.0%                                                    
   25809 root     man                   149        0        0     100.0%       0.0%                                                    
   25820 root     bash                  149        0        0     100.0%       0.0%                                                    
   25810 root     man                   154        0        0     100.0%       0.0%                                                    
   25812 root     man                   181        0        0     100.0%       0.0%                                                    
   25816 root     nroff                 199        0        0     100.0%       0.0%                                                    

  • fileslower - langsame Dateisystem Lese-/Schreib-Operationen
# ./fileslower
Tracing sync read/writes slower than 10 ms
TIME(s)  COMM           TID    D BYTES   LAT(ms) FILENAME
16.561   grep           24679  R 32768     10.46 COPYING.UCB
17.285   grep           24679  R 32768     10.96 resizepart.8.gz
17.584   grep           24679  R 32768     12.85 uptime.1.gz
18.763   grep           24679  R 2191360   12.27 mountpoint
  • filetop - die Dateien mit den häufigsten Zugriffen nach Dateiname und Prozess
0:05:23 loadavg: 0.22 0.15 0.10 2/115 24743

TID    COMM             READS  WRITES R_Kb    W_Kb    T FILE
24734  dnf              2223   0      8930    0       R history.sqlite-wal
24734  dnf              1149   0      7413    0       R AppStream-filenames.solvx
24734  dnf              439    0      3258    0       R BaseOS-filenames.solvx
24734  dnf              1342   0      2684    0       R efbf08031c19c7b017f847e41703b...
24734  dnf              293    0      1703    0       R AppStream.solv
24734  dnf              177    0      1429    0       R BaseOS.solv
24734  dnf              174    171    680     684     R packages.db
  • biotop - Block Device IO nach Prozesen und Block-Device
20:07:59 loadavg: 0.48 0.20 0.12 4/118 24798

PID    COMM             D MAJ MIN DISK       I/O  Kbytes  AVGms
24782  dnf              W 8   0   sda         57  1700.0   0.72
433    jbd2/sda1-8      W 8   0   sda          2   104.0   0.19
0                       R 0   0   ?            2 0.015625   8.68
  • biolatency - Histogram der Zugriffsgeschwindigkeiten (Latenz) auf Block-Devices
# ./biolatency
Tracing block device I/O... Hit Ctrl-C to end.
^C
     usecs               : count     distribution
	 0 -> 1          : 0        |                                        |
	 2 -> 3          : 0        |                                        |
	 4 -> 7          : 0        |                                        |
	 8 -> 15         : 0        |                                        |
	16 -> 31         : 0        |                                        |
	32 -> 63         : 0        |                                        |
	64 -> 127        : 164      |                                        |
       128 -> 255        : 10167    |***********************************     |
       256 -> 511        : 11385    |****************************************|
       512 -> 1023       : 1906     |******                                  |
      1024 -> 2047       : 889      |***                                     |
      2048 -> 4095       : 404      |*                                       |
      4096 -> 8191       : 34       |                                        |
      8192 -> 16383      : 16       |                                        |
     16384 -> 32767      : 1        |                                        |
  • biosnoop - Block-IO Zugriffe protokollieren
# ./biosnoop
TIME(s)        COMM           PID    DISK    T  SECTOR    BYTES   LAT(ms)
0.000000000    ?              0              R  -1        8          0.68
2.053140000    ?              0              R  -1        8          5.90
3.038143000    NetworkManager 748    sda     R  4196368   4096       0.47
3.038876000    NetworkManager 748    sda     W  4782048   4096       0.38
3.039616000    jbd2/sda1-8    433    sda     W  3211240   40960      0.30
3.040320000    jbd2/sda1-8    433    sda     W  3211320   4096       0.18
3.041672000    NetworkManager 748    sda     R  4197120   4096       1.08
3.041702000    NetworkManager 748    sda     R  4197136   4096       1.09
3.041712000    NetworkManager 748    sda     R  4197152   4096       1.08

  • opensnoop - welche Prozesse greifen auf welche Dateien zu
# ./opensnoop
PID    COMM               FD ERR PATH
/proc/25034/cmdline
3102   tmux: server       11   0 /proc/23629/cmdline
3102   tmux: server       11   0 /proc/23629/cmdline
3102   tmux: server       11   0 /proc/25036/cmdline
3102   tmux: server       11   0 /etc/ld.so.cache
25036  ls                  3   0 /lib64/libselinux.so.1
25036  ls                  3   0 /lib64/libcap.so.2
25036  ls                  3   0 /lib64/libc.so.6
25036  ls                  3   0 /lib64/libpcre2-8.so.0
25036  ls                  3   0 /lib64/libdl.so.2
25036  ls                  3   0 /lib64/libpthread.so.0
25036  ls                  3   0 /usr/lib/locale/locale-archive
25036  ls                 -1   2 /usr/share/locale/locale.alias

10.2.3 Kernel

  • exesnoop - zeigt neu Prozesse an
# ./execsnoop 
PCOMM            PID    PPID   RET ARGS
ls               25738  23629    0 /usr/bin/ls --color=auto
dnf              25739  23629    0 /usr/bin/dnf -4 update
ldconfig         25740  25739    0 /sbin/ldconfig -p
top              25741  23629    0 /usr/bin/top

  • syssnoop - Top 10 Syscalls
# ./syscount
Tracing syscalls, printing top 10... Ctrl+C to quit.
^C[20:21:12]
SYSCALL                   COUNT
rt_sigaction              64731
pread                     15558
read                       4816
stat                       2088
lseek                      1513
fstat                      1148
openat                      888
close                       880
pwrite                      788
mmap                        484

10.2.4 Interrupts

  • softirq - Rechnenzeit in Software IRQs
# ./softirqs
Tracing soft irq event time... Hit Ctrl-C to end.
^C
SOFTIRQ          TOTAL_usecs
block                     75
rcu                      122
net_rx                   778
timer                   1836

  • hardirq - Rechnerzeit welche in Hardware Interrups verbraucht wird
# ./hardirqs
Tracing hard irq event time... Hit Ctrl-C to end.
^C
HARDIRQ                    TOTAL_usecs
virtio0-input.0                    438
ata_piix                           941

10.3 Bücher

10.3.1 Linux Observability with BPF

  • by Lorenzo Fontana, David Calavera
  • Publisher: O'Reilly Media, Inc.
  • Release Date: November 2019
  • ISBN: 9781492050209

10.3.2 BPF Performance Tools: Linux System and Application Observability

11 Journal

11.1 Journal Updates

  • die Journal-Einstellungen systemd.journald.max_level_console, systemd.journald.max_level_store, systemd.journald.max_level_syslog, systemd.journald.max_level_kmsg, systemd.journald.max_level_wall können über die Kernel-Kommandozeile übergeben werden und sind aktiv, wenn das Journal in der Init-Ramdisk gestartet wird (und die Journal-Konfigurarionsdatei noch nicht gelesen wurde).
  • Maximale Anzahl von Journal-Datenbank-Dateien: in der Konfiguration /etc/systemd/journal.conf kann konfiguriert werden, wieviel archivierte Journal-Datenbank-Dateien der Journal-Daemon vorhalten soll. Der Standardwert ist 100. Dieser Wert kann über die Einstellungen SystemMaxFiles und RuntimeMaxFiles angepasst werden. Mit dem Befehl journalctl --vacuum-files können alle alten Journal-Datenbanken bis auf die im Befehl angegebene Anzahl gelöscht werden.
  • der Befehl journalctl --sync sort dafür das der Journal-Daemon alle noch im Speicher befindlichen Meldungen in die Datenbank im Dateisystem schreibt
  • wir beim Befehl journalctl als Selektor ein Gerätepfad angegeben, so gibt der Befehl auch Meldungen der Eltern-Geräte-Treiber aus (z.B. des SATA-Kontrollers, wenn eine SATA-Platte angegeben wird)
  • Mit dem Parameter journalctl --root kann ein Journal aus einem alternativen Root-Verzeichnis (z.B. Container) gelesen werden. In den Verzeichnis muss kein Journal-Dienst gestartet sein (d.h. bei einem Container muss der Container nicht gestartet sein)
  • Mit der Option --grep=<suchbegriff> kann die Ausgabe von journalctl auf einen beliebigen Suchbegriff gefiltert werden. Diese Filterung geschied im Journal-Daemon und ist effizienter als eine nachträgliche Filterung mit grep auf der Kommandozeile

11.2 Remote Logging mit Journald

  • Vorteile von Journald Logging im Vergleich zu Syslog
    • mehr Struktur und Metadaten in den Meldungen
    • Datenbankabfrage nach Meldungen, einfache Korrelierung von Events über mehere Systeme
    • Transport über HTTPS/TLS, auch über Web-Proxies möglich
    • abgeschlossene (sealed = kryptografisch abgesichterte) Journal-Datenbanken
    • Pull oder Push

11.3 Dienst systemd-journal-gatewayd

  • wir arbeiten auf dem Laptop
  • mit dem Dienst systemd-journal-gatewayd kann das Journal eines Rechners nach aussen über das Netzwerk exportiert werden. Die Daten werden über HTTP oder HTTPS Protokoll ausgeliefert. Für HTTPS muss ein x509-Zertifikat hinterlegt werden.
  • Paket für Journal-Logging über Netzwerk installieren. Das Paket systemd-journal-remote beinhaltet den systemd-journal-gatewayd Dienst
# dnf install systemd-journal-remote
  • Dienst-Socket starten. Der Socket horcht auf Port 19531/TCP:
# systemctl enable --now systemd-journal-gatewayd.socket
  • In der Firewall Port 19531 freischalten
# firewall-cmd --add-port=19531/tcp --permanent
# firewall-cmd --reload
  • System-Reboot oder Rechte auf /var/log/journal für Gruppe systemd-journal setzen (z.B. via systemd-tmpfiles --create)
  • per Browser auf http://<rechnername>:19531/ ist nun das Journal über ein Web-GUI abfragbar (Achtung: es gibt keine Benutzer-Authentisierung!)
  • Journal-Einträge können auch über HTTP-Kommandozeilen Programme abgerufen werden
# curl 'http://<rechnername-oder-ip>:19531/entries?follow'
  • dabei können die Einträge auch auf Journal-Felder gefiltert werden
curl 'http://<rechnername-oder-ip>:19531/entries?follow&_COMM=sshd'
  • systemd-journal-gatewayd ist die Gegenstelle zu einem zentralen Journal im Pull Modus

11.4 systemd-journal-remote.service

  • das Journal kann in zwei verschiedenen Modi über das Netzwerk transportiert werden: Pull-Modus (zentraler Server holt die Daten von den zu überwachenden Rechnern) oder Push-Modus (zu überwachende Rechner senden aktiv die Daten zum zentralen Journal-Server)

11.4.1 Pull Modus / Aktiver Modus

  • wir arbeiten in der VM und holen das Journal vom Laptop des Trainers (oder eines anderen Teilnehmers)
  • auf dem zentralen Journal-Log-Server (VM) das Paket für Journal-Logging über Netzwerk installieren
# dnf install systemd-journal-remote
  • ein Zielverzeichnis für die neuen Logs erstellen
# mkdir -p /var/log/journal/remote
  • manueller Test, ob die Daten vom entfernten System gelesen werden können
# /usr/lib/systemd/systemd-journal-remote --url http://<rechnername-oder-ip>:19531/entries?follow
  • prüfen das eine neue Journal-Datenbank angelegt wurde
# ls -l /var/log/journal/remote/
  • Remote Logs anschauen
# journalctl -D /var/log/journal/remote -lf
  • lokales Journal zusammen (Parameter -m Merge) mit den entfernten Journals durchsuchen (hier nach Meldungen der Unit sshd)
# journalctl -lmu sshd
  1. Aufgabe: Systemd-Unit für Pull-Modus
    • schreibe eine Systemd-Unit für den Pull-Modus
    • empfange die Journale vom Trainer-Laptop und mehreren Teilnehmer-Rechnern
  2. Lösung
    • Systemd-Unit in /etc/systemd/system/journal-pull.service
    [Unit]
    Description=Service für Remote Journal Pull Modus
    After=network.target
    
    [Service]
    ExecStart=/usr/lib/systemd/systemd-journal-remote --url http://<rechnername-oder-ip>:19531/entries?follow
    Restart=on-failure
    RestartSec=42s
    
    [Install]
    WantedBy=multi-user.target
    
    • Systemd Konfiguration neu laden
    # systemctl daemon-reload
    
    • Dienst starten
    # systemctl enable --now journal-pull
    
    • Dienst prüfen
    # systemctl status journal-pull
    ● journal-pull.service - Service für Remote Journal Pull Modus
       Loaded: loaded (/etc/systemd/system/journal-pull.service; enabled; vendor preset: disabled)
       Active: active (running) since Tue 2020-03-03 14:41:03 CET; 1s ago
     Main PID: 6763 (systemd-journal)
        Tasks: 2 (limit: 26213)
       Memory: 26.9M
       CGroup: /system.slice/journal-pull.service
               ├─6763 /usr/lib/systemd/systemd-journal-remote --url http://192.168.1.240:19531/entries?follow
               └─6764 curl -HAccept: application/vnd.fdo.journal --silent --show-error http://192.168.1.240:19531/entries?follow
    
    Mar 03 14:41:03 notebook33 systemd[1]: Started Service für Remote Journal Pull Modus.
    Mar 03 14:41:03 notebook33 systemd-journal-remote[6763]: Spawning curl http://192.168.1.240:19531/entries?follow...
    
    • neue Journal-Datenbanken erscheinen unter /var/log/journal/remote
    # ls -l /var/log/journal/remote/
    total 49156
    -rw-r-----+ 1 root systemd-journal 25165824 Mar  3 14:41 remote-192.168.1.240.journal
    -rw-r-----+ 1 root systemd-journal 16777216 Mar  3 14:32 remote-192.168.1.241.journal
    -rw-r-----+ 1 root systemd-journal  8388608 Mar  3 14:40 remote-192.168.1.247.journal
    
  3. Alternative Lösung: Unit-Datei mit Parametern
    • Unit-Datei mit Parameter in Datei /etc/systemd/system/journal-pull@.service
    [Unit]
    Description=Service für Remote Journal Pull Modus for Host %I
    After=network.target
    
    [Service]
    ExecStart=/usr/lib/systemd/systemd-journal-remote --url http://%i:19531/entries?follow
    Restart=on-failure
    RestartSec=42s
    
    [Install]
    WantedBy=multi-user.target
    
    
    • Benutzung der Unit-Datei mit Parameter
    # systemctl enable --now journal-pull@192.168.1.239
    # systemctl enable --now journal-pull@192.168.1.230
    

11.4.2 Push Modus / Passiver Modus

  1. Empfänger/Log-Server
    • der VM Rechner ist der Empfänger der Journal-Daten
    • der Push-Modus erwartet verschlüsselte Kommunikation per https. Dafür werden im Internet gültige x509 Zertifikate oder Zertifikate aus einer eigenen CA benötigt. Um die Funktionalität zu zeigen, arbeiten wir hier mit unverschlüsseltem HTTP. Diese Konfiguration ist für Produktiv-Umgebungen nicht zu empfehlen (bitte Zertifikate besorgen und HTTPS benutzen!)
    • die Unit-Datei des Journal-Empfänger-Dienstes anzeigen
    less /usr/lib/systemd/system/systemd-journal-remote.service
    
    • ein Konfigurations-Drop-In für die Systemd-Unit des Dienstes erstellen (für die Konfigurationsänderung HTTPS zu HTTP)
    # systemctl edit systemd-journal-remote.service
    
    • Inhalt der Drop-In Datei
    [Service]
    ExecStart=
    ExecStart=/usr/lib/systemd/systemd-journal-remote --listen-http=-3 --output=/var/log/journal/remote/
    
    • die Konfigurationsdatei des Dienstes. Hier werden bei der Benutzung von HTTPS die Zertifikatsdateien eingetragen. Wir müssen hier in unserer Übung keine Änderungen vornehmen.
    # cat /etc/systemd/journal-remote.conf
    [Remote]
    # Seal=false
    # SplitMode=host
    # ServerKeyFile=/etc/ssl/private/journal-remote.pem
    # ServerCertificateFile=/etc/ssl/certs/journal-remote.pem
    # TrustedCertificateFile=/etc/ssl/ca/trusted.pem
    
    • der Dienst empfängt die Journal-Daten über Port 19532/tcp. Dieser Port wird in der Firewall freigeschalten
    # firewall-cmd --zone=public --add-port=19532/tcp --permanent
    # firewall-cmd --reload
    
    • die neuen Journal-Dateien werden unter /var/log/journal/remote abgelegt, dieses Verzeichnis muss für den Benutzer systemd-journal-remote beschreibbar sein
    # chown systemd-journal-remote /var/log/journal/remote
    
    • den Socket-Listener für den Remote-Journal Dienst starten
    systemctl enable --now systemd-journal-remote.socket
    
    • der Dienst sollte nun auf dem Port 19532 horchen
    # dnf install -y lsof
    # lsof -Poni :19532
    COMMAND    PID                   USER   FD   TYPE DEVICE OFFSET NODE NAME
    systemd      1                   root   27u  IPv6  82082    0t0  TCP *:19532 (LISTEN)
    systemd-j 2562 systemd-journal-remote    3u  IPv6  82082    0t0  TCP *:19532 (LISTEN)
    
  2. Log-Sender (Log-Client)
    • wir arbeiten auf dem Laptop und senden die Journaldaten auf einem VM-Rechner eines oder mehrerer Nachbar-Teilnehmers (bitte absprechen)
    • Konfigurationsdatei /etc/systemd/journal-upload.conf
    [Upload]
    URL=http://<rechnername-oder-ip>
    # ServerKeyFile=/etc/ssl/private/journal-upload.pem
    # ServerCertificateFile=/etc/ssl/certs/journal-upload.pem
    # TrustedCertificateFile=/etc/ssl/ca/trusted.pem
    
    • Manueller Test eines Uploads. Der Parameter --save-state speichert die Information, bis zu welchem Journal-Eintrag die Daten schon gesendet wurden
    # /usr/lib/systemd/systemd-journal-upload --save-state
    
    • die State-Datei wieder löschen (diese gehört dem benutzer Root und kann vom System-journal-upload Dienst nicht gelesen und geschrieben werden)
    # rm /var/lib/systemd/journal-upload/state
    
    • war der manuelle Test erfolgreich, den Journal-Upload Dienst starten
    # systemctl enable --now systemd-journal-upload
    

11.4.3 Aufgabe

  • Richte ein Remote Journal nach den Anweisungen oben ein
  • warum schlägt der Empfang fehl?
  • Teamwork: versuche das Problem auf dem Empfänger zu finden

11.4.4 Lösung

  • SELinux verhindert auf dem Sender den Zugriff auf Port 19532
# ausearch -ts recent -i
[...]
type=PROCTITLE msg=audit(03/03/2020 15:52:32.957:139) : proctitle=/usr/lib/systemd/systemd-journal-upload --save-state 
type=SYSCALL msg=audit(03/03/2020 15:52:32.957:139) : arch=x86_64 syscall=connect success=no exit=EACCES(Permission denied) a0=0x7 a1=0x7ffeedeacea0 a2=0x10 a3=0x15dad322800000 items=0 ppid=1 pid=3403 auid=unset uid=systemd-journal-upload gid=systemd-journal-upload euid=systemd-journal-upload suid=systemd-journal-upload fsuid=systemd-journal-upload egid=systemd-journal-upload sgid=systemd-journal-upload fsgid=systemd-journal-upload tty=(none) ses=unset comm=systemd-journal exe=/usr/lib/systemd/systemd-journal-upload subj=system_u:system_r:init_t:s0 key=(null) 
type=AVC msg=audit(03/03/2020 15:52:32.957:139) : avc:  denied  { name_connect } for  pid=3403 comm=systemd-journal dest=19532 scontext=system_u:system_r:init_t:s0 tcontext=system_u:object_r:unreserved_port_t:s0 tclass=tcp_socket permissive=0 
  • SELinux verhindert das beim Emfänger die Journal-Datei angelegt wird
# ausearch -ts recent -i
[...]
type=SYSCALL msg=audit(03/03/2020 15:20:44.992:141) : arch=x86_64 syscall=openat success=no exit=EACCES(Permission denied) a0=0xffffff9c a1=0x557b24ce8ad0 a2=O_RDWR|O_CREAT|O_NONBLOCK|O_CLOEXEC a3=0x1a0 items=0 ppid=1 pid=27829 auid=unset uid=systemd-journal-remote gid=systemd-journal-remote euid=systemd-journal-remote suid=systemd-journal-remote fsuid=systemd-journal-remote egid=systemd-journal-remote sgid=systemd-journal-remote fsgid=systemd-journal-remote tty=(none) ses=unset comm=systemd-journal exe=/usr/lib/systemd/systemd-journal-remote subj=system_u:system_r:init_t:s0 key=(null) 
type=AVC msg=audit(03/03/2020 15:20:44.992:141) : avc:  denied  { create } for  pid=27829 comm=systemd-journal name=remote-192.168.1.154.journal scontext=system_u:system_r:init_t:s0 tcontext=system_u:object_r:var_log_t:s0 tclass=file permissive=0 
  • Lösung: die SELinux Policy anpassen (oder temporär SELinux in den permissive Modus schalten)
# setenforce permissive  # <- SELinux temporär ausschalten

12 Container

12.1 RedHat Container Toolkit (Buildah, Podman, Skopeo)

12.1.1 Podman als Docker Ersatz

  1. Podman installieren
    • Podman Pakete installieren
    dnf install podman
    
  2. Mit Podman arbeiten
    • Conatiner-Image (hier das aktuelle CentOS) herunterladen
    # podman pull centos:8
    # podman images
    
    • Ein Centos mit Bash starten. Die Parameter -it geben ein _Interaktives _Tterminal.
    # podman run --name=application1 -it centos /bin/bash
    container# dnf update -y
    container# dnf install -y httpd
    container# dnf clean all
    container# exit
    # podman ps -a
    
    • mit laufendem Podman Container verbinden
    podman attach application1
    
    • Podman Container Statistiken
    # podman top <container>
    # podman stats <container1> <container2> ...
    
    • einen weiteren Prozess im Podman Container ausfuehren
    # podman exec -d <container> touch /etc/new-config
    # podman exec -t -i <container> /bin/sh
    
    • Podman Container stoppen
    # podman stop application1
    
    • Podman Container bei Applikations-Ende automatisch neu starten
    podman run --restart=always
    podman run --restart=on-failure:5
    
    podman inspect <container>
    podman inspect --format '{{ .NetworkSettings.IPAddress }}' <container>
    
    • Podman Container im Hintergrund (-d) starten
    podman run --name <name> -d <image> <command>
    
    • Ausgaben der Anwendung im Podman Container anschauen
    podman logs <container>
    podman logs -f <container>
    podman logs --tail -f <container>
    podman logs --tail 50 <container>
    
    • Podman Logging-Treiber (json-file, syslog, none, …) um Log-Ausgaben des Containers nach syslog, in eine Datei oder in ein schwarzes Loch (ausgaben verschwinden) zu schreiben
    podman run --log-driver="syslog" ...
    
  3. Podman Image bauen
    • ein leeres Verzeichnis für unser Dockerfile erstellen
    mkdir -p ~/podman-work
    cd ~/podman-work
    
    • Dockerfile mit einem Editor erstellen
    $EDITOR Dockerfile
    
    • Inhalt der Datei Dockerfile
    # Debian 10(latest) with nginx
    # Version 1
    FROM debian:buster
    
    MAINTAINER Linuxhotel Trainer
    
    # Update image
    RUN apt update
    # Add httpd package. procps and iproute are only added to investigate the image later.
    RUN apt -y install nginx
    RUN echo container.example.com > /etc/hostname
    
    # Create an index.html file
    RUN bash -c 'echo "Your Web server test on Debian a Podman Container is successful." >> /var/www/html/index.html'
    # create a nginx start-command
    CMD nginx -g "daemon off;"
    
    • Podman Image bauen
    podman build -t debian-nginx --no-cache .
    
    • neuen Podman Container aus dem Image starten. Port 80 im Container wird mit Port 8080 auf dem Linux-Host gebunden
    podman run -d -t --name=deb-nginx1 -p 8080:80 debian-nginx
    
    • mit einem Webbrowser (Firefox) die Webseite des Webservers im Container aufrufen (URL: http://localhost:8080/). Es sollte Webseite des NGINX Webservers im Container angezeigt werden.
  4. mit Podman Images arbeiten
    • Podman Image History anschauen
    podman images
    podman history <image-name>
    
    • Podman Image(s) in eine Datei sichern. Matedaten und Schichten bleiben erhalten
    podman save -o mycontainerapp.tar <image-name> [<image-name2>]
    
    • Podman-Image aus einer Datei laden (welche mit podman save erstellt wurde)
    podman load -i mycontainerapp.tar
    
    • Podman Image exportieren (nur das Dateisystem wird exportiert, die Schichten/Layer verschwinden)
    podman images
    podman export -o mycontainerapp.tar <image-name>
    xz -v mycontainerapp.tar
    
    • Podman Image vom Tarball importieren
    xzcat mycontainerapp.tar.xz | podman import - <image-name>
    
    • Podman Container in ein Image umwandeln (z.B. für forensische Analyse)
    podman commit <container-ID> <image-name>
    
  5. Podman Container verbinden
    • Volumes
    podman run -v <local-dir>:<container-dir>[:ro] ...
    
    • Volumes im Dockerfile definieren. Hierdurch werden Volumes beim Erstellen des Containers ausserhalb des Containers erstellt (unter /var/lib/containers/... auf dem Linux-Host) und in den Container eingebunden
    # Dockerfile
    [...]
    VOLUME /data
    VOLUME /var/www/html
    
  6. Podman Übung: Nextcloud
    • wir arbeiten auf dem Laptop
    • wir installieren NextCloud im Container. NextCloud (ein Fork von OwnCloud) eine Softwarelösung welche Dateisynchronisation zwischen Geräten (auch Mobiltelefonen und Tablets), Kalender, Chat, Mail, Audio- und Video-Konferenzen, gemeinsames Editieren an Dateien (und vieles mehr) anbietet
    • diese einfache Installation skaliert für kleine Arbeitsgruppen bis 20 Personen. Bei grösseren Benutzerzahlen sollte eine Installation mit mehreren Containern und einer "richtigen" Datenbank (MariaDB, PostgreSQL) verwendet werden (diese Installation benutzt SQLite).
    • Informationen über das offizielle Nextcloud-Image befindet sich unter https://hub.docker.com/_/nextcloud/
    • Ein Verzeichnis für die NextCloud Daten (persistent) erstellen
    # mkdir -p /srv/container/daten/nextcloud
    
    • Nextcloud Image laden
    # podman pull docker.io/library/nextcloud
    
    • Nextcloud Container erstellen und starten
    # podman run -d --name Nextcloud01 -v /srv/container/daten/nextcloud:/var/www/html -p 80:80 nextcloud
    
    • Alternativ: wenn der Container nur lokal auf der Loopback-Schnittstelle horchen soll, dann bei der Portfreigabe die loopback-Adresse angeben: -p 127.0.0.1:80:80
    • prüfen das der Nextcloud Container gestartet ist und läuft
    # podman ps
    CONTAINER ID  IMAGE                               COMMAND               CREATED         STATUS             PORTS                   NAMES
    0913feb6cde2  docker.io/library/nextcloud:latest  apache2-foregroun...  9 seconds ago   Up 8 seconds ago   0.0.0.0:80->80/tcp      Nextcloud01
    
    • per Browser auf http://localhost/ verbinden und die Einrichtung von NextCloud abschliessen (Admin-Passwort vergeben etc)
    • im Verzeichnis für die Daten sollten nun die Container-Daten liegen
    ls -l /srv/container/daten/nextcloud
    
    • in den laufenden Nextcloud-Container hineinschauen
    # podman exec -it Nextcloud01 /bin/bash
    
    • Einige Befehle zum Probieren (als Benutzer root auf dem Host)
    podman logs <container>   # Anzeige der Logausgaben des Hauptprozesses
    podman top <container>    # Anzeige der Prozesse im Container
    podman stats -a           # Anzeige der von allen Container benutzten Resourcen 
    
    • wird NextCloud im Internet eingesetzt, wird empfohlen auf dem Host einen TLS-Reverse-Proxy einzusetzen, welcher HTTPS/TLS Verschlüsselung anbietet. TLS Zertifikate können von Let's Encrypt kostenlos bezogen werden (siehe Kurs NGINX Webserver oder Netzwerksicherheit und Firewall.
  7. Docker Registry
    • Docker Registry als Podman-Container starten. Die Docker Registry benutzt Port 5000/tcp.
    podman run -d --name container-registry -p 5000:5000 docker.io/library/registry
    
    • Image für den Upload in die Registry markieren ("taggen")
    podman images
    podman tag <image-id> localhost:5000/debian-nginx:01
    
    • Image in die Registry laden (push)
    podman push --tls-verify=false localhost:5000/debian-nginx:01
    
    • Image lokal löschen (Achtung: Images können erst gelöscht werden, wenn keine aktiven under inaktiven Container dieses Image benuzten. Ggf. müssen erst die auf diese Images basierenden Container per podman rm <container> gelöscht werden)
    podman rmi localhost:5000/debian-nginx:01
    podman rmi localhost/debian-nginx
    podman rmi debian:latest
    podman images
    
    • Image aus der lokalen Registy (neu) laden (kann nun von beliebigen Rechner im Netzwerk aus geschehen)
    podman pull localhost:5000/debian-nginx:01
    
    • Podman erwarter für die die Kommunikation zwischen Registry und Podman-Client das die Kommunikation mit TLS/SSL abgesichert ist. Dazu muss auf der Registry ein x509 Zertifikat installiert werden. Optionen:
      • von Let's Encrypt ein x509 Zertifikat besorgen und einbauen. Da Let's Encrypt Zertifkate nur 3 Monate gültig sind, sollte dieser Prozess automatisiert und überwacht sein
      • ein x509 Zertifikat von einer Zertifizierungsstelle (CA) kaufen
      • Option ohne TLS: per SSH einen Tunnel von Port 5000 des Clients auf Port 5000 des Registry-Hosts aufbauen und den Podman-Client gegen den "localhost" Port laufen lassen. Bonus: per Systemd-Socket-Activation auf dem Client kann der SSH-Tunnel automatisch aufgebaut werden.
      • Verbindung mit IPSec absichern
    • History (Layer) eines lokalen Docker Images anschauen
    podman history <image-name>
    
    • RedHat/Fedora/CentOS/Docker Hub (Container Registries im Internet) nach einem Image durchsuchen
    podman search <suchbegriff>
    
    • Liste der Images in einer lokalen Registry laden und anzeigen
    dnf install jq
    curl --silent -X GET http://localhost:5000/v2/_catalog | jq
    

12.1.2 Podman/Docker als Sicherheits-Werkzeug

  • Podman/Docker bietet gegenüber dem Betrieb von klassischen Linux-Installationen (auf "bare Metal" oder virtualisiert) einige Vorteile:
    • Anwendungen werden voneinander isoliert. Selbst die Bestandteile einer Anwendung (z.B. LAMP - Linux/Apache/MySQL/PHP) können in eigene Container ausgelagert und voneinander isoliert werden.
    • die Rechte einer Anwendung im Conatiner kann per Seccomp-bpf und Linux-Capabilities beschränkt werden
    • die Sicht auf den Netzwerkstack kann für Anwendungen eingeschränkt werden (Admin-Netzwerk für Anwendungen nicht sichtbar)
    • Podman/Docker unterstützt ein Implementations-Design, bei dem Anwendungs-Programme und Daten getrennt gehalten werden (Anwendungen in Container-Images, Daten in Speicher-Volumes ausserhalb der Container)
    • Über Dockerfiles sind die Container jederzeit reproduzierbar. Bei einem Einbruch in einen Container kann dieser zu Beweiszwecken eingefroren werden und durch ein neues, sauberes Container-Image ersetzt werden
    • Container werden (in der Regel) nicht per Software-Update aktualisiert, sondern durch ein neues Container-Image mit aktueller Software ersetzt. Hierdurch kann sich ein (auch bisher unbemerkter) Einbrecher nicht im System festsetzen
  • Nachteile:
    • die Isolierung von Anwendungen durch Linux-Container-Virtualisierung ist nicht so stark und vollständig wie bei einer Voll-Virtualisierung (VMWare, HyperV, VirtualBox). Linux-Container können jedoch innerhalb einer Voll-Virtualisierung eingesetzt werden und somit werden die Vorteile beider Systeme genutzt
    • Anwendungs-Installationen müssen angepasst werden, um Programme und Daten sauber zu trennen
    • Docker oder Podman erhöht die Komplexität der Installation (Podman weniger als Docker)
    • Container-Verwaltungswerkzeuge (Kubernetes etc) erhöhen die Komplexität und haben ggf. eigene Sicherheitsprobleme

12.1.3 Podman Container checkpoint

  • einen einfachen Container auf Basis Alpine-Linux erstellen. Im Alpine Container läuft das top Programm
# podman run --rm --name cp-test -d -t alpine top
  • in den Ausgaben des Containers können wir sehen das der Container aktiv ist
# podman logs cp-test
  • der Container wird auch in der Liste der Container aufgeführt
# podman ps
  • nun stoppen wir den Container (CRIU im Hintergrund) und exportieren den Container in ein gezipptes TAR-Archiv
# podman container checkpoint -e alpine.tgz cp-test
  • der Container ist nun aus der Liste der Container verschwunden
# podman ps
  • dafür gibt es eine Archiv-Datei mit dem "gefrohrenen" Zustand des Containers
# ls -lh *.tgz
-rw-------. 1 root root  32K Mar  3 13:50 alpine.tgz
  • das Archiv kann nun wieder im Podman importiert werden (das Container Image muss im Podman Image Store existieren)
# podman container restore -i alpine.tgz 
  • und der Container läuft wieder
# podman ps

12.1.4 Podman "rootless" Container

# dnf install slirp4netns podman
  • die Anzahl der User-Namespaces erhöhen
# echo "user.max_user_namespaces=28633" > /etc/sysctl.d/userns.conf
# sysctl -p /etc/sysctl.d/userns.conf
  • arbeite als Benutzer nutzerXX (direkter Login, nicht per su oder sudo). Wir laden ein Container-Image aus der Fedora Registry
$ podman pull docker.io/library/alpine
  • Das Container-Image wurde erfolgreich geladen
$ podman images
REPOSITORY                 TAG      IMAGE ID       CREATED       SIZE
docker.io/library/alpine   latest   e7d92cdc71fe   6 weeks ago   5.86 MB
  • einen neuen Container aus dem Image starten
$ podman run --name alpine -it alpine /bin/sh
  • Im Container hat der Benutzer nutzer anscheinend Root-Rechte
/ # id
uid=0(root) gid=0(root)
  • Im Container kann der Benutzer Software installieren
/ # apk add nginx
fetch http://dl-cdn.alpinelinux.org/alpine/v3.11/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.11/community/x86_64/APKINDEX.tar.gz
(1/2) Installing pcre (8.43-r0)
(2/2) Installing nginx (1.16.1-r6)
Executing nginx-1.16.1-r6.pre-install
Executing busybox-1.31.1-r9.trigger
OK: 7 MiB in 16 packages
  • und auch starten
/ # nginx -V
nginx version: nginx/1.16.1
built with OpenSSL 1.1.1d  10 Sep 2019
TLS SNI support enabled
[...]
  • Mapping der Benutzer-IDs anzeigen (als unpriviligierter Benutzer, ausserhalb des Containers). Die Werte sind: UID-im-Container, UID-ausserhalb des Containers, Anzahl der UIDs verfügbar
$ podman unshare cat /proc/self/uid_map                                                                   
         0       1000          1
         1     100000      65536
  • Rootless Container werden im Heimverzeichnis des Benutzers gespeichert
$ ls -l ~/.local/share/containers/storage/
total 32
drwx------. 2 nutzer nutzer 4096 Mar  3 05:51 libpod
drwx------. 2 nutzer nutzer 4096 Mar  3 05:51 mounts
drwx------. 5 nutzer nutzer 4096 Mar  3 06:05 overlay
drwx------. 3 nutzer nutzer 4096 Mar  3 06:05 overlay-containers
drwx------. 3 nutzer nutzer 4096 Mar  3 06:04 overlay-images
drwx------. 2 nutzer nutzer 4096 Mar  3 06:05 overlay-layers
-rw-------. 1 nutzer nutzer   64 Mar  3 06:14 storage.lock
drwx------. 2 nutzer nutzer 4096 Mar  3 05:51 tmp

12.1.5 Container-Toolbox (auf RHEL 8.x)

  • Toolbox Befehl installieren
dnf install toolbox
  • eine Bash in der Toolbox starten
toolbox bash

12.1.6 Alternative: einen Fedora-Toolbox Container starten

  • CentOS mit Fedora 31 Toolbox direkt per podman starten (dies passiert beim original toolbox Befehl im Hintergrund, nur mit einem RedHat Container-Image). Administratoren sollten sich ein eigenes Toolbox-Image erstellen
podman run -it \
  --name toolbox-root \
  --privileged \
  --ipc=host \
  --net=host \
  --pid=host \
  -e HOST=/host \
  -e NAME=toolbox-root \
  -e IMAGE=registry.fedoraproject.org/f31/fedora-toolbox \
  -v /run:/run \
  -v /var/log:/var/log \
  -v /etc/machine-id:/etc/machine-id \
  -v /etc/localtime:/etc/localtime \
  -v /:/host \
  registry.fedoraproject.org/f31/fedora-toolbox

12.1.7 Universal Base Images (UBI) unter Centos

# podman login -u "account-name" -p "access-token" registry.redhat.io
  • UBI Image aus dem RedHat Repository laden
# podman pull registry.access.redhat.com/ubi8/ubi:latest
  • UBI Container starten
# podman run -it --name rhel8-test ubi

12.1.8 Buildah

# dnf install buildah
  • einen neuen Container auf Basis Ubuntu bauen
# buildah from ubuntu
  • verfügbare buildah Images anzeigen
# buildah images
REPOSITORY                 TAG      IMAGE ID       CREATED       SIZE
docker.io/library/ubuntu   latest   72300a873c2c   10 days ago   66.6 MB
  • verfügbare buildah Container
# buildah containers
CONTAINER ID  BUILDER  IMAGE ID     IMAGE NAME                       CONTAINER NAME
452c891a4fb2     *     72300a873c2c docker.io/library/ubuntu:latest  ubuntu-working-container
  • Paketliste innerhalb des Ubuntu Containers aktualisieren
# buildah run ubuntu-working-container apt update
  • NGINX Webserver im Container installieren
# buildah run ubuntu-working-container apt install nginx
  • Container mounten
# buildah mount ubuntu-working-container
/var/lib/containers/storage/overlay/4db098fe597968ab120b8361525249283ce29c33294072fe7ea52a894afb5287/merged
# ls /var/lib/containers/storage/overlay/4db098fe597968ab120b8361525249283ce29c33294072fe7ea52a894afb5287/merged
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
  • eine Datei im Container erstellen
# cd /var/lib/containers/storage/overlay/4db098fe597968ab120b8361525249283ce29c33294072fe7ea52a894afb5287/merged
# echo "Meine HTML Seite" > var/www/html/index.nginx-debian.html 
  • Container-Dateisystem aushängen
# buildah umount ubuntu-working-container
452c891a4fb2c03c3362a00d7aed1e95f4ed73fac14b70e62f03a2bdb27b5e99
  • Änderungen in ein Container-Image für Podman überführen
# buildah commit ubuntu-working-container mynginx
Getting image source signatures
Copying blob cc4590d6a718 skipped: already exists
Copying blob 8c98131d2d1d skipped: already exists
Copying blob 03c9b9f537a4 skipped: already exists
Copying blob 1852b2300972 skipped: already exists
Copying blob ac7126531e4a done
Copying config 41a7450a9d done
Writing manifest to image destination
Storing signatures
41a7450a9d36de438ea7d584efd27c3f9be0f731da7215ed83507e3ccad91f23
  • die Container-Images sind direkt für den Podman sichtbar und nutzbar
# podman run -d -p 80:80 --name nginx mynginx nginx -g 'daemon off;'
74be1539b85c52dde991faa10893e7dc64ada793aab81ae4411e97595bb6ea73
  • prüfen das der Container läuft
# podman ps
CONTAINER ID  IMAGE                     COMMAND               CREATED         STATUS             PORTS               NAMES
e5d22830f587  localhost/mynginx:latest  nginx -g daemon o...  35 seconds ago  Up 34 seconds ago  0.0.0.0:80->80/tcp  nginx
  • Firewall Freischaltung für Port 80
# firewall-cmd --add-service=http --permanent
# firewall-cmd --reload
  • Testen, ob die Webseite erreichbar ist

12.1.9 Container Images laden und konvertieren mit "skopeo"

  • mit dem Befehl skopeo können Container Images verschiedener Formate umgewandelt werden
  • Unterstützte Formate
    • Container-Storage (Podman), lokales Image Repository wie unter /etc/containers/storage.conf konfiguriert
    • Verzeichnisse (z.B. für systemd-nspawn)
    • Docker Registry (auch RedHat/Fedora/CentOS/Quay.io Docker-Image Registries)
    • Docker-Archiv welches mit dem Befehl docker save angelegt wurde
    • Image aus einem laufenden Docker-Daemon
    • Image aus einem OCI (Open Container Image Layout Specification) Pfad
    • OSTREE-Image: https://ostree.readthedocs.io/en/latest/
  • in diesem Beispiel wird ein Docker-Container aus der Docker-Registry in ein Container-Verzeichnis umgewandelt, so das der Container mit systemd-nspawn benutzt werden kann
  • skopeo installieren
# dnf install skopeo systemd-container
  • anlegen des Container Verzeichnis
# mkdir -p /srv/container/debian
  • per skopeo das Image direkt aus der Docker Registry in das Verzeichnis kopieren
# skopeo copy docker://debian:latest dir:/srv/container/debian
  • das TAR-Image in das Container-Verzeichnis auspacken (die UUID einsetzen)
# ls -lh /srv/container/debian/
# tar -C /srv/container/debian/ -xzf /srv/container/debian/<uuid-des-container-images>
  • In den Container wechseln und ein Passwort für den Root-Benutzer vergeben
systemd-nspawn -D /srv/container/debian/
root@debian:~# passwd
  • Systemd im Container installieren
root@debian:~# apt update
root@debian:~# apt install systemd
root@debian:~# exit
  • Debian Container per systemd-nspawn starten
systemd-nspawn -bD /srv/container/debian/
  • Systemd Container beenden
(container)# poweroff
  • oder
(container)# systemctl exit

12.2 Systemd-Container

12.2.1 systemd-nspawn Container aus komprimierten Images starten

  • ein Container-Image laden (hier ein Fedora 28). Siehe https://nspawn.org für weitere Images
# curl -o debian.img.xz  https://nspawn.org/storage/debian/buster/raw/image.raw.xz
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 1026M  100 1026M    0     0  83.3M      0  0:00:12  0:00:12 --:--:-- 91.3M
  • Container starten um das Root-Passwort zu setzen
#  systemd-nspawn -i debian.img.xz 
Spawning container debian.img.xz on /root/debian.img.xz.
Press ^] three times within 1s to kill container.
root@debian:~# passwd
New password: 
Retype new password: 
passwd: password updated successfully
root@debian:~# logout
Container debian.img.xz exited successfully.
  • Container aus dem Image booten
# systemd-nspawn -bi debian.img.xz

12.2.2 Emphermeral Container aus Images

  • systemd-nspawn erlaubt nun auch ephermeral (flüchtige) Container aus (komprimierten) Image Dateien. Nach dem Beenden des Containers werden alle Änderungen an den Container verworfen.
# systemd-nspawn --ephemeral  -bi debian.img.xz

12.2.3 systemd-nspawn und Netzwerk-Zonen

  • systemd-nspawn gained a new –network-zone= switch, that allows creating ad-hoc virtual Ethernet links between multiple containers, that only exist as long as at least one container referencing them is running. This allows easy connecting of multiple containers with a common link that implements an Ethernet broadcast domain. Each of these network "zones" may be named relatively freely by the user, and may be referenced by any number of containers, but each container may only reference one of these "zones". On the lower level, this is implemented by an automatically managed bridge network interface for each zone, that is created when the first container referencing its zone is created and removed when the last one referencing its zone terminates.
  • ersten Container starten
# systemd-nspawn --network-zone=debian -bD /srv/container/debian/
  • in diesem Container die Netzwerkschnittstelle host0 mit einer IP-Adresse versehen und Netzwerkschnittstelle aktivieren
container1# ip addr add 10.0.0.1/24 dev host0
container1# ip link set dev host0 up
  • zweiten Container starten und Netzwerkschnittstelle konfigurieren
# systemd-nspawn --network-zone=debian -bD /srv/container/debian-2/
container2# ip addr add 10.0.0.2/24 dev host0
container2# ip link set dev host0 up
  • Auf dem Host die Netzwerkschnittstellen anschauen
# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000                                           
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000                                   
    link/ether 96:00:00:44:77:1f brd ff:ff:ff:ff:ff:ff
    inet 95.216.196.19/32 brd 95.216.196.19 scope global dynamic noprefixroute eth0                                                   
       valid_lft 54246sec preferred_lft 54246sec
    inet6 2a01:4f9:c010:541f::1/64 scope global noprefixroute
       valid_lft forever preferred_lft forever
    inet6 fe80::9400:ff:fe44:771f/64 scope link noprefixroute
       valid_lft forever preferred_lft forever
3: vb-debian@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master vz-debian state UP group default qlen 1000          
    link/ether 42:7d:ce:7a:0f:9d brd ff:ff:ff:ff:ff:ff link-netnsid 0                                                                 
    inet6 fe80::407d:ceff:fe7a:f9d/64 scope link
       valid_lft forever preferred_lft forever
4: vz-debian: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000                                            
    link/ether 42:7d:ce:7a:0f:9d brd ff:ff:ff:ff:ff:ff
5: vb-debian-2@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master vz-debian state UP group default qlen 1000        
    link/ether e2:77:74:7e:c8:d4 brd ff:ff:ff:ff:ff:ff link-netnsid 1                                                                 
    inet6 fe80::e077:74ff:fe7e:c8d4/64 scope link
       valid_lft forever preferred_lft forever
  • Ethernet Bridge "vz-debian" auf dem Container-Host aktivieren
# ip link set dev vz-debian up
  • die Container können nun über die host0 Schnittstelle kommunizieren
container2* ping 10.0.0.1

12.2.4 Extra VETH Schnittstellen in systemd-nspawn

  • systemd-nspawn kann zusätzliche "virtuelle Ethernet" Schnittstellen (veth) erzeugen und mit dem Host-System verbinden
  • Beispiel: start des Containers
# systemd-nspawn --network-veth --network-veth-extra=vethX -bD /srv/container/debian-2/
  • Netwerkschnittstellen im Container
container# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: host0@if8: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 9e:27:47:fc:d0:d2 brd ff:ff:ff:ff:ff:ff link-netnsid 0
3: vethX@if9: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 46:5f:5a:c9:24:0b brd ff:ff:ff:ff:ff:ff link-netnsid 0
  • Netzwerkschnittstellen auf dem Host
# ip a
[...]
8: ve-debian-2@if2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether e2:77:74:7e:c8:d4 brd ff:ff:ff:ff:ff:ff link-netnsid 0
9: vethX@if3: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 4e:ed:7e:92:c4:df brd ff:ff:ff:ff:ff:ff link-netnsid 0

12.2.5 IPVLAN - schnelle Netzwerkanbindung für Container

12.2.6 Aufgabe: Container mit IPVLAN

  • wir benutzen das Debian Verzeichnis unter /srv/container/debian
  • Container mit IPVLAN auf dem WLAN-Interface mit Hilfe von systemd-nspawn erstellen
# systemd-nspawn --network-ipvlan=wlp2s0 -bD /srv/container/debian
  • im den Container von aussen eine Shell erstellen (in einem anderen Terminal)
# machinectl shell debian
  • das IPVLAN Interface
root@buster:~# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: iv-wlp2s0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 96:00:00:44:77:1f brd ff:ff:ff:ff:ff:ff
  • IP-Adressen auf die Schnittstelle vergeben (freie IP-Adressen im Host-Netzwerk 192.168.1.60-69)
root@buster:~# ip addr add 192.168.1.60/24 dev iv-wlp2s0
  • Schnittstelle aktivieren
root@buster:~# ip link set dev iv-wlp2s0 up
  • Route setzen (Default-Route im Host-Netzwerk ermitteln und benutzen!)
# ip route add default via 192.168.1.5 dev iv-wlp2s0
  • Netzwerk funktioniert
root@buster:~# ping 1.1.1.1
  • bei IPVLAN die IP-Adressen manuell konfigurieren, kein DHCP(v6) verwenden, da die IPVLAN Schnittstelle die gleiche MAC-Adresse wie der Host hat und daher die gleiche IP-Adresse per DHCP bekommt – doppelte IP-Adresse im Netzwerk und weder Host noch Container können zuverlässig komunizieren

12.2.7 weitere RHEL 8 Neuihkeiten rund um Systemd-nspawn und Container (Übersetzung und Beispiele kommen)

  • systemd-nspawn gained a new –overlay= switch for mounting overlay file systems into the container using the new kernel overlayfs support.
  • systemd-nspawn gained a new –private-users= switch to make use of user namespacing available on recent Linux kernels.
  • systemd-nspawn gained a new –property= setting to set unit properties for the container scope. This is useful for setting resource parameters (e.g. "CPUShares=500") on containers started from the command line.
  • machinectl gained a new verb 'shell' which opens a fresh shell on the target container or the host. It is similar to the existing 'login' command of machinectl, but spawns the shell directly without prompting for username or password. The pseudo machine '.host' now refers to the local host and is used by default. Hence, 'machinectl shell' can be used as replacement for 'su -' which spawns a session as a fresh systemd unit in a way that is fully isolated from the originating session.
  • nspawn learnt support for .nspawn settings files, that may accompany the image files or directories of containers, and may contain additional settings for the container. This is an alternative to configuring container parameters via the nspawn command line.
  • systemd-nspawn gained a new –as-pid2 switch that invokes any specified command line as PID 2 rather than PID 1 in the container. In this mode PID 1 is a minimal stub init process that implements the special POSIX and Linux semantics of PID 1 regarding signal and child process management. Note that this stub init process is implemented in nspawn itself and requires no support from the container image. This new logic is useful to support running arbitrary commands in the container, as normal processes are generally not prepared to run as PID 1.
  • systemd-nspawn gained a new –chdir= switch for setting the current working directory for the process started in the container.
  • systemd-nspawn gained support for automatically patching the UID/GIDs of the owners and the ACLs of all files and directories in a container tree to match the UID/GID user namespacing range selected for the container invocation. This mode is enabled via the new –private-users-chown switch. It also gained support for automatically choosing a free, previously unused UID/GID range when starting a container, via the new –private-users=pick setting (which implies –private-users-chown). Together, these options for the first time make user namespacing for nspawn containers fully automatic and thus deployable. The systemd-nspawn@.service template unit file has been changed to use this functionality by default.
  • systemd-nspawn gained a new switch –notify-ready= taking a boolean value. This may be used for requesting that the system manager inside of the container reports start-up completion to nspawn which then propagates this notification further to the service manager supervising nspawn itself. A related option NotifyReady= in .nspawn files has been added too. This functionality allows ordering of the start-up of multiple containers using the usual systemd ordering primitives.
  • "machinectl list" now shows the IP address of running containers in the output, as well as OS release information.
  • systemd-nspawn gained support for a new –pivot-root= switch. If specified the root directory within the container image is pivoted to the specified mount point, while the original root disk is moved to a different place. This option enables booting of ostree images directly with systemd-nspawn.
  • A new unit file option RootImage= has been added, which has a similar effect as RootDirectory= but mounts the service's root directory from a disk image instead of plain directory. This logic reuses the same image dissection and mount logic that systemd-nspawn already uses, and hence supports any disk images systemd-nspawn supports, including those following the Discoverable Partition Specification, as well as Verity enabled images. This option enables systemd to run system services directly off disk images acting as resource bundles, possibly even including full integrity data.
  • A new tool /usr/lib/systemd/systemd-dissect has been added that may be used to dissect disk images the same way as systemd-nspawn does it, following the Bootable Partition Specification. It may even be used to mount disk images with complex partition setups (including LUKS and Verity partitions) to a local host directory, in order to inspect them. This tool is not considered public API (yet), and is thus not installed into /usr/bin. Please do not rely on its existence, since it might go away or be changed in later systemd versions.
  • systemd-nspawn gained a new –network-namespace-path= command line option, which may be used to make a container join an existing network namespace, by specifying a path to a "netns" file.
  • systemd-nspawn gained a new –rlimit= switch for setting initial resource limits for the container payload. There's a new switch –hostname= to explicitly override the container's hostname. A new –no-new-privileges= switch may be used to control the PRSETNONEWPRIVS flag for the container payload. A new –oom-score-adjust= switch controls the OOM scoring adjustment value for the payload. The new –cpu-affinity= switch controls the CPU affinity of the container payload. The new –resolv-conf= switch allows more detailed control of /etc/resolv.conf handling of the container. Similarly, the new –timezone= switch allows more detailed control of /etc/localtime handling of the container.

13 OS-Sicherheit

13.1 Systemd Sicherheit (Übersetzung und Beispiele anstehend)

  • Mastering systemd: Securing and sandboxing applications and services: https://www.redhat.com/sysadmin/mastering-systemd
  • The coredumpctl tool gained a new –directory= option to operate on journal files in a specific directory.
  • The systemd-analyze tool gained a new "set-log-target" verb to change the logging target the system manager logs to dynamically during runtime. This is similar to how "systemd-analyze set-log-level" already changes the log level.
  • There's a new system.conf setting DefaultTasksMax= to control the default TasksMax= setting for services and scopes running on the system. (TasksMax= is the primary setting that exposes the "pids" cgroup controller on systemd and was introduced in the previous systemd release.) The setting now defaults to 512, which means services that are not explicitly configured otherwise will only be able to create 512 processes or threads at maximum, from this version on. Note that this means that thread- or process-heavy services might need to be reconfigured to set TasksMax= to a higher value. It is sufficient to set TasksMax= in these specific unit files to a higher value, or even "infinity". Similar, there's now a logind.conf setting UserTasksMax= that defaults to 4096 and limits the total number of processes or tasks each user may own concurrently. nspawn containers also have the TasksMax= value set by default now, to 8192. Note that all of this only has an effect if the "pids" cgroup controller is enabled in the kernel. The general benefit of these changes should be a more robust and safer system, that provides a certain amount of per-service fork() bomb protection.
  • A new service setting RuntimeMaxSec= has been added that may be used to specify a maximum runtime for a service. If the timeout is hit, the service is terminated and put into a failure state.
  • A new service setting MemoryDenyWriteExecute= has been added, taking a boolean value. If turned on, a service may no longer create memory mappings that are writable and executable at the same time. This enhances security for services where this is enabled as it becomes harder to dynamically write and then execute memory in exploited service processes. This option has been enabled for all of systemd's own long-running services.
  • The SystemCallFilter= unit file setting gained support for pre-defined, named system call filter sets. For example SystemCallFilter=@clock is now an effective way to make all clock changing-related system calls unavailable to a service. A number of similar pre-defined groups are defined. Writing system call filters for system services is simplified substantially with this new concept. Accordingly, all of systemd's own, long-running services now enable system call filtering based on this, by default.
# systemd-analyze syscall-filter
# man systemd.exec
  • The InaccessableDirectories=, ReadOnlyDirectories= and ReadWriteDirectories= unit file settings have been renamed to InaccessablePaths=, ReadOnlyPaths= and ReadWritePaths= and may now be applied to all kinds of file nodes, and not just directories, with the exception of symlinks. Specifically these settings may now be used on block and character device nodes, UNIX sockets and FIFOS as well as regular files. The old names of these settings remain available for compatibility.
  • In service units the various ExecXYZ= settings have been extended with an additional special character as first argument of the assigned value: if the character '+' is used the specified command line it will be run with full privileges, regardless of User=, Group=, CapabilityBoundingSet= and similar options. The effect is similar to the existing PermissionsStartOnly= option, but allows configuration of this concept for each executed command line independently.
  • Services may be started with their own user namespace using the new boolean PrivateUsers= option. Only root, nobody, and the uid/gid under which the service is running are mapped. All other users are mapped to nobody.
  • The new MemorySwapMax= option can be used to limit the maximum swap usage under the unified cgroup hierarchy.
  • Support for dynamically creating users for the lifetime of a service has been added. If DynamicUser=yes is specified, user and group IDs will be allocated from the range 61184..65519 for the lifetime of the service. They can be resolved using the new nss-systemd.so NSS module. The module must be enabled in /etc/nsswitch.conf. Services started in this way have PrivateTmp= and RemoveIPC= enabled, so that any resources allocated by the service will be cleaned up when the service exits. They also have ProtectHome=read-only and ProtectSystem=strict enabled, so they are not able to make any permanent modifications to the system.
  • The new ProtectKernelModules= option can be used to disable explicit load and unload operations of kernel modules by a service. In addition access to /usr/lib/modules is removed if this option is set.
  • ProtectSystem= option gained a new value "strict", which causes the whole file system tree with the exception of /dev, /proc, and /sys, to be remounted read-only for a service.
  • The new ProtectKernelTunables= option can be used to disable modification of configuration files in /sys and /proc by a service. Various directories and files are remounted read-only, so access is restricted even if the file permissions would allow it.
  • The new ProtectControlGroups= option can be used to disable write access by a service to /sys/fs/cgroup.
  • A new unit file option RestrictNamespaces= has been added that may be used to restrict access to the various process namespace types the Linux kernel provides. Specifically, it may be used to take away the right for a service unit to create additional file system, network, user, and other namespaces. This sandboxing option is particularly relevant due to the high amount of recently discovered namespacing related vulnerabilities in the kernel.
  • systemd-analyze gained a new verb "syscall-filter" which shows which system call groups are defined for the SystemCallFilter= unit file setting, and which system calls they contain.
  • Units gained new options StateDirectory=, CacheDirectory=, LogsDirectory= and ConfigurationDirectory= which are closely related to RuntimeDirectory= but manage per-service directories below /var/lib, /var/cache, /var/log and /etc. By making use of them it is possible to write unit files which when activated automatically gain properly owned service specific directories in these locations, thus making unit files self-contained and increasing compatibility with stateless systems and factory reset where /etc or /var are unpopulated at boot. Matching these new settings there's also StateDirectoryMode=, CacheDirectoryMode=, LogsDirectoryMode=, ConfigurationDirectoryMode= for configuring the access mode of these directories. These settings are particularly useful in combination with DynamicUser=yes as they provide secure, properly-owned, writable, and stateful locations for storage, excluded from the sandbox that such services live in otherwise.
  • A new TemporaryFileSystem= setting can be used to mask out part of the real file system tree with tmpfs mounts. This may be combined with BindPaths= and BindReadOnlyPaths= to hide files or directories not relevant to the unit, while still allowing some paths lower in the tree to be accessed. ProtectHome=tmpfs may now be used to hide user home and runtime directories from units, in a way that is mostly equivalent to "TemporaryFileSystem=/home /run/user /root".
  • A new unit file setting PrivateMounts= has been added. It's a boolean option. If enabled the unit's processes are invoked in their own file system namespace. Note that this behaviour is also implied if any other file system namespacing options (such as PrivateTmp=, PrivateDevices=, ProtectSystem=, …) are used. This option is hence primarily useful for services that do not use any of the other file system namespacing options. One such service is systemd-udevd.service where this is now used by default.
  • A new system.conf setting NoNewPrivileges= is now available which may be used to turn off acquisition of new privileges system-wide (i.e. set Linux' PRSETNONEWPRIVS for PID 1 itself, and thus also for all its children). Note that turning this option on means setuid binaries and file system capabilities lose their special powers. While turning on this option is a big step towards a more secure system, doing so is likely to break numerous pre-existing UNIX tools, in particular su and sudo.

13.2 Anwendungs Whitelist mit dem "File Access Policy Daemon"

# dnf install fapolicyd
  • Liste der zu überwachenden Dateisysteme / Mountpoint inder Datei /etc/fapolicyd/fapolicyd.mounts erstellen
/
/boot
/run
  • den fapolicyd Dienst starten
# systemctl enable --now fapolicyd
  • Versuch, FZF, den "command-line fuzzy finder" zu instalieren und zu benutzen (ein statisch gelinktes Go Program)
# dnf -y install tar
# curl -L -O https://github.com/junegunn/fzf-bin/releases/download/0.20.0/fzf-0.20.0-linux_amd64.tgz
# tar xvfz fzf-0.20.0-linux_amd64.tgz
# ls -l fzf
-rwxr-xr-x. 1 501 games 2952388 Dec 17 17:18 fzf
# ./fzf
-bash: ./fzf: Operation not permitted
  • fapolicyd im Debug-Modus starten
# systemctl stop fapolicyd
# /usr/sbin/fapolicyd --permissive --debug

13.2.1 Aufgabe

  • FZF: https://github.com/junegunn/fzf
  • lade die FZF Binärdatei und speichere die Datei unter /home/nutzerXX/bin
  • berechne die SHA256 Prüfsumme der Datei fzf
  • erstelle eine neue Regel (siehe Dokumentation man fapolicyd.rules) in /etc/fapolicyd/fapolicyd.rules um die Ausführung von fzf zu erlauben
# sha256sum /root/fzf
29dfb84ef14dd6dd78df1dbf7624048607c6878e731b1e84713f6469d6f9081f  /root/fzf

13.2.2 Lösung FZF im "fapolicyd" freischalten

  • Regel für fzf in fapolicyd.rules. Die Regel muss am Anfang der Datei stehen
allow all sha256hash=29dfb84ef14dd6dd78df1dbf7624048607c6878e731b1e84713f6469d6f9081f
[...]
# Only allow system ELF Applications - note: depends on above check
# for untrusted executables.
allow all dir=execdirs ftype=application/x-executable
deny_audit all ftype=application/x-executable
[...]
  • fzf an eine gute Stelle kopieren
# mkdir ~/bin
# mv /root/fzf ~/bin
  • Aufruf von fzf testen

13.3 SELinux Update

  • getrlimit Rechte auf "process" Klassen - die SELinux Policy kann nun verhindern das ein Prozess die Prozesslimits eines anderen Prozesses ausliest
  • SELinux Policies können nun Zugriffe per mmap auf Dateisystemobjekte wie Dateien, Verzeichnisse und Sockets kontrollieren
  • SELinux unterstützt die Systemd Konfiguration No New Privileges. Diese Verhindert das ein Prozess per suid Bit auf einer Datei beim Start erweiterte Rechte bekommt
  • neue SELinux Schalter (Booleans)
    • colordusenfs
    • mysqlconnecthttp
    • pdnscannetworkconnectdb
    • sshusetcpd
    • sslhcanbindanyport
    • sslhcanconnectanyport
    • virtusepcscd

13.3.1 UDICA - SELinux Richtlinien für Container

  • udica ist ein neues Werkzeug um unter RedHat/CentOS SELinux Richtlinien für Linux-Container zu erzeugen Quellcode und Dokumentation: https://github.com/containers/udica
  • SELinux muss im Enforcing Modus sein
# setenforce 1
# getenforce
Enforcing
  • wir starten einen Container mit Podman auf Basis von Fedora Linux
# podman run -v /home:/home:ro -v /var/spool:/var/spool:rw -p 80:80 -it fedora bash
  • dieser Container hat mehrere Probleme mit SELinux
    • Zugriff aus dem Container auf /home ist nicht möglich
    • Zugriff auf /var/spool ist nicht möglich
    • der Container hat keine Beschränkungen um auf das Netzwerk zuzugreifen, Prozesse im Container können sich auf alle Ports (nicht nur Port 80) binden (jedoch ist nur Port 80 von aussen per Port-Forwarding erreichbar)
  • mit dem Werkzeug udica kann eine auf den Container zugeschnittene SELinux Policy erzeugt werden
  • der Container muss dazu gestartet sein(!)
  • die Container-ID ermitteln (oder, wenn ein Name vergeben wurde, den Namen des Containers verwenden)
# podman ps
  • UDICA Installieren
# dnf install udica
  • neue SELinux Richtlinie erstellen
# podman inspect <container-id> | udica fedora-container

Policy fedora-container created!

Please load these modules using:
# semodule -i fedora-container.cil /usr/share/udica/templates/{base_container.cil,net_container.cil,home_container.cil}

Restart the container with: "--security-opt label=type:fedora-container.process" parameter

  • neues SELinux Modul neu laden
# semodule -i fedora-container.cil /usr/share/udica/templates/{base_container.cil,net_container.cil,home_container.cil}
  • Fedora Container beenden (Shell verlassen) und im Podman den alten Container löschen
# podman rm <container-id>
  • Container neu erstellen, dabei die neue Sicherheitsrichtlinie referenzieren
# podman run --security-opt label=type:fedora-container.process -v /home:/home:ro -v /var/spool:/var/spool:rw -p 80:80 -it fedora bash
  • der Container hat nun Zugriff auf /home und /var/spool und Prozesse im Container dürfen sich nur an Port 80 binden

14 Cockpit

dnf install 'cockpit*'
  • Port 9090 (webSM) in der Red Hat Firewall freischalten
firewall-cmd --add-port=9090/tcp
firewall-cmd --permanent --add-port=9090/tcp
  • Cockpit starten
systemctl enable --now cockpit
  • per Browser auf https://<servername-oder-ip>:9090/ verbinden
  • Als Benuzter nutzerXX anmelden

14.1 Cockpit Jump-Host

  • auf dem Cockpit Jumphost Cockpit-Dashboard installieren
dnf update
dnf install cockpit-dashboard
  • neuen Server grafisch über die Web-UI hinzufügen
  • auf dem Cockpit Jumphost SSH-Schlüssel erzeugen und eine Passphrase setzen
ssh-keygen -t ed25519
  • öffentlicher SSH-Schlüssel vom Cockpit-Jumphost auf das Ziel-System kopieren
ssh-copy-id nutzer@192.168.1.233
  • Cockpit auf dem Ziel-System installieren (muss nicht gestartet werden)
dnf install cockpit
  • In der Cockpit-Web-UI unter Authentication den neuen SSH-Schlüssel importieren (dabei die Passphrase eingeben)
  • das Ziel-System unter "Dashboard" dem Cockpit Jumphost hinzufügen
  • das Ziel-System sollte nun im Cockpit Web-UI sichtbar und administrierbar sein
  1. Aufgabe: Trainer-Laptop in das eigene Cockpit aufnehmen
    • Cockpit auf dem Laptop installieren und aktivieren
    • den eigenen SSH-Schlüssel per ssh-copy-id auf den Laptop des Trainers (notebook33.linuxhotel.de) kopieren
    • den Trainer-Laptop mit in das eigene Cockpit aufnehmen
    • Alternativ: Authentisierung/Anmeldung per Benutzername/Passwort probieren
  2. Aufgabe: weitere Cockpit-Module installieren
    • per dnf search cockpit eine Liste der verfuegbaren Cockpit Module auflisten
    • ein oder mehrere Cockpit Module installieren, z.B. cockpit-storaged, cockpit-podman oder/und cockpit-machines
    • im Cockpit-Webinterface aus- und wieder einloggen, schauen das die neue Funktion verfügbar ist

15 OverlayFS

  • OverlayFS vereinigt zwei oder mehr Verzeichnisse.
    • Prozesse im Linux-System sehen die Menge aller Verzeichnisse die im OverlayFS zusammengefasst sind
    • es gibt ein oberes (upper) und ein oder mehrere untere (lower) Verzeichnisse
    • die unteren (lower) Verzeichnisse sind nur-lesbar
    • alle Schreibzugriffe und Änderungen landen im oberen (upper) Verzeichnis
    • OverlayFS benötigt ein leeres "Arbeitsverzeichnis" um temporär Daten abzulegen (workdir)
  • Einsatzgebiete
    • Live-Linux-CD-Roms
    • Container-Image-Installationen
    • Ephermal (verwerfbare) Konfigurationen -> Systeme, die immer mit dem gleichen Ausgangszustand starten (Digital Signage, Kiosk-PCs, Anzeigetafeln etc)
    • Delta zwischen Installationen herausfinden (Software-Paketierung, Dokumentation)
    • Dateisystem-Delta bei Rechner-Einbrüchen erstellen

15.1 Beispiel: OverlayFS mounten

  • erstellen der Verzeichnisse. /srv/etc-ro wird das untere (lower) nur-lese Verzeichnis. /srv/etc wird der Mount-Point für das vereinte Verzeichnis, /srv/overlayfs-work ist das Arbeitsverzeichnis des OverlayFS (muss auf dem gleichen Dateisystem liegen wie das obere Verzeichnis)
mkdir /srv/etc-ro
mkdir /srv/etc-rw
mkdir /srv/etc
mkdir /srv/overlayfs-work
  • ein paar Daten in das untere (lower) Verzeichnis kopieren
cp -a /etc/* /srv/etc-ro/
  • OverlayFS mounten
mount -t overlay overlay \
   -o lowerdir=/srv/etc-ro,upperdir=/srv/etc-rw,workdir=/srv/overlayfs-work \
   /srv/etc
  • Verzeichnisse anschauen
ls -l /srv/etc
ls -l /srv/etc-rw
ls -l /srv/overlayfs-work
  • eine Datei verändern
$EDITOR /srv/etc/motd
  • Dateien in den Verzeichnissen anschauen
cat /srv/etc/motd
cat /srv/etc-ro/motd
cat /srv/etc-rw/motd

15.2 Ausgabe - weitere Forschung:

Finde heraus, wie sich die Schichten des OverlayFS bei den folgenden Dateisystem-Aktionen verhalten:

  • was passiert, wenn eine Datei gelöscht wird?
  • was passiert, wenn unter /srv/etc/ ein Verzeichnis erstellt wird?
  • was passiert, wenn unter /srv/etc/ ein Verzeichnis gelöscht wird, welches in /srv/etc-ro existiert?
  • was passiert, wenn ein Verzeichnis umbenannt wird?

15.3 Anwendung für Container-Images

  • aus dem Basis-Debian Container-Verzeichnis erstellen wir ein Verzeichnis per OverlayFS, in dem wir nur die Änderungen für einen nginx Webserver speichern
  • ein installiertes Debian-Root-Verzeichnis existiert schon in /srv/container/debian
  • Verzeichnisse erstellen
mkdir /srv/container/debian-nginx
mkdir /srv/container/debian-nginx-work
mkdir /srv/container/debian-nginx-delta
  • Dateisysteme mounten (hier umgebrochen, damit der Befehl auf die Seite passt)
mount -t overlay overlay -o lowerdir=/srv/container/debian, \
  upperdir=/srv/container/debian-nginx-delta, \
  workdir=/srv/container/debian-nginx-work /srv/container/debian-nginx
  • Dateisysteme mounten (gleicher Befehl wie zuvor, nun aber alles in einer Zeile zum Kopieren über die Zwischenablage)
mount -t overlay overlay -o lowerdir=/srv/container/debian,upperdir=/srv/container/debian-nginx-delta,workdir=/srv/container/debian-nginx-work /srv/container/debian-nginx
  • Container starten auf dem neuen OverlayFS starten
systemd-nspawn -bD /srv/container/debian-nginx
  • den nginx Webserver installieren, anschalten und starten
apt update
apt upgrade
apt install nginx
systemctl enable --now nginx
  • Container stoppen (im Container)
poweroff
  • die OverlayFS Verzeichnisse anschauen

15.4 Weitere Optionen

  • OverlayFS funktioniert auch über Netzwerklaufwerke, solange die Netzwerklaufwerke das Erstellen von Character-Device-Dateien erlauben
  • OverlayFS in der fstab. Die Option noauto,x-systemd.automount verhindert das Systemd das OverlayFS schon beim Systemstart einbindet. Die Option automount sorgt dafür, das das OverlayFS beim ersten Zugriff auf das Verzeichnis /merged eingehangen wird
overlay /merged overlay noauto,x-systemd.automount,lowerdir=/lower,upperdir=/upper,workdir=/work 0 0
  • OverlayFS mit mehreren unteren (lower) Verzeichnissen. Wenn "upperdir" und "workdir" nicht angegeben werden, dann ist das Zielverzeichnis auch nur-lesbar.
mount -t overlay overlay -o lowerdir=/lower1:/lower2:/lower3 /merged

16 SSHFS (FUSE)

  • SSHFS ist ein virtuelles Dateisystem auf Basis von SSH-Verbindungen
  • SSHFS erlaubt es, Dateisystem anderer Linux/Unix Rechner über SSH (und damit das Netzwerk) lokal einzuhängen
  • die Datenübertragung ist dabei per SSH verschlüsselt und abgesichert
  • SSHFS eignet sich als Ad-Hoc Mount für entfernte Dateisysteme, jedoch nicht als Ersatz für NFS oder SMB/CIFS.
  • Das Paket fuse-sshfs befindet sich im PowerTools Repository
dnf config-manager --set-enabled PowerTools
dnf update
dnf install fuse-sshfs
  • Anhängen eines entfernten Rechners (mount)
sshfs benutzer@domain-oder-ip:<pfad-auf-entferntem-Rechner>  /<mount-verzeichnis>
  • der SSHFS Befehl versteht viele Optionen des ssh Kommandos (Kompression bei der Übertragung etc)
  • Aushängen eines SSHFS Dateisystems einfach per umount
umount /<mount-verzeichnis>

17 Einfache IPSec-VPNs mit LibreSWAN – opportunistisches VPN

17.1 per x509 Zertifikat von Let's Encypt

  • LibreSwan, die IPSEC/IKE2 Implementierung in RedHat 8, unterstützt opportunistisches VPN mit Let's Encrypt Zertifikaten
  • bei opportunistischem VPN wird erst eine VPN Verschlüsselung probiert, wenn diese nicht zustandekommt wird unverschlüsselt gesprochen
  • bei dem opportunistischem Modus wird der Server von Client authentisiert, aber nicht der Client vom Server (ähnlich wie bei TLS/HTTPS)
  • alternativ unterstützt LibreSwan auch ein Mesh-VPN mit Let's Encrypt Zertifikaten. Bei diesem Modus authentisieren sich beide Seiten per x509 Zertifikat.

17.2 Server (clear-or-private)

  • wir arbeiten im Internet auf der VM aXX.dane.onl via Cockpit (Port 9090)
  • Benutzername nutzer, Passwort villa
  • Installation der benötigten Softwarepakete
dnf install git socat libreswan bind-utils
  • das ACME Zertifikat wird mit dem Shell-Skript acme.sh angefordert
  • acme.sh per git aus dem Repository laden
git clone https://github.com/Neilpang/acme.sh
  • acme.sh installieren
cd acme.sh
./acme.sh --install --cert-home /etc/tls --home /etc/acme
  • Port 80 für die Kommunikation mit Let's Encrypt freischalten
# firewall-cmd --add-service="http" --permanent
# firewall-cmd --reload
  • Test: ein Zertifikat für den Namen aXX.dane.onl per standalone Webservice anfordern (Port 80 auf dem Server muss frei sein)
cd ~
source ~/.bashrc
acme.sh  --issue  -d aXX.dane.onl  --standalone --cert-home /etc/tls
[Sat Feb 29 10:54:21 UTC 2020] Standalone mode.
[Sat Feb 29 10:54:21 UTC 2020] Single domain='aXX.dane.onl'
[Sat Feb 29 10:54:22 UTC 2020] Getting domain auth token for each domain
[Sat Feb 29 10:54:24 UTC 2020] Getting webroot for domain='aXX.dane.onl'
[Sat Feb 29 10:54:24 UTC 2020] Verifying: oe1.dane.onl
[Sat Feb 29 10:54:24 UTC 2020] Standalone mode server
[Sat Feb 29 10:54:28 UTC 2020] Success
[Sat Feb 29 10:54:28 UTC 2020] Verify finished, start to sign.
[Sat Feb 29 10:54:28 UTC 2020] Lets finalize the order, Le_OrderFinalize: https://acme-v02.api.letsencrypt.org/acme/finalize/79357257/2482192265
[Sat Feb 29 10:54:29 UTC 2020] Download cert, Le_LinkCert: https://acme-v02.api.letsencrypt.org/acme/cert/03053523225ecddb768abe8381a834ef13e0
[Sat Feb 29 10:54:30 UTC 2020] Cert success.
-----BEGIN CERTIFICATE-----
MIIFTzCCBDegAwIBAgISAwU1IyJezdt2ir6Dgag07xPgMA0GCSqGSIb3DQEBCwUA
MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD
ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0yMDAyMjkwOTU0MjlaFw0y
[...]
VniqleXfkuSZFUzyLlQxmt1pjq8HERHQRGYzdy3LX/Rj35yJ/71gfy+K06BoL+sx
5pJdehKSelTtiOkZ+bP5kBCTs+DHbAs20x098bIBB1XWhyv/8vDKLb01GPJnArPL
YKBCbB00oKMfMpxKYRXVa6ejzAKNDhYmIgTYESZ8rKBtakHvRQI6WnLB0zunfHBE
66rLAVn7OKupPXRouN5e0IFRKA==
-----END CERTIFICATE-----
[Sat Feb 29 10:54:30 UTC 2020] Your cert is in  /etc/tls/aXX.dane.onl/aXX.dane.onl.cer
[Sat Feb 29 10:54:30 UTC 2020] Your cert key is in  /etc/tls/aXx.dane.onl/aXX.dane.onl.key
[Sat Feb 29 10:54:30 UTC 2020] The intermediate CA cert is in  /etc/tls/aXX.dane.onl/ca.cer
[Sat Feb 29 10:54:30 UTC 2020] And the full chain certs is there:  /etc/tls/aXX.dane.onl/fullchain.cer
  • x509-Zertifikat in eine p12 Zertifikatsdatei wandeln
# openssl pkcs12 -export -inkey /etc/tls/aXX.dane.onl/aXX.dane.onl.key \
    -in /etc/tls/aXX.dane.onl/aXX.dane.onl.cer \
    -name aXX.dane.onl \
    -certfile /etc/tls/aXX.dane.onl/fullchain.cer \
    -out aXX.dane.onl.p12
  • IPSec (NSS) Zertifikatsdatenbank erstellen
# ipsec initnss
Initializing NSS database
  • die p12 Zertifikatsdatei in die Zertifikatsdatenbank von LibreSwan importieren
# ipsec import aXX.dane.onl.p12
Enter password for PKCS12 file:
pk12util: PKCS12 IMPORT SUCCESSFUL
  • die Vorlage der Server-Konfigurationsdatei für opportunistische Verschlüsselung (OE = opportunistic encryption) kopieren
# cp /usr/share/doc/libreswan/examples/oe-letsencrypt-server.conf /etc/ipsec.d/
  • die Konfigurationsdatei anpassen, den Namen des eigenen Servers eintragen
[...]
	leftcert=aXX.dane.onl
[...]
  • IPSec Policy anpassen. Wir wollen das jede beliebige IP-Adresse (0.0.0.0/0) die Verbindung starten kann. Policy ist clear-or-private, d.h. wenn die Gegenstelle IPSec startet, dann wird verschlüsselt, ansonsten wird unverschlüssel kommuniziert
echo "0.0.0.0/0" >> /etc/ipsec.d/policies/clear-or-private
  • IPSec (neu-) starten um die neue Konfiguration zu aktivieren
# systemctl enable --now ipsec
  • IPSec Statusmeldungen anzeigen
journalctl -fu ipsec

17.3 Client (private-or-clear)

  • wir arbeiten im Internet auf der VM bXX.dane.onl via Cockpit (Port 9090)
  • Pakete auf der Client-Seite installieren. Wir benutzen den DNS-Resolver Unbound, um lokale DNSSEC-Validierung zu bekommen
dnf install libreswan unbound
  • Unbound aktivieren und starten
# systemctl enable --now unbound
  1. Lokale DNS-Resolver Konfiguration
    • Netzwerkkonfigurationen des Netzwerkmanagers auflisten
    # nmcli con show
    NAME         UUID                                  TYPE      DEVICE
    System eth0  5fb06bd0-0bb0-7ffb-45f1-d6edd65f3e03  ethernet  eth0
    
    • DNS Konfiguration manuell auf die Loopback-Adressen (Unbound DNS-Resolver) festlegen
    # nmcli con mod "System eth0" ipv4.ignore-auto-dns yes
    # nmcli con mod "System eth0" ipv6.ignore-auto-dns yes
    # nmcli con mod "System eth0" ipv4.dns "127.0.0.1"
    # nmcli con mod "System eth0" ipv6.dns "::1"
    
    • Networkmanager Konfiguration neu ausrollen
    # nmcli con down "System eth0" && nmcli con up "System eth0"
    
    • prüfen, das die Konfiguration erfolgreich übernommen wurde
    # cat /etc/resolv.conf
    nameserver 127.0.0.1
    nameserver ::1
    
    • wenn die Änderung der DNS-Konfiguration nicht funktioniert (nicht für Produktions-Umgebungen empfohlen!):
    echo "nameserver 127.0.0.1" > /etc/resolv.conf
    chattr +i /etc/resolv.conf
    
    • DNS Abfrage mit DNSSEC testen (AD-Flag!)
    # dnf install bind-utils
    # dig dnssec.works +adflag +multi
    
    ; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.el8 <<>> dnssec.works +adflag +multi
    ;; global options: +cmd
    ;; Got answer:
    ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 25162
    ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
    
    ;; OPT PSEUDOSECTION:
    ; EDNS: version: 0, flags:; udp: 4096
    ;; QUESTION SECTION:
    ;dnssec.works.          IN A
    
    ;; ANSWER SECTION:
    dnssec.works.           3600 IN A 5.45.107.88
    
    ;; Query time: 17 msec
    ;; SERVER: 127.0.0.1#53(127.0.0.1)
    ;; WHEN: Sat Feb 29 04:04:58 UTC 2020
    ;; MSG SIZE  rcvd: 57
    
  2. IPSec/LibreSwan Konfiguration
    • IPSec (NSS) Zertifikatsdatenbank erstellen
    # ipsec initnss
    Initializing NSS database
    
    # dnf install wget
    # wget https://letsencrypt.org/certs/isrgrootx1.pem.txt
    # wget https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem.txt
    # wget https://letsencrypt.org/certs/lets-encrypt-x4-cross-signed.pem.txt
    # wget https://letsencrypt.org/certs/trustid-x3-root.pem.txt
    
    • die Zertifikate in die IPSEC Datenbank importieren, damit den Let's Encrypt Zertifikaten vertraut wird. LibreSwan benutzt nicht die Zertifikatsdatenbank des Betriebssystems (welche z.B. der Browser benutzt), sondern hat eine eigene Datenbank die manuell verwaltet wird.
    # certutil -A -i lets-encrypt-x3-cross-signed.pem.txt -n lets-encrypt-x3 -t CT,, -d sql:/etc/ipsec.d
    # certutil -A -i lets-encrypt-x4-cross-signed.pem.txt -n lets-encrypt-x4 -t CT,, -d sql:/etc/ipsec.d
    # certutil -A -i isrgrootx1.pem.txt -n isrgrootx1 -t CT,, -d sql:/etc/ipsec.d
    # certutil -A -i trustid-x3-root.pem.txt -n trustid-x3 -t CT,, -d sql:/etc/ipsec.d
    
    • IP-Adresse der Gegenstelle in die Richtliniendatei private-or-clear eintragen. Bei dieser Richtlinie wird erst versucht eine VPN-Verbindung aufzubauen, wenn die nicht klappt, wird unverschlüsselt kommuniziert (Fail-Open):
    # echo "w.x.y.z/32" >> /etc/ipsec.d/policies/private-or-clear
    
    • die Konfigurations-Datei /etc/ipsec.d/oe-le-client.conf für LibreSwan erstellen:
    # See https://libreswan.org/wiki/HOWTO:_Opportunistic_IPsec_using_LetsEncrypt
    #
    conn private-or-clear
    	rightid=%fromcert
    	rightrsasigkey=%cert
    	rightauth=rsasig
    	right=%opportunisticgroup
    	rightmodecfgclient=yes
    	rightcat=yes
    	# Any CA will do because we only load the LetsEncrypt CA
    	rightca=%any
    	#
    	left=%defaultroute
    	leftid=%null
    	leftauth=null
    	leftmodecfgclient=yes
    	leftcat=yes
    	#
    	narrowing=yes
    	type=tunnel
    	ikev2=insist
    	negotiationshunt=drop
    	failureshunt=passthrough
    	keyingtries=1
    	retransmit-timeout=3s
    	auto=ondemand
    
    • IPSec starten
    # systemctl enable --now ipsec
    
    • Test der Verbindung
    ping -4 -c4 aXX.dane.onl
    
    • Log-Meldungen auf der Server Seite
    Feb 29 11:55:04 oe1 pluto[13677]: "clear-or-private#0.0.0.0/0"[1] ...209.250.233.90 #1: processing IKE_SA_INIT request: SA,KE,Ni,N,N,N (message arrived 0 seconds ago)
    Feb 29 11:55:04 oe1 pluto[13677]: "clear-or-private#0.0.0.0/0"[1] ...209.250.233.90: constructed local IKE proposals for clear-or-private#0.0.0.0/0 (IKE SA responder matching remote proposals): 1:IKE:ENCR=AES_GCM_C_256;PRF=HMAC_SHA2_512,HMAC_SHA2_256;INTEG=NONE;DH=ECP_256,ECP_384,ECP_521,MODP2048,MODP3072,MODP4096,MODP8192 2:IKE:ENCR=CHACHA20_POLY1305;PRF=HMAC_SHA2_512,HMAC_SHA2_256;INTEG=NONE;DH=ECP_256,ECP_384,ECP_521,MODP2048,MODP3072,MODP4096,MODP8192 3:IKE:ENCR=AES_CBC_256;PRF=HMAC_SHA2_512,HMAC_SHA2_256;INTEG=HMAC_SHA2_512_256,HMAC_SHA2_256_128;DH=ECP_256,ECP_384,ECP_521,MODP2048,MODP3072,MODP4096,MODP8192 4:IKE:ENCR=AES_GCM_C_128;PRF=HMAC_SHA2_512,HMAC_SHA2_256;INTEG=NONE;DH=ECP_256,ECP_384,ECP_521,MODP2048,MODP3072,MODP4096,MODP8192 5:IKE:ENCR=AES_CBC_128;PRF=HMAC_SHA2_256;INTEG=HMAC_SHA2_256_128;DH=ECP_256,ECP_384,ECP_521,MODP2048,MODP3072,MODP4096,MODP8192
    Feb 29 11:55:04 oe1 pluto[13677]: "clear-or-private#0.0.0.0/0"[1] ...209.250.233.90 #1: processing encrypted IKE_AUTH request: SK (message arrived 0 seconds ago)
    Feb 29 11:55:04 oe1 pluto[13677]: "clear-or-private#0.0.0.0/0"[1] ...209.250.233.90 #1: processing decrypted IKE_AUTH request: SK{IDi,AUTH,SA,TSi,TSr}
    Feb 29 11:55:04 oe1 pluto[13677]: "clear-or-private#0.0.0.0/0"[1] ...209.250.233.90 #1: Authenticated using authby=null
    Feb 29 11:55:04 oe1 pluto[13677]: "clear-or-private#0.0.0.0/0"[1] ...209.250.233.90: constructed local ESP/AH proposals for clear-or-private#0.0.0.0/0 (IKE_AUTH responder matching remote ESP/AH proposals): 1:ESP:ENCR=AES_GCM_C_256;INTEG=NONE;DH=NONE;ESN=DISABLED 2:ESP:ENCR=CHACHA20_POLY1305;INTEG=NONE;DH=NONE;ESN=DISABLED 3:ESP:ENCR=AES_CBC_256;INTEG=HMAC_SHA2_512_256,HMAC_SHA1_96,HMAC_SHA2_256_128;DH=NONE;ESN=DISABLED 4:ESP:ENCR=AES_GCM_C_128;INTEG=NONE;DH=NONE;ESN=DISABLED 5:ESP:ENCR=AES_CBC_128;INTEG=HMAC_SHA1_96,HMAC_SHA2_256_128;DH=NONE;ESN=DISABLED
    Feb 29 11:55:04 oe1 pluto[13677]: "clear-or-private#0.0.0.0/0"[1] ...209.250.233.90 #2: negotiated connection [108.61.189.206-108.61.189.206:0-65535 0] -> [209.250.233.90-209.250.233.90:0-65535 0]
    
    • Log-Meldungen auf der Client Seite
    # journalctl -fu ipsec
    Feb 29 11:55:04 oe2 pluto[4957]: "private-or-clear#108.61.189.206/32"[2] ...108.61.189.206: constructed local IKE proposals for private-or-clear#108.61.189.206/32 (IKE SA initiator selecting KE): 1:IKE:ENCR=AES_GCM_C_256;PRF=HMAC_SHA2_512,HMAC_SHA2_256;INTEG=NONE;DH=ECP_256,ECP_384,ECP_521,MODP2048,MODP3072,MODP4096,MODP8192 2:IKE:ENCR=CHACHA20_POLY1305;PRF=HMAC_SHA2_512,HMAC_SHA2_256;INTEG=NONE;DH=ECP_256,ECP_384,ECP_521,MODP2048,MODP3072,MODP4096,MODP8192 3:IKE:ENCR=AES_CBC_256;PRF=HMAC_SHA2_512,HMAC_SHA2_256;INTEG=HMAC_SHA2_512_256,HMAC_SHA2_256_128;DH=ECP_256,ECP_384,ECP_521,MODP2048,MODP3072,MODP4096,MODP8192 4:IKE:ENCR=AES_GCM_C_128;PRF=HMAC_SHA2_512,HMAC_SHA2_256;INTEG=NONE;DH=ECP_256,ECP_384,ECP_521,MODP2048,MODP3072,MODP4096,MODP8192 5:IKE:ENCR=AES_CBC_128;PRF=HMAC_SHA2_256;INTEG=HMAC_SHA2_256_128;DH=ECP_256,ECP_384,ECP_521,MODP2048,MODP3072,MODP4096,MODP8192
    Feb 29 11:55:04 oe2 pluto[4957]: "private-or-clear#108.61.189.206/32"[2] ...108.61.189.206: constructed local ESP/AH proposals for private-or-clear#108.61.189.206/32 (IKE SA initiator emitting ESP/AH proposals): 1:ESP:ENCR=AES_GCM_C_256;INTEG=NONE;DH=NONE;ESN=DISABLED 2:ESP:ENCR=CHACHA20_POLY1305;INTEG=NONE;DH=NONE;ESN=DISABLED 3:ESP:ENCR=AES_CBC_256;INTEG=HMAC_SHA2_512_256,HMAC_SHA1_96,HMAC_SHA2_256_128;DH=NONE;ESN=DISABLED 4:ESP:ENCR=AES_GCM_C_128;INTEG=NONE;DH=NONE;ESN=DISABLED 5:ESP:ENCR=AES_CBC_128;INTEG=HMAC_SHA1_96,HMAC_SHA2_256_128;DH=NONE;ESN=DISABLED
    Feb 29 11:55:04 oe2 pluto[4957]: "private-or-clear#108.61.189.206/32"[2] ...108.61.189.206 #3: loading root certificate cache
    Feb 29 11:55:04 oe2 pluto[4957]: "private-or-clear#108.61.189.206/32"[2] ...108.61.189.206 #3: certificate verified OK: CN=oe1.dane.onl
    Feb 29 11:55:04 oe2 pluto[4957]: "private-or-clear#108.61.189.206/32"[2] ...108.61.189.206 #3: Authenticated using RSA
    Feb 29 11:55:04 oe2 pluto[4957]: "private-or-clear#108.61.189.206/32"[2] ...108.61.189.206 #3: negotiated connection [209.250.233.90-209.250.233.90:0-65535 0] -> [108.61.189.206-108.61.189.206:0-65535 0]
    
    • IPSec Kommunikation kann per tcpdump betrachtet werden
    tcpdump -n -i eth0 esp or udp port 500 or udp port 4500
    

18 Systemd Updates

18.1 DNS

  • systemd-resolved antwortet auf die Anfragen zu den Namen _gateway (lokales Netzwerk-Gateway), localhost und den eigenen Hostnamen.
[root@centos-2gb-nbg1-1 ~]# dig @127.0.0.53 centos-2gb-nbg1-1 +short
127.0.0.1
[root@centos-2gb-nbg1-1 ~]# dig @127.0.0.53 _gateway +short
172.31.1.1
  • systend-nspawn macht die Datei /etc/resolv.conf des Hosts per Bind-Mount im Container verfügbar. Der Container hat damit die gleiche DNS-Stub-Resolver Konfiguration wie der Host
  • systemd-resolved erstellt dynamisch die DNS-Stub-Konfigurations-Datei /run/systemd/resolve/stub-resolv.conf. Um systemd-resolved als Systemd-Resolver zu benutzen kann die Datei /etc/resolv.conf ein (symbolischer-) Link auf diese Datei sein.
# cat  /run/systemd/resolve/stub-resolv.conf 
# This file is managed by man:systemd-resolved(8). Do not edit.
#
# This is a dynamic resolv.conf file for connecting local clients to the
# internal DNS stub resolver of systemd-resolved. This file lists all
# configured search domains.
#
# Run "resolvectl status" to see details about the uplink DNS servers
# currently in use.
#
# Third party programs must not access this file directly, but only through the
# symlink at /etc/resolv.conf. To manage man:resolv.conf(5) in a different way,
# replace this symlink by a static file or a different symlink.
#
# See man:systemd-resolved.service(8) for details about the supported modes of
# operation for /etc/resolv.conf.

nameserver 127.0.0.53

18.2 System-Management

  • systemctl kill hat nun ein --fail Parameter. Damit gibt der Befehl einen Fehlercode zurück, wenn kein Prozess gekillt werden konnte (weil z.B. die Unit keinen Prozess gestartet hatte)
  • Der Befehl systemctl exit (benutzt z.B. um Systemd-nspawn Container zu verlassen) nimmt nun optional einen Exit-Code als Rückgabewert.
  • Zeit-Konfigurationsparameter in Unit-Dateien verstehe den Wert infinity. In RHEL7/CentOS 7 wurde der Wert 0 für "unendlich" benutzt. Der Wert 0 bedeutet nun "sofort".
  • der Befehl systemctl revert setzt eine Unit auf den Auslieferungszustand zurück, alle manuellen Änderungen werden verworfen
  • Die Unit-Optionen MemoryLimit und TasksMax können jetzt auch Prozentwerte entgegennehmen
  • systemctl und systemd-run besitzen nun einen neuen Parameter --wait welcher die Befehle veranlasst, zu warten bis die gestartete Unit wieder beendet wurde
  • Systemd-Units haben nun einen internen Zähler NRestarts welcher angibt, wie oft eine Unit automatisch neu gestartet wurde
# systemctl show -p NRestarts systemd-resolved
NRestarts=1
  • systemd-analyze hat den Sub-Befehl cat-config, dieser Sub-Befehl gibt eine Systemd-Konfigurationsdatei inkl. aller drop-in Änderungen aus (so wie Systemd die Konfigurationsdatei "sieht"). Die Befehle systemd-tmpfiles und systemd-sysusers haben die ähnliche Option --cat-config bekommen
# systemd-analyze cat-config systemd/journald.conf
  • Units mit Syntax-Fehlern in der Unit-Datei bekommen nun den Status bad-setting
  • Programmnamen in der Option ExecStart in Unit-Dateien müssen nicht mehr mit vollem Pfad angegeben werden. Die Dateien werden in einem Systemd-internen Suchpfad gesucht. Dieser Pfad kann mittels systemd-path search-binaries-default abgefragt werden
  • besitzt eine Unit-Datei Bindestriche/Minus im Dateinamen, so werden Drop-In Dateien hierarchisch gesucht. Heisst die Unit foo-bar-baz.service, so werden Drop-Ins in foo-bar-baz.service.d/*.conf (Default) und zusätzlich in "foo-bar-.service.d/*.conf und foo-.service.d/ gesucht.

18.3 Systemstart

  • es gibt einen eigenen (EFI-)Bootloader in Systemd mit dem Namen systemd-boot (früher Gummiboot). Mit dem Befehl bootctl list kann die (EFI) Boot-Konfiguration ausgegeben werden.
  • systemctl reboot --firmware-setup bootet den Rechner in das EFI Setup Programm
  • systemctl reboot hat nun einen Schalter --message um eine Meldung an die angemeldeten Benutzer zu senden
  • Wenn Systemd (PID 1) beim Systemstart bemerkt das das Systemdatum vor dem Release der Systemd-Version liegt, so wird das Datum auf das Systemd-Release-Datum gesetzt
  • Über die Einstellung CtrlAltDelBurstAction in der Konfigurationsdatei /etc/systemd/system.conf kann definiert werden, was passiert wenn der Benutzer mehr als 7 mal innerhalb von 2 Sekunden die Tastenkombination Ctrl-Alt-Del drückt

18.4 Timer

  • Timer-Units haben eine neue Einstellung RemainAfterElapse welche angibt, wie lange die Unit im System nach dem Beenden noch sichtbar sein soll (damit ein Benutzer den Status abfragen kann)
  • Zeiten in Timer-Units können nun Intervalle mit den Zeichen ".." definieren. Beispiel: "4..7:10" veranlasst den Timer um 4:10, 5:10, 6:10 und 7:10 jeden Tag zu starten
  • der Befehl timedatectl show gibt die Konfiguration des Dienstes systemd-timedated aus
# timedatectl show
Timezone=Europe/Berlin
LocalRTC=no
CanNTP=yes
NTP=yes
NTPSynchronized=yes
TimeUSec=Thu 2020-03-05 07:40:57 CET
RTCTimeUSec=Thu 2020-03-05 07:40:57 CET

18.5 Verschiedenes

systemd-socket-activate -l 2000 --inetd -a cat
systemd-socket-activate -l 19531 /usr/lib/systemd/systemd-journal-gatewayd
  • bei Socket-Units kann die Anzahl der Verbindungen von einer Quelle (IP-Adresse) limitiert werden: MaxConnectionsPerSource
  • systemd-socket-proxyd hat den neuen Parameter --connections-max um die maximale Anzahl gleichzeitiger Verbindungen zu konfigurieren
  • systemd-run hat nun die Parameter --pipe um die Ausgaben der Ad-Hoc Unit über Standard-Eingabe/Ausgabe/Fehler-Kanal an die Shell weiterzugeben. Damit können diese Systemd-Units in Shell-Pipelines verwendet werden

18.6 Socket-Proxy mit "systemd-socket-proxyd"

  • systemd-socket-proxyd ist eine Socket-Proxy Komponente, um Daten zwischen IPv4, IPv6 und Unix-Domain-Sockets zu verbinden
  • ermöglicht es, Programme, welche nur Unix-Domain-Sockets anbieten, über das Netzwerk anzusprechen (Sicherheit beachten, Zugriff einschränken, ggf. Verschlüsseln!)
  • ermöglicht es, IPv4 auf IPv6 oder IPv6 af IPv4 umzusetzen
  • kann Socket-Proxy-Lösungen mit netcat, nc oder socat ersetzen
  • Aktivierung von systemd-socket-proxyd über eine Socket-Unit und eine Service-Unit
  • Beispiel IPv4 auf IPv6 Umsetzung: der Webserver ist in einem IPv6-only Netwerk unter der Adresse 2001:db8::80 erreichbar. Der Socket-Proxy-Server nimmt Anfragen auf Port 80 auf der IPv4-Adresse 192.0.2.6 an und startet die Service-Unit welche per systemd-socket-proxyd die Verbindung an den IPv6-Webserver herstellt.
    • Socket Unit
[Socket]
ListenStream=192.0.2.6:80

[Install]
WantedBy=sockets.target
  • Service Unit
[Unit]
Requires=web-ipv4-to-ipv6.socket
After=web-ipv4-to-ipv6.socket

[Service]
ExecStart=/usr/lib/systemd/systemd-socket-proxyd [2001:db8::80]:80
PrivateTmp=yes

18.6.1 Aufgabe:

  • arbeite auf dem Laptop
  • Erstelle einen Podman Container mit einem Apache Webserver
  • Mappe ein externes Verzeichnis mit einer eigenen HTML-Seite in den Pfad des Webservers
  • der Container soll nur per localhost Port 8080 erreichbar sein
  • schreibe eine Service-Unit mit systemd-socket-proxyd, welcher auf Port 8080 auf localhost (den Container) verbindet
  • schreibe eine Socket-Activation Unit für IPv4, welche auf Port 80 horcht und die Service-Unit aktiviert
  • schreibe eine Socket-Activation Unit für IPv6, welche auf Port 80 horcht und die Service-Unit aktiviert
  • teste die Verbindung per IPv4, IPv6 und Domain-Name vom Browser. Erscheint die HTML-Seite?

18.6.2 Lösung

  • Podman Image laden
podman pull docker.io/library/httpd
  • Verzeichnis für Webseite erstellen
mkdir -p /srv/container/daten/webseite
  • HTML Seite erstellen
echo "Dies ist meine Webseite" > /srv/container/daten/webseite/index.html
  • Podman Container starten
podman run -d --name webserver -p 127.0.0.1:8080:80 \
   -v /srv/container/daten/webseite:/usr/local/apache2/htdocs \
   docker.io/library/httpd
  • Socket Unit unter /etc/systemd/system/webserver.socket
[Socket]
ListenStream=80

[Install]
WantedBy=sockets.target
  • Service Unit unter /etc/systemd/system/webserver.service
[Unit]
Requires=webserver.socket
After=webserver.socket

[Service]
ExecStart=/usr/lib/systemd/systemd-socket-proxyd 127.0.0.1:8080
  • Systemd Konfiguration neu starten und Socket-Unit starten
systemctl daemon-reload
systemctl enable --now webserver.socket
  • per Web-Browser die Webseite testen

19 nftables

19.1 "nftables" vs. "iptables"

  • iptables ist fragmentiert, mehrere Kommandos mit sehr ähnlicher Funktion -> Code-Duplizität
    • iptables
    • ip6tables
    • arptables
    • ebtables
  • nftables vereint diese Funktionen in einem Werkzeug

19.2 "nftables" vs. "iptables"

  • bei iptables gibt es eine "Race-Condition"-Gefahr durch das Fehlen eines Regelsatz-Kompilers
    • iptables hat kein eigenes Konfigurationsformat für Firewall-Regeln
    • das Regelwerk wird über Aufrufe des iptables Kommandos aufgebaut.
  • bei nftables können die Regeln in einer Regelsatz-Datei definiert und per Transaktion in den Kernel geladen werden

19.3 "nftables" vs. "iptables"

  • iptables Regelwerke werden durch Shell-Scripte aufgebaut
    • erhöhte Komplexitaet für Firewall-Administratoren mit geringem Shell-Scripting-Wissen
  • die Regel-Beschreibungsprache von nftables ist einfach(er) lesbar

19.4 iptables im Kernel

  • iptables-Firewall ist durch statische Kernel-Module für die Haupt-Funktionen und Erweiterungen implementiert
  • Diese Module benutzen das gleiche Kernel-Framework (netfilter), duplizieren aber einen nicht unerheblichen Teil der Firewall-Funktionen in jedem Modul

19.5 nftables im Kernel

  • nftables implementiert die Firewall-Funktionalität durch eine generische Virtuelle-Maschine im Kernel
    • Die virtuelle Maschine wird von dem Kommandozeilen-Tool nft mit Bytecode geladen
    • Der Bytecode ist ein Repräsentation der Firewall-Regeln als ausführbares Programm für die nftables-VM
    • Der Bytecode wird ausserhalb des Kernels erzeugt und in die nftables-VM des Kernels geladen
    • Neue Firewall-Funktionen können so unabhähngig von der Kernel-Version realisiert werden

19.6 Der nft Befehl

  • nft verwaltet die nftables-Firewall.
  • Anders als das iptables Kommando werden die Firewall-Regeln nicht durch Kommandozeilen-Parameter angegeben, sondern in der nftables-eigenen Beschreibungssprache für Firewall-Regeln.
    • Diese Beschreibungssprache funktioniert ein wenig wie eine kleine Programmiersprache.

19.7 Der nft Befehl

  • Neben Definitionen von Firewall-Regeln nimmt nft auch Befehle entgegen
    • löschen einer Regel
    • löschen des gesamten Regelsatzes
    • Export der aktiven Regeln in eine Datei

19.8 Der nft Befehl

  • nft kann Regeln aus einer Datei, von der Kommando-Zeile (Shell) oder in einem interaktiven Modus direkt vom der Tastatur einlesen.
  • Da die Beschreibungssprache Zeichen beinhalten kann, welche in Unix-Shells besondere Bedeutungen haben, müssen diese Zeichen, oder besser der gesamte nft Befehlsteil, per Quoting vor dem Zugriff der Shell geschützt werden.

19.9 Der nft Befehl

  • Beispiel: Lesen der Firewall-Regeln aus einer Datei
# nft -f /etc/nftables/firewall.nft
  • Beispiel: Eine Regel (IPv4, Tabelle "fw", Kette "input") hinzufügen
# nft "add rule ip fw input drop"

19.10 Interaktive nft Sitzung

  • Beispiel: eine interaktive nft Sitzung
# nft -ia
nft> list ruleset
table inet workstation-fw {
    chain input {
             type filter hook input priority 0;
    }
}
nft> add rule inet workstation-fw input tcp dport {ssh, http} accept
nft> list ruleset
table inet workstation-fw {
    chain input {
             type filter hook input priority 0;
             tcp dport { ssh, http} accept # handle 3
    }
}
nft> quit

19.11 Regeln löschen

  • Der Befehl flush löscht Objekte aus der nftables Kernel-Firewall.
  • Ein flush ruleset löscht die gesamten Firewall-Regeln.
  • Ein flush ruleset sollte am Anfang eines nftables-Regelsatzes stehen:
# nft flush ruleset
  • Über flush chain und flush table können Ketten und Tabellen gelöscht werden.

19.12 Regeln hinzufügen

  • Der Befehl add fügt die Regel immer am Ende der Kette an
  • mit insert kann eine Regel an einer beliebigen Stelle der Kette eingefügt werden.
  • Der Befehl delete löscht eine Regel aus einer Kette. Zum Löschen einer Regel wird das Handle der Regel benötigt, das Handle wird über den Kommandozeilenparameter -a ausgegeben:
# nft -a list ruleset
...
ip6 saddr 2001:db8::/64 # handle 15
...
# nft delete rule inet filter input handle 15

19.13 Monitor

  • Mittels nft monitor können Änderungen in der nftables-Firewall überwacht werden.
  • Der Befehl schreibt Modifikationen im Regelsatz der Firewall als nft-Befehlszeilen (Alternativ als XML oder JSON) auf die Konsole:
# nft monitor
add table inet filter
add chain inet filter input { type filter hook input priority 0; }
add rule inet filter input iif lo accept
add rule inet filter input ct state established,related accept
add rule inet filter input ip6 daddr ff02::1010 udp dport ntp accept
add rule inet filter input ip6 daddr ff02::fb udp dport mdns accept
add rule inet filter input ip daddr 224.0.0.251 udp dport mdns accept
add rule inet filter input ip6 saddr & :: == :: udp dport dhcpv6-client accept
add rule inet filter input udp dport ipp accept
add rule inet filter input ip6 saddr & :: == :: icmpv6 type { nd-neighbor-solicit, nd-router-advert, nd-neighbor-advert} accept
add rule inet filter input ip6 saddr & :: == :: icmpv6 type { echo-reply, echo-request, packet-too-big, destination-unreachable, time-exceeded, param-problem} accept
add rule inet filter input counter packets 0 bytes 0 log prefix "nftables drop: " drop

19.14 Tabellen und Ketten

  • die aus iptables bekannten Konzepte von Tabellen (Tables) und Ketten (Chains) finden sich auch in nftables wieder
  • vordefinierten Tabellen (in iptables 'filter', 'nat' und 'mangle') gibt es im nftables nicht
  • Auch die in iptables vorhandenen Ketten ('input', 'output', 'forward') sucht man vergebens
  • nftables kommt ohne vordefinierte Tabellen und Ketten.
  • Die vordefinierten Ketten in iptables sind ein Performance-Problem bei grossen Datenmengen, da Netzwerkpakete auch durch unbenutze, leere Ketten geschleusst werden.
    • Unter nftables sind nur Tabellen und Ketten aktiv, welche der Administrator definiert hat.

19.15 Tabellen und Ketten

  • In nftables sind Tabellen einfache Container für beliebige Ketten. Eine Tabelle muss einem Protokoll zugewiesen werden (ip = IPv4, arp, ip6 = IPv6, inet = IPv4 und IPv6, bridge).
  • Die Tabellen können beliebige Namen haben, auch wenn in vielen Beispielen im Internet die aus iptables bekannten Namen verwendet werden.

19.16 Tabellen und Ketten

  • Bei den Ketten (Chains) unterscheidet man "base-chains" und "auxiliary chains".
  • Bei den "base-chains" handelt es sich um Ketten, welche in den Paketfluss des Netfilter-Framework eingeklinkt werden.
    • Diese Ketten erhalten Netzwerkpakete aus den Zugriffspunkten (Hooks) des Linux-Kernels.
    • Diese Zugriffspunkte für eine Kette vom Typ "filter" heissen "input", "output" und "forward".
    • Die Konzepte sind von iptables übernommen worden, der Firewall-Administrator hat nun aber mehr Freiraum, die Ketten zu organisieren.

19.17 Beispiel-Tabelle

  • Beispiel einer Tabelle mit zwei (leeren) "filter" Ketten, für "input" und "output":
table inet filter01 {
        chain input01 {
                type filter hook input priority 0;
        }
        chain output01 {
                type filter hook output priority 0;
        }
}

19.18 Base- und Auxiliary-Ketten

  • Mit dem Schlüsselwort hook wird eine Kette mit den Linux-Kernel-Internen Schnittstellen des Netfilter-Frameworks verbunden.
  • Eine Kette mit Verbindung zum den Kernel-Schnittstellen ist eine "base-chain".
  • Zusätzlich zu den "base-chains" kann der Administrator noch beliebig weitere "auxiliary chains" erzeugen.
  • Diese Chains erhalten nur Netzwerkpakete, wenn diese aus einer "base-chain" per goto oder jump Direktive an die "auxiliary chain" verteilt werden:

19.19 Beispiel Base- und Auxiliary-Ketten

table inet filter01 {
        # auxiliary chain 
        chain link-local-aux01 {
                 counter packets 0 bytes 0 log prefix "link-local: " accept
                 # weitere Regeln für link-local IPv6 
                 [...]
        }
        # base chain
        chain input01 {
                type filter hook input priority 0;
                ip6 daddr fe80::/64 jump link-local-aux01
        }
        # base chain
        chain output01 {
                type filter hook output priority 0;
        }

}

19.20 Filter-Regeln

  • Eine Hauptaufgabe einer Firewall ist das Filtern von Netzwerkverkehr.
  • Die nftables-Firewall bietet umfangreiche Möglichkeiten, Netzwerkpakete in Filterregeln auszuwählen:
    • nach Quell- und Ziel-Adressen
    • UDP- und TCP-Ports
    • Meta-Informationen wie
      • Netzwerk-Interfaces
      • Protokolle
      • Hardware-MAC-Adressen
      • VLAN-Informationen
      • Status einer IP-Verbindung (Connection-Tracking)

19.21 Beispiel einer Filter-Regel

  • In diesem Beispiel wird eine Regel der Firewall hinzugefügt.
  • Gefiltert wird nach der IPv6-Zieladdresse daddr ff02::fb und dem UDP-Port dport mdns (Multicast-DNS):
# nft "add rule inet filter input ip6 daddr ff02::fb udp dport mdns accept"
  • Eine Liste der Filter-Optionen findet sich in der man-Page zu nft.

19.22 Verdict Statements

  • Am Ende einer Firewall-Regel wird das Urteil (Verdict) über eine Netzwerk-Verbindung getroffen, das sogennante Verdict-Statement.
  • Es gibt entgültige Urteile, welche die Bearbeitung eines Netzwerkpaketes sofort beenden.
  • Dazu zählen
    • accept (Paket passieren lassen)
    • drop (Paket ohne Rückmeldung an den Sender verwerfen) und
    • reject (mit Rückmeldung verwerfen).

19.23 Verdict Statements

  • Bei reject kann optional die ICMP-Meldung spezifiziert werden, welche an den Sender des Paketes zurückgeliefert wird:
# nft "add rule inet filter input ip6 saddr 2001:db8::/64" \
      "reject with icmpv6 type admin-prohibited"

19.24 Verdict Statements

  • Neben den entgültigen Urteilen kann eine Regel die Bearbeitung eines Paketes auch an anderen Stelle fortsetzen:
    • continue Bearbeitung des Paketes mit die nächsten Regel in der Kette
    • jump <chain> verzweigt die Bearbeitung wie ein Unterprogrammaufruf in eine andere Kette. Am Ende der neuen Kette wird die Bearbeitung in der ursprünglichen Kette weitergeführt.
    • goto <chain> wird direkt in eine andere Kette gesprungen, ohne das die Bearbeitung jemals wieder zurückkehrt.
    • queue verzweigt die Verarbeitung an ein externes Programm im Userspace.
    • return beendet die Bearbeitung der aktuellen Kette an dieser Stelle. Wird return in einer Kette der obersten Bearbeitungsebene verwendet, so wird das Paket durch die Firewall gelassen (identisch zu einem accept).

19.25 Logging und Zaehler

  • Über das Befehlswort log werden Informationen zu dem gerade bearbeiteten Netzwerk-Paket in das Kernel-Log (und damit in den meisten Systemen auch in das System-Log) geschrieben.
  • Der Befehl counter erzeugt einen Zähler für diese Firewall-Regel.

19.26 Logging und Zaehler

  • Anders als bei iptables müssen Counter für Regeln explizit erzeugt werden. Dies hat Performance-Gründe, die Zähler werden nur dann mitgeführt, wenn der Administrator diese im Regelsatz angefordert hat.
  • In dem Zähler werden die Anzahl der gefilterten Pakete und die Datenmenge in Bytes gezählt.
  • Der Zähler wird beim Auflisten des Regelwerkes, z.B. mit list ruleset, ausgegeben.

19.27 Logging und Zaehler

  • Die Position des Befehls log in der Regel wichtig:
    • Steht der Befehl vor der Filter-Bedingung, so wird ein Log-Eintrag für jedes Paket geschrieben, welches von dieser Regel gesehen wird, unabhängig ob die Regel danach aktiv wird oder nicht.
    • Steht jedoch der Befehl log nach der Filterbedingung, so wird der Log-Eintrag nur geschrieben, wenn die Filterbedingung zutrifft.

19.28 Logging und Zaehler

  • Gleiches gilt für die Position des Befehls counter.
# schreibe einen Log-Eintrag für jedes Paket welches von dieser Regel gesehen wird
log tcp dport { 22, 80, 443 } ct state new accept
# schreibe einen Log-Eintrag nur wenn die Regel zutrifft
tcp dport { 22, 80, 443 } ct state new log counter accept
  • Dem Befehl log kann mit dem Parameter prefix eine beliebige Zeichenkette mitgegeben werden.
  • Diese Zeichenkette erscheint vor jeder Log-Meldung und wird benutzt, um Log-Einträge zu finden und zu filtern.

19.29 IPv4 und IPv6 kombinieren

  • Neben den Protokollen ip für IPv4 und ip6 für IPv6 unterstützt nftables auch das Pseudo-Protokoll inet für kombinierte IPv4- und IPv6-Filter.
  • Anstatt z.B. Port 80 für einen Webserver in zwei getrennten Regeln für je IPv4 und IPv6 freizugeben, kann dies in nftables in nur einer Regel geschehen.
  • Bei einem Server mit Dual-Stack und vielen Diensten kann dies das Regelwerk vereinfachen.

19.30 IPv4 und IPv6 kombinieren

  • Für das Protokoll inet muss eine eigene Tabelle mit Chains erstellt werden.
table inet filter {
    chain input { 
       ...
    }
}

19.31 IPv4 und IPv6 kombinieren

  • Die Tabelle mit dem Pseudo-Protokoll inet existiert paralell zu Tabellen mit IPv4- und IPv6-Regeln.
  • Werden Tabellen mit dedizierten IPv4 und IPv6 Regeln genutzt, so müssen die Pakete sowohl in der inet Tabelle als auch in der jeweiligen Tabelle für das IP-Protokoll erlaubt werden.
  • Um Fehler zu vermeiden, sollte entweder kombinierte inet Tabellen, oder protokoll-spezifische Tabellen benutzt werden, aber nicht beides.

19.32 Datenstrukturen

  • nftables bietet verschiedene Datenstrukturen, welche die Erstellung eines Regelwerkes vereinfachen:
    • Variablen
    • Intervalle
    • Sets
    • benannte und anonyme Maps
    • benannte und anonyme Dictionaries/Verdict-Maps

19.33 Variablen

  • Variablen erlauben symbolische Namen für Werte und IP-Adressen in einem nftables-Regelwerk.
  • Variablen sind jeweils in der Umgebung sichtbar, in der sie definiert wurden (Table, Chain).

19.34 Variablen

  • Variablen werden über das Schlüsselwort define deklariert und mit einem Wert versehen.
  • Im Regelwerk wird dann der Variablenname mit einem vorangestellem Dollar-Zeichen "$" verwendet, vergleichbar mit Variablen der Unix-Shell.
define lan_if = eth0
define DMZ-Dienste = { ssh, smtp, dns, http, https }
add rule inet filter input iif $lan_if tcp dport $DMZ-Dienste accept

19.35 Intervalle

  • Intervalle in nftables sind Wertefolgen mit einem Start- und End-Wert. Intervalle werden z.B. für IP-Adresse-Bereiche und TCP/UDP-Port-Bereiche verwendet.
nft "add rule inet filter input ip6 daddr 2001:db8::0-2001:db8::1000 drop"
nft "add rule inet filter input tcp dport 0-1023 drop"

19.36 Sets

  • Sets definieren eine Sammlung von Werten eines gleichen Typs.
  • Ein Set wird durch geschweifte Klammern eingeleitet und die Elemente des Sets werden mit Komma getrennt.
  • Beispiel: Ein anonymes Set mit Port-Nummern (Microsoft SMB/CIFS-Protokoll):
nft "add rule inet filter input udp dport { 137, 138, 139, 445 } reject" 

19.37 Sets

  • Bei der Anlage eines benannten Sets muss nftables der Werte-Typ mitgeteilt werden.
  • Eine (leider noch unvollständige) Liste der verfügbaren Werte-Typen ist in der nft man-Page aufgelistet:
nft "add set inet filter bogus { type ipv4_addr; }"
nft "add element inet filter bogus { 203.0.113.0; }"
nft "add element inet filter bogus { 203.0.113.1; }"
nft "add rule inet filter input ip saddr @bogus drop"
nft "list set inet filter bogus"
  • Der letzte Befehl des Beispiel gibt den aktuellen Inhalt des benannten Sets bogus aus.

19.38 Sets

  • Ein benanntes Set kann in einer Regel mit vorangestelltem "@" eingefügt werden.
  • Eine Filterregel mit benanntem Set wird vom der nftables Virtuellen-Maschine schneller bearbeitet als eine Reihe von Einzel-Regeln.

19.39 Anonyme und benannte Maps und Dictionaries

  • Maps und Dictionaries existieren in anonymen (statischen) und benannten Versionen.
  • Die anonymen Versionen werden direkt in die Regel geschrieben und sind damit fester Bestandteil der Regel.
  • Die Inhalte von anonymen Datenstrukturen können nicht zu einem späeteren Zeipunk geändert werden.

19.40 Anonyme und benannte Maps und Dictionaries

  • Bei den benannten Maps und Dictionaries können die Inhalte nach dem Laden des Firewall-Regelwerkes noch angepasst werden.
  • So können z.B. Programme wie fail2ban oder denyhost direkt mit der Firewall interagieren und IP-Adressen von Angreifern sperren.
  • Oder eine Anti-Spam-Dienst kann das Einliefern von Spam-E-Mail über die IP-Adressen von identifizierten Spammern mittels einer Rate-Limit-Regel drosseln.

19.41 Maps

  • Maps oder Data-Maps verbinden zwei Werte miteinander.
  • Der Eingangswert wird in der Liste der Index-Werte der Map gesucht und der dort gespeicherte Wert wird an die Regel zurückgegeben.
  • Eine Beispiel-Anwendung ist das Verzweigen auf verschiedene interne Server mit privaten Adressen per NAT, basierend auf der Port-Nummer des Dienstes:
# nft "add rule ip nat prerouting dnat" \
      "tcp dport map { 80 : 192.168.1.100, 8888 : 192.168.1.101 }"

19.42 Verdict-Maps/Dictionaries

  • Verdict-Maps, auch Dictionaries genannt, verbinden einen Eingangswert des zu betrachtenen Pakets mit der Filter-Entscheidung einer Regel.
  • Somit lassen sich für die verschiedenen Werte einers IP-Paketes automatisch unterschiedliche Aktionen auslösen.

19.43 Verdict-Maps/Dictionaries

  • In diesem Beispiel werden die Ergebnisse einer Regel an die Quell-IPv4-Adresse des Netzwerk gebunden:
nft "add map inet filter aktion { type ipv4_addr : verdict; }"

nft "add element inet filter aktion" \
    "{ 192.0.2.80 : accept, 192.0.2.88 : drop, 192.0.2.99 : drop }"

nft "add rule inet filter input ip saddr vmap @aktion"

19.44 Beispiel: ein Regelwerk für eine Host-Firewall

  • Das nachfolgende nftable-Regelwerk kann als Grundlage für eine Host-Firewall für eine Linux-Workstation benutzt werden.
  • Gefiltert werden die eingehenden IPv4- und IPv6-Verbindungen.
  • Gängige Dienste auf einer Linux-Workstation wie Internet Printing Protocol (IPP/Cups) und Multicast-DNS werden erlaubt:

19.45 Beispiel: ein Regelwerk für eine Host-Firewall

flush ruleset

define any = 0::0/0

table inet filter {
        chain input {
                type filter hook input priority 0;

                # accept any localhost traffic
                iif lo accept

                # accept traffic originated from us
                ct state established,related accept

                # activate the following line to accept common local services
                #tcp dport { 22, 80, 443 } ct state new accept

                # NTP multicast
                ip6 daddr ff02::1010 udp dport 123 accept

                # mDNS (avahi)
                ip6 daddr ff02::fb udp dport 5353 accept
                ip  daddr 224.0.0.251 udp dport 5353 accept

                # DHCPv6
                ip6 saddr $any udp dport 546 accept

                # IPP (CUPS)
                udp dport 631 accept

                # Accept neighbour discovery otherwise IPv6 connectivity breaks.
                ip6 saddr $any icmpv6 type { nd-neighbor-solicit,  nd-router-advert, nd-neighbor-advert }  accept

                # Accept essential icmpv6
                # nft cannot parse "param-problem" (icmpv6 type 4)
                ip6 saddr $any icmpv6 type { echo-reply, echo-request, packet-too-big, destination-unreachable, time-exceeded, 4 } accept

                # count and drop any other traffic
                counter log prefix "nftables drop: " drop
        }
}

19.46 Beispiel: ein Regelwerk für einen Gateway-Router mit IPv4-NAT

  • Nachfolgend ein nftables-Regelwerk für eine einfache Firewall mit DMZ-, WAN- und LAN-Schittstelle. In der DMZ befinden sich die Server mit Web und E-Mail.
  • In der Postrouting-Kette werden alle Pakete aus dem LAN-Segment, welche die Firewall in Richtung Internet (WAN) verlassen, per Masquerading-NAT auf die IPv4-Adresse der WAN-Netzwerkschnittelle umgeschrieben.

19.47 Gateway-Router mit IPv4-NAT

#!/usr/bin/nft -f
flush ruleset
define mgt_if = eth0
define wan_if = eth1
define lan_if = eth3
define dmz_if = eth2
define any_v6  = 0::0/0

table inet gateway-fw {
        chain forward {
                type filter hook forward priority 0
                # accept established traffic
                ct state established,related accept
                # allow all outgoing traffic from LAN
                iif $lan_if accept
                # access to services in the DMZ
                oif $dmz_if tcp dport { http, https, smtp, imap, imaps } counter accept
                # Accept essential icmpv6
                # nft cannot parse "param-problem" (icmpv6 type 4)
                ip6 saddr $any_v6 icmpv6 type { echo-reply, echo-request, packet-too-big, destination-unreachable, time-exceeded, 4 } accept
                # reject everything else
                counter log reject
       }
       chain input {
                type filter hook input priority 0
                iif lo accept
                iif $mgt_if tcp dport ssh accept
                ip6 saddr $any_v6 icmpv6 type { nd-neighbor-solicit,  nd-router-advert, nd-neighbor-advert }  accept
                ip6 saddr $any_v6 icmpv6 type { echo-reply, echo-request, packet-too-big, destination-unreachable, time-exceeded, 4 } accept
                counter log reject
       }
}
table ip nat {
        chain prerouting {
                type nat hook prerouting priority 0
        }
        chain postrouting {
                type nat hook postrouting priority 0
                oif $wan_if log masquerade
        }
}

20 nftables Firewall Praxis

  • auf dem Server aXX.dane.onl arbeiten
  • ntf Version abfragen
dnf install nftables
nft -v
  • das nftables Ruleset auflisten (sollte am Anfang leer sein)
nft list ruleset
  • ein nft Ruleset für eine Host-Firewall, per Editor in die Datei /etc/nftables/inet-filter.nft schreiben
# Regelsatz löschen
flush ruleset

# Variable "any" definieren
define any = 0::0/0

table inet filter {
        chain input {
                type filter hook input priority 0;

		# set default policy to "drop"
		policy drop;

                # accept any localhost traffic
                iif lo accept

                # accept traffic originated from us
                ct state established,related accept

                # activate the following line to accept common local services
                tcp dport { 22, 80, 443 } ct state new accept

                # NTP multicast
                ip6 daddr ff02::1010 udp dport 123 accept

                # mDNS (avahi)
                ip6 daddr ff02::fb udp dport 5353 accept
                ip  daddr 224.0.0.251 udp dport 5353 accept

                # DHCPv6
                ip6 saddr $any udp dport 546 accept

                # IPP (CUPS)
                tcp dport 631 accept

                # Accept neighbour discovery otherwise IPv6 connectivity breaks.
                ip6 saddr $any icmpv6 type { nd-neighbor-solicit,
                                             nd-router-advert,
                                             nd-neighbor-advert }  accept

                # Accept essential icmpv6
                ip6 saddr $any icmpv6 type { echo-reply,
                                             echo-request,
                                             packet-too-big,
                                             destination-unreachable,
                                             time-exceeded,
                                             parameter-problem } accept

                # count and drop any other traffic
                counter log prefix "nftables drop: " drop
        }
}
  • nftables inet Regeldatei aktivieren: in der Datei /etc/sysconfig/nftables.conf die Datei /etc/nftables/inet-filter.nft einkommentieren
  • nftables Firewall laden
systemctl start nftables
  • Regelwerk anzeigen
nft list ruleset
  • Log-Ausgaben anzeigen, es sollten nun Pakete mit dem Log-Prefix "nftables drop:" im Log erscheinen
journalctl -f | grep nftables
  • eigenen Router vom Laptop aus mit nmap scannen (einmal mit nftables Firewall eingeschaltet, danach mit der nftables Firewall ausgeschaltet. Gibt es einen Unterschied?)
dnf install nmap
nmap -sT aXX.dane.onl
  • Beipsiel der nmap Ausgabe
Starting Nmap 7.70 ( https://nmap.org ) at 2019-12-10 11:31 CET
Nmap scan report for 192.168.1.166
Host is up (0.00048s latency).
Not shown: 996 filtered ports
PORT    STATE  SERVICE
22/tcp  open   ssh
80/tcp  closed http
443/tcp closed https
631/tcp closed ipp
MAC Address: 08:00:00:00:00:0A (Unknown)

Nmap done: 1 IP address (1 host up) scanned in 5.08 seconds

20.1 nftables Port Knocking

  • "Port Knocking" beschreibt eine Sicherheitstechnik, bei der ein Port in einer Firewall erst geöffnet wird, nach dem der Client auf einen (oder mehreren) spezifischen Port(s) verbunden ("angeklopft") hat.
  • im nachfolgenden Beispiel wird der Port für Secure Shell (SSH, Port 22) erst nach einer TCP Verbindung auf Port 6502 geöffnet. Nach 90 Sekunden wird der Port automatisch geschlossen.
  • Alternativen zu TCP Ports für Port Knocking sind ICMP-Pakete mit speziellen (ungebräuchlichen) Parametern, Flags in IP-Headern, IPv6 Extension-Header oder spezielle Daten in UDP-Pakete auf einem geöffneten Port (z.B. DNS)
  • in Datei /etc/nftables/inet-filter.nft
# Regelsatz löschen
flush ruleset

# Variable "any" definieren
define any = 0::0/0

table inet filter {
        # Set mit IPv4 Adressen und Timeout-Werten
        set allow_ssh4 {
                type ipv4_addr;
                flags timeout;
        }
        set allow_ssh6 {
                type ipv6_addr;
                flags timeout;
        }
        chain input {
                type filter hook input priority 0;
                policy accept;

                # alle Pakete auf dem Loopback Interface erlauben
                iif lo accept;

                # alle Pakete von bestehenden Verbindungen erlauben
                ct state established,related accept;

                # wird auf Port 6502 verbunden, so wird die Quell-IP-Adresse
                # in das Set "allow_ssh[4|6]" mit einem Timeout von 90 Sekunden aufgenommen
                ip  daddr  94.130.27.184         tcp dport 6502 log add @allow_ssh4 { ip  saddr timeout 90s } reject;
                ip6 daddr  2a01:4f8:c0c:7c3c::1  tcp dport 6502 log add @allow_ssh6 { ip6 saddr timeout 90s } reject;

                # erlaube SSH für alle Quell-IP-Adressen, welche in dem Set
                # "allow_ssh" gespeichert sind
                ip  saddr @allow_ssh4 tcp dport ssh log accept;
                ip6 saddr @allow_ssh6 tcp dport ssh log accept;

                # IPv6 neighbour discovery, notwendig für IPv6
                ip6 saddr $any icmpv6 type { nd-neighbor-solicit,
                                             nd-router-advert,
                                             nd-neighbor-advert }  accept

                # ICMPv6 essentielle Meldungen 
                ip6 saddr $any icmpv6 type { echo-reply,
                                             echo-request,
                                             packet-too-big,
                                             destination-unreachable,
                                             time-exceeded,
                                             parameter-problem } accept


                # alle anderen Pakete verwerfen
                log drop;
        }
}

  • inet nftables Regeldatei unter /etc/sysconfig/nftables.conf freischalten
#
# This this will contain your nftables rules and
# is read by the systemd service when restarting
#
# These provide an iptables like set of filters
# (uncomment to include)
# include "/etc/nftables/bridge-filter.nft"
include "/etc/nftables/inet-filter.nft"
# include "/etc/nftables/ipv4-filter.nft"
# include "/etc/nftables/ipv4-mangle.nft"
# include "/etc/nftables/ipv4-nat.nft"
# include "/etc/nftables/ipv6-filter.nft"
# include "/etc/nftables/ipv6-mangle.nft"
# include "/etc/nftables/ipv6-nat.nft"
  • nftables Unit (neu) starten
systemctl start nftables
  • nftables Unit aktivieren
systemctl enable nftables
  • Testen
telnet aXX.dane.onl 6502  # <-- anklopen
ssh aXX.dane.onl          # SSH funktioniert nach dem Anklopfen
  • Manuell einen Eintrag für 1 Stunde in die Map eintragen
nft add element table inet filter allow_ssh4 { 192.0.2.22 timeout 3600 }

20.2 Firewalld mit nftables

21 DNS-over-TLS und DNS-over-HTTPS mit Unbound

  • wir arbeiten auf aXX.dane.onl
  • wir haben ein Let's Encrypt Zertifikat unter /etc/tls/aXX.dane.onl
  • wir installieren und starten einen Unbound DNS Resolver
dnf install unbound
systemctl enable --now unbound
  • Unbound DNSSEC validierung testen
dig @127.0.0.1 dnssec.works +adflag +multi

21.1 DoT Konfiguration

  • Unbound Konfiguration unter /etc/unbound/unbound.conf anpassen
# DNS-over-TLS Ports freischalten
interface: 0.0.0.0@853
interface: ::0@853
# Access Control Lists
access-control: 0.0.0.0/0 allow
access-control: 127.0.0.0/8 allow
access-control: ::0/0 allow
# DoT Konfiguration
tls-service-key: "/etc/tls/aXX.dane.onl/aXX.dane.onl.key"
tls-service-pem: "/etc/tls/aXX.dane.onl/aXX.dane.onl.cer"
tls-port: 853
  • Unbound Konfiguration testen
unbound-checkconf
  • Unbound neu starten
systemctl restart unbound

21.2 DoH Konfiguration

  • Golang Entwicklungspakete installieren. Go-Programme sind statische Programme, die Programme können auf einem beliebigen 64bit Linux-Rechner kompiliert werden und dann auf den DoH-Server übertragen werden. Die Entwicklungsprogramme sollte nicht auf einem Produktions-Server im Internet liegen!
dnf install make git golang
  • trustydns Quellcode aus Github laden, Fehlermeldung ignorieren
go get -d -u github.com/markdingo/trustydns
  • trustydns übersetzen
cd /root/src/src/github.com/markdingo/trustydns
make updatepackages
make all
make install
  • Resolver Konfiguration anlegen, so das trustydns den lokalen Unbound als Resolver benutzt
echo "nameserver 127.0.0.1" > /etc/unbound/resolv.conf
  • DoH Server starten
trustydns-server -tls-cert /etc/tls/aXX.dane.onl/fullchain.cer \
      -tls-key /etc/tls/aXX.dane.onl/aXX.dane.onl.key \
      -c /etc/unbound/resolv.conf 
  • DoH Server testen
# /usr/local/bin/trustydns-dig https://aXX.dane.onl/dns-query heise.de a   
;; opcode: QUERY, status: NOERROR, id: 65408
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;heise.de.      IN       A

;; ANSWER SECTION:
heise.de.       86400   IN      A       193.99.144.80

;; Query Time: 9ms/104ms
;; Final Server: https://aXX.dane.onl/dns-query
;; Tries: 1(queries) 1(servers)
;; Payload Size: 50

22 (aus dem Netzwerk-Sicherheit Kurs) TOR - The Onion Router

22.1 TOR Installieren

  • auf dem Router und auf dem Laptop die Tor-Software installieren
apt install tor

22.2 TOR-Browser

  • auf dem Laptop bei installiertem Tor-Dienst den Socksv5-Proxy im Browser auf Port 9050 einstellen
  • Alternativ kann der Tor-Browser des Tor-Projekt installiert werden ( http://www.torproject.org ). Der Tor-Browser hat den Tor-Daemon schon eingebaut, dieser muss dann nicht extra installiert sein

22.3 TOR-Onion-Services

  • auf dem Router in der Tor-Konfiguration einen Onion Hidden-Service auf Localhost Port 8000 einrichten
$EDITOR /etc/tor/torrc
[...]
HiddenServiceDir /var/lib/tor/hidden_service/
HiddenServicePort 80 127.0.0.1:8000
[...]
  • Tor neu starten
systemctl restart tor
systemctl status tor
  • auf dem Router einen Webserver Service starten (einfacher Python Webserver auf Port 8000)
python -m SimpleHTTPServer
  • auf dem Router den Onion-Namen herausfinden (Datei /var/lib/tor/hidden_service/hostname) und an einen der Teilnehmer weitergeben oder selbst im Firefox (bei eingeschaltetem Socks5-Proxy auf Port 9050)
  • den Onion-Dienst mit diesem "Domain"-Namen ansprechen, per Socks-Proxy aus dem Firefox oder mit dem Tor-Browser

22.4 Programme ohne Socks-Support mit Tor benutzen

  • einige Programme (wie ssh oder links) haben keinen Support für Socks5 Proxies
  • mit dem Programm torify können Programm für Tor eingerichtet werden
torify links http://<onion-adresse>.onion

22.5 Sicherheit

  • Einige Server-Dienste schalten spezielle Admin-Funktionen frei, wenn der Server über eine Loopback-Adresse (127.0.0.1) angesprochen wird (z.B. der Apache Webserver –> https://www.heise.de/security/meldung/Apache-verpetzt-moeglicherweise-Tor-Hidden-Services-3090218.html). Bei Bennutzung als Tor-Dienst auf einer Loopback-Adresse sind diese Admin-Funktionen von aussen über das Tor-Netzwerk erreichbar. Lösung: den Dienst auf einer nicht-Loopback Adresse konfigurieren, oder die speziellen Admin-Funktionen in der Server-Konfiguration ausschalten.

22.6 Client-Authentisierung mit Tor Onion Service V3

  • seit Version 0.3.5 der Tor-Software wird ein neues, sicheres Protokoll für die Onion-Services verwendet. Die Konfiguration der Authentisierung von Tor-Clients mit der Version 3 der Onion-Services wird im folgenden beschrieben

22.6.1 Schlüssel erstellen

  • es gibt mehrere Wege, ein Schlüsselpaar (ED25519) für einen Onion-Service zu erstellen
  1. per Python Programm
    • wir installieren python-nacl, eine Python-Bibliothek mit Krypto-Funktionen und laden dann von Github ein kleines Python-Script, welches eine Schlüssel-Paar für einen V3 Onion-Service erstellt:
    apt install python-nacl
    
    #!/usr/bin/env python3
    import base64
    try:
        import nacl.public
    except ImportError:
        print('PyNaCl is required: "pip install pynacl" or similar')
        exit(1)
    
    
    def key_str(key):
        # bytes to base 32
        key_bytes = bytes(key)
        key_b32 = base64.b32encode(key_bytes)
        # strip trailing ====
        assert key_b32[-4:] == b'===='
        key_b32 = key_b32[:-4]
        # change from b'ASDF' to ASDF
        s = key_b32.decode('utf-8')
        return s
    
    
    def main():
        priv_key = nacl.public.PrivateKey.generate()
        pub_key = priv_key.public_key
        print('public:  %s' % key_str(pub_key))
        print('private: %s' % key_str(priv_key))
    
    
    if __name__ == '__main__':
        exit(main())
    
    • ein Aufruf dieses Programms erstellt ein Schlüsselpaar und gibt dieses auf den Bildschirm aus
    # python x25519-gen.py
    public:  5U3RTWSB2BVYSC5UQTNRYHH5COACEJJLNCMDZBETEGGFZZFHIAPQ
    private: KRPY7WFH322QJL4KC3WHXDGV7WAMNVYLIUA65GUEWOOLMUHEIJIA
    

22.6.2 per OpenSSL

  • alternativ kann ein Schlüsselpaar mit OpenSSL erstellt werden
  • zuerst der private Schlüssel
openssl genpkey -algorithm x25519 -out key.private.pem
cat key.private.pem | grep -v " PRIVATE KEY" | base64 -d | tail --bytes=32 | base32 | sed 's/=//g' > private.key
  • und dann der öffentliche Schlüssel
openssl pkey -in key.private.pem -pubout | grep -v " PUBLIC KEY" | base64 -d | tail --bytes=32 | base32 | sed 's/=//g' > public.key

22.6.3 Authentisierung auf der Server-Seite einrichten

  • auf der Seite des Tor-Onion-Dienstes, im Unterverzeichnis authorized_clients des Dienstes eine Datei mit der Endung .auth anlegen. In unserem Beispiel wir die Datei /var/lib/tor/hidden_service/authorized_clients/nutzer.auth angelegt
cd /var/lib/tor/hidden_service/authorized_clients/
$EDITOR nutzer.auth
  • diese Datei enthält des öffentlichen Schlüssel des Clients im Format descriptor:x25519:<public-key>
  • den Tor-Dienst neu starten
systemctl restart tor
  • Nun kann nur noch ein Client, welcher den entsprechenden privaten Schlüssel zu den öffentlichen Schlüsseln des Dienstes hat, auf den Dienst zugreifen. Alle anderen Clients können nicht sehen, ob der Dienst existiert.

22.6.4 Authentisierung auf der Client-Seite einrichten

  • auf dem Tor-Client ein Verzeichnis für die Client-Schlüssel anlegen (hier /var/lib/tor/auth) und die Rechte für die Tor-Software setzen
mkdir /var/lib/tor/auth
chmod 700 /var/lib/tor/auth
chown toranon /var/lib/tor/auth/
  • in diesem Verzeichnis eine Text-Datei mit der Endung .auth_private anlegen. In diese Datei den privaten Schlüsseln für jeden Tor-Dienst eintragen (je eine Zeile pro Dienst). Jeder Eintrag hat das Format <onion-address>:descriptor:x25519:<base32-encoded-private-key>
$EDITOR /var/lib/tor/auth/nutzer.auth_private
  • das Verzeichnis mit den Authentisierungs-Datei(en) auf dem Client in die Konfiguration der Tor-Software eintragen. Datei /etc/tor/torrc:
ClientOnionAuthDir /var/lib/tor/auth

22.7 Vor- und Nachteile von Tor-Onion-Diensten

22.7.1 Vorteile

  • keine Änderungen an der (Heim-)Firewall notwendig. Keine Port-Forwardings etc.
  • kein DynDNS notwendig, um eine wechselne IP-Adresse mit einen Namen zu verbinden. Der Onion-Name wird immer im Tor-Netz gefunden
  • Datenverkehr ist verschlüsselt (Curve25519)
  • Datenverkehr ist anonymisiert

22.7.2 Nachteile

  • Client muss die Tor-Software als Proxy benutzen
  • hohe Latenz (Verzögerung) bei den Paketlaufzeiten

22.8 Links

23 (aus dem Netzwerk-Sicherheit Kurs) WireGuard

  • Wir haben virtuelle Maschinen im Internet (vm01-vm10.defaultroutes.de)
  • Plan: VPN vom Laptop zur VM im Internet, alle Pakete vom Laptop sollen über das VPN und die VM im Internet gesendet werden

23.1 Wireguard Debian Installation (VPN-Client/VPN-Server)

  • Installationsinformationen für Wireguard https://www.wireguard.com/install/
  • Derzeit ist Wireguard noch nicht in den Linux-Kernel eingezogen, soll aber in Version ~5.6 in den Kernel kommen
  • der Laptop ist unser Wireguard-Client
  • auf dem Laptop und auf dem VPS Server im Internet das Wireguard Repository hinzufügen, Paketlisten updaten und Wireguard-Pakete installieren
echo "deb http://deb.debian.org/debian/ unstable main" > /etc/apt/sources.list.d/unstable.list
printf 'Package: *\nPin: release a=unstable\nPin-Priority: 90\n' > /etc/apt/preferences.d/limit-unstable
apt update
apt upgrade
reboot
apt install wireguard linux-headers-$(uname -r)

23.2 Konfiguration Wireguard auf dem VPN-Server (Gateway)

  • User-Mask für neue Dateien und Verzeichnisse setzen, ein Verzeichnis für die Wireguard-Dateien erstellen
umask 077
mkdir -p /etc/wireguard
cd /etc/wireguard
  • einen privaten Schlüssel für den Wireguard-Dienst erstellen
wg genkey > private.key
  • Wireguard-Interface erstellen
ip link add dev wg0 type wireguard
  • IP-Adresse auf dem neuen Wireguard-Interface wg0 setzen
ip addr add 10.0.0.2/24 dev wg0
  • Privaten Schlüssel in das wg0 Interface laden
wg set wg0 private-key ./private.key
  • Interface wg0 aktivieren
ip link set wg0 up
  • Konfiguration der Schnittstelle anzeigen
wg show wg0

23.3 Konfiguration Wireguard auf dem VPN-Client

  • der Laptop ist unser VPN-Client
  • Wireguard installieren. Wurde ein neuer Linux-Kernel installiert, dann nach der Installation von Wireguard den Rechner neu starten, denn die Wireguard-Kernel-Module wurden schon für die neue Kernel-Version gebaut
echo "deb http://deb.debian.org/debian/ unstable main" > /etc/apt/sources.list.d/unstable.list
printf 'Package: *\nPin: release a=unstable\nPin-Priority: 90\n' > /etc/apt/preferences.d/limit-unstable
apt update
apt install wireguard
  • Verzeichnis für die Wireguard-Dateien erstellen
umask 077
mkdir /etc/wireguard
cd /etc/wireguard
  • einen privaten Schlüssel für den Wireguard-Dienst erstellen
wg genkey > private.key
  • Wireguard-Interface erstellen
ip link add dev wg0 type wireguard
  • IP-Adresse auf dem neuen Wireguard-Interface wg0 setzen
ip addr add 10.0.0.1/24 dev wg0
  • Privaten Schlüssel in das wg0 Interface laden
wg set wg0 private-key ./private.key
  • Interface wg0 aktivieren
ip link set wg0 up
  • öffentlicher Schlüssel, erlaubte IP-Adressen und IP/Port des VPN-Servers eintragen
wg set wg0 peer <schlüssel> allowed-ips 0.0.0.0/0 endpoint <vpn-server>:<port>
  • Konfiguration der Schnittstelle anzeigen
wg show wg0
  • Konfiguration in die Konfigurationsdatei speichern
wg showconf wg0 > /etc/wireguard/wg0.conf
chmod 0600 /etc/wireguard/wg0.conf
  • Konfigurationsdatei anpassen, Address einfügen und Abschnitt Peer
[Interface]
ListenPort = <port>
PrivateKey = <private-key>
Address = 10.0.0.1/24

[Peer]
PublicKey = <public-key-of-vpn-server>
AllowedIPs = 0.0.0.0/0
Endpoint = <ip-of-vpn-server>:<port>

23.4 Client auf dem Server erlauben

  • auf dem VPN-Server, die Wireguard-Configuration speichern
wg showconf wg0 > /etc/wireguard/wg0.conf
chmod 0600 /etc/wireguard/wg0.conf
  • Konfigurationsdatei anpassen (Address und Abschnitt Peer)
[Interface]
ListenPort = <port>
PrivateKey = <private-key>
Address = 10.0.0.2/24

[Peer]
PublicKey = <public-key-of-client>
AllowedIPs = 10.0.0.1/32

23.5 IP-NATPT auf dem Server und IPv4-Forwarding anschalten

iptables -A POSTROUTING -t nat -o eth0 -j MASQUERADE
echo 1 > /proc/sys/net/ipv4/ip_forward
echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.conf

23.6 Wireguard manuell aktivieren

  • auf dem VPN-Gateway
root@vm0X:/etc/wireguard# wg-quick down wg0
[#] ip link delete dev wg0
root@vm0X:/etc/wireguard# wg-quick up wg0
[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip link set mtu 1420 up dev wg0
[#] ip route add 10.0.0.1/32 dev wg0
  • auf dem VPN-Client
root@router05:/etc/wireguard# wg-quick down wg0
[#] ip link delete dev wg0
root@router05:/etc/wireguard# wg-quick up wg0
[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip link set mtu 1420 up dev wg0
[#] wg set wg0 fwmark 51820
[#] ip -4 route add 0.0.0.0/0 dev wg0 table 51820
[#] ip -4 rule add not fwmark 51820 table 51820
[#] ip -4 rule add table main suppress_prefixlength 0

23.7 VPN Test

  • Ping vom VPN-Client Wireguard-IP zum VPN-Server
ping 10.0.0.2

23.8 DNS Resolver auf einen Resolver im Internet setzen

  • der DNS-Resolver des Linuxhotels ist über den Tunnel nicht erreichbar, daher müssen wir einen DNS-Resolver im Internet benuzten (oder, besser, einen eigenen DNS-Resolver auf dem VPN-Gateway-Server).
echo "nameserver 1.1.1.1" > /etc/resolv.conf

23.9 Tests der Wireguard-Verbindung

  • Sichtbare IP-Adresse des Client mit und ohne Wireguard prüfen, z.B. per Firefox auf der Seite https://ripe.net
  • Route zu einem Host im Internet per mtr testen, mit und ohne Wireguard
  • Wireguard aktivieren, mtr auf einen Server im Internet laufen lassen. Dann von Ethernet (Kabel) auf WLAN umschalten, der mtr Trace darf nicht abbrechen, der Wireguard Tunnel überlebt das umschalten
apt install mtr
mtr -t google.com

23.10 Wireguard per systemd

  • die folgenden Schritte sowohl auf dem VPN-Gateway, als auch auf dem Client ausführen
  • manuell gestartetes Wireguard beenden
wg-quick down wg0
  • Wireguard per Systemd aktivieren
systemctl enable wg-quick@wg0
systemctl start wg-quick@wg0
systemctl status wg-quick@wg0
● wg-quick@wg0.service - WireGuard via wg-quick(8) for wg0
   Loaded: loaded (/lib/systemd/system/wg-quick@.service; enabled; vendor preset: enabled)
   Active: active (exited) since Mon 2019-05-06 16:18:02 EDT; 1s ago
     Docs: man:wg-quick(8)
	   man:wg(8)
	   https://www.wireguard.com/
	   https://www.wireguard.com/quickstart/
	   https://git.zx2c4.com/WireGuard/about/src/tools/man/wg-quick.8
	   https://git.zx2c4.com/WireGuard/about/src/tools/man/wg.8
  Process: 13492 ExecStart=/usr/bin/wg-quick up wg0 (code=exited, status=0/SUCCESS)
 Main PID: 13492 (code=exited, status=0/SUCCESS)

May 06 16:18:02 router05 systemd[1]: Starting WireGuard via wg-quick(8) for wg0...
May 06 16:18:02 router05 wg-quick[13492]: [#] ip link add wg0 type wireguard
May 06 16:18:02 router05 wg-quick[13492]: [#] wg setconf wg0 /dev/fd/63
May 06 16:18:02 router05 wg-quick[13492]: [#] ip address add 10.0.0.1/24 dev wg0
May 06 16:18:02 router05 wg-quick[13492]: [#] ip link set mtu 1420 up dev wg0
May 06 16:18:02 router05 wg-quick[13492]: [#] wg set wg0 fwmark 51820
May 06 16:18:02 router05 wg-quick[13492]: [#] ip -4 route add 0.0.0.0/0 dev wg0 table 51820
May 06 16:18:02 router05 wg-quick[13492]: [#] ip -4 rule add not fwmark 51820 table 51820
May 06 16:18:02 router05 wg-quick[13492]: [#] ip -4 rule add table main suppress_prefixlength 0
May 06 16:18:02 router05 systemd[1]: Started WireGuard via wg-quick(8) for wg0.

23.11 Optional: Alternatives Routing auf dem Client ohne wg-quick

  • Alle Pakete (mit Aussnahme der Wireguard Pakete) sollen durch den VPN-Tunnel gesendet werden. Eine Split-Default-Route sorgt dafür, das wir die original Default-Route nicht verlieren
ip route add <ip-des-VPN-servers>/32 via 192.168.1.5 dev eth0
ip route add  0.0.0.0/1 via 10.0.0.2 dev wg0
ip route add  128.0.0.0/1 via 10.0.0.2 dev wg0
  • Test
# tracepath google.com
 1?: [LOCALHOST]                                         pmtu 1420
 1:  10.0.0.2                                             15.453ms
 1:  10.0.0.2                                             15.446ms
 2:  no reply
 3:  45.63.118.33                                         18.164ms
 4:  no reply
 5:  ffm-b12-link.telia.net                               20.718ms
 6:  ffm-bb4-link.telia.net                               15.889ms
 7:  ffm-b1-link.telia.net                                16.062ms
 8:  google-ic-319727-ffm-b1.c.telia.net                  15.997ms asymm 10
[...]

23.12 Optional: Wireguard mit alternativen Routing auf dem Client ausschalten

  • Routen löschen
ip r del 0.0.0.0/1 via 10.0.0.2 dev wg0
ip r del 128.0.0.0/1 via 10.0.0.2 dev wg0
ip r del <ip-des-vpn-servers> via 192.168.1.5 dev eth0
  • Wireguard Interface ausschalten
ip link set dev wg0 down

23.13 Links