JailServer mit FreeBSD 10.1: Unterschied zwischen den Versionen

Aus UUGRN
K (→‎Grundkonfiguration des Servers (afterboot): Namen, IP-Adressen, Domains)
Zeile 281: Zeile 281:
Alle in den folgenden Beispielen verwendeten IP-Adressen und Hostnamen ensprechen einem real existierenden Server, dessen Aufbau hier beschrieben wird.
Alle in den folgenden Beispielen verwendeten IP-Adressen und Hostnamen ensprechen einem real existierenden Server, dessen Aufbau hier beschrieben wird.


{! Bezeichnung
{|
! Bezeichnung
  ! Wert
  ! Wert
  ! Bemerkung
  ! Bemerkung
  |-
  |-
  | Hostname des Servers || srv01.sigsys.de || ||
  ! Hostname des Servers  
| srv01.sigsys.de
|
|-
! Domain(s)
| sigsys.de und sigsys.lan
| analog zu den IP-Netzen
|-
! IPv4
| 164.177.170.96/29
| externe IP-Adressen auf em0
|-
! IPv4
| 10.253.2.0/24
| interne IP-Adressen auf "lan" (=lo1)
|-
! IPv6
| 2a03:2500:1:8::/64
| externe IPv6-Adressen auf em0
|-
  |}
  |}





Version vom 18. Februar 2015, 04:34 Uhr

Dieser Artikel beschreibt den Aufbau eines FreeBSD JailServers basierend auf FreeBSD 10.1.

Anforderungen und Rahmenbedingungen

  • Hardware besteht aus einer 64bittigen Architektur, zB amd64
  • Es soll ausschließlich ZFS genutzt werden. Der Storage besteht mindestens aus 2 Massenspeichern (Festplatten), optional zusätzlich 2 SSDs für swap, log und cache
  • Es gibt ein IPv4-Netz mit mindestens /29
  • Es gibt echtes IPv6, mindestens ein /64
  • Optional internes Interface (LAN), ersatzweise wird ein Loopback-Interface verwendet, hier gibt es ein nicht geroutetes RfC1918 Netzwerk mit /24
  • die externe Sichbarkeit von Services soll auf das absolute Minimum reduziert werden, rein intern genutzte Services (zB Datenbanken, Syslog, …) sollen ausschießlich im LAN zugreifbar sein
  • Alle maßgeblichen Services sollen in individuellen Jails laufen.
  • Folgende Services sollten jeweils ein eigenes extern erreichbares Jail erhalten:
    • mail (aka mail.sigsys.de, sigsys_mail, zroot/jails/sigsys/mail/, ".2")
    • dns (aka dns.sigsys.de, sigsys_dns, zroot/jails/sigsys/dns/, ".3")
    • proxy (aka proxy.sigsys.de, sigsys_proxy, zroot/jails/sigsys/proxy/, ".4")
    • shell (aka shell.sigsys.de, sigsys_shell, zroot/jails/sigsys/shell/, ".5")
  • Webapplikationen sollen in Jails mit ausschließlich RfC1918-IP ("lan") betrieben werden und ausschließlich mittels Proxy und Reverse-Proxy mit der Außenwelt kommunizieren. Das soll unkontrolliertes nach Hause telefonieren unterbinden und kann bei Bedarf über den verfügbaren ProxyServer (squid auf proxy.sigsys.lan:3128) abgewickelt werden (zB Umgebungsvariablen setzen für libcurl sofern entsprechend verwendet).
  • Mailrouting findet in einem dedizierten Jail statt. Hier erfolgt auch der Zurgriff auf Mailboxen.
  • Es werden 2 DNS-Server betrieben: Einer direkt auf dem Host für allgemeine Verwendung, zB rekursive Abfragen, einer ausschließlich für Domainhosting und als Hidden Primary (eigenes Jail dns.sigsys.de)
  • SSH-Zugänge (SSH Jumphost etc) und alles, was normale Benutzer auf dem Server tun können soll im shell-Jail stattfinden.
  • Alle Jails (mit ausnahme des shell-Jails) sind ausschließlich über das "lan"-Interface per SSH erreichbar (via shell.sigsys.de /shell.sigsys.lan als Jumphost)
  • SSH-Zugriff auf den Server (srv01.sigsys.de) direkt sollte wenn möglich gar nicht oder nur stark eingeschränkt ermöglicht werden, normale Benutzeraccounts soll es auf dem Server direkt ohnehin nicht geben.
  • Alle Services auch in den Jails werden durch konservative Konfiguration auf das erforerliche Minimum reduziert. Eine Firewall ist in diesem Setup somit nicht erforderlich (aber generell möglich, wenn auch sehr komplexx aufgrund der Kommunikationsmatrix zwischen den ganzen Jails).
  • Kommunikation zwischen internen Services erfolgt ausschließlich über das "lan"-Interface.

