LPI 202 Vorbereitung

Topic 207: Domain Name Server

207.1 Basic DNS server configuration

Einführung

A) Geschichtliches

Es gibt verschiedene Möglichkeiten der Namensauflösung:

  1. Datei hosts.txt (heute: /etc/hosts, Hyperlink: siehe oben)

  2. Yellow Pages (aus Lizenzgründen umbenannt in Network Information System)

  3. Domain Name System

B) Wichtige Kennzeichen von DNS

  1. Dezentral, um dem Datenaufkommen Herr zu werden (13 Root-Server)

  2. Hierarische Struktur

  3. Authoritative Root Server

TIPP: Domänen-Suche am besten bei den jeweiligen gemeinnützigen Organisationen oder mit whois duchführen:

C) Begriffe

  • Weltweit einheuitlicher Namensraum, Weltwurzel = ein Punkt

  • Domäne = Teil des Namensraums

  • Zone = Verwaltungseinheit einer Domäne

Cache-only Nameserver einrichten

ZIEL: Häufige DNS-Anfragen zwischenspeichern, Performancegewinn

Die Installation ist schnell erledigt:

$ apt-get install bind9 dnsutils

Eine Änderung der Konfiguration ist in diesem Szenario nur erforderlich, wenn keine transparenten Downloads von Zoneninformationen möglich sind. Dann müssen ‚forwarders‘ Verwendung finden:

$ grep -A3 forwarders /etc/bind/named.conf.options
      // nameservers, you probably want to use them as forwarders.
      // Uncomment the following block, and insert the addresses replacing
      // the all-0's placeholder.

      forwarders {
            194.25.2.129; 8.8.8.8;
      };

$

In unserem Netzwerk haben wir allerdings keinen Handlungsbedarf und belassen die Datei, wie sie ist.

DNS-Client Konfigurieren

Auf dem Nameserver selbst, wird in aller Regel der hier laufende Bind9-Daemon als zu befragender DNS-Server angegeben:

$ cat /etc/resolv.conf
nameserver 127.0.0.1

Soll ein Windowssystem als DNS-Client herangezogen werden, ist der Weg dieser:

$ ncpa.cpl $ ... Eigenschaften ... Karte DNS ...

Starten und Testen

$ systemctl start bind9
$ systemctl status bind9
 * bind9.service - BIND Domain Name Server
   Loaded: loaded (/lib/systemd/system/bind9.service; enabled; vendor preset: enabled)
   Drop-In: /run/systemd/generator/bind9.service.d
           `50-insserv.conf-$named.conf
   Active: active (running) since Mi 2016-10-26 11:50:00 CEST; 1s ago
     Docs: man:named(8)
   Main PID: 19894 (named)
     Tasks: 4
   Memory: 11.4M
      CPU: 26ms
   CGroup: /system.slice/bind9.service
           `19894 /usr/sbin/named -f -u bind

Okt 26 11:50:00 dns1 named[19894]: command channel listening on 127.0.0.1#953
Okt 26 11:50:00 dns1 named[19894]: configuring command channel from '/etc/bind/rndc.key'
Okt 26 11:50:00 dns1 named[19894]: command channel listening on ::1#953
Okt 26 11:50:00 dns1 named[19894]: managed-keys-zone: loaded serial 0
Okt 26 11:50:00 dns1 named[19894]: zone 0.in-addr.arpa/IN: loaded serial 1
Okt 26 11:50:00 dns1 named[19894]: zone 127.in-addr.arpa/IN: loaded serial 1
Okt 26 11:50:00 dns1 named[19894]: zone 255.in-addr.arpa/IN: loaded serial 1
Okt 26 11:50:00 dns1 named[19894]: zone localhost/IN: loaded serial 2
Okt 26 11:50:00 dns1 named[19894]: all zones loaded
Okt 26 11:50:00 dns1 named[19894]: running
$


$ host linux.at
linux.at has address 143.130.20.3
linux.at mail is handled by 10 mx1.luga.at.
$
$
$ nslookup linux.com
Server:         127.0.0.1
Address:        127.0.0.1#53

Non-authoritative answer:
Name:   linux.com
Address: 151.101.129.5
Name:   linux.com
Address: 151.101.193.5
Name:   linux.com
Address: 151.101.65.5
Name:   linux.com
Address: 151.101.1.5

$

Der DNS-Cache

Wer sehen möchte, dass schon erfolgte Namensauflösungen nun aus dem Cache heraus beantwortet werden können, führe am besten mehrmals hintereinander

$ dig metager.de | grep "Query time"

aus. Die zweite Auflösung ist viel schneller als die erste abgelaufen, sie wurde soeben aus dem Cache beantwortet.

Nach dem Anlernen des Caches z.B. mit dig metager.de, kann man ihn leicht in die Datei /var/cache/bind/named_dump.db exportieren:

$ rndc dumpdb

Im Experiment:

$ rndc dumpdb
$
$ ls -ltrc /var/cache/bind/
insgesamt 16
-rw-r--r-- 1 bind bind  821 Okt 26 11:50 managed-keys.bind
-rw-r--r-- 1 bind bind 6160 Okt 26 12:02 named_dump.db
$
$ less /var/cache/bind/named_dump.db
$
$
$ cp  /var/cache/bind/named_dump.db  /root/
$
$ systemctl stop bind9
$
$ less /var/cache/bind/named_dump.db
$
$
$ systemctl start bind9
$
$ grep erfurt /var/cache/bind/named_dump.db
erfurt.de.              35      \-DS    ;-$NXRRSET
$
$ systemctl stop bind9
$
$ rm /var/cache/bind/named_dump.db
$
$ systemctl start bind9
$
$ grep erfurt /var/cache/bind/named_dump.db
grep: /var/cache/bind/named_dump.db: Datei oder Verzeichnis nicht gefunden
$
$
$ dig erfurt.de | tail -5
;; Query time: 148 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Wed Oct 26 12:06:55 CEST 2016
;; MSG SIZE  rcvd: 265

$
$ dig erfurt.de | tail -5
;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Wed Oct 26 12:07:00 CEST 2016
;; MSG SIZE  rcvd: 265

$
$ grep erfurt /var/cache/bind/named_dump.db
grep: /var/cache/bind/named_dump.db: Datei oder Verzeichnis nicht gefunden
$
$ rndc dumpdb
$
$ grep erfurt /var/cache/bind/named_dump.db
erfurt.de.              23      \-DS    ;-$NXRRSET
$

207.2 Create and maintain DNS zones

Eine eigene Domäne

DEFINITION: Eine Domäne ist ein Teil des DNS-Namensraumes, der weltweit einheitlich ist. Verwaltet wird sie in einem Zonenfile. Unter Debian wird z.B. die Datei /etc/bind/db.local verwendet, um eine eigene Zone für localhost bereitzustellen.

Voraussetzungen

Der Name der Domäne entsteht über die Einträge in der /etc/hosts:

127.0.1.1   dns1.dom1.test  dns1

Da wir selber einen bind9-Server auf der Maschine haben, muss die DNS-Clientseite idealerweise auch davon erfahren:

$ vi /etc/resolv.conf
search dom1.test

Man kann auch alles in der /etc/network/interfaces konfigurieren, wenn das Paket resolvconf installiert ist:

auto eth0
iface eth0 inet static
   address 10.20.30.4
   netmask 255.255.255.0
   gateway 10.20.30.1

dns-nameservers 127.0.0.1
dns-search dom1.test

Da der Bind9-Daemon schon läuft, muss auch schon die eigene, lokale Zone benutzbar sein:

Mit dig A localhost | grep -v '^\;' | grep -v '^\.' schauen wir uns die Vorwärtsauflösung an:

localhost.              604800  IN      A       127.0.0.1

localhost.              604800  IN      NS      localhost.

localhost.              604800  IN      AAAA    ::1

Mit dig -x 127.0.0.1 | grep -v '^\;' | grep -v '^\.' danach die Rückwärtsauflösung:

1.0.0.127.in-addr.arpa. 604800  IN      PTR     localhost.

127.in-addr.arpa.       604800  IN      NS      localhost.

localhost.              604800  IN      A       127.0.0.1
localhost.              604800  IN      AAAA    ::1

Das ist bereits am Start aufgrund der vorhandenen Zonendateien db.local und db.127, die für unsere eigen Zone Ausgangspunkt sein werden.

Zonenfiles bereitstellen

$ cd /etc/bind
$ cp db.local db.dom1.test
$ cp db.127 db.10.20.30

Die Inhalte sind nun nach den jeweiligen Bedürfnissen anzupassen.

Die wichtigste Datei ist die für die Vorwärtsauflösung. Sie heißt ‚db.dom1.test‘ und beinhaltet im Endeffekt folgendes:

$TTL    604800
@       IN      SOA     dns1.dom1.test. root.dns1.dom1.test. (
                              2         ; Serial
                         604800         ; Refresh
                          86400         ; Retry
                        2419200         ; Expire
                         604800 )       ; Negative Cache TTL
;
@        IN      NS      dns1.dom1.test.
dns1     IN      A       10.20.30.3

; Weitere Einträge (ähnlich der /etc/hosts, allerdings ZUERST die Hostnamen, DANN die IPs!)
dns2     IN      A       10.20.30.4
xphost   IN      A       10.20.30.126

Die Datei für die Rückwärtsauflösung heißt ‚db.10.20.30‘, sie beinhaltet im Endeffekt folgendes:

$TTL    604800
@       IN      SOA     dns1.dom1.test. root.dns1.dom1.test. (
                              1         ; Serial
                         604800         ; Refresh
                          86400         ; Retry
                        2419200         ; Expire
                         604800 )       ; Negative Cache TTL
;
@       IN      NS      dns1.dom1.test.
3       IN      PTR     dns1.dom1.test.

; Weitere...
4       IN      PTR     dns2.dom1.test.
126     IN      PTR     xphost.dom1.test.

Einbinden der Zonendateien:

So ähnlich wie bei den beiden Zonendateien db.local und db.127 müssen wir nun unsere Zonenfiles einbinden:

$ vi named.conf.local

Die beiden wichtigen Abschnitte sehen schließlich so aus:

zone "dom1.test" {
        type master;
        file "/etc/bind/db.dom1.test";
};

zone "30.20.10.in-addr.arpa" {
        type master;
        file "/etc/bind/db.10.20.30";
};

Danach:

$ tail -f /var/log/syslog    # in zweitem Fenster
$ systemctl restart bind9

Testings

Mit Hilfe des Kommandos ‚host‘:

$ host `hostname -f`
dns1.dom1.test has address 10.20.30.3
dns1.dom1.test has IPv6 address ::1


$ host -t ptr 10.20.30.3
3.30.20.10.in-addr.arpa domain name pointer dns1.dom1.test.
$

Anschauliche Ausgabe bei MX-Einträgen bei Verwendung von ‚host‘:

$ host -t mx web.de
web.de mail is handled by 100 mx-ha03.web.de.
web.de mail is handled by 100 mx-ha02.web.de.
$
$
$ host -t ns web.de
web.de name server ns-webde.ui-dns.de.
web.de name server ns-webde.ui-dns.biz.
web.de name server ns-webde.ui-dns.org.
web.de name server ns-webde.ui-dns.com.
$

Mit Hilfe des Kommandos ‚dig‘:

$ dig dns1  | grep -v '\;' | grep -v ^$
.                       10800   IN      SOA     a.root-servers.net. nstld.verisign-grs.com. 2016102700 1800 900 604800 86400
$
$ dig -x 10.20.30.3 | grep -v '\;' | grep -v ^$
3.30.20.10.in-addr.arpa. 604800 IN      PTR     dns1.dom1.test.
30.20.10.in-addr.arpa.  604800  IN      NS      dns1.dom1.test.
dns1.dom1.test.          604800  IN      A       10.20.30.3
dns1.dom1.test.          604800  IN      AAAA    ::1
$

Slave-Nameserver

Bereitstellen eines zweites Servers

ZIEL: Einen zweiten Nameserver als Slave für Replikation vorbereiten.

Am einfachsten ist es, wir klonen uns DNS1 (Debian-System namens ‚dns1.dom1.test‘) via VirtualBox zu DNS2…

EINGELOGGT AUF DNS2 (dns2.dom1.test):

Umbenennen, anpassen der IP-Adresse auf 10.20.30.4

$ grep dns2 /etc/hostname
dns2
$
$ grep dns2 /etc/hosts
127.0.1.1       dns2.dom1.test dns2
$
$
$ grep 4 /etc/network/interfaces
   address 10.20.30.4
$
$ systemctl restart networking
$
$ /etc/init.d/hostname.sh
$
$ hostname --fqdn
dns1.dom1.test
$
$ hostname dns2
$
$ hostname --fqdn
dns2.dom1.test
$
$
$ hostname -d
dom1.test
$
$ dnsdomainname :
dom1.test

Anpassen der Zonen-Definition für Slave-Rolle:

$ vi /etc/bind/named.conf.local

BITTE AUF FOLGENDE WERTE ÄNDERN:

  1. Ändern von master auf slave, Ergebnis: type slave;

  2. Einfügen dieser Zeile: masters { 10.20.30.3; };

Insgesamt sieht das Gnaze dann so aus:

zone "dom1.test" {
        type slave;
        masters { 10.20.30.3; };
        file "/etc/bind/db.dom1.test";
};

zone "30.20.10.in-addr.arpa" {
        type slave;
        masters { 10.20.30.3; };
        file "/etc/bind/db.10.20.30";
};

Zum Weiterforschen siehe http://www.microhowto.info/howto/configure_bind_as_a_slave_dns_server.html

Replikation einrichten

Beide VMs sind mit Debian 8 ausgestattet und haben folgende Eigenschaften:

  1. Master-Server

    • Hostname: dns1.dom1.test

    • IP-Adresse: 10.20.30.3

  2. Slave-Server:

    • Hostname: dns2.dom1.test

    • IP-Adresse: 10.20.30.4

Konfiguration des Masters

Hier ist besonders die Zeile notify yes; von Belang. Wir haben sie hinzugefügt, um den Slave bei Erhöhung der serial-Nummer informieren zu können, dass er sich die Daten replizieren muss:

$ vi /etc/bind/named.conf.local

Der Inhalt sollte danach folgendermaßen aussehen:

zone "dom1.test" {
        type master;
        notify yes;
        file "/etc/bind/db.dom1.test";
};

zone "30.20.10.in-addr.arpa" {
        type master;
        notify yes;
        file "/etc/bind/db.10.20.30";
};

AUFGABE: Bitte die Sicherheit mit allow-transfer verbesseren!

Im entsprechenden Zonenfile ist es wichtig, den zweiten Nameserver, der als Slave fungieren soll, auch als solchen mit aufzunehmen. Das wird mit der folgenden, hinzuzufügenden Zeile realisiert:

@  IN    NS   dns2.dom1.test.

Vergisst man dies, kann sich zwar der Slave die Daten bei einem systemctl restart bind9 selber ziehen, wird aber nicht vom Master mittels seiner notify-Nachrichten über Änderugen informiert!

$ vi /etc/bind/db.dom1.test

Der Inhalt sollte danach folgendermaßen aussehen:

$TTL    604800
@       IN      SOA     dns1.dom1.test. root.dns1.dom1.test. (
                             90         ; Serial
                         604800         ; Refresh
                          86400         ; Retry
                        2419200         ; Expire
                         604800 )       ; Negative Cache TTL
;
; Dies ist der eigene, lokale Master-Nameserver:
@       IN      NS      dns1.dom1.test.

; HINZUGEFÜGT: Dies ist der andere, entfernte Slave-Nameserver:
@       IN      NS      dns2.dom1.test.

dns1    IN      A       10.20.30.3

; Weitere Einträge (ähnlich der /etc/hosts, allerdings ZUERST die Hostnamen, DANN die IPs!)
dns2    IN      A       10.20.30.4
xphost  IN      A       10.20.30.126
xphost2 IN      A       10.20.30.127

AUFGABE: Bitte auch die reversen Zonenfiles anpassen!

Konfiguration des Slaves

Hier ist zuerst einmal wichtig, anzugeben, wer der Master ist, von dem dann die Daten kopiert werden sollen. Das legen wir mit der Anweisung masters { 10.20.30.3; }; fest:

$ cat /etc/bind/named.conf.local

Der Inhalt sollte dann so aussehen:

zone "dom1.test" {
        type slave;
        masters { 10.20.30.3; };
        file "/etc/bind/db.dom1.test";
};

zone "30.20.10.in-addr.arpa" {
        type slave;
        masters { 10.20.30.3; };
        file "/etc/bind/db.10.20.30";
};

Dann brauchen wir auch wieder das Zonenfile. Anders als beim Master, wo wir den Slave mittels NS-Record eintragen mussten, sind für die Replikation keine besonderen Einstellungen erforderlich:

$ cat /etc/bind/db.dom1.test
$TTL    604800
@       IN      SOA     dns2.dom1.test. root.dns2.dom1.test. (
                              2         ; Serial
                         604800         ; Refresh
                          86400         ; Retry
                        2419200         ; Expire
                         604800 )       ; Negative Cache TTL
;
@       IN      NS      dns2.dom1.test.
dns2    IN      A       10.20.30.4

; Weitere Einträge sind hier auf dem Slave nicht erforderlich,
; da er sich die Datensätze repliziert.

Testings

  • Auf beiden Maschinen: tail -f /var/log/syslog

  • Auf dem Master - Datensatz hinzufügen - Seriennummer erhöhen - Config neu laden: rndc reload

Sicherheit

(Lediglich auf dem Master durchzuführen)

Um nur dem Slave-Server mit der Adresse 10.20.30.4 Zonentransfers zu erlauben (AXFR = Asynchronous Full Transfer Zone oder Asynchronous Xfer Full Range), verwenden wir allow-transfer:

zone "dom1.test" {
        type master;
        notify yes;
        allow-transfer { 10.20.30.4; };
        file "/etc/bind/db.dom1.test";
};

zone "30.20.10.in-addr.arpa" {
        type master;
        notify yes;
        file "/etc/bind/db.10.20.30";
};

Weiterhin kann man das ganz normale Abfragen der Datenbank (nslookup) reglementieren, in der Zonendefinition können wir dazu diese Zeile einfügen:

allow-query { 127.0.0.1; 10.20.30.0/24; };

Damit haben wir unsere beiden DNS-Server mit einfachen Mitteln schon mal etwas sicherer gemacht.

207.3 Securing a DNS server

Einführung

Zu möglichen Angriffen siehe http://www.tecchannel.de/a/dns-attacken-typen-und-sicherheitsvorkehrungen,2064862

Relevante Schutzziele:

  • Integrität

  • Verfügbarkeit

  • Authentizität

Siehe dazu

Gegenmaßnahmen:

Zur Kryptographie:

Master/Slave via TSIG absichern

A) Auf dem Master

$ cd /etc/bind
$
$ dnssec-keygen -a HMAC-MD5 -b 512 -n HOST rndc-key
Krndc-key.+157+04038
$
$ ls -ltrc | tail -5
-rw-r--r-- 1 root bind  494 Nov  1 09:23 named.conf.local
-rw-r--r-- 1 root bind  545 Nov  1 09:35 named.conf
-rw-r----- 1 root bind   77 Nov  1 09:39 rndc.key
-rw------- 1 root bind  229 Nov  1 16:24 Krndc-key.+157+04038.private
-rw------- 1 root bind  117 Nov  1 16:24 Krndc-key.+157+04038.key

Wir sehen uns nun die Datei an, in der unser Pre-Shared-Key steht und erzeugen daraus die Schlüsseldatei:

$ cat Krndc-key.+157+04038.private
Private-key-format: v1.3
Algorithm: 157 (HMAC_MD5)
Key: 8kvk9rllTIsb/WlBYvLQdSsXKoMJ8uCUYYLIAy0DMoOmNdZiAgdK+yloqCDZnDya1CIrYAbsVV8mi1/nI3v0CQ==
Bits: AAA=
Created: 20161101152458
Publish: 20161101152458
Activate: 20161101152458
$

In der neu anzulegenden Datei namens ‚tsig.key‘ müssen wir als nächstes einige Eintragungen vornehmen:

  • Den eben mittels ‚cat‘ ausgegebenen Key bei „secret“ hinterlegen

  • Die IP-Adresse des Slave-Servers angeben

# Dateiinhalt von '/etc/bind/tsig.key'
#

key "TRANSFER" {
          algorithm hmac-md5;
          secret "8kvk9rllTIsb/WlBYvLQdSsXKoMJ8uCUYYLIAy0DMoOmNdZiAgdK+yloqCDZnDya1CIrYAbsVV8mi1/nI3v0CQ==";
};

# Slave server IP # 1
server 10.20.30.4 {
        keys {
                TRANSFER;
    };
};

################################
# If you have 3rd slave server with IP 64.1.2.3
#server 64.1.2.3 {
#        keys {
#                TRANSFER;
#    };
#};
################################

Weitere Schritte sind das Einbinden der Schlüsseldatei sowie die Anpassung der Dateirechte:

$ echo 'include "/etc/bind/tsig.key";' >> named.conf
$
$ tail -4 named.conf
include "/etc/bind/named.conf.options";
include "/etc/bind/named.conf.local";
include "/etc/bind/named.conf.default-zones";
include "/etc/bind/tsig.key";
$
$ chmod 640 tsig.key

Nun legen wir fest, wer die Datensätze replizieren darf:

$ vi /etc/bind/named.conf.local

Dazu fügen wir die jeweilige Zonendefinition folgendes ein:

allow-transfer {  key TRANSFER; };

Jetzt können wir den Daemon schon mal neu starten:

$ systemctl restart bind9

Und kopieren schließlich nur noch den Schlüssel für die spätere Übertragung an einen passenden Ort:

$ cp /etc/bind/tsig.key /home/tux
$ chmod 700 /home/tux/
$ chown tux: /home/tux/tsig.key

B) Auf dem Slave

Wir müssen uns nun die Schlüsseldatei hierher auf den Slave-Server kopieren und wieder die Rechte anpassen:

$ scp tux@10.20.30.3:tsig.key /etc/bind
$ chmod 640 /etc/bind/tsig.key
$ chown root:bind /etc/bind/tsig.key

Die nächsten Schritte sind das Einbinden und Anpassen der Datei ‚/etc/bind/tsig.key‘ in ähnlicher Weise wie auf dem Master-Server, nur dass jetzt anstelle der IP-Adresse des Slaves die des Masters eingetragen werden muss:

$ echo 'include "/etc/bind/tsig.key";' >> named.conf
$ vi /etc/bind/tsig.key

Mit grep -v ^# /etc/bind/tsig.key kontrollieren wir abschließend die Einstellungen:

key "TRANSFER" {
        algorithm hmac-md5;
    secret "8kvk9rllTIsb/WlBYvLQdSsXKoMJ8uCUYYLIAy0DMoOmNdZiAgdK+yloqCDZnDya1CIrYAbsVV8mi1/nI3v0CQ==";
};
server 10.20.30.3 {
        keys {
                TRANSFER;
    };
};

Die Datei ‚/etc/bind/named.conf.local‘ muss hier nicht um die Direktive allow-transfer {  key TRANSFER; }; in der Zonendefinition erweitert werden.

Es fehlt schließlich nur noch ein Neustart des Daemons:

$ systemctl restart bind9

Have a‘ lot of fun…

Kennenlernen von DNSSEC

ZIEL: Asymmetrische Verschlüsselung für die Authentizitätsprüfung kennenlernen und verstehen (Bei eventuellen praktischen Versuchen am besten vorher VM-Snapshot anlegen!)

Erste Schritte mit DNSSEC

Zu den Grundlagen siehe:

Mehr Entropie für lange Schlüssel

QUELLE https://www.digitalocean.com/community/tutorials/how-to-setup-additional-entropy-for-cloud-servers

Damit das Erzeugen der Schlüsseln nachher schneller geht, installieren wir zuerst haveged und überprüfen, ob der Daemon läuft:

$ pgrep -a have
516 /usr/sbin/haveged --Foreground --verbose=1 -w 1024
$

Gut verfahren lässt sich nach dem Tutorial von https://www.digitalocean.com/community/tutorials/how-to-setup-dnssec-on-an-authoritative-bind-dns-server–2

ACHTUNG: Die Direktive dnssec-validation auto; bitte in der Datei named.conf.options auskommentieren, sie ist schon per Default gesetzt. Ansonsten kann sie einfach wie im Folgenden gezeigt, mit sed nachträglich entfernt werden.

Hinzufügen müssen wir in diese Datei dann folgendes:

dnssec-enable yes;
dnssec-validation yes;
dnssec-lookaside auto;

Das folgende Hilfsskript macht uns nachher das Ergänzen unseres Zonefiles um die Schlüssel einfacher:

$ cat /home/tux/include-key.sh

Und das ist der Inhalt:

for key in `ls Kdom1.test*.key`
  do
     echo "\$INCLUDE $key">> db.dom1.test
done

Nun geht es mit der Schlüsselerzeugung des Zone Signing Keys (ZSK) los:

$ dnssec-keygen -a NSEC3RSASHA1 -b 2048 -n ZONE dom1.test
Generating key pair.......................................................+++ ......................+++
Kdom1.test.+007+50675
$
$ ls -ltrc
insgesamt 60
-rw-r--r-- 1 root root   375 Nov  1 17:04 db.10.20.30
-rw-r--r-- 1 root root    53 Nov  3 08:00 bind9-default.md5sum
-rw-r--r-- 1 bind bind   540 Nov  3 11:14 db.dom1.test
-rw------- 1 root root  1779 Nov  3 11:36 Kdom1.test.+007+50675.private
-rw-r--r-- 1 root root   602 Nov  3 11:36 Kdom1.test.+007+50675.key

Danach wird ein Key Signing Key (KSK) erzeugt:

$ dnssec-keygen -f KSK -a NSEC3RSASHA1 -b 4096 -n ZONE dom1.test
Generating key pair................................++ ...........................................++
Kdom1.test.+007+23568
$
$ ls -ltrc
insgesamt 68
-rw-r--r-- 1 root root   375 Nov  1 17:04 db.10.20.30
-rw-r--r-- 1 root root    53 Nov  3 08:00 bind9-default.md5sum
-rw-r--r-- 1 bind bind   540 Nov  3 11:14 db.dom1.test
-rw------- 1 root root  1779 Nov  3 11:36 Kdom1.test.+007+50675.private
-rw-r--r-- 1 root root   602 Nov  3 11:36 Kdom1.test.+007+50675.key
-rw------- 1 root root  3319 Nov  3 11:38 Kdom1.test.+007+23568.private
-rw-r--r-- 1 root root   947 Nov  3 11:38 Kdom1.test.+007+23568.key
$

