X-Git-Url: https://iankelling.org/git/?a=blobdiff_plain;f=mail-setup;h=28e02ce089f63edc39362f7123610f77bc3ad578;hb=e958999a4ab6fddd723270b596b4899c0811fa41;hp=4325b7a79d7c8e4913bbb14afe55ce3106ba6bed;hpb=01083a0fcfcea5d45731b6b7cf1bffe3725ac134;p=distro-setup diff --git a/mail-setup b/mail-setup index 4325b7a..28e02ce 100755 --- a/mail-setup +++ b/mail-setup @@ -3,17 +3,6 @@ # Copyright (C) 2019 Ian Kelling # SPDX-License-Identifier: AGPL-3.0-or-later -# todo: sandbox / harden exim: -# 1. stop it from running as root. how? -# https://www.exim.org/exim-html-current/doc/html/spec_html/ch-security_considerations.html -# * avoid using .forward files, remove that router -# * set deliver_drop_privilege -# * set user to run as Debian-exim in systemd -# * set port to something like 2500, and forward 25 to 2500 with iptables. same for 587. -# https://superuser.com/questions/710253/allow-non-root-process-to-bind-to-port-80-and-443/1334552#1334552 -# * consider whether other routers like postmaster need modification / removal. -# 2. restrict its filesystem access from within systemd - # todo: harden dovecot. need to do some research. one way is for it to only listen on a wireguard vpn interface, so only clients that are on the vpn can access it. # todo: consider hardening cups listening on 0.0.0.0 # todo: stop/disable local apache, and rpc.mountd, and kdeconnect when not in use. @@ -26,8 +15,6 @@ # todo: emailing info@amnimal.ninja produces a bounce, user doesn't exist # instead of a simple rejection like it should. -# todo: auto restart of je on checkrestart - # todo: run mailping test after running, or otherwise # clear out terminal alert @@ -378,7 +365,7 @@ esac # * Install universal packages -# installs epanicclean +# installs epanicclean iptables-exim ip6tables-exim /a/bin/ds/install-my-scripts if [[ $(debian-codename-compat) == bionic ]]; then @@ -394,7 +381,7 @@ pi-nostart exim4 exim4-daemon-heavy spamassassin openvpn unbound clamav-daemon w # note: pyzor debian readme says you need to run some initialization command # but its outdated. -pi spf-tools-perl p0f postgrey pyzor razor jq moreutils certbot +pi spf-tools-perl p0f postgrey pyzor razor jq moreutils certbot fail2ban # bad packages that sometimes get automatically installed pu openresolv resolvconf @@ -492,11 +479,15 @@ Requires=mailnn.service After=network.target mailnn.service JoinsNamespaceOf=mailnn.service BindsTo=mailnn.service +StartLimitIntervalSec=0 [Service] PrivateNetwork=true # i dont think we need any of these, but it doesnt hurt to stay consistent BindPaths=$bindpaths + +Restart=on-failure +RestartSec=20 EOF ;; esac @@ -541,7 +532,7 @@ PrivateNetwork=true BindPaths=$bindpaths Restart=always # time to sleep before restarting a service -RestartSec=1 +RestartSec=20 [Install] WantedBy=multi-user.target @@ -563,7 +554,7 @@ PrivateNetwork=true ExecStart=/usr/bin/flock -w 20 /tmp/newns.flock /a/bin/newns/newns -n 10.173.8 start mail ExecStop=/usr/bin/flock -w 20 /tmp/newns.flock /a/bin/newns/newns stop mail Restart=always -RestartSec=10 +RestartSec=20 [Install] @@ -598,7 +589,7 @@ Type=simple ExecStart=/usr/local/bin/mailbindwatchdog $vpnser ${nn_progs[@]} unbound.service radicale.service Restart=always # time to sleep before restarting a service -RestartSec=1 +RestartSec=10 [Install] WantedBy=multi-user.target @@ -675,7 +666,7 @@ PrivateNetwork=true BindPaths=$bindpaths Restart=always -RestartSec=1 +RestartSec=20 EOF # sooo, there are a few ways to get traffic from the mail network @@ -726,7 +717,7 @@ PrivateNetwork=true BindPaths=$bindpaths Restart=always -RestartSec=1 +RestartSec=20 EOF done ;; @@ -829,6 +820,121 @@ if $bhost_t && [[ ! -e /etc/exim4/certs/$wghost/privkey.pem ]]; then --deploy-hook /a/bin/ds/le-exim-deploy -d $wghost fi +# * fail2ban + +# todo: test that these configs actually work, eg run +# s iptables-exim -S +# and see someone is banned. + +sed 's/^ *before *= *iptables-common.conf/before = iptables-common-exim.conf/' \ + /etc/fail2ban/action.d/iptables-multiport.conf| i /etc/fail2ban/action.d/iptables-exim.conf +i /etc/fail2ban/action.d/iptables-common-exim.conf <<'EOF' +# iank: same as iptables-common, except iptables is iptables-exim, ip6tables is ip6tables-exim + +# Fail2Ban configuration file +# +# Author: Daniel Black +# +# This is a included configuration file and includes the definitions for the iptables +# used in all iptables based actions by default. +# +# The user can override the defaults in iptables-common.local +# +# Modified: Alexander Koeppe , Serg G. Brester +# made config file IPv6 capable (see new section Init?family=inet6) + +[INCLUDES] + +after = iptables-blocktype.local + iptables-common.local +# iptables-blocktype.local is obsolete + +[Definition] + +# Option: actionflush +# Notes.: command executed once to flush IPS, by shutdown (resp. by stop of the jail or this action) +# Values: CMD +# +actionflush = -F f2b- + + +[Init] + +# Option: chain +# Notes specifies the iptables chain to which the Fail2Ban rules should be +# added +# Values: STRING Default: INPUT +chain = INPUT + +# Default name of the chain +# +name = default + +# Option: port +# Notes.: specifies port to monitor +# Values: [ NUM | STRING ] Default: +# +port = ssh + +# Option: protocol +# Notes.: internally used by config reader for interpolations. +# Values: [ tcp | udp | icmp | all ] Default: tcp +# +protocol = tcp + +# Option: blocktype +# Note: This is what the action does with rules. This can be any jump target +# as per the iptables man page (section 8). Common values are DROP +# REJECT, REJECT --reject-with icmp-port-unreachable +# Values: STRING +blocktype = REJECT --reject-with icmp-port-unreachable + +# Option: returntype +# Note: This is the default rule on "actionstart". This should be RETURN +# in all (blocking) actions, except REJECT in allowing actions. +# Values: STRING +returntype = RETURN + +# Option: lockingopt +# Notes.: Option was introduced to iptables to prevent multiple instances from +# running concurrently and causing irratic behavior. -w was introduced +# in iptables 1.4.20, so might be absent on older systems +# See https://github.com/fail2ban/fail2ban/issues/1122 +# Values: STRING +lockingopt = -w + +# Option: iptables +# Notes.: Actual command to be executed, including common to all calls options +# Values: STRING +iptables = /usr/local/bin/iptables-exim + + +[Init?family=inet6] + +# Option: blocktype (ipv6) +# Note: This is what the action does with rules. This can be any jump target +# as per the iptables man page (section 8). Common values are DROP +# REJECT, REJECT --reject-with icmp6-port-unreachable +# Values: STRING +blocktype = REJECT --reject-with icmp6-port-unreachable + +# Option: iptables (ipv6) +# Notes.: Actual command to be executed, including common to all calls options +# Values: STRING +iptables = /usr/local/bin/ip6tables-exim +EOF + +i /etc/fail2ban/jail.d/exim.local <<'EOF' +[exim] +enabled = true +port = 25,587 +filter = exim +banaction = iptables-exim +EOF +if $ir; then + m systemctl restart fail2ban +fi + # * common exim4 config @@ -901,12 +1007,14 @@ fi m sed -ri 's/^(\s*rotate\s).*/\11000/' /etc/logrotate.d/exim4-base -## https://blog.dhampir.no/content/make-exim4-on-debian-respect-forward-and-etcaliases-when-using-a-smarthost -# i only need .forwards, so just doing that one. -cd /etc/exim4/conf.d/router -b=userforward_higher_priority -# replace the router name so it is unique -sed -r s/^\\S+:/$b:/ 600_exim4-config_userforward >175_$b +## disabled. not using .forward files, but this is still interesting +## for reference. +# ## https://blog.dhampir.no/content/make-exim4-on-debian-respect-forward-and-etcaliases-when-using-a-smarthost +# # i only need .forwards, so just doing that one. +# cd /etc/exim4/conf.d/router +# b=userforward_higher_priority +# # replace the router name so it is unique +# sed -r s/^\\S+:/$b:/ 600_exim4-config_userforward >175_$b # todo, consider 'separate' in etc/exim4.conf, could it help on busy systems? @@ -1277,7 +1385,7 @@ PrivateNetwork=true BindPaths=$bindpaths Restart=always # time to sleep before restarting a service -RestartSec=1000 +RestartSec=20 [Install] # for openvpn @@ -1390,8 +1498,8 @@ case $HOSTNAME in break fi done - for f in /p/c/subdir_files/sieve/*sieve /a/c/subdir_files/sieve/*sieve; do - m sudo -u $u /a/exe/lnf -T $f $uhome/sieve/${f##*/} + for f in /p/c/subdir_files/sieve/*sieve /a/bin/ds/subdir_files/sieve/*sieve; do + m sudo -u $u /a/exe/lnf -v -T $f $uhome/sieve/${f##*/} done # https://wiki.dovecot.org/SSL/DovecotConfiguration @@ -1867,7 +1975,6 @@ EOF m chown -R www-data.www-data $rctmpdir /m/rc m chmod 750 $rctmpdir # Ensure the log file monitored by fail2ban exists, or else fail2ban can't start. - # todo: setup fail2ban # todo: check for other mailinabox things m sudo -u www-data touch $rclogdir/errors.log @@ -2168,7 +2275,7 @@ if (( ${#files[@]} )); then fi -# ** auth +# ** exim: auth case $HOSTNAME in bk|je) @@ -2204,7 +2311,7 @@ server_advertise_condition = ${if eq{$tls_in_cipher}{}{}{*}} EOF fi -# ** main daemon use non-default config file +# ** exim: main daemon use non-default config file case $HOSTNAME in bk|$MAIL_HOST) # to see the default comments in /etc/default/exim4: @@ -2215,8 +2322,11 @@ QUEUERUNNER='combined' QUEUEINTERVAL='30m' COMMONOPTIONS='-C /etc/exim4/my.conf' UPEX4OPTS='-o /etc/exim4/my.conf' -#E4BCD_PANICLOG_NOISE='malware acl condition: clamd /var/run/clamav/clamd\.ctl : unable to connect to UNIX socket' +#E4BCD_PANICLOG_NOISE='exim user lost privilege for using -C option' EOF + chown Debian-exim:Debian-exim /usr/sbin/exim4 + # needs guid set in order to become Debian-exim + chmod g+s,u+s /usr/sbin/exim4 i /etc/exim4/trusted_configs <<'EOF' /etc/exim4/my.conf EOF @@ -2230,7 +2340,45 @@ EOF ;; esac +# ** exim non-root + +case $HOSTNAME in + bk|je|li) + # no reason to expect it to ever be there. + rm -fv /etc/systemd/system/exim4.service.d/nonroot.conf + ;; + *) + i /etc/systemd/system/exim4.service.d/nonroot.conf <<'EOF' +[Service] +# see 56.2 Root privilege in exim spec +AmbientCapabilities=CAP_NET_BIND_SERVICE +# https://www.redhat.com/sysadmin/mastering-systemd +# things that seem good and reasonabl.e +PrivateTmp=yes +ProtectHome=yes +# note, in t10 systemd, if one of these is an sshfs mountpoint, +# this whole setting doesnt work. tried it with a newer systemd 250 though +# an nspawn, and it worked there. +InaccessiblePaths=d m media mnt nocow o p q +NoNewPrivileges=yes +ProtectSystem=yes + +# when we get newer systemd +#ProtectDevices=yes +EOF + i /etc/exim4/conf.d/main/000_local-noroot <<'EOF' +# see 56.2 Root privilege in exim spec +deliver_drop_privilege = true +EOF + # Note: there are other routers that would also fail due to not running as root, + # but afaik, the main router will catch all mail. If not, we will see + # something in the queue. + rm -fv /etc/exim4/conf.d/router/600_exim4-config_userforward + ;; +esac + case $HOSTNAME in + # ** $MAIL_HOST|bk|je) $MAIL_HOST|bk|je) @@ -2562,7 +2710,7 @@ StartLimitIntervalSec=0 [Service] Restart=always # time to sleep before restarting a service -RestartSec=1 +RestartSec=20 EOF i /etc/default/exim4in <<'EOF' @@ -2677,7 +2825,7 @@ StartLimitIntervalSec=0 [Service] Restart=always -RestartSec=300 +RestartSec=20 EOF else