bley
is an intelligent greylisting daemon for Postfix (and Exim).
It uses various test (incl. RBL and SPF) to decide whether a sender should be greylisted or not, thus mostly eliminating the usual greylisting delay while still filtering most of the spam.
Package repository hosting is graciously provided by Cloudsmith
# mkdir -p /etc/apt/keyrings/
# curl 'https://dl.cloudsmith.io/public/bley/bley/gpg.31A9C34356A3F75F.key' -o /etc/apt/keyrings/bley.asc
# echo 'deb [signed-by=/etc/apt/keyrings/bley.asc] https://dl.cloudsmith.io/public/bley/bley/deb/debian sid main' > /etc/apt/sources.list.d/bley.list
bley
is written in Python using the
Twisted framework. It uses
pyspf for SPF validation and
publicsuffix2 for checking
of domains against the PublicSuffix.org
database. Database interaction is implemented via
sqlite3 for SQLite,
psycopg2 for PostgreSQL and
mysqlclient for MySQL.
Unpack the tarball (or clone the git tree), adjust bley.conf.example
,
rename it to bley.conf
and run python -m bley.cli
.
Unpack the tarball (or clone the git tree), run python setup.py build
followed by python setup.py install
, copy /etc/bley/bley.conf.example
to /etc/bley/bley.conf
, adjust it to your needs (see CONFIGURATION below)
and run /usr/bin/bley
.
Basically you just have to configure the database:
dbtype = pgsql for PostgreSQL, mysql for MySQL or sqlite3 for SQLite
dbhost = the host where the database runs on (usually localhost)
dbport = the port where the database runs on (can be left unset for
the default 5432 for PostgreSQL and 3306 for MySQL)
dbuser = the name of the database user
dbpass = the password of the database user
dbname = the name (or path in case of SQLite) of the database
dbpath = you can also set the path separately and load ${dbpath}/${dbname}
After that you can point your Postfix to bley
as a
policy server by
adding check_policy_service inet:127.0.0.1:1337
to your
smtpd_recipient_restrictions
in main.cf
.
bley
will be working now, but you probably would like to tune it more
for your needs (esp. the used DNWLs and DNSBLs, the greylisting times
and the hit thresholds).
Sometimes, you want to bind bley
to something else than 127.0.0.1:1337
,
this can be achieved with the following two parameters.
listen_addr = 127.0.0.1
listen_port = 1337
As bley
is designed to be a deamon, it will write a pid file and a log file.
The locations of the two can be configured with the following parameters.
pid_file = bley.pid
log_file = bley.log
Setting log_file
to the special word syslog
will make bley
log to
syslog
instead of a file, using the mail
facility.
If you want to inform the sender about the greylisting, you can adjust the message sent via
reject_msg = greylisted, try again later
The DNSWLs and DNSBLs bley
uses for its tests can be set via
dnsbls = ix.dnsbl.manitu.net
dnswls = list.dnswl.org
Thresholds define how many sub-checks have to hit, to trigger a feature (whitelisting in case of dnswl, greylisting in case of dnsbl and rfc).
dnswl_threshold = 1
dnsbl_threshold = 1
rfc_threshold = 2
How long should a sender be greylisted, when should we allow him in at the very last and how long should he have to wait more, if he retries to early (all in minutes)?
greylist_period = 29
greylist_max = 720
greylist_penalty= 10
After how many days should old entries be deleted from the database? Entries of senders who have not verified to be "good" should be purged earlier.
purge_days = 40
purge_bad_days = 10
SPF (Sender Policy Framework) checks can be turned off. SPF Best Guess should always be turned off.
use_spf = 1
use_spf_guess = 0
If you use Exim instead of Postfix, set this to 1. It will automatically close connections after the decision is sent. While Postfix supports checking multiple senders over the same connections, Exim does not. In fact it even closes the sending part of the socket as soon all details have been transmitted.
exim_workaround = 0
In some situations, it is useful to be able to whitelist senders or recipients. This can be done by providing lists as files (syntax is postgrey compatible).
whitelist_recipients_file = ./whitelist_recipients
whitelist_clients_file = ./whitelist_clients
This file contains a list of recipients who are excluded from greylisting. One entry per line. An entry can be either a full email address, the local part, a domain name or a regular expression:
user@example.com
postmaster@
example.com
/app.*example/
This file contains a list of clients who are excluded from greylisting. One entry per line. An entry can be either an IP adress, a subnet, a domain name or a regular expression.
192.0.2.200/30
example.net
/sender.*example/
The first check is, of course, whether our database already knows about the
(ip, sender, recipient)
tuple. If it does, act accordignly, otherways
continue with the other checks.
Check whether the sender IP address is listed in the configured DNSWLs and DNSBLs. If either one reaches the configured threshold, the mail is considered good or bad, depending on which threshold was reached.
While the following checks are not all about stricktly implementing the RFC, all of them try to identify suboptimal behaviour of the sending MTA, which often indicates a spammer.
Check whether the name used in HELO/EHLO
matches the reverse DNS entry.
Check whether the hostname looks like a dynamic one.
People usually do not send mail themself "over the Internet" (and local mail should not be checked by a policy daemon). Spammers on the other hand, often try to bypass address-checks by using the same address as sender and receiver.
The Sender Policy Framework allows domain owners to define which servers are allowed to send mail using their domain and which are not.
bley
includes a small graphing utility called bleygraph
.
It will analyze the bley_log
table of the database, and plot a few graphs
using matplotlib.
There is not much configuration possible for bleygraph
: the database
settings are taken from the bley
section of bley.conf
and the path
for the graph output (destdir
) is the only setting in the bleygraph
section of the configuration file.
For exim4, we can install the following ACL:
# Check policy service "bley", using the postfix policy service protocol.
defer log_message = greylisted host $sender_host_address
set acl_m0 = request=smtpd_access_policy\n\
protocol_state=RCPT\n\
protocol_name=${uc:$received_protocol}\n\
helo_name=$sender_helo_name\n\
client_address=$sender_host_address\n\
client_name=$sender_host_name\n\
sender=$sender_address\n\
recipient=$local_part@$domain\n\
\n
set acl_m0 = ${sg\
{${readsocket{inet:127.0.0.1:1337}{$acl_m0}{5s}{}{action=DUNNO}}}\
{action=}\
{}\
}
message = ${sg{$acl_m0}{^\\w+\\s*}{}}
condition = ${if eq{${uc:${substr{0}{5}{$acl_m0}}}}{DEFER}{true}{false}}
# Warn if delayed
warn message = ${sg{$acl_m0}{^\\w+\\s*}{}}
condition = ${if eq{${uc:${substr{0}{7}{$acl_m0}}}}{PREPEND}{true}{false}}
On a Debian system using split configuration for Exim, this can be placed in a file, for instance /etc/exim4/greylist.bley.conf
, and included from the RCPT acl by setting the CHECK_RCPT_LOCAL_ACL_FILE
variable to point to that file, in /etc/exim4/conf.d/main/01_local-variables
.
# /etc/exim4/conf.d/main/01_local-variables
CHECK_RCPT_LOCAL_ACL_FILE = /etc/exim4/greylist.bley.conf