[Debian-uk] BATV and exim notes (not quite a HOWTO)

Stephen Gran steve at lobefin.net
Wed, 29 Oct 2008 12:01:19 +0000


--IS0zKkzwUGydFO0o
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

Hi all,

A couple of people asked on IRC this morning for a howto for BATV and
exim.  Since I have such a setup running, I'll outline what I've done
with a few notes.

BATV works by assigning a token to an email address, and then using that
token and the current time to create a hash for envelope munging of
outgoing mail.  By checking for this envelope munging on mail coming
back in, you can reliably tell that this is not a legitimate DSN for
mail you sent (or an address probe for mail you sent).

The major caveat is mail forwarders - if you have an address that you
use as the envelope of outbound mail (sgran@debian.org, eg), you'll need
to skip the BATV checks for those hosts which will be forwarding you
mail, as they will be doing address rewriting and won't attach a BATV
token, even to DSNs.  In the example below, these hosts that forward
mail to me have been assigned to the hostgroup +no_check_hosts.

So, all that being said, figure out a method to store your tokens - I
keep mine in postgres, and look them up in a view that returns=20

 --------------------------------------
|  email              |  secret        |
 --------------------------------------
| steve@lobefin.net   | reallytoughpw  |
 --------------------------------------

So I use the following constructs in the main section of the config:

PRVSCHECK_SQL =3D ${lookup pgsql{SELECT secret FROM view_user_secrets WHERE=
 email=3D'${quote_pgsql:$prvscheck_address}'}{$value}}
addresslist batv_users =3D ${lookup pgsql{SELECT email FROM view_user_secre=
ts}{$value}}

You could also use flat files, or whatever suits your fancy.

This next bit goes fairly early in the rcpt acl to throw away bad mail
with fairly low overhead.

acl_check_rcpt:

  # Bounces: drop unsigned addresses for BATV senders - the : construct
  # for senders matches the NULL envelope used for bounces.  This could
  # be expanded to test for additional things like mailer-daemon or
  # postfix's default, double-bounce, but so far I haven't bothered.
  deny   message       =3D This address does not send an unsigned reverse p=
ath.
         senders       =3D :
         !hosts        =3D +no_check_hosts
         recipients    =3D +batv_users

  # Bounces: In case of prvs-signed address, check signature.  If we
  # didn't sign it, reject it.
  deny   message       =3D Invalid reverse path signature.
         senders       =3D :
         !hosts        =3D +no_check_hosts
         condition     =3D ${prvscheck {$local_part@$domain}{PRVSCHECK_SQL}=
{1}}
         !condition    =3D $prvscheck_result

  # And again for hosts that forward to us - in this, we just add a
  # header that we can filter aside.
  warn   message       =3D X-Joe-Job: maybe
         senders       =3D :
         hosts         =3D +no_check_hosts
         recipients    =3D +batv_users

  warn   message       =3D X-Joe-Job: maybe
         senders       =3D :
         hosts         =3D +no_check_hosts
         condition     =3D ${prvscheck {$local_part@$domain}{PRVSCHECK_SQL}=
{1}}
         !condition    =3D $prvscheck_result


This needs to be one of the early local routers, so that it comes before=20
the normal local delivery routers but after remote delivery (no need to
attempt to decrypt prvs tokens for remote users :)

routers:

# We need to remove the BATV token on it's way in so that normal routing
# of an address succeeds - this will turn prvs/steve=3Dwibble605@lobefin.ne=
t=20
# back into steve@lobefin.net
batv_redirect:
  debug_print =3D "R: batv_redirect for $local_part@$domain"
  driver =3D redirect
  data =3D ${prvscheck {$local_part@$domain}{PRVSCHECK_SQL}}
  domains =3D +local_delivery
  local_part_suffix =3D +*
  local_part_suffix_optional

Order does not matter for transports - in Debian you will already
have a transport named remote_smtp, so just make sure it has the
return_path modification below.

transports:

# We need to set the BATV token on the way out.  This will change the
# envelope from steve@lobefin.net into prvs/steve=3Dwibble605@lobefin.net
remote_smtp:
  debug_print =3D "T: remote_smtp for $local_part@$domain"
  return_path =3D ${prvs {$return_path}{${lookup pgsql{SELECT secret FROM v=
iew_user_secrets WHERE email=3D'${quote_pgsql:$sender_address}'}{$value}fai=
l}}}
  driver =3D smtp

Cheers,
--=20
 --------------------------------------------------------------------------
|  Stephen Gran                  | Fine's Corollary:  Functionality breeds |
|  steve@lobefin.net             | Contempt.                               |
|  http://www.lobefin.net/~steve |                                         |
 --------------------------------------------------------------------------

--IS0zKkzwUGydFO0o
Content-Type: application/pgp-signature; name="signature.asc"
Content-Description: Digital signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)

iD8DBQFJCFCPSYIMHOpZA44RAholAJ4+tTTcNHQ3qvrXDxj466tr18nmUQCfbDet
97witvyHNGBVzxXuafNKkG8=
=B2R+
-----END PGP SIGNATURE-----

--IS0zKkzwUGydFO0o--