Einrichten

Frisch installiert kommt der Server zum Ersten mal hoch. ssh login funktioniert, sudo auch? Sehr gut.

Netzwerk

Als erstes kümmert man sich um korrektes Netzwerk. Die /etc/rc.conf wird von DHCP auf fixe Adressen umgestellt:

# Network
hostname="machine"
ifconfig_igb0="inet <v4 Addresse vom Server>/32"
gateway_if="igb0"
gateway_ip="<v4 Addresse vom Gateway>"
static_routes="gateway default"
route_gateway="-host $gateway_ip -interface $gateway_if"
route_default="default $gateway_ip"

ipv6_default_interface="igb0"
ifconfig_igb0_ipv6="inet6 <v6 Addresse vom Server> prefixlen 64 accept_rtadv"
ipv6_defaultrouter="fe80::1%igb0"

resolv_enable="NO"
netwait_enable="YES"

Anmerkung der Redaktion: Kommt auf die Netwerk-Karte an wie der Device-Name ist: em0, bge0, … – Oder wie bei mir: igb0.

OpenSSH abdichten

Orientiere mich dabei an der cipherlist will aber (da es beim OS-Update nervt) die /etc/ssh/sshd_config nicht anfassen.

Deshalb kommt in die /etc/rc.config mittlerweile so was:

# OpenSSH
sshd_flags=" \
-o ListenAddress=<v4 Addresse vom Server>:23 \
-o ListenAddress=[<v6 Addresse vom Server>]:23 \
-o Protocol=2 \
-o HostKey=/etc/ssh/ssh_host_ed25519_key \
-o HostKey=/etc/ssh/ssh_host_rsa_key \
-o HostKeyAlgorithms=ssh-ed25519,rsa-sha2-512,rsa-sha2-256 \
-o KexAlgorithms=curve25519-sha256@libssh.org,curve25519-sha256,diffie-hellman-group18-sha512,diffie-hellman-group16-sha512,diffie-hellman-group14-sha256,diffie-hellman-group-exchange-sha256 \
-o Ciphers=chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr \
-o MACs=hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com \
-o PermitRootLogin=no \
-o IgnoreRhosts=yes \
-o PasswordAuthentication=no \
-o PermitEmptyPasswords=no \
-o KbdInteractiveAuthentication=no \
-o UsePAM=no \
-o X11Forwarding=no \
"
sshd_enable="YES"

Erwischt: Ja ich nutze den telnet Port für ssh.

NTPd listen local

Da habe ich noch keine Lösung wie man das mit ntpd_flags hin bekommt.

sockstat -l verrät uns, dass der NTPd auf jedem Interface Port 123 lauscht.

Die /etc/ntp.conf bekommt ein interface ignore wildcard, so wie auf einer eigenen Seite beschrieben.

Firewall

Noch nichts spannendes damit geplant, aber wenn Jails dazu kommen ist es gut eine Grundlage zu haben - /etc/pf.conf:

# public addresses
 ip_igb0_p4 = "<v4 Addresse vom Server>"
 ip_igb0_p6 = "<v6 Addresse vom Server>"

# tables
 table <tbl_allow> const { "my.other.host.example.net", "dyndns.example.org" }
 table <tbl_block> persist {}

# services hosted on this box
#   60000: mosh
 inbound_tcp = "{ telnet }"
 inbound_udp = "{ 60000:60010 }"

# services consumed by this box
 outbound_tcp = "{ ssh, telnet, domain, http, https, ftp }"
 outbound_udp = "{ domain, ntp }"

# icmp types
 icmp_types_p4 = "{ echoreq, unreach }"
 icmp_types_p6 = "{ echoreq, echorep, unreach, toobig, timex, routersol, routeradv, neighbrsol, neighbradv, redir }"

# allow loopback traffic
 set skip on { lo0 }

# do not reject, just drop
 set block-policy drop

# incoming traffic is normalized and defragmented
 scrub in on igb0 all fragment reassemble

# default rule - block all
 block log all

# apply tables
 block drop in from <tbl_block> to any
 pass       in from <tbl_allow> to any

# allow ping
 pass inet  proto icmp  all icmp-type  $icmp_types_p4 keep state
 pass inet6 proto icmp6 all icmp6-type $icmp_types_p6 keep state

# allow access to outside world
 pass out proto tcp to any port $outbound_tcp keep state
 pass out proto udp to any port $outbound_udp keep state

# allow outside access into this box
 pass in log proto tcp to any port $inbound_tcp keep state (max-src-conn 5, max-src-conn-rate 2/10, overload <tbl_block> flush global)
 pass in log proto udp to any port $inbound_udp keep state (max-src-conn 5, max-src-conn-rate 2/10, overload <tbl_block> flush global)
  • Eher unspannend, von außen sind nur noch die Ports telnet (für ssh) und die 60000er Range für mosh offen.
  • Wichtiger sind die zwei Tables:
    • tbl_allow
      • Sind fixe Adressen von meinen anderen Kisten.
      • Soll verhindern, dass ich mich versehentlich aussperre.
    • tbl_block
      • Wird auf alle offenen Ports angesetzt und macht ein Rate-Limiting
      • Wehrt stumpfsinnige DoS Angriffe ab.
      • Das pf_auth Script erweitert die noch um Einträge aus der /var/log/auth.log.

In der /etc/rc.conf noch einschalten:

# Firewall
pf_enable="YES"
pf_rules="/etc/pf.conf"
pflog_enable="YES"
pflog_logfile="/var/log/pflog"

(Wobei man pflog auch weglassen kann.)

Tools

Habe mir im Laufe der Zeit eine paar Scripte geschrieben die das Leben einfacher machen.

