Your Zimbra is backscattering? This is what may help you:
Update 2018-08-21:
Before doing anything else, make sure you don’t have a CatchAll defined for your domain. To do so:
su - zimbra
zmprov gd example.com | grep zimbraMailCatchAllAddress
# should be empty. NOT @example.com
zmprov gd example.com | grep zimbraMailCatchAllForwardingAddress
# should be empty. NOT @example.com
zmprov gd example.com | grep zimbraMailTransport
# should be lmtp:zimbra.example.com:7025 . NOT e.g. smtp:relayhost.com:587
If any of this is not as should be, then change it:
zmprov md domain.com zimbraMailCatchAllAddress ""
zmprov md domain.com zimbraMailCatchAllForwardingAddress ""
zmprov md domain.com zimbraMailTransport lmtp:zimbra.example.com:7025
Note that in the last line, you need to give the FQDN of your Zimbra server, instead of zimbra.example.com.
You may also read the Zimbra wiki about catchalls.
Original article:
A Zimbra 8.0 Server (on Ubuntu) was backscattering. Unfortunately Zimbra servers cannot use the postfix setting
smtpd_reject_unlisted_sender=yes
when an alias domain is setup. Everybody says it is easy, just install the policyd as a recipient_restriction and that’s it. All you need to do is:
su - zimbra
zmlocalconfig -e postfix_enable_smtpd_policyd=yes
zmprov mcf +zimbraMtaRestriction "check_policy_service unix:private/policy"
zmmtactl stop
zmmtactl start
Unfortunately, this did not work for me with Zimbra 8.0. The server was still backscattering.
First, I enabled verbose output for the policyd. To do so, open /opt/zimbra/postfix/conf/master.cf.in (the .in is important) in a texteditor and search for this part:
%%uncomment LOCAL:postfix_enable_smtpd_policyd%%policy unix - n n - - spawn
%%uncomment LOCAL:postfix_enable_smtpd_policyd%% user=zimbra argv=/usr/bin/perl /opt/zimbra/libexec/zmpostfixpolicyd
Add a -v ad the end of the command:
%%uncomment LOCAL:postfix_enable_smtpd_policyd%%policy unix - n n - - spawn
%%uncomment LOCAL:postfix_enable_smtpd_policyd%% user=zimbra argv=/usr/bin/perl /opt/zimbra/libexec/zmpostfixpolicyd -v
Then (as zimbra user), recreate the master.cf and restart postfix with these commands:
zmmtactl stop
zmmtactl start
Now when a mail is received (from an external sender), you will see output like this in your mail log (on Debian/Ubuntu: /var/log/mail.log):
/opt/zimbra/libexec/zmpostfixpolicyd[29326]: Attribute: ccert_fingerprint=
/opt/zimbra/libexec/zmpostfixpolicyd[29326]: Attribute: sasl_method=
/opt/zimbra/libexec/zmpostfixpolicyd[29326]: Attribute: sasl_sender=
/opt/zimbra/libexec/zmpostfixpolicyd[29326]: Attribute: size=3428
/opt/zimbra/libexec/zmpostfixpolicyd[29326]: Attribute: helo_name=[...]
/opt/zimbra/libexec/zmpostfixpolicyd[29326]: Attribute: reverse_client_name=[...]
/opt/zimbra/libexec/zmpostfixpolicyd[29326]: Attribute: queue_id=
/opt/zimbra/libexec/zmpostfixpolicyd[29326]: Attribute: encryption_cipher=AECDH-AES256-SHA
/opt/zimbra/libexec/zmpostfixpolicyd[29326]: Attribute: encryption_protocol=TLSv1.2
/opt/zimbra/libexec/zmpostfixpolicyd[29326]: Attribute: etrn_domain=
/opt/zimbra/libexec/zmpostfixpolicyd[29326]: Attribute: ccert_subject=
/opt/zimbra/libexec/zmpostfixpolicyd[29326]: Attribute: request=smtpd_access_policy
/opt/zimbra/libexec/zmpostfixpolicyd[29326]: Attribute: protocol_state=RCPT
/opt/zimbra/libexec/zmpostfixpolicyd[29326]: Attribute: stress=
/opt/zimbra/libexec/zmpostfixpolicyd[29326]: Attribute: recipient=does-not-exist@example.com
/opt/zimbra/libexec/zmpostfixpolicyd[29326]: Attribute: sasl_username=
/opt/zimbra/libexec/zmpostfixpolicyd[29326]: Attribute: ccert_pubkey_fingerprint=
/opt/zimbra/libexec/zmpostfixpolicyd[29326]: Attribute: instance=7289.556db23f.b6b7d.0
/opt/zimbra/libexec/zmpostfixpolicyd[29326]: Attribute: protocol_name=ESMTP
/opt/zimbra/libexec/zmpostfixpolicyd[29326]: Attribute: encryption_keysize=256
/opt/zimbra/libexec/zmpostfixpolicyd[29326]: Attribute: recipient_count=0
/opt/zimbra/libexec/zmpostfixpolicyd[29326]: Attribute: ccert_issuer=
/opt/zimbra/libexec/zmpostfixpolicyd[29326]: Attribute: sender=[...]
/opt/zimbra/libexec/zmpostfixpolicyd[29326]: Attribute: client_name=[...]
/opt/zimbra/libexec/zmpostfixpolicyd[29326]: Attribute: client_address=[...]
/opt/zimbra/libexec/zmpostfixpolicyd[29326]: Recipient Domain: example.com
/opt/zimbra/libexec/zmpostfixpolicyd[29326]: Recipient userid: does-not-exist
/opt/zimbra/libexec/zmpostfixpolicyd[29326]: Action: dunno
If you see these logs, then zmpostfixpolicyd is set up correctly in postfix. If you don’t, check the postfix configuration.
But the policy daemon always returned “dunno”, even if the recipient did not exist. Therefore, I looked into the perl code of the policy daemon (/opt/zimbra/libexec/zmpostfixpolicyd):
The original code includes this part:
if (lc(($ldap->get_values("zimbraDomainType"))[0]) eq "alias") {
my $robject = ($ldap->get_values("zimbraMailCatchAllForwardingAddress"))[0];
syslog $syslog_priority, "Real Domain: %s", $robject if $verbose;
@attrs=('1.1');
$mesg = $ldap->search_s(
"",
LDAP_SCOPE_SUBTREE,
"(&(|(zimbraMailDeliveryAddress=$user"."$robject)(zimbraMailDeliveryAddress=$daddr)(zimbraMailAlias=$user".
"$robject)(zimbraMailAlias=$daddr)(zimbraMailCatchAllAddress=$user"."$robject)(zimbraMailCatchAllAddress=$robject)".
"(zimbraMailCatchAllAddress=$daddr))(zimbraMailStatus=enabled))",
\@attrs,
0,
$result
);
$ent = $ldap->first_entry();
$ldap->unbind;
if ($ent != 0) {
return "dunno";
} else {
return "reject 5.1.1 Mailbox unavailable";
}
} else {
$ldap->unbind;
return "dunno";
}
So basically, this code only rejects mail to recipients for alias-domains, but accepts all mail to domains that are not alias-domains. I adjusted the code as follows:
if (lc(($ldap->get_values("zimbraDomainType"))[0]) eq "alias") {
my $robject = ($ldap->get_values("zimbraMailCatchAllForwardingAddress"))[0];
syslog $syslog_priority, "Real Domain: %s", $robject if $verbose;
@attrs=('1.1');
$mesg = $ldap->search_s(
"",
LDAP_SCOPE_SUBTREE,
"(&(|(zimbraMailDeliveryAddress=$user"."$robject)(zimbraMailDeliveryAddress=$daddr)(zimbraMailAlias=$user".
"$robject)(zimbraMailAlias=$daddr)(zimbraMailCatchAllAddress=$user"."$robject)(zimbraMailCatchAllAddress=$robject)".
"(zimbraMailCatchAllAddress=$daddr))(zimbraMailStatus=enabled))",
\@attrs,
0,
$result
);
$ent = $ldap->first_entry();
$ldap->unbind;
if ($ent != 0) {
syslog $syslog_priority, "Existing Alias-Recipient";
return "dunno";
} else {
syslog $syslog_priority, "Non-Existing Alias-Recipient";
return "reject 5.1.1 Mailbox unavailable";
}
} else {
@attrs=('1.1');
$mesg = $ldap->search_s(
"",
LDAP_SCOPE_SUBTREE,
"(&(|(zimbraMailDeliveryAddress=$user"."$domain)(zimbraMailDeliveryAddress=$daddr)(zimbraMailAlias=$user".
"$domain)(zimbraMailAlias=$daddr)(zimbraMailCatchAllAddress=$user"."$domain)(zimbraMailCatchAllAddress=$domain)".
"(zimbraMailCatchAllAddress=$daddr))(zimbraMailStatus=enabled))",
\@attrs,
0,
$result
);
$ent = $ldap->first_entry();
$ldap->unbind;
if ($ent != 0) {
syslog $syslog_priority, "Existing Recipient";
return "dunno";
} else {
syslog $syslog_priority, "Non-Existing Recipient";
return "reject 5.1.1 Mailbox unavailable";
}
}
Then I restarted postfix as a zimbra user with:
zmmtactl stop
zmmtactl start
And finally, the policy daemon rejected mails to unexisting recipients 🙂
/opt/zimbra/libexec/zmpostfixpolicyd[5799]: Recipient Domain: example.com
/opt/zimbra/libexec/zmpostfixpolicyd[5799]: Recipient userid: does-not-exist
/opt/zimbra/libexec/zmpostfixpolicyd[5799]: Non-Existing Recipient
/opt/zimbra/libexec/zmpostfixpolicyd[5799]: Action: reject 5.1.1 Mailbox unavailable
postfix/smtpd[5791]: NOQUEUE: reject: RCPT from [...]: 554 5.1.1 <does-not-exist@example.com>: Recipient address rejected: Mailbox unavailable; [...]
Please use the described solution with care. It is my workaround, it is working on the system in question. It might not work with another setup. If you use it, test thoroughly if only the correct mails get rejected.
A Zimbra update will overwrite the zmpostfixpolicyd code and thus revert the change, so you might need to readjust the code after an update.
This drove me nuts and I hope this information is of help for somebody. Please comment if you have a better solution or find the described solution useful.