Die 4 neuen Schlüsselpaare (ZSK und KSK) werden nun weiterverwendet. Mit Hilfe des o.g. Skriptes werden die öffentlichen Schlüssel, die den DNSKEY-Record des Zonenfiles enthalten, hinzugefügt.

$ bash /home/tux/include-key.script
$
$ tail -5 db.dom1.test
xp2                     A       10.20.30.127
xphost                  A       10.20.30.126
testhost                A       10.20.30.128
$INCLUDE Kdom1.test.+007+23568.key
$INCLUDE Kdom1.test.+007+50675.key
$

Als letztes wird die Zone signiert, wobei der Salt-Anteil durch Zufallszahlen ersetzt wird:

$ dnssec-signzone -A -3 $(head -c 1000 /dev/random | sha1sum | cut -b 1-16) -N INCREMENT -o dom1.test -t db.dom1.test
Verifying the zone using the following algorithms: NSEC3RSASHA1.
Zone fully signed:
Algorithm: NSEC3RSASHA1: KSKs: 1 active, 0 stand-by, 0 revoked
                         ZSKs: 1 active, 0 stand-by, 0 revoked
db.dom1.test.signed
Signatures generated:                       20
Signatures retained:                         0
Signatures dropped:                          0
Signatures successfully verified:            0
Signatures unsuccessfully verified:          0
Signing time in seconds:                 0.029
Signatures per second:                 689.441
Runtime in seconds:                      0.051
$

Zur Kontrolle der Ergebnisse sei dem geneigten Leser schließlich dieser Output mitgegeben:

$ ls -ltrc | tail -5
-rw------- 1 root root  3319 Nov  3 11:38 Kdom1.test.+007+23568.private
-rw-r--r-- 1 root root   947 Nov  3 11:38 Kdom1.test.+007+23568.key
-rw-r--r-- 1 bind bind   610 Nov  3 11:40 db.dom1.test
-rw-r--r-- 1 root root   163 Nov  3 11:42 dsset-dom1.test.
-rw-r--r-- 1 root root 13313 Nov  3 11:42 db.dom1.test.signed
$


$ ls -l
insgesamt 88
-rw-r--r-- 1 root root    53 Nov  3 08:00 bind9-default.md5sum
-rw-r--r-- 1 root root   375 Nov  1 17:04 db.10.20.30
-rw-r--r-- 1 bind bind   610 Nov  3 11:40 db.dom1.test
-rw-r--r-- 1 root root 13313 Nov  3 11:42 db.dom1.test.signed
-rw-r--r-- 1 root root   163 Nov  3 11:42 dsset-dom1.test.
-rw-r--r-- 1 root root   947 Nov  3 11:38 Kdom1.test.+007+23568.key
-rw------- 1 root root  3319 Nov  3 11:38 Kdom1.test.+007+23568.private
-rw-r--r-- 1 root root   602 Nov  3 11:36 Kdom1.test.+007+50675.key
-rw------- 1 root root  1779 Nov  3 11:36 Kdom1.test.+007+50675.private
$
$ less Kdom1.test.+007+23568.key
$
$ less Kdom1.test.+007+23568.private
$
$ cat Kdom1.test.+007+50675.key
; This is a zone-signing key, keyid 50675, for dom1.test.
; Created: 20161103103631 (Thu Nov  3 11:36:31 2016)
; Publish: 20161103103631 (Thu Nov  3 11:36:31 2016)
; Activate: 20161103103631 (Thu Nov  3 11:36:31 2016)
dom1.test. IN DNSKEY 256 3 7 AwEAAcGkG9CjVlJKlJb8nv0lRyCn3x5Akt2SPoJaiAHjTjlEfpqHd1ra 6Etxkk5+bWn0xuIXNPsfyYX4ZibpIrffCo/xzuwseQhNjr2vNlSxxdRK zSPFZ4kmf9C3Er77/JF9OLe6roag3E2B4PRmr9O0xy4JO9ea4tXm4NWh VDJWy+6c2Ht70lyiaI1Cf+EYZfmBlH5i3lw8BbeKJs3FM2PzxImVO2kr 6o+IN2ets8pZUyAS4if3JrZhLDMbF0K7jxJXaTcnUnUVmf2T8oawpr89 xxZ8DWzb8rJCeS0pbl6WSbn347YTJO4wDTmGUoDGW2EGVryWe54SFTV4 U6miOwulkvk=
$
$ head Kdom1.test.+007+50675.private
Private-key-format: v1.3
Algorithm: 7 (NSEC3RSASHA1)
Modulus: waQb0KNWUkqUlvye/SVHIKffHkCS3ZI+glqIAeNOOUR+mod3WtroS3GSTn5tafTG4hc0+x/JhfhmJukit98Kj/HO7Cx5CE2Ova82VLHF1ErNI8VniSZ/0LcSvvv8kX04t7quhqDcTYHg9Gav07THLgk715ri1ebg1aFUMlbL7pzYe3vSXKJojUJ/4Rhl+YGUfmLeXDwFt4omzcUzY/PEiZU7aSvqj4g3Z62zyllTIBLiJ/cmtmEsMxsXQruPEldpNydSdRWZ/ZPyhrCmvz3HFnwNbNvyskJ5LSluXpZJuffjthMk7jANOYZSgMZbYQZWvJZ7nhIVNXhTqaI7C6WS+Q==
PublicExponent: AQAB
PrivateExponent: wKUzxu25A0WPbmcFBXQAv0xDfSVg9253IdhPVxF80RyDl9kNtSXz1Jq4o77Du5X6BxRvcSa+prnpZuypzaPoLiyzX+MexlPinnOh6cCyv/FrBRtvVdMndc2sqLSpIVUjCCaBWw7OHY4I7xz57/T586LcFjPRWFzJcb9+tFYFrOxCr6zryRiBt0x3wovEPfM0paCfMpjlAG0WFd2vlU24sOn68/CsWMeXtTy6lMbg8DFC5peVABVYsAFG9RWs+FwZKZNMOSIFIiF1e07ICMT4EbaoRrJKMb9VcbScWbb753tjYZ0J4+W3yYo+/51x2uyGYCt+7jkHwr+3/wTOwVTIwQ==
Prime1: 3veH134Fo/VKXs0k/PRfNKKMjYFppGcFEXlahh4zr0YueyjFcLN0a2SBKprFiAOykHu3iZ41dRJg72BzXmkCJyZwJol6yF0QoPR3asGVmzLxY7qpfD3Z/q/6Ypd73PVPZpZbu/cN42HPcTkQm4demAjuYIMd/41kG8n9bnY8LzM=
Prime2: 3lRV3+UxHHuEmmQpKMcZgZ9RndysuElZlbn8NtdR1pJ74BxLdh22AGsgiZ6kGs3nH4KOaOwHbrxcdfJgrsDK+w3W79BIt5o0cnCY1iBox9mO1S3qRtHZl8KQDQpvdsNPbV4IyENGfdazhFPZPPV95nssGT7LKfb0Qy/BJAIEZSM=
Exponent1: YSbiHddfhc1/lkc08rNYOIsLSy00Ztosryx9cSr/wkOGRUvCnBTViWXFklbV8yoJSENf+ariCBz199fC7UQ8F+r7uw70XRGQCVH8JpwrH/DWlWnkJ6qbrgnnw8XVxrVs33pshj5j4svfo6oFvn8BjKV3mL4I+C0XjbQ5pUQHfVk=
Exponent2: usGm/RMeBOnwwmv+cwWD9HFq8qsq3wamXPJE3aBTW2Xi7qd17/sXJhTW2SNMgEOTsNFPZO1XdPp+xIjcFA9Ysji24u1YF/pNsg/JIp1Ixw+GPqZ6FBE0sZk6vemVJfL8JkeGIwr4DL6sPyzb36vrnQ68RVyM9mw+VK2plOCo5nc=
Coefficient: zPeQaoYzo7TuLDCXpgadzc7+uir1FAOMwqTIhQW8wdNuMAsquh2KgkkakHalv0h3vfO9hyKWfUKTHQK7eFmjIb/gSo1ZHD0vxI1pAfzvWwoKZXfVtQ5A6ixhPPMhTSte3BaJpt0POY7Rq1VHdHpyY7wN5dxGj/8t3PWZCCHYSlU=
$

Bind-Version unterdrücken

In der Standardeinstellung verrät nämlich der Daemon die ganze Karte:

$ dig @localhost version.bind txt chaos

; <<>> DiG 9.10.3-P4-Ubuntu <<>> @localhost version.bind txt chaos
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 56569
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;version.bind.                  CH      TXT

;; ANSWER SECTION:
version.bind.           0       CH      TXT     "9.10.3-P4-Ubuntu"

;; AUTHORITY SECTION:
version.bind.           0       CH      NS      version.bind.

;; Query time: 0 msec
;; SERVER: ::1#53(::1)
;; WHEN: Thu Nov 03 11:21:59 CET 2016
;; MSG SIZE  rcvd: 84

$
$ vi /etc/bind/named.conf.options

Wir fügen hier eine Zeile ein:

version "Not supported";

Nun verrät unser Server nicht mehr seine Version:

$ dig @localhost version.bind txt chaos

; <<>> DiG 9.10.3-P4-Ubuntu <<>> @localhost version.bind txt chaos
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 36261
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;version.bind.                  CH      TXT

;; ANSWER SECTION:
version.bind.           0       CH      TXT     "Not supported"

;; AUTHORITY SECTION:
version.bind.           0       CH      NS      version.bind.

;; Query time: 0 msec
;; SERVER: ::1#53(::1)
;; WHEN: Thu Nov 03 13:51:39 CET 2016
;; MSG SIZE  rcvd: 81

$

Siehe auch https://raymii.org/s/tutorials/Get_DNS_server_version_and_hide_it_in_BIND.html

Andere DNS-Server

Chroot für bind9

(Ein missglückter Versuch)

Siehe:

$ ps auxZ | grep -v uncon
LABEL                           USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
/usr/sbin/named (enforce)       bind      2352  0.0  3.9 208892 19804 ?        Ssl  09:26   0:00 /usr/sbin/named -f -u bind
$
$
$ vi mychroot-setup.sh
$
$ cat mychroot-setup.sh
mkdir -p /var/bind9/chroot/{etc,dev,var/cache/bind,var/run/named}
mknod /var/bind9/chroot/dev/null c 1 3
mknod /var/bind9/chroot/dev/random c 1 8
chmod 660 /var/bind9/chroot/dev/{null,random}
$
$ bash mychroot-setup.sh
$
$ ls -lR /var/bind9/
/var/bind9/:
insgesamt 4
drwxr-xr-x 5 root root 4096 Nov  4 09:31 chroot

/var/bind9/chroot:
insgesamt 12
drwxr-xr-x 2 root root 4096 Nov  4 09:31 dev
drwxr-xr-x 2 root root 4096 Nov  4 09:31 etc
drwxr-xr-x 4 root root 4096 Nov  4 09:31 var

/var/bind9/chroot/dev:
insgesamt 0
crw-rw---- 1 root root 1, 3 Nov  4 09:31 null
crw-rw---- 1 root root 1, 8 Nov  4 09:31 random

/var/bind9/chroot/etc:
insgesamt 0

/var/bind9/chroot/var:
insgesamt 8
drwxr-xr-x 3 root root 4096 Nov  4 09:31 cache
drwxr-xr-x 3 root root 4096 Nov  4 09:31 run

/var/bind9/chroot/var/cache:
insgesamt 4
drwxr-xr-x 2 root root 4096 Nov  4 09:31 bind

/var/bind9/chroot/var/cache/bind:
insgesamt 0

/var/bind9/chroot/var/run:
insgesamt 4
drwxr-xr-x 2 root root 4096 Nov  4 09:31 named

/var/bind9/chroot/var/run/named:
insgesamt 0
$
$ systemctl stop bind9
$
$ systemctl stop isc-dhcp-server.service
$
$ mv /etc/bind /var/bind9/chroot/etc/
$
$ ln -s /var/bind9/chroot/etc/bind/ /etc/bind
$
$ ls -l /etc/bind
bind/                   bindresvport.blacklist
$ ls -l /etc/bind/named.conf*
-rw-r--r-- 1 root bind 575 Nov  1 16:32 /etc/bind/named.conf
-rw-r--r-- 1 root bind 490 Sep 26 21:57 /etc/bind/named.conf.default-zones
-rw-r--r-- 1 root bind 530 Nov  1 17:24 /etc/bind/named.conf.local
-rw-r--r-- 1 root bind 165 Sep 26 21:57 /etc/bind/named.conf.local~
-rw-r--r-- 1 root bind 918 Nov  3 13:51 /etc/bind/named.conf.options
$
$
$ cp /etc/localtime /var/bind9/chroot/etc/
$
$ chown bind:bind /var/bind9/chroot/etc/bind/rndc.key
$ chmod 775 /var/bind9/chroot/var/{cache/bind,run/named}
$ chgrp bind /var/bind9/chroot/var/{cache/bind,run/named}
$
$
$

Startkonfiguration anpassen:

$ vi /etc/init.d/bind9
$
$
$
$ echo "\$AddUnixListenSocket /var/bind9/chroot/dev/log" > /etc/rsyslog.d/
20-ufw.conf      50-default.conf
$ echo "\$AddUnixListenSocket /var/bind9/chroot/dev/log" > /etc/rsyslog.d/bind-chroot.onf
$
$ cat /etc/rsyslog.d/bind-chroot.conf
$AddUnixListenSocket /var/bind9/chroot/dev/log
$

Ermitteln, welches die Unit-Datei ist:

$ systemctl status bind9.service | grep loaded

Nach dem bearbeiten:

$ cat /lib/systemd/system/bind9.service
[Unit]
Description=BIND Domain Name Server
Documentation=man:named(8)
After=network.target

[Service]
#ExecStart=/usr/sbin/named -f -u bind
ExecStart=/usr/sbin/named -f -u bind -t /var/bind9/chroot
ExecReload=/usr/sbin/rndc reload
ExecStop=/usr/sbin/rndc stop

[Install]
WantedBy=multi-user.target
$
$ systemctl restart bind9
Warning: bind9.service changed on disk. Run 'systemctl daemon-reload' to reload units.
$ systemctl daemon-reload
$
$ systemctl restart bind9
$

Leider sind im Syslog viele Fehler zu finden, die einen Start des bind-Daemons verhindern. Offenbar liegt es an fehlenden Libraries in der chroot-Umgebung.

DNS blocking

Siehe dazu:

Topic 208: Web Services

208.1 Implementing a web server

Ein LAMP-System aufsetzen

Die Bestandteile:

  • Linux (Ubuntu Server)

  • Apache (Version 2)

  • MySQL als Datenbank

  • PHP oder Perl als serversetige Skriptsprache

Installation unter Debian / Ubuntu

Bei der Installation muss ein Passwort für die MySQL-Datenbank gesetzt werden!:

$ apt-get install apache2 mysql-server php php-mysql libapache2-mod-php

Normalerweise wird der Webserver auch gleich gestartet, Port 80 wird geöffnet:

$ telnet localhost 80
Trying ::1...
Connected to localhost.
Escape character is '^]'.
HEAD / HTTP/1.1

HTTP/1.1 400 Bad Request
Date: Mon, 07 Nov 2016 10:05:13 GMT
Server: Apache/2.4.18 (Ubuntu)
Connection: close
Content-Type: text/html; charset=iso-8859-1

Connection closed by foreign host.
$

Eine PHP-Testseite im Verzeichnis /var/www/html (= DocumentRoot) erzeugen:

$ cat > phpinfo.php <<EOF
 <?php
      phpinfo();
 ?>
 > EOF
$
$ cat phpinfo.php
 <?php
      phpinfo();
 ?>
$
$ pgrep -a sql
 4914 /usr/sbin/mysqld
$

Dann in einem Webbrowser diese Seite aufrufen:

http://IP-des-Apache/phpinfo.php

HINWEIS: Falls über einen Router (Tiny Core Linux) hinweg auf den Web-Server zugefiffen werden soll, ist die folgende Zeile erforderlich (vom Windows-Host aus durch diesen Router hindurch, Port-Forwarding):

$ iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination 10.20.30.3

Testszenario: Wordpress installieren

ZIEL: Erfahrungen sammeln….

$ https://wordpress.org/latest.tar.gz
$ tar -xf latest.tar.gz
$
$ mv wordpress/ wp
$
$ grep www-data /etc/passwd /etc/group
 /etc/passwd:www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
 /etc/group:www-data:x:33:
$
$ chown -R www-data: wp

Nun müssen wir lediglich eine Datenbank anlegen, das geht ganz einfach mit:

$ mysqladmin -u root -p create wordpress

(MySQL-root-Passwort eingeben!)

Nun geht es im Web-UI mit der Installation weiter:

$ firefox http://localhost/wp

Auszufüllen sind nur wenige Felder, vor allem den Datenbank-Benutzername root und das dazugehörige Passwort toor:

a) Hier sollten die Zugangsdaten zu deiner Datenbank eingetragen werden. Im Zweifel frage bitte deinen Webhoster.
b) Datenbank Name -     Der Name der Datenbank, die du für WordPress benutzen möchtest. (wordpress)
c) Benutzername - Dein Datenbank-Benutzername. (root)
d) Passwort - Dein Datenbank-Passwort. (toor)
e) Datenbank-Host - Sollte localhost nicht funktionieren, erfrage bitte den korrekten Wert bei deinem Web-Hoster. (localhost)
f) Tabellen-Präfix - Falls du mehrere WordPress-Installationen innerhalb einer Datenbank aufbauen möchtest, ändere diesen

In Sachen Troubleshooting kann man sich z.B. einfach in die Datenbank einloggen:

$ mysql -p -u root
 Enter password:
 Welcome to the MySQL monitor.  Commands end with ; or \g.
 Your MySQL connection id is 7
 Server version: 5.7.16-0ubuntu0.16.04.1 (Ubuntu)

 Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.

 Oracle is a registered trademark of Oracle Corporation and/or its
 affiliates. Other names may be trademarks of their respective
 owners.

 Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

 mysql> ^DBye
$

Sicherheit verbessern:

$ grep -r axel
$
$ grep -r toor
 wp/wp-config.php:define('DB_PASSWORD', 'toor');
$
$
$ ls -l wp/wp-config.php
 -rw-rw-rw- 1 www-data www-data 3125 Nov  7 11:46 wp/wp-config.php
$
$
$ chmod 440 wp/wp-config.php

Webserver Apache

Grundlegende Konfiguration

Wir begeben uns dazu ins „ServerRoot“-Verzeichnis (cd /etc/apache2), um dort nach grundlegend wichtigen Direktiven zu suchen, wie z.B.:

  • ServerRoot

  • DocumentRoot

  • DirectoryIndex

  • Options

  • VirtualHost

$ cd /etc/apache2
$
$ grep --color -r ServerRoot
apache2.conf:# ServerRoot: The top of the directory tree under which the server's
apache2.conf:#ServerRoot "/etc/apache2"
$
$
$
$ grep --color -r DocumentRoot
sites-available/000-default.conf:       DocumentRoot /var/www/html
sites-available/default-ssl.conf:               DocumentRoot /var/www/html
$
$
$ grep --color -r DirectoryIndex
mods-available/dir.conf:        DirectoryIndex index.html index.cgi index.pl index.php index.xhtml index.htm
$
$
$ grep --color -r Virtual
conf-available/localized-error-pages.conf:# even on a per-VirtualHost basis.  If you include the Alias in the global server
conf-available/other-vhosts-access-log.conf:# Define an access log for VirtualHosts that don't define their own logfile
ports.conf:# have to change the VirtualHost statement in
apache2.conf:# If you do not specify an ErrorLog directive within a <VirtualHost>
apache2.conf:# logged here.  If you *do* define an error logfile for a <VirtualHost>
sites-available/000-default.conf:<VirtualHost *:80>
sites-available/000-default.conf:</VirtualHost>
sites-available/default-ssl.conf:       <VirtualHost _default_:443>
sites-available/default-ssl.conf:       </VirtualHost>
$
$
$
$ ls -l sites-enabled/
insgesamt 0
lrwxrwxrwx 1 root root 35 Nov  7 11:02 000-default.conf -> ../sites-available/000-default.conf
$

Directory Listing

Für den folgenden Test benennen wir die Standardseite index.html in start.html um. Nach der clientseitigen Aktualisierung (im Webbrowser) ist dann zu beobachten, dass sich der Server öffnet und alle seine weiteren Dateien und Verzeichnisse auflistet:

$ mv /var/www/html/index.html  /var/www/html/start.html

ZIEL: Das Directory-Listing abschalten (Direktive: Options Indexes)

Am praktischsten verfährt man dabei so, dass die verantwortliche Datei über ihren Symlink aufgerufen wird (via Verzeichnis sites-enabled):

$ vi /etc/apache2/sites-enabled/000-default.conf

Diesen Abschnitt unterhalb von DocumentRoot /var/www/html einfügen:

<Directory /var/www/html/>
    Options none
    AllowOverride None
    Require all granted
</Directory>

Danach die Konfiguration mit apachectl graceful neu einlesen (= reload).

Siehe auch https://wiki.apache.org/httpd/DirectoryListings

Apache historisch: httpd.conf

Siehe https://www.pantz.org/software/apache/apache13config.html

Zugriffsschutz einrichten

Grundlegend gibt es zwei Möglichkeiten:

  1. Mittels separater .htaccess-Datei in DocumentRoot („Directory-level configuration“)

  2. Mittels einer Directory-Anweisung (z.B. in Konfigdatei eines Vhosts)

Für beides benötigen wir die Direktive AllowOverride AuthConfig und Kommando htpasswd.

Siehe auch https://httpd.apache.org/docs/2.4/de/mod/core.html#allowoverride

Zur Methode A) via .htaccess
$ vi /etc/apache/sites-enabled/000-default.conf
### Hinzugefügter Abschnitt, um die Server-Defaults zu überschreiben
<Directory /var/www/html/>
        Options none
        AllowOverride AuthConfig
        Require all granted
</Directory>
$ apachectl graceful
$ mkdir /var/www/html/privat
$ vi /var/www/html/privat/.htaccess
## Dateiname: .htaccess
## Diese versteckte Datei schützt ein privates Verzeichnis mit Benutzername/Passwort-Paar
##
## VORAUSSETZUNG: Apache muss mit Einstellung 'AllowOverride AuthConfig' des virtuellen
## Hosts neu gestartet werden!
## Zu finden ist sie innerhalb der Directory-Direktive des "DocumentRoot"-Vereichnispfades.
##
## Die Passwortdatei wird erstmalig zusammen mit dem ersten Benutzer kreiert:
##
##        htpasswd -c /etc/apache2/passwords/access-passwd susi
##
## Später MUSS der Schalter '-c'  beim Anlegen neuer Benutzer sowie beim Ändern eines
## Passworts WEGGELASSEN werden.
## Ansonsten wird die Datei ohne Rückfrage überschrieben!!

AuthName        "Adminbereich"
AuthType        Basic
## Passwortdatei muss mit absolutem Pfad angegeben werden:
AuthUserFile   /etc/apache2/passwords/access-passwd

<Limit GET POST PUT>
## Alternativ kann ein bestimmter Benutzer abverlangt werden:
#require user tux max lisa
require valid-user
</Limit>

ACHTUNG: Wird die Datei nicht richtig benannt oder weggschoben, dann ist damit auch der der Schutz weg!

Überzeugen wir uns:

$ mv /var/www/html/privat/.htaccess /var/www/html/privat/.htacces
   ... F5 im Webbrower drücken: Alles offen!
Zur Methode B) via <VIRTUAL-HOST>.conf

Siehe dazu den Abschnitt Privates Verzeichnis für Firma 2, was im Dokument über Apaches virtuelle Hosts beschrieben wird.

Virtuelle Hosts für Apache2

Siehe dazu das Dokument Apache - virtuelle Hosts

208.2 Apache configuration for HTTPS

Grundlagen

Im OSI-Modell ist TLS-Protokoll zwischen den Schichten 5 bis 6 angesiedelt.

Zur Sicherheit des hierarchischen und pyramidenförmigen Aufbaus (Protokoll: X.509):

Kostenlose Zertifikate gibt es, aber

Einrichtung der Verschlüsselung

Ein selbstsignierters Zertifikat ist schnell erzeugt. Nach dem Aktivieren des Moduls mittels a2enmod ssl und dem Neustart von Apache kann das Zertifikat mit nur einer Zeile und der Fingerabdruck zur späteren Verifizierung mit einer weiteren erstellt werden:

$ cd /etc/ssl/
$ openssl req -new -outform PEM -out certs/testing.pem -newkey rsa:2048 -nodes \
    -keyout private/testing.key -keyform PEM -days 3650 -x509
$ openssl x509 -fingerprint -noout -in testing.pem

Hier speziell ein Auszug der Schritte für Debian 8 (Jessie) mit Apache 2.4.10:

$ cd /etc/ssl/
$
$ ls -l
insgesamt 36
drwxr-xr-x 2 root root     20480 Nov  7 11:03 certs
-rw-r--r-- 1 root root     10835 Mai  2  2016 openssl.cnf
drwx--x--- 2 root ssl-cert  4096 Nov  7 11:03 private
$
$ openssl req -new -outform PEM -out certs/myweb.pem -newkey rsa:2048 -nodes -keyout private/myweb.key -keyform PEM -days 3650 -x509
Generating a 2048 bit RSA private key
..............................................................+++
...............+++
writing new private key to 'private/myweb.key'
 -----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
 -----
Country Name (2 letter code) [AU]:DE
State or Province Name (full name) [Some-State]:Sachsen
Locality Name (eg, city) []:Dresden
Organization Name (eg, company) [Internet Widgits Pty Ltd]:ComCave
Organizational Unit Name (eg, section) []:Technik
Common Name (e.g. server FQDN or YOUR name) []:www.dom1.test
Email Address []:axel@pemmann.de
$
$
$ head -4 private/myweb.key certs/myweb.pem
=$ private/myweb.key <==
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCqn7/oIYfy/XTB
czdfL437TSoKHoSI84dHslvoAdFQBCr+aernXxaywvErtOeLbDYihW8vXShtHH05
dwBOnVQqGB0TKOeYyI1hSnmZfU8GHGAMEkdrD8P98mV53o9I3IFWjyLpL1xCNQRc

=$ certs/myweb.pem <==
-----BEGIN CERTIFICATE-----
MIID7zCCAtegAwIBAgIJALrpEOAkl9tGMA0GCSqGSIb3DQEBCwUAMIGNMQswCQYD
VQQGEwJERTEQMA4GA1UECAwHU2FjaHNlbjEQMA4GA1UEBwwHRHJlc2RlbjEQMA4G
A1UECgwHQ29tQ2F2ZTEQMA4GA1UECwwHVGVjaG5pazEWMBQGA1UEAwwNd3d3LmRv
$

