Add SRS to Exim in Debian without recompile

SRS and Exim is still in an experimental phase and the library used is dead upstream, so the Debian-Bug got refused: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=702358

Marco Gaiarin did a lot of basic research, how to fix this issue with stock Debian tools and posted it on the Exim Mailing List: https://lists.exim.org/lurker/message/20150725.134657.b8720d98.en.html

Sadly Marco never posted a full setup, but I managed with his help to do the setup and he gave me permission to post this how-to:

Step 1: Install srs tool:

apt-get install srs

Step 2: Create /etc/exim4/srs-secret file:

The SRS program needs a custom secret file for the generation of the SRS signatures, so we need to build one.

(tr -c -d '0123456789abcdefghijklmnopqrstuvwxyz,.;:-_#+*!$%' /dev/null;echo) > /etc/exim4/srs-secret

This will generate a srs-secret file with 96 chars taken from /dev/urandom.

Step 3: Specify srs Globals in /etc/exim4/conf.d/main/00_globals file:

I have my Exim setup in Debian split into several files. I add my local configs into a special file /etc/exim4/conf.d/main/00_globals. For the SRS setup I have added the following lines:

#####
# SRS
#####

# Define SRS Secret File
SRS_SECRETFILE = /etc/exim4/srs-secret

# SRS Hash Length
SRS_HASHLENGTH = 8

# SRS Domain
SRS_DOMAIN = ${lookup mysql {SELECT domain FROM domain WHERE domain=\'${quote_mysql:$domain}\';}{$value}}
SRS_REWRITE_DOMAIN = ${lookup mysql {SELECT domain FROM domain WHERE domain=\'${quote_mysql::$domain}\';}{$value}}

# Because the hash may contain the '/' character, the local part character restriction have to be relaxed:
CHECK_RCPT_LOCAL_LOCALPARTS = ^[.] : ^.*[@%!|`#&?]

# Add more logging for SRS
MAIN_LOG_SELECTOR == MAIN_LOG_SELECTOR +address_rewrite +return_path_on_delivery +sender_on_delivery

# (updated 2016-05-25: Not needed)
## SRS Header Rewrite
#REMOTE_SMTP_HEADERS_REWRITE = *@* "${if eq{${domain::$h_errors_to::}}{SRS_REWRITE_DOMAIN}{$h_errors_to::}{fail}}" s

# Remove some headers...
SRS_HEADERS_REMOVE = DKIM-Signature:X-CNFS-Analysis:Received

I have virtual eMail addresses stored in MySQL and therefore the SRS_DOMAIN line has a mysql-lookup in it. If you have only one domain, specify it there. Watch the ‘s’ at the end of REMOTE_SMTP_HEADERS_REWRITE. It specifies that the Sender should be rewritten.

SRS_DOMAIN and SRS_REWRITE_DOMAIN differ only in the single-colon and double-colon. But the router needs the quote_mysql macro with one colon and the transport (where the rewrite happens) needs a double colon.

Step 4: Add SRS routers:

To have SRS now working, we need new routers exim: /etc/exim4/conf.d/router/999_srs_router

#####
# SRS
#####
.ifdef SRS_SECRETFILE
srs_bounce:
debug_print = "R: srs_bounce for $local_part@$domain"
driver = redirect
domains = +local_domains
allow_fail
allow_defer
local_part_prefix = srs0+ : srs0- : srs0= : srs1+ : srs1- : srs1=
caseful_local_part
address_data = ${run{/bin/sh -c "/usr/bin/srs --reverse --secretfile=SRS_SECRETFILE --hashlength=SRS_HASHLENGTH \
${local_part_prefix}${local_part}@${domain} 2> /dev/null"}\
{${quote_local_part:${local_part:$value}}@${domain:$value}}{:fail: Invalid SRS address}}
data = $address_data

virtual_forward_director_srs:
debug_print = "R: virtual_forward_director_srs for $local_part@$domain"
driver = redirect
domains = +local_domains
condition = ${if and{{!eq{${domain:$sender_address}}{SRS_DOMAIN}}{!eq{$sender_address}{}}}}
address_data = ${run{/bin/sh -c "/usr/bin/srs --secretfile=SRS_SECRETFILE --hashlength=SRS_HASHLENGTH --alias=SRS_DOMAIN $sender_address 2>/dev/null"}\
{${quote_local_part:${local_part:$value}}@${domain:$value}}{:fail: SRS failure}}
errors_to = $address_data
headers_add = "X-SRS: Sender address rewritten from <$sender_address> to <$address_data> by $primary_hostname."
headers_remove = SRS_HEADERS_REMOVE
data = ${lookup mysql {SELECT forward FROM MYSQL_EMAILTABLE WHERE domain='${quote_mysql:$domain}' AND local_part='${quote_mysql:$local_part}' AND forward != ''}{$value}}
check_ancestor
.endif

virtual_forward_director:
debug_print = "R: virtual_forward_director for $local_part@$domain"
driver = redirect
domains = +local_domains
data = ${lookup mysql {SELECT forward FROM MYSQL_EMAILTABLE WHERE domain='${quote_mysql:$domain}' AND local_part='${quote_mysql:$local_part}' AND forward != ''}{$value}}
check_ancestor

Jeremy Harris has found a solution without using any external utilities: https://bugs.exim.org/show_bug.cgi?id=1649#c3

Leave a Reply

Your email address will not be published. Required fields are marked *