diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3835bc0 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +dkim.key diff --git a/Dockerfile b/Dockerfile index 9d08af2..e0d324b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,7 +15,7 @@ RUN echo mail > /etc/hostname; \ # Install packages RUN apt-get update && \ - apt-get install -y --no-install-recommends postfix mailutils busybox-syslogd curl ca-certificates && \ + apt-get install -y --no-install-recommends postfix mailutils busybox-syslogd opendkim curl ca-certificates && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* @@ -26,14 +26,18 @@ RUN DIR=$(mktemp -d) && cd ${DIR} && \ tar -xzf s6.tar.gz -C / && \ rm -rf ${DIR} -# Configure Postfix +# Configure Postfix / dkim RUN postconf -e smtpd_banner="\$myhostname ESMTP" && \ # Enable submission postconf -Me submission/inet="submission inet n - - - - smtpd" && \ # Cache spool dir as template cp -a /var/spool/postfix /var/spool/postfix.cache && \ # Remove snakeoil certs - rm -f /etc/ssl/private/ssl-cert-snakeoil.key /etc/ssl/certs/ssl-cert-snakeoil.pem + rm -f /etc/ssl/private/ssl-cert-snakeoil.key /etc/ssl/certs/ssl-cert-snakeoil.pem && \ + rm -f /etc/opendkim.conf && \ + mkdir /etc/opendkim/ + +COPY opendkim.conf.sh /etc/ COPY s6 /etc/s6/ diff --git a/Makefile b/Makefile index b1a19f1..aed8db6 100644 --- a/Makefile +++ b/Makefile @@ -12,3 +12,10 @@ run: @echo "Running ${ID} @ smtp://${IP}" @docker attach ${ID} @docker kill ${ID} + +run-dkim: + $(eval ID := $(shell docker run -d --hostname mail.example.com -e MAILNAME=mail.example.com -e DKIM_DOMAINS=foo.example.com,bar.example.com -e USE_DKIM=yes -v `pwd`/dkim.key:/etc/opendkim/dkim.key ${docker_tag})) + $(eval IP := $(shell docker inspect --format '{{ .NetworkSettings.IPAddress }}' ${ID})) + @echo "Running ${ID} @ smtp://${IP}" + @docker attach ${ID} + @docker kill ${ID} diff --git a/README.md b/README.md index 9a2a34a..e68f0d6 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ Postfix SMTP Relay. Fairly simple drop-in container for SMTP relaying. Use wherever a connected service -requires SMTP sending capabilities. +requires SMTP sending capabilities. Supports TLS out of the box and DKIM (if enabled and configured). ## Environment Variables @@ -14,16 +14,24 @@ requires SMTP sending capabilities. TLS parameters: -- `USETLS` - Enable opportunistic TLS. default `yes` -- `TLSKEY` - Default `/etc/ssl/private/ssl-cert-snakeoil.key` -- `TLSCRT` - Default `/etc/ssl/certs/ssl-cert-snakeoil.pem` -- `TLSCA` - Default '' +- `USE_TLS` - Enable opportunistic TLS. Default `yes` +- `TLS_KEY` - Default `/etc/ssl/private/ssl-cert-snakeoil.key` +- `TLS_CRT` - Default `/etc/ssl/certs/ssl-cert-snakeoil.pem` +- `TLS_CA` - Default '' -NB. The snake-oil certificate will generated on start if required. +NB. A "snake-oil" certificate will generated on start if required. + +DKIM parameters: + +- `USE_DKIM` - Enable DKIM. Default `no` +- `DKIM_KEYFILE` - DKIM Keyfile location. Default `/etc/opendkim/dkim.key` +- `DKIM_DOMAINS` - Domains to sign. Default to MAILNAME. Multiple domains will use the same key and selector. +- `DKIM_SELECTOR` - DKIM key selector. Default `mail`. `._domainkey.` is used for resolving the public key in DNS. ## Volumes -No volumes are defined. If you want persistent spool storage then mount `/var/spool/postfix` outside of the container. +No volumes are defined. If you want persistent spool storage then mount +`/var/spool/postfix` outside of the container. ## Test email diff --git a/opendkim.conf.sh b/opendkim.conf.sh new file mode 100755 index 0000000..cae6f8d --- /dev/null +++ b/opendkim.conf.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash + +set -e + +OUTPUT='/etc/opendkim.conf' + +# exit if config already exists +[ -f "${OUTPUT}" ] && exit 0 + +# defaults +: ${DKIM_KEYFILE:='/etc/opendkim/dkim.key'} +: ${DKIM_DOMAINS:="${MAILNAME}"} +: ${DKIM_SELECTOR:='mail'} + +# Checks +if [ ! -f "${DKIM_KEYFILE}" ]; then + echo "dkim >> Error: DKIM_KEYFILE ${DKIM_KEYFILE} not found" + # shutdown everything + s6-svscanctl -t /etc/s6 + exit 128 +else + echo "dkim >> Setting mode and owner on $DKIM_KEYFILE" + chown opendkim:opendkim ${DKIM_KEYFILE} + chmod 400 ${DKIM_KEYFILE} +fi + +# Status Output +echo "dkim >> Setting DKIM_KEYFILE to $DKIM_KEYFILE" +echo "dkim >> Setting DKIM_DOMAINS to $DKIM_DOMAINS" +echo "dkim >> Setting DKIM_SELECTOR to $DKIM_SELECTOR" + +# Render the dkim config +cat > ${OUTPUT} <> USE_DKIM = ${USE_DKIM}. Not starting opendkim." + s6-svc -d $(pwd) + exit +fi + +# Render config template +/etc/opendkim.conf.sh + +# exit cleanly +trap "{ /usr/sbin/service opendkim stop; }" EXIT + +# start postfix +/usr/sbin/service opendkim start + +sleep 10 # wait for startup + +# watch for opendkim exit +while kill -0 $(pidof opendkim) 2>/dev/null; do + sleep 1 +done diff --git a/s6/postfix/run b/s6/postfix/run index 6aac635..6664511 100755 --- a/s6/postfix/run +++ b/s6/postfix/run @@ -14,49 +14,59 @@ fi # Defaults if [ -z "$MAILNAME" ]; then - echo "Error: MAILNAME not specified" + echo "postfix >> Error: MAILNAME not specified" exit 128 fi if [ -z "$MYNETWORKS" ]; then MYNETWORKS='127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16' - echo "Warning: MYNETWORKS not specified, allowing all private IPs" + echo "postfix >> Warning: MYNETWORKS not specified, allowing all private IPs" fi if [ -z "$SIZELIMIT" ]; then SIZELIMIT=15728640 # 10Meg with headroom fi +# DKIM +if [ "${USE_DKIM}" == "yes" ]; then + # TODO s6-svwait for dkim + echo "postfix >> Enabling dkim milter" + postconf -e milter_protocol="6" + postconf -e milter_default_action="accept" + postconf -e smtpd_milters="inet:localhost:8891" + postconf -e non_smtpd_milters="inet:localhost:8891" +fi + # TLS -: ${USETLS:='yes'} -: ${TLSKEY:='/etc/ssl/private/ssl-cert-snakeoil.key'} -: ${TLSCRT:='/etc/ssl/certs/ssl-cert-snakeoil.pem'} -: ${TLSCA:=''} +: ${USE_TLS:='yes'} +: ${TLS_KEY:='/etc/ssl/private/ssl-cert-snakeoil.key'} +: ${TLS_CRT:='/etc/ssl/certs/ssl-cert-snakeoil.pem'} +: ${TLS_CA:=''} -echo "Setting smtpd_use_tls to $USETLS" -postconf -e smtpd_use_tls="$USETLS" +echo "postfix >> Setting smtpd_use_tls to $USE_TLS" +postconf -e smtpd_use_tls="$USE_TLS" -if [ "${USETLS}" == "yes" ]; then - if [ "${TLSKEY}" == "/etc/ssl/private/ssl-cert-snakeoil.key" ]; then - echo "Generating snakeoil SSL cert" +if [ "${USE_TLS}" == "yes" ]; then + if [ "${TLS_KEY}" == "/etc/ssl/private/ssl-cert-snakeoil.key" ]; then + echo "postfix >> Generating snakeoil SSL cert" dpkg-reconfigure -f noninteractive ssl-cert fi - echo "Setting smtpd_tls parameters" - postconf -e smtpd_tls_key_file="$TLSKEY" - postconf -e smtpd_tls_cert_file="$TLSCRT" - postconf -e smtpd_tls_CAfile="$TLSCA" + echo "postfix >> Setting smtpd_tls parameters" + postconf -e smtpd_tls_key_file="$TLS_KEY" + postconf -e smtpd_tls_cert_file="$TLS_CRT" + postconf -e smtpd_tls_CAfile="$TLS_CA" fi # Configure Postfix General parameters -echo "Setting mailname to $MAILNAME" +echo "postfix >> Setting mailname to $MAILNAME" echo $MAILNAME > /etc/mailname postconf -e myhostname="$MAILNAME" postconf -e mydestination="$MAILNAME" -echo "Setting mynetworks to $MYNETWORKS" +echo "postfix >> Setting mynetworks to $MYNETWORKS" postconf -e mynetworks="$MYNETWORKS" -echo "Setting message_size_limit to $SIZELIMIT" +echo "postfix >> Setting message_size_limit to $SIZELIMIT" postconf -e message_size_limit="$SIZELIMIT" # exit cleanly diff --git a/s6/syslogd/run b/s6/syslogd/run index 730e81a..ce9dfd5 100755 --- a/s6/syslogd/run +++ b/s6/syslogd/run @@ -5,6 +5,6 @@ # Defaults : ${LOGOUTPUT:='/dev/stdout'} -echo "Setting syslogd output to ${LOGOUTPUT}" +echo "syslogd >> Setting syslogd output to ${LOGOUTPUT}" exec syslogd -n -O ${LOGOUTPUT} -S