From 62dede3e7ad2c0ee566145f3efabf1fd23df46a7 Mon Sep 17 00:00:00 2001 From: Ian Kelling Date: Fri, 18 Feb 2022 23:10:15 -0500 Subject: [PATCH] limit exim to Debian-exim user --- install-my-scripts | 2 + ip6tables-exim | 2 + iptables-exim | 2 + mail-setup | 180 +++++++++++++++++++++++++++++++++++++++------ 4 files changed, 163 insertions(+), 23 deletions(-) create mode 100755 ip6tables-exim create mode 100755 iptables-exim diff --git a/install-my-scripts b/install-my-scripts index 2969a09..67a576a 100755 --- a/install-my-scripts +++ b/install-my-scripts @@ -44,5 +44,7 @@ rsync -t --chmod=755 --chown=root:root switch-mail-host btrbk-run mount-latest-s check-mailq \ unsaved-buffers.el \ mail-backup-clean \ + iptables-exim \ + ip6tables-exim \ /usr/local/bin rsync -t --chmod=755 --chown=root:root /a/bin/errhandle/err /usr/local/lib diff --git a/ip6tables-exim b/ip6tables-exim new file mode 100755 index 0000000..92ea7a6 --- /dev/null +++ b/ip6tables-exim @@ -0,0 +1,2 @@ +#!/bin/bash +nsenter -t $(systemctl show --property MainPID --value mailnn) -n -m ip6tables "$@" diff --git a/iptables-exim b/iptables-exim new file mode 100755 index 0000000..b35a344 --- /dev/null +++ b/iptables-exim @@ -0,0 +1,2 @@ +#!/bin/bash +nsenter -t $(systemctl show --property MainPID --value mailnn) -n -m iptables "$@" diff --git a/mail-setup b/mail-setup index 0514ea5..13f9947 100755 --- a/mail-setup +++ b/mail-setup @@ -4,15 +4,7 @@ # 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 +# 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 @@ -26,8 +18,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 +368,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 +384,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 @@ -833,6 +823,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 @@ -905,12 +1010,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? @@ -1871,7 +1978,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 @@ -2172,7 +2278,7 @@ if (( ${#files[@]} )); then fi -# ** auth +# ** exim: auth case $HOSTNAME in bk|je) @@ -2208,7 +2314,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: @@ -2219,8 +2325,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 @@ -2234,7 +2343,32 @@ 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 +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) -- 2.30.2