This file README.postfix is part of the amavisd-new distribution, which can be found at http://www.ijs.si/software/amavisd/ Author: Mark Martinec Last updated: 2003-11-21 How to use amavisd-new with Postfix *********************************** A quick recipe for the impatient first. Your Postfix must not be ancient, it must support parameter content_filter. Check for the purpose of this parameter in ./README_FILES/FILTER_README of the Postfix distribution. This file was revised in postfix-1.1.9-20020512, and again in postfix 20030120, you may want to read the latest version. For compatibility with previous versions of amavisd the choice of default port numbers is 10024 and 10025, in contrast to 10025 and 10026 as used in FILTER_README examples. We are assuming that Postfix is already installed, configured and is working as expected. 1. Install and run amavisd (as explained in INSTALL - just the daemon, no helper programs amavis(.c) or amavisd-milter(.c) are needed) For the first time it is best to start it interactively and keep it attached to the terminal: # su - vscan #(or whatever username you decided to use, e.g. amavis) $ /usr/local/sbin/amavisd debug From another window check that it is listening on a local SMTP port 10024 (default): --> $ telnet 127.0.0.1 10024 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. 220 [127.0.0.1] ESMTP amavisd-new service ready --> quit 221 Bye Connection closed by foreign host. 2. With a text editor add to the Postfix master.cf file the following two entries, e.g. near the end of the file: smtp-amavis unix - - y/n - 2 smtp -o smtp_data_done_timeout=1200 -o disable_dns_lookups=yes (the '-o disable_dns_lookups=yes' is no longer needed since Postfix 2.0) 127.0.0.1:10025 inet n - y/n - - smtpd -o content_filter= -o local_recipient_maps= -o relay_recipient_maps= -o smtpd_restriction_classes= -o smtpd_client_restrictions= -o smtpd_helo_restrictions= -o smtpd_sender_restrictions= -o smtpd_recipient_restrictions=permit_mynetworks,reject -o mynetworks=127.0.0.0/8 -o strict_rfc821_envelopes=yes -o smtpd_error_sleep_time=0 -o smtpd_soft_error_limit=1001 -o smtpd_hard_error_limit=1000 Of all the options specified above in the second entry, the one that is essential is the '-o content_filter=' . Change the 'y/n' to either 'y' or 'n', depending on how you prefer the smtp and smtpd postfix services to run - either chroot-ed, or not. See your other (normal) smtp and smtpd postfix services in this file and use the same setting here. If you have an entry like 'vscan unix - n n - 2 pipe user=vscan ...' from an old amavisd installation, you don't need it anymore and it may be removed. Keeping it does no harm. 3. Do a 'postfix reload', check its log file for any complaints, and test if it is listening on port 10025: --> $ telnet 127.0.0.1 10025 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. 220 yourhost.example.com ESMTP Postfix --> quit 221 Bye Connection closed by foreign host. 4. If you want, simulate a mail sent to amavisd and see if it gets delivered via Postfix to its recipient. Try first with a simple and clean message, then with an EICAR test virus pattern which should be recognized by all virus scanners (unless you have them disabled or not installed): --> $ telnet 127.0.0.1 10024 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. 220 [127.0.0.1] ESMTP amavisd-new service ready --> MAIL FROM: 250 2.1.0 Sender test@example.com OK --> RCPT TO: 250 2.1.5 Recipient postmaster OK --> DATA 354 End data with . --> Subject: test1 --> --> test1 --> . *** 250 2.6.0 Ok, id=31859-01, from MTA: 250 Ok: queued as 90B7F16F --> MAIL FROM: 250 2.1.0 Sender test@example.com OK --> RCPT TO: 250 2.1.5 Recipient postmaster OK --> DATA 354 End data with . --> Subject: test2 - virus test pattern --> --> X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H* --> . you should get one of the following replies, depending on your $final_virus_destiny and *virus_lovers* settings in amavisd.conf: *** 550 5.7.1 Message content rejected, id=16968-01 - VIRUS: EICAR-AV-Test *** 250 2.5.0 Ok, but 1 BOUNCE *** 250 2.7.1 Ok, discarded, id=16984-01 - VIRUS: EICAR-AV-Test *** 250 2.6.0 Ok, id=17041-01, from MTA: 250 Ok: queued as 3F1841A5F5 --> QUIT 221 2.0.0 [127.0.0.1] (amavisd) closing transmission channel Connection closed by foreign host. You may need/want to use different sender and recipient addresses. The test pattern must be entered exactly, starting at the beginning of the line (without indentation). Depending on the settings in amavisd.conf, the sender (test@example.com) and the virus administrator should have been sent a (non-)delivery status notification, the second message quarantined, and the first message must have been successfully delivered to the recipient. See the log that is scrolling on the terminal (as setup at step 1) and check for possible problems. 5. Tell Postfix to start forwarding all mail it receives to amavisd-new for content inspection. To the Postfix main.cf file add a line: content_filter = smtp-amavis:[127.0.0.1]:10024 either with a text editor, or preferably using a shell command: # postconf -e 'content_filter = smtp-amavis:[127.0.0.1]:10024' 6. Do a 'postfix reload' and watch the logs - both the Postfix logs, and the amavisd log file (on the screen or wherever you have it directed). If you get in trouble, you only need to undo the step 5 and reload postfix. New mail will no longer be tagged with content filter routing. NOTE: the messages that have been received while 'content_filter' was set, will still try to get delivered to your old setting of content_filter, and will wait in the queue until successful or deleted - or until you do: postsuper -r ALL; postfix reload If all is fine, you may abort the process running 'amavisd debug', and start amavisd without a 'debug' option, making it detach and daemonize. There is no need to stop or restart Postfix. This completes the integration of amavisd and Postfix. It uses the SMTP (or LMTP) protocol for Postfix->amavisd, and SMTP protocol for amavisd->Postfix communication. This is the fastest and recommended method, and simplest to set up. ALTERNATIVE: If you have a recent Postfix version such as 2.0, and amavisd-new-20021116 or younger, Postfix can be told to feed mail to amavisd via LMTP protocol instead of SMTP. This brings multi-session mail transaction capability and per-recipient status responses. Just replace the service name (last item) 'smtp' with 'lmtp' in the master.cf entry: vvvv smtp-amavis unix - - y/n - 2 lmtp -o smtp_data_done_timeout=1200 It works with earlier version of Postfix as well, but there are one or two minor bugs in the Postfix lmtp client code (parsing a LMTP port number, and unnecessarily lowercasing the addresses), so it is easiest to stick to the fresh Postfix version. Option 'max_use=10' should be added to main.cf to limit the session reuse. OPTIONAL: I also like to set up an e-mail addresses with Postfix to receive all quarantined viruses, so that a mailer will deal with storing (or forwarding) them, and you don't even have to set up a quarantine directory directly accessible to amavisd. Here is one way of doing it, but see 'local(8)' Postfix man page for more options. This method of quarantining may be the only method available if amavisd is running chrooted and quarantine should be located outside of chroot jail. To the aliases file add an entry for an e-mail address, e.g. 'infected', either to forward its mail to some place, or do a local delivery to a file or directory, e.g.: infected: /var/spool/mail/infected (append a '/' if you prefer Maildir style mailbox), then run 'newaliases' (or 'postalias /etc/postfix/aliases'). In your amavisd.conf file specify: $virus_quarantine_to = 'infected@'; # forward to MTA for delivery Reload amavisd (amavisd reload) if it is already running, to make it re-read its config file, and check the log file. All set! Send some infected mail and watch it appear at the specified mailbox. ---------------------------------------------------------------------------- The next section is a heavily commented setup that can be directly appended to the Postfix master.cf file instead of the item (2.) above, in case you need finer control or better understanding. It describes a Postfix setup with two cleanup services, as recommended by the new Postfix 2.0.3 ./README_FILES/FILTER_README . Here is an overall picture (adapted from FILTER_README to match port numbers and service name as traditionally used by amavisd-new): ....................................... : Postfix : ----->smtpd \ : : -pre-cleanup-\ /local----> ---->pickup / -queue- : : -cleanup-/ | \smtp-----> : bounces/ ^ v : : and locally | v : : forwarded smtpd smtp-amavis : : messages 10025 | : ...........................|........... ^ | | v ............|.............................. : | $inet_socket_port=10024 : : | : : $forward_method='smtp:127.0.0.1:10025' : : $notify_method ='smtp:127.0.0.1:10025' : : : : amavisd-new : ........................................... To be able to get largely unmodified e-mail addresses to content filter (avoiding virtual_alias_maps before the content filter), one needs to use two cleanup services: - add new service 'pre-cleanup'; - (optionally) add options to existing service 'cleanup'; - add option cleanup_service_name=pre-cleanup to existing services 'smtp' and 'pickup'; as described below. # Append this to the master.cf Postfix file and edit to will. # It defaults to the standard settings as described in README.postfix . # # Instruct Postfix content filtering to SEND all mail TO amavisd: # =============================================================== # # By default amavisd will listen to both protocols (SMTP/LMTP over TCP, # as well as amavis helper protocol on a Unix socket). The older method # using the helper program amavis.c still works, but is not recommended, and # is not described here. To disable amavisd-new unnecessarily listening on a # Unix socket, comment out the assignment to $unix_socketname in amavisd.conf. # # NOTE1: match number of sending Postfix processes (the '2' below) with # $max_servers in amavisd.conf. Two or three per CPU should be enough. # Going beyond 10 just wastes memory and does not help with throughput. # NOTE2: point the 'content_filter' hostname part to where amavisd is running, # and match the port number with $inet_socket_port in amavisd.conf, e.g: # content_filter = smtp-amavis:my-amavisd-server.example.com:10024 # NOTE3: you should restrict amavisd to only accept connections from the # authorized Postfix host(s) by the @inet_acl access list in # the amavisd.conf file, and/or by binding to specific interface, e.g.: # $inet_socket_bind = '127.0.0.1'; # limit bind to loopback interface # NOTE4: set the chroot field the same (y/n) as for your regular smtp service; # NOTE5: set $child_timeout (in amavisd.conf) to a shorter time than # the Postfix parameter smtp_data_done_timeout - see rfc1047. # The value in '-o smtp_data_done_timeout=1200' must always be larger # (with some margin) than the value of $child_timeout in amavisd.conf # NOTE6: the option '-o disable_dns_lookups=yes' is recommended for reducing # latency with Postfix versions older than 2.0, but specify the IP # address and not the DNS name in the content_filter specification # (thanks to Victor Duchovni for the suggestion). # # The "smtp-amavis" transport is a dedicated instance of the "smtp" # delivery agent for injecting messages into the SMTP/LMTP content filter. # Using a dedicated "smtp" or "lmtp" transport allows one to tune it # for the specific task of delivering mail to a local content filter # (low latency, low concurrency, throughput dependent on predictably # low latency). # #smtp-amavis unix - - n - 2 lmtp smtp-amavis unix - - n - 2 smtp -o smtp_data_done_timeout=1200 #some more ideas: # -o disable_dns_lookups=yes # -o smtp_line_length_limit=0 # -o notify_classes=protocol,resource,software # -o fallback_relay=backup-filter.example.com:10024 # NOTE: # To provide a backup content filter in case the primary fails, # either use the '-o fallback_relay' as above, or use a DNS name and # provide multiple MX records for it. See /etc/postfix/sample-smtp.cf # and smtp(8) man page for details. # from amavisd back to Postfix: # ============================= # # variant 1A: via SMTP, same host - or see 1B for multihost setup # In amavisd.conf choose the host running Postfix and its port number, e.g.: # $notify_method = 'smtp:127.0.0.1:10025'; # $forward_method = 'smtp:127.0.0.1:10025'; # $relayhost_is_client = 0; # This is the SMTP listener that receives filtered messages from the # content filter. It *MUST* clear the content_filter parameter to avoid loops. # # This "smtpd" uses the normal cleanup service which is also used # for bounces and for internally forwarded mail. # # Disable all access control other than insisting on connections from one # of the IP addresses of the host. This is typically overkill, but can reduce # resource usage, if the default restrictions use lots of tables. # # NOTE: set the chroot field the same (y/n) as for your regular smtpd service # # 127.0.0.1:10025 inet n - n - - smtpd -o content_filter= -o local_recipient_maps= -o relay_recipient_maps= -o smtpd_restriction_classes= -o smtpd_client_restrictions= -o smtpd_helo_restrictions= -o smtpd_sender_restrictions= -o smtpd_recipient_restrictions=permit_mynetworks,reject -o mynetworks=127.0.0.0/8 -o mynetworks_style=host -o strict_rfc821_envelopes=yes #some more ideas: # -o smtpd_data_restrictions= # -o always_bcc=user@example.com # This is the cleanup daemon that handles messages in front of # the content filter. It does header_checks and body_checks (if any), # but does no virtual alias or canonical address mapping, # so that mail comes out of your content filter with the original # recipient addresses still intact. # # Virtual alias or canonical address mapping happens in the second # cleanup phase after the content filter. This gives the content_filter # access to *largely* unmodified addresses for maximum flexibility. # # Note that some sites may specifically want to perform canonical or # virtual address mapping in front of the content_filter. However, # in that case you still have to enable address rewriting in the # after-filter cleanup instance, in order to correctly process # forwarded mail or bounced mail. # # handle both the canonicalization and virtual_alias_maps later # (this will provide content filter with largely unmodified addresses) # pre-cleanup unix n - n - 0 cleanup -o virtual_alias_maps= -o canonical_maps= -o sender_canonical_maps= -o recipient_canonical_maps= -o masquerade_domains= # ... or leave canonicalization in pre-cleanup, but do virtual_alias_maps later # (this is useful if canonicalization is used to map internal e-mail # addresses to external, and you want the content filter to always see # external canonical addresses of local users, both as senders, # and as recipients): # #pre-cleanup unix n - n - 0 cleanup # -o virtual_alias_maps= # This is the normal cleanup daemon. No header or body checks, because # those have already been taken care of by the pre-cleanup service # before the content filter. The normal cleanup instance does all # the virtual alias and canonical address mapping that was disabled # in the pre-cleanup instance before the content filter. # cleanup unix n - n - 0 cleanup -o mime_header_checks= -o nested_header_checks= -o body_checks= -o header_checks= # or use second-stage header checks, to be able to place mail bombs on HOLD # -o header_checks=pcre:/etc/postfix/header_checks2 # Place the following line (without the leading # and space) into file # /etc/postfix/header_checks2, and use the -o header_checks=pcre:... above, # if you need trouble mail (e.g. mail bombs) to be placed on hold by Postfix, # instead of being passed to recipients: # # /^X-Amavis-Hold:/ HOLD # These are the usual input "smtpd" and local "pickup" servers already # present in master.cf. We add an option to select a non-default # cleanup service. # smtp inet n - n - - smtpd -o cleanup_service_name=pre-cleanup pickup fifo n - n 60 1 pickup -o cleanup_service_name=pre-cleanup # variant 1B: via SMTP - with amavisd on a different host, # also good for the case of several MTAs using the same amavisd server. # - re-injection (forwarding) if $forward_method is smtp:... # - notification messages if $notify_method is smtp:... # - quarantine if $virus_quarantine_to contains '@' # In amavisd.conf set port number where Postfix (one or more) is # listening for re-injected mail and notifications, and optionally set # $relayhost_is_client to 1, if you want to have host field in the # $forward_method and $notify_method specification dynamically replaced # (re-injection port number is automatically set to one higher than the # port number on which message came in to amavisd, making possible for # several MTA pairs on the same host to independently use amavisd, e.g. # separately for incoming and outgoing mail). To prevent unauthorized use # of the service you SHOULD restrict the set of IP addresses from which # amavisd is willing to accept mail by specifying authorized Postfix host(s) # with the access list @inet_acl in the amavisd.conf file. Bind must not be # restricted to the loopback interface, so set $inet_socket_bind to undef. # # NOTE1: you SHOULD also restrict Postfix to only accept connections # on port 10025 from the amavisd host by '-o mynetworks = ...' # NOTE2: set the chroot field the same (y/n) as for your regular smtp service. #10025 inet n - n - - smtpd # -o content_filter= # -o local_recipient_maps= # -o relay_recipient_maps= # -o smtpd_restriction_classes= # -o smtpd_client_restrictions= # -o smtpd_helo_restrictions= # -o smtpd_sender_restrictions= # -o smtpd_recipient_restrictions=permit_mynetworks,reject # -o mynetworks=127.0.0.0/8,10.0.0.0/8,192.168.1.1 # -o mynetworks_style=host # -o strict_rfc821_envelopes=yes # -o smtpd_error_sleep_time=0 # -o smtpd_soft_error_limit=1001 # -o smtpd_hard_error_limit=1000 #some more ideas: # -o smtpd_data_restrictions= # -o always_bcc=user@example.com A tip from Wietse Venema (2002-12-12): | If you want to filter inbound SMTP mail only, then: | | /etc/postfix/main.cf: | smtpd_recipient_restrictions = | check_recipient_access hash:/etc/postfix/recipient_access | ...the usual stuff here... | reject_unauth_destination | | /etc/postfix/recipient_access: | my.domain FILTER foo:bar | | That filters all the mail that has at least one recipient in your | domain, and does not filter mail with external recipients only. (comment: the 'foo:bar' is what you would traditionally specify in content_filter option, i.e. smtp-amavis:[127.0.0.1]:10024 ) Since Postfix snapshot 2.0.13-20030706 there is a new parameter 'receive_override_options' that eliminates the need for two cleanup services. See SMTPD(8) man page, and README_FILES/FILTER_README in the Postfix documentation