Hardware

In diesem Setup wird ein Server mit Intel(R) Core(TM)2 Duo CPU E8400 @ 3.00GHz mit 16GB RAM betrieben.

Über ein 4fach Wechselrahmen für 2.5" Platten werden insgesamt 2 Stück 1TB HDD (geeignet für 24/7 Betrieb) und zusätzlich 2 SSDs mit jeweils 120GB eingebaut, wobei die HDDs an einem SATA2 Controller (3Gbps) angeschlossen sind, die beiden SSDs jeweils an einem SATA3 Port (6Gbps).

FreeBSD Setup auf dem JailServer

Basisinstallation

Auf dem System wird über den Installer von FreeBSD 10.1 eine normale Installation ausgeführt, keine manuellen Hacks erforderlich. Das Storage-Setup beinhaltet initial nur die beiden mechanischen Festplatten als ZFS mirror. Der Installer kümmert sich darum, dass ein entsprechender zpool ("zroot") angelegt wird und alles so eingerichtet wird, dass man später direkt davon booten kann. Partitioniert wird ausschließlich mit GPT.

Die beiden SSDs werden dann später manuell aufgesetzt und hinzugefügt.

Nach Abschluss der Installation und dem reboot sollte der Server per SSH über das Internet erreichbar sein.

Storage Setup erweitern: SSDs einbinden

Nach der Installation durch bsdinstall mit ZFS auf zwei 1TB-Festplatten (Western Digital Red / WDC WD10JFCX-68N6GN0, als /dev/ada3 und /dev/ada4) existiert ein zpool namens "zroot", der etwa so aussieht:

# zpool status
  pool: zroot
 state: ONLINE
  scan: scrub repaired 0 in 0h0m with 0 errors on Sun Feb 15 03:48:59 2015
config:

        NAME                               STATE     READ WRITE CKSUM
        zroot                              ONLINE       0     0     0
          mirror-0                         ONLINE       0     0     0
            gpt/zfs0                       ONLINE       0     0     0
            diskid/DISK-WD-WXK1E848AH8Pp3  ONLINE       0     0     0

errors: No known data errors

Aus Performancegründen sollen sowohl Lese als auch Schreibzugriffe über SSDs (Flash-Speicher) beschleunigt werden. Dazu existieren 2 verschiedene SSDs mit jeweils 120GB Nutzapazität:

  • Corsair Force GT / SandForce Driven SSDs
  • SPCC Solid State Disk

SSDs mit GPT partitionieren

Die beiden SSDs sind als "ada0" und "ada1" im System eingebunden. Mittels "gpart" wird folgendes GPT-Setup erzeugt:

  • Alle Offsets sind 1m-Aligned (4k-Alignment wäre auch ausreichend, 1m ist je nach Speicherorganisation der SSDs ggf. hilfreich)
  • 512k für den BootLoader
  • 16GB für swap (wird via /etc/fstab eingetragen, evtl vorhandener swap auf HDDs deaktivieren)
  • 32GB für ZIL (ZFS Intent Log) oder kurz log
  • 64GB für L2ARC (ZFS Cache) oder kurz cache.
=>       34  234441581  ada0  GPT  (112G)
         34          6        - free -  (3.0K)
         40       1024     1  freebsd-boot  (512K)
       1064        984        - free -  (492K)
       2048   33554432     2  freebsd-swap  (16G)
   33556480   67108864     3  freebsd-zfs  (32G)
  100665344  133775360     4  freebsd-zfs  (64G)
  234440704        911        - free -  (456K)

=>       34  234441581  ada1  GPT  (112G)
         34          6        - free -  (3.0K)
         40       1024     1  freebsd-boot  (512K)
       1064        984        - free -  (492K)
       2048   33554432     2  freebsd-swap  (16G)
   33556480   67108864     3  freebsd-zfs  (32G)
  100665344  133775360     4  freebsd-zfs  (64G)
  234440704        911        - free -  (456K)

Die ada2 und ada3 sind die Festplatten, die von bsdinstall eingerichtet wurden, hier nur der Vollständigkeit halber gezeigt:

=>        34  1953525101  diskid/DISK-WD-WXK1E848AH8P  GPT  (932G)
          34           6                               - free -  (3.0K)
          40        1024                            1  freebsd-boot  (512K)
        1064     8388608                            2  freebsd-swap  (4.0G)
     8389672  1945135456                            3  freebsd-zfs  (928G)
  1953525128           7                               - free -  (3.5K)

=>        34  1953525101  ada3  GPT  (932G)
          34           6        - free -  (3.0K)
          40        1024     1  freebsd-boot  (512K)
        1064     8388608     2  freebsd-swap  (4.0G)
     8389672  1945135456     3  freebsd-zfs  (928G)
  1953525128           7        - free -  (3.5K)

