# Copyright (C) 2019 Ian Kelling
# SPDX-License-Identifier: AGPL-3.0-or-later
+# todo: backup hosts should only allow external mail that is authed and
+# destined for backup route. it is a minor issue since traffic is
+# limited to the wghole network.
+
# todo: emailing info@amnimal.ninja produces a bounce, user doesn't exist
# instead of a simple rejection like it should.
}
sstart() {
for service; do
- m systemctl start $service
- m systemctl enable $service;
+ m systemctl enable --now $service;
done
}
mailhost() {
done
}
-mxhost=mail.iankelling.org
+mxhost=mx.iankelling.org
mxport=587
forward=$u@$mxhost
err "\$MAIL_HOST not set"
fi
+bhost_t=false
+case $HOSTNAME in
+ $MAIL_HOST) : ;;
+ kd|frodo|x2|x3|kw|sy)
+ bhost_t=true
+ ;;
+esac
+
# * Install universal packages
# 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
+pi spf-tools-perl p0f postgrey pyzor razor jq moreutils certbot
# bad packages that sometimes get automatically installed
pu openresolv resolvconf
# our nostart pi fails to avoid enabling
-# * bu setup
-
-if ! getent passwd bu; then
- useradd -c bu -Um -s /bin/bash -d /bu/home bu
- usermod -a -G bu $u
- # note, no reason for /bu/mnt to be owned by bu,
- # but its just convenient to have it here.
- for dir in /bu/mnt /bu/home/md /bu/home/md/{cur,tmp,new}; do
- [[ -e $dir ]] && continue
- dirs+=($dir)
- done
- if (( ${#dirs[@]} )); then
- mkdir -p "${dirs[@]}"
- chown bu:bu "${dirs[@]}"
- fi
- sed -ri '/Subsystem[[:space:]]+sftp/d' /etc/ssh/sshd_config
-
- install -d -o bu -g bu /bu/home/.ssh
- install -T -o bu -g bu /root/.ssh/h.pub /bu/home/.ssh/authorized_keys
-
- i /etc/ssh/sshd_config.d/mail.conf <<'EOF'
-# for mail chroot restriction
-# https://serverfault.com/questions/660160/openssh-difference-between-internal-sftp-and-sftp-server
-Subsystem sftp internal-sftp
-Match user bu
- ChrootDirectory /bu/home
- X11Forwarding no
- AllowTcpForwarding no
- PermitTunnel no
- AllowAgentForwarding no
- ForceCommand internal-sftp
-EOF
- if $ir; then
- systemctl reload sshd
- fi
-fi
-
-
-
# * user forward file
case $HOSTNAME in
$MAIL_HOST)
Restart=always
RestartSec=1
+EOF
+
+ # sooo, there are a few ways to get traffic from the mail network
+ # namespace to go over the wghole.
+ #
+ #1: unify the mail vpn and wghole
+ # into 1 network. this seems simple and logical, but the thing is
+ # that if we ever have a network block we need to overcome, for
+ # example with a tcp 443 vpn connection, then i'd need to setup some
+ # hole hosts on that vpn too, which is kind of a pain.
+ #
+ # 2. We can route 10.5.3.0/24 out of the mail nn and nat it into wghole.
+ #
+ # 3. We can setup the routing to happen on li, which seemed like I
+ # just needed to add 10.8.0.4/24 to AllowedIPs in at least the
+ # wghole clients, but I think that is kind of hacky and breaks ipv4
+ # routing within the mailvpn, it happened to work just because exim
+ # prefers ipv6 and that was also available in the mailvpn.
+ #
+ # 4. Put the hole interface into the mail network
+ # namespace. Apparently wireguard is smart enough to get around the
+ # mailvpn default routing and establish a direct connection. That is
+ # what I'm doing here. I only use the hole vpn for randomish things,
+ # it should be fine to join the mail nn for that. If that becomes a
+ # problem, I think I'd go with option #2.
+ i /etc/systemd/system/wg-quick@wghole.service.d/override.conf <<'EOF'
+[Unit]
+Requires=mailvpn.service
+After=network.target mailnn.service mailvpn.service
+JoinsNamespaceOf=mailnn.service
+BindsTo=mailnn.service
+
+[Service]
+PrivateNetwork=true
+# i dont think we need any of these, but it doesnt hurt to stay consistent
+BindPaths=$bindpaths
EOF
;;&
WantedBy=timers.target
EOF
+
+wghost=${HOSTNAME}wg.b8.nz
+if $bhost_t && [[ ! -e /etc/exim4/certs/$wghost/privkey.pem ]]; then
+ certbot -n --manual-public-ip-logging-ok --eff-email --agree-tos -m letsencrypt@iankelling.org \
+ certonly --manual --preferred-challenges=dns \
+ --manual-auth-hook /a/bin/ds/le-dns-challenge \
+ --manual-cleanup-hook /a/bin/ds/le-dns-challenge-cleanup \
+ --deploy-hook /a/bin/ds/le-exim-deploy -d $wghost
+fi
+
# * common exim4 config
# old name
rm -fv /etc/exim4/conf.d/retry/37_retry
-# Retry faster than usual for domains that I send with send-test-forward.
cat >/etc/exim4/conf.d/retry/17_retry <<'EOF'
+# Retry faster than usual for sending to domains that I send with send-test-forward.
iankelling.org * F,2d,15m;F,14d,2h
amnimal.ninja * F,2d,15m;F,14d,2h
expertpathologyreview.com * F,2d,15m;F,14d,2h
cat >/etc/exim4/conf.d/main/000_local <<EOF
MAIN_TLS_ENABLE = true
+# require tls connections for all smarthosts
+REMOTE_SMTP_SMARTHOST_HOSTS_REQUIRE_TLS = *
+
# debian exim config added this in 2016 or so?
# it's part of the smtp spec, to limit lines to 998 chars
# but a fair amount of legit mail does not adhere to it. I don't think
# ian: commented this. I get all local parts. for bk, an rcpt
# check handles checking with dovecot, and the only router
# after this is root.
- local_parts = ! root
+# local_parts = ! root
transport = LOCAL_DELIVERY
cannot_route_message = Unknown user
# ian: added for + addressing.
# ** auth
case $HOSTNAME in
- $MAIL_HOST)
- i /etc/exim4/conf.d/auth/29_exim4-config_auth <<'EOF'
-# from 30_exim4-config_examples
-plain_server:
-driver = plaintext
-public_name = PLAIN
-server_condition = "${if crypteq{$auth3}{${extract{1}{:}{${lookup{$auth2}lsearch{CONFDIR/passwd}{$value}{*:*}}}}}{1}{0}}"
-server_set_id = $auth2
-server_prompts = :
-.ifndef AUTH_SERVER_ALLOW_NOTLS_PASSWORDS
-server_advertise_condition = ${if eq{$tls_in_cipher}{}{}{*}}
-.endif
-EOF
- ;;
bk|je)
# avoid accepting mail for invalid users
# https://wiki.dovecot.org/LMTP/Exim
EOF
;;
esac
-
+if $bhost_t; then
+ i /etc/exim4/conf.d/auth/29_exim4-config_auth <<'EOF'
+# from 30_exim4-config_examples
+plain_server:
+driver = plaintext
+public_name = PLAIN
+server_condition = "${if crypteq{$auth3}{${extract{1}{:}{${lookup{$auth2}lsearch{CONFDIR/passwd}{$value}{*:*}}}}}{1}{0}}"
+server_set_id = $auth2
+server_prompts = :
+.ifndef AUTH_SERVER_ALLOW_NOTLS_PASSWORDS
+server_advertise_condition = ${if eq{$tls_in_cipher}{}{}{*}}
+.endif
+EOF
+fi
# ** main daemon use non-default config file
case $HOSTNAME in
# ** $MAIL_HOST|bk|je)
$MAIL_HOST|bk|je)
+ echo|i /etc/exim4/conf.d/router/870_backup_local
+
cat >>/etc/exim4/update-exim4.conf.conf <<EOF
# note: some things we don't set that are here by default because they are unused.
dc_local_interfaces=''
EOF
- i /etc/exim4/conf.d/transport/30_backup_maildir <<EOF
-# modified debian maildir transport
-backup_maildir:
- driver = appendfile
- directory = /bu/mnt
- delivery_date_add
- envelope_to_add
- return_path_add
- maildir_format
- directory_mode = 0700
- mode = 0644
- mode_fail_narrower = false
- # this makes it so if the directory is unmounted, messages stay in the queue
- create_directory = false
-EOF
+ # note on backups: I used to do an automatic sshfs and restricted
+ # permissions to a specific directory on the remote server, /bu/mnt,
+ # which required using a dedicated user, but realized smtp will be
+ # more reliable and less fuss. If I ever need that again, see the
+ # history of this file, and bum in brc2.
i /etc/exim4/conf.d/router/890_backup_copy <<EOF
### router/900_exim4-config_local_user
#################################
# todo, it would be nice to save sent email too,
-# but its not so important, they still exist in my head.
+# but its not so important, they still exist in my head
+
+backup_redir:
+driver = redirect
+domains = +local_domains
+# b is just an arbirary short string
+data = b@eximbackup.b8.nz
+# note, to test this, i could temporarily allow testignore.
+# alerts avoids potential mail loop. root is already
+# redirected earlier, so that is just being overly cautious.
+local_parts = ! root : ! testignore : ! alerts
+unseen
+
backup_copy:
- driver = accept
- domains = +local_domains
- local_parts = ! root : ! testignore
- # uncomment this when testing, comment the above line
- #local_parts = ! root : testignore
- transport = backup_maildir
- cannot_route_message = Unknown user
- local_part_suffix = +*
- local_part_suffix_optional
- unseen
- user = bu
+driver = manualroute
+domains = eximbackup.b8.nz
+transport = backup_remote
+ignore_target_hosts = ${HOSTNAME}wg.b8.nz
+# note changes here also require change in passwd.client
+route_list = * eximbackup.b8.nz
+same_domain_copy_routing = yes
+no_more
+EOF
+
+
+ i /etc/exim4/conf.d/transport/30_backup_remote <<'EOF'
+backup_remote:
+ driver = smtp
+ multi_domain
+.ifndef IGNORE_SMTP_LINE_LENGTH_LIMIT
+ message_size_limit = ${if > {$max_received_linelength}{998} {1}{0}}
+.endif
+ hosts_require_auth = *
+ hosts_try_auth = *
+ return_path = alerts@iankelling.org
+ envelope_to_add
+ # manual return path because we dont want it to be the envelope sender
+ # we got not the one we are using in this smtp transport
+ headers_add = "Return-path: $sender_address"
+.ifdef REMOTE_SMTP_SMARTHOST_HOSTS_AVOID_TLS
+ hosts_avoid_tls = REMOTE_SMTP_SMARTHOST_HOSTS_AVOID_TLS
+.endif
+.ifdef REMOTE_SMTP_SMARTHOST_HOSTS_REQUIRE_TLS
+ hosts_require_tls = REMOTE_SMTP_SMARTHOST_HOSTS_REQUIRE_TLS
+.endif
+.ifdef REMOTE_SMTP_SMARTHOST_TLS_VERIFY_CERTIFICATES
+ tls_verify_certificates = REMOTE_SMTP_SMARTHOST_TLS_VERIFY_CERTIFICATES
+.endif
+.ifdef REMOTE_SMTP_SMARTHOST_TLS_VERIFY_HOSTS
+ tls_verify_hosts = REMOTE_SMTP_SMARTHOST_TLS_VERIFY_HOST
+.endif
+.ifdef REMOTE_SMTP_HEADERS_REWRITE
+ headers_rewrite = REMOTE_SMTP_HEADERS_REWRITE
+.endif
+.ifdef REMOTE_SMTP_HELO_DATA
+ helo_data=REMOTE_SMTP_HELO_DATA
+.endif
+.ifdef TLS_DH_MIN_BITS
+tls_dh_min_bits = TLS_DH_MIN_BITS
+.endif
+.ifdef REMOTE_SMTP_SMARTHOST_TLS_CERTIFICATE
+tls_certificate = REMOTE_SMTP_SMARTHOST_TLS_CERTIFICATE
+.endif
+.ifdef REMOTE_SMTP_SMARTHOST_PRIVATEKEY
+tls_privatekey = REMOTE_SMTP_SMARTHOST_PRIVATEKEY
+.endif
+.ifdef REMOTE_SMTP_TRANSPORTS_HEADERS_REMOVE
+ headers_remove = REMOTE_SMTP_TRANSPORTS_HEADERS_REMOVE
+.endif
EOF
+
# this avoids some error. i cant remember what. todo:
# test it out and document why/if its needed.
i /etc/exim4/host_local_deny_exceptions <<'EOF'
echo|i /etc/exim4/conf.d/router/188_exim4-config_smarthost
echo|i /etc/exim4/conf.d/router/190_exim4-config_fsfsmarthost
echo|i /etc/exim4/conf.d/rcpt_local_acl
+ echo|i /etc/exim4/conf.d/router/890_backup_copy
+
+
+ if $bhost_t; then
+ cat >>/etc/exim4/conf.d/main/000_local <<EOF
+MAIN_TLS_CERTIFICATE = /etc/exim4/certs/$wghost/fullchain.pem
+MAIN_TLS_PRIVATEKEY = /etc/exim4/certs/$wghost/privkey.pem
+# so we can maintiain the originals of the backups.
+# we wouldnt want this if we were dealing with any other
+# local deliveries, but we sent all others to the smarthost
+# which then strips the headers.
+envelope_to_remove = false
+return_path_remove = false
+EOF
+ fi
# catches things like cronjob email
i /etc/exim4/conf.d/router/880_universal_forward <<'EOF'
echo | /a/exe/cedit nn /etc/hosts || [[ $? == 1 ]]
echo | /a/exe/cedit mail /etc/dnsmasq-servers.conf || [[ $? == 1 ]]
- cat >>/etc/exim4/update-exim4.conf.conf <<EOF
-# If theres like a temporary problem where mail gets sent to
+ if $bhost_t; then
+ i /etc/exim4/conf.d/transport/30_backup_maildir <<EOF
+# modified debian maildir transport
+backup_maildir:
+ driver = appendfile
+ directory = /bu/md
+ delivery_date_add
+ # note, no return path or envelope added
+ maildir_format
+ directory_mode = 0700
+ mode = 0644
+ mode_fail_narrower = false
+ user = $u
+EOF
+
+ i /etc/exim4/conf.d/router/870_backup_local <<EOF
+### router/900_exim4-config_local_user
+#################################
+
+backup_local:
+ debug_print = "R: local_user for \$local_part@\$domain"
+ driver = accept
+ domains = eximbackup.b8.nz
+ transport = backup_maildir
+EOF
+
+
+ wgholeip=$(sed -rn 's/^ *Address *= *([^/]+).*/\1/p' /etc/wireguard/wghole.conf)
+ cat >>/etc/exim4/update-exim4.conf.conf <<EOF
+dc_other_hostnames='eximbackup.b8.nz'
+dc_local_interfaces='127.0.0.1;::1;$wgholeip'
+EOF
+ else
+ cat >>/etc/exim4/update-exim4.conf.conf <<EOF
+# Note: If theres like a temporary problem where mail gets sent to
# one of these hosts, if exim isnt listening, it will be a temporary error
# instead of a permanent 5xx.
dc_local_interfaces='127.0.0.1;::1'
+EOF
+ fi
+ cat >>/etc/exim4/update-exim4.conf.conf <<EOF
dc_eximconfig_configtype='smarthost'
dc_smarthost='$smarthost'
EOF
hostname -f |i /etc/mailname
-
cat >>/etc/exim4/update-exim4.conf.conf <<EOF
# The manpage incorrectly states this will do header rewriting, but
# that only happens if we have dc_hide_mailname is set.
# for now. It looks like a dns failure.
#5-59/5 * * * * root mailtest-check |& log-once -1 mailtest-check
#0 * * * * root mailtest-check slow |& log-once -1 mailtest-slow
-*/5 * * * * root mailtest-check slow |& log-once -12 mailtest-check
+*/5 * * * * root timeout 290 mailtest-check slow |& log-once -12 mailtest-check
EOF
m sudo rsync -ahhi --chown=root:root --chmod=0755 \
/b/ds/mailtest-check /b/ds/check-remote-mailqs /usr/local/bin/