Wednesday, January 13, 2016

Email server using amavisd-new fails with (!)DENIED ACCESS from IP 1.2.3.4, policy bank ''

I have used ClamAV and Spamassassin for many years. I've had a less experience with Amavis (now amavisd-new), but I've decided to give it a try with a new mail server deployment I've been working on. As a reference for my install, I relied on the documentation provided by Amavis for integration with Postfix as well as a somewhat-outdated but still-relevant walkthrough published by CentOS. Prior to integration with amavisd, Postfix worked fine. Similarly, I had no issues with Spamassassin on its own.

But once I finished my install of amavisd-new, things quickly went wrong. Attempting to send messages to accounts hosted on my email server resulted in the following chaing of errors in my maillog:

Jan 13 18:17:34 hostname amavis[31578]: Net::Server: 2016/01/13-18:17:34 CONNECT TCP Peer: "[192.168.1.1]:40209" Local: "[127.0.0.1]:10024"
Jan 13 18:17:34 hostname amavis[31578]: loaded base policy bank
Jan 13 18:17:34 hostname amavis[31578]: lookup_ip_acl (inet_acl) arr.obj: key="192.168.1.1", no match
Jan 13 18:17:34 hostname amavis[31578]: (!)DENIED ACCESS from IP 192.168.1.1, policy bank ''

Just as background, the system this article refers to is an AWS EC2 virtual machine, running CentOS 7 with Postfix v2.10.1, Dovecot v2.2.10 and Roundcube version 1.1.3; the trouble I experienced should be relevant to integrating amavis with other MTAs and operating systems, though - so if you encounter the same issue I did its worth giving this a try, particularly as I did not find this method in any of the many forum posts on this topic. For the purposes of this article, also assume that the firewall just works and is not filtering any relevant traffic (you should have already checked your firewall settings anyway).

For readers not familiar with EC2, by default linux machines are assigned two network interfaces - a loopback interface named lo which is assigned 127.0.0.0/8, and a second interface eth0 which is assigned a private IP address from Amazon's pool. Ordinarily, Amazon takes care of the routing that turns that private IP to the public IP used to communicate with the world. During the installation, my email server was setup to listen on 0.0.0.0, so that it can easily accept local connections from 127.0.0.1 or connections from the world through eth0, which let's say is 192.168.1.1. All of this is very basic stuff; there's no load balancing going on here and services arent divided among multiple servers.

I also setup amavis services to use the default TCP ports: 10024 for the amavisd-new client and 10025 for the smtp server that amavis-new uses to reroute emails once its done with them. Test connections using telnet to both ports worked fine immediately following installation:

# telnet localhost 10024
Trying ::1...
Connected to localhost.
Escape character is '^]'.
220 [::1] ESMTP amavisd-new service ready
EHLO localhost
250-[::1]
250-VRFY
250-PIPELINING
250-SIZE
250-ENHANCEDSTATUSCODES
250-8BITMIME
250-SMTPUTF8
250-DSN
250 XFORWARD NAME ADDR PORT PROTO HELO IDENT SOURCE
QUIT
221 2.0.0 [::1] amavisd-new closing transmission channel
Connection closed by foreign host.

# telnet localhost 10025
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 mailserver.domain.ext ESMTP Postfix
EHLO localhost
250-mailserver.domain.ext
250-PIPELINING
250-SIZE 30720000
250-VRFY
250-ETRN
250-STARTTLS
250-AUTH PLAIN
250-AUTH=PLAIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
QUIT
221 2.0.0 Bye
Connection closed by foreign host.

Note how connections fail when attempting to establish a connection through the socket through 10025 - this is also the result of using a default amavisd configuration. Connecting to postfix itself through the socket presents no issues:

# telnet localhost 25
Trying ::1...
Connected to localhost.
Escape character is '^]'.
220 mailserver.domain.ext ESMTP Postfix

Anyway, talking through the socket isn't necessary to get things working, so I will save that for the next amavisd article.

So when I started looking around for a solution to this in the forums, there was a lot of hemming and hawing about settings that were completely irrelevant to the problem, and occasionally some mention of settings thought could have conceivably had something to do with my problem, but didn't in my case. Of the latter type that I encountered, I was fairly convinced that this had something to do with the @mynetworks setting in the primary amavisd-new configuration file amavisd.conf (this setting is for the most part the same as the mynetworks setting in Postfix's main.cf file, except it uses Perl syntax, like adding @ before lists). By default, @mynetworks looks like this:

@mynetworks = qw( 127.0.0.0/8 [::1] [FE80::]/10 [FEC0::]/10
10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 );

But that's a little bit wider than I needed. I tried a whole bunch of different combinations of things. I added the subnet from each one of my network interfaces and even my public IP just for the hell of it, but that did little to change things besides occasionally breaking my ability to connect to the amavis client or server entirely. Ultimately, I settled on this:

@mynetworks = qw( 127.0.0.0/8 [::1] );

But that didn't fix anything. What isn't mentioned in any of the troubleshooting articles or install walkthroughs I saw was how to actually modify amavisd-new's ACL. After all, the error message I encountered very frankly says that inbound emails are failing as a result of the involved connection's failure to be found in amavisd's ACL:

Jan 13 18:17:34 hostname amavis[31578]: Net::Server: 2016/01/13-18:17:34 CONNECT TCP Peer: "[192.168.1.1]:40209" Local: "[127.0.0.1]:10024"
Jan 13 18:17:34 hostname amavis[31578]: loaded base policy bank
Jan 13 18:17:34 hostname amavis[31578]: lookup_ip_acl (inet_acl) arr.obj: key="192.168.1.1", no match
Jan 13 18:17:34 hostname amavis[31578]: (!)DENIED ACCESS from IP 192.168.1.1, policy bank ''

So what this means is that Postfix is receiving an email from eth0, which is assigned IP 192.168.1.1. Postfix than establishes a connection with amavisd from 192.168.1.1 to the localhost entry. Some enterprising dunce decided that its possible to cheat the need to change the ACL by changing the interface that amavisd listens to. This can be accomplished by assigned a value like the following to amavisd.conf:

$inet_socket_bind = 192.168.1.1;

This does not work; at least it didn't on my system. It might work with some additional work, but additional work is stupid. Modifying the ACL is smart. You can modify the ACL by adding a line resembling the following one to amavisd.conf:

@inet_acl = qw( 192.168.1.1 127.0.0.1 [::1] );

Note how with this ACL I only add IP addresses (or sockets) that I want to exempt. Amavisd defaults to exempting everybody; this isn't a blacklist. Also, you don't want @inet_acl to be identical to your @mynetworks setting. In my case, I do not include either 192.168.1.1 or its entire subnet in @mynetworks because @mynetworks represents subnets that we always treat as local delivery. Remember - NATing is handled by AWS on my server, so even though my eth0 has a "local" IP address, it does not mean that emails handled by that IP will be local. Quite the opposite, in fact.

So that's it, after opening up the ACL amavisd routes email correctly (although I still have some more testing to do in order to confirm that Spam Assassin is actually functioning correctly).

Hope this helps - good luck!

No comments:

Post a Comment