Danach die Apache-Konfig-Datei in Sachen Zertifikatsdatei und -schlüssel anpassen:

SSLEngine on
SSLCertificateFile      /etc/ssl/certs/myweb.pem
SSLCertificateKeyFile   /etc/ssl/private/myweb.key

LPI-RELEVANT: Ein auskommentierter Parameter ist u.a. SSLVerifyClient require. Damit kann eine clientseitige Authentifzierung mit Zertifikat erzwungen werden. Dies entspricht in etwa einem Anmeldevorgang mit einem Benutzername/Passwort-Paar. Siehe dazu http://www.phpgangsta.de/client-zertifikate-als-sicherer-login-ersatz

Insgesamt sieht die Datei dann so aus:

$ grep -v \#  sites-enabled/default-ssl.conf | grep -v '^$'
<IfModule mod_ssl.c>
        <VirtualHost _default_:443>
                ServerAdmin webmaster@localhost
                DocumentRoot /var/www/html
                ErrorLog ${APACHE_LOG_DIR}/error.log
                CustomLog ${APACHE_LOG_DIR}/access.log combined
                SSLEngine on
                SSLCertificateFile      /etc/ssl/certs/myweb.pem
                SSLCertificateKeyFile /etc/ssl/private/myweb.key
                <FilesMatch "\.(cgi|shtml|phtml|php)$">
                                SSLOptions +StdEnvVars
                </FilesMatch>
                <Directory /usr/lib/cgi-bin>
                                SSLOptions +StdEnvVars
                </Directory>
        </VirtualHost>
</IfModule>
$

Nun müssen noch diese Konfigurationsdatei sowie das SSL-Modul aktiviert werden:

$ a2ensite default-ssl.conf
$ a2enmode ssl
$ apache2ctl restart

Mit apachectl -M | grep -i ssl kann überprüft werden, ob das Modul aktiviert wurde.

Kommandozeilenbasierten Verbindungsaufbau durchführen

$ openssl s_client -tls1_2 -connect 10.20.30.3:443

Die Ausgabe sieht dann so aus:

CONNECTED(00000003)
depth=0 C = DE, ST = Sachsen, L = Dresden, O = ComCave, OU = Technik, CN = www.dom1.test, emailAddress = axel@pemmann.de
verify error:num=18:self signed certificate
verify return:1
depth=0 C = DE, ST = Sachsen, L = Dresden, O = ComCave, OU = Technik, CN = www.dom1.test, emailAddress = axel@pemmann.de
verify return:1
---
Certificate chain
 0 s:/C=DE/ST=Sachsen/L=Dresden/O=ComCave/OU=Technik/CN=www.dom1.test/emailAddress=axel@pemmann.de
   i:/C=DE/ST=Sachsen/L=Dresden/O=ComCave/OU=Technik/CN=www.dom1.test/emailAddress=axel@pemmann.de
---
Server certificate
-----BEGIN CERTIFICATE-----
MIID7zCCAtegAwIBAgIJALrpEOAkl9tGMA0GCSqGSIb3DQEBCwUAMIGNMQswCQYD
VQQGEwJERTEQMA4GA1UECAwHU2FjaHNlbjEQMA4GA1UEBwwHRHJlc2RlbjEQMA4G
A1UECgwHQ29tQ2F2ZTEQMA4GA1UECwwHVGVjaG5pazEWMBQGA1UEAwwNd3d3LmRv


... usw. ...

    Start Time: 1478693723
    Timeout   : 7200 (sec)
    Verify return code: 18 (self signed certificate)

    ^C

208.3 Implementing a proxy server

ZIEL: Ein sehr sicheren, cachenden HTTP-Proxy (Stellvertreter-Dienst nicht nur für HTTP) installieren und konfigurieren:

$ apt-get install squid3
Paketlisten werden gelesen... Fertig
Abhängigkeitsbaum wird aufgebaut.
Statusinformationen werden eingelesen.... Fertig
Die folgenden zusätzlichen Pakete werden installiert:
  libecap2 libltdl7 libnetfilter-conntrack3 squid-langpack squid3-common
Vorgeschlagene Pakete:
  squidclient squid-cgi squid-purge resolvconf smbclient ufw winbindd
Die folgenden NEUEN Pakete werden installiert:
  libecap2 libltdl7 libnetfilter-conntrack3 squid-langpack squid3 squid3-common
0 aktualisiert, 6 neu installiert, 0 zu entfernen und 20 nicht aktualisiert.
Es müssen 2.575 kB an Archiven heruntergeladen werden.
Nach dieser Operation werden 9.115 kB Plattenplatz zusätzlich benutzt.
Möchten Sie fortfahren? [J/n]

Konfiguration des Servers

ACHTUNG: Es ist das ganze Handbuch enthalten, deshalb erst einmal nur die aktiven Zeilen ausgeben:

$ grep -Ev '^\s*#|^$' /etc/squid3/squid.conf
acl SSL_ports port 443
acl CONNECT method CONNECT
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports
http_access allow localhost manager
http_access deny manager
http_access allow localhost
http_access deny all
http_port 3128
coredump_dir /var/spool/squid3
refresh_pattern ^ftp:           1440    20%     10080
refresh_pattern ^gopher:        1440    0%      1440
refresh_pattern -i (/cgi-bin/|\?) 0     0%      0
refresh_pattern .               0       20%     4320
$

Wichtige Grundeinstellungen:

  • http_port 3128

  • cache_dir ufs /var/spool/squid3 100 16 256

  • cache_mem 256 MB

Der Proxy-Server arbeitet bei Debian per Default nur als lokal verwendbarer Server, deshalb müssen wir sogleich die Konfigurationsdatei ändern:

$ vi /etc/squid3/squid.conf

Wir suchen nach INSERT und schreiben unsere Regeln VOR die deny-Zeile (Hier herrscht batch-Betrieb!):

#
# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
#

# Example rule allowing access from your local networks.
# Adapt localnet in the ACL section to list your (internal) IP networks
# from where browsing should be allowed
#http_access allow localnet
http_access allow localhost

# And finally deny all other access to this proxy
http_access deny all

Wir schreiben oberhalb der Regel ‚http_access deny all‘ die zwei folgenden Zeilen hinein:

acl myDMZ src 10.20.30.0/24
http_access allow myDMZ

Oder aber einfach die fertigen Regeln mit localnet suchen und aktivieren:

$ grep -v '\#' /etc/squid3/squid.conf  | grep -v '^$'
acl SSL_ports port 443
acl CONNECT method CONNECT
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports
http_access allow localhost manager
http_access deny manager
http_access allow localnet
http_access allow localhost
http_access deny all
http_port 3128
coredump_dir /var/spool/squid3
refresh_pattern ^ftp:           1440    20%     10080
refresh_pattern ^gopher:        1440    0%      1440
refresh_pattern -i (/cgi-bin/|\?) 0     0%      0
refresh_pattern .               0       20%     4320
$
$ systemctl restart squid3.service
$ pgrep -a squid
4664 /usr/sbin/squid3 -YC -f /etc/squid3/squid.conf
4666 (squid-1) -YC -f /etc/squid3/squid.conf
$
$ tail -f /var/log/squid3/access.log

Konfiguration des Clients

Am besten zuerst einmal für Testzwecke die Variable ‚http_proxy‘ setzen:

$ export http_proxy="http://10.20.30.5:3128"
$ wget blindekuh.de

Port-Forwarding mit iptables

Falls der Proxy-Server hinter einem Router steht, lässt sich auf folgende Weise eine Portweiterleitung einrichten. Die dritte Zeile ist dabei die eigentliche für den Proxy-Serverzugriff erforderliche (Socket: 10.20.30.5:3128):

$ iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination 10.20.30.3
$ iptables -t nat -A PREROUTING -i eth0 -p udp --dport 53 -j DNAT --to-destination 10.20.30.3
$ iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 3128 -j DNAT --to-destination 10.20.30.5

Weitere Server-Einstellungen

Filter mit urlpath_regex

https://wiki.gentoo.org/wiki/Security_Handbook/Firewalls

Dort nach files.acl suchen:

Definition der ACL:

acl archives urlpath_regex "/etc/squid3/files.acl"

Dann weiter unten VOR der allow- und deny-Regel:

http_access deny archives

Insgesamt sieht das so aus:

acl archives urlpath_regex "/etc/squid3/files.acl"
http_access deny archives

http_access allow localnet
http_access allow localhost

# And finally deny all other access to this proxy
http_access deny all

AUFGABE: die Datei /etc/squid3/files.acl erstellen und testen:

\.[Zz][Ii][pP]$
\.[Vv][Ii][Vv].*
\.[Ee][Xx][Ee]$
\.[Mm][Pp]3$
\.[Rr][Aa][Rr]$
\.[Aa][Cc][Ee]$
\.[Aa][Ss][Ff]$
\.[Aa][Vv][Ii]$
\.[Mm][Oo][Vv]$
\.[Mm][Pp][Gg]$
\.[Mm][Pp][Ee][Gg]$
\.[Aa][Uu]$
\.[Rr][Aa]$
\.[Aa][Rr][Jj]$
\.[Tt][Aa][Rr]$
\.[Gg][Zz]$
\.[Zz]$
$ systemctl reload squid3

ACLs logisch verknüpfen

Es lassen sich problemlos logisch ODER- sowie UND-Verknüpfungen realisieren.

Im folgenden Beispiel werden zuerst einmal Datenpakete, die aus den beiden Netzwerken ‚10.20.30.0/24‘ sowie ‚10.22.15.0/24‘ herrühren (‚src‘), in einer ACL namens ‚myDMZ‘ mittels logischem ODER verknüpft und später entsprechend verarbeitet.

Danach wird in der ACL ‚surfZeit‘ eine Zeitspanne festgelegt.

Und schließlich geben wir mittels der ‚http_access‘-Direktive Zugriff auf den Cache des Proxies, wobei eine UND-Verknüpfung von ‚myDMZ‘ und ‚surfZeit‘ zur Anwendung kommt:

acl myDMZ src 10.20.30.0/24
acl myDMZ src 10.22.15.0/24
acl surfZeit time 12:00-13:00
http_access allow myDMZ surfZeit

Siehe dazu auch http://www.selflinux.org/selflinux/html/squid05.html

Mitsamt unserer obigen ACL namens ‚archives‘ und der Voreinstellungen gestaltet sich das Regelwerk unterhalb von ‚INSERT‘ dann so:

http_access allow localhost

acl archives urlpath_regex "/etc/squid3/files.acl"
acl myDMZ src 10.20.30.0/24
acl myDMZ src 10.22.15.0/24
acl surfzeit time 12:00-13:00
http_access deny archives
http_access allow myDMZ surfzeit

# And finally deny all other access to this proxy
http_access deny all

Benutzer-Authentifzierung

(Kurznotizen vom März 2013, Debian stable)

ÜBERBLICK (im oberen Bereich der Konfigdatei einzufügen):

  • Regeln mit auth_param definieren

  • Insbesondere muss ein ‚realm‘ festgelegt werden, Standard ist: „Squid proxy-caching web server“

  • Für einen Benutzer muss dann in Zusammenhang mit diesem ‚realm‘ ein Passwort-Dateieintrag erzeugt werden (md5sum aus einem Skript aufgerufen $ digest_passwd.sh)

  • Abschließend VOR dem Erlauben der „lokales Netz“-Regel ist die Authentifizieren abzuverlangen:

    • acl vertrautenutzer proxy_auth REQUIRED

    • http_acces allow vertrautenutzer

Inhalt der Datei ‚/etc/squid3/squid.conf‘:

auth_param digest program /usr/lib/squid3/digest_pw_auth -c  /etc/squid3/digestpw
auth_param digest children 5
auth_param digest realm Squid proxy-caching web server
auth_param digest nonce_garbage_interval 5 minutes
auth_param digest nonce_max_duration 30 minutes
auth_param digest nonce_max_count 50
acl manager proto cache_object
acl localhost src 127.0.0.1/32 ::1
acl to_localhost dst 127.0.0.0/8 0.0.0.0/32 ::1
acl SSL_ports port 443
acl Safe_ports port 80              # http
acl Safe_ports port 21              # ftp
acl Safe_ports port 443             # https
acl Safe_ports port 70              # gopher
acl Safe_ports port 210             # wais
acl Safe_ports port 1025-65535      # unregistered ports
acl Safe_ports port 280             # http-mgmt
acl Safe_ports port 488             # gss-http
acl Safe_ports port 591             # filemaker
acl Safe_ports port 777             # multiling http
acl CONNECT method CONNECT
http_access allow manager localhost
http_access deny manager
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports
acl trusted_users proxy_auth REQUIRED
http_access allow trusted_users
acl local_net src 10.2.3.0/24       # RFC1918 possible internal network
http_access allow local_net
acl INSIDE_IP dst 10.2.3.0/24
always_direct allow INSIDE_IP
never_direct allow all
http_access allow localhost
http_access deny all
http_port 3128 intercept
cache_peer 10.2.3.1 parent 3128 0 proxy-only
hierarchy_stoplist cgi-bin ?
coredump_dir /var/spool/squid3
refresh_pattern ^ftp:               1440    20%     10080
refresh_pattern ^gopher:    1440    0%      1440
refresh_pattern -i (/cgi-bin/|\?) 0 0%      0
refresh_pattern .           0       20%     4320

Inhalt der Datei ‚/etc/squid3/digestpw‘:

otto:Squid proxy-caching web server:89221b025babc71df635bca946ce0e21

Relevanter Anteil aus der ‚squid.conf‘:

# Wichtiger Hinweis
# http://www.squid-cache.org/Doc/config/auth_param/
# WARNING: authentication can't be used in a transparently intercepting
#   proxy as the client then thinks it is talking to an origin server and
#   not the proxy. This is a limitation of bending the TCP/IP protocol to
#   transparently intercepting port 80, not a limitation in Squid.
#   Ports flagged 'transparent', 'intercept', or 'tproxy' have
#   authentication disabled.

### Wichtige Voreinstellungen
auth_param digest program /usr/lib/squid3/digest_pw_auth -c  /etc/squid3/digestpw
auth_param digest children 5
auth_param digest realm Squid proxy-caching web server
auth_param digest nonce_garbage_interval 5 minutes
auth_param digest nonce_max_duration 30 minutes
auth_param digest nonce_max_count 50

### Eine dazu passende ACL (oberhalb der LAN-Zugriffs-Regel zu plazieren)
acl trusted_users proxy_auth REQUIRED
http_access allow trusted_users

Inhalt der Datei ‚digest_passwd.sh‘:

#!/bin/sh
#
# http://fsk141.com/tutorial-squid-proxy-with-digest-authentication
#
#
# AUFRUF: digest_passwd.sh name password 'Squid proxy-caching web server' > /etc/squid/digest_passwd

user=$1
pass=$2
realm=$3

if [ -z "$1" -o -z "$2" -o -z "$3" ] ; then
        echo "Usage: $0 user password 'realm'";
        exit 1
fi

ha1=$(echo -n "$user:$realm:$pass"|md5sum |cut -f1 -d' ')
echo "$user:$realm:$ha1"

Benachbarten Proxy-Cache anzapfen

Wichtige Anweisungen:

  • cache_peer  10.2.3.1  parent 3128  0  proxy-only

  • Zur Optimierung im Falle älterer Proxy-Versionen:

    • acl INSIDE_IP dst 10.2.3.0/24

    • always_direct allow INSIDE_IP

    • never_direct allow all

208.4 Implementing Nginx as a web server and a reverse proxy

Nginx als reverser Proxy

Siehe dazu:

Apache am Port 8000 betreiben

$ vi /etc/apache2/ports.conf
$
$ vi /etc/apache2/sites-enabled/000-default.conf
$
$ grep 8000 /etc/apache2/ports.conf /etc/apache2/sites-enabled/000-default.conf
/etc/apache2/ports.conf:Listen 8000
/etc/apache2/sites-enabled/000-default.conf:<VirtualHost *:8000>
$
$ apache2ctl restart
$
$ lsof -i -Pn | grep 8000
apache2 1342     root    8u  IPv6  37268      0t0  TCP *:8000 (LISTEN)
apache2 4526 www-data    8u  IPv6  37268      0t0  TCP *:8000 (LISTEN)
apache2 4527 www-data    8u  IPv6  37268      0t0  TCP *:8000 (LISTEN)
apache2 4528 www-data    8u  IPv6  37268      0t0  TCP *:8000 (LISTEN)
apache2 4529 www-data    8u  IPv6  37268      0t0  TCP *:8000 (LISTEN)
apache2 4530 www-data    8u  IPv6  37268      0t0  TCP *:8000 (LISTEN)
apache2 4531 www-data    8u  IPv6  37268      0t0  TCP *:8000 (LISTEN)
apache2 4532 www-data    8u  IPv6  37268      0t0  TCP *:8000 (LISTEN)
apache2 4533 www-data    8u  IPv6  37268      0t0  TCP *:8000 (LISTEN)
apache2 4534 www-data    8u  IPv6  37268      0t0  TCP *:8000 (LISTEN)
apache2 4535 www-data    8u  IPv6  37268      0t0  TCP *:8000 (LISTEN)
apache2 4536 www-data    8u  IPv6  37268      0t0  TCP *:8000 (LISTEN)
apache2 4537 www-data    8u  IPv6  37268      0t0  TCP *:8000 (LISTEN)
$

Nginx installieren und einrichten

$ apt-get install nginx

Zu allererst wollen wir eine vom Apache altbekannte Einstellung, das Directory Listing (Options Indexes) jetzt auch mit diesem Webserver realisieren. Siehe dazu auch http://nginx.org/en/docs/http/ngx_http_autoindex_module.html

Wir bearbeiten deshalb die Hauptkonfigurationsdatei namens ‚/etc/nginx/sites-enabled/default‘. Innerhalb der default-Direktive server { ... } kann man auf einfache Weise eine Freigabe z.B. für einen Ordner namens ‚doc‘ hinzufügen. Dazu benötigen wir den Parameter autoindex on;:

location /doc {
               autoindex on;
       }

