This tool is design to verify effectiveness of antispam solutions. It send lots of crafted emails, which are more or less compliant with email standards and contains more or less elements which can suggest that this is a spam.
spamtest have two elements:
- main script to send emails from operator host
- postfix server in docker, which is configured as a MSA to 'proxy' emails from operator to target MTA server
Postfix is required because:
- ISP of operator can block port 25, which sometimes is needed to send emails
- operator has a better chance to change rDNS on VPS (where postfix can be deployed) than on his host / gateway
Main script, spam_tester.py, has two phases of constructing emails
- mangling
SMTP FROM
andbody From
headers - creating emails with different contantes
Headers are mangling in this way: (attacker is a synonym of operator)
[smtp_from] | [body_from] |
---|---|
victim_domain_email | victim_domain_email |
victim_domain_email | attacker_* |
attacker_* | victim_domain_email |
attacker_* | attacker_* |
Where attacker_* are:
- operator domain without DKIM and SPF (e.g. none.spamtest.operator-domain.com)
- operator domain with only DKIM (e.g. dkim.spamtest.operator-domain.com)
- operator domian with only SPF (e.g. spf.spamtest.operator-domain.com)
- operator domain with both DKIM and SPF (e.g. dkim-spf.spamtest.operator-domain.com)
Side note:
- DKIM check
body From:
- SPF check
SMTP FROM
spam_tester.py create:
- simply, plain email where content is in text form
- email with content in html
- email with both text and html content
- email with both text and html content, additionaly with big image
- email with both text and html content, additionaly with big image and executable (windows exe file) as a attachment
- email with both text and html content, additionaly with big image and MS Excel spreedsheet with macros as a attachemnt
- email with both text and html content, additionaly with big image and link to executable (windows exe file)
- email with both text and html content, additionaly with big image and link to some page
- email with both text and html content, additionaly with big image and encrypted zip archive
Just install dependencies from requirements file:
pip install -r requirements.txt
spam_tester.py is a Python 3 script, so you need that version of Python (tested on 3.7.7).
For each domain which will have DKIM records, i.e.:
- dkim.spamtest.operator-domain.com
- dkim-spf.spamtest.operator-domain.com
We need generate private and public keys:
openssl genrsa -out dkim.spamtest.operator-domain.com.key 2048
openssl rsa -in dkim.spamtest.operator-domain.com.key -pubout -out dkim.spamtest.operator-domain.com.pub
openssl genrsa -out dkim-spf.spamtest.operator-domain.com.key 2048
openssl rsa -in dkim-spf.spamtest.operator-domain.com.key -pubout -out dkim-spf.spamtest.operator-domain.com.pub
spam_tester.py will be looking for filename exactly like body From:
header with .key suffix.
You can configure spam_tester.py in file spam_tester.conf, which looks like this:
[victim]
reciptien_name = John Smith
reciptien_email = john.smith@example.com
[attacker]
attacker_name = Uncle Fred
victim_domain_email = uncle.fred@example.com
attacker_domain_none_email = uncle.fred@none.ex4mple.com
attacker_domain_dkim_email = uncle.fred@dkim.ex4mple.com
attacker_domain_spf_email = uncle.fred@spf.ex4mple.com
attacker_domain_dkim_spf_email = uncle.fred@dkim-spf.ex4mple.com
[mailtrap]
enabled = yes
user = some_user
pass = some_pass
[custom_msa]
enabled = yes
address = 127.0.0.1
user = msa_user
pass = msa_pass
[victim]
section is about target email, to which we will send our mails. reciptien_email
is used as a value of SMTP RCPT
and body To:
headers, where reciptien_name
in body To:
header.
[attacker]
section configure which addresses will be used as a SMTP FROM
and body From:
headers. In this example:
- domain example.com is domain which belong to target, operator cannot configure it
- domain ex4mple.com is domain which belong to operator, which he can configure and add new record. In this README it is operator-domain.com
[mailtrap]
section enable or disable sending emails to mailtrap.io, where you can debug your emails. user
and pass
are credentials to authenticate in this service.
[custom-msa]
section is our postfix-msa container, with parameters to connect and to enable it. If both mailtrap and custom_msa are enabled, then mailtrap will have higher priority and mails will be sent to that service. In out examples in this document, address of custom_msa is mail.spamtest.operator-domain.com
To simplify deployment, docker container has been prepared with preconfigured Postfix to act as a MSA. To build image below command can be performed:
docker build --pull --rm -f "path\to\spamtest\docker\Dockerfile" -t postfix-msa:latest --build-arg HOSTNAME=mail --build-arg DOMAIN=spamtest.operator-domain.com spamtest "path\to\spamtest\docker"
Then, container can be run:
docker run --rm -it --name spamtest -p 587:587 --hostname mail --domainname spamtest.operator-domain.com
Where:
--build-arg HOSTNAME=mail
and--hostname mail
is hostname of docker container--build-arg DOMAIN=spamtest.operator-domain.com
and--domainname spamtest.operator-domain.com
is domain of docker container Both will be in rDNS and it will be use in comunication with target MTA server as mail.spamtest.operator-domain.com
After run a container, it will display output from syslog - connections to postfix.
You need to add this DNS records (assume, that operator-domain.com is your domain):
dkim-spf.spamtest 60 IN MX 10 dkim-spf.spamtest.operator-domain.com.
dkim-spf.spamtest 60 IN A POSTFIX-MSA_EXTERNAL_IP
dkim-spf.spamtest 60 IN TXT "v=spf1 a mx ip4:POSTFIX-MSA_EXTERNAL_IP ~all"
dkim.spamtest 60 IN MX 10 dkim.spamtest.operator-domain.com.
dkim.spamtest 60 IN A POSTFIX-MSA_EXTERNAL_IP
mail.spamtest 60 IN A POSTFIX-MSA_EXTERNAL_IP
none.spamtest 60 IN MX 10 none.spamtest.operator-domain.com.
none.spamtest 60 IN A POSTFIX-MSA_EXTERNAL_IP
spf.spamtest 60 IN MX 10 spf.spamtest.operator-domain.com.
spf.spamtest 60 IN A POSTFIX-MSA_EXTERNAL_IP
spf.spamtest 60 IN TXT "v=spf1 a mx ip4:POSTFIX-MSA_EXTERNAL_IP ~all"
value._domainkey.dkim-spf.spamtest 60 IN TXT ( "v=DKIM1;h=sha256;k=rsa;p=PUBLIC KEY;" )
value._domainkey.dkim.spamtest 60 IN TXT ( "v=DKIM1;h=sha256;k=rsa;p=PUBLIC KEY;" )
Where:
- POSTFIX-MSA_EXTERNAL_IP - external IP address of VPS on which docker witch postfix-msa container is running
- PUBLIC KEY - content of files dkim/dkim-spf.spamtest.operator-domain.com.pub, but without lines started with '---'. Also you need to concatenate all lines to one line, then this one line add to DNS record.
In VPS configuration (propably some web page from VPS provider) set this rDNS (Reverse DNS): mail.spamtest.operator-domain.com
Just execute spam_tester.py - simply, isn't it? :)