Background
Some of our Zimbra customers are complaining for authenticated user can customizing FROM header which can lead to fraud email. this issue can be reproduce by using thunderbird once compose an email as following picture.
or by using this script, change variables username, password, fake_from and to_addr based on your environment.
Solution
I created customized milter engine using python milter library for my workaroud with following features:
- the filter triggered when “MAIL FROM:” in smtp command is not match with “FROM:” email’s header.
- “MAIL FROM:” and “FROM:” be can allowed as long as it’s account alias, canonical address or catch all address (this can be customized).
- Some exception (whitelist) using regex patterns.
- Allowing sender send as distribution list (if allowed using grants sendAsDistList).
- Daemonized using supervisord
Installation
note: Following steps are executed in each your MTA servers.
Some packages dependencies are in EPEL repository, so install it’s repo first
yum install epel-release
Download dependencies
yum install python-pymilter python-ldap supervisor git-core
Clone repository
cd /opt git clone https://github.com/iomarmochtar/zmbr_check_sender
Create configuration from template
cd zmbr_check_sender/etc cp config_dist.ini config.ini vim config.ini
Adjust configuration based on your environment, for basic setup just change main.domains for list of domain that will be filtered, ldap.url for ldap your zimbra ldap host and zimbra.pwd for your zimbra ldap admin password that can be seen using command (as zimbra user).
zmlocalconfig -s ldap_root_password
Append supervisord configuration.
cat daemon.ini >> /etc/supervisord.conf
Run the service and make sure it run on boot.
service supervisord start chkconfig supervisord on
You can check using telnet if the service are listed on port 5000.
telnet localhost 5000
Configure zimbra for using it as milter.
su - zimbra zmprov ms `zmhostname` zimbraMtaSmtpdMilters inet:127.0.0.1:5000 zmprov ms `zmhostname` zimbraMilterServerEnabled TRUE zmmtactl restart
Do the test by using thunderbird or script tes_sasl.py in folder test
Debug
You can see verbosely what this milter engine do by set configuration main.debug to true then restart the supervisord service.
all activity can be seen by grep it’s name process in mail log.
tail -f /var/log/zimbra.log | grep mail_from_check
Summary
This is only my workaround related to this issue, really hope this “hardening” will be default in Zimbra’s builtin milter for preventing fraud email which some of our customer cannot tolerate it.
One also needs to run:
zmprov ms `zmhostname` zimbraMilterServerEnabled TRUE
Or Zimbra will not load the change
LikeLike
sorry i forgot to add it, thank you for reminding
LikeLike
zmprov ms `zmhostname` zimbraMilterBindPort 5000
Then it works
LikeLike
This will make a port conflict between customized milter with zimbra builtin milter (which listen in port 7026 as default)
LikeLike
When I do not add the zimbraMilterBindPort 5000 it will show something in the log as connection refused to ip:7026. So it tries to connect to the built-in Milter, that is not running.
I re-tried it on a different install and w/o setting the zimbraMilterBindPort to 5000 it does not work. zmmtactl restart and such do not seem to give a port conflict.
LikeLike
if you set zimbraMilterBindPort to 5000 there will be duplicated on postfix’s milters config. you can check it by using this command (as zimbra user)
postconf smtpd_milters
zimbra milters will be active after service after mta service restarted.
LikeLike
One more little detail to make it even nicer:
cp daemon.ini /etc/supervisord.d/check_sender_access.ini
This is a little easier to maintain, as opposed to adding it to the supervisord.conf. If there are future changes.
LikeLike
i was considering for that, but since there is no “include” feature in old supervisord version (which shipped in Centos 6.x) so i tend to append the configuration in main config file which supported both in old and new version of supervisord.
LikeLike
Hi,
Zimbra allows force a match between the from in the header and the sasl user. https://wiki.zimbra.com/wiki/Enforcing_a_match_between_FROM_address_and_sasl_username_8.5
Despite the confusing use of “alternate” address in that wiki, exception db will be only needed for those who use an email address that does not belong to your domain and thus, no delegation to send as or in behalf of was made.
May I ask if you do what you do because you did not know about this native Zimbra feature or is there any other reason?
Thanks for sharing your knowledge!!!
Sebas
LikeLike
You must know the differentiate MAIL FROM envelope address and FROM header first.
of course i have do all in zimbra wiki’s steps and it not solving the problem. also there was ticket related to this issue in zimbra bugzilla (https://bugzilla.zimbra.com/show_bug.cgi?id=108036) with unanswered question, so that’s why i searching for my own solution.
better if you have zimbra you may try it by test using thunderbird or testing script that i have provided.
LikeLike
Hi how to implement it for ubuntu server?
LikeLike
just adjusting for supervisord package in ubuntu.
LikeLike
Hi this is great thank you very much. the things is we are getting from these email from different domain is there any way to filter every domain ?
LikeLike
do you mean for internal zimbra domain ?
LikeLike
No external domains (gmail,yahoomail etc)
LikeLike
yes it can still work, i just update the script but forgot to update in github. but just now i just push it to the repo (github) you can check it.
LikeLike
Hi Thank you now it’s working but I’m getting below error for some users.
” milter-reject: END-OF-MESSAGE from unknown”
Do you have any idea for this ?
LikeLike
you may enable debug as mentioned above then grab some useful log here, is it internal user that sending to outside ?
LikeLike
Ok will do , Yes this is happening when internal users sending multiple attachment for outside.
LikeLike