Sinngemäß ist für /dev/ada0 und /dev/ada1 jeweils folgendes auszuführen: (abgekupfert unter auf blog.ociru.net und auch sehr gut erklärt in FreeBSD Mastery: Storage Essentials, ebook von Michael W Lucas)

# gpart destroy ada0
# gpart destroy ada1
# gpart create -s gpt ada0
# gpart create -s gpt ada1
# gpart add -t freebsd-boot -a 1m -s 512k -l ssdboot0 ada0
# gpart add -t freebsd-boot -a 1m -s 512k -l ssdboot1 ada1
# gpart add -t freebsd-swap -a 1m -s 16G -l ssdswap0 ada0
# gpart add -t freebsd-swap -a 1m -s 16G -l ssdswap1 ada1
# gpart add -t freebsd-zfs -a 1m -s 32G -l log0 ada0
# gpart add -t freebsd-zfs -a 1m -s 32G -l log1 ada1
# gpart add -t freebsd-zfs -a 1m -s 64G -l cache0 ada0
# gpart add -t freebsd-zfs -a 1m -s 64G -l cache1 ada1

GPT-ZFS Bootloader

Auf die jeweils erste Partition (adaXp1) soll noch der aktuelle Bootloader installiert werden. Je nachdem von welchen Disks der Server vom BIOS her nachher bootet sollte in jedem Fall ein gültiger Bootloader gefunden werden, der in der Lage ist das ZFS auf den verfügbaren GPT-Partitionen zu finden.

# gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ada0
# gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ada1

Nach Major-RELEASE Upgrades von FreeBSD, bei denen auch ZFS signifikant erneuert wurde, sollte dieser Vorgang für alle verfügbaren Boot-Devices wiederholt werden, also auch ada2 und ada3 sofern vorhanden.

Die jeweils zum RELEASE gehörende Version von /boot/gptzfsboot sollte ausgerollt werden. Das gilt insbesondere bei Uprgade von ZFS Version <28 (FreeBSD 7.x, 8.x)!

/boot/pmbr wird als protective MBR bezeichnet und erzeugt einen Pseudo-MBR, der verindern soll, dass ein nicht GPT fähiges OS (zB WinXP) die Platte irrtümlich als "Frei" erkennt und anfängt dinge damit zu tun.

Mehr dazu unter RootOnZFS/GPTZFSBoot im FreeBSD-Wiki.

GPT-Partitionen auf SSD als ZFS log und cache einbinden

Die nun so geschaffenen GPT-Devices können nun als log und cache dem bereits existierenden zpool (zroot) zugefügt werden. Dabei sei deutlich zu erwähnen:

  • SSDs tendieren dazu kaputt zugehen. Das ist im Falle von ZFS besonders für das ZIL schädlich. Entsprechend wird ZIL hier als mirror betrieben. Aufgrund der Verschiedenen SSDs ist die Wahrscheinlichkeit eines gleichzeitigen Ausfalls relativ gering. Sollte eine SSD kaputt gehen, sollte bis zum Ersatz zumindest das log-Device ("ZIL") aus dem zpool auskonfiguriert werden!
  • cache ("L2ARC") kann nicht ausfallsicher gebaut werden. Das ist auch nicht erforderlich, da Lesefehler im Cache automatisch zu einem Lesevorgang auf der Festplatte führt. Ein physisch beschädigtes cache-device sollte allerdings auskonfiguriert werden.

Der folgende Befehl fügt dem bestehenden "zroot" nun log und cache aus den oben erzeugten GPT-Devices hinzu:

# zpool add zroot log mirror /dev/gpt/log0 /dev/gpt/log1 cache /dev/gpt/cache0 /dev/gpt/cache1


Der zpool sieht danach so aus:

# zpool status
  pool: zroot
 state: ONLINE
  scan: scrub repaired 0 in 0h0m with 0 errors on Sun Feb 15 03:48:59 2015
config:

        NAME                               STATE     READ WRITE CKSUM
        zroot                              ONLINE       0     0     0
          mirror-0                         ONLINE       0     0     0
            gpt/zfs0                       ONLINE       0     0     0
            diskid/DISK-WD-WXK1E848AH8Pp3  ONLINE       0     0     0
        logs
          mirror-1                         ONLINE       0     0     0
            gpt/log0                       ONLINE       0     0     0
            gpt/log1                       ONLINE       0     0     0
        cache
          gpt/cache0                       ONLINE       0     0     0
          gpt/cache1                       ONLINE       0     0     0

errors: No known data errors

swap-Partitionen von HDD auf SSD umbiegen

Von bsdinstall wurde bereits swap-Speicher auf den Festplatten eingerichtet. Dieser soll entfallen zugunsten von swap-Partitionen auf SSDs. Auch wenn die oben angelegten 2x 16GB freebsd-swap üppig erscheinen (ergibt immerhin 32Gb swap), der Platz ist auf den SSDs ohnehin günstig und schnell vorhanden.

Abgesehen von klassischem "paging" kann der in Summe nun 32GB große swapspace verwendet werden für

  • /tmp als swap basierte RAM-Disk (swap backed memory disk, md)
  • crash dump Partition (dumpon=AUTO)


1. Zunächst prüfen, dass genug RAM frei ist und swap nicht anderweitig genutzt wird, dann swap deaktivieren:

# swapoff -a

2. Anschließend in /etc/fstab sinngemäß folgnde Änderungen (hier dargestellt als unified diff) durchführen:

--- /etc/fstab.orig     2015-02-18 02:06:47.466768456 +0100
+++ /etc/fstab  2015-02-15 03:25:40.010168828 +0100
@@ -1,4 +1,8 @@
 # Device               Mountpoint      FStype  Options         Dump    Pass#
-/dev/ada0p2            none    swap    sw              0       0
-/dev/ada1p2            none    swap    sw              0       0
+#/dev/ada0p2           none    swap    sw              0       0
+#/dev/ada1p2           none    swap    sw              0       0
+
+/dev/gpt/ssdswap0      none    swap    sw      0       0
+/dev/gpt/ssdswap1      none    swap    sw      0       0
+
 fdesc                  /dev/fd         fdescfs rw 0 0

Die GPT-Labels "ssdswap0" und "ssdswap1" wurden zuvor mittels "gpart add … -t freebsd-swap -l ssdswap0 …" erzeugt. Man könnte hier generell auch /dev/ada0p1 und /dev/ada0p2 verwenden, was aber bei Wegfall von einzelnen Devices oder Neu/Umverkabelung von SATA-Ports zu Problemen führt (andere Numerierung! der ada-Devices).

3. swap nun wieder aktivieren:

# swapon -a
mögliche Nutzung von swap für /tmp

Verantwortlich für die Erzeugung einer "swap-based memory disk für /tmp" ist das Startscript /etc/rc.d/tmp, welches wie folgt parametrisiert werden kann:

Aus rc.conf(5)
     tmpmfs      Controls the creation of a /tmp memory file system.  Always
                 happens if set to ``YES'' and never happens if set to ``NO''.
                 If set to anything else, a memory file system is created if
                 /tmp is not writable.

     tmpsize     Controls the size of a created /tmp memory file system.

     tmpmfs_flags
                 Extra options passed to the mdmfs(8) utility when the memory
                 file system for /tmp is created.  The default is ``-S'',
                 which inhibits the use of softupdates on /tmp so that file
                 system space is freed without delay after file truncation or
                 deletion.  See mdmfs(8) for other options you can use in
                 tmpmfs_flags.
aus mdmfs(8)
     By default, mdmfs creates a swap-based (MD_SWAP) disk with soft-updates
     enabled and mounts it on mount-point.


Generell könnte über diesen Mechanismus auch /tmp-Speicher für die jails angeboten werden, der beim Start eines Jails (vorab) automatisch bereitgestellt wird. Nach der Änderung der Storages ist ein Neustart vom Server hilfreich, bevor man anfängt viel Arbeit in das Setup zu investieren!

swap space für crash dumps

Der FreeBSD-Kernel kann im Falle einer Kernelpanic seinen gesamten Speicher oder auszüge daraus für eine spätere Analyse auf ein "dump-device" schreiben (sofern die Kernel-Panic nicht durch das Storage-Subsystem ausgelöst wurde).

Dies kann eine dedizierte crashdump-Partition sein, üblicherweise wird hier allerdings eine (ausreichend große) swap-Partition verwendet. Nach dem dann folgenden Reboot wird dieser crash-dump vor der Initialisierung von Swap automatisch gefunden und nach /var/crash kopiert, wo er post mortem analysiert werden kann.

Da der Server 16GB RAM hat sind die (beiden) SWAP-Partitionen ebenfalls 16GB groß, aber nicht aufgrund der "SWAP = 2xRAM"-Regel sondern eben für die crash-dumps.

aus rc.conf(5)
     dumpdev     (str) Indicates the device (usually a swap partition) to
                 which a crash dump should be written in the event of a system
                 crash.  If the value of this variable is ``AUTO'', the first
                 suitable swap device listed in /etc/fstab will be used as
                 dump device.  Otherwise, the value of this variable is passed
                 as the argument to dumpon(8).  To disable crash dumps, set
                 this variable to ``NO''.

     dumpdir     (str) When the system reboots after a crash and a crash dump
                 is found on the device specified by the dumpdev variable,
                 savecore(8) will save that crash dump and a copy of the ker-
                 nel to the directory specified by the dumpdir variable.  The
                 default value is /var/crash.  Set to ``NO'' to not run
                 savecore(8) at boot time when dumpdir is set.