pkg install vim git-lite

(git-lite bringt weniger Abhängigkeiten mit als git, gut für den Server)

Und dann als User clonen:

mkdir ~/code
cd ~/code

git clone https://gitlab.com/spookey/quicksnap.git
git clone https://github.com/spookey/dirty_little_helpers.git
git clone https://github.com/spookey/say_cheese_zfs.git

quicksnap

Einfach, aber effektiv. Hat eine input.txt mit einem Pfad pro Zeile und kopiert die Files rüber. Das ganze in ein git repo packen und zack, hat man seine Config versioniert und ein Backup davon.

Erst mal einen Key anlegen:

ssh-keygen -t ed25519 -f `/root/.ssh/quicksnap_ed25519` -C 'root@machine'

Bei dem git Hoster des geringsten Misstrauens ein private Repo anlegen, und /root/.ssh/quicksnap_ed25519.pub hinterlegen.

Eine entsprechende ssh config für root:

cat << LOL >> /root/.ssh/config
Host git.example.net
    User git
    IdentityFile ~/.ssh/quicksnap_ed25519

Host *
    VisualHostKey true
LOL

Das Repo clonen:

mkdir /root/code
cd /root/code

git clone ssh://git.example.net/user/conf_machine.git

Als letztes noch das Wrapper-Script für quicksnap

mkdir /root/bin
cat << LOL >> /root/bin/quicksnap
#!/usr/bin/env sh

INPUT=/root/code/conf_machine/input.txt \
OUTPUT=/root/code/conf_machine/output \
    /usr/home/user/code/quicksnap/quicksnap.sh "$@"
LOL

dirty little helpers

Hier brauchen wir nur wenige Sachen..

pf_auth

Macht nur Sinn, wenn man pf so eingerichtet hat, dass Einträge von tbl_block auch wirklich blockiert werden.

Alles was wir brauchen ist ein Eintrag in der crontab von root:

*/2  *   *   *   *   /usr/home/user/code/dirty_little_helpers/pf_auth/pf_auth.sh -n 3 /var/log/auth.log >> /var/log/pf_auth.log 2>&1

Es lassen sich der auth.log Parameter mehrfach angeben.

Ab dem Moment wenn jails laufen sollte man den Eintrag noch um /usr/jails/*/var/log/auth.log erweitern, um alles einzusammeln.

jail_pkg_list

Die Paket-Namen mit Version einfach in einer Text-Datei speichern. Das ganze ins quicksnap Repo legen, dann weiß man wann was installiert wurde.

ln -s /usr/home/spky/code/dirty_little_helpers/jail_pkg_list/jail_pkg_list.sh /root/bin/jail_pkg_list

Und das ganze auch noch automatisch in der crontab von root:

*/30  *   *  *   *    /usr/home/spky/code/dirty_little_helpers/jail_pkg_list/jail_pkg_list.sh > /var/log/jail_pkg_list.log

Geht auch als normaler user, aber aufpassen bei den Berechtigungen vom Log-File.

jail_pkg

Einmal pkg für alle Jails ausführen. Anwendungsfall zu 99% ist jail_pkg update und jail_pkg upgrade.

Hier reicht eine Verlinkung nach /root/bin (analog zu oben).

say cheese

Macht automatisch zfs Snapshots, und räumt auch wieder auf.

Python ist durch vim schon längst da, aber es fehlt noch das Meta-Package:

pkg install python3

In der crontab von root noch einrichten:

# say cheese
  1   *   *   *   *   /usr/local/bin/python3 /usr/home/user/code/say_cheese_zfs/take_snapshots.py          auto_hourly   >> /var/log/say_cheese.log 2>&1
 11   *   *   *   *   /usr/local/bin/python3 /usr/home/user/code/say_cheese_zfs/purge_snapshots.py 24 H -p auto_hourly   >> /var/log/say_cheese.log 2>&1

  3   0   *   *   *   /usr/local/bin/python3 /usr/home/user/code/say_cheese_zfs/take_snapshots.py          auto_daily    >> /var/log/say_cheese.log 2>&1
 13   0   *   *   *   /usr/local/bin/python3 /usr/home/user/code/say_cheese_zfs/purge_snapshots.py  7 d -p auto_daily    >> /var/log/say_cheese.log 2>&1

  5   0   *   *   0   /usr/local/bin/python3 /usr/home/user/code/say_cheese_zfs/take_snapshots.py          auto_weekly   >> /var/log/say_cheese.log 2>&1
 15   0   *   *   0   /usr/local/bin/python3 /usr/home/user/code/say_cheese_zfs/purge_snapshots.py  4 w -p auto_weekly   >> /var/log/say_cheese.log 2>&1

  7   0   1   *   *   /usr/local/bin/python3 /usr/home/user/code/say_cheese_zfs/take_snapshots.py          auto_monthly  >> /var/log/say_cheese.log 2>&1
 17   0   1   *   *   /usr/local/bin/python3 /usr/home/user/code/say_cheese_zfs/purge_snapshots.py 12 m -p auto_monthly  >> /var/log/say_cheese.log 2>&1

  9   0   1   1   *   /usr/local/bin/python3 /usr/home/user/code/say_cheese_zfs/take_snapshots.py          auto_yearly   >> /var/log/say_cheese.log 2>&1
 19   0   1   1   *   /usr/local/bin/python3 /usr/home/user/code/say_cheese_zfs/purge_snapshots.py  2 y -p auto_yearly   >> /var/log/say_cheese.log 2>&1

Nach und nach sollten die Snapshots jetzt eintrudeln.

last update: 2025-01-29 20:22:06 +0100