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"
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ürssh) und die60000er Range fürmoshoffen. - 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_authScript erweitert die noch um Einträge aus der/var/log/auth.log.
- tbl_allow
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 klonen:
mkdir ~/code
cd ~/code
git clone https://github.com/spookey/dirty_little_helpers.git
git clone https://github.com/spookey/geli_remote_unlock.git
git clone https://github.com/spookey/say_cheese_zfs.git
git clone https://gitlab.com/spookey/quicksnap.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 unter /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 "$@"
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.
Log Rotation – /usr/local/etc/newsyslog.conf.d/pf_auth.conf:
cat << LOL >> /usr/local/etc/newsyslog.conf.d/pf_auth.conf
/var/log/pf_auth.log 644 4 * @T00 BCNX
LOL
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/user/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/user/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.
Log Rotation – /usr/local/etc/newsyslog.conf.d/say_cheese.conf:
cat << LOL >> /usr/local/etc/newsyslog.conf.d/say_cheese.conf
/var/log/say_cheese.log 644 9 1000 * BCNX
LOL
geli remote unlock (rc Script)
Das rc Script kopieren:
cp /usr/home/user/code/geli_remote_unlock/geliremoteunlock /usr/local/etc/rc.d/
chown root:wheel /usr/local/etc/rc.d/geliremoteunlock
chmod +x /usr/local/etc/rc.d/geliremoteunlock
Erlaubt uns die Pools automatisch zu entsperren…