Grundkonfiguration des Servers (afterboot)

Namen, IP-Adressen, Domains

Alle in den folgenden Beispielen verwendeten IP-Adressen und Hostnamen ensprechen einem real existierenden Server, dessen Aufbau hier beschrieben wird.

Bezeichnung Wert Bemerkung
Hostname des Servers srv01.sigsys.de
Domain(s) sigsys.de und sigsys.lan analog zu den IP-Netzen
IPv4 164.177.170.96/29 externe IP-Adressen auf em0
IPv4 10.253.2.0/24 interne IP-Adressen auf "lan" (=lo1)
IPv6 2a03:2500:1:8::/64 externe IPv6-Adressen auf em0


Software installieren

Die Installation eines vorkompilierten Paketes erfolgt einfach mittels "pkg install paketname". Pakete können mittels "pkg search" gesucht werden. Mehr info unter man 7 pkg (bzw pkg(7)) und pkg(8).

  • pkg (das bootstrappt sich selbst beim erstmaligen Aufruf von "pkg")
  • bash
  • bind99
  • buffer
  • iperf
  • nmap
  • openntpd
  • rsync
  • screen
  • smartmontools
  • sudo
  • vim-lite
  • wget

Grundkonfiguration /etc/rc.conf

Services und deren Parameter werden entweder in /etc/rc.conf und teilweise ergänzend in eigenen Konfigurationsdateien (zB /etc/ssh/sshd_config) konfiguriert.


Nach der Installation befinden sich beispielsweise folgende Einträge in /etc/rc.conf:

hostname="srv01.sigsys.de"
keymap="german.iso.kbd"

# ifconfig_em0="DHCP"
# ifconfig_em0_ipv6="inet6 accept_rtadv"

sshd_enable="YES"
ntpd_enable="YES"
# Set dumpdev to "AUTO" to enable crash dumps, "NO" to disable
dumpdev="AUTO"
zfs_enable="YES"

clear_tmp_enable="YES"

Das Netzwerksetup wird dann konkretisiert:

# IPv4: Net: 164.177.170.96/29
#       GW:  164.177.170.102
# IPv6: Net: 2a03:2500:1:8::/64
#       GW:  2a03:2500:1:8::1

defaultrouter="164.177.170.102"
ifconfig_em0="inet 164.177.170.97 netmask 255.255.255.248"

ifconfig_em0_ipv6="inet6 2a03:2500:1:8:1:: prefixlen 64"
ipv6_defaultrouter="2a03:2500:1:8::1"

Für die rein interne Kommunikation soll ein LAN-Interface eingerichtet werden, entweder als echtes physikalisches Interface mit Verbindung zum LAN oder wie hier gezeigt als Loopback-Interface:

# LAN: 10.253.2.0/24
cloned_interfaces="lo1"
ifconfig_lo1="inet 10.253.2.1 netmask 255.255.255.0 name lan"


Außerdem sollen weitere Dienste gestartet werden, deren Konfiguration nachfolgende erläutert wird:

# S.M.A.R.T Monitoring
smartd_enable="YES"

# syslogd soll nur im LAN lauschen
syslogd_flags="-s -b 10.253.2.1:514"

# setup von /etc/mail/sendmail.cf nicht vergessen!
sendmail_enable="YES"

# Systemzeit beim booten *hart* einstellen
ntpdate_enable="YES"
ntpdate_flags="europe.pool.ntp.org"

# Statt dem default-ntpd soll openntpd verwendet werden
ntpd_enable="NO"
openntpd_enable="YES"

# Try to set the time immediately at startup, as opposed to slowly adjusting the clock.
openntpd_flags="-s"

# setup in /usr/local/etc/namedb/named.conf
named_enable="YES"

sshd einrichten

Der OpenSSH-Daemon soll nur auf Port 2222 lauschen (auf Port 22 kommen zuviele Botnetze/Scanner rein, die nur für unnötigen Ballast im auth.log sorgen) und auch nur auf dedizierten IP-Adressen (das ist für den Betrieb von Jails erforderlich, da sonst auch unter der IP-Adresse der Jails der OpenSSH-Daemon des Servers selbst angesprochen würde).

ListenAddress 164.177.170.97:2222
ListenAddress [2a03:2500:1:8:1::]:2222
ListenAddress 127.0.0.1:22
ListenAddress 10.253.2.1:22

PermitRootLogin without-password

Weitere "Härtungen" (zB authorized_keys nur für root zugreifbar, hosts_access(5), sshd-via-xinetd, …) finden hier ersteinmal nicht statt.

Abschließend sshd neu starten (die bestehende SSH-Session bleibt dabei erhalten!):

# service sshd restart
Performing sanity check on sshd configuration.
Stopping sshd.
Waiting for PIDS: 664.
Performing sanity check on sshd configuration.
Starting sshd.

… und direkt im Anschluss unbedingt von extern mit einer neuen ssh-Session prüfen, dass der Login noch klappt!

Die noch offene SSH-Session ist evtl. hilfreich, falls das Setup doch nochmal korrigiert werden muss!

sendmail einrichten

In /etc/mail müssen initial Hostnamen-spezifische Templates angelegt werden.

# make
cp freebsd.mc srv01.sigsys.de.mc
/usr/bin/m4 -D_CF_DIR_=/usr/share/sendmail/cf/   /usr/share/sendmail/cf/m4/cf.m4 srv01.sigsys.de.mc > srv01.sigsys.de.cf
cp freebsd.submit.mc srv01.sigsys.de.submit.mc
/usr/bin/m4 -D_CF_DIR_=/usr/share/sendmail/cf/   /usr/share/sendmail/cf/m4/cf.m4 srv01.sigsys.de.submit.mc > srv01.sigsys.de.submit.cf

Im Anschluss dann in zB srv01.sigsys.de.mc bearbeitet, hier dargestellt als unified diff zum Default "freebsd.mc":

--- freebsd.mc  2014-11-11 22:03:42.000000000 +0100
+++ srv01.sigsys.de.mc  2015-02-16 17:17:12.803364117 +0100
@@ -87,7 +87,7 @@
 dnl FEATURE(dnsbl, `dnsbl.example.com', ``"550 Mail from " $&{client_addr} " rejected"'')
 
 dnl Dialup users should uncomment and define this appropriately
-dnl define(`SMART_HOST', `your.isp.mail.server')
+define(`SMART_HOST', `mail.sigsys.lan')
 
 dnl Uncomment the first line to change the location of the default
 dnl /etc/mail/local-host-names and comment out the second line.
@@ -95,8 +95,16 @@
 define(`confCW_FILE', `-o /etc/mail/local-host-names')
 
 dnl Enable for both IPv4 and IPv6 (optional)
-DAEMON_OPTIONS(`Name=IPv4, Family=inet')
-DAEMON_OPTIONS(`Name=IPv6, Family=inet6, Modifiers=O')
+dnl DAEMON_OPTIONS(`Name=IPv4, Family=inet')
+dnl DAEMON_OPTIONS(`Name=IPv6, Family=inet6, Modifiers=O')
+
+FEATURE(no_default_msa)dnl ## overridden with DAEMON_OPTIONS below
+
+DAEMON_OPTIONS(`Name=IPv4, Addr=10.253.2.1, Family=inet')dnl
+DAEMON_OPTIONS(`Name=IPv4, Addr=127.0.0.1, Family=inet')dnl
+DAEMON_OPTIONS(`Name=MSA, Addr=10.253.2.1, Port=587, M=E')dnl
+DAEMON_OPTIONS(`Name=MSA, Addr=127.0.0.1, Port=587, M=E')dnl
+DAEMON_OPTIONS(`Name=IPv6, Addr=::1, Family=inet6')dnl
 
 define(`confBIND_OPTS', `WorkAroundBrokenAAAA')
 define(`confNO_RCPT_ACTION', `add-to-undisclosed')

Das "Festnageln" der verwendeten IP-Adressen sorgt auch ier dafür, dass sendmail sich nicht auf alle IP-Adressen bindet, die ggf. durch andere Jails verwendet werden sollen. Außerdem soll für jegliche Mailkommunikation der Mailserver unter mail.sigsys.lan verwendet werden, auf dem dann einheitlich und für alle Jails das Mailrouting implementiert wird.

Die Aktivierung dieser Konfiguration erfolgt abschließend mit

# make        
/usr/bin/m4 -D_CF_DIR_=/usr/share/sendmail/cf/   /usr/share/sendmail/cf/m4/cf.m4 srv01.sigsys.de.mc > srv01.sigsys.de.cf
/usr/bin/m4 -D_CF_DIR_=/usr/share/sendmail/cf/   /usr/share/sendmail/cf/m4/cf.m4 srv01.sigsys.de.submit.mc > srv01.sigsys.de.submit.cf

# make install
install -m 444 srv01.sigsys.de.cf /etc/mail/sendmail.cf
install -m 444 srv01.sigsys.de.submit.cf /etc/mail/submit.cf

# service sendmail restart
Stopping sendmail.
Waiting for PIDS: 5095.
Starting sendmail.

bind einrichten

Als DNS-Rekursor und ggf. als Slave-DNS für wichtige Zonen soll direkt auf dem Host ein Bind 9.9 Server betrieben werden. Seit FreeBSD 10 ist bind nicht mehr Bestandteil des Basis-Systems und muss daher als Fremdsoftware (Port oder Package) nachinstalliert werden:

# pkg install bind99

Die Konfiguration und alle Dateien befinden sich unter /usr/local/etc/namedb/, als Kompatiblität zum bisherigen Pfad wird ein Symlink /etc/named/ angelegt, der dahin zeigt.

Dieser DNS-Server soll nur als Rekursor und Slave für wichtige Zonen dienen, Master-Zonen gibt es ausschließlich im dedizierten DNS-Jail (mehr dazu folgt unten).

Der folgende (gekürzte) unified diff zeigt, welche Einstellungen abweichend zum Default in /usr/local/etc/namedb/named.conf vorgenommen werden:

--- named.conf.sample   2015-01-09 04:25:53.000000000 +0100
+++ named.conf  2015-02-16 01:04:42.875385781 +0100
@@ -8,6 +8,19 @@
 // simple mistakes, you can break connectivity for affected parties,
 // or cause huge amounts of useless Internet traffic.
 
+
+acl jpru {
+        195.49.136.0/22;
+        164.177.168.0/21;
+        2a03:2500::/32;
+};
+
+acl lan {
+        10.253.0.0/16;
+};
+
+
+
 options {
        // All file and path names are relative to the chroot directory,
        // if any, and should be fully qualified.
@@ -19,12 +32,26 @@
 // If named is being used only as a local resolver, this is a safe default.
 // For named to be accessible to the network, comment this option, specify
 // the proper IP address, or delete this option.
-       listen-on       { 127.0.0.1; };
+       listen-on       {
+                               127.0.0.1;
+                               164.177.170.97;
+                               10.253.2.1;
+                       };
 
 // If you have IPv6 enabled on this system, uncomment this option for
 // use as a local resolver.  To give access to the network, specify
 // an IPv6 address, or the keyword "any".
-//     listen-on-v6    { ::1; };
+       listen-on-v6    { 
+                               ::1; 
+                               2a03:2500:1:8:1::;
+                       };
+
+        recursion yes;
+        allow-recursion {
+                jpru;
+                lan;
+        };
+
 
 // These zones are already covered by the empty zones listed below.
 // If you remove the related empty zones below, comment these lines out.
@@ -70,6 +97,33 @@
        // query-source address * port NNNNN;
 };
 
+
+key FOOXXXBARYYY.sigsys.de {
+        algorithm HMAC-MD5;
+        secret  "gw[…]XQ o[…]RQ==";
+};
+
+// logging {
+//      channel query.log {
+//              file "/var/log/query.log";
+//              // Set the severity to dynamic to see all the debug messages.
+//              severity debug 3;
+//      };
+//      channel debug.log {
+//              file "/var/log/debug.log";
+//              // Set the severity to dynamic to see all the debug messages.
+//              severity debug 3;
+//      };
+// 
+//      category security {debug.log; };
+//      category update {debug.log; };
+//      category update-security {debug.log; };
+// 
+//      category queries { query.log; };
+// };
+// 
+
+
 // If you enable a local name server, don't forget to enter 127.0.0.1
 // first in your /etc/resolv.conf so this server will be queried.
 // Also, make sure to enable it in /etc/rc.conf.
@@ -77,6 +131,168 @@
 // The traditional root hints mechanism. Use this, OR the slave zones below.
 zone "." { type hint; file "/usr/local/etc/namedb/named.root"; };
 
+zone "96-103.170.177.164.in-addr.arpa" {
+        type slave;
+        file "/usr/local/etc/namedb/slave/96-103.170.177.164.in-addr.arpa.slave";
+        masters {
+                10.253.2.3;     // dns.sigsys.lan (jail!)
+        };
+};
+
+zone "8.0.0.0.1.0.0.0.0.0.5.2.3.0.a.2.ip6.arpa" {
+        type slave;
+        file "/usr/local/etc/namedb/slave/8.0.0.0.1.0.0.0.0.0.5.2.3.0.a.2.ip6.arpa.slave";
+        masters {
+                10.253.2.3;     // dns.sigsys.lan (jail!)
+        };
+};
+
+zone "2.253.10.in-addr.arpa" {
+        type slave;
+        file "/usr/local/etc/namedb/slave/2.253.10.in-addr.arpa.slave";
+        masters {
+                10.253.2.3;     // dns.sigsys.lan (jail!)
+        };
+};
+
+zone "sigsys.de" {
+        type slave;
+        file "/usr/local/etc/namedb/slave/sigsys.de.slave";
+        masters {
+                10.253.2.3;     // dns.sigsys.lan (jail!)
+        };
+};
+
+zone "sigsys.lan" {
+        type slave;
+        file "/usr/local/etc/namedb/slave/sigsys.lan.slave";
+        masters {
+                10.253.2.3;     // dns.sigsys.lan (jail!)
+        };
+};
+
[… alle weiteren slave-Zonen sind hier uninteressant…]
+
+
+
 /*     Slaving the following zones from the root name servers has some
        significant advantages:
        1. Faster local resolution for your users
@@ -358,3 +574,4 @@
        };
 };
 */
+

openntpd einrichten

Abweichend von der Standardkonfiguration wird /usr/local/etc/ntpd.conf wie folgt bearbeitet:

--- ntpd.conf.sample    2015-02-04 13:22:21.000000000 +0100
+++ ntpd.conf   2015-02-15 13:55:00.462693215 +0100
@@ -9,3 +9,7 @@
 # use a random selection of NTP Pool Time Servers
 # see http://support.ntp.org/bin/view/Servers/NTPPoolServers
 servers pool.ntp.org
+
+listen on 127.0.0.1
+listen on ::1
+

Jails werden über das Hostsystem mit der Systemzeit versorgt, daher muss der Daemon nicht auf dem lan-Interface lauschen. Hier exemplarisch nur die Einstellung dass der Daemon ausschlielich auf localhost lauscht.

Jails

Grundlagen zu Jails

  • Neu seit FreeBSD 9.x: Konfiguration mittels jail.conf (old-style aber immernoch supported!)
  • Neue Jails anlegen, ganz einfach!
  • Jails einzeln Starten/Beenden/Neustarten mittels jail(8) und jail.conf(5)
  • ZFS und Jails
  • Automatisch Starten/Beenden von Jails beim Systemboot

ZFS Setup für Jails

Jedes Jail soll ein eigenes ZFS-Volume verwenden. Das ermöglichst später die automatische Erstellung von Snapshots beim Starten oder Beenden von Jails oder damit dann feingranulare Rollbacks nach fehlgeschlagenen Upgrades innerhalb von Jails, ohne dass benachbarte Jails zwangsweise mit zurückgerollt werden.


Jails beim Booten automatisch starten

Das Script /etc/rc.d/jail wurde seit FreeBSD 4.x bis FreeBSD 9.x kontinuierlich weiter entwickelt. Es basierte darauf, dass alle Parameter für alle Jails in jail_* variables in /etc/rc.conf gepackt wurden. Da Jails als solche seit FreeBSD 8.x drastisch an Komplexität zugenommen haben (feingranulare Properties, MultiIP/NoIP/IPv6(only) etc) war es nicht mehr praktikabel alle möglichen Parameter auf diesem Weg (/etc/rc.conf) zu verwalten.

Das jail(8)-Tool hatte lange Zeit 2 getrennte Syntaxe:

historischer Stil (alle Parameter müssen direkt an jail(8) übergeben werden, komplexe Dinge musste das Startscript mit Variablen aus /etc/rc.conf erledigen)
     jail [-hi] [-n jailname] [-J jid_file] [-s securelevel]
          [-l -u username | -U username] path hostname [ip[,..]] command ...
aktueller Stil mit Support für /etc/jail.conf, wobei jail(8) einen Großteil der Kompelexität selbst implementiert.
     jail [-dhilqv] [-J jid_file] [-u username] [-U username] [-cmr]
          param=value ... [command=command ...]
     jail [-dqv] [-f conf_file] [-p limit] [-cmr] [jail]
     jail [-qv] [-f conf_file] [-rR] [* | jail ...]
     jail [-dhilqv] [-J jid_file] [-u username] [-U username] [-n jailname]
          [-s securelevel] [path hostname [ip[,...]] command ...]

Beim "old-style" war es praktisch nicht möglich Jails zu verwalten ohne dabei das /etc/rc.d/jail-Startscript zu verwenden, welches signifikant komplexe Dinge getan hatte und dennoch spürbare Grenzen hatte. Zusätzliche Jailmanagement Tools wie "ezjail" haben mit eigenen Methoden um /etc/rc.d/jail herum das ein Stück weit erträglicher gemacht für den Administrator.

Neuartige Jails kann man nun sehr einfach mittels jail(8) verwalten, zB jail -c jail_name zum Starten (create) oder jail -r jail_name zum Beenden (remove), wobei alle mit jail_name assoziierten Parameter aus /etc/jail.conf kommen.

Damit konnte die Komplexität des /etc/rc.d/jail-Startscript drastisch reduziert werden und es ist auch nicht mehr erforderlich dieses Startscript ansich zu nutzen.