Die Datei sieht dann insgesamt so aus (cat /etc/nginx/sites-enabled/default  | grep -v \# | grep -v ^$):

server {
        listen 80 default_server;
        listen [::]:80 default_server;
        root /var/www/html;
        index index.html index.htm index.nginx-debian.html;
        server_name _;
        location / {
                try_files $uri $uri/ =404;
        }
        location /doc {
                autoindex on;
        }
}

Natürlich müssen wir die Änderungen wieder einlesen:

$ systemctl restart nginx

Erweiterung um reverse Proxy-Funktion

Mit Hilfe von proxy_pass lassen wir jetzt unseren neuen Webserver als vorgeschalteten Server für den Apachen arbeiten. Die erforderliche Konfiguration in der ‚/etc/nginx/sites-enabled/default‘ sieht im Endeffekt so aus:

server {
        listen 80 default_server;
        listen [::]:80 default_server;
        root /var/www/html;
        index index.html index.htm index.nginx-debian.html;
        server_name _;
        location / {
                # Zeile hinzugefügt:
                proxy_pass http://127.0.0.1:8000;

                # Zeile auskommentiert:
                #try_files $uri $uri/ =404;
        }
        # Abschnitt hinzugefügt:
        location /doc {
                autoindex on;
        }
}

Im Zusammenhang mit der reversen Arbeitsweise gibt es neben proxy_pass noch zwei weitere LPI-relevante Direktiven:

  • proxy_set_header - Im location-Abschnitt: um auch dynamische Inhalte weiterzuleiten

  • fastcgi_pass - In einem separaten location-Abschnitt: um Requests von FastCGI-Anwendungen behandeln zu können (PHP)

Siehe dazu:

HINWEIS: Um Nginx als eigenständigen Webserver mitzuteilen, dass die index.html per Default aus einem Unterverzeichnis von root zu laden ist (um z.B. ein kleines CMS wie https://getnikola.com/ auszuprobieren), ist so etwas erforderlich wie hier:

location / {
        if ($uri = '/'){
                 rewrite ^/(.*)$ https://pemmann.de/cms/ permanent;
        }
}

Siehe dazu https://stackoverflow.com/questions/17738088/rewrite-root-address-to-a-subdirectory-in-nginx

AUFGABE: Apache soll jetzt nur noch an 127.0.0.1 lauschen

Die momentane Situation sieht nämlich so aus und birgt Sicherheitsrisiken:

$ grep 8000 /etc/apache2/ports.conf /etc/apache2/sites-enabled/000-default.conf
/etc/apache2/ports.conf:Listen 8000
/etc/apache2/sites-enabled/000-default.conf:<VirtualHost *:8000>
$

LÖSUNG / Vertiefung apache/bind

AUFGABE: Bitte die Datei /etc/apache2/ports.conf anpassen auf folgende Einstellung:

Listen 127.0.0.1:8000

Grund: Angreifer könnten sonst im Zusammenhang mit nginx als reversen Proxyserver auf den privaten, von Apache freigegebenen Ordner via

http://10.20.30.3:8000/privat

zugreifen, wobei dann KEINE Passwortabfrage erfolgt!

Zu bind9: Zur Frage, ob überhaupt forwarders bei Bind9 erforderlich und nützlich sind, siehe http://peter-kline.com/?p=64

Topic 209: File Sharing

209.1 SAMBA Server Configuration

Samba - ein Ersatz für Windows Server; wichtige Eckpunkte:

  • Version 3 wird nicht mehr offiziell supportet! ⇒ umsteigen auf Version 4 (gilt nicht für LTS-Distributionen wie auch CentOS 7)

  • Der Samba 3-Quellcode wird in samba4 weitergeplegt und fürs File- und Printer-Sharing benutzt

  • Samba3-Daemons: smbd, nmbd, winbindd

  • Samba4-Daemon (LDAP- und DNS-Ersatz, Kerberos-Dienst): samba

$ whatis smbd
smbd (8)             - server to provide SMB/CIFS services to clients
$
$ whatis winbindd
winbindd (8)         - Name Service Switch daemon for resolving names from NT servers
$
$ whatis samba
samba (8)            - Server to provide AD and SMB/CIFS services to clients
samba (7)            - A Windows AD and SMB/CIFS fileserver for UNIX
$ whatis samba-tool
samba-tool (8)       - Main Samba administration tool.
$
$
$
$ whatis nmbd
nmbd (8)             - NetBIOS name server to provide NetBIOS over IP naming services to clients
$

Installation und Konfiguration für einfaches File-Sharing

Wir beginnen einfach mal…

$ apt-get install samba smbclient
...
$ cd /etc/samba
$ cp smb.conf smb.conf.orig
$
$ less smb.conf

Aufbau der smb.conf:

  • Wie Windows-init-Dateien

  • Vordefinirter Abschnitt 1: [global]

    • Arbeitsgruppen- oder Domänenname festlegen: workgroup = dom1
      (Im Zusammenhang mit domain logons = Yes ist das dann der NetBIOS-Domaine)
    • Sicherheitsstufe: security = User (ist ehemals Default, heute: „server role = …“)

    • Gast-Account aktivieren: map to guest = Bad User

  • Vordefinirter Abschnitt 2 (optional): [homes] - gibt alle Unix-Heimatverzeichnisse frei

  • Vordefinirter Abschnitt 3 (optional): [printers] - gibt alle eingerichteten Drucker frei

Eine einfache /etc/samba/smb.conf kann so aussehen:

[global]
  map to guest = bad user

[free4all]
  path = /srv/samba/pub
  public = yes
  writable = yes

Wir testen nun ausgiebig (Voreinstellungen mit -v):

# testparm
Load smb config files from /etc/samba/smb.conf
Processing section "[free4all]"
Loaded services file OK.
Server role: ROLE_STANDALONE

Press enter to see a dump of your service definitions

# Global parameters
[global]
        map to guest = Bad User
        idmap config * : backend = tdb


[free4all]
        path = /srv/samba/pub
        read only = No
        guest ok = Yes
#
#
# testparm -v | grep guest
Load smb config files from /etc/samba/smb.conf
Processing section "[free4all]"
Loaded services file OK.
Server role: ROLE_STANDALONE

Press enter to see a dump of your service definitions

        map to guest = Bad User
        guest account = nobody
        usershare allow guests = No
        guest only = No
        guest ok = No
        guest ok = Yes
#
# testparm -v | grep workgroup
Load smb config files from /etc/samba/smb.conf
Processing section "[free4all]"
Loaded services file OK.
Server role: ROLE_STANDALONE

Press enter to see a dump of your service definitions

        workgroup = WORKGROUP
#
# testparm -v | grep security
Load smb config files from /etc/samba/smb.conf
Processing section "[free4all]"
Loaded services file OK.
Server role: ROLE_STANDALONE

Press enter to see a dump of your service definitions

        security = AUTO
#

Wir erzeugen jetzt das Freigabeverzeichnis und starten den Server neu:

# mkdir -m 1777 -p /srv/samba/pub/write
#
#
# ls -lRa /srv/samba/pub/
/srv/samba/pub/:
insgesamt 12
drwxr-xr-x 3 root root 4096 Nov 17 11:31 .
drwxr-xr-x 3 root root 4096 Nov 17 11:31 ..
drwxrwxrwt 2 root root 4096 Nov 17 11:31 write

/srv/samba/pub/write:
insgesamt 8
drwxrwxrwt 2 root root 4096 Nov 17 11:31 .
drwxr-xr-x 3 root root 4096 Nov 17 11:31 ..
#
# systemctl restart smbd
#
# systemctl restart nmbd

Testings

Browseliste beziehen (Welche Shares gibt es?)

# smbclient -NL localhost
Domain=[WORKGROUP] OS=[Windows 6.1] Server=[Samba 4.2.10-Debian]

        Sharename       Type      Comment
        ---------       ----      -------
        free4all        Disk
        IPC$            IPC       IPC Service (Samba 4.2.10-Debian)
Domain=[WORKGROUP] OS=[Windows 6.1] Server=[Samba 4.2.10-Debian]

        Server               Comment
        ---------            -------
        D8SQUID              Samba 4.2.10-Debian

        Workgroup            Master
        ---------            -------
        WORKGROUP
#

Zugriff aufs Share als Gast (anonymous):

# smbclient -U% //localhost/free4all
Domain=[WORKGROUP] OS=[Windows 6.1] Server=[Samba 4.2.10-Debian]
smb: \>
smb: \> mkdir ABC
NT_STATUS_ACCESS_DENIED making remote directory \ABC
smb: \>
smb: \> dir
  .                                   D        0  Thu Nov 17 11:31:03 2016
  ..                                  D        0  Thu Nov 17 11:31:03 2016
  write                               D        0  Thu Nov 17 11:31:03 2016

                8516872 blocks of size 1024. 7201860 blocks available
smb: \> cd write\
smb: \write\>
smb: \write\> mkdir ABC
smb: \write\>
smb: \write\>

Authentifzierter Zugriff von Linux- und Windows-Clients aus

Hierbei wurde der Gast-Account deaktiviert (mit Semikolon):

# vi smb.conf
#
# cat smb.conf
[global]
  ;map to guest = bad user

[free4all]
  path = /srv/samba/pub
  public = yes
  writable = yes

#
# systemctl restart smbd
#
#
# testparm -v | grep guest
Load smb config files from /etc/samba/smb.conf
Processing section "[free4all]"
Loaded services file OK.
Server role: ROLE_STANDALONE

Press enter to see a dump of your service definitions

        map to guest = Never
        guest account = nobody
        usershare allow guests = No
        guest only = No
        guest ok = No
        guest ok = Yes
#
# smbclient -U% //localhost/free4all
Domain=[WORKGROUP] OS=[Windows 6.1] Server=[Samba 4.2.10-Debian]
smb: \> quit
#

Jetzt unter Windows mit winuser zugreifen:

# useradd -d /nodir -s /bin/false winuser
#
# smbpasswd -a winuser
New SMB password:
Retype new SMB password:
Added user winuser.
#
#
# smbclient -Uwinuser //localhost/free4all
Enter winuser's password:
session setup failed: NT_STATUS_LOGON_FAILURE
#
# smbclient -Uwinuser //localhost/free4all
Enter winuser's password:
Domain=[WORKGROUP] OS=[Windows 6.1] Server=[Samba 4.2.10-Debian]
smb: \>
smb: \> ls
  .                                   D        0  Thu Nov 17 11:31:03 2016
  ..                                  D        0  Thu Nov 17 11:31:03 2016
  write                               D        0  Thu Nov 17 11:49:40 2016

                8516872 blocks of size 1024. 7201852 blocks available
smb: \> mkdir VonWinuser
NT_STATUS_ACCESS_DENIED making remote directory \VonWinuser
smb: \>
smb: \> cd write\
smb: \write\>
smb: \write\> mkdir VonWinuser
smb: \write\>
smb: \write\> by
by: command not found
smb: \write\>
smb: \write\> quit
#
# ls -l /srv/samba/pub/write/
insgesamt 12
drwxr-xr-x 2 nobody  nogroup 4096 Nov 17 11:41 ABC
drwxr-xr-x 2 nobody  nogroup 4096 Nov 17 11:49 New folder
drwxr-xr-x 2 winuser winuser 4096 Nov 17 12:00 VonWinuser
#
#
# ls -l /srv/samba/pub/write/
insgesamt 16
drwxr-xr-x 2 nobody  nogroup 4096 Nov 17 11:41 ABC
drwxr-xr-x 2 nobody  nogroup 4096 Nov 17 11:49 New folder
drwxr-xr-x 2 winuser winuser 4096 Nov 17 12:01 New folder (2)
drwxr-xr-x 2 winuser winuser 4096 Nov 17 12:00 VonWinuser
#

Die Lage der trivialen Datenbank des SAM-Managers (backend: tdbsam) ist hier zu sehen:

# ls -l /var/lib/samba/private/
insgesamt 840
-rw------- 1 root root    696 Nov 17 09:33 netlogon_creds_cli.tdb
-rw------- 1 root root 421888 Nov 17 11:58 passdb.tdb
-rw------- 1 root root 430080 Nov 17 09:30 secrets.tdb
drwxr-xr-x 3 root root   4096 Nov 17 09:33 smbd.tmp
#
#
# testparm -v | grep backend
Load smb config files from /etc/samba/smb.conf
Processing section "[free4all]"
Loaded services file OK.
Server role: ROLE_STANDALONE

Press enter to see a dump of your service definitions

        config backend = file
        passdb backend = tdbsam
        idmap backend = tdb
        share backend = classic
        idmap config * : backend = tdb
#
#

Anders als Windows schert sich Linux NICHT um den deaktivierten Gastzugang:

# smbclient -U% //localhost/free4all
Domain=[WORKGROUP] OS=[Windows 6.1] Server=[Samba 4.2.10-Debian]
smb: \>
smb: \>

Linktipp: Methoden der Namensauslösung - http://www.elektronik-kompendium.de/sites/net/0901081.htm

WINS - Namensauflösung für NetBIOS-Namen

Samba soll selber als WINS-Server auftreten: wins support = yes

$ man smb.conf
wins support (G)

           This boolean controls if the nmbd(8) process in Samba will act as a WINS server. You
           should not set this to yes unless you have a multi-subnetted network and you wish a
           particular nmbd to be your WINS server. Note that you should NEVER set this to yes on
           more than one machine in your network.

           Default: wins support = no

Dagegen tritt Samba als WINS-Client mit dieser Direktive auf: wins server = myNeighborWinServer

ACHTUNG: Die beiden Schalter schließen sich gegenseitig aus!

Grundeinstellungen im globalen Abschnitt

Sicherheitslevel

Im globalen Abschnitt der smb.conf findet sich security = ..., was verschiedene Werte kennt.

Hintergrund ist die historische Entwicklung, die gemeinsam mit IBM begann: der alte LAN-Manager beherrschte nur die Sicherheit auf Share-Ebene, d.h. ein grundsätzliches sich am Server Anmelden-Müssen gab es nicht (aus einem LPI-Braindump: „Using for a simple Print Server“). Die entsprechende Einstellung lautet:

security = share

Heutzutage sollte sich aber ein „User“ zuerst am Server anmelden, danach bekommt er erst die Shares zu sehen. Der User-Level ist Voreinstellung bei Samba v3. Dieser Modus wir auch benötigt, wenn unser Samba-Server selber als PDC auftreten möchte (domain logons = yes). Die entsprechende Einstellung lautet:

security = user

Weitere Modi sind wichtig, wenn Samba als Mitgliedsserver in einer Windows-Domänen arbeiten soll, hierbei übernimmt ein alter Windows NT DC die Authentifizierung:

security = domain

Ab Windows 2000 Server gibt es ein zentrales LDAP-Verzeichnis, daher auch ein anderes Level, mit dem Samba als Mitgliedsserver in einem ADS auftreten kann:

security = ads

Falls security = AUTO auftaucht, liegt Samba in Version 4 vor, wo es jetzt anstelle dessen eigentlich server role = ... gibt:

[root@debi:~]# testparm -vs 2>/dev/null | grep "server role"
    server role = auto
[root@debi:~]#
[root@debi:~]# testparm -vs 2>/dev/null | grep "security"
    security = AUTO
[root@debi:~]# #    >> Alles "auto", dh. es findet eine automatische Erkennung statt.

Siehe dazu:

Passwort-Backends

Weil wir zweigleisig fahren müssen (Unix: PosixAccount + Windows: SambaSamAccount) muss je nach Sicherheitslevel bzw. Serverrolle ein anderes Backend verwendet werden:

root@debi:~# testparm -vs 2>/dev/null | grep backend
    config backend = file
    idmap backend = tdb
    passdb backend = tdbsam
    share backend = classic
    idmap config * : backend = tdb
root@debi:~#

Das tdbsam-Backend ist schon länger Standard, das Kürzel steht für „Trivial DataBase of the Security Account Manager“. Diese triviale Datenbank kann schon länger Windows recht gut nachahmen, beinhaltet aber keinen zentralen Verzeichnisdienst. Nachdem wir unserem bereits vorhandenen Unix-Nutzer „tux“ mittels pdbedit -a tux einen Samba-Account beigeordent haben, können wir uns nun seine Eigenschaften ansehen:

root@debi:~# pdbedit -L -u tux -v
Unix username:        tux
NT username:
Account Flags:        [U          ]
User SID:             S-1-5-21-2079638846-3257800411-525591495-1000
Primary Group SID:    S-1-5-21-2079638846-3257800411-525591495-513
Full Name:            Mr. tux
Home Directory:       \\debi\tux
HomeDir Drive:
Logon Script:
Profile Path:         \\debi\tux\profile
Domain:               DEBI
Account desc:
Workstations:
Munged dial:
Logon time:           0
Logoff time:          Mi, 06 Feb 2036 16:06:39 CET
Kickoff time:         Mi, 06 Feb 2036 16:06:39 CET
Password last set:    Mo, 07 Jun 2021 10:27:40 CEST
Password can change:  Mo, 07 Jun 2021 10:27:40 CEST
Password must change: never
Last bad password   : 0
Bad password count  : 0
Logon hours         : FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF

Weitere Backends sind:

  • Flache Textdateien (veraltet!): passdb backend = smbpasswd (ähnlich der /etc/passwd)

  • LDAP-Datenbank basierte Authentifizierung: passdb backend = ldapsam (Nutzung eines zentralen Verzeichnisdienstes)

Siehe dazu:

Samba 4 in der Rolle eines alten PDC

Neu ist hier, dass wir einen zusätzlichen Parameter brauchen: server role = classic primary domain controller

$ vi /etc/samba/smb.conf
[global]
  ;map to guest = bad user
  workgroup = DOM1
  server role = classic primary domain controller


  ; Einstellungen fürs Browsing
  domain master = yes
  local master = yes
  preferred master = yes
  os level = 255

  ; Übermittlung an Clients, welcher UNC-Pfad verwedet werden soll
  ;logon path = \\%L\profiles\%U
  ; AUFGABE: Bitte dies für verschiedene Windows-Architekturen robuster machen!
  logon path = \\%L\profiles\%U\%a

[profiles]
  comment = Profile Share
  path = /srv/samba/profiles
  writable = yes
  profile acls = yes

[free4all]
  path = /srv/samba/pub
  public = yes
  writable = yes
$ mkdir -m 707 /srv/samba/profiles
$ testparm -v

Maschinenaccount anlegen

$ groupadd machines
$
$ useradd -d /nodir -s /bin/false -g machines  IE8WIN7$
$
$ smbpasswd -a -m IE8WIN7
Added user IE8WIN7$.
$
$ pdbedit -L
winuser:1001:
IE8WIN7$:1002:
$

Oder ausführliche Ausgabe aller Objekte: pdbedit -L -v

Root zur Samba-Passwortdatenbank temporär hinzufügen (für Domänenbeitritt con Clients)_

$ smbpasswd -a root
New SMB password:
Retype new SMB password:
Added user root.
$

AUFGAE: Wie heißt die Direktive, mit der ein Samba-Username-Mapping (root = Administrator) eingerichtet werden kann? ANTWORT: ‚username map‘, im Beispiel:

username map = /etc/samba/smbusers

Domänenbeitritt von Windows 7

Via Windows und dem einfachen NetBIOS-Namen dom1….

Troubleshooting

http://www.oreilly.com/openbook/samba/book/ch09_01.html

$ killall smbd
$
$ pgrep -a mbd
1472 /usr/sbin/nmbd -D
$
$ smbd -F -S -i -d 5
INFO: Current debug levels:
  all: 5
  tdb: 5
  printdrivers: 5
  ...

In der Logausgabe lesen wir, dass das Maschine-Konto noch fehlt (= samba user), wir legen es deshalb an:

$ pgrep -a mbd
1472 /usr/sbin/nmbd -D
$
$
$ useradd -d /nodir -s /bin/false -g machines  WIN-2CA02O8XNNS$
$
$
$ smbpasswd -am  WIN-2CA02O8XNNS
Added user WIN-2CA02O8XNNS$.
$
$ pdbedit -L
winuser:1001:
root:0:root
IE8WIN7$:1002:
WIN-2CA02O8XNNS$:1003:
$

Ein erfolreicher Mitschnitt der Domänenaufnahme sieht danach so aus:

$ smbd -F -S -i -d 3
Maximum core file size limits now 16777216(soft) -1(hard)
smbd version 4.2.10-Debian started.
Copyright Andrew Tridgell and the Samba Team 1992-2014
uid=0 gid=0 euid=0 egid=0
lp_load_ex: refreshing parameters
Initialising global parameters
Processing section "[global]"
Registered MSG_REQ_POOL_USAGE
Registered MSG_REQ_DMALLOC_MARK and LOG_CHANGED
lp_load_ex: refreshing parameters
Initialising global parameters
Processing section "[global]"
Processing section "[profiles]"
Processing section "[free4all]"
adding IPC service
added interface eth0 ip=10.20.30.5 bcast=10.20.30.255 netmask=255.255.255.0
loaded services
pdb_create_builtin_alias: Could not get a gid out of winbind
WARNING: Failed to create BUILTIN\Administrators group!  Can Winbind allocate gids?
pdb_create_builtin_alias: Could not get a gid out of winbind
WARNING: Failed to create BUILTIN\Users group! Can Winbind allocate gids?
waiting for connections
Unable to connect to CUPS server localhost:631 - Ungültiger Dateideskriptor
failed to retrieve printer list: NT_STATUS_UNSUCCESSFUL
Could not find child 1760 -- ignoring

Allowed connection from 10.20.30.98 (10.20.30.98)
GENSEC backend 'gssapi_spnego' registered
GENSEC backend 'gssapi_krb5' registered
GENSEC backend 'gssapi_krb5_sasl' registered
GENSEC backend 'spnego' registered
GENSEC backend 'schannel' registered
GENSEC backend 'naclrpc_as_system' registered
GENSEC backend 'sasl-EXTERNAL' registered
GENSEC backend 'ntlmssp' registered
GENSEC backend 'ntlmssp_resume_ccache' registered
GENSEC backend 'http_basic' registered
GENSEC backend 'http_ntlm' registered
GENSEC backend 'krb5' registered
GENSEC backend 'fake_gssapi_krb5' registered
Got NTLMSSP neg_flags=0xe2088297
Got user=[root] domain=[dom1] workstation=[WIN-2CA02O8XNNS] len1=24 len2=218
lp_load_ex: refreshing parameters
Initialising global parameters
Processing section "[global]"
Processing section "[profiles]"
Processing section "[free4all]"
adding IPC service
check_ntlm_password:  Checking password for unmapped user [dom1]\[root]@[WIN-2CA02O8XNNS] with the new password interface
check_ntlm_password:  mapped user is: [dom1]\[root]@[WIN-2CA02O8XNNS]
Forcing Primary Group to 'Domain Users' for root
check_ntlm_password: sam authentication for user [root] succeeded
check_ntlm_password:  authentication for user [root] -> [root] -> [root] succeeded
NTLMSSP Sign/Seal - Initialising with flags:
Got NTLMSSP neg_flags=0xe2088215
NTLMSSP Sign/Seal - Initialising with flags:
Got NTLMSSP neg_flags=0xe2088215
pdb_create_builtin_alias: Could not get a gid out of winbind
WARNING: Failed to create BUILTIN\Administrators group!  Can Winbind allocate gids?
pdb_create_builtin_alias: Could not get a gid out of winbind
WARNING: Failed to create BUILTIN\Users group! Can Winbind allocate gids?
Allowed connection from 10.20.30.98 (10.20.30.98)
Got NTLMSSP neg_flags=0xe20882b7
Got user=[Administrator] domain=[WIN-2CA02O8XNNS] workstation=[WIN-2CA02O8XNNS] len1=24 len2=218
lp_load_ex: refreshing parameters
Initialising global parameters
Processing section "[global]"
Processing section "[profiles]"
Processing section "[free4all]"
adding IPC service
check_ntlm_password:  Checking password for unmapped user [WIN-2CA02O8XNNS]\[Administrator]@[WIN-2CA02O8XNNS] with the new password interface
check_ntlm_password:  mapped user is: [DOM1]\[Administrator]@[WIN-2CA02O8XNNS]
check_sam_security: Couldn’t find user 'Administrator' in passdb.
check_winbind_security: Not using winbind, requested domain [DOM1] was for this SAM.
check_ntlm_password:  Authentication for user [Administrator] -> [Administrator] FAILED with error NT_STATUS_NO_SUCH_USER
_netr_ServerAuthenticate3: no challenge sent to client WIN-2CA02O8XNNS
Got NTLMSSP neg_flags=0xe20882b7
Got user=[Administrator] domain=[WIN-2CA02O8XNNS] workstation=[WIN-2CA02O8XNNS] len1=24 len2=218
lp_load_ex: refreshing parameters
Initialising global parameters
Processing section "[global]"
Processing section "[profiles]"
Processing section "[free4all]"
adding IPC service
check_ntlm_password:  Checking password for unmapped user [WIN-2CA02O8XNNS]\[Administrator]@[WIN-2CA02O8XNNS] with the new password interface
check_ntlm_password:  mapped user is: [DOM1]\[Administrator]@[WIN-2CA02O8XNNS]
check_sam_security: Couldn’t find user 'Administrator' in passdb.
check_winbind_security: Not using winbind, requested domain [DOM1] was for this SAM.
check_ntlm_password:  Authentication for user [Administrator] -> [Administrator] FAILED with error NT_STATUS_NO_SUCH_USER
Forcing Primary Group to 'Domain Users' for WIN-2CA02O8XNNS$
Forcing Primary Group to 'Domain Users' for WIN-2CA02O8XNNS$
Beendet
$

Tests von Windows aus

WIN + R:  \\d8squid.dom1.test\profiles
$ Ordner anlegen
$ systemctl restart  smbd
$
$
$ pgrep -a mbd
1472 /usr/sbin/nmbd -D
1814 /usr/sbin/smbd -D
1816 /usr/sbin/smbd -D
$
$ smbpasswd tux
New SMB password:
Retype new SMB password:
Failed to find entry for user tux.
$
$
$ pdbedit -L
winuser:1001:
root:0:root
IE8WIN7$:1002:
WIN-2CA02O8XNNS$:1003:
$
$ smbpasswd -a tux
New SMB password:
Retype new SMB password:
Added user tux.
$ ls -l /srv/samba/profiles/
insgesamt 4
drwxr-xr-x 2 tux tux 4096 Nov 18 11:35 Neuer Ordner
$

Einen gleichnamigen Benutzer tux mit selben Passwort wie unter Linux anlegen….

Abmelden als Adminsitrator, anmelden als tux….

Kontrolle unter Linux

$ ### Nach dem Domänenlogin von tux:
$
$ ls -la /srv/samba/profiles/
insgesamt 20
drwx---rwx  4 root root 4096 Nov 18 11:42 .
drwxr-xr-x  4 root root 4096 Nov 18 08:39 ..
drwxr-xr-x  2 tux  tux  4096 Nov 18 11:35 Neuer Ordner
drwxrwx--x+ 3 tux  tux  4096 Nov 18 11:42 tux
$
$ ls -la /srv/samba/profiles/tux/
insgesamt 20
drwxrwx--x+ 3 tux  tux  4096 Nov 18 11:42 .
drwx---rwx  4 root root 4096 Nov 18 11:42 ..
drwxrwx--x+ 2 tux  tux  4096 Nov 18 11:42 Vista.V2
$
$ ls -la /srv/samba/profiles/tux/Vista.V2/
insgesamt 16
drwxrwx--x+ 2 tux tux 4096 Nov 18 11:42 .
drwxrwx--x+ 3 tux tux 4096 Nov 18 11:42 ..
$
$
$ ls -la /srv/samba/profiles/tux/Vista.V2/
insgesamt 16
drwxrwx--x+ 2 tux tux 4096 Nov 18 11:42 .
drwxrwx--x+ 3 tux tux 4096 Nov 18 11:42 ..
$
$ ls -F /srv/samba/profiles/tux/Vista.V2/
$ ls -F /srv/samba/profiles/tux/Vista.V2/
AppData/   Desktop/    Downloads/  Links/  NTUSER.DAT*  Pictures/     Searches/
Contacts/  Documents/  Favorites/  Music/  ntuser.ini*  Saved Games/  Videos/
$
$ grep --color '%a' /etc/samba/smb.conf
  logon path = \\%L\profiles\%U\%a
$
$
$ cat /etc/samba/smb.conf
[global]
  ;map to guest = bad user
  workgroup = dom1
  server role = classic primary domain controller

  ; Ich bin PDC:
  domain logons = yes

  ; Einstellungen fürs Browsing
  domain master = yes
  local master = yes
  preferred master = yes
  os level = 255

  ; Übermittlung an Clients, welcher UNC-Pfad verwendet werden soll
  logon path = \\%L\profiles\%U\%a

  load printers = No

[profiles]
  comment = Profile Share
  path = /srv/samba/profiles
  writable = yes
  profile acls = yes

[free4all]
  path = /srv/samba/pub
  public = yes
  writable = yes

Vertiefung PDC

Problembehebung DDNS für Windows-Clients

$ vi /etc/dhcp/dhcpd.conf
#server-identifier           d8master;
server-name                 d8master;
$ systemctl restart isc-dhcp-server.service

Die manuelle Namensauslösung den Windows-2008R2-Clients entfernen:

$ rndc freeze
$
$ vi /var/lib/bind/db.dom1.test
$
$ rndc reload
server reload successful
$
$ rndc thaw

Die aktuelle smb.conf:

[global]
  ;map to guest = bad user
  workgroup = dom1.test
  server role = classic primary domain controller
  security = User

  ; Ich bin PDC:
  domain logons = yes

  ; Einstellungen fürs Browsing
  domain master = yes
  local master = yes
  preferred master = yes
  os level = 255

  ; Übermittlung an Clients, welcher UNC-Pfad verwendet werden soll
  logon path = \\%L\profiles\%U\%a

  load printers = No

[profiles]
  comment = Profile Share
  path = /srv/samba/profiles
  writable = yes
  profile acls = yes

[free4all]
  path = /srv/samba/pub
  public = yes
  writable = yes

Neustarten…

$ systemctl restart smbd
$
$
$ systemctl restart nmbd
$
$
$ ps axf | egrep "samba|smbd|nmbd|winbindd"
 1341 pts/0    S+     0:00                      \_ grep -E samba|smbd|nmbd|winbindd
 1328 ?        Ss     0:00 /usr/sbin/smbd -D
 1330 ?        S      0:00  \_ /usr/sbin/smbd -D
$

Troubleshooting:

$ nmblookup __samba__
10.20.30.5 __samba__
$

Root-Passwort ändern, nicht mehr vorhandene Maschinenaccounts löschen:

$ pdbedit -L
winuser:1001:
root:0:root
tux:1000:tux
IE8WIN7$:1002:
WIN-2CA02O8XNNS$:1003:
$
$
$ smbpasswd root
New SMB password:
Retype new SMB password:
Mismatch - password unchanged.
Unable to get new password.
$
$ smbpasswd root
New SMB password:
Retype new SMB password:
$
$ ls -ltrc /var/lib/samba/private/
insgesamt 844
drwxr-xr-x 3 root root   4096 Nov 17 09:33 smbd.tmp
-rw------- 1 root root    696 Nov 18 08:13 netlogon_creds_cli.tdb
-rw------- 1 root root 430080 Nov 18 12:52 secrets.tdb
-rw------- 1 root root    696 Nov 21 09:41 schannel_store.tdb
-rw------- 1 root root 421888 Nov 21 11:02 passdb.tdb
$
$ testparm -v | grep backend
Load smb config files from /etc/samba/smb.conf
Processing section "[profiles]"
Processing section "[free4all]"
Loaded services file OK.
Server role: ROLE_DOMAIN_PDC

Press enter to see a dump of your service definitions

        config backend = file
        passdb backend = tdbsam
        idmap backend = tdb
        share backend = classic
        idmap config * : backend = tdb
$
$
$
$ pdbedit -x IE8WIN7$
$
$ pdbedit -L
winuser:1001:
root:0:root
tux:1000:tux
WIN-2CA02O8XNNS$:1003:
$
$ pdbedit -x WIN-2CA02O8XNNS$
$

Automatisierung des Anlegens von Maschinenaccounts:

$ cat /etc/samba/smb.conf
[global]
  ;map to guest = bad user
  workgroup = dom1.test
  server role = classic primary domain controller
  security = User

  ; Ich bin PDC:
  domain logons = yes

  ; Einstellungen fürs Browsing
  domain master = yes
  local master = yes
  preferred master = yes
  os level = 255

  ; Übermittlung an Clients, welcher UNC-Pfad verwendet werden soll
  logon path = \\%L\profiles\%U\%a

  load printers = No

  add user script = /usr/sbin/useradd -m '%u'
  delete user script = /usr/sbin/userdel -r '%u'
  add group script = /usr/sbin/groupadd '%g'
  delete group script = /usr/sbin/groupdel '%g'
  add user to group script = /usr/sbin/usermod -G '%g' '%u'
  add machine script = /usr/sbin/useradd -s /bin/false -d /dev/null '%u'

[profiles]
  comment = Profile Share
  path = /srv/samba/profiles
  writable = yes
  profile acls = yes

[free4all]
  path = /srv/samba/pub
  public = yes
  writable = yes
$ systemctl restart  smbd

Nun nehmen wir die Windows 2008 - Maschine erfolgreich in die Domäne auf, indem wir lediglich auf dieser Windows-Maschine den Domänenbeitritt wie üblich durchführen. Zur Kontrolle und zur Erinnerung:

$ pdbedit -L
winuser:1001:
root:0:root
tux:1000:tux
W2K8-CL$:1004:W2K8-CL$
$
$
$ ### Wir ersparen uns mit 'add machine script = /usr/sbin/useradd ...' folgende
$ # Zeile:
$
$ #  useradd -d /nodir -s /bin/false -g machines  WIN-2CA02O8XNNS$

Zum Testen, ob auch Nutzer mittels add user script via Windows angelegt werden können, müssen wir uns mit dem Samba-root-Account an der Domäne anmelden…

Samba-Tools

$ apt-get install smbclient cifs-utils

Der Zugriff auf FTP-Art mittels smbclient:

$ smbclient -NL d8squid
Anonymous login successful
Domain=[DOM1.SITE] OS=[Windows 6.1] Server=[Samba 4.2.10-Debian]

        Sharename       Type      Comment
        ---------       ----      -------
        profiles        Disk      Profile Share
        free4all        Disk
        IPC$            IPC       IPC Service (Samba 4.2.10-Debian)
Anonymous login successful
Domain=[DOM1.SITE] OS=[Windows 6.1] Server=[Samba 4.2.10-Debian]

        Server               Comment
        ---------            -------
        D8SQUID              Samba 4.2.10-Debian

        Workgroup            Master
        ---------            -------
        DOM1.SITE            D8SQUID
        WORKGROUP            JESSIE
$
$ smbclient \\\\d8squid\\free4all -U%
Domain=[DOM1.SITE] OS=[Windows 6.1] Server=[Samba 4.2.10-Debian]
smb: \> dir
  .                                   D        0  Thu Nov 17 11:31:03 2016
  ..                                  D        0  Fri Nov 18 08:39:17 2016
  write                               D        0  Thu Nov 17 12:01:01 2016

                8516872 blocks of size 1024. 7199432 blocks available
smb: \> quit
$

Transparenter Zugriff via smbfs (veraltet) oder besser cifs (TCP/IP only = NBT):

$ mount -t cifs -o guest \\\\d8squid\\free4all /mnt
mount error(13): Permission denied
Refer to the mount.cifs(8) manual page (e.g. man mount.cifs)
$

Dies gelingt nicht, weil sich Common Internet File System (cifs) anders als smbclient an die Regeln hält und

map to guest = never

respektiert.

Nach dem Setzen von map to guest = bad user gelingt es dann auch anonym.

Oder wir authentifizieren uns richtig beim Mounten:

$ mount -t cifs -o username=tux,password=t  //d8squid/profiles /mnt
$
$ ls -l /mnt/
insgesamt 0
drwxrwx--x+ 3 1005 1005 0 Nov 21 11:33 otto
drwxrwx--x+ 3 root root 0 Nov 21 11:24 root
drwxrwx--x+ 3 tux  tux  0 Nov 18 11:42 tux
$ mkdir /mnt/tux/Verzeichnis
mkdir: das Verzeichnis „/mnt/tux/Verzeichnis“ kann nicht angelegt werden: Keine Berechtigung
$

ACHTUNG: Die Übergabe von Benutzername und Passwort auf der Kommandozeile ist NICHT empfehlenswert, vor allem, wenn man das in die Datei /etc/fstab aufnehmen will!

Bitte nur so:

$ vi /etc/fstab
//d8squid/profiles /home/tux/smb  noauto,user,credentials=/etc/samba/useraccounts  0   0

Dann brauchen wir die Datei:

$ vi /etc/samba/useraccounts
username = tux
password = sup3r-GeHe1m...
$ chmod 600 /etc/samba/useraccounts

Mapping Windows usernames to Linux usernames

ZIEL: Windows-Nutzer können mit dem Namen Administrator arbeiten, es wird aber dann auf root gemappt:

Die [global]-Direktive lautet: username map = </pfad/zur/datei>

Die Datei ist dann so aufgebaut:

root = administrator admin

Samba tools and utilities

# whatis smbstatus
smbstatus (1)        - report on current Samba connections

net-Tools

Vergleich mit Windows

ACHTUNG: Diese Werkzeuge sind nicht 100% kompatibel zu Windows!

Unter Windows ein Netzlaufwerk bereitstellen: net use P: \\d8squid\free4all /user:tux /persistent:yes

c:\> REM Die Serverseite:
C:\> net use
Neue Verbindungen werden gespeichert.

Es sind keine Einträge in der Liste.

C:\> REM Die Serverseite:
C:\>net share

Name         Ressource                       Beschreibung

 ------------------------------------------------------------
C$           C:\                             Standardfreigabe
IPC$                                         Remote-IPC
ADMIN$       C:\windows                      Remoteverwaltung
Pointofix    C:\Users\apemmann\Documents\Pointofix

Der Befehl wurde erfolgreich ausgeführt.

C:\>

Siehe auch html/samba-pdc.html

Unter Linux

Benutzer anlegen:

$ net user add "winuser-01" "winpw"
Enter root’s password:
Added user 'winuser-01'.
$
$
$ ### Damit ist beides passiert: Es wurde ein Unix- sowie Samba-User angelegt.
$
$ tail -1 /etc/passwd
winuser-01:x:1007:1007::/home/winuser-01:/bin/sh
$
$ pdbedit -L | tail -1
winuser-01:1007:
$

Weitere Experimente:

$ net status sessions
PID     Username      Group         Machine
 ------------------------------------------------------------------
   2669   tux           tux           10.20.30.3   (ipv4:10.20.30.3:60923)
$

$ net status shares

Service      pid     machine       Connected at
 ------------------------------------------------------
profiles     2669   10.20.30.3    Mon Nov 21 16:38:06 2016
IPC$         2669   10.20.30.3    Mon Nov 21 16:38:06 2016
$
$ net lookup d8master
10.20.30.3
$
$ net lookup d8squid
127.0.1.1
$

Speziell zu Fragen der Berechtigung:

$ net rpc rights list
Enter root’s password:
Could not connect to server 127.0.0.1
The username or password was not correct.
Connection failed: NT_STATUS_LOGON_FAILURE
$
$ net rpc rights list
Enter root’s password:
     SeMachineAccountPrivilege  Add machines to domain
      SeTakeOwnershipPrivilege  Take ownership of files or other objects
             SeBackupPrivilege  Back up files and directories
            SeRestorePrivilege  Restore files and directories
     SeRemoteShutdownPrivilege  Force shutdown from a remote system
      SePrintOperatorPrivilege  Manage printers
           SeAddUsersPrivilege  Add users and groups to the domain
       SeDiskOperatorPrivilege  Manage disk shares
           SeSecurityPrivilege  System security
$


$ net rpc  rights list "dom1.test\winuser-01"
Enter root’s password:
$
$ net rpc rights grant  "dom1.test\winuser-01" SeDiskOperatorPrivilege
Enter root’s password:
Successfully granted rights.
$
$
$ net rpc  rights list "dom1.test\winuser-01"
Enter root’s password:
SeDiskOperatorPrivilege
$
$ net rpc rights grant  "dom1.test\winuser-01" SeTakeOwnershipPrivilege
Enter root’s password:
Successfully granted rights.
$
$ net rpc rights list
Enter root’s password:
$ net rpc  rights list "dom1.test\winuser-01"
Enter root’s password:
SeTakeOwnershipPrivilege
SeDiskOperatorPrivilege
$

Weitere Links insbesondere zum Kommando *net rpc rights …*:

Ausblick: Samba4 kann selber als DC agieren:

Exkurs: Kleine Firma mit Standalone Samba-Server

Ziel: Implementieren einer beispielhaften ‚smb.conf‘, die eine kleine Firma ohne Domänenkontroller abbildet.

Im Detail: Eine kleine Firma möchte drei Freigaben mit abgestufter Sicherheit nutzen:

  1. Austausch: Für Jedermann schreibfähig

  2. Dokumente: Nur für authentifizierte Benutzer bei Verwendung einer Schreibliste (otto, kaspar)

  3. Verwaltung: Nur für die vertrauenswürdigen Benutzer der Verwaltung otto und kaspar)

Dabei sollen möglichst robuste Einstellungen für den Zugriff auf das Dateisystem getroffen werden.

Erstellung der Konfigurationsdatei

Die Hauptkonfigurationsdatei für Samba ist neu anzulegen, deshalb die alte erst einmal sichern:

mv /etc/samba/smb.conf /etc/samba/smb.conf.old

Danach einfach eine neue Datei erzeugen:

vi /etc/samba/smb.conf

Vorbereitungen

Benutzer u. Gruppe anlegen:

useradd -m -s /bin/bash otto

useradd -m -s /bin/bash hans

useradd -m -s /bin/bash kaspar

smbpasswd -a otto

smbpasswd -a hans

smbpasswd -a kaspar

groupadd verwaltung

Benutzer zur Gruppe ‚verwaltung‘ zuordnen:

usermod -g verwaltung otto

usermod -g verwaltung hans

usermod -aG verwaltung kaspar

Dateirechte anpassen:

mkdir -p -m 777/srv/samba/free

mkdir -m 775 /srv/samba/doc

mkdir -m 770 /srv/samba/verwaltung

chgrp verwaltung /srv/samba/doc /srv/samba/verwaltung

Einfügen des neuen Inhaltes

Nun werden die folgenden Zeilen eingefügt:

[global]
  workgroup = firma1
  security = user
  map to guest = bad user

[Austausch]
  path = /srv/samba/free
  guest ok = yes
  read only = no
  create mask = 666
  directory mask = 777
  ; Alternativ zu den beiden mask-Zeilen:
  ;force user = nobody

[Dokumente]
  path = /srv/samba/doc
  read only = yes
  write list = otto,kaspar
  create mask = 775
  directory mask = 775
  force group = verwaltung

[Verwaltung]
  path = /srv/samba/verwaltung
  read only = no
  create mask = 770
  valid users = otto,kaspar
  force group = verwaltung

Das Dokument bitte speichern und den Editor beenden.

Neustarten des Daemons und Testings

Nun muss die Konfiguration neu eingelesen werden, dann kann es ans Testen gehen.

/etc/init.d/samba restart

SMB-Clients:

  1. Linux-Kommandozeile: smbclient, mount -t cifs //host/Austausch /mnt -o guest (Voraussetzung: Installiertes Paket „cifs-utils“)

  2. Linux-GUI: nautilus, konqueror

  3. Windows-Workstation

209.2 NFS Server Configuration

Ziel: Dateitransfer mit dem Network File System (NFS) durchführen, Bereitstellung eines Netzwerkdateisystemes, das Unix-Clients bequem mounten können.

(Freie Windows-Clients sind rar, eine Möglichkeit ist unter http://nekodrive.software.informer.com/ zu finden.)

Ein paar wichtige Eckpunkte:

  • NFS stammt von der 1982 gegründeten Firma SUN Microsystems, 1984 gelang ihr mit diesem Protokoll der Durchbruch in der Unix-Welt

  • Es wird als verteiltes Dateisystem bezeichnet; wenn ein beteiligter Server wegbricht, können allerdings automatische Failover-Aktionen nicht wie bei Ceph oder DFS stattfinden

  • Client/Server-Anwendung: der Server exportiert einen Teil seines Dateisystemes, der Client importiert es durch einen klassischen Mountvorgang

  • Transparente Arbeitsweise: auf die entfernte Ressource wird über einen lokalen Ordner zugegriffen (–> systemweit einheitlicher Namensraum)

  • Bis Version 3 benutzt NFS das verbindungslose UDP, die aktuelle Version 4 verwendet TCP und behebt damit kleinere Probleme, ist aber dadurch nicht mehr ganz so schnell

  • Bis Version 3 authentifizieren sich Benutzer via User-ID-Mapping, ab Version 4 ist außerdem Authentifizierung mittels Kerberos möglich

  • NFS benötigt Remote Procedure Calls (RPC), die sich auf OSI-Schicht 5 um das Zuordnen von lokalen und entfernten UDP/TCP-Ports kümmern und ein initiales Filehandle einrichten

  • RPC wird bis NFSv3 mit dem Dienst ‚portmap‘ realisiert (UDP/2049), ab NFSv4 über ‚rpcbind‘ (TCP/2049)

  • Die NFSv3-Daemons rpc.mountd, rpc.lockd und rpc.statd werden von NFSv4 nicht mehr verwendet (feste Integration im Kernel), dafür aber gibt es jetzt ein Listening am TCP-Port 2049

  • Rollen:

    • Server = der Exporteur (Datei: ‚/etc/exports‘, Tool: exportfs)

    • Client = der Importeur (Kommando mount -t nfs Server:Pfad Mountpunkt)

Installation unter Debian

Die Installation ist schnell durchgeführt. Falls nicht schon vorhanden, wird der zugrundeliegende Portmapper (Paket ‚rpcbind‘) automatisch mit installiert, ebenso wie der NFS-Client (Paket ‚nfs-common‘):

apt-get install nfs-kernel-server

Der NFS-Daemon startet sich aber nicht automatisch, wie sonst unter Debian üblich, es sei denn, es existiert bereits in der Konfigurationsdatei eine gültige Freigabe.

Als weitere Voraussetzung muss der Kernel NFS unterstützen; das Dateisystem wird dann in der Datei /proc/filesystems mit aufgelistet. Bei selbst kompilierten Kerneln fehlt diese Option oft!

NFSv3-kompatible Freigaben

Die Konfigurationsdatei bearbeitet man mit

vi /etc/exports

Für NFSv3 reicht im einfachsten Fall nur eine Zeile, die das Verzeichnis ‚/srv/pub‘ für alle Rechner ‚*‘ schreibfähig (rw) freigibt, wobei Änderungen sofort auf die Festplatte geschrieben werden (sync), außerdem sollen Dateirechte nicht rekursiv geprüft werden (no_subtree_check), was sich nur bei reinen Heimatverzeichnissen lohnt:

/srv/pub       *(rw,sync,no_subtree_check)

Nach dem Anlegen des Verzeichnisses mit

mkdir -m 777 /srv/pub

muss der NFS-Dienst gestartet werden:

/etc/init.d/nfs-kernel-server start

Eine Freigabe mit NFSv3 clientseitig einbinden

Ob der Server erreichbar ist und was er exportiert, kann auf dem Client via Netzwerk mittels

showmount -e server

überprüft werden. Das Mounten in den normalerweise leeren Ordner ‚/mnt‘ gelingt dann mit

mount -o vers=3 server:/srv/pub /mnt

Für NFSv3 ist hierbei die Option ‚vers=3‘ ausschlaggebend, was bedeutet, dass als Transportprotokoll das schnellere UDP verwendet wird.

Zum automatischen Mounten beim Bootvorgang editieren wir die Datei ‚/etc/fstab‘:

vi /etc/fstab

Als Mountpunkt legt man z.B. vorher einen Ordner ‚/media/pub‘ an und schreibt:

server:/srv/pub  /media/pub  nfs  soft,bg  0  0

Die Option ‚soft‘ verhindert ein Hängenbleiben des Clients beim Bootvorgang, falls der Server nicht erreichbar ist; mit ‚bg‘ versucht er es im Hintergrund weiter. Nach dem Abspeichern der Änderungen kann ein Reboot mittels

mount -a

simuliert werden.

Freigaben mit NFSv4

Grundsätzlich kann die bisherige Konfiguration mit der einen Zeile in der ‚/etc/exports‘ beibehalten werden. Ein moderner NFS-Client benutzt dann automatisch NFSv4, wenn er beim Mounten die Versions-Option ‚vers=3‘ weglässt. Damit kann man allerdings nicht alle Features des neuen Protokolls ausnutzen, wie z.B. das automatische Einhängen aller Freigaben unter einem bestimmten NFS-Wurzelverzeichnis.

Die Konfigurationsdatei ist zuerst einmal wieder die alte:

vi /etc/exports

Idealerweise deklariert man für NFSv4 zuerst in einer extra Zeile einen Ordner als NFS-Wurzelpunkt; das wichtigste Kennzeichen ist ‚fsid=0‘. Die zweite Zeile definiert dann die eigentliche Freigabe, auf die der Client später in relativer Schreibweise beim Mounten zugreift (im Beispiel einfach nur mit ‚pub‘, ohne führenden Slash):

/srv/nfs4      *(rw,sync,fsid=0,crossmnt,no_subtree_check)
/srv/nfs4/pub  *(rw,sync,no_subtree_check)

Nach dem Anlegen des Verzeichnisses mit

mkdir -p -m 777 /srv/nfs4/pub

muss der NFS-Dienst neu gestartet werden:

/etc/init.d/nfs-kernel-server restart

Eine Freigabe mit NFSv4 clientseitig einbinden

Ob der Server erreichbar ist und was er exportiert, kann auf dem Client wiederum mittels

showmount -e server

überprüft werden. Das Mounten in den Ordner ‚/mnt‘ gelingt dann in kürzerer Schreibweise mit

mount server:pub /mnt

Für NFSv4 ist hierbei zu beachten, dass lediglich der betreffende Freigabeordner als RELATIVER PFAD (hier: ‚pub‘) zur NFS-Wurzel (hier: ‚/srv/nfs4‘) direkt nach dem Doppelpunkt angegeben wird!

Zum automatischen Mounten beim Bootvorgang editieren wir wieder die Datei ‚fstab‘:

vi /etc/fstab

Als Mountpunkt verwenden wir nach einem ‚umount /media/pub‘ wieder den selben Ordner, die betreffende Zeile sieht jetzt so aus:

server:pub  /media/pub  nfs4  soft,bg  0  0

Nach dem Abspeichern der Änderungen kann ein Reboot mittels

mount -a

simuliert werden.

Benutzung mit dem Backend ‚exportfs‘

Das Verzeichnis soll lesend und schreiben freigegeben werden:

$ exportfs -o rw *:/tmp
$ ps aux | grep -E 'nfsd|mountd'
root      3969  0.0  0.6  12748  2136 pts/1    S+   20:21   0:00 grep -E nfsd|mountd
$
$ rpc.nfsd
$ rpc.mountd
$
$ ps aux | grep -E 'nfsd|mountd'
root      3973  0.0  0.0      0     0 ?        S<   20:21   0:00 [nfsd4]
root      3974  0.0  0.0      0     0 ?        S<   20:21   0:00 [nfsd4_callbacks]
root      3978  0.0  0.0      0     0 ?        S    20:21   0:00 [nfsd]
root      3979  0.0  0.0      0     0 ?        S    20:21   0:00 [nfsd]
root      3980  0.0  0.0      0     0 ?        S    20:21   0:00 [nfsd]
root      3981  0.0  0.0      0     0 ?        S    20:21   0:00 [nfsd]
root      3982  0.0  0.0      0     0 ?        S    20:21   0:00 [nfsd]
root      3983  0.0  0.0      0     0 ?        S    20:21   0:00 [nfsd]
root      3984  0.0  0.0      0     0 ?        S    20:21   0:00 [nfsd]
root      3985  0.0  0.0      0     0 ?        S    20:21   0:00 [nfsd]
root      3987  0.0  1.5  40956  5416 ?        Ss   20:21   0:00 rpc.mountd
root      3989  0.0  0.6  12748  2132 pts/1    S+   20:21   0:00 grep -E nfsd|mountd
$
$ rpcinfo -p | grep 2049
    100003    2   tcp   2049  nfs
    100003    3   tcp   2049  nfs
    100003    4   tcp   2049  nfs
    100227    2   tcp   2049
    100227    3   tcp   2049
    100003    2   udp   2049  nfs
    100003    3   udp   2049  nfs
    100003    4   udp   2049  nfs
    100227    2   udp   2049
    100227    3   udp   2049
$
$ showmount -e localhost
Export list for localhost:
/tmp *

Will man alle Exporte mit einem Mal entfernen, schreibt man einfach:

$ exportfs -ua

Clientseitge Einbindung

Mit der Option ‚vers=3‘ nutzen wir explizit die zwar alte, aber dank UDP schnellere Version 3:

$ showmount -e d8squid
Export list for d8squid:
/tmp *
$
$ mount -o vers=3 d8squid:/tmp /tmp/mnt/
$
$ echo 123 > /tmp/mnt/datei-von-root
$
$ su - tux
$ echo 123 > /tmp/mnt/datei-von-tux

ACHTUNG: Der Benutzer root wird immer auf nobody gequetscht (Default Option: root_squash):

$ ls -ltrc /tmp/ | tail -5
insgesamt 2
-rw-r--r-- 1 nobody nogroup 4 Nov 21 20:27 datei-von-root
-rw-r--r-- 1 tux    tux     4 Nov 21 20:28 datei-von-tux
$

Fehlersuche

Fehler können sich natürlich an vielen Stellen ergeben, z.B. durch nicht vorhandene Verzeichnisse oder nicht laufende bzw. nicht neu gestartete Daemons. Zu Diagnosezwecken kommt neben dem bereits bekannten Kommando ‚showmount‘ das speziell für RPC geeignete Kommando ‚rpcinfo‘ in Frage:

rpcinfp -p client

rpcinfp -p server

Damit lässt sich kontrollieren, ob die Remote Procedure Calls auf dem Client (ca. 8 Prozesse sichtbar, vor allem ‚portmapper‘) sowie auf dem Server (ca. 30 Prozesse, neben ‚portmapper‘ auch ‚nfs‘ und ‚mountd‘) zur Verfügung stehen.

Probleme treten oft durch Firewalls auf, insbesondere mit NFSv3.

Dank der NFS-Wurzel-Option ‚fsid=0‘ wird das zu importierende Dateisystem nicht als lokales Blockgerät mit Major- und Minor-Nummer bzw. UUID betrachtet, sondern einfach mit der Dateisystem-ID 0 ausgestattet. Dadurch werden nervende „stale NFS mounts“ vermieden, deren Ursache in nicht mehr erreichbaren NFS-Servern liegen.

Topic 210: Network Client Management

210.1 DHCP configuration

DHCP-Server einrichten

Nach der Installation mittels apt-get install isc-dhcp-server

legt man am besten gleich erst einmal das Listening-Interface fest:

$ vi /etc/default/isc-dhcp-server

Wir müssen hier die Schnittstelle angeben, an welcher der Daemon lauschen soll, z.B.:

INTERFACES="eth1"

Dann ist die Hauptkonfigurationsdatei dran. Nach dem Aktivieren und Anpassen des Abschnitts, der mit „very basic subnet declaration“ überschrieben ist, sieht die Datei ‚dhcpd.conf‘ folgendermaßen aus:

$ grep -v '^#' /etc/dhcp/dhcpd.conf

Der Inhalt nach der Bearbeitung:

option domain-name "dom1.test";
option domain-name-servers 10.20.30.3, 10.20.30.4;

default-lease-time 600;
max-lease-time 7200;

ddns-update-style none;

subnet 10.20.30.0 netmask 255.255.255.0 {
  range 10.20.30.50 10.20.30.100;
  option routers 10.20.30.3;
}

Weitere Möglichkeiten für Bereichsoptionen sind in diesem Codebeispiel zu sehen:

# A slightly different configuration for an internal subnet.
subnet 10.5.5.0 netmask 255.255.255.224 {
  range 10.5.5.26 10.5.5.30;
  option domain-name-servers ns1.internal.example.org;
  option domain-name "internal.example.org";
  option routers 10.5.5.1;
  option broadcast-address 10.5.5.31;
  default-lease-time 600;
  max-lease-time 7200;
}

Ein beliebtes LPI-Thema ist in diesem Zusammenhang das Zuweisen fester IP-Adressen anhand der Client-MAC-Adresse:

host mycentos6 { hardware ethernet 08:00:07:26:c0:a5;
  fixed-address 10.20.30.88;
}

Danach bitte nicht vergessen, die Konfiguration neu einzulesen:

$ systemctl restart isc-dhcp-server

Zum Testen ist Live-Monitoring unerlässlich, z.B. mit tail -f /var/log/syslog.

210.2 PAM authentication

Das System der Pluggable Authentication Modules wurde ursprünglich von Sun entwickelt, um auf neue Authentifizierungsmöglichkeiten wie SmartCards flexibler reagieren zu können.

PAM ist nicht zwingend erforderlich, so kommen Tiny-Core und Alpine Linux erst einmal ohne daher: sie verwenden die klassischen C-Bibliotheksroutinen getpwuid, getpwnam und getpwent und parsen die Datei /etc/passwd. Man kann es nachinstallieren, wobei dann nur spezielle, vorkompilierte Module zur Verfügung stehen.

Neben der Flexibilität gibt es einen weiteren Vorteil, der mit PAM als Abstraktionsschicht zwischen User und Anwendung zu tun hat: Programmierer und Distributionsdesigner müssen sich nicht mit den Details der klassischen Shadow-Suite-Authentifizierung herumplagen, sie brauchen ihre Anwendungen nur gegen die gewünschten PAM-Libs auszurichten.

Die Architektur geht gut aus der um eigene Kommentare ergänzten Grafik von medium.com hervor:

../_images/pam-stack.png

Das PAM-System ist nicht zwingend erforderlich, so kommen Tiny-Core und Alpine Linux erst einmal ohne daher. Man kann es nachinstallieren, wobei dann nur wenige spezielle, vorkompilierte Module zur Verfügung stehen.

Die PAM-Libraries liegen normalerweise unter /lib/security/, bei Debian 8 und höher allerdings etwas tiefer unter ‚/lib/x86_64-linux-gnu/security/‘.

Die Konfigurationsdateien liegen normalerweise im Verzeichnis /etc/pam.d, als alternative Verzeichnisse kommen je nach Distribution aber auch /usr/lib/pam.d sowie /usr/etc/pam.d in Frage. Falls davon keines existiert, wird die Datei /etc/pam.conf abgearbeitet. In man pam lesen wir dazu:

This dynamic configuration is set by the contents of the single Linux-PAM configuration file /etc/pam.conf. Alternatively, the configuration can be set by individual configuration files located in the /etc/pam.d/ directory. The presence of this directory will cause Linux-PAM to ignore /etc/pam.conf.

Die Datei /etc/pam.conf liegt im menschlesbaren Tabellenformat vor, hier ein Beispiel für den Service „sshd“ (Quelle: Linux from Scratch):

# Service   Type       Control    Module-path         Module-arguments
sshd        auth       requisite  pam_securetty.so
sshd        auth       required   pam_unix.so
sshd        account    required   pam_unix.so
sshd        session    required   pam_unix.so
sshd        password   required   pam_unix.so         shadow  md5

Beim „Service“ handelt es sich um die Applikation, die reglementiert werden soll, hier den SSH-Daemon. „Type“ und „Control“ besprechen wir im Folgenden.

Modul-Typen und -steuerung

Der Modultyp (type) gibt die Art der Nutzung des Modules an, was in Verwaltungsgruppen organisiert ist: ob man es dafür einsetzen möchte, den Loginprozess zu überwachen oder aber den Prozess beim Ändern von Passwörtern zu gestalten.

Nehmen wir z.B. das wichtigste Modul pam_unix.so her; es kann verschiedenen Zwecken dienen: dem Prüfen der account-Gültigkeit, der authentication selbst, der Verwaltung der session und schließlich dem password-Ändern.

Wir unterscheiden also diese 4 Modultypen:

  • account - Zugriffsberechtigung prüfen (z.B. anhand der Tageszeit und der Anzahl eingeloggter Benutzer)

  • auth - Zugriff gewähren (stellt u.a. Loginprompt zur Verfügung)

  • session - Sitzungsverwaltung (z.B. Logging: bei Debian: /var/log/auth.log, Verzeichnisse mounten)

  • password - Kennwortänderung („is required for updating the authentication token associated with the user“)

Die Modulsteuerung (control) gibt das Verhalten der PAM-API an, falls das Modul seine Authentifizierungsaufgabe nicht erfolgreich ausführen kann.

Bei dieser Fehlersteuerung unterscheiden wir (von restriktiv zu optional):

  • requisite - Der erste aufgetretene Fehler führt zum sofortigen Abbruch der Stapelverarbeitung.

    Beispiel Debian: auth requisite pam_deny.so

  • required - Fehler werden registriert, zum Abbruch kommt es erst nach dem Durchlaufen anderer Module selben Services und Typs.

    Beispiel Alpine: account required pam_unix.so

  • sufficient - Bei Erfolg wird die Stapelverarbeitung sofort beendet, bei Misserfolg geht die Verarbeitung weiter.

    Beispiel Debian für service ‚su‘: auth sufficient pam_wheel.so trust

  • optional - Erfolg oder Misserfolg spielen nur eine Rolle, wenn es sich um das einzige Modul im Stapel handelt.

    Beispiel Debian für service ‚su‘: session optional pam_mail.so nopen

Dies sollte nur einen kleinen Überblick bieten, für die LPI-Lernziele studieren Sie bitte die englische Originalformulierung in man pam.conf. Der erweiterte, komplexe Modus mit eckigen Klammern ist für LPI nicht relevant.

Experimente mit PAM

ACHTUNG: Änderungen sind sofort wirksam, auch root kann sich u.U. nicht mehr einloggen! Daher folgendes beachten:

  1. Backup von /etc/pam.d/ anfertigen

  2. root-Login auf einer zweiten Konsole offen halten

Danach benennen wir unter Debian 12 mittels

mv /etc/pam.d /etc/pam.d_orig
mv /usr/lib/pam.d /usr/lib/pam.d_orig

die beiden pam-Directories um, damit nun die Datei /etc/pam.conf abgearbeitet wird, in der wir alles zentral konfigurieren können.

Und dies sind die Zeilen, die wir für eine minimale pam.conf brauchen (sie beinhaltet bei Debian lediglich ein paar auskommentierte Infos):

other   account   requisite  pam_unix.so
other   auth      requisite  pam_unix.so
other   session   requisite  pam_unix.so
#other  password  requisite  pam_unix.so minlen=1 shadow

Die vierte Zeile bleibt bei den ersten Login-Versuchen noch auskommentiert. Bitte testen, ob ein User sein Passwort ändern kann. Es dürfte nicht funktionieren (siehe dabei Debians /var/log/auth.log!). Dann diese Zeile einkommentieren, worauf Passwortänderungen wieder möglich sind.

Mit dieser minimalen Datei können wir nun weitere Experimente anstellen. Am Schluss aber bitte nicht vergessen, mittels mv /etc/pam.d_orig /etc/pam.d sowie mv /usr/lib/pam.d_orig /usr/lib/pam.d den Ausgangszustand wiederherzustellen.

Passwortstärke mit PAM verbessern

Ziel ist die Installation eines proaktiven Passwortcheckers.

Mittels apt-get install libpam-pwquality werden unter Debian 12 die Pakete libcrack2 und cracklib-runtime mit installiert, die ein einfaches Wörterbuch sowie die dazugehörigen Tools beinhalten.

Damit wurde auch schon das neue Modul in die PAM-Konfiguration eingebunden:

[root@d12:~]# grep qual /etc/pam.d/*
/etc/pam.d/common-password:password     requisite        pam_pwquality.so retry=3
[root@d12:~]#

Und schon gehts an die Benutzung. Zuerst einmal prüfen wir gewisse Zeichenketten, ob sie als Passwort taugen würden:

[root@d12:~]# cracklib-check
123, qwer
123, qwer: OK
P@ssw0rd
P@ssw0rd: OK
^C
[root@d12:~]# #   >>> beide Passwörter werden akzeptiert!!!

Nun wollen wir diese beiden Zeichenketten blockieren, die zu editierende Wörterbuchdatei cracklib-small stammt aus dem Paket cracklib-runtime:

[root@d12:~]# cat >> /usr/share/dict/cracklib-small <<EOF
> 123, qwer
> P@ssw0rd
> EOF
[root@d12:~]#
[root@d12:~]# update-cracklib
skipping line: 1
446108 446107
[root@d12:~]#
[root@d12:~]# cracklib-check
123, qwer
123, qwer: Es basiert auf einem Wörterbucheintrag
^C
[root@d12:~]# #   >>> Prima Sache, dies wird nun nicht mehr akzeptiert.

PAM für faillock konfigurieren

Nach https://www.server-world.info/en/note?os=Debian_12&p=pam&f=2

Es sollen Login-Fehler bei gleichzeitiger Sperrung des Accounts aufgezeichnet werden (Distribution: Debian 12). Dazu sind drei Konfigurationsdateien anzupassen.

Wir editieren die erste Datei mittels vi +17 /etc/pam.d/common-auth und fügen drei Zeilen hinzu (wir stehen dabei schon auf Zeile 17, was die erste aktivierte Zeile ist; siehe dazu die mit „AXPE“ beginnenden Kommentare):

#
# /etc/pam.d/common-auth - authentication settings common to all services
#
# This file is included from other service-specific PAM config files,
# and should contain a list of the authentication modules that define
# the central authentication scheme for use on the system
# (e.g., /etc/shadow, LDAP, Kerberos, etc.).  The default is to use the
# traditional Unix authentication mechanisms.
#
# As of pam 1.0.1-6, this file is managed by pam-auth-update by default.
# To take advantage of this, it is recommended that you configure any
# local modules either before or after the default block, and use
# pam-auth-update to manage selection of other modules.  See
# pam-auth-update(8) for details.

# AXPE: eine Zeile oberhalb der ersten aktiven Zeile einfügen:
auth    required                        pam_faillock.so preauth

# AXPE: dies ist die ursprünglich erste aktive Zeile mit dazugehörigem Kommentar:
# here are the per-package modules (the "Primary" block)
auth    [success=1 default=ignore]      pam_unix.so nullok

# AXPE: und nun diese zwei neue Zeilen unterhalb der ursprünglich ersten aktiven Zeile einfügen:
auth    [default=die]                   pam_faillock.so authfail
auth    sufficient                      pam_faillock.so authsucc

# here's the fallback if no module succeeds
auth    requisite                       pam_deny.so
# prime the stack with a positive return value if there isn't one already;
# this avoids us returning an error just because nothing sets a success code
# since the modules above will each just jump around
auth    required                        pam_permit.so
# and here are more per-package modules (the "Additional" block)
# end of pam-auth-update config

Die zweite Datei bearbeiten wir mittels vi +17 /etc/pam.d/common-account, wie landen wieder auf Zeile 17; es ist hier aber nur eine Zeile hinzuzufügen und zwar als erste aktive Zeile vor allen anderen (sie ist wieder mit „AXPE“ kommentiert):

#
# /etc/pam.d/common-account - authorization settings common to all services
#
# This file is included from other service-specific PAM config files,
# and should contain a list of the authorization modules that define
# the central access policy for use on the system.  The default is to
# only deny service to users whose accounts are expired in /etc/shadow.
#
# As of pam 1.0.1-6, this file is managed by pam-auth-update by default.
# To take advantage of this, it is recommended that you configure any
# local modules either before or after the default block, and use
# pam-auth-update to manage selection of other modules.  See
# pam-auth-update(8) for details.
#

# AXPE: diese Zeile einfach als erste ganz obenan einfügen:
account required                        pam_faillock.so

# AXPE: Das ist ursprünglich Zeile 17:
# here are the per-package modules (the "Primary" block)
account [success=1 new_authtok_reqd=done default=ignore]        pam_unix.so
# here's the fallback if no module succeeds
account requisite                       pam_deny.so
# prime the stack with a positive return value if there isn't one already;
# this avoids us returning an error just because nothing sets a success code
# since the modules above will each just jump around
account required                        pam_permit.so
# and here are more per-package modules (the "Additional" block)
# end of pam-auth-update config

Als dritte Datei bearbeiten wir noch die /etc/security/faillock.conf und passen drei Einstellungen an:

  • silent – keine Infos über Fehlversuche ausgeben

  • deny = 1 – nur zwei Fehlversuche erlaubt

  • unlock_time = 0 – zeitgesteuertes Freischalten ist deaktiviert

Jetzt können wir den Login via lokaler Anmeldung oder ssh gründlich austesten, dabei ist es ratsam, einen Blick auf das Syslog zu werfen, z.B.: journalctl -f

Gesprerrte Accounts sehen wir dann mittels faillock:

[root@d12:~]# faillock
root:
When                Type  Source                                           Valid
tux:
When                Type  Source                                           Valid
2024-06-26 12:12:33 RHOST 192.168.2.104                                        V
[root@d12:~]#

Wieder freischalten können wir einen gesperrten Account mit der Option --reset:

[root@d12:~]# faillock --user tux --reset
[root@d12:~]#
[root@d12:~]# faillock
root:
When                Type  Source                                           Valid
tux:
When                Type  Source                                           Valid
[root@d12:~]#
[root@d12:~]#

ZUSAMMENFASSUNG pam_faillock:

  • kein zusätzliches Software-Paket erforderlich

  • es müssen 3 Configs angepasst werden

Siehe dazu diese Ausschnitte:

[root@d12:~]# alias gg
alias gg='grep -Ev '\''\s*#|^$'\'''
[root@d12:~]#
[root@d12:~]# gg /etc/pam.d/common-auth
auth    required                        pam_faillock.so preauth   # <<< Oben drüber gesetzt
auth    [success=1 default=ignore]      pam_unix.so nullok        # Originalzeile
auth    [default=die]                   pam_faillock.so authfail  # <<< unten drunter gesetzt
auth    sufficient                      pam_faillock.so authsucc  # <<< unten drunter gesetzt
auth    requisite                       pam_deny.so
auth    required                        pam_permit.so
[root@d12:~]#
[root@d12:~]# gg /etc/pam.d/common-account
account required                        pam_faillock.so                          # <<< Oben drüber gesetzt
account [success=1 new_authtok_reqd=done default=ignore]        pam_unix.so      # Originalzeile
account requisite                       pam_deny.so
account required                        pam_permit.so
[root@d12:~]#
[root@d12:~]# gg /etc/security/faillock.conf
silent
deny = 2
unlock_time = 0
[root@d12:~]#
  • Tests durchführen, Kommandos faillock und faillock --user tux --reset

PAM-Konfiguration bei bei Suse 11.0 - ohne Passwort einloggen

(Dies funktioniert im wesentlichen auch bei aktuellen SuSE-Releases)

Es reicht leider nicht mehr aus, die Dateien /etc/passwd und /etc/shadow zu bearbeiten (jeweils die zweite Spalte leeren), zusätzlich muss die PAM-Konfiguration (Pluggable Authentication Modules) angepasst werden:

RUN_AS_ROOT:~# pam-config -a --nullok

Siehe auch: http://vavai.net/tag/opensuse-kiwi-remastering-livecd/

210.3 LDAP client usage

LDAP unter Linux

Siehe dazu:

Die Zielstellung ist etwas anders als z.B. bei Artikeldatenbanken, die Häufigkeit der Schreibzyklen sind bei LDAP nicht entscheidend, hier geht es mehr um Eigenschaften, die die Realität besonders auch im Zusammenhang mit Workflows abbilden können.

Das zugrundeliegende Protokoll ist X.500, es wird allerdings nur in einer verkürzten Form angewendet.

Hauptgedanke ist, dass weltweit Namesräume für Objekte geschaffen werden (siehe IANA.org).

Grobaufteilung:

  1. Container-Objekte (Dateisystem: Verzeichnisse)

  2. Blatt-Objekte (Dateisystem: Dateien)

Einrichtung unter Debian 8

Auf Maschine: smb1.dom1.test

Wir installieren die Client-Werkzeuge und den Server mit apt-get install ldap-utils slapd

Erster Test: Was läuft?

$ slapd -V
@(#) $OpenLDAP: slapd  (Jan 16 2016 23:00:08) $
       root@chimera:/tmp/buildd/openldap-2.4.40+dfsg/debian/build/servers/slapd

ACHTUNG: Hier wird die Konfiguration in der Datenbank selber gespeichert! (Option -F):

Das bedeutet, es liegt die neue Online-Konfiguration vor.

$ ps aux | grep slapd
openldap  2697  0.0  1.7 1221240 5084 ?        Ssl  05:17   0:00 /usr/sbin/slapd -h ldap:/// ldapi:/// -g openldap -u openldap -F /etc/ldap/slapd.d
root      2757  0.0  0.7  12748  2100 pts/0    S+   05:24   0:00 grep slapd
$

Ein erster Fehler beim clientseitigen Abfragen der Datenbank:

$ ldapsearch -x
# extended LDIF
#
# LDAPv3
# base <> (default) with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#

# search result
search: 2
result: 32 No such object

# numResponses: 1
$ echo $?
32
$
$ ldapsearch -x '*'
# extended LDIF
#
# LDAPv3
# base <> (default) with scope subtree
# filter: (objectclass=*)
# requesting: *
#

# search result
search: 2
result: 32 No such object

# numResponses: 1
$

Die Ursache liegt im Fehlen der BASE-Angabe in der clientseitigen Konfigurationsdatei:

$ grep -v ^# /etc/ldap/ldap.conf
TLS_CACERT      /etc/ssl/certs/ca-certificates.crt
$

Ein erfolgreicher, anonymer Zugriff mitsamt DC-Angaben (Domain Component):

$ ldapsearch -x -b dc=dom1,dc=site
# extended LDIF
#
# LDAPv3
# base <dc=dom1,dc=site> with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#

# dom1.test
dn: dc=dom1,dc=site
objectClass: top
objectClass: dcObject
objectClass: organization
o: dom1.test
dc: dom1

# admin, dom1.test
dn: cn=admin,dc=dom1,dc=site
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: admin
description: LDAP administrator

# search result
search: 2
result: 0 Success

# numResponses: 3
# numEntries: 2
$

Eine authentifizierte Abfrage:

$ ldapsearch -x -b dc=dom1,dc=site -W -D cn=admin,dc=dom1,dc=site
Enter LDAP Password:
# extended LDIF
#
# LDAPv3
# base <dc=dom1,dc=site> with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#

# dom1.test
dn: dc=dom1,dc=site
objectClass: top
objectClass: dcObject
objectClass: organization
o: dom1.test
dc: dom1

# admin, dom1.test
dn: cn=admin,dc=dom1,dc=site
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: admin
description: LDAP administrator
userPassword:: e1NTSEF9aFRFYURITHhtZVhMNUJiU3JBbVdWQ3IrU0RFUE85SHM=

# search result
search: 2
result: 0 Success

# numResponses: 3
# numEntries: 2
$

Dazu drei Aufgaben:

  1. Datei /etc/ldap/ldap.conf bearbeiten, anpassen von BASE   dc=example,dc=com

  2. Backup der Datenbank anlegen mkdir ldap.bk ; cp -a /var/lib/ldap/ ldap.bk/

  3. Asisstenten starten: dpkg-reconfigure slapd

ACHTUNG das geht nur 1 mal, das Verzeichnis kann aber einfach verschoben werden.

mv /var/backups/unknown-2.4.40+dfsg-1+deb8u2.ldapdb /root

210.4 Configuring an OpenLDAP server

Nutzer via LDIF-Dateien hinzufügen

Zuerst einmal: Habe ich überhaupt die passenden Schemadateien für die gewünschten Objekteigenschaften bereits eingebunden?

$ grep organizationalUnit /etc/ldap/schema/*.schema
/etc/ldap/schema/core.schema:attributetype ( 2.5.4.11 NAME ( 'ou' 'organizationalUnitName' )
/etc/ldap/schema/core.schema:objectclass ( 2.5.6.5 NAME 'organizationalUnit'
/etc/ldap/schema/cosine.schema:         organizationName $ organizationalUnitName $ host )
/etc/ldap/schema/cosine.schema:         organizationName $ organizationalUnitName $
/etc/ldap/schema/cosine.schema:         localityName $ organizationName $ organizationalUnitName )
/etc/ldap/schema/cosine.schema: SUP ( organization $ organizationalUnit ) STRUCTURAL
/etc/ldap/schema/openldap.schema:       SUP organizationalUnit
$
$
$ grep posixAccount  /etc/ldap/schema/*.schema
/etc/ldap/schema/nis.schema:objectclass ( 1.3.6.1.1.1.2.0 NAME 'posixAccount'
$

Das Hinzufügen des Benutzers „Hugo Schulz“ gelingt problemlos:

$ cat hugo.ldif
dn: cn=Hugo Schulz,dc=dom1,dc=site
objectclass: person
cn: Hugo Schulz
sn: Schulz
$
$ file hugo.ldif
hugo.ldif: ASCII text
$


$ ldapadd -x -w admin -D cn=admin,dc=dom1,dc=site -f hugo.ldif
adding new entry "cn=Hugo Schulz,dc=dom1,dc=site"

$ echo $?
0
$
$ ldapsearch -x
# extended LDIF
#
# LDAPv3
# base <dc=dom1,dc=site> (default) with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#

# dom1.test
dn: dc=dom1,dc=site
objectClass: top
objectClass: dcObject
objectClass: organization
o: dom1.test
dc: dom1

# admin, dom1.test
dn: cn=admin,dc=dom1,dc=site
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: admin
description: LDAP administrator

# Hugo Schulz, dom1.test
dn: cn=Hugo Schulz,dc=dom1,dc=site
objectClass: person
cn: Hugo Schulz
sn:: U2NodWx6IA==

# search result
search: 2
result: 0 Success

# numResponses: 4
# numEntries: 3
$

Eine initiale Struktur für Samba und Thunderbird

Das folgende Beispiel legt die Grundlagen für Strukturen, wie sie für eine Samba PDC Domäne sowie eine Kontaktdatenbank für Thunderbird (Mail-Client) erforderlich sind.

Die initiale Struktur fügen wir mit Hilfe der Datei init.ldif in die Datenbank ein, ihr Inhalt lautet folgendermaßen:

# Falls kein Debian bzw. 'dpkg-reconfigure slapd' Verwendung findet, muss zuerste eine
# grundlegende Struktur gegründet und der Admin angelegt werden (die beiden folg. Blöcke):
#dn: dc=dom1,dc=site
#objectClass: top
#objectClass: dcObject
#objectClass: organization
#o: dom1.test
#dc: dom1

#dn: cn=admin,dc=dom1,dc=site
#objectClass: simpleSecurityObject
#objectClass: organizationalRole
#cn: admin
#description: LDAP administrator
#userPassword: secret

# Für den Samba DC
dn: ou=users,dc=dom1,dc=site
objectClass: organizationalUnit
ou: users

dn: ou=groups,dc=dom1,dc=site
objectClass: organizationalUnit
ou: groups

dn: ou=idmap,dc=dom1,dc=site
objectClass: organizationalUnit
ou: idmap

dn: ou=computers,dc=dom1,dc=site
objectClass: organizationalUnit
ou: computers

# Für Thunderbirds Kontaktdatenbank
dn: ou=contacts,dc=dom1,dc=site
objectClass: organizationalUnit
ou: contacts

Das Kommando dazu lautet ähnlich wie oben:

$ ldapadd -x -w admin -D cn=admin,dc=dom1,dc=site -f init.ldif

Zum Einbinden von Thunderbird (Addressbuch mittels „ou=contacts“) siehe unter:

Vertiefung LDAP

Hinzufügen des Benutzers ‚fritz‘, der als echter Linux-User netzwerkweit einsetzbar ist.

Dateiinhalt von fritz-posixAccount.ldif:

dn: cn=fritz,dc=dom1,dc=site
objectclass: person
objectclass: posixAccount
cn: fritz
sn: Schulz
uid: fritz
uidNumber: 2000
gidNumber: 100
homeDirectory: /home/fritz
loginShell: /bin/bash
gecos: Fritz Schulz

Danach wollen wir uns den ‚fritz‘ anzeigen lassen:

ldapsearch -x -b dc=dom1,dc=site cn=fritz
# extended LDIF
#
# LDAPv3
# base <dc=dom1,dc=site> with scope subtree
# filter: cn=fritz
# requesting: ALL
#

# fritz, dom1.test
dn: cn=fritz,dc=dom1,dc=site
objectClass: person
objectClass: posixAccount
cn: fritz
sn: Schulz
uid: fritz
uidNumber: 2000
gidNumber: 100
homeDirectory: /home/fritz
loginShell: /bin/bash
gecos: Fritz Schulz

# search result
search: 2
result: 0 Success

# numResponses: 2
# numEntries: 1

Nutzer modifizieren

  1. Mittels löschen und neu anlegen

Komplett entfernen: lda:pdelete  -x -w admin -D cn=admin,dc=dom1,dc=site cn=fritz,dc=dom1,dc=site

Ldif-Datei ändern: vi fritz-posixAccount.ldif (ändern z.B. von „uidNumber“)

$ ldapadd -x -w admin -D cn=admin,dc=dom1,dc=site -f fritz-posixAccount.ldif
adding new entry "cn=fritz,dc=dom1,dc=site"

$
$ ldapsearch -x -b dc=dom1,dc=site uid=3000
# extended LDIF
#
# LDAPv3
# base <dc=dom1,dc=site> with scope subtree
# filter: uid=3000
# requesting: ALL
#

# search result
search: 2
result: 0 Success

# numResponses: 1
$ ldapsearch -x -b dc=dom1,dc=site uidNumber=3000
# extended LDIF
#
# LDAPv3
# base <dc=dom1,dc=site> with scope subtree
# filter: uidNumber=3000
# requesting: ALL
#

# fritz, dom1.test
dn: cn=fritz,dc=dom1,dc=site
objectClass: person
objectClass: posixAccount
cn: fritz
sn: Schulz
uid: fritz
uidNumber: 3000
gidNumber: 100
homeDirectory: /home/fritz
loginShell: /bin/bash
gecos: Fritz Schulz

# search result
search: 2
result: 0 Success

# numResponses: 2
# numEntries: 1
$
  1. Eleganteres Modifizieren mit ldapmodify

Die entscheidende Angabe ist hier changetype, sie gibt an, ob nur modifiziert oder sogar gelöscht werden soll, außerdem muss mit replace angegeben werden, welcher Wert zu ändern ist:

$ cat fritz-uid-modify-posixAccount.ldif
dn: cn=fritz,dc=dom1,dc=site
changetype: modify
replace: uidNumber
uidNumber: 3500
$


$ ldapmodify -x -w admin -D cn=admin,dc=dom1,dc=site -f fritz-uid-modify-posixAccount.ldif
modifying entry "cn=fritz,dc=dom1,dc=site"

$
$ ldapsearch -LLL -x -b dc=dom1,dc=site uidNumber=3000
$
$ ldapsearch -LLL -x -b dc=dom1,dc=site uidNumber=3500
dn: cn=fritz,dc=dom1,dc=site
objectClass: person
objectClass: posixAccount
cn: fritz
sn: Schulz
uid: fritz
gidNumber: 100
homeDirectory: /home/fritz
loginShell: /bin/bash
gecos: Fritz Schulz
uidNumber: 3500

Will man dem Nutzer ein Passwort setzen, benötigen wir ldappasswd:

$ ldappasswd -x -D cn=admin,dc=dom1,dc=site -w admin   cn=fritz,dc=dom1,dc=site -s halloWelt
$
$ ldapsearch -LLL -x -b dc=dom1,dc=site uidNumber=3500 -D cn=admin,dc=dom1,dc=site -w admin
dn: cn=fritz,dc=dom1,dc=site
objectClass: person
objectClass: posixAccount
cn: fritz
sn: Schulz
uid: fritz
gidNumber: 100
homeDirectory: /home/fritz
loginShell: /bin/bash
gecos: Fritz Schulz
uidNumber: 3500
userPassword:: e1NTSEF9a1BiMFNEcXBMT2duZ0luMUNuZFZKT3ZLcE1pSjB1M2g=

Was weiterhin erforderlich sein wird, ist die Objektklasse shadowAccount, um Linux-Logins komplett zu machen:

Sicherheit mit SASL mittel einfach einzurichtenten GnuTLS dank easy-rsa:

Konvertierung vom Old Style Config File zur Online-Konfiguration:

Konvertierung in umgekehrte Richtung zur old style Config File Konfiguration:

Online-Konfiguration komplett ausgeben:

ldapsearch  -Y EXTERNAL -H ldapi:/// -b "cn=config" | less

Speziell, um nur „RootDN“ zu finden:

$ ldapsearch  -Y EXTERNAL -H ldapi:/// -b "cn=config" | grep --color -A3  RootDN  SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
olcAttributeTypes: ( OLcfgDbAt:0.8 NAME 'olcRootDN' EQUALITY distinguishedName
Match SYNTAX OMsDN SINGLE-VALUE )
olcAttributeTypes: ( OLcfgGlAt:51 NAME 'olcRootDSE' EQUALITY caseIgnoreMatch S
YNTAX OMsDirectoryString )
--
cRequires $ olcRestrict $ olcRootDN $ olcRootPW $ olcSchemaDN $ olcSecurity $
olcSizeLimit $ olcSyncUseSubentry $ olcSyncrepl $ olcTimeLimit $ olcUpdateDN
$ olcUpdateRef $ olcMirrorMode $ olcMonitoring $ olcExtraAttrs ) )
olcObjectClasses: ( OLcfgGlOc:5 NAME 'olcOverlayConfig' DESC 'OpenLDAP Overlay
--
olcRootDN: cn=admin,cn=config

# {1}mdb, config
dn: olcDatabase={1}mdb,cn=config
--
olcRootDN: cn=admin,dc=dom1,dc=site
olcRootPW: {SSHA}UM4SLSJpzRHAuzfOEvxSOjn7iMSe8GRb
olcDbCheckpoint: 512 30
olcDbIndex: objectClass eq
$

Fortgeschrittenes Filtern mit ldapsearch

Zuerst legen wir weitere Nutzer an, die auch für spätere Linux-Authentifizierung genutzt werden können:

$ vi fritz1.ldif
$
$ cat fritz1.ldif
dn: uid=fritz,dc=dom1,dc=test
objectClass: top
objectClass: person
objectClass: posixAccount
objectClass: shadowAccount
objectClass: inetOrgPerson
uid: fritz
uidNumber: 10000
gidNumber: 100
cn: fritz
sn: Meier
loginShell: /bin/bash
homeDirectory: /home/fritz
mail: fritz@dom1.test
$
$
$ ldapadd -xWD cn=admin,dc=dom1,dc=test -f fritz1.ldif
Enter LDAP Password:
adding new entry "uid=fritz,dc=dom1,dc=test"

$
$ ldapsearch -xLLL uid=fr*
dn: uid=fritz,dc=dom1,dc=test
objectClass: top
objectClass: person
objectClass: posixAccount
objectClass: shadowAccount
objectClass: inetOrgPerson
uid: fritz
uidNumber: 10000
gidNumber: 100
cn: fritz
sn: Meier
loginShell: /bin/bash
homeDirectory: /home/fritz
mail: fritz@dom1.test

$
$ sed 's/fritz/friedrich/;s/10000/10001/' fritz1.ldif > friedrich1.ldif
$
$ cat friedrich1.ldif
dn: uid=friedrich,dc=dom1,dc=test
objectClass: top
objectClass: person
objectClass: posixAccount
objectClass: shadowAccount
objectClass: inetOrgPerson
uid: friedrich
uidNumber: 10001
gidNumber: 100
cn: friedrich
sn: Meier
loginShell: /bin/bash
homeDirectory: /home/friedrich
mail: friedrich@dom1.test
$
$
$ ldapadd -xWD cn=admin,dc=dom1,dc=test -f friedrich1.ldif
Enter LDAP Password:
adding new entry "uid=friedrich,dc=dom1,dc=test"

$
$ ldapsearch -xLLL uid=fri*
dn: uid=fritz,dc=dom1,dc=test
objectClass: top
objectClass: person
objectClass: posixAccount
objectClass: shadowAccount
objectClass: inetOrgPerson
uid: fritz
uidNumber: 10000
gidNumber: 100
cn: fritz
sn: Meier
loginShell: /bin/bash
homeDirectory: /home/fritz
mail: fritz@dom1.test

dn: uid=friedrich,dc=dom1,dc=test
objectClass: top
objectClass: person
objectClass: posixAccount
objectClass: shadowAccount
objectClass: inetOrgPerson
uid: friedrich
uidNumber: 10001
gidNumber: 100
cn: friedrich
sn: Meier
loginShell: /bin/bash
homeDirectory: /home/friedrich
mail: friedrich@dom1.test

$

Dann vergeben wir ihnen Passwörter:

$ ldappasswd -xWD cn=admin,dc=dom1,dc=test uid=fritz,dc=dom1,dc=test -s fritS001
Enter LDAP Password:
$
$ ldappasswd -xWD cn=admin,dc=dom1,dc=test uid=friedrich,dc=dom1,dc=test -s friedS001
Enter LDAP Password:
$
$ ldapsearch -xLLL uid=frit*
dn: uid=fritz,dc=dom1,dc=test
objectClass: top
objectClass: person
objectClass: posixAccount
objectClass: shadowAccount
objectClass: inetOrgPerson
uid: fritz
uidNumber: 10000
gidNumber: 100
cn: fritz
sn: Meier
loginShell: /bin/bash
homeDirectory: /home/fritz
mail: fritz@dom1.test

$ ldapsearch -xLLL uid=frit* -WD cn=admin,dc=dom1,dc=test
Enter LDAP Password:
dn: uid=fritz,dc=dom1,dc=test
objectClass: top
objectClass: person
objectClass: posixAccount
objectClass: shadowAccount
objectClass: inetOrgPerson
uid: fritz
uidNumber: 10000
gidNumber: 100
cn: fritz
sn: Meier
loginShell: /bin/bash
homeDirectory: /home/fritz
mail: fritz@dom1.test
userPassword:: e1NTSEF9bThBYWFKeENnM2d2QXB5YkxIcndtYTB5VXdicFMrZFY=

$

Und jetzt kommt das Filtern mit logisch UND bzw. ODER.

  1. Logisch ODER:

$ ldapsearch -xLLL '(|(uid=fritz)(cn=ad*))'
dn: cn=admin,dc=dom1,dc=test
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: admin
description: LDAP administrator

dn: uid=fritz,dc=dom1,dc=test
objectClass: top
objectClass: person
objectClass: posixAccount
objectClass: shadowAccount
objectClass: inetOrgPerson
uid: fritz
uidNumber: 10000
gidNumber: 100
cn: fritz
sn: Meier
loginShell: /bin/bash
homeDirectory: /home/fritz
mail: fritz@dom1.test

$
  1. Logisch UND:

$ ldapsearch -xLLL '(&(uid=fri*)(uidNumber=10001))'
dn: uid=friedrich,dc=dom1,dc=test
objectClass: top
objectClass: person
objectClass: posixAccount
objectClass: shadowAccount
objectClass: inetOrgPerson
uid: friedrich
uidNumber: 10001
gidNumber: 100
cn: friedrich
sn: Meier
loginShell: /bin/bash
homeDirectory: /home/friedrich
mail: friedrich@dom1.test

$
  1. Logisch UND, wobei aber der 2. Term negiert werden soll:

$ ldapsearch -xLLL '(&(uid=fri*)(!(uidNumber=10001)))'
dn: uid=fritz,dc=dom1,dc=test
objectClass: top
objectClass: person
objectClass: posixAccount
objectClass: shadowAccount
objectClass: inetOrgPerson
uid: fritz
uidNumber: 10000
gidNumber: 100
cn: fritz
sn: Meier
loginShell: /bin/bash
homeDirectory: /home/fritz
mail: fritz@dom1.test

$

Siehe dazu auch https://www.tecchannel.de/a/ldap-abfragen-erstellen,464680,2

Von Online Configuration zu Konfigurationsdateien

ZIEL: Konvertierung/Downgrade von OLC zu Files

$ systemctl stop slapd
$
$ mv /etc/ldap/slapd.d /root
$ cp /usr/share/slapd/slapd.conf /etc/ldap/
$ sed -i "s/@BACKEND@/hdb/" /etc/ldap/slapd.conf
$ sed -i "s/@SUFFIX@/dc=dom1,dc=site/" /etc/ldap/slapd.conf
$ sed -i "s/# rootdn/rootdn/" /etc/ldap/slapd.conf
$ slappasswd
New password:
Re-enter new password:
{SSHA}YuHMAaXTvmqNZSyzSXgqN5PQ96btrgjI
$
$ vi /etc/ldap/slapd.conf
$

Hinzuzufügen war die zweite Zeile, wie hier zu sehen:

$ grep -B1 rootpw /etc/ldap/slapd.conf
rootdn          "cn=admin,dc=dom1,dc=site"
rootpw          "{SSHA}YuHMAaXTvmqNZSyzSXgqN5PQ96btrgjI"
$

$ sed -i "s/@ADMIN@/cn=admin,dc=dom1,dc=site/" /etc/ldap/slapd.conf
$
$ ls -l /var/lib/ldap/
insgesamt 144
-rw------- 1 openldap openldap 143360 Nov 19 11:19 data.mdb
-rw------- 1 openldap openldap   8192 Nov 19 13:07 lock.mdb
$
$ mv -v /var/lib/ldap/* /root
„/var/lib/ldap/data.mdb“ -> „/root/data.mdb“
„/var/lib/ldap/data.mdb“ wurde entfernt
„/var/lib/ldap/lock.mdb“ -> „/root/lock.mdb“
„/var/lib/ldap/lock.mdb“ wurde entfernt
$
$ systemctl start slapd
Job for slapd.service failed. See 'systemctl status slapd.service' and 'journalctl -xn' for details.
$

Der Start schlägt fehl, sind die Startparameter in Ordnung?

Zu Erinnerung:

$ pgrep -a slap
3073 /usr/sbin/slapd -h ldap:/// ldapi:/// -g openldap -u openldap -F /etc/ldap/slapd.d

Die Konfigdatei sieht insgesamt so aus:

$ grep -v ^# /etc/ldap/slapd.conf  | grep -v ^$
include         /etc/ldap/schema/core.schema
include         /etc/ldap/schema/cosine.schema
include         /etc/ldap/schema/nis.schema
include         /etc/ldap/schema/inetorgperson.schema
pidfile         /var/run/slapd/slapd.pid
argsfile        /var/run/slapd/slapd.args
loglevel        none
modulepath      /usr/lib/ldap
moduleload      back_hdb
sizelimit 500
tool-threads 1
backend         hdb
database        hdb
suffix          "dc=dom1,dc=site"
rootdn directive for specifying a superuser on the database. This is needed
rootdn          "cn=admin,dc=dom1,dc=site"
rootpw          "{SSHA}YuHMAaXTvmqNZSyzSXgqN5PQ96btrgjI"
directory       "/var/lib/ldap"
dbconfig set_cachesize 0 2097152 0
dbconfig set_lk_max_objects 1500
dbconfig set_lk_max_locks 1500
dbconfig set_lk_max_lockers 1500
index           objectClass eq
lastmod         on
checkpoint      512 30
access to attrs=userPassword,shadowLastChange
        by dn="cn=admin,dc=dom1,dc=site" write
        by anonymous auth
        by self write
        by * none
access to dn.base="" by * read
access to *
        by dn="cn=admin,dc=dom1,dc=site" write
        by * read
$

Ein Startversuch mit

/usr/sbin/slapd -4 -d 15  -h ldap://127.0.0.1:9009/  -g openldap -u openldap -f /etc/ldap/slapd.conf

schlägt aber leider auch fehl.

Aufgabe: Hier bitte weiterstudieren: https://wiki.debian.org/LDAP/OpenLDAPSetup#Access_control

FEHLER GEFUNDEN

Der entscheidende Hinweis kam durch den Start mit dem Debug-Wert von 64 zustande (configuration processing), siehe zum Debugging: http://www.openldap.org/doc/admin24/runningslapd.html

Das obige sed -i "s/# rootdn/rootdn/" /etc/ldap/slapd.conf hatte etwas zuviel einkommentiert!

Nach dem Auskommentieren von „rootdn directive for specifying a superuser on the database. This is needed“ funktioniert es jetzt ohne Fehlermeldungen.

Mit folgender Zeile läuft der slpad erst einmal an:

/usr/sbin/slapd -g openldap -u openldap -f /etc/ldap/slapd.conf -d 64

Viel Erfolg und Spaß weiterhin…

Übungsumgebung

Für die nächsten Themen benötigen wir eine etwas komplexere Übungsumgebung. Siehe dazu http://pemmann.de/cc/Doc/Testumgebung/Misc/dmz.png

Topic 211: E-Mail Services

211.1 Using e-mail servers

ROLLE: Mail Transfer Agent (MTA)

Typische Daemons:

  • sendmail

  • qmail

  • postfix

  • exim

Port-Nummern für E-Mail (https://de.wikipedia.org/wiki/STARTTLS):

  • SMTP auf Port 25 bzw. 587 und SMTPS auf Port 465

  • IMAP auf Port 143 und IMAPS auf Port 993

  • POP3 auf Port 110 und POP3S auf Port 995

Zu exim

https://gambaru.de/blog/2012/03/21/nur-versenden-mailserver-mit-debian-und-exim/

Welchen Port er öffnen soll, wird dem Daemin über die Datei /etc/default/exim4 mitgegeben. Ansonsten ist Port 25 voreingestellt:

$ ps aux  | grep exim
Debian-+  1035  0.0  0.4  53248  3272 ?        Ss   Nov23   0:00 /usr/sbin/exim4 -bd -q30m

Am besten wir vergleichen die Konfiguration vor der Umstellung auf „Internet Server“ und danach:

$ mkdir /root/exim4.configs_orig
$
$ cp /etc/default/exim4 /root/exim4.configs_orig/etc__default__exim4
$
$ cp -a /etc/exim4/ /root/etc__exim4
$
$ dpkg-reconfigure exim4-config

Wir wählen im Assistenten:

  • „Internet Server“

  • deb8.dom1.test

  • 127.0.0.1 ; ::1 ; 10.20.30.5

  • deb8.dom1.test

  • Alle weiteren Voreinstellungen übernehmen…

Danach sieht das Ganze so aus:

$ service exim4 restart
$ lsof -i TCP -Pn | grep 25
named      613     bind   23u  IPv4  12588      0t0  TCP 127.0.0.1:953 (LISTEN)
named      613     bind   24u  IPv6  12589      0t0  TCP [::1]:953 (LISTEN)
sshd       615     root    3u  IPv4  12576      0t0  TCP *:22 (LISTEN)
sshd       615     root    4u  IPv6  12585      0t0  TCP *:22 (LISTEN)
exim4     2270     root    4u  IPv4  15370      0t0  TCP 127.0.0.1:25 (LISTEN)
exim4     2270     root    5u  IPv6  15371      0t0  TCP [::1]:25 (LISTEN)
$
$
$ ps xu | grep exim
root      2270  0.0  0.7  53244  2172 ?        Ss   09:48   0:00 /usr/sbin/exim4 -bd -q30m
root      2274  0.0  0.7  12748  2176 pts/0    S+   09:48   0:00 grep exim
$

In der Startkonfiguration hat sich nichts geändert:

$ ls -l /etc/default/exim4
-rw-r--r-- 1 root root 1018 Nov 14 18:34 /etc/default/exim4
$

$ lsof -i TCP -Pn | grep exim
exim4     2270     root    4u  IPv4  15370      0t0  TCP 127.0.0.1:25 (LISTEN)
exim4     2270     root    5u  IPv6  15371      0t0  TCP [::1]:25 (LISTEN)
$

Aber hier werden wir fündig:

$ grep -v ^# /etc/exim4/update-exim4.conf.conf
dc_eximconfig_configtype='internet'
dc_other_hostnames='deb8.dom1.test'
dc_local_interfaces='127.0.0.1 ; ::1 ; 10.20.30.5'
dc_readhost=''
dc_relay_domains=''
dc_minimaldns='false'
dc_relay_nets=''
dc_smarthost=''
CFILEMODE='644'
dc_use_split_config='false'
dc_hide_mailname=''
dc_mailname_in_oh='true'
dc_localdelivery='mail_spool'
$
$
$ grep -r 'dc_eximconfig_configtype' /root/etc__exim4/                    /root/etc__exim4/update-exim4.conf.conf:dc_eximconfig_configtype='local'

Migration von exim4 zu sendmail

Autor: https://de.wikipedia.org/wiki/Alan_Cox

Problem: Exim ist nicht gar zu sehr kompatibel zu sendmail!

Deshalb wollen wir Sendmail installieren:

$ apt-get install sendmail-bin

Dabei wird Exim entfernt und sendmail gestartet (was leider nicht ohne Warnungen verlief):

$ lsof -i TCP -Pn | grep 25
named      613     bind   23u  IPv4  12588      0t0  TCP 127.0.0.1:953 (LISTEN)
named      613     bind   24u  IPv6  12589      0t0  TCP [::1]:953 (LISTEN)
sshd       615     root    3u  IPv4  12576      0t0  TCP *:22 (LISTEN)
sshd       615     root    4u  IPv6  12585      0t0  TCP *:22 (LISTEN)
sendmail- 4689     root    3u  IPv4  19208      0t0  TCP 127.0.0.1:25 (LISTEN)
$

Erste Tests:

$ mailq
MSP Queue status...
/var/spool/mqueue-client is empty
                Total requests: 0
MTA Queue status...
/var/spool/mqueue is empty
                Total requests: 0
$
$
$ ls -l /var/spool/mail/
insgesamt 4
-rw-rw---- 1 tux mail 517 Nov 29 11:03 tux
$
$
$
$ echo 123 | mail -s "testmail 2" tux
$
$ ls -l /var/spool/mail/
insgesamt 4
-rw-rw---- 1 tux mail 517 Nov 29 11:03 tux
$
$
$
$
$ mailq
MSP Queue status...
/var/spool/mqueue-client is empty
                Total requests: 0
MTA Queue status...
                /var/spool/mqueue (1 request)
-----Q-ID----- --Size-- -----Q-Time----- ------------Sender/Recipient-----------
uATAEes6004750        4 Tue Nov 29 11:14 <tux@d8slave.dom1.test>
                (Operating system error)
                                        <tux@d8slave.dom1.test>
                Total requests: 1
$

ACHTUNG: Nicht einmal die lokale Mailkommunikation funktioniert!

Evl. könnte es an diesem Mischmasch liegen:

$ cat /etc/mailname
deb8.dom1.test
$

$ hostname -f > /etc/mailname
$
$ cat /etc/mailname
d8slave.dom1.test
$

SMTP - Returncodes: http://www.elektronik-kompendium.de/sites/net/0903081.htm

Sendmail ist in Debian 8 nicht mehr besonders gut integriert, das Paket ‚sendmail‘ lässt sich überhaupt nicht installieren, ein Stück weit kommen wir aber damit:

$ dpkg-reconfigure sendmail-bin
Could not open /etc/mail/databases(Datei oder Verzeichnis nicht gefunden), creating it.
$

Die nächsten Schritte zur Erforschung der Konfiguration:

http://64-bit.de/dokumentationen/netzwerk/f/002/DE-Mailserver-HOWTO-3.html

  • Hauptfile: sendmail.cf

  • Makro-Konfig-file: /etc/mail/sendmail.mc (Kommentar: „dnl“)

  • Frontend-file: /etc/mail/sendmail.conf

$ ls -l /etc/mail
insgesamt 336
-rw------- 1 root  root   4261 Nov 29 11:23 access
-rw-r----- 1 smmta smmsp 12288 Nov 29 11:23 access.db
-rw-r--r-- 1 root  root    281 Jun 30 20:08 address.resolve
lrwxrwxrwx 1 root  smmsp    10 Nov 29 11:11 aliases -> ../aliases
-rw-r----- 1 smmta smmsp 12288 Nov 29 11:23 aliases.db
-rw-r--r-- 1 root  root   3219 Nov 29 11:23 databases
-rw-r--r-- 1 root  root   5657 Jul  4 00:32 helpfile
-rw-r--r-- 1 root  smmsp    28 Nov 29 11:11 local-host-names
drwxr-sr-x 2 smmta smmsp  4096 Nov 29 11:11 m4
-rwxr-xr-- 1 root  smmsp  9995 Nov 29 11:23 Makefile
drwxr-xr-x 2 root  root   4096 Nov 29 11:11 peers
drwxr-xr-x 2 root  smmsp  4096 Jun 30 20:08 sasl
-rw-r--r-- 1 root  smmsp 64522 Nov 29 11:23 sendmail.cf
-rw-r--r-- 1 root  smmsp   269 Nov 29 11:23 sendmail.cf.errors
-rw-r--r-- 1 root  root  64518 Nov 29 11:23 sendmail.cf.old
-rw-r--r-- 1 root  root  12236 Nov 29 11:23 sendmail.conf
-rw-r--r-- 1 root  smmsp  4221 Nov 29 11:23 sendmail.mc
-rw-r--r-- 1 root  root    149 Jun 30 20:08 service.switch
-rw-r--r-- 1 root  root    180 Jun 30 20:08 service.switch-nodns
drwxr-sr-x 2 smmta smmsp  4096 Nov 29 11:11 smrsh
-rw-r--r-- 1 root  smmsp 44055 Nov 29 11:23 submit.cf
-rw-r--r-- 1 root  root  44051 Nov 29 11:23 submit.cf.old
-rw-r--r-- 1 root  smmsp  2381 Nov 29 11:23 submit.mc
drwxr-xr-x 2 smmta smmsp  4096 Nov 29 11:11 tls
-rw-r--r-- 1 root  smmsp     0 Nov 29 11:11 trusted-users
$
$ whatis m4
m4 (1)               - macro processor
$
$ grep -i smarthost /etc/mail/sendmail.cf
#O FallbackSmartHost=fall.back.host.net
R$* < @ [ $+ ] : > $*           $#esmtp $@ [$2] $: $1 < @ [$2] > $3     no smarthost: send
R$* < @ [ $+ ] : $- : $*> $*    $#$3 $@ $4 $: $1 < @ [$2] > $5  smarthost with mailer
R$* < @ [ $+ ] : $+ > $*        $#esmtp $@ $3 $: $1 < @ [$2] > $4       smarthost without mailer
# pass names that still have a host to a smarthost (if defined)
R$* < @ $* > $*         $: $>MailerToTriple < $S > $1 < @ $2 > $3       glue on smarthost name
$

Das erzeugt nun die eigentliche Konfigdatei:

$ cp /etc/mail/sendmail.mc .
$
$ vi sendmail.mc
$
$ m4 sendmail.mc > sendmail.cf

Weiter Konfigadteien:

Siehe https://www.freebsd.org/doc/de_DE.ISO8859-1/books/handbook/sendmail.html

Die Datei ‚/etc/mail/local-host-names‘ ist das Pendant zu Postfix’s Direktive ‚mydestination‘, damit wird festgelegt, für welche Domänen der Server E-Mails annehmen soll:

# local-host-names - include all aliases for your machine here.
# Example from http://www.faqs.org/docs/securing/chap22sec180.html
openna.com
deep.openna.com
www.openna.com
win.openna.com
mail.openna.com

Unter Debian:

$ cat /etc/mail/local-host-names
localhost
d8slave.dom1.test
$
$ ### Warteschlange ausgehender Mails:
$
$ # mailq = sendmail -bq
$
$ ls -l /var/spool/mqueue
insgesamt 16
-rw-r----- 1 smmta smmsp   4 Nov 29 11:14 dfuATAEes6004750
-rw-r----- 1 root  smmsp   4 Nov 29 11:24 dfuATAOW2H005638
-rw-r----- 1 root  smmsp 859 Nov 29 11:43 qfuATAEes6004750
-rw-r----- 1 root  smmsp 859 Nov 29 11:43 qfuATAOW2H005638
$
$
$
$
$ ### Pfad für ausgelieferte Mails (in house, MDA):
$
$ ls -l /var/spool/mail
lrwxrwxrwx 1 root root 7 Nov 14 18:25 /var/spool/mail -> ../mail
$
$ ls -lL /var/spool/mail
insgesamt 4
-rw-rw---- 1 tux mail 517 Nov 29 11:03 tux
$

Migration zu Postfix

$ apt-get install postfix
Paketlisten werden gelesen... Fertig
Abhängigkeitsbaum wird aufgebaut.
Statusinformationen werden eingelesen.... Fertig
Die folgenden Pakete wurden automatisch installiert und werden nicht mehr benötigt:
libecap2 libnetfilter-conntrack3 squid-langpack squid3-common
Verwenden Sie »apt-get autoremove«, um sie zu entfernen.
Die folgenden zusätzlichen Pakete werden installiert:
ssl-cert
Vorgeschlagene Pakete:
postfix-mysql postfix-pgsql postfix-ldap postfix-pcre sasl2-bin dovecot-common postfix-cdb
ufw postfix-doc openssl-blacklist
Die folgenden Pakete werden ENTFERNT:
sendmail-bin
Die folgenden NEUEN Pakete werden installiert:
postfix ssl-cert
0 aktualisiert, 2 neu installiert, 1 zu entfernen und 5 nicht aktualisiert.
Es müssen 1.392 kB an Archiven heruntergeladen werden.
Nach dieser Operation werden 2.021 kB Plattenplatz zusätzlich benutzt.
Möchten Sie fortfahren? [J/n]

Der Assistent kommt wieder zum Vorschein, wir wählen:

  • „Internet Site“

  • „d8slave.dom1.test“

Die beiden wichtigsten Dateien sind:

Ein einfaches Szanrio, was ohne DNS auskommt (/etc/hosts pflegen!):

disable_dns_lookups = yes
mydestination = d8slave.dom1.test, localhost.dom1.test, , localhost
mynetworks = 10.20.30.0/24 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
inet_interfaces = all

Wir ändern ganz praktisch die Datei ‚main.cf‘, hinzuzufügen ist ‚dom1.test‘ beim ersten Eintrag, beim zweiten dann ‚10.20.30.0/24‘:

mydestination = dom1.test, d8slave.dom1.test, localhost.dom1.test, , localhost
mynetworks = 10.20.30.0/24 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128

Außerdem wichtig fürs Port-Listening (ist bei Debian per Default so eingestellt):

inet_interfaces = all

Die Syntax der eigenen Einstellungen prüfen:

$ postconf -n
alias_database = hash:/etc/aliases
alias_maps = hash:/etc/aliases
append_dot_mydomain = no
biff = no
config_directory = /etc/postfix
inet_interfaces = all
mailbox_command = procmail -a "$EXTENSION"
mailbox_size_limit = 0
mydestination = dom1.test, d8slave.dom1.test, localhost.dom1.test, , localhost
myhostname = d8slave.dom1.test
mynetworks = 10.20.30.0/24 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
myorigin = /etc/mailname
readme_directory = no
recipient_delimiter = +
relayhost =
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
smtpd_tls_cert_file = /etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file = /etc/ssl/private/ssl-cert-snakeoil.key
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtpd_use_tls = yes
$


$ lsof -i TCP -Pn | grep 25
named      613     bind   23u  IPv4  12588      0t0  TCP 127.0.0.1:953 (LISTEN)
named      613     bind   24u  IPv6  12589      0t0  TCP [::1]:953 (LISTEN)
sshd       615     root    3u  IPv4  12576      0t0  TCP *:22 (LISTEN)
sshd       615     root    4u  IPv6  12585      0t0  TCP *:22 (LISTEN)
sendmail- 5621     root    3u  IPv4  20881      0t0  TCP 127.0.0.1:25 (LISTEN)
$
$ killall sendmail-bin
sendmail-bin: Kein Prozess gefunden
$
$ pkill -9 sendmail
$ lsof -i TCP -Pn | grep 25
named     613     bind   23u  IPv4  12588      0t0  TCP 127.0.0.1:953 (LISTEN)
named     613     bind   24u  IPv6  12589      0t0  TCP [::1]:953 (LISTEN)
sshd      615     root    3u  IPv4  12576      0t0  TCP *:22 (LISTEN)
sshd      615     root    4u  IPv6  12585      0t0  TCP *:22 (LISTEN)
$
$
$ systemctl restart postfix
$
$ postfix status
postfix/postfix-script: the Postfix mail system is running: PID: 8386
$
$
$ echo 123 | mail -s "testmail 4" tux
$
$ mailq
Mail queue is empty
$
$ tail -5 /var/spool/mail/tux
Date: Tue, 29 Nov 2016 13:07:40 +0100 (CET)
From: root@d8slave.dom1.test (root)

123

$

Die nächsten Schritte für eine SMTP-Direktkommunikation

Mail-Daemons für SMTP mit zwei postfix-Installationen auf verschiedenen Rechnern

  • Server 1: dom1.test

  • Server 2: dom2.test

  • Bind9: Eine weiter Zone für dom2.test hinzufügen

  • MX-Records für beide MTAs anlegen

Szenario mit zwei MTAs

MTA 2 - d8mx2.dom2.test

Auf dem zweiten MTA (Debian 8, geklont aus d8slave, bind9 deinstalliert):

Die Datei ‚/etc/postfix/main.cf‘ wurde bereits für ‚dom2.test‘ angepasst:

$ grep -v ^# /etc/postfix/main.cf  | grep -v ^$ | grep --color  dom[1,2].test
myhostname = d8mx2.dom2.test
mydestination = dom2.test, d8mx2.dom2.test, localhost.dom2.test, ,  localhost
$

Insgesamt sieht die ‚main.cf‘ dann so aus:

smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
biff = no
append_dot_mydomain = no
readme_directory = no
smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
smtpd_use_tls=yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
myhostname = d8mx2.dom2.test
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination = dom2.test, d8mx2.dom2.test, localhost.dom2.test, , localhost
relayhost =
mynetworks = 10.20.30.0/24 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_command = procmail -a "$EXTENSION"
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all

DNS-Server um zone dom2.test erweitern

Wir editieren die Datei für die Zonendefinitionen: vi /etc/bind/named.conf.local

zone "dom2.test" {
        type master;
        notify yes;
        allow-transfer { key TRANSFER; localhost; };
        allow-update { key "rndc-key"; };
        file "/var/lib/bind/db.dom2.test";
};




$ vi /etc/bind/named.conf.local
$
$ cd /var/lib/bind/
root@d8master:/var/lib/bind#
root@d8master:/var/lib/bind# rndc freeze
root@d8master:/var/lib/bind#
root@d8master:/var/lib/bind# cp db.dom1.test db.dom2.test
root@d8master:/var/lib/bind#
root@d8master:/var/lib/bind# vi db.dom2.test


:1,$s/dom1/dom2/g
:1,$s/d8master/d8mx2/g

Hinzufügen der RRs für den MTA in Domäne 2

dom2.test.              MX 10   d8mx2.dom2.test.
d8mx2                   A       10.20.30.6

Nach dem Abspeichern kontrollieren wir kurz:

root@d8master:/var/lib/bind# grep dom2 db.dom2.test
dom2.test               IN SOA  d8mx2.dom2.test. root.d8mx2.dom2.test. (
                        NS      d8slave.dom2.test.
                        NS      d8mx2.dom2.test.
dom2.test.              MX 10   d8mx2.dom2.test.
$ORIGIN dom2.test.
root@d8master:/var/lib/bind#
root@d8master:/var/lib/bind#
root@d8master:/var/lib/bind# grep 10.20.30.6 db.dom2.test
d8mx2                   A       10.20.30.6
root@d8master:/var/lib/bind#

Hinzufügen des RRs für den MTA in Domäne 1

vi db.dom1.test

dom1.test.              MX  10  d8master.dom1.test.

Testings auf d8mx2

Nach dem Neustart von bind9 beginnen wir auf ‚d8mx2‘:

$ cat /etc/resolv.conf
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
nameserver 10.20.30.3
nameserver 10.20.30.4
search dom2.test
$


$ host -t mx dom2.test
dom2.test mail is handled by 10 d8mx2.dom2.test.
$
$ host -t mx dom1.test
dom1.test mail is handled by 10 d8master.dom1.test.
$


tail -f /var/log/mail.log

Eine erste Mail wird mit dem Fehler „…….“ blockiert… (Todo!)

$ echo OK?? | mail -s test1 tux@dom1.test
$
$ echo OK?? | mail -s selftest tux@dom2.test
$
$ telnet d8mx2.dom2.test. 25
Trying 10.20.30.6...
Connected to d8mx2.dom2.test.
Escape character is '^]'.
220 d8mx2.dom2.test ESMTP Postfix (Debian/GNU)
helo
501 Syntax: HELO hostname
mail from: billy@gates.ms
250 2.1.0 Ok
rcpt to: tux@dom1.test
250 2.1.5 Ok

500 5.5.2 Error: bad syntax
data
354 End data with <CR><LF>.<CR><LF>
Hallo,

Frühstück endlich....!
.
250 2.0.0 Ok: queued as 3FC15623
quit
221 2.0.0 Bye
Connection closed by foreign host.
$

Troubleshooting

https://www.cyberciti.biz/tips/howto-linux-unix-check-dns-file-errors.html

Wo steckt der hier der Fehler?

$ cat /var/lib/bind/db.dom1.test
$ORIGIN .
$TTL 604800     ; 1 week
dom1.test               IN SOA  d8master.dom1.test. root.d8master.dom1.test. (
                                73         ; serial
                                604800     ; refresh (1 week)
                                86400      ; retry (1 day)
                                2419200    ; expire (4 weeks)
                                604800     ; minimum (1 week)
                                )
                        NS      d8slave.dom1.test.
                        NS      d8master.dom1.test.
dom1.test.              MX  10  d8master.dom1.test.

d8master                A       10.20.30.3
d8slave                 A       10.20.30.4
d8squid                 A       10.20.30.5
$
$ named-checkzone dom1.test /var/lib/bind/db.dom1.test
/var/lib/bind/db.dom1.test:14: ignoring out-of-zone data (d8master)
/var/lib/bind/db.dom1.test:15: ignoring out-of-zone data (d8slave)
/var/lib/bind/db.dom1.test:16: ignoring out-of-zone data (d8squid)
zone dom1.test/IN: NS 'd8slave.dom1.test' has no address records (A or AAAA)
zone dom1.test/IN: NS 'd8master.dom1.test' has no address records (A or AAAA)
zone dom1.test/IN: not loaded due to errors.
$

Es liegt an dem einzelnen Punkt bei $ORIGIN ., was durch die Koppelung von DHCP -> DNS (DDNS) automatisch zustande kam.

Es muss allerdings $ORIGIN dom1.test. lauten. Alternativ kann der Eintrag auch ganz weggelassen werden.

211.2 Managing Local E-Mail Delivery

Ziel ist, Mails mit Hilfe von Sieve und Procmail ausfiltern zu können. Siehe dazu die Dokumentation E-Mails ausfiltern.

211.3 Managing Remote E-Mail Delivery

Ziel ist, verschiedene Mail Acccess Agents für POP3 und IMAP in unser Mailsystem einzubinden. Siehe dazu die Dokumentation Mailserver mit Postfix und Dovocot.

Topic 212: System Security

212.1 Configuring a router

Hardening

Empfehlenswert ist VOR dem ersten Ans-Netz-nehmen folgendes:

  • Updates von einem lokalen Mirror einspielen (ähnlich wie unter http://www.informationsarchiv.net/topics/65052/ beschrieben)

  • Nur die Anwendungen und Dienste installieren, die man benötigt

  • IDS-Systeme installieren (tripwire, aide, fail2ban, artillery, logwatch, snort)

Siehe dazu auch

Hinweise zum Härten:

  • Kein Journaling-Dateisystem verwenden

  • Deinstallieren von Software (z.B. apt-get remove rpcbind cups)

Danach sieht es nun so aus:

root@deb8:~# lsof -i | grep LISTEN
sshd      527        root    3u  IPv4  21545      0t0  TCP *:ssh (LISTEN)
sshd      527        root    4u  IPv6  21547      0t0  TCP *:ssh (LISTEN)
exim4     794 Debian-exim    4u  IPv4  12569      0t0  TCP localhost:smtp (LISTEN)
exim4     794 Debian-exim    5u  IPv6  12570      0t0  TCP localhost:smtp (LISTEN)
root@deb8:~#
root@deb8:~#

Firewalls unter Linux

Definition: Schutzeinrichtung gegen unerwünschte Datenpakete, die den Rechner selbst bzw. angeschlossene Netzwerke betreffen können.

Firewall-Architekturen

Siehe http://www.netzmafia.de/skripten/sicherheit/sicher4.html

  • Architektur mit Dualhomed-Host (ein Router als Firewall)

  • Architektur mit überwachtem Host (ein Router sowie ein Proxy-Server)

  • Architektur mit überwachtem Teilnetz (DMZ)

Firewall-Technologien

Siehe dazu http://docplayer.org/16366167-Einfuehrung-in-die-firewall-technologie.html

  • Paketfilter

  • Circuit Level Gateway

  • Application Level Gateway (Eine einfache From: transparenter Proxy mit iptables und squid)

Paketfilter-Technologie

Im einfachsten Falle gibt es kein dynamisches Reagieren auf Ereignisse, wie es auch erst später mit Stateful Packet Inspection (SPI) möglich geworden ist (Die Firma Checkpoint ist wohl noch Patentinhaber).

Gundsätzlich ist es immer eine gute Idee, zuerst einmal die Möglichkeiten des Kernels, was ‚/proc/sys/net/‘ betrifft, auszureizen, siehe http://www.thegeekstuff.com/2010/07/how-to-disable-ping-replies-in-linux/

Mit folgender Zeile werden eingehende ICMP-Pakete verworfen:

$ echo "1" > /proc/sys/net/ipv4/icmp_echo_ignore_all

Dieses lässt sich auch mit später auch mit ‚iptables‘ machen…

Zum den intern verwendeten Tabellen und darin befindlichen Ketten siehe http://www.pro-linux.de/artikel/2/761/2,grunds%C3%A4tzliche-funktionsweise.html

Eine grundlegend restriktive Arbeitsweise aktivieren:

$ iptables -P INPUT DROP
$ iptables -P FORWARD DROP
$ iptables -P OUTPUT DROP

Die lokale Kommunikation komplett erlauben:

$ iptables -A INPUT -i lo -j ACCEPT
$ iptables -A OUTPUT -o lo -j ACCEPT

Eingehend ssh zulassen:

$ iptables -A INPUT -i eth0 -p tcp --dport 22 -j ACCEPT
$ iptables -A OUTPUT -o eth0 -p tcp --sport 22 -j ACCEPT

Etwas sicherer wird es, wenn wir den Portbereich für die Antwortpakete ebenfalls vorgeben (‘–sport 1024:65553‘ == ‚–sport 1024:‘):

$ iptables -A INPUT -i eth0 -p tcp --dport 22 --sport 1024: -j ACCEPT
$ iptables -A OUTPUT -o eth0 -p tcp --sport 22 --dport 1024: -j ACCEPT

Zum Speichern der aktuellen Regeln wird ‚iptables-save‘ verwendet, zur späteren wiedereinlesen ‚iptables-restore‘:

root@deb8:~# iptables-save
# Generated by iptables-save v1.4.21 on Tue Dec  6 11:56:41 2016
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
-A INPUT -i lo -j ACCEPT
-A INPUT -i eth0 -p tcp -m tcp --dport 22 -j ACCEPT
-A OUTPUT -o lo -j ACCEPT
-A OUTPUT -o eth0 -p tcp -m tcp --sport 22 -j ACCEPT
COMMIT
# Completed on Tue Dec  6 11:56:41 2016
root@deb8:~#

AUFGABE: Eingehend ping erlauben, aber nur für die Nachrichten-Typen 1 und 8!

LÖSUNG:

$ iptables -A INPUT -i eth0 -p icmp --icmp-type 0 -j ACCEPT
$ iptables -A OUTPUT -o eth0 -p icmp --icmp-type 8 -j ACCEPT

Siehe auch:

Isoliertes Teilnetz nach dem Vorbild einer DMZ

Siehe dazu die Netzwerktopolgie unter http://pemmann.de/cc/Doc/dmz.png sowie die beiden folgenden iptables-Skripte:

Ausblick ip6fables / nftables

IPtabels für IPv6

Ausblick auf das neue Linux-Firewallbackend ‚ntfables‘

Softwarelösungen, die als „Reation System“ iptables-Regeln erzeuegn:

212.2 Securing FTP servers

Experimente mit chroot

ZIEL: Einrichtung eines Change-Root Jails

Eine chroot-Jail per Hand aufzusetzen, ist heutzutage nicht mehr ganz so einfach, weil die Daemons selbst schon ein eigenes mitbringen und ein Linken gegen externe Binaries nicht mehr erwünscht ist. Daher scheitern die folgenden Experimente auch, zeigen aber das grundsätzliche Verfahren sehr gut auf:

Die Lösung der Aufgabenstellung (aus Braindump):

$ cp /lib/x86_64-linux-gnu/{libwrap.so.0,libpam.so.0,libcap.so.2,libnsl.so.1,libaudit.so.1,libattr.so.1} /home/sam/jail/lib/x86_64-linux-gnu/
$ mkdir /home/sam/jail/usr/lib/
$ cp /usr/lib/x86_64-linux-gnu/{libssl.so.1.0.0,libcrypto.so.1.0.0} /home/sam/jail/usr/lib/

Ohne Konfigurationsdatei gelingt das Starten des Daemons nicht: „500 OOPS: vsftpd: not configured for standalone, must be started from inetd“:

$ mkdir /home/sam/jail/etc
$ cat > /home/sam/jail/etc/vsftpd.conf <<EOF
# http://www.sigerr.org/linux/setup-vsftpd-custom-multiple-directories-users-accounts-ubuntu-step-by-step/
listen=YES
anonymous_enable=NO
local_enable=YES
write_enable=YES
local_umask=022
nopriv_user=vsftpd
virtual_use_local_privs=YES
guest_enable=YES
user_sub_token=$USER
local_root=/var/www/$USER
chroot_local_user=YES
hide_ids=YES
guest_username=vsftpd
EOF

$ /usr/sbin/chroot /home/sam/jail /usr/sbin/vsftpd

^C
$

Was zu zeigen war: Der FTP Daemon läuft…

Er ist zwar noch nicht benutzbar („cannot locate user specified in ‚guest_username‘:vsftpd“ bei einem ‚ftp localhost‘), ist aber als Daemon in der chroot-Umgebung aktiv und hat dort seine Konfigurationsdatei selbständig gefunden.

Ausflug in die verkehrte Welt:

$ mv /home/sam/jail/lib/x86_64-linux-gnu/libc.so.6 /tmp
$
$ /usr/sbin/chroot /home/sam/jail /usr/sbin/vsftpd
/usr/sbin/vsftpd: error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory
$
$ ln -s /lib/x86_64-linux-gnu/libc.so.6 /home/sam/jail/lib/x86_64-linux-gnu/libc.so.6
$
$ /usr/sbin/chroot /home/sam/jail /usr/sbin/vsftpd
/usr/sbin/vsftpd: error while loading shared libraries: libc.so.6: cannot open shared object file: Error 40
$

Wiederherstellen des korrekten Zustands:

$ rm /home/sam/jail/lib/x86_64-linux-gnu/libc.so.6
$ cp /lib/x86_64-linux-gnu/libc.so.6 /home/sam/jail/lib/x86_64-linux-gnu/
$
$ /usr/sbin/chroot /home/sam/jail /usr/sbin/vsftpd

^C
$

Alles klar…?

Einrichten von chroot mit vsftpd

ZIEL: Praktisches Zurverfügungstellen eines FTP-Servers mit chroot-Verzeichnis

=> AUF DEM SERVER ‚dns2‘ (in DMZ)

$ vi /etc/vsftpd.conf

AKTIVIEREN VON:

write_enable=YE
chroot_local_user=YES

Im Endeffekt sieht die Konfiguration folgendermaßen aus (grep -v ^# /etc/vsftpd.conf):

listen=NO
listen_ipv6=YES
anonymous_enable=NO
local_enable=YES
write_enable=YE
dirmessage_enable=YES
use_localtime=YES
xferlog_enable=YES
connect_from_port_20=YES
chroot_local_user=YES
secure_chroot_dir=/var/run/vsftpd/empty
pam_service_name=vsftpd
rsa_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
rsa_private_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
ssl_enable=NO

Nach einem Einlesen der geänderten Konfiguration mit systemctl restart vsftpd testen wir gleich mit dem lokalen Host als Client:

root@dns2:~# ftp localhost
Connected to localhost.
220 (vsFTPd 3.0.2)
Name (localhost:tux): tux
331 Please specify the password.
Password:
500 OOPS: vsftpd: refusing to run with writable root inside chroot()
Login failed.
ftp>

Wo liegt das PROBLEM? Es handelt sich wohl tatsächlich eher um ein Feature als um einen Bug. Grund ist, dass das Wurzelverzeichnis ‚/home/tux‘ jetzt kein Schreibrecht mehr haben darf! Wir beheben es auf folgende Weise:

$ chmod -w /home/tux
$ mkdir /home/tux/Writing
$ chown tux: /home/tux/Writing

Nun können auf dem Server leider nur noch unter ‚~/Writing‘ Daten schreibend abgelegt werden:

root@dns2:~# ftp localhost
Connected to localhost.
220 (vsFTPd 3.0.2)
Name (localhost:tux): tux
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp>
ftp> cd Writing
250 Directory successfully changed.
ftp>
ftp> mkdir ABC
257 "/Writing/ABC" created
ftp>
ftp> ls
200 EPRT command successful. Consider using EPSV.
150 Here comes the directory listing.
drwx------    2 1000     1000         4096 Mar 17 13:12 ABC
226 Directory send OK.
ftp>
ftp> by
221 Goodbye.
root@dns2:~#

Es gibt für dieses Problem Patches, durch die eine Einstellung allow_writeable_chroot=YES möglich wird, was wohl aber nicht alle Distributionen aus Sicherheitsgründen für gut heißen.

Pure-FTPD

Diese eben geschilderten Probleme vom vsftp-Daemon sind natürlich kein Zustand, wenn es sich um die Heimatverzeichisse von realen Benutzern handelt. Dann empfiehlt es sich, einen Blick auf den pure-ftpd zu werfen:

212.3 Secure shell (SSH)

ZIEL: ssh gegen Brute-Force Angriffe einsetzen und härten

SSH-Tunnel für HTTP

ZIEL: Sambas swat-Konfigurationswerkzeug über einen sicheren SSH-Tunnel absichern

Auf dem ‚zielserver‘ läuft Samba 3.0 mit aktiviertem Swat-Frontend:

  1. Als normaler Benutzer von der Workstation aus einen sicheren Tunnel aufbauen:

$ ssh -L 9901:localhost:901 zielserver
  1. Im Web-Browser von der Workstation aus die verschlüsselte Verbindung zum swat-Frontend herstellen:

Prinzipiell lässt sich auf diese Art lässt sich jede HTTP-Kommunikation absichern, so könnte man z.B. aus dem Verzeichnis ~/public_html heraus mit

$ python -m SimpleHTTPServer

einen Webserver starten, der am Port 8000 lauscht. Der Clientzugriff kann dann via Tunnel geschehen:

$ ssh -L 8888:localhost:8000 zielserver
$ wget http://localhost:8888/my-important-file.txt

Reverse SSH-Tunnel

Diese Art von Tunnel benötigt man, wenn andersherum als üblich der Server zum Client eine Verbindung z.B. für die Fernadministration aufbauen möchte. Dafür benötigt man die ssh-Option: ‚-R‘.

Weiterführende Dokumente:

ssh-Hostschlüssel

Fingerabdruck von Host-Keys ausgeben

$ ssh-keygen -l -f /etc/ssh/ssh_host_rsa_key.pub
2048 30:1b:5b:5a:9e:99:a7:5c:8a:9f:6b:41:e9:7e:d3:9c ssh_host_rsa_key.pub (RSA)

Neue Schlüsselpaare erzeugen, hier nur für RSA:

$ cd /etc/ssh
$ cp ssh_host_rsa_key* /root
$
$ ssh-keygen -t rsa -b 4096 -N "" -f ssh_host_rsa_key.pub
Generating public/private rsa key pair.
ssh_host_rsa_key.pub already exists.
Overwrite (y/n)? y
Your identification has been saved in ssh_host_rsa_key.pub.
Your public key has been saved in ssh_host_rsa_key.pub.pub.
The key fingerprint is:
41:a6:be:ea:f0:0b:aa:17:b3:7b:4e:ae:25:4e:84:6b root@d8master
The key's randomart image is:
+---[RSA 4096]----+
|        o        |
|       +         |
|      . .        |
| .   .   .       |
|. .   . S        |
| oo    .         |
|.E=+o .          |
|.+oO..           |
|+.+*B.           |
+-----------------+
$
$ systemctl restart ssh
$
$ ssh-keygen -l -f ssh_host_rsa_key.pub
4096 41:a6:be:ea:f0:0b:aa:17:b3:7b:4e:ae:25:4e:84:6b ssh_host_rsa_key.pub.pub (RSA)

Clientseitig eine bestimmte Verschlüsselung anfordern

Soll z.B. nicht ECDSA sondern RSA verwendet werden, schreibt man:

$ ssh  -o  HostKeyAlgorithms=ssh-rsa-cert-v01@openssh.com,ssh-dss-cert-v01@openssh.com,ssh-rsa-cert-v00@openssh.com,ssh-dss-cert-v00@openssh.com,ssh-rsa,ssh-dss  tux@localhost

Bei neueren ssh-Implementationen lässt sich dies kürzer mit -o HostKeyAlgorithms=ssh-rsa erreichen.

Serverseitig nur bestimmte Schlüssel anbieten

Dazu müssen wir nur diejenigen auskommentieren, nicht mehr an Clients ausgeliefert werden sollen: vi /etc/ssh/sshd_config

# What ports, IPs and protocols we listen for
Port 22
# Use these options to restrict which interfaces/protocols sshd will bind to
#ListenAddress ::
#ListenAddress 0.0.0.0
Protocol 2
# HostKeys for protocol version 2
HostKey /etc/ssh/ssh_host_rsa_key
##HostKey /etc/ssh/ssh_host_dsa_key
##HostKey /etc/ssh/ssh_host_ecdsa_key
##HostKey /etc/ssh/ssh_host_ed25519_key

Nun müssen wir noch einmal die Konfiguration neu einlesen:

$ systemctl restart sshd

212.4 Security tasks

fail2ban - ein Intrusion Prevention System (IPS)

ZIEL: Einbruchsversuche anhand von Logeinträgen erkennen und abwehren

Literatur:

Die Installation erfolgt zuerst auf der inneren Firewall:

$ apt-get install fail2ban
$ cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

Die Konfigurationsdatei ist dann die Datei ‚/etc/fail2ban/jail.local‘.

Inbetriebnahme mit Voreinstellungen

root@d8fw2:/etc/fail2ban# grep 'enabled'  /etc/fail2ban/jail.local | grep true
# enabled = true
enabled  = true
root@d8fw2:/etc/fail2ban#
root@d8fw2:/etc/fail2ban# pgrep -a fail
1259 /usr/bin/python /usr/bin/fail2ban-server -b -s /var/run/fail2ban/fail2ban.sock -p /var/run/fail2ban/fail2ban.pid
root@d8fw2:/etc/fail2ban#
root@d8fw2:/etc/fail2ban#
root@d8fw2:/etc/fail2ban# systemctl restart fail2ban
root@d8fw2:/etc/fail2ban#
root@d8fw2:/etc/fail2ban# ls -l /var/log/fail2ban.log
-rw-r----- 1 root adm 1743 Dez 12 10:58 /var/log/fail2ban.log
root@d8fw2:/etc/fail2ban#
root@d8fw2:/etc/fail2ban# tail -f /var/log/fail2ban.log
2016-12-12 10:58:41,558 fail2ban.server [1259]: INFO    Exiting Fail2ban
2016-12-12 10:58:42,009 fail2ban.server [1373]: INFO    Changed logging target to /var/log/fail2ban.log for Fail2ban v0.8.13
2016-12-12 10:58:42,010 fail2ban.jail   [1373]: INFO    Creating new jail 'ssh'
2016-12-12 10:58:42,023 fail2ban.jail   [1373]: INFO    Jail 'ssh' uses pyinotify
2016-12-12 10:58:42,035 fail2ban.jail   [1373]: INFO    Initiated 'pyinotify' backend
2016-12-12 10:58:42,036 fail2ban.filter [1373]: INFO    Added logfile = /var/log/auth.log
2016-12-12 10:58:42,037 fail2ban.filter [1373]: INFO    Set maxRetry = 6
2016-12-12 10:58:42,038 fail2ban.filter [1373]: INFO    Set findtime = 600
2016-12-12 10:58:42,038 fail2ban.actions[1373]: INFO    Set banTime = 600
2016-12-12 10:58:42,062 fail2ban.jail   [1373]: INFO    Jail 'ssh' started


--->> Zwischenzeitlich versuchen sich Personen von den Maschinen
10.1.1.2 sowie 10.20.30.5 mit falschem Benutzername/Passwort einzuloggen <<---

2016-12-12 11:01:52,351 fail2ban.actions[1373]: WARNING [ssh] Ban 10.1.1.2
2016-12-12 11:04:59,651 fail2ban.actions[1373]: WARNING [ssh] Ban 10.20.30.5

Zusätzlich zu den eigenen Firewallregeln schreibt ‚fail2ban‘ die beiden letzteren Zeilen:

root@d8fw2:/etc/fail2ban# iptables -vnL
Chain INPUT (policy DROP 2 packets, 484 bytes)
pkts bytes target     prot opt in     out     source               destination
253 25016 fail2ban-ssh  tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            multiport dports 22
    0     0 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0
1934 1243K ACCEPT     all  --  eth0   *       0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
32  5258 ACCEPT     all  --  eth1   *       0.0.0.0/0            0.0.0.0/0
    2   120 ACCEPT     tcp  --  eth0   *       0.0.0.0/0            0.0.0.0/0            tcp dpt:22
24  5808 LOG        all  --  *      *       0.0.0.0/0            0.0.0.0/0            limit: avg 5/min burst 7 LOG flags 0 level 6 prefix "iptables: "

Chain FORWARD (policy ACCEPT 1 packets, 76 bytes)
pkts bytes target     prot opt in     out     source               destination
5077  506K ACCEPT     all  --  eth1   *       0.0.0.0/0            0.0.0.0/0

Chain OUTPUT (policy DROP 0 packets, 0 bytes)
pkts bytes target     prot opt in     out     source               destination
    0     0 ACCEPT     all  --  *      lo      0.0.0.0/0            0.0.0.0/0
1337  241K ACCEPT     all  --  *      eth0    0.0.0.0/0            0.0.0.0/0            state NEW,RELATED,ESTABLISHED
63  7650 ACCEPT     all  --  *      eth1    0.0.0.0/0            0.0.0.0/0
    0     0 LOG        all  --  *      *       0.0.0.0/0            0.0.0.0/0            LOG flags 0 level 4 prefix "iptables-out: "

Chain fail2ban-ssh (1 references)
pkts bytes target     prot opt in     out     source               destination
    0     0 REJECT     all  --  *      *       10.20.30.5           0.0.0.0/0            reject-with icmp-port-unreachable
24  1992 REJECT     all  --  *      *       10.1.1.2             0.0.0.0/0            reject-with icmp-port-unreachable
229 23024 RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0
root@d8fw2:/etc/fail2ban#



root@d8fw2:/etc/fail2ban# fail2ban-client -v status ssh
INFO   Using socket file /var/run/fail2ban/fail2ban.sock
Status for the jail: ssh
|- filter
|  |- File list:        /var/log/auth.log
|  |- Currently failed: 1
|  `- Total failed:     12
`- action
|- Currently banned: 0
|  `- IP list:
`- Total banned:     1
root@d8fw2:/etc/fail2ban# fail2ban-client -v status ssh
INFO   Using socket file /var/run/fail2ban/fail2ban.sock
Status for the jail: ssh
|- filter
|  |- File list:        /var/log/auth.log
|  |- Currently failed: 0
|  `- Total failed:     13
`- action
|- Currently banned: 1
|  `- IP list:       10.20.30.5
`- Total banned:     2
root@d8fw2:/etc/fail2ban#

Manuelles Aufheben der Verbannung:

root@d8fw2:/etc/fail2ban# fail2ban-client set ssh unbanip 10.20.30.5
10.20.30.5
root@d8fw2:/etc/fail2ban#
root@d8fw2:/etc/fail2ban#
root@d8fw2:/etc/fail2ban#
root@d8fw2:/etc/fail2ban# fail2ban-client -v status ssh
INFO   Using socket file /var/run/fail2ban/fail2ban.sock
Status for the jail: ssh
|- filter
|  |- File list:        /var/log/auth.log
|  |- Currently failed: 0
|  `- Total failed:     13
`- action
|- Currently banned: 0
|  `- IP list:
`- Total banned:     2
root@d8fw2:/etc/fail2ban#

Weiterführende Links:

212.5 OpenVPN

Siehe dazu unter das Dokument VPN mit SSL: OpenVPN.