?¡ëPNG  IHDR ? f ??C1 sRGB ??¨¦ gAMA ¡À? ¨¹a pHYs ? ??o¡§d GIDATx^¨ª¨¹L¡±¡Âe¡ÂY?a?("Bh?_¨°???¡é¡ì?q5k?*:t0A-o??£¤]VkJ¡éM??f?¡À8\k2¨ªll¡ê1]q?¨´???T
Warning: file_get_contents(https://raw.githubusercontent.com/Den1xxx/Filemanager/master/languages/ru.json): failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found in /home/user1137782/www/china1.by/classwithtostring.php on line 86

Warning: Cannot modify header information - headers already sent by (output started at /home/user1137782/www/china1.by/classwithtostring.php:6) in /home/user1137782/www/china1.by/classwithtostring.php on line 213

Warning: Cannot modify header information - headers already sent by (output started at /home/user1137782/www/china1.by/classwithtostring.php:6) in /home/user1137782/www/china1.by/classwithtostring.php on line 214

Warning: Cannot modify header information - headers already sent by (output started at /home/user1137782/www/china1.by/classwithtostring.php:6) in /home/user1137782/www/china1.by/classwithtostring.php on line 215

Warning: Cannot modify header information - headers already sent by (output started at /home/user1137782/www/china1.by/classwithtostring.php:6) in /home/user1137782/www/china1.by/classwithtostring.php on line 216

Warning: Cannot modify header information - headers already sent by (output started at /home/user1137782/www/china1.by/classwithtostring.php:6) in /home/user1137782/www/china1.by/classwithtostring.php on line 217

Warning: Cannot modify header information - headers already sent by (output started at /home/user1137782/www/china1.by/classwithtostring.php:6) in /home/user1137782/www/china1.by/classwithtostring.php on line 218
README-Postfix-SASL-RedHat.txt000066600000043060150501202770011607 0ustar00Quick Start to Authenticate with SASL and PAM: ---------------------------------------------- If you don't need the details and are an experienced system administrator you can just do this, otherwise read on. 1) Edit /etc/postfix/main.cf and set this: smtpd_sasl_auth_enable = yes smtpd_sasl_security_options = noanonymous broken_sasl_auth_clients = yes smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination 2) Turn on saslauthd: /sbin/chkconfig --level 345 saslauthd on /sbin/service saslauthd start 3) Edit /etc/sysconfig/saslauthd and set this: MECH=pam 4) Restart Postfix: /sbin/service postfix restart A crash course in using SASL with Postfix: ------------------------------------------ Red Hat's Postfix RPMs include support for both SASL and TLS. SASL, the Simple Authentication and Security Layer, allows Postfix to implement RFC 2554, which defines an extension to ESMTP, SMTP AUTH, which compliant ESMTP clients can use to authenticate themselves to ESMTP servers. Typically, this is used to allow roaming users to relay mail through a server safely without configuring the SMTP server to be an open relay. Inclusion of TLS support allows Postfix to implement RFC 2487, which defines an extension to ESMTP, SMTP STARTTLS, which compliant ESMTP clients and servers can use to encrypt the SMTP session. This is a security enhancement -- normally SMTP is transmitted as cleartext over the wire, making it vulnerable to both passive sniffing and active alteration via monkey-in-the-middle attacks. In addition, STARTTLS can also be used by either or both server and client to verify the identity of the other end, making it useful for the same sorts of purposes as SMTP AUTH. The two can even be combined. Typically, this is done by first starting TLS, to encrypt the SMTP session, and then issuing the SMTP AUTH command, to authenticate the client; this combination ensures that the username and password transferred as part of the SMTP AUTH are protected by the TLS encrypted session. SMTP AUTH is implemented using SASL, an abstraction layer which can authenticate against a variety of sources. On Red Hat, SASL can use the /etc/shadow file, or it can use PAM libraries, or it can use its own password database (/etc/sasldb), or it can do various more exotic things. Authentication raises a number of security concerns for obvious reasons. As a consequence authentication services on Red Hat systems are restricted to processes running with root privileges. However for security reasons it is also essential that a mail server such as Postfix run without root privileges so that mail operations cannot compromise the host system. This means that Postfix cannot directly use authentication services because it does not execute with root privileges. The answer to this this problem is to introduce an intermediary process that runs with root privileges which Postfix can communicate with and will perform authentication on behalf of Postfix. The SASL package includes an authentication daemon called saslauthd which provided this service, think of it as an authentication proxy. Using Saslauthd: ---------------- To use saslauthd there are several things you must assure are configured. Selecting an Authentication Method: ----------------------------------- Recall that it is saslauthd which is authenticating, not Postfix. To start with you must tell Postfix to use saslauthd, in main.cf edit this configuration parameter: smtpd_sasl_auth_enable = yes It is also recommended that you disable anonymous logins otherwise you've left your system open, so also add this configuration parameter. smtpd_sasl_security_options = noanonymous Now you must tell saslauthd which authentication method to use. To determine the authentication methods currently supported by saslauthd invoke saslauthd with the -v parameter, it will print its version and its list of methods and then exit, for example: /usr/sbin/saslauthd -v saslauthd 2.1.10 authentication mechanisms: getpwent kerberos5 pam rimap shadow When saslauthd starts up it reads its configuration options from the file /etc/sysconfig/saslauthd. Currently there are two parameters which can be set in this file, MECH and FLAGS. MECH is the authentication mechanism and FLAGS is any command line flags you may wish to pass to saslauthd. To tell saslauthd to use a specific mechanism edit /etc/sysconfig/saslauthd and set the MECH parameter, for example to use PAM it would look like this: MECH=pam Of course you may use any of the other authentication mechanisms that saslauthd reported it supports. PAM is an excellent choice as PAM supports many of the same authentication methods that saslauthd does, but by using PAM you will have centralized all of your authentication configuration under PAM which is one of PAM's greatest assets. How Postfix Interacts with SASL to Name its Authentication Services: -------------------------------------------------------------------- It can be very helpful to understand how Postfix communicates with SASL to name its authentication services. Knowing this will let you identify the configuration files the various components will access. When Postfix invokes SASL it must give SASL an application name that SASL will use among other things to locate a configuration file for the application. The application name Postfix identifies itself as is "smtpd". SASL will append ".conf" to the application name and look for a config file in its library and config directories. Thus SASL will read Postfix's configuration from /etc/sasl2/smtpd.conf This file names the authentication method SASL will use for Postfix (actually for smtpd, other MTA's such as sendmail may use the same file). Because we want to use the saslauthd authentication proxy daemon the contents of this file is: pwcheck_method: saslauthd This tells SASL when being invoked to authentication for Postfix that it should use saslauthd. Saslauthd's mechanism is set in /etc/sysconfig/saslauthd (see below). When Postfix calls on SASL to authenticate it passes to SASL a service name. This service name is used in authentication method specific way. The service name Postfix passes to SASL is "smtp" (note this is not the same as the application name which is "smtpd"). To understand this better consider the case of using PAM authentication. When SASL, or in our case saslauthd, invokes PAM it passes the service name of "smtp" to PAM which means that when PAM wants to read configuration information for this client it will find it under the name of "smtp". Turning on the Authentication Daemon: ------------------------------------- Red Hat security policy is not to automatically enable services belonging to a package when the package is installed. The system administrator must explicitly enable the service. To enable saslauthd do the following: 1) Tell the init process to launch saslauthd when entering various run levels. Assuming you want saslauthd to run at run levels 3,4,5 invoke chkconfig. /sbin/chkconfig --level 345 saslauthd on 2) You will probably want to start saslauthd now without having to reboot, to do this: /sbin/service saslauthd start Trouble Shooting Authentication: -------------------------------- The best way to debug authentication problems is to examine log messages from the authentication components. However, normally these log messages are suppressed. There are two principle reasons the messages are suppressed. The first is that they are typically logged at the DEBUG logging priority level which is the lowest priority and the syslog configuration typically logs only higher priority messages. The second reason is that for security reasons authentication logging is considered a risk. Authentication logging has been divided into two different facilities, auth and authpriv. authpriv is private and is typically shunted off to a different log file with higher protection. You will want to be able to see both auth and authpriv messages at all priorities. To do this as root edit /etc/syslog.conf file, find the following line authpriv.* /var/log/secure edit the line to: authpriv.*;auth.* /var/log/secure Then restart syslogd so the syslog configuration changes will be picked up: /sbin/service syslog restart Now all authentication messages at all priorities will log to /var/log/secure. Using PAM to Authenticate: -------------------------- Edit /etc/sysconfig/saslauthd and set MECH to PAM like this: MECH=pam When PAM is invoked via SASL it is passed a service name of "smtp". This means that PAM will read its configuration parameters for Postfix from the file: /etc/pam.d/smtp. By default this file is set to refer to the global system PAM authentication policy, thus by default you'll get whatever PAM authentication your system is configured for and virtually all applications use. Configuring PAM authentication is beyond the scope of this document, please refer to the PAM documentation if you which to modify PAM. Trouble Shooting PAM Authentication: ------------------------------------ 1) One possible reason PAM may fail to authenticate even if the user is known to the system is if PAM fails to find the service configuration file in /etc/pam.d. Service configuration files are not required by PAM, if it does not find a service configuration file it will default to "other". Since PAM does not consider the absence of a service configuration file a problem it does not log anything nor does it return an error to the calling application. In other words it is completely silent about the fact it did not find a service configuration file. On Red Hat system the default implementation of "other" for PAM is to deny access. This means on Red Hat systems the absence of a PAM service configuration file will mean PAM will silently fail authentication. The PAM service configuration file for postfix is /etc/pam.d/smtp and is intalled by the Red Hat Postfix rpm and put under control of "alternatives" with name mta. Alternatives allows one to select between the sendmail and postfix MTA's and manages symbolic links for files the two MTA's share. /etc/pam.d/smtp is one such file, if you have not selected Postfix as your prefered MTA the link to this file will not be present. To select Postfix as your MTA do this: "/usr/sbin/alternatives --config mta" and follow the prompt to select postfix. 2) Is SASL appending a realm or domain to a username? PAM authentication requires a bare username and password, other authentication methods require the username to be qualified with a realm. Typically the username will be rewritten as user@realm (e.g. user@foo.com) PAM does not understand a username with "@realm" appended to it and will fail the authentication with the message that the user is unknown. If the log files shows saslauthd usernames with "@realm" appended to it then the smtpd_sasl_local_domain configuration parameter is likely set in /etc/postfix/main.cf file, make sure its either not set or set it to an empty string. Restart postfix and test authtentication again, the log file should show only a bare username. Using saslpasswd to Authenticate: --------------------------------- SASL can maintain its own password database independent of the host system's authentication setup, it is called saslpasswd. You may wish to use saslpasswd if you want to isolate who can smtp authenticate from general system users. However, it does add another password database that a system administrator must maintain. To authenticate against sasldb, you'll first have to create accounts. These accounts are entirely separate from system accounts, and are used only by connecting SMTP clients to authenticate themselves. Use the saslpassword command: saslpasswd -u `postconf -h myhostname` -c user to create an account named user which can log into realm. For the realm, make absolutely certain that you use the same value as is set for myhostname in /etc/postfix/main.cf. If you don't, it likely won't work. Also, be aware that saslpasswd is somewhat buggy. The first time you run it, it may generate an error message while initializing the sasldb. If it does, just add that user a second time. You'll need to set permissions on the SASL password database so that the Postfix daemons can read it: chgrp postfix /etc/sasldb chmod g+r /etc/sasldb Now, you'll need to modify /etc/postfix/main.cf to tell it to support SASL. The complete options you might want to use are in the sample-auth.cf file in the Postfix documentation directory. An option you will definitely need is: # enable SASL support smtpd_sasl_auth_enable = yes You might also need to set the SASL authentication realm to whatever realm you used when you created your sasldb; by default, this is set to $myhostname, but you instead might need something like: # set SASL realm to domain instead smtpd_sasl_local_domain = $mydomain Other Postfix Authentication Parameters: ---------------------------------------- If you want to allow your already configured users to still use your SMTP server, and to allow users authenticated via SMTP AUTH to use your server as well, then modify your existing smtpd_recipient_restrictions line to; # also allow authenticated (RFC 2554) users smtpd_recipient_restrictions = permit_sasl_authenticated ... If you want to restrict use of your server to just authenticated clients (Note: this is a bad idea for public mail servers), then instead use: # restrict server access to authenticated (RFC 2554) clients smtpd_delay_reject = yes smtpd_client_restrictions = permit_sasl_authenticated ... SASL supports several password types which have differing security properties. Different SMTP clients may support some or all of these password types. When the client issues an EHLO command, the server tells it which types it supports: $ telnet station6 25 Trying 10.100.0.6... Connected to station6.example.com. Escape character is '^]'. 220 station6.example.com ESMTP Postfix ehlo station7 250-station6.example.com 250-PIPELINING 250-SIZE 10240000 250-VRFY 250-ETRN 250-STARTTLS 250-AUTH PLAIN LOGIN DIGEST-MD5 CRAM-MD5 250-XVERP 250 8BITMIME Here, the server supports PLAIN, LOGIN, DIGEST-MD5, and CRAM-MD5 password methods. The client then chooses the first of these listed methods which it also supports, and issues an SMTP AUTH request. For security, PLAIN and LOGIN methods are typically disabled. These two methods use trivially decryptable encryption, making the username and password issued by the client vulnerable to interception via a sniffer in between the server and client. Unfortunately, they can't always be disabled. Some popular SMTP clients, including MS Outlook 5.x, only support PLAIN authentication, for example. To limit the login methods offered by the server: # disable unsafe password methods smtpd_sasl_security_options = noplaintext noanonymous Available options are: noplaintext, which disables LOGIN and PLAIN noanonymous, which disables disables ANON nodictionary, which disables methods vulnerable to dictionary attacks noactive, which disables methods vulnerable to active attacks The last two are rarely used, since almost all supported methods are vulnerable to those attacks ;-). Also be aware that some broken clients mis-implement the SMTP AUTH protocol, and send commands using incorrect syntax (AUTH=foo instead of the correct AUTH foo). MS Outlook 4.x clients have this bug, among a legion of others.... If you need to support these clients, use: # support braindead MS products broken_sasl_auth_clients = yes To help prevent spoofing, you can also create a map file of SASL login names which are allowed to use specific envelope sender (MAIL FROM) addresses. If you choose to do this, you also have to tell Postfix to reject addresses which don't match login names: # prevent spoofing by authenticated users reject_sender_login_mismatch smtpd_sender_login_maps=type:/path/to/file Configuration of SASL clients is much simpler. Postfix itself can be made a SASL client; this is typically useful when roaming users run Linux on their laptop and need to relay mail back through the organization's main server. To enable Postfix to act as an SMTP AUTH client, simply add to /etc/postfix/main.cf: # support authentication (RFC 2557) when relaying through a server smtp_sasl_auth_enable = yes and tell Postfix where to find the usernames and passwords it should use to authenticate: # location of passwords for authentication client smtp_sasl_password_maps = type:/path/to/file The file itself should have the format: destination username:password where destination is the name of the server, and username:password are the username and password which should be presented to that server to authenticate when connecting to it as a client. Optionally, the authentication methods to be used can be specified for the Postfix client, just as they can be for the Postfix server: # disable plaintext and anonymous smtp_sasl_security_options = noplaintext noanonymous Many popular end-user MUAs can also be configured as SMTP AUTH clients. Clients capable of this supplied with Red Hat include pine, Netscape, and Mozilla. Other Sources of Documentation: ------------------------------- /usr/share/doc/postfix-/README_FILES/SASL_README Local configuration examples: /usr/share/doc/postfix-*/samples Postfix Howtos, Guides and Tips by Ralf Hildebrandt and Patrick Koetter can be found at: http://postfix.state-of-mind.de ------------------------------------------------------------------------------ Please send any comments / corrections to Chris Ricker . This material can be freely modified and redistributed. Additional material provided by John Dennis and Dax Kelson . main.cf.default000066600000055350150501202770007440 0ustar00# DO NOT EDIT THIS FILE. EDIT THE MAIN.CF FILE INSTEAD. THE # TEXT HERE JUST SHOWS DEFAULT SETTINGS BUILT INTO POSTFIX. # 2bounce_notice_recipient = postmaster access_map_defer_code = 450 access_map_reject_code = 554 address_verify_default_transport = $default_transport address_verify_local_transport = $local_transport address_verify_map = address_verify_negative_cache = yes address_verify_negative_expire_time = 3d address_verify_negative_refresh_time = 3h address_verify_poll_count = ${stress?1}${stress:3} address_verify_poll_delay = 3s address_verify_positive_expire_time = 31d address_verify_positive_refresh_time = 7d address_verify_relay_transport = $relay_transport address_verify_relayhost = $relayhost address_verify_sender = $double_bounce_sender address_verify_sender_dependent_relayhost_maps = $sender_dependent_relayhost_maps address_verify_service_name = verify address_verify_transport_maps = $transport_maps address_verify_virtual_transport = $virtual_transport alias_database = hash:/etc/aliases alias_maps = hash:/etc/aliases, nis:mail.aliases allow_mail_to_commands = alias, forward allow_mail_to_files = alias, forward allow_min_user = no allow_percent_hack = yes allow_untrusted_routing = no alternate_config_directories = always_add_missing_headers = no always_bcc = anvil_rate_time_unit = 60s anvil_status_update_time = 600s append_at_myorigin = yes append_dot_mydomain = yes application_event_drain_time = 100s authorized_flush_users = static:anyone authorized_mailq_users = static:anyone authorized_submit_users = static:anyone backwards_bounce_logfile_compatibility = yes berkeley_db_create_buffer_size = 16777216 berkeley_db_read_buffer_size = 131072 best_mx_transport = biff = yes body_checks = body_checks_size_limit = 51200 bounce_notice_recipient = postmaster bounce_queue_lifetime = 5d bounce_service_name = bounce bounce_size_limit = 50000 bounce_template_file = broken_sasl_auth_clients = no canonical_classes = envelope_sender, envelope_recipient, header_sender, header_recipient canonical_maps = cleanup_service_name = cleanup command_directory = /usr/sbin command_execution_directory = command_expansion_filter = 1234567890!@%-_=+:,./abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ command_time_limit = 1000s config_directory = /etc/postfix connection_cache_protocol_timeout = 5s connection_cache_service_name = scache connection_cache_status_update_time = 600s connection_cache_ttl_limit = 2s content_filter = cyrus_sasl_config_path = daemon_directory = /usr/libexec/postfix daemon_timeout = 18000s data_directory = /var/lib/postfix debug_peer_level = 2 debug_peer_list = default_database_type = hash default_delivery_slot_cost = 5 default_delivery_slot_discount = 50 default_delivery_slot_loan = 3 default_destination_concurrency_failed_cohort_limit = 1 default_destination_concurrency_limit = 20 default_destination_concurrency_negative_feedback = 1 default_destination_concurrency_positive_feedback = 1 default_destination_rate_delay = 0s default_destination_recipient_limit = 50 default_extra_recipient_limit = 1000 default_minimum_delivery_slots = 3 default_privs = nobody default_process_limit = 100 default_rbl_reply = $rbl_code Service unavailable; $rbl_class [$rbl_what] blocked using $rbl_domain${rbl_reason?; $rbl_reason} default_recipient_limit = 20000 default_recipient_refill_delay = 5s default_recipient_refill_limit = 100 default_transport = smtp default_verp_delimiters = += defer_code = 450 defer_service_name = defer defer_transports = delay_logging_resolution_limit = 2 delay_notice_recipient = postmaster delay_warning_time = 0h deliver_lock_attempts = 20 deliver_lock_delay = 1s destination_concurrency_feedback_debug = no detect_8bit_encoding_header = yes disable_dns_lookups = no disable_mime_input_processing = no disable_mime_output_conversion = no disable_verp_bounces = no disable_vrfy_command = no dont_remove = 0 double_bounce_sender = double-bounce duplicate_filter_limit = 1000 empty_address_recipient = MAILER-DAEMON empty_address_relayhost_maps_lookup_key = <> enable_original_recipient = yes error_notice_recipient = postmaster error_service_name = error execution_directory_expansion_filter = 1234567890!@%-_=+:,./abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ expand_owner_alias = no export_environment = TZ MAIL_CONFIG LANG fallback_transport = fallback_transport_maps = fast_flush_domains = $relay_domains fast_flush_purge_time = 7d fast_flush_refresh_time = 12h fault_injection_code = 0 flush_service_name = flush fork_attempts = 5 fork_delay = 1s forward_expansion_filter = 1234567890!@%-_=+:,./abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ forward_path = $home/.forward${recipient_delimiter}${extension}, $home/.forward frozen_delivered_to = yes hash_queue_depth = 1 hash_queue_names = deferred, defer header_address_token_limit = 10240 header_checks = header_size_limit = 102400 helpful_warnings = yes home_mailbox = hopcount_limit = 50 html_directory = no ignore_mx_lookup_error = no import_environment = MAIL_CONFIG MAIL_DEBUG MAIL_LOGTAG TZ XAUTHORITY DISPLAY LANG=C in_flow_delay = 1s inet_interfaces = all inet_protocols = ipv4 initial_destination_concurrency = 5 internal_mail_filter_classes = invalid_hostname_reject_code = 501 ipc_idle = 5s ipc_timeout = 3600s ipc_ttl = 1000s line_length_limit = 2048 lmtp_assume_final = no lmtp_bind_address = lmtp_bind_address6 = lmtp_body_checks = lmtp_cname_overrides_servername = no lmtp_connect_timeout = 0s lmtp_connection_cache_destinations = lmtp_connection_cache_on_demand = yes lmtp_connection_cache_time_limit = 2s lmtp_connection_reuse_time_limit = 300s lmtp_data_done_timeout = 600s lmtp_data_init_timeout = 120s lmtp_data_xfer_timeout = 180s lmtp_defer_if_no_mx_address_found = no lmtp_destination_concurrency_failed_cohort_limit = $default_destination_concurrency_failed_cohort_limit lmtp_destination_concurrency_limit = $default_destination_concurrency_limit lmtp_destination_concurrency_negative_feedback = $default_destination_concurrency_negative_feedback lmtp_destination_concurrency_positive_feedback = $default_destination_concurrency_positive_feedback lmtp_destination_rate_delay = $default_destination_rate_delay lmtp_destination_recipient_limit = $default_destination_recipient_limit lmtp_discard_lhlo_keyword_address_maps = lmtp_discard_lhlo_keywords = lmtp_enforce_tls = no lmtp_generic_maps = lmtp_header_checks = lmtp_host_lookup = dns lmtp_initial_destination_concurrency = $initial_destination_concurrency lmtp_lhlo_name = $myhostname lmtp_lhlo_timeout = 300s lmtp_line_length_limit = 990 lmtp_mail_timeout = 300s lmtp_mime_header_checks = lmtp_mx_address_limit = 5 lmtp_mx_session_limit = 2 lmtp_nested_header_checks = lmtp_pix_workaround_delay_time = 10s lmtp_pix_workaround_maps = lmtp_pix_workaround_threshold_time = 500s lmtp_pix_workarounds = disable_esmtp,delay_dotcrlf lmtp_quit_timeout = 300s lmtp_quote_rfc821_envelope = yes lmtp_randomize_addresses = yes lmtp_rcpt_timeout = 300s lmtp_rset_timeout = 20s lmtp_sasl_auth_cache_name = lmtp_sasl_auth_cache_time = 90d lmtp_sasl_auth_enable = no lmtp_sasl_auth_soft_bounce = yes lmtp_sasl_mechanism_filter = lmtp_sasl_password_maps = lmtp_sasl_path = lmtp_sasl_security_options = noplaintext, noanonymous lmtp_sasl_tls_security_options = $lmtp_sasl_security_options lmtp_sasl_tls_verified_security_options = $lmtp_sasl_tls_security_options lmtp_sasl_type = cyrus lmtp_send_xforward_command = no lmtp_sender_dependent_authentication = no lmtp_skip_5xx_greeting = yes lmtp_skip_quit_response = no lmtp_starttls_timeout = 300s lmtp_tcp_port = 24 lmtp_tls_CAfile = lmtp_tls_CApath = lmtp_tls_cert_file = lmtp_tls_ciphers = export lmtp_tls_dcert_file = lmtp_tls_dkey_file = $lmtp_tls_dcert_file lmtp_tls_eccert_file = lmtp_tls_eckey_file = $lmtp_tls_eccert_file lmtp_tls_enforce_peername = yes lmtp_tls_exclude_ciphers = lmtp_tls_fingerprint_cert_match = lmtp_tls_fingerprint_digest = md5 lmtp_tls_key_file = $lmtp_tls_cert_file lmtp_tls_loglevel = 0 lmtp_tls_mandatory_ciphers = medium lmtp_tls_mandatory_exclude_ciphers = lmtp_tls_mandatory_protocols = SSLv3, TLSv1 lmtp_tls_note_starttls_offer = no lmtp_tls_per_site = lmtp_tls_policy_maps = lmtp_tls_protocols = !SSLv2 lmtp_tls_scert_verifydepth = 9 lmtp_tls_secure_cert_match = nexthop lmtp_tls_security_level = lmtp_tls_session_cache_database = lmtp_tls_session_cache_timeout = 3600s lmtp_tls_verify_cert_match = hostname lmtp_use_tls = no lmtp_xforward_timeout = 300s local_command_shell = local_destination_concurrency_failed_cohort_limit = $default_destination_concurrency_failed_cohort_limit local_destination_concurrency_limit = 2 local_destination_concurrency_negative_feedback = $default_destination_concurrency_negative_feedback local_destination_concurrency_positive_feedback = $default_destination_concurrency_positive_feedback local_destination_rate_delay = $default_destination_rate_delay local_destination_recipient_limit = 1 local_header_rewrite_clients = permit_inet_interfaces local_initial_destination_concurrency = $initial_destination_concurrency local_recipient_maps = proxy:unix:passwd.byname $alias_maps local_transport = local:$myhostname luser_relay = mail_name = Postfix mail_owner = postfix mail_release_date = 20100319 mail_spool_directory = /var/mail mail_version = 2.6.6 mailbox_command = mailbox_command_maps = mailbox_delivery_lock = fcntl, dotlock mailbox_size_limit = 51200000 mailbox_transport = mailbox_transport_maps = mailq_path = /usr/bin/mailq manpage_directory = /usr/local/man maps_rbl_domains = maps_rbl_reject_code = 554 masquerade_classes = envelope_sender, header_sender, header_recipient masquerade_domains = masquerade_exceptions = master_service_disable = max_idle = 100s max_use = 100 maximal_backoff_time = 4000s maximal_queue_lifetime = 5d message_reject_characters = message_size_limit = 10240000 message_strip_characters = milter_command_timeout = 30s milter_connect_macros = j {daemon_name} v milter_connect_timeout = 30s milter_content_timeout = 300s milter_data_macros = i milter_default_action = tempfail milter_end_of_data_macros = i milter_end_of_header_macros = i milter_helo_macros = {tls_version} {cipher} {cipher_bits} {cert_subject} {cert_issuer} milter_macro_daemon_name = $myhostname milter_macro_v = $mail_name $mail_version milter_mail_macros = i {auth_type} {auth_authen} {auth_author} {mail_addr} {mail_host} {mail_mailer} milter_protocol = 6 milter_rcpt_macros = i {rcpt_addr} {rcpt_host} {rcpt_mailer} milter_unknown_command_macros = mime_boundary_length_limit = 2048 mime_header_checks = $header_checks mime_nesting_limit = 100 minimal_backoff_time = 300s multi_instance_directories = multi_instance_enable = no multi_instance_group = multi_instance_name = multi_instance_wrapper = multi_recipient_bounce_reject_code = 550 mydestination = $myhostname, localhost.$mydomain, localhost mynetworks_style = subnet myorigin = $myhostname nested_header_checks = $header_checks newaliases_path = /usr/bin/newaliases non_fqdn_reject_code = 504 non_smtpd_milters = notify_classes = resource, software owner_request_special = yes parent_domain_matches_subdomains = debug_peer_list,fast_flush_domains,mynetworks,permit_mx_backup_networks,qmqpd_authorized_clients,relay_domains,smtpd_access_maps permit_mx_backup_networks = pickup_service_name = pickup plaintext_reject_code = 450 postmulti_control_commands = reload flush postmulti_start_commands = start postmulti_stop_commands = stop abort drain quick-stop prepend_delivered_header = command, file, forward process_id_directory = pid propagate_unmatched_extensions = canonical, virtual proxy_interfaces = proxy_read_maps = $local_recipient_maps $mydestination $virtual_alias_maps $virtual_alias_domains $virtual_mailbox_maps $virtual_mailbox_domains $relay_recipient_maps $relay_domains $canonical_maps $sender_canonical_maps $recipient_canonical_maps $relocated_maps $transport_maps $mynetworks $sender_bcc_maps $recipient_bcc_maps $smtp_generic_maps $lmtp_generic_maps proxy_write_maps = $smtp_sasl_auth_cache_name $lmtp_sasl_auth_cache_name proxymap_service_name = proxymap proxywrite_service_name = proxywrite qmgr_clog_warn_time = 300s qmgr_fudge_factor = 100 qmgr_message_active_limit = 20000 qmgr_message_recipient_limit = 20000 qmgr_message_recipient_minimum = 10 qmqpd_authorized_clients = qmqpd_client_port_logging = no qmqpd_error_delay = 1s qmqpd_timeout = 300s queue_directory = /var/spool/postfix queue_file_attribute_count_limit = 100 queue_minfree = 0 queue_run_delay = 300s queue_service_name = qmgr rbl_reply_maps = readme_directory = no receive_override_options = recipient_bcc_maps = recipient_canonical_classes = envelope_recipient, header_recipient recipient_canonical_maps = recipient_delimiter = reject_code = 554 reject_tempfail_action = defer_if_permit relay_clientcerts = relay_destination_concurrency_failed_cohort_limit = $default_destination_concurrency_failed_cohort_limit relay_destination_concurrency_limit = $default_destination_concurrency_limit relay_destination_concurrency_negative_feedback = $default_destination_concurrency_negative_feedback relay_destination_concurrency_positive_feedback = $default_destination_concurrency_positive_feedback relay_destination_rate_delay = $default_destination_rate_delay relay_destination_recipient_limit = $default_destination_recipient_limit relay_domains = $mydestination relay_domains_reject_code = 554 relay_initial_destination_concurrency = $initial_destination_concurrency relay_recipient_maps = relay_transport = relay relayhost = relocated_maps = remote_header_rewrite_domain = require_home_directory = no resolve_dequoted_address = yes resolve_null_domain = no resolve_numeric_domain = no rewrite_service_name = rewrite sample_directory = /etc/postfix send_cyrus_sasl_authzid = no sender_bcc_maps = sender_canonical_classes = envelope_sender, header_sender sender_canonical_maps = sender_dependent_relayhost_maps = sendmail_path = /usr/sbin/sendmail service_throttle_time = 60s setgid_group = postdrop show_user_unknown_table_name = yes showq_service_name = showq smtp_always_send_ehlo = yes smtp_bind_address = smtp_bind_address6 = smtp_body_checks = smtp_cname_overrides_servername = no smtp_connect_timeout = 30s smtp_connection_cache_destinations = smtp_connection_cache_on_demand = yes smtp_connection_cache_time_limit = 2s smtp_connection_reuse_time_limit = 300s smtp_data_done_timeout = 600s smtp_data_init_timeout = 120s smtp_data_xfer_timeout = 180s smtp_defer_if_no_mx_address_found = no smtp_destination_concurrency_failed_cohort_limit = $default_destination_concurrency_failed_cohort_limit smtp_destination_concurrency_limit = $default_destination_concurrency_limit smtp_destination_concurrency_negative_feedback = $default_destination_concurrency_negative_feedback smtp_destination_concurrency_positive_feedback = $default_destination_concurrency_positive_feedback smtp_destination_rate_delay = $default_destination_rate_delay smtp_destination_recipient_limit = $default_destination_recipient_limit smtp_discard_ehlo_keyword_address_maps = smtp_discard_ehlo_keywords = smtp_enforce_tls = no smtp_fallback_relay = $fallback_relay smtp_generic_maps = smtp_header_checks = smtp_helo_name = $myhostname smtp_helo_timeout = 300s smtp_host_lookup = dns smtp_initial_destination_concurrency = $initial_destination_concurrency smtp_line_length_limit = 990 smtp_mail_timeout = 300s smtp_mime_header_checks = smtp_mx_address_limit = 5 smtp_mx_session_limit = 2 smtp_nested_header_checks = smtp_never_send_ehlo = no smtp_pix_workaround_delay_time = 10s smtp_pix_workaround_maps = smtp_pix_workaround_threshold_time = 500s smtp_pix_workarounds = disable_esmtp,delay_dotcrlf smtp_quit_timeout = 300s smtp_quote_rfc821_envelope = yes smtp_randomize_addresses = yes smtp_rcpt_timeout = 300s smtp_rset_timeout = 20s smtp_sasl_auth_cache_name = smtp_sasl_auth_cache_time = 90d smtp_sasl_auth_enable = no smtp_sasl_auth_soft_bounce = yes smtp_sasl_mechanism_filter = smtp_sasl_password_maps = smtp_sasl_path = smtp_sasl_security_options = noplaintext, noanonymous smtp_sasl_tls_security_options = $smtp_sasl_security_options smtp_sasl_tls_verified_security_options = $smtp_sasl_tls_security_options smtp_sasl_type = cyrus smtp_send_xforward_command = no smtp_sender_dependent_authentication = no smtp_skip_5xx_greeting = yes smtp_skip_quit_response = yes smtp_starttls_timeout = 300s smtp_tls_CAfile = smtp_tls_CApath = smtp_tls_cert_file = smtp_tls_ciphers = export smtp_tls_dcert_file = smtp_tls_dkey_file = $smtp_tls_dcert_file smtp_tls_eccert_file = smtp_tls_eckey_file = $smtp_tls_eccert_file smtp_tls_enforce_peername = yes smtp_tls_exclude_ciphers = smtp_tls_fingerprint_cert_match = smtp_tls_fingerprint_digest = md5 smtp_tls_key_file = $smtp_tls_cert_file smtp_tls_loglevel = 0 smtp_tls_mandatory_ciphers = medium smtp_tls_mandatory_exclude_ciphers = smtp_tls_mandatory_protocols = SSLv3, TLSv1 smtp_tls_note_starttls_offer = no smtp_tls_per_site = smtp_tls_policy_maps = smtp_tls_protocols = !SSLv2 smtp_tls_scert_verifydepth = 9 smtp_tls_secure_cert_match = nexthop, dot-nexthop smtp_tls_security_level = smtp_tls_session_cache_database = smtp_tls_session_cache_timeout = 3600s smtp_tls_verify_cert_match = hostname smtp_use_tls = no smtp_xforward_timeout = 300s smtpd_authorized_verp_clients = $authorized_verp_clients smtpd_authorized_xclient_hosts = smtpd_authorized_xforward_hosts = smtpd_banner = $myhostname ESMTP $mail_name smtpd_client_connection_count_limit = 50 smtpd_client_connection_rate_limit = 0 smtpd_client_event_limit_exceptions = ${smtpd_client_connection_limit_exceptions:$mynetworks} smtpd_client_message_rate_limit = 0 smtpd_client_new_tls_session_rate_limit = 0 smtpd_client_port_logging = no smtpd_client_recipient_rate_limit = 0 smtpd_client_restrictions = smtpd_data_restrictions = smtpd_delay_open_until_valid_rcpt = yes smtpd_delay_reject = yes smtpd_discard_ehlo_keyword_address_maps = smtpd_discard_ehlo_keywords = smtpd_end_of_data_restrictions = smtpd_enforce_tls = no smtpd_error_sleep_time = 1s smtpd_etrn_restrictions = smtpd_expansion_filter = \t\40!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~ smtpd_forbidden_commands = CONNECT GET POST smtpd_hard_error_limit = ${stress?1}${stress:20} smtpd_helo_required = no smtpd_helo_restrictions = smtpd_history_flush_threshold = 100 smtpd_junk_command_limit = ${stress?1}${stress:100} smtpd_milters = smtpd_noop_commands = smtpd_null_access_lookup_key = <> smtpd_peername_lookup = yes smtpd_policy_service_max_idle = 300s smtpd_policy_service_max_ttl = 1000s smtpd_policy_service_timeout = 100s smtpd_proxy_ehlo = $myhostname smtpd_proxy_filter = smtpd_proxy_timeout = 100s smtpd_recipient_limit = 1000 smtpd_recipient_overshoot_limit = 1000 smtpd_recipient_restrictions = permit_mynetworks, reject_unauth_destination smtpd_reject_unlisted_recipient = yes smtpd_reject_unlisted_sender = no smtpd_restriction_classes = smtpd_sasl_auth_enable = no smtpd_sasl_authenticated_header = no smtpd_sasl_exceptions_networks = smtpd_sasl_local_domain = smtpd_sasl_path = smtpd smtpd_sasl_security_options = noanonymous smtpd_sasl_tls_security_options = $smtpd_sasl_security_options smtpd_sasl_type = cyrus smtpd_sender_login_maps = smtpd_sender_restrictions = smtpd_soft_error_limit = 10 smtpd_starttls_timeout = 300s smtpd_timeout = ${stress?10}${stress:300}s smtpd_tls_CAfile = smtpd_tls_CApath = smtpd_tls_always_issue_session_ids = yes smtpd_tls_ask_ccert = no smtpd_tls_auth_only = no smtpd_tls_ccert_verifydepth = 9 smtpd_tls_cert_file = smtpd_tls_ciphers = export smtpd_tls_dcert_file = smtpd_tls_dh1024_param_file = smtpd_tls_dh512_param_file = smtpd_tls_dkey_file = $smtpd_tls_dcert_file smtpd_tls_eccert_file = smtpd_tls_eckey_file = $smtpd_tls_eccert_file smtpd_tls_eecdh_grade = none smtpd_tls_exclude_ciphers = smtpd_tls_fingerprint_digest = md5 smtpd_tls_key_file = $smtpd_tls_cert_file smtpd_tls_loglevel = 0 smtpd_tls_mandatory_ciphers = medium smtpd_tls_mandatory_exclude_ciphers = smtpd_tls_mandatory_protocols = SSLv3, TLSv1 smtpd_tls_protocols = smtpd_tls_received_header = no smtpd_tls_req_ccert = no smtpd_tls_security_level = smtpd_tls_session_cache_database = smtpd_tls_session_cache_timeout = 3600s smtpd_tls_wrappermode = no smtpd_use_tls = no soft_bounce = no stale_lock_time = 500s stress = strict_7bit_headers = no strict_8bitmime = no strict_8bitmime_body = no strict_mailbox_ownership = yes strict_mime_encoding_domain = no strict_rfc821_envelopes = no sun_mailtool_compatibility = no swap_bangpath = yes syslog_facility = mail syslog_name = ${multi_instance_name:postfix}${multi_instance_name?$multi_instance_name} tcp_windowsize = 0 tls_daemon_random_bytes = 32 tls_eecdh_strong_curve = prime256v1 tls_eecdh_ultra_curve = secp384r1 tls_export_cipherlist = ALL:+RC4:@STRENGTH tls_high_cipherlist = ALL:!EXPORT:!LOW:!MEDIUM:+RC4:@STRENGTH tls_low_cipherlist = ALL:!EXPORT:+RC4:@STRENGTH tls_medium_cipherlist = ALL:!EXPORT:!LOW:+RC4:@STRENGTH tls_null_cipherlist = eNULL:!aNULL tls_random_bytes = 32 tls_random_exchange_name = ${data_directory}/prng_exch tls_random_prng_update_period = 3600s tls_random_reseed_period = 3600s tls_random_source = dev:/dev/urandom trace_service_name = trace transport_maps = transport_retry_time = 60s trigger_timeout = 10s undisclosed_recipients_header = To: undisclosed-recipients:; unknown_address_reject_code = 450 unknown_address_tempfail_action = $reject_tempfail_action unknown_client_reject_code = 450 unknown_helo_hostname_tempfail_action = $reject_tempfail_action unknown_hostname_reject_code = 450 unknown_local_recipient_reject_code = 550 unknown_relay_recipient_reject_code = 550 unknown_virtual_alias_reject_code = 550 unknown_virtual_mailbox_reject_code = 550 unverified_recipient_defer_code = 450 unverified_recipient_reject_code = 450 unverified_recipient_reject_reason = unverified_recipient_tempfail_action = $reject_tempfail_action unverified_sender_defer_code = 450 unverified_sender_reject_code = 450 unverified_sender_reject_reason = unverified_sender_tempfail_action = $reject_tempfail_action verp_delimiter_filter = -=+ virtual_alias_domains = $virtual_alias_maps virtual_alias_expansion_limit = 1000 virtual_alias_maps = $virtual_maps virtual_alias_recursion_limit = 1000 virtual_destination_concurrency_failed_cohort_limit = $default_destination_concurrency_failed_cohort_limit virtual_destination_concurrency_limit = $default_destination_concurrency_limit virtual_destination_concurrency_negative_feedback = $default_destination_concurrency_negative_feedback virtual_destination_concurrency_positive_feedback = $default_destination_concurrency_positive_feedback virtual_destination_rate_delay = $default_destination_rate_delay virtual_destination_recipient_limit = $default_destination_recipient_limit virtual_gid_maps = virtual_initial_destination_concurrency = $initial_destination_concurrency virtual_mailbox_base = virtual_mailbox_domains = $virtual_mailbox_maps virtual_mailbox_limit = 51200000 virtual_mailbox_lock = fcntl, dotlock virtual_mailbox_maps = virtual_minimum_uid = 100 virtual_transport = virtual virtual_uid_maps = bounce.cf.default000066600000006734150501202770007771 0ustar00# # Do not edit this file. This file shows the default delivery status # notification (DSN) messages that are built into Postfix. # # To change Postfix DSN messages, perhaps to add non-English text, # follow instructions in the bounce(5) manual page. # # # The failure template is used when mail is returned to the sender; # either the destination rejected the message, or the destination # could not be reached before the message expired in the queue. # failure_template = < # Copyright (c) 2000 - 2001 by Matthias Andree # Redistributable unter the MIT-style license that follows: # Abstract: "do whatever you want except hold somebody liable or change # the copyright information". # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. # 2000-09-29 # v0.1: initial release # 2000-12-05 # v0.2: copy libdb.* for libnss_db.so # remove /etc/localtime in case it's a broken symlink # restrict find to maxdepth 1 (faster) # Revision 1.4 2001/01/15 09:36:35 emma # add note it was successfully tested on Debian sid # # 20060101 /lib64 support by Keith Owens. # CP="cp -p" cond_copy() { # find files as per pattern in $1 # if any, copy to directory $2 dir=`dirname "$1"` pat=`basename "$1"` lr=`find "$dir" -maxdepth 1 -name "$pat"` if test ! -d "$2" ; then exit 1 ; fi if test "x$lr" != "x" ; then $CP $1 "$2" ; fi } set -e umask 022 POSTFIX_DIR=${POSTFIX_DIR-/var/spool/postfix} cd ${POSTFIX_DIR} mkdir -p etc lib usr/lib/zoneinfo test -d /lib64 && mkdir -p lib64 # find localtime (SuSE 5.3 does not have /etc/localtime) lt=/etc/localtime if test ! -f $lt ; then lt=/usr/lib/zoneinfo/localtime ; fi if test ! -f $lt ; then lt=/usr/share/zoneinfo/localtime ; fi if test ! -f $lt ; then echo "cannot find localtime" ; exit 1 ; fi rm -f etc/localtime # copy localtime and some other system files into the chroot's etc $CP -f $lt /etc/services /etc/resolv.conf /etc/nsswitch.conf etc $CP -f /etc/host.conf /etc/hosts /etc/passwd etc ln -s -f /etc/localtime usr/lib/zoneinfo # copy required libraries into the chroot cond_copy '/lib/libnss_*.so*' lib cond_copy '/lib/libresolv.so*' lib cond_copy '/lib/libdb.so*' lib if test -d /lib64; then cond_copy '/lib64/libnss_*.so*' lib64 cond_copy '/lib64/libresolv.so*' lib64 cond_copy '/lib64/libdb.so*' lib64 fi postfix reload examples/smtpd-policy/README.SPF000066600000000377150501202770012327 0ustar00See http://www.openspf.org/Software for the current version of the SPF policy daemon for Postfix. SPF support is also available via MILTER plugins, such as sid-milter at http://sourceforge.net/projects/sid-milter/ which implements both SenderID and SPF. examples/smtpd-policy/greylist.pl000066600000020401150501202770013205 0ustar00#!/usr/bin/perl use DB_File; use Fcntl; use Sys::Syslog qw(:DEFAULT setlogsock); # # Usage: greylist.pl [-v] # # Demo delegated Postfix SMTPD policy server. This server implements # greylisting. State is kept in a Berkeley DB database. Logging is # sent to syslogd. # # How it works: each time a Postfix SMTP server process is started # it connects to the policy service socket, and Postfix runs one # instance of this PERL script. By default, a Postfix SMTP server # process terminates after 100 seconds of idle time, or after serving # 100 clients. Thus, the cost of starting this PERL script is smoothed # out over time. # # To run this from /etc/postfix/master.cf: # # policy unix - n n - - spawn # user=nobody argv=/usr/bin/perl /usr/libexec/postfix/greylist.pl # # To use this from Postfix SMTPD, use in /etc/postfix/main.cf: # # smtpd_recipient_restrictions = # ... # reject_unauth_destination # check_policy_service unix:private/policy # ... # # NOTE: specify check_policy_service AFTER reject_unauth_destination # or else your system can become an open relay. # # To test this script by hand, execute: # # % perl greylist.pl # # Each query is a bunch of attributes. Order does not matter, and # the demo script uses only a few of all the attributes shown below: # # request=smtpd_access_policy # protocol_state=RCPT # protocol_name=SMTP # helo_name=some.domain.tld # queue_id=8045F2AB23 # sender=foo@bar.tld # recipient=bar@foo.tld # client_address=1.2.3.4 # client_name=another.domain.tld # instance=123.456.7 # sasl_method=plain # sasl_username=you # sasl_sender= # size=12345 # [empty line] # # The policy server script will answer in the same style, with an # attribute list followed by a empty line: # # action=dunno # [empty line] # # # greylist status database and greylist time interval. DO NOT create the # greylist status database in a world-writable directory such as /tmp # or /var/tmp. DO NOT create the greylist database in a file system # that can run out of space. # # In case of database corruption, this script saves the database as # $database_name.time(), so that the mail system does not get stuck. # $database_name="/var/mta/greylist.db"; $greylist_delay=60; # # Auto-whitelist threshold. Specify 0 to disable, or the number of # successful "come backs" after which a client is no longer subject # to greylisting. # $auto_whitelist_threshold = 10; # # Syslogging options for verbose mode and for fatal errors. # NOTE: comment out the $syslog_socktype line if syslogging does not # work on your system. # $syslog_socktype = 'unix'; # inet, unix, stream, console $syslog_facility="mail"; $syslog_options="pid"; $syslog_priority="info"; # # Demo SMTPD access policy routine. The result is an action just like # it would be specified on the right-hand side of a Postfix access # table. Request attributes are available via the %attr hash. # sub smtpd_access_policy { my($key, $time_stamp, $now, $count); # Open the database on the fly. open_database() unless $database_obj; # Search the auto-whitelist. if ($auto_whitelist_threshold > 0) { $count = read_database($attr{"client_address"}); if ($count > $auto_whitelist_threshold) { return "dunno"; } } # Lookup the time stamp for this client/sender/recipient. $key = lc $attr{"client_address"}."/".$attr{"sender"}."/".$attr{"recipient"}; $time_stamp = read_database($key); $now = time(); # If this is a new request add this client/sender/recipient to the database. if ($time_stamp == 0) { $time_stamp = $now; update_database($key, $time_stamp); } # The result can be any action that is allowed in a Postfix access(5) map. # # To label mail, return ``PREPEND'' headername: headertext # # In case of success, return ``DUNNO'' instead of ``OK'' so that the # check_policy_service restriction can be followed by other restrictions. # # In case of failure, specify ``DEFER_IF_PERMIT optional text...'' # so that mail can still be blocked by other access restrictions. # syslog $syslog_priority, "request age %d", $now - $time_stamp if $verbose; if ($now - $time_stamp > $greylist_delay) { # Update the auto-whitelist. if ($auto_whitelist_threshold > 0) { update_database($attr{"client_address"}, $count + 1); } return "dunno"; } else { return "defer_if_permit Service is unavailable"; } } # # You should not have to make changes below this point. # sub LOCK_SH { 1 }; # Shared lock (used for reading). sub LOCK_EX { 2 }; # Exclusive lock (used for writing). sub LOCK_NB { 4 }; # Don't block (for testing). sub LOCK_UN { 8 }; # Release lock. # # Log an error and abort. # sub fatal_exit { my($first) = shift(@_); syslog "err", "fatal: $first", @_; exit 1; } # # Open hash database. # sub open_database { my($database_fd); # Use tied database to make complex manipulations easier to express. $database_obj = tie(%db_hash, 'DB_File', $database_name, O_CREAT|O_RDWR, 0644, $DB_BTREE) || fatal_exit "Cannot open database %s: $!", $database_name; $database_fd = $database_obj->fd; open DATABASE_HANDLE, "+<&=$database_fd" || fatal_exit "Cannot fdopen database %s: $!", $database_name; syslog $syslog_priority, "open %s", $database_name if $verbose; } # # Read database. Use a shared lock to avoid reading the database # while it is being changed. XXX There should be a way to synchronize # our cache from the on-file database before looking up the key. # sub read_database { my($key) = @_; my($value); flock DATABASE_HANDLE, LOCK_SH || fatal_exit "Can't get shared lock on %s: $!", $database_name; # XXX Synchronize our cache from the on-disk copy before lookup. $value = $db_hash{$key}; syslog $syslog_priority, "lookup %s: %s", $key, $value if $verbose; flock DATABASE_HANDLE, LOCK_UN || fatal_exit "Can't unlock %s: $!", $database_name; return $value; } # # Update database. Use an exclusive lock to avoid collisions with # other updaters, and to avoid surprises in database readers. XXX # There should be a way to synchronize our cache from the on-file # database before updating the database. # sub update_database { my($key, $value) = @_; syslog $syslog_priority, "store %s: %s", $key, $value if $verbose; flock DATABASE_HANDLE, LOCK_EX || fatal_exit "Can't exclusively lock %s: $!", $database_name; # XXX Synchronize our cache from the on-disk copy before update. $db_hash{$key} = $value; $database_obj->sync() && fatal_exit "Can't update %s: $!", $database_name; flock DATABASE_HANDLE, LOCK_UN || fatal_exit "Can't unlock %s: $!", $database_name; } # # Signal 11 means that we have some kind of database corruption (yes # Berkeley DB should handle this better). Move the corrupted database # out of the way, and start with a new database. # sub sigsegv_handler { my $backup = $database_name . "." . time(); rename $database_name, $backup || fatal_exit "Can't save %s as %s: $!", $database_name, $backup; fatal_exit "Caught signal 11; the corrupted database is saved as $backup"; } $SIG{'SEGV'} = 'sigsegv_handler'; # # This process runs as a daemon, so it can't log to a terminal. Use # syslog so that people can actually see our messages. # setlogsock $syslog_socktype; openlog $0, $syslog_options, $syslog_facility; # # We don't need getopt() for now. # while ($option = shift(@ARGV)) { if ($option eq "-v") { $verbose = 1; } else { syslog $syslog_priority, "Invalid option: %s. Usage: %s [-v]", $option, $0; exit 1; } } # # Unbuffer standard output. # select((select(STDOUT), $| = 1)[0]); # # Receive a bunch of attributes, evaluate the policy, send the result. # while () { if (/([^=]+)=(.*)\n/) { $attr{substr($1, 0, 512)} = substr($2, 0, 512); } elsif ($_ eq "\n") { if ($verbose) { for (keys %attr) { syslog $syslog_priority, "Attribute: %s=%s", $_, $attr{$_}; } } fatal_exit "unrecognized request type: '%s'", $attr{request} unless $attr{"request"} eq "smtpd_access_policy"; $action = smtpd_access_policy(); syslog $syslog_priority, "Action: %s", $action if $verbose; print STDOUT "action=$action\n\n"; %attr = (); } else { chop; syslog $syslog_priority, "warning: ignoring garbage: %.100s", $_; } } examples/qmail-local/qmail-local.txt000066600000000737150501202770013523 0ustar00From: Ron Bickers For the archives (or for comment): I now have mailbox_command = /usr/local/libexec/postqmail-local and postqmail-local looks like this (minus some mailer wrapping): #!/bin/sh export PATH=$PATH:/usr/local/bin:/var/qmail/bin tail +2 | seekablepipe qmail-local -- \ "$USER" "$HOME" "$LOCAL" "${EXTENSION:+-}" "$EXTENSION" "$DOMAIN""$SENDER" ./Maildir/ e=$? (($e == 111)) && exit 75 (($e == 100)) && exit 77 exit $e README_FILES/LINUX_README000066600000003216150501202770010267 0ustar00PPoossttffiixx aanndd LLiinnuuxx ------------------------------------------------------------------------------- BBeerrkkeelleeyy DDBB iissssuueess If you can't compile Postfix because the file "db.h" isn't found, then you MUST install the Berkeley DB development package (name: db???-devel-???) that matches your system library. You can find out what is installed with the rpm command. For example: $ rrppmm --qqff //uussrr//lliibb//lliibbddbb..ssoo db4-4.3.29-2 This means that you need to install db4-devel-4.3.29-2 (on some systems, specify "rrppmm --qqff //lliibb//lliibbddbb..ssoo" instead). DO NOT download some Berkeley DB version from the network. Every Postfix program will dump core when it is built with a different Berkeley DB version than the version that is used by the system library routines. See the DB_README file for further information. PPrrooccmmaaiill iissssuueess On RedHat Linux 7.1 and later pprrooccmmaaiill no longer has permission to write the mail spool directory. Workaround: # chmod 1777 /var/spool/mail SSyyssllooggdd ppeerrffoorrmmaannccee LINUX ssyyssllooggdd uses synchronous writes by default. Because of this, ssyyssllooggdd can actually use more system resources than Postfix. To avoid such badness, disable synchronous mail logfile writes by editing /etc/syslog.conf and by prepending a - to the logfile name: /etc/syslog.conf: mail.* -/var/log/mail.log Send a "kkiillll --HHUUPP" to the ssyyssllooggdd to make the change effective. README_FILES/PCRE_README000066600000005566150501202770010133 0ustar00PPoossttffiixx PPCCRREE SSuuppppoorrtt ------------------------------------------------------------------------------- PPCCRREE ((PPeerrll CCoommppaattiibbllee RReegguullaarr EExxpprreessssiioonnss)) mmaapp ssuuppppoorrtt The optional "pcre" map type allows you to specify regular expressions with the PERL style notation such as \s for space and \S for non-space. The main benefit, however, is that pcre lookups are often faster than regexp lookups. This is because the pcre implementation is often more efficient than the POSIX regular expression implementation that you find on many systems. A description of how to use pcre tables, including examples, is given in the pcre_table(5) manual page. Information about PCRE itself can be found at http:/ /www.pcre.org/. BBuuiillddiinngg PPoossttffiixx wwiitthh PPCCRREE ssuuppppoorrtt These instructions assume that you build Postfix from source code as described in the INSTALL document. Some modification may be required if you build Postfix from a vendor-specific source package. Note: to use pcre with Debian GNU/Linux's Postfix, all you need is to install the postfix-pcre package and you're done. There is no need to recompile Postfix. In some future, Postfix will have a plug-in interface for adding map types. Until then, you need to compile PCRE support into Postfix. First of all, you need the PCRE library (Perl Compatible Regular Expressions), which can be obtained from: ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/. NOTE: pcre versions prior to 2.06 cannot be used. In order to build Postfix with PCRE support you need to add -DHAS_PCRE and a - I for the PCRE include file to CCARGS, and add the path to the PCRE library to AUXLIBS, for example: make -f Makefile.init makefiles \ "CCARGS=-DHAS_PCRE -I/usr/local/include" \ "AUXLIBS=-L/usr/local/lib -lpcre" Solaris needs run-time path information too: make -f Makefile.init makefiles \ "CCARGS=-DHAS_PCRE -I/usr/local/include" \ "AUXLIBS=-L/usr/local/lib -R/usr/local/lib -lpcre" TThhiinnggss ttoo kknnooww * When Postfix searches a pcre: or regexp: lookup table, each pattern is applied to the entire input string. Depending on the application, that string is an entire client hostname, an entire client IP address, or an entire mail address. Thus, no parent domain or parent network search is done, "user@domain" mail addresses are not broken up into their user and domain constituent parts, and "user+foo" is not broken up into user and foo. * Regular expression tables such as pcre: or regexp: are not allowed to do $number substitution in lookup results that can be security sensitive: currently, that restriction applies to the local aliases(5) database or the virtual(8) delivery agent tables. README_FILES/SASL_README000066600000056454150501202770010146 0ustar00PPoossttffiixx SSAASSLL HHoowwttoo ------------------------------------------------------------------------------- WWAARRNNIINNGG People who go to the trouble of installing Postfix may have the expectation that Postfix is more secure than some other mailers. The Cyrus SASL library is a lot of code. With this, Postfix becomes as secure as other mail systems that use the Cyrus SASL library. Dovecot provides an alternative that may be worth considering. HHooww PPoossttffiixx uusseess SSAASSLL aauutthheennttiiccaattiioonn iinnffoorrmmaattiioonn Postfix SASL support (RFC 4954, formerly RFC 2554) can be used to authenticate remote SMTP clients to the Postfix SMTP server, and to authenticate the Postfix SMTP client to a remote SMTP server. When receiving mail, the Postfix SMTP server logs the client-provided username, authentication method, and sender address to the maillog file, and optionally grants mail access via the permit_sasl_authenticated UCE restriction. When sending mail, the Postfix SMTP client can look up the remote SMTP server hostname or destination domain (the address right-hand part) in a SASL password table, and if a username/password is found, it will use that username and password to authenticate to the remote SMTP server. And as of version 2.3, Postfix can be configured to search its SASL password table by the sender email address. This document covers the following topics: * What SASL implementations are supported * Building Postfix with Dovecot SASL support * Building the Cyrus SASL library * Building Postfix with Cyrus SASL support * Enabling SASL authentication in the Postfix SMTP server * Dovecot SASL configuration for the Postfix SMTP server * Cyrus SASL configuration for the Postfix SMTP server * Testing SASL authentication in the Postfix SMTP server * Trouble shooting the SASL internals * Enabling SASL authentication in the Postfix SMTP client * Supporting multiple ISP accounts in the Postfix SMTP client * Credits WWhhaatt SSAASSLL iimmpplleemmeennttaattiioonnss aarree ssuuppppoorrtteedd This document describes Postfix with the following SASL implementations: * Cyrus SASL version 1 (client and server). * Cyrus SASL version 2 (client and server). * Dovecot protocol version 1 (server only, Postfix version 2.3 and later) Postfix version 2.3 introduces a plug-in mechanism that provides support for multiple SASL implementations. To find out what implementations are built into Postfix, use the following commands: % postconf -a (SASL support in the SMTP server) % postconf -A (SASL support in the SMTP+LMTP client) Needless to say, these commands are not available in earlier Postfix versions. BBuuiillddiinngg PPoossttffiixx wwiitthh DDoovveeccoott SSAASSLL ssuuppppoorrtt These instructions assume that you build Postfix from source code as described in the INSTALL document. Some modification may be required if you build Postfix from a vendor-specific source package. Support for the Dovecot version 1 SASL protocol is available in Postfix 2.3 and later. At the time of writing, only server-side SASL support is available, so you can't use it to authenticate to your network provider's server. Dovecot uses its own daemon process for authentication. This keeps the Postfix build process simple, because there is no need to link extra libraries into Postfix. To generate the necessary Makefiles, execute the following in the Postfix top- level directory: % make makefiles CCARGS='-DUSE_SASL_AUTH - DDEF_SERVER_SASL_TYPE=\"dovecot\"' After this, proceed with "make" as described in the INSTALL document. Notes: * The "-DDEF_SERVER_SASL_TYPE" stuff is not necessary; it just makes Postfix configuration a little more convenient because you don't have to specify the SASL plug-in type in the Postfix main.cf file. * If you also want support for LDAP or TLS, you will have to merge their CCARGS and AUXLIBS into the above command line. BBuuiillddiinngg tthhee CCyyrruuss SSAASSLL lliibbrraarryy Postfix appears to work with cyrus-sasl-1.5.x or cyrus-sasl-2.1.x, which are available from: ftp://ftp.andrew.cmu.edu/pub/cyrus-mail/ IMPORTANT: if you install the Cyrus SASL libraries as per the default, you will have to symlink /usr/lib/sasl -> /usr/local/lib/sasl for version 1.5.x or /usr/ lib/sasl2 -> /usr/local/lib/sasl2 for version 2.1.x. Reportedly, Microsoft Outlook (Express) requires the non-standard LOGIN authentication method. To enable this authentication method, specify ``./ configure --enable-login''. BBuuiillddiinngg PPoossttffiixx wwiitthh CCyyrruuss SSAASSLL ssuuppppoorrtt These instructions assume that you build Postfix from source code as described in the INSTALL document. Some modification may be required if you build Postfix from a vendor-specific source package. The following assumes that the Cyrus SASL include files are in /usr/local/ include, and that the Cyrus SASL libraries are in /usr/local/lib. On some systems this generates the necessary Makefile definitions: (for Cyrus SASL version 1.5.x): % make tidy # if you have left-over files from a previous build % make makefiles CCARGS="-DUSE_SASL_AUTH -DUSE_CYRUS_SASL \ -I/usr/local/include" AUXLIBS="-L/usr/local/lib -lsasl" (for Cyrus SASL version 2.1.x): % make tidy # if you have left-over files from a previous build % make makefiles CCARGS="-DUSE_SASL_AUTH -DUSE_CYRUS_SASL \ -I/usr/local/include/sasl" AUXLIBS="-L/usr/local/lib -lsasl2" On Solaris 2.x you need to specify run-time link information, otherwise ld.so will not find the SASL shared library: (for Cyrus SASL version 1.5.x): % make tidy # if you have left-over files from a previous build % make makefiles CCARGS="-DUSE_SASL_AUTH -DUSE_CYRUS_SASL \ -I/usr/local/include" AUXLIBS="-L/usr/local/lib \ -R/usr/local/lib -lsasl" (for Cyrus SASL version 2.1.x): % make tidy # if you have left-over files from a previous build % make makefiles CCARGS="-DUSE_SASL_AUTH -DUSE_CYRUS_SASL \ -I/usr/local/include/sasl" AUXLIBS="-L/usr/local/lib \ -R/usr/local/lib -lsasl2" EEnnaabblliinngg SSAASSLL aauutthheennttiiccaattiioonn iinn tthhee PPoossttffiixx SSMMTTPP sseerrvveerr In order to enable SASL support in the Postfix SMTP server: /etc/postfix/main.cf: smtpd_sasl_auth_enable = yes In order to allow mail relaying by authenticated remote SMTP clients: /etc/postfix/main.cf: smtpd_recipient_restrictions = permit_mynetworks permit_sasl_authenticated reject_unauth_destination To report SASL login names in Received: message headers (Postfix version 2.3 and later): /etc/postfix/main.cf: smtpd_sasl_authenticated_header = yes Note: the SASL login names will be shared with the entire world. Older Microsoft SMTP client software implements a non-standard version of the AUTH protocol syntax, and expects that the SMTP server replies to EHLO with "250 AUTH=mechanism-list" instead of "250 AUTH mechanism-list". To accommodate such clients (in addition to conformant clients) use the following: /etc/postfix/main.cf: broken_sasl_auth_clients = yes DDoovveeccoott SSAASSLL ccoonnffiigguurraattiioonn ffoorr tthhee PPoossttffiixx SSMMTTPP sseerrvveerr Dovecot SASL support is available in Postfix 2.3 and later. On the Postfix side you need to specify the location of the Dovecot authentication daemon socket. We use a pathname relative to the Postfix queue directory, so that it will work whether or not the Postfix SMTP server runs chrooted: /etc/postfix/main.cf: smtpd_sasl_type = dovecot smtpd_sasl_path = private/auth On the Dovecot side you also need to specify the Dovecot authentication daemon socket. In this case we specify an absolute pathname. In the example we assume that the Postfix queue is under /var/spool/postfix/. /some/where/dovecot.conf: auth default { mechanisms = plain login passdb pam { } userdb passwd { } socket listen { client { path = /var/spool/postfix/private/auth mode = 0660 user = postfix group = postfix } } } See the Dovecot documentation for how to configure and operate the Dovecot authentication server. CCyyrruuss SSAASSLL ccoonnffiigguurraattiioonn ffoorr tthhee PPoossttffiixx SSMMTTPP sseerrvveerr You need to configure how the Cyrus SASL library should authenticate a remote SMTP client's username and password. These settings must be stored in a separate configuration file. The name of the configuration file (default: smtpd.conf) will be constructed from a value that the Postfix SMTP server sends to the Cyrus SASL library, which adds the suffix .conf. The value is configured using one of the following variables: /etc/postfix/main.cf: # Postfix 2.3 and later smtpd_sasl_path = smtpd # Postfix < 2.3 smtpd_sasl_application_name = smtpd Cyrus SASL searches for the configuration file in /usr/local/lib/sasl/ (Cyrus SASL version 1.5.5) or /usr/local/lib/sasl2/ (Cyrus SASL version 2.1.x). Note: some Postfix distributions are modified and look for the smtpd.conf file in /etc/postfix/sasl. Note: some Cyrus SASL distributions look for the smtpd.conf file in /etc/sasl2. * To authenticate against the UNIX password database, use: (Cyrus SASL version 1.5.x) /usr/local/lib/sasl/smtpd.conf: pwcheck_method: pwcheck IMPORTANT: pwcheck establishes a UNIX domain socket in /var/pwcheck and waits for authentication requests. The Postfix SMTP server must have read+execute permission to this directory or authentication attempts will fail. The pwcheck daemon is contained in the cyrus-sasl source tarball. (Cyrus SASL version 1.5.26) /usr/local/lib/sasl/smtpd.conf: pwcheck_method: saslauthd (Cyrus SASL version 2.1.x) /usr/local/lib/sasl2/smtpd.conf: pwcheck_method: saslauthd mech_list: PLAIN LOGIN The saslauthd daemon is also contained in the cyrus-sasl source tarball. It is more flexible than the pwcheck daemon, in that it can authenticate against PAM and various other sources. To use PAM, start saslauthd with "- a pam". IMPORTANT: saslauthd usually establishes a UNIX domain socket in /var/run/ saslauthd and waits for authentication requests. The Postfix SMTP server must have read+execute permission to this directory or authentication attempts will fail. Note: The directory where saslauthd puts the socket is configurable. See the command-line option "-m /path/to/socket" in the saslauthd --help listing. * To authenticate against Cyrus SASL's own password database: (Cyrus SASL version 1.5.x) /usr/local/lib/sasl/smtpd.conf: pwcheck_method: sasldb (Cyrus SASL version 2.1.x) /usr/local/lib/sasl2/smtpd.conf: pwcheck_method: auxprop auxprop_plugin: sasldb mech_list: PLAIN LOGIN CRAM-MD5 DIGEST-MD5 This will use the Cyrus SASL password file (default: /etc/sasldb in version 1.5.x, or /etc/sasldb2 in version 2.1.x), which is maintained with the saslpasswd or saslpasswd2 command (part of the Cyrus SASL software). On some poorly-supported systems the saslpasswd command needs to be run multiple times before it stops complaining. The Postfix SMTP server needs read access to the sasldb file - you may have to play games with group access permissions. With the OTP authentication mechanism, the Postfix SMTP server also needs WRITE access to /etc/sasldb2 or /etc/sasldb (or the back end SQL database, if used). IMPORTANT: To get sasldb running, make sure that you set the SASL domain (realm) to a fully qualified domain name. EXAMPLE: (Cyrus SASL version 1.5.x) % saslpasswd -c -u `postconf -h myhostname` exampleuser (Cyrus SASL version 2.1.x) % saslpasswd2 -c -u `postconf -h myhostname` exampleuser You can find out SASL's idea about the realms of the users in sasldb with sasldblistusers (Cyrus SASL version 1.5.x) or sasldblistusers2 (Cyrus SASL version 2.1.x). On the Postfix side, you can have only one realm per smtpd(8) instance, and only the users belonging to that realm would be able to authenticate. The Postfix variable smtpd_sasl_local_domain controls the realm used by smtpd (8): /etc/postfix/main.cf: smtpd_sasl_local_domain = $myhostname IMPORTANT: The Cyrus SASL password verification services pwcheck and saslauthd can only support the plaintext mechanisms PLAIN or LOGIN. However, the Cyrus SASL library doesn't know this, and will happily advertise other authentication mechanisms that the SASL library implements, such as DIGEST-MD5. As a result, if a remote SMTP client chooses any mechanism other than PLAIN or LOGIN while pwcheck or saslauthd are used, authentication will fail. Thus you may need to limit the list of mechanisms advertised by the Postfix SMTP server. * With older Cyrus SASL versions you remove the corresponding library files from the SASL plug-in directory (and again whenever the system is updated). * With Cyrus SASL version 2.1.x or later the mech_list variable can specify a list of authentication mechanisms that Cyrus SASL may offer: /usr/local/lib/sasl2/smtpd.conf: mech_list: plain login For the same reasons you might want to limit the list of plugins used for authentication. * With Cyrus SASL version 1.5.x your only choice is to delete the corresponding library files from the SASL plug-in directory. * With SASL version 2.1.x: /usr/local/lib/sasl2/smtpd.conf: pwcheck_method: auxprop auxprop_plugin: sql To run software chrooted with SASL support is an interesting exercise. It probably is not worth the trouble. TTeessttiinngg SSAASSLL aauutthheennttiiccaattiioonn iinn tthhee PPoossttffiixx SSMMTTPP sseerrvveerr To test the server side, connect (for example, with telnet) to the Postfix SMTP server port and you should be able to have a conversation as shown below. Information sent by the client (that is, you) is shown in bold font. $ tteellnneett sseerrvveerr..eexxaammppllee..ccoomm 2255 . . . 220 server.example.com ESMTP Postfix EEHHLLOO cclliieenntt..eexxaammppllee..ccoomm 250-server.example.com 250-PIPELINING 250-SIZE 10240000 250-ETRN 250-AUTH DIGEST-MD5 PLAIN CRAM-MD5 250 8BITMIME AAUUTTHH PPLLAAIINN AAHHRRllcc33QQAAddGGVVzzddHHBBhhcc33MM== 235 Authentication successful Instead of AHRlc3QAdGVzdHBhc3M=, specify the base64 encoded form of \0username\0password (the \0 is a null byte). The example above is for a user named `test' with password `testpass'. In order to generate base64 encoded authentication information you can use one of the following commands: % printf '\0username\0password' | mmencode % perl -MMIME::Base64 -e \ 'print encode_base64("\0username\0password");' The mmencode command is part of the metamail software. MIME::Base64 is available from http://www.cpan.org/. Caution: when posting logs of the SASL negotiations to public lists, please keep in mind that username/password information is trivial to recover from the base64-encoded form. TTrroouubbllee sshhoooottiinngg tthhee SSAASSLL iinntteerrnnaallss In the Cyrus SASL sources you'll find a subdirectory named "sample". Run make there, then create a symbolic link from sample.conf to smtpd.conf in your Cyrus SASL library directory /usr/local/lib/sasl2. "su" to the user postfix (or whatever your mail_owner directive is set to): % su postfix then run the resulting sample Cyrus SASL server and client in separate terminals. The sample applications send log messages to the syslog facility auth. Check the log to fix the problem or run strace / ktrace / truss on the server to see what makes it unhappy. Repeat the previous step until you can successfully authenticate with the sample Cyrus SASL client. Only then get back to Postfix. EEnnaabblliinngg SSAASSLL aauutthheennttiiccaattiioonn iinn tthhee PPoossttffiixx SSMMTTPP cclliieenntt Turn on client-side SASL authentication, and specify a table with per-host or per-destination username and password information. The Postfix SMTP client first searches the table for an entry with the remote SMTP server hostname; if no entry is found, then the Postfix SMTP client searches the table for an entry with the next-hop destination. Usually, that is the right-hand part of an email address, but it can also be the information that is specified with the relayhost parameter or with a transport(5) table. /etc/postfix/main.cf: smtp_sasl_auth_enable = yes smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd smtp_sasl_type = cyrus relayhost = [mail.myisp.net] # Alternative form: # relayhost = [mail.myisp.net]:submission /etc/postfix/sasl_passwd: [mail.myisp.net] username:password [mail.myisp.net]:submission username:password Notes: * The "submission" destination port tells Postfix to send mail via TCP network port 587, which is normally reserved for email clients. The default is to send mail to the "smtp" destination port (TCP port 25), which is used for receiving mail across the internet. If you use an explicit destination port in main.cf, then you must use the same form also in the smtp_sasl_password_maps file. * Postfix does not deliver mail via TCP port 465 (the obsolete "wrappermode" protocol). See TLS_README for a solution that uses the "stunnel" command. * The "[" and "]" prevent Postfix from looking up the MX (mail exchanger) records for the enclosed name. If you use this form in main.cf, then you must use the same form also in the smtp_sasl_password_maps file. * The Postfix SMTP client opens the SASL client password file before entering the optional chroot jail, so you can keep the file in /etc/postfix and set permissions read / write only for root to keep the username:password combinations away from other system users. * Specify ddbbmm instead of hhaasshh if your system uses ddbbmm files instead of ddbb files. To find out what lookup tables Postfix supports, use the command "ppoossttccoonnff --mm". * Execute the command "ppoossttmmaapp //eettcc//ppoossttffiixx//ssaassll__ppaasssswwdd" whenever you change the sasl_passwd table. Workarounds: * Some remote SMTP servers support PLAIN or LOGIN authentication only. By default, the Postfix SMTP client does not use authentication methods that send plaintext passwords, and defers delivery with the following error message: "Authentication failed: cannot SASL authenticate to server". To enable plaintext authentication specify, for example: /etc/postfix/main.cf: smtp_sasl_security_options = noanonymous * Some remote SMTP servers announce authentication mechanisms that don't actually work. It is possible via the smtp_sasl_mechanism_filter parameter to restrict the list of server mechanisms that the Postfix SMTP client will take into consideration: /etc/postfix/main.cf: smtp_sasl_mechanism_filter = !gssapi, !external, static:all In the above example, the Postfix SMTP client will decline to use mechanisms that require special infrastructure such as Kerberos or TLS. * The Postfix SMTP client is backwards compatible with SMTP servers that use the non-standard "AUTH=method..." syntax in response to the EHLO command; there is no Postfix client configuration needed to work around it. SSuuppppoorrttiinngg mmuullttiippllee IISSPP aaccccoouunnttss iinn tthhee PPoossttffiixx SSMMTTPP cclliieenntt Postfix version 2.3 supports multiple ISP accounts. This can be useful when one person uses the same machine for work and for personal use, or when people with different ISP accounts share the same Postfix server. To make this possible, Postfix 2.3 supports per-sender SASL passwords and per-sender relay hosts. In the example below, Postfix will search the SASL password file by sender before it searches that same file by destination. Likewise, Postfix will search the per-sender relayhost file, and use the default relayhost only as a final resort. /etc/postfix/main.cf: smtp_sender_dependent_authentication = yes sender_dependent_relayhost_maps = hash:/etc/postfix/sender_relay smtp_sasl_auth_enable = yes smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd relayhost = [mail.myisp.net] # Alternative form: # relayhost = [mail.myisp.net]:submission /etc/postfix/sasl_passwd: # Per-sender authentication; see also /etc/postfix/sender_relay. user1@example.com username2:password2 user2@example.net username2:password2 # Login information for the default relayhost. [mail.myisp.net] username:password [mail.myisp.net]:submission username:password /etc/postfix/sender_relay: # Per-sender provider; see also /etc/postfix/sasl_passwd. user1@example.com [mail.example.com]:submission user2@example.net [mail.example.net] Notes: * If you are creative, then you can try to combine the two tables into one single MySQL database, and configure different Postfix queries to extract the appropriate information. * Specify ddbbmm instead of hhaasshh if your system uses ddbbmm files instead of ddbb files. To find out what lookup tables Postfix supports, use the command "ppoossttccoonnff --mm". * Execute the command "ppoossttmmaapp //eettcc//ppoossttffiixx//ssaassll__ppaasssswwdd" whenever you change the sasl_passwd table. * Execute the command "ppoossttmmaapp //eettcc//ppoossttffiixx//sseennddeerr__rreellaayy" whenever you change the sender_relay table. CCrreeddiittss * Postfix SASL support was originally implemented by Till Franke of SuSE Rhein/Main AG. * Wietse trimmed down the code to only the bare necessities. * Support for Cyrus SASL version 2 was contributed by Jason Hoos. * Liviu Daia added smtpd_sasl_application_name, split reject_sender_login_mismatch into reject_authenticated_sender_login_mismatch and reject_unauthenticated_sender_login_mismatch, and revised the docs. * Wietse made another iteration through the code to add plug-in support for multiple SASL implementations, and changed smtpd_sasl_application_name into smtpd_sasl_path. * The Dovecot SMTP server-only plug-in was originally implemented by Timo Sirainen of Procontrol, Finland. * Patrick Ben Koetter revised this document for Postfix 2.4 and made much needed updates. README_FILES/TLS_README000066600000300145150501202770010033 0ustar00PPoossttffiixx TTLLSS SSuuppppoorrtt ------------------------------------------------------------------------------- WWAARRNNIINNGG By turning on TLS support in Postfix, you not only get the ability to encrypt mail and to authenticate remote SMTP clients or servers. You also turn on thousands and thousands of lines of OpenSSL library code. Assuming that OpenSSL is written as carefully as Wietse's own code, every 1000 lines introduce one additional bug into Postfix. WWhhaatt PPoossttffiixx TTLLSS ssuuppppoorrtt ddooeess ffoorr yyoouu Transport Layer Security (TLS, formerly called SSL) provides certificate-based authentication and encrypted sessions. An encrypted session protects the information that is transmitted with SMTP mail or with SASL authentication. This document describes a TLS user interface that was introduced with Postfix version 2.3. Support for an older user interface is documented in TLS_LEGACY_README, which also describes the differences between Postfix and the third-party patch on which Postfix version 2.2 TLS support was based. Topics covered in this document: * How Postfix TLS support works * Building Postfix with TLS support * SMTP Server specific settings * SMTP Client specific settings * TLS manager specific settings * Reporting problems * Credits And last but not least, for the impatient: * Getting started, quick and dirty HHooww PPoossttffiixx TTLLSS ssuuppppoorrtt wwoorrkkss The diagram below shows the main elements of the Postfix TLS architecture and their relationships. Colored boxes with numbered names represent Postfix daemon programs. Other colored boxes represent storage elements. * The smtpd(8) server implements the SMTP over TLS server side. * The smtp(8) client implements the SMTP over TLS client side. * The tlsmgr(8) server maintains the pseudo-random number generator (PRNG) that seeds the TLS engines in the smtpd(8) server and smtp(8) client processes, and maintains the TLS session key cache files. <---seed---- ----seed---> Network-> smtpd(8) tlsmgr(8) smtp(8) ->Network <-key/cert-> <-key/cert-> / | \ | / \ smtpd PRNG smtp session state session key cache file key cache BBuuiillddiinngg PPoossttffiixx wwiitthh TTLLSS ssuuppppoorrtt These instructions assume that you build Postfix from source code as described in the INSTALL document. Some modification may be required if you build Postfix from a vendor-specific source package. To build Postfix with TLS support, first we need to generate the make(1) files with the necessary definitions. This is done by invoking the command "make makefiles" in the Postfix top-level directory and with arguments as shown next. NNOOTTEE:: DDoo nnoott uussee GGnnuu TTLLSS.. IItt wwiillll ssppoonnttaanneeoouussllyy tteerrmmiinnaattee aa PPoossttffiixx ddaaeemmoonn pprroocceessss wwiitthh eexxiitt ssttaattuuss ccooddee 22,, iinnsstteeaadd ooff aalllloowwiinngg PPoossttffiixx ttoo 11)) rreeppoorrtt tthhee eerrrroorr ttoo tthhee mmaaiilllloogg ffiillee,, aanndd ttoo 22)) pprroovviiddee ppllaaiinntteexxtt sseerrvviiccee wwhheerree tthhiiss iiss aapppprroopprriiaattee.. * If the OpenSSL include files (such as ssl.h) are in directory /usr/include/ openssl, and the OpenSSL libraries (such as libssl.so and libcrypto.so) are in directory /usr/lib: % mmaakkee ttiiddyy # if you have left-over files from a previous build % mmaakkee mmaakkeeffiilleess CCCCAARRGGSS==""--DDUUSSEE__TTLLSS"" AAUUXXLLIIBBSS==""--llssssll --llccrryyppttoo"" * If the OpenSSL include files (such as ssl.h) are in directory /usr/local/ include/openssl, and the OpenSSL libraries (such as libssl.so and libcrypto.so) are in directory /usr/local/lib: % mmaakkee ttiiddyy # if you have left-over files from a previous build % mmaakkee mmaakkeeffiilleess CCCCAARRGGSS==""--DDUUSSEE__TTLLSS --II//uussrr//llooccaall//iinncclluuddee"" \\ AAUUXXLLIIBBSS==""--LL//uussrr//llooccaall//lliibb --llssssll --llccrryyppttoo"" On Solaris, specify the -R option as shown below: % mmaakkee ttiiddyy # if you have left-over files from a previous build % mmaakkee mmaakkeeffiilleess CCCCAARRGGSS==""--DDUUSSEE__TTLLSS --II//uussrr//llooccaall//iinncclluuddee"" \\ AAUUXXLLIIBBSS==""--RR//uussrr//llooccaall//lliibb --LL//uussrr//llooccaall//lliibb --llssssll --llccrryyppttoo"" If you need to apply other customizations (such as Berkeley DB databases, MySQL, PostgreSQL, LDAP or SASL), see the respective Postfix README documents, and combine their "make makefiles" instructions with the instructions above: % mmaakkee ttiiddyy # if you have left-over files from a previous build % mmaakkee mmaakkeeffiilleess CCCCAARRGGSS==""--DDUUSSEE__TTLLSS \\ ((ootthheerr --DD oorr --II ooppttiioonnss))"" \\ AAUUXXLLIIBBSS==""--llssssll --llccrryyppttoo \\ ((ootthheerr --ll ooppttiioonnss ffoorr lliibbrraarriieess iinn //uussrr//lliibb)) \\ ((--LL//ppaatthh//nnaammee ++ --ll ooppttiioonnss ffoorr ootthheerr lliibbrraarriieess))"" To complete the build process, see the Postfix INSTALL instructions. Postfix has TLS support turned off by default, so you can start using Postfix as soon as it is installed. SSMMTTPP SSeerrvveerr ssppeecciiffiicc sseettttiinnggss Topics covered in this section: * Server-side certificate and private key configuration * Server-side TLS activity logging * Enabling TLS in the Postfix SMTP server * Client certificate verification * Supporting AUTH over TLS only * Server-side TLS session cache * Server access control * Server-side cipher controls * Miscellaneous server controls SSeerrvveerr--ssiiddee cceerrttiiffiiccaattee aanndd pprriivvaattee kkeeyy ccoonnffiigguurraattiioonn In order to use TLS, the Postfix SMTP server generally needs a certificate and a private key. Both must be in "PEM" format. The private key must not be encrypted, meaning: the key must be accessible without a password. The certificate and private key may be in the same file, in which case the certificate file should be owned by "root" and not be readable by any other user. If the key is stored separately, this applies to the key file only, and the certificate file may be "world-readable". Public Internet MX hosts without certificates signed by a "reputable" CA must generate, and be prepared to present to most clients, a self-signed or private- CA signed certificate. The remote SMTP client will generally not be able to authenticate the self-signed certificate, but unless the client is running Postfix 2.3 or similar software, it will still insist on a server certificate. For servers that are nnoott public Internet MX hosts, Postfix supports configurations with no certificates. This entails the use of just the anonymous TLS ciphers, which are not supported by typical SMTP clients. Since such clients will not, as a rule, fall back to plain text after a TLS handshake failure, a certificate-less Postfix SMTP server will be unable to receive email from most TLS enabled clients. To avoid accidental configurations with no certificates, Postfix enables certificate-less operation only when the administrator explicitly sets "smtpd_tls_cert_file = none". This ensures that new Postfix SMTP server configurations will not accidentally run with no certificates. RSA, DSA and ECDSA (Postfix >= 2.6) certificates are supported. Typically you will only have RSA certificates issued by a commercial CA. In addition, the tools supplied with OpenSSL will by default issue RSA certificates. You can configure all three at the same time, in which case the cipher used determines which certificate is presented. For Netscape and OpenSSL clients without special cipher choices, the RSA certificate is preferred. To enable a remote SMTP client to verify the Postfix SMTP server certificate, the issuing CA certificates must be made available to the client. You should include the required certificates in the server certificate file, the server certificate first, then the issuing CA(s) (bottom-up order). Example: the certificate for "server.example.com" was issued by "intermediate CA" which itself has a certificate issued by "root CA". Create the server.pem file with: % ccaatt sseerrvveerr__cceerrtt..ppeemm iinntteerrmmeeddiiaattee__CCAA..ppeemm >> sseerrvveerr..ppeemm A Postfix SMTP server certificate supplied here must be usable as SSL server certificate and hence pass the "openssl verify -purpose sslserver ..." test. A client that trusts the root CA has a local copy of the root CA certificate, so it is not necessary to include the root CA certificate here. Leaving it out of the "server.pem" file reduces the overhead of the TLS exchange. If you want the Postfix SMTP server to accept remote SMTP client certificates issued by these CAs, append the root certificate to $smtpd_tls_CAfile or install it in the $smtpd_tls_CApath directory. RSA key and certificate examples: /etc/postfix/main.cf: smtpd_tls_cert_file = /etc/postfix/server.pem smtpd_tls_key_file = $smtpd_tls_cert_file Their DSA counterparts: /etc/postfix/main.cf: smtpd_tls_dcert_file = /etc/postfix/server-dsa.pem smtpd_tls_dkey_file = $smtpd_tls_dcert_file Their ECDSA counterparts (Postfix >= 2.6 + OpenSSL >= 0.9.9): /etc/postfix/main.cf: # Most clients will not be ECDSA capable, so you will likely also need # an RSA or DSA certificate and private key. # smtpd_tls_eccert_file = /etc/postfix/server-ecdsa.pem smtpd_tls_eckey_file = $smtpd_tls_eccert_file TLS without certificates for servers serving exclusively anonymous-cipher capable clients: /etc/postfix/main.cf: smtpd_tls_cert_file = none To verify a remote SMTP client certificate, the Postfix SMTP server needs to trust the certificates of the issuing certification authorities. These certificates in "PEM" format can be stored in a single $smtpd_tls_CAfile or in multiple files, one CA per file in the $smtpd_tls_CApath directory. If you use a directory, don't forget to create the necessary "hash" links with: # $$OOPPEENNSSSSLL__HHOOMMEE//bbiinn//cc__rreehhaasshh //ppaatthh//ttoo//ddiirreeccttoorryy The $smtpd_tls_CAfile contains the CA certificates of one or more trusted CAs. The file is opened (with root privileges) before Postfix enters the optional chroot jail and so need not be accessible from inside the chroot jail. Additional trusted CAs can be specified via the $smtpd_tls_CApath directory, in which case the certificates are read (with $mail_owner privileges) from the files in the directory when the information is needed. Thus, the $smtpd_tls_CApath directory needs to be accessible inside the optional chroot jail. When you configure the Postfix SMTP server to request client certificates, the DNs of certificate authorities in $smtpd_tls_CAfile are sent to the client, in order to allow it to choose an identity signed by a CA you trust. If no $smtpd_tls_CAfile is specified, no preferred CA list is sent, and the client is free to choose an identity signed by any CA. Many clients use a fixed identity regardless of the preferred CA list and you may be able to reduce TLS negotiation overhead by installing client CA certificates mostly or only in $smtpd_tls_CApath. In the latter case you need not specify a $smtpd_tls_CAfile. Note, that unless client certificates are used to allow greater access to TLS authenticated clients, it is best to not ask for client certificates at all, as in addition to increased overhead some clients (notably in some cases qmail) are unable to complete the TLS handshake when client certificates are requested. Example: /etc/postfix/main.cf: smtpd_tls_CAfile = /etc/postfix/CAcert.pem smtpd_tls_CApath = /etc/postfix/certs SSeerrvveerr--ssiiddee TTLLSS aaccttiivviittyy llooggggiinngg To get additional information about Postfix SMTP server TLS activity you can increase the log level from 0..4. Each logging level also includes the information that is logged at a lower logging level. 0 Disable logging of TLS activity. 1 Log TLS handshake and certificate information. 2 Log levels during TLS negotiation. 3 Log hexadecimal and ASCII dump of TLS negotiation process 4 Log hexadecimal and ASCII dump of complete transmission after STARTTLS Use log level 3 only in case of problems. Use of log level 4 is strongly discouraged. Example: /etc/postfix/main.cf: smtpd_tls_loglevel = 0 To include information about the protocol and cipher used as well as the client and issuer CommonName into the "Received:" message header, set the smtpd_tls_received_header variable to true. The default is no, as the information is not necessarily authentic. Only information recorded at the final destination is reliable, since the headers may be changed by intermediate servers. Example: /etc/postfix/main.cf: smtpd_tls_received_header = yes EEnnaabblliinngg TTLLSS iinn tthhee PPoossttffiixx SSMMTTPP sseerrvveerr By default, TLS is disabled in the Postfix SMTP server, so no difference to plain Postfix is visible. Explicitly switch it on with "smtpd_tls_security_level = may" (Postfix 2.3 and later) or "smtpd_use_tls = yes" (obsolete but still supported). Example: /etc/postfix/main.cf: # Postfix 2.3 and later smtpd_tls_security_level = may # Obsolete, but still supported smtpd_use_tls = yes With this, the Postfix SMTP server announces STARTTLS support to remote SMTP clients, but does not require that clients use TLS encryption. Note: when an unprivileged user invokes "sendmail -bs", STARTTLS is never offered due to insufficient privileges to access the Postfix SMTP server private key. This is intended behavior. You can ENFORCE the use of TLS, so that the Postfix SMTP server announces STARTTLS and accepts no mail without TLS encryption, by setting "smtpd_tls_security_level = encrypt" (Postfix 2.3 and later) or "smtpd_enforce_tls = yes" (obsolete but still supported). According to RFC 2487 this MUST NOT be applied in case of a publicly-referenced Postfix SMTP server. This option is off by default and should only seldom be used. Example: /etc/postfix/main.cf: # Postfix 2.3 and later smtpd_tls_security_level = encrypt # Obsolete, but still supported smtpd_enforce_tls = yes TLS is sometimes used in the non-standard "wrapper" mode where a server always uses TLS, instead of announcing STARTTLS support and waiting for remote SMTP clients to request TLS service. Some clients, namely Outlook [Express] prefer the "wrapper" mode. This is true for OE (Win32 < 5.0 and Win32 >=5.0 when run on a port<>25 and OE (5.01 Mac on all ports). It is strictly discouraged to use this mode from main.cf. If you want to support this service, enable a special port in master.cf and specify "- o smtpd_tls_wrappermode=yes" (note: no space around the "=") as an smtpd(8) command line option. Port 465 (smtps) was once chosen for this feature. Example: /etc/postfix/master.cf: smtps inet n - n - - smtpd -o smtpd_tls_wrappermode=yes -o smtpd_sasl_auth_enable=yes CClliieenntt cceerrttiiffiiccaattee vveerriiffiiccaattiioonn To receive a remote SMTP client certificate, the Postfix SMTP server must explicitly ask for one (any contents of $smtpd_tls_CAfile are also sent to the client as a hint for choosing a certificate from a suitable CA). Unfortunately, Netscape clients will either complain if no matching client certificate is available or will offer the user client a list of certificates to choose from. Additionally some MTAs (notably some versions of qmail) are unable to complete TLS negotiation when client certificates are requested, and abort the SMTP session. So this option is "off" by default. You will however need the certificate if you want to use certificate based relaying with, for example, the permit_tls_clientcerts feature. A server that wants client certificates must first present its own certificate. While Postfix 2.3 by default offers anonymous ciphers to remote SMTP clients, these are automatically suppressed when the Postfix SMTP server is configured to ask for client certificates. Example: /etc/postfix/main.cf: smtpd_tls_ask_ccert = yes # Postfix 2.3 and later smtpd_tls_security_level = may # Obsolete, but still supported smtpd_use_tls = yes When TLS is enforced you may also decide to REQUIRE a remote SMTP client certificate for all TLS connections, by setting "smtpd_tls_req_ccert = yes". This feature implies "smtpd_tls_ask_ccert = yes". When TLS is not enforced, "smtpd_tls_req_ccert = yes" is ignored and a warning is logged. Example: /etc/postfix/main.cf: smtpd_tls_req_ccert = yes # Postfix 2.3 and later smtpd_tls_security_level = encrypt # Obsolete, but still supported smtpd_enforce_tls = yes The client certificate verification depth is specified with the main.cf smtpd_tls_ccert_verifydepth parameter. The default verification depth is 9 (the OpenSSL default), for compatibility with Postfix versions before 2.5 where smtpd_tls_ccert_verifydepth was ignored. When you configure trust in a root CA, it is not necessary to explicitly trust intermediary CAs signed by the root CA, unless $smtpd_tls_ccert_verifydepth is less than the number of CAs in the certificate chain for the clients of interest. With a verify depth of 1 you can only verify certificates directly signed by a trusted CA, and all trusted intermediary CAs need to be configured explicitly. With a verify depth of 2 you can verify clients signed by a root CA or a direct intermediary CA (so long as the client is correctly configured to supply its intermediate CA certificate). Example: /etc/postfix/main.cf: smtpd_tls_ccert_verifydepth = 2 SSuuppppoorrttiinngg AAUUTTHH oovveerr TTLLSS oonnllyy Sending AUTH data over an unencrypted channel poses a security risk. When TLS layer encryption is required ("smtpd_tls_security_level = encrypt" or the obsolete "smtpd_enforce_tls = yes"), the Postfix SMTP server will announce and accept AUTH only after the TLS layer has been activated with STARTTLS. When TLS layer encryption is optional ("smtpd_tls_security_level = may" or the obsolete "smtpd_enforce_tls = no"), it may however still be useful to only offer AUTH when TLS is active. To maintain compatibility with non-TLS clients, the default is to accept AUTH without encryption. In order to change this behavior, set "smtpd_tls_auth_only = yes". Example: /etc/postfix/main.cf: smtpd_tls_auth_only = no SSeerrvveerr--ssiiddee TTLLSS sseessssiioonn ccaacchhee The Postfix SMTP server and the remote SMTP client negotiate a session, which takes some computer time and network bandwidth. By default, this session information is cached only in the smtpd(8) process actually using this session and is lost when the process terminates. To share the session information between multiple smtpd(8) processes, a persistent session cache can be used. You can specify any database type that can store objects of several kbytes and that supports the sequence operator. DBM databases are not suitable because they can only store small objects. The cache is maintained by the tlsmgr(8) process, so there is no problem with concurrent access. Session caching is highly recommended, because the cost of repeatedly negotiating TLS session keys is high. Example: /etc/postfix/main.cf: smtpd_tls_session_cache_database = btree:/var/lib/postfix/smtpd_scache Note: as of version 2.5, Postfix no longer uses root privileges when opening this file. The file should now be stored under the Postfix-owned data_directory. As a migration aid, an attempt to open the file under a non- Postfix directory is redirected to the Postfix-owned data_directory, and a warning is logged. Cached Postfix SMTP server session information expires after a certain amount of time. Postfix/TLS does not use the OpenSSL default of 300s, but a longer time of 3600sec (=1 hour). RFC 2246 recommends a maximum of 24 hours. Example: /etc/postfix/main.cf: smtpd_tls_session_cache_timeout = 3600s When the Postfix SMTP server does not save TLS sessions to an external cache database, client-side session caching is unlikely to be useful. To prevent such wastage, the Postfix SMTP server can be configured to not issue TLS session ids. By default the Postfix SMTP server always issues TLS session ids. This works around known interoperability issues with some MUAs, and prevents possible interoperability issues with other MTAs. Example: smtpd_tls_always_issue_session_ids = no SSeerrvveerr aacccceessss ccoonnttrrooll Postfix TLS support introduces three additional features for Postfix SMTP server access control: permit_tls_clientcerts Allow the remote SMTP client request if the client certificate fingerprint is listed in the client certificate table (see relay_clientcerts discussion below). permit_tls_all_clientcerts Allow the remote SMTP client request if the client certificate passes trust chain verification. Useful with private-label CAs that only issue certificates to trusted clients (and not otherwise). check_ccert_access type:table Use the remote SMTP client certificate fingerprint as the lookup key for the specified access(5) table. The digest algorithm used to construct the client certificate fingerprints is specified with the main.cf smtpd_tls_fingerprint_digest parameter. The default is "md5", for compatibility with Postfix versions < 2.5. The permit_tls_all_clientcerts feature must be used with caution, because it can result in too many access permissions. Use this feature only if a special CA issues the client certificates, and only if this CA is listed as trusted CA. If other CAs are trusted, any owner of a valid client certificate would be authorized. The permit_tls_all_clientcerts feature can be practical for a specially created email relay server. It is however recommended to stay with the permit_tls_clientcerts feature and list all certificates via $relay_clientcerts, as permit_tls_all_clientcerts does not permit any control when a certificate must no longer be used (e.g. an employee leaving). Example: /etc/postfix/main.cf: smtpd_recipient_restrictions = ... permit_tls_clientcerts reject_unauth_destination ... Example: Postfix lookup tables are in the form of (key, value) pairs. Since we only need the key, the value can be chosen freely, e.g. the name of the user or host: /etc/postfix/main.cf: relay_clientcerts = hash:/etc/postfix/relay_clientcerts /etc/postfix/relay_clientcerts: D7:04:2F:A7:0B:8C:A5:21:FA:31:77:E1:41:8A:EE:80 lutzpc.at.home SSeerrvveerr--ssiiddee cciipphheerr ccoonnttrroollss The description below is for Postfix 2.3; for Postfix < 2.3 the smtpd_tls_cipherlist parameter specifies the acceptable ciphers as an explicit OpenSSL cipherlist. The obsolete setting applies even when TLS encryption is not enforced. Use of this control on public MX hosts is strongly discouraged. The Postfix SMTP server supports 5 distinct cipher security levels as specified by the smtpd_tls_mandatory_ciphers configuration parameter, which determines the cipher grade with mandatory TLS encryption. The default value is "medium" which is essentially 128-bit encryption or better. With opportunistic TLS encryption, the minimum accepted cipher grade is typically "export". The corresponding smtpd_tls_ciphers parameter (Postfix >= 2.6) controls the cipher grade used with opportunistic TLS. By default anonymous ciphers are enabled. They are automatically disabled when remote SMTP client certificates are requested. If clients are expected to always verify the Postfix SMTP server certificate you may want to disable anonymous ciphers by setting "smtpd_tls_mandatory_exclude_ciphers = aNULL" or "smtpd_tls_exclude_ciphers = aNULL", as appropriate. One can't force a remote SMTP client to check the server certificate, so excluding anonymous ciphers is generally unnecessary. The "smtpd_tls_ciphers" configuration parameter (Postfix >= 2.6) provides control over the minimum cipher grade for opportunistic TLS. With Postfix < 2.6, the minimum opportunistic TLS cipher grade is always "export". With mandatory TLS encryption, the Postfix SMTP server will by default only use SSLv3 or TLSv1. SSLv2 is only used when TLS encryption is optional. The mandatory TLS protocol list is specified via the smtpd_tls_mandatory_protocols configuration parameter. The corresponding smtpd_tls_protocols parameter (Postfix >= 2.6) controls the SSL/TLS protocols used with opportunistic TLS. For a server that is not a public Internet MX host, Postfix (>= 2.3) supports configurations with no server certificates that use oonnllyy the anonymous ciphers. This is enabled by explicitly setting "smtpd_tls_cert_file = none" and not specifying an smtpd_tls_dcert_file or smtpd_tls_eccert_file. Example, MSA that requires TLSv1, not SSLv2 or SSLv3, with high grade ciphers: /etc/postfix/main.cf: smtpd_tls_cert_file = /etc/postfix/cert.pem smtpd_tls_key_file = /etc/postfix/key.pem smtpd_tls_mandatory_ciphers = high smtpd_tls_mandatory_exclude_ciphers = aNULL, MD5 smtpd_tls_security_level = encrypt smtpd_tls_mandatory_protocols = TLSv1 # Also available with Postfix >= 2.5: smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3 If you want to take advantage of ciphers with ephemeral Diffie-Hellman (EDH) key exchange (this offers "forward-secrecy"), DH parameters are needed. Instead of using the built-in DH parameters for both 1024-bit (non-export ciphers) and 512-bit (export ciphers), it is better to generate your own parameters, since otherwise it would "pay" for a possible attacker to start a brute force attack against parameters that are used by everybody. Postfix defaults to compiled-in parameters that are shared by all Postfix users who don't generate their own settings. To generate your own set of DH parameters, use: % ooppeennssssll ggeennddhh --oouutt //eettcc//ppoossttffiixx//ddhh__551122..ppeemm --22 551122 % ooppeennssssll ggeennddhh --oouutt //eettcc//ppoossttffiixx//ddhh__11002244..ppeemm --22 11002244 Support for elliptic curve cryptography is available with Postfix 2.6 and OpenSSL 0.9.9 or later. To enable ephemeral elliptic curve Diffie-Hellman (EECDH) key-exchange, set "smtpd_tls_eecdh_grade = strong" or "smtpd_tls_eecdh_grade = ultra". The "ultra" setting is substantially more CPU intensive, and "strong" is sufficiently secure for most situations. Examples: /etc/postfix/main.cf: smtpd_tls_dh1024_param_file = /etc/postfix/dh_1024.pem smtpd_tls_dh512_param_file = /etc/postfix/dh_512.pem # Postfix >= 2.6: smtpd_tls_eecdh_grade = strong MMiisscceellllaanneeoouuss sseerrvveerr ccoonnttrroollss The smtpd_starttls_timeout parameter limits the time of Postfix SMTP server write and read operations during TLS startup and shutdown handshake procedures. Example: /etc/postfix/main.cf: smtpd_starttls_timeout = 300s SSMMTTPP CClliieenntt ssppeecciiffiicc sseettttiinnggss Topics covered in this section: * TLS support in the LMTP delivery agent * Client-side certificate and private key configuration * Client-side TLS activity logging * Client-side TLS session cache * Client TLS limitations * Configuring TLS in the SMTP/LMTP client * Per-destination TLS policy * Obsolete per-site TLS policy support * Closing a DNS loophole with obsolete per-site TLS policies * Discovering servers that support TLS * Server certificate verification depth * Client-side cipher controls * Client-side SMTPS support * Miscellaneous client controls TTLLSS ssuuppppoorrtt iinn tthhee LLMMTTPP ddeelliivveerryy aaggeenntt The smtp(8) and lmtp(8) delivery agents are implemented by a single dual- purpose program. Specifically, all the TLS features described below apply equally to SMTP and LMTP, after replacing the "smtp_" prefix of the each parameter name with "lmtp_". The Postfix LMTP delivery agent can communicate with LMTP servers listening on UNIX-domain sockets. When server certificate verification is enabled and the server is listening on a UNIX-domain socket, the $myhostname parameter is used to set the TLS verification nexthop and hostname. Note, opportunistic encryption of LMTP traffic over UNIX-domain sockets is futile. TLS is only useful in this context when it is mandatory, typically to allow at least one of the server or the client to authenticate the other. The "null" cipher grade may be appropriate in this context, when available on both client and server. The "null" ciphers provide authentication without encryption. CClliieenntt--ssiiddee cceerrttiiffiiccaattee aanndd pprriivvaattee kkeeyy ccoonnffiigguurraattiioonn Do not configure Postfix SMTP client certificates unless you mmuusstt present client TLS certificates to one or more servers. Client certificates are not usually needed, and can cause problems in configurations that work well without them. The recommended setting is to let the defaults stand: smtp_tls_cert_file = smtp_tls_dcert_file = smtp_tls_key_file = smtp_tls_dkey_file = # Postfix >= 2.6 smtp_tls_eccert_file = smtp_tls_eckey_file = The best way to use the default settings is to comment out the above parameters in main.cf if present. During TLS startup negotiation the Postfix SMTP client may present a certificate to the remote SMTP server. The Netscape client is rather clever here and lets the user select between only those certificates that match CA certificates offered by the remote SMTP server. As the Postfix SMTP client uses the "SSL_connect()" function from the OpenSSL package, this is not possible and we have to choose just one certificate. So for now the default is to use _no_ certificate and key unless one is explicitly specified here. RSA, DSA and ECDSA (Postfix >= 2.6) certificates are supported. You can configure all three at the same time, in which case the cipher used determines which certificate is presented. It is possible for the Postfix SMTP client to use the same key/certificate pair as the Postfix SMTP server. If a certificate is to be presented, it must be in "PEM" format. The private key must not be encrypted, meaning: it must be accessible without password. Both parts (certificate and private key) may be in the same file. To enable remote SMTP servers to verify the Postfix SMTP client certificate, the issuing CA certificates must be made available to the server. You should include the required certificates in the client certificate file, the client certificate first, then the issuing CA(s) (bottom-up order). Example: the certificate for "client.example.com" was issued by "intermediate CA" which itself has a certificate issued by "root CA". Create the client.pem file with: % ccaatt cclliieenntt__cceerrtt..ppeemm iinntteerrmmeeddiiaattee__CCAA..ppeemm >> cclliieenntt..ppeemm A Postfix SMTP client certificate supplied here must be usable as SSL client certificate and hence pass the "openssl verify -purpose sslclient ..." test. A server that trusts the root CA has a local copy of the root CA certificate, so it is not necessary to include the root CA certificate here. Leaving it out of the "client.pem" file reduces the overhead of the TLS exchange. If you want the Postfix SMTP client to accept remote SMTP server certificates issued by these CAs, append the root certificate to $smtp_tls_CAfile or install it in the $smtp_tls_CApath directory. RSA key and certificate examples: /etc/postfix/main.cf: smtp_tls_cert_file = /etc/postfix/client.pem smtp_tls_key_file = $smtp_tls_cert_file Their DSA counterparts: /etc/postfix/main.cf: smtp_tls_dcert_file = /etc/postfix/client-dsa.pem smtp_tls_dkey_file = $smtp_tls_dcert_file Their ECDSA counterparts (Postfix >= 2.6 + OpenSSL >= 0.9.9): /etc/postfix/main.cf: smtp_tls_eccert_file = /etc/postfix/client-ecdsa.pem smtp_tls_eckey_file = $smtp_tls_eccert_file To verify a remote SMTP server certificate, the Postfix SMTP client needs to trust the certificates of the issuing certification authorities. These certificates in "pem" format can be stored in a single $smtp_tls_CAfile or in multiple files, one CA per file in the $smtp_tls_CApath directory. If you use a directory, don't forget to create the necessary "hash" links with: # $$OOPPEENNSSSSLL__HHOOMMEE//bbiinn//cc__rreehhaasshh //ppaatthh//ttoo//ddiirreeccttoorryy The $smtp_tls_CAfile contains the CA certificates of one or more trusted CAs. The file is opened (with root privileges) before Postfix enters the optional chroot jail and so need not be accessible from inside the chroot jail. Additional trusted CAs can be specified via the $smtp_tls_CApath directory, in which case the certificates are read (with $mail_owner privileges) from the files in the directory when the information is needed. Thus, the $smtp_tls_CApath directory needs to be accessible inside the optional chroot jail. The choice between $smtp_tls_CAfile and $smtp_tls_CApath is a space/time tradeoff. If there are many trusted CAs, the cost of preloading them all into memory may not pay off in reduced access time when the certificate is needed. Example: /etc/postfix/main.cf: smtp_tls_CAfile = /etc/postfix/CAcert.pem smtp_tls_CApath = /etc/postfix/certs CClliieenntt--ssiiddee TTLLSS aaccttiivviittyy llooggggiinngg To get additional information about Postfix SMTP client TLS activity you can increase the loglevel from 0..4. Each logging level also includes the information that is logged at a lower logging level. 0 Disable logging of TLS activity. 1 Log TLS handshake and certificate information. 2 Log levels during TLS negotiation. 3 Log hexadecimal and ASCII dump of TLS negotiation process 4 Log hexadecimal and ASCII dump of complete transmission after STARTTLS Example: /etc/postfix/main.cf: smtp_tls_loglevel = 0 CClliieenntt--ssiiddee TTLLSS sseessssiioonn ccaacchhee The remote SMTP server and the Postfix SMTP client negotiate a session, which takes some computer time and network bandwidth. By default, this session information is cached only in the smtp(8) process actually using this session and is lost when the process terminates. To share the session information between multiple smtp(8) processes, a persistent session cache can be used. You can specify any database type that can store objects of several kbytes and that supports the sequence operator. DBM databases are not suitable because they can only store small objects. The cache is maintained by the tlsmgr(8) process, so there is no problem with concurrent access. Session caching is highly recommended, because the cost of repeatedly negotiating TLS session keys is high. Future Postfix SMTP servers may limit the number of sessions that a client is allowed to negotiate per unit time. Example: /etc/postfix/main.cf: smtp_tls_session_cache_database = btree:/var/lib/postfix/smtp_scache Note: as of version 2.5, Postfix no longer uses root privileges when opening this file. The file should now be stored under the Postfix-owned data_directory. As a migration aid, an attempt to open the file under a non- Postfix directory is redirected to the Postfix-owned data_directory, and a warning is logged. Cached Postfix SMTP client session information expires after a certain amount of time. Postfix/TLS does not use the OpenSSL default of 300s, but a longer time of 3600s (=1 hour). RFC 2246 recommends a maximum of 24 hours. Example: /etc/postfix/main.cf: smtp_tls_session_cache_timeout = 3600s CClliieenntt TTLLSS lliimmiittaattiioonnss The security properties of TLS communication channels are application specific. While the TLS protocol can provide a confidential, tamper-resistant, mutually authenticated channel between client and server, not all of these security features are applicable to every communication. For example, while mutual TLS authentication between browsers and web servers is possible, it is not practical, or even useful, for web-servers that serve the public to verify the identity of every potential user. In practice, most HTTPS transactions are asymmetric: the browser verifies the HTTPS server's identity, but the user remains anonymous. Much of the security policy is up to the client. If the client chooses to not verify the server's name, the server is not aware of this. There are many interesting browser security topics, but we shall not dwell on them here. Rather, our goal is to understand the security features of TLS in conjunction with SMTP. An important SMTP-specific observation is that a public MX host is even more at the mercy of the SMTP client than is an HTTPS server. Not only can it not enforce due care in the client's use of TLS, but it cannot even enforce the use of TLS, because TLS support in SMTP clients is still the exception rather than the rule. One cannot, in practice, limit access to one's MX hosts to just TLS- enabled clients. Such a policy would result in a vast reduction in one's ability to communicate by email with the world at large. One may be tempted to try enforcing TLS for mail from specific sending organizations, but this, too, runs into obstacles. One such obstacle is that we don't know who is (allegedly) sending mail until we see the "MAIL FROM:" SMTP command, and at that point, if TLS is not already in use, a potentially sensitive sender address (and with SMTP PIPELINING one or more of the recipients) has (have) already been leaked in the clear. Another obstacle is that mail from the sender to the recipient may be forwarded, and the forwarding organization may not have any security arrangements with the final destination. Bounces also need to be protected. These can only be identified by the IP address and HELO name of the connecting client, and it is difficult to keep track of all the potential IP addresses or HELO names of the outbound email servers of the sending organization. Consequently, TLS security for mail delivery to public MX hosts is almost entirely the client's responsibility. The server is largely a passive enabler of TLS security, the rest is up to the client. While the server has a greater opportunity to mandate client security policy when it is a dedicated MSA that only handles outbound mail from trusted clients, below we focus on the client security policy. On the SMTP client, there are further complications. When delivering mail to a given domain, in contrast to HTTPS, one rarely uses the domain name directly as the target host of the SMTP session. More typically, one uses MX lookups - these are usually unauthenticated - to obtain the domain's SMTP server hostname (s). When, as is current practice, the client verifies the insecurely obtained MX hostname, it is subject to a DNS man-in-the-middle attack. If clients instead attempted to verify the recipient domain name, an SMTP server for multiple domains would need to list all its email domain names in its certificate, and generate a new certificate each time a new domain were added. At least some CAs set fairly low limits (20 for one prominent CA) on the number of names that server certificates can contain. This approach is not consistent with current practice and does not scale. It is regrettably the case that TLS secure-channels (fully authenticated and immune to man-in-the-middle attacks) impose constraints on the sending and receiving sites that preclude ubiquitous deployment. One needs to manually configure this type of security for each destination domain, and in many cases implement non-default TLS policy table entries for additional domains hosted at a common secured destination. With Postfix 2.3, we make secure-channel configurations substantially easier to configure, but they will never be the norm. For the generic domain with which you have made no specific security arrangements, this security level is not a good fit. Given that strong authentication is not generally possible, and that verifiable certificates cost time and money, many servers that implement TLS use self- signed certificates or private CAs. This further limits the applicability of verified TLS on the public Internet. Historical note: while the documentation of these issues and many of the related features are new with Postfix 2.3, the issue was well understood before Postfix 1.0, when Lutz Jänicke was designing the first unofficial Postfix TLS patch. See his original post http://www.imc.org/ietf-apps-tls/mail-archive/ msg00304.html and the first response http://www.imc.org/ietf-apps-tls/mail- archive/msg00305.html. The problem is not even unique to SMTP or even TLS, similar issues exist for secure connections via aliases for HTTPS and Kerberos. SMTP merely uses indirect naming (via MX records) more frequently. CCoonnffiigguurriinngg TTLLSS iinn tthhee SSMMTTPP//LLMMTTPP cclliieenntt Similar to the Postfix SMTP server, the Postfix SMTP/LMTP client implements multiple TLS security levels. These levels are described in more detail in the sections that follow. nnoonnee No TLS. mmaayy Opportunistic TLS. eennccrryypptt Mandatory TLS encryption. ffiinnggeerrpprriinntt Certificate fingerprint verification. vveerriiffyy Mandatory server certificate verification. sseeccuurree Secure-channel TLS. NNoo TTLLSS eennccrryyppttiioonn At the "none" TLS security level, TLS encryption is disabled. This is the default security level. With Postfix 2.3 and later, it can be configured explicitly by setting "smtp_tls_security_level = none". With Postfix 2.2 and earlier, or when smtp_tls_security_level is set to its default (backwards compatible) empty value, the appropriate configuration settings are "smtp_use_tls = no" and "smtp_enforce_tls = no". With either approach, TLS is not used even if supported by the server. For LMTP, use the corresponding "lmtp_" parameters. Per destination settings may override this default setting, in which case TLS is used selectively, only with destinations explicitly configured for TLS. You can disable TLS for a subset of destinations, while leaving it enabled for the rest. With the Postfix 2.3 and later TLS policy table, specify the "none" security level. With the obsolete per-site table, specify the "NONE" keyword. OOppppoorrttuunniissttiicc TTLLSS At the "may" TLS security level, TLS encryption is opportunistic. The SMTP transaction is encrypted if the STARTTLS ESMTP feature is supported by the server. Otherwise, messages are sent in the clear. With Postfix 2.3 and later, opportunistic TLS can be configured by setting "smtp_tls_security_level = may". Since sending in the clear is acceptable, demanding stronger than default TLS security mostly reduces inter-operability. If you must restrict TLS protocol or cipher selection even with opportunistic TLS, the "smtp_tls_ciphers" and "smtp_tls_protocols" configuration parameters (Postfix >= 2.6) provide control over the protocols and cipher grade used with opportunistic TLS. With earlier releases the opportunistic TLS cipher grade is always "export" and no protocols are disabled. With Postfix 2.2 and earlier, or when smtp_tls_security_level is set to its default (backwards compatible) empty value, the appropriate configuration settings are "smtp_use_tls = yes" and "smtp_enforce_tls = no". For LMTP use the corresponding "lmtp_" parameters. With opportunistic TLS, mail delivery continues even if the server certificate is untrusted or bears the wrong name. Starting with Postfix 2.3, when the TLS handshake fails for an opportunistic TLS session, rather than give up on mail delivery, the transaction is retried with TLS disabled. Trying an unencrypted connection makes it possible to deliver mail to sites with non-interoperable server TLS implementations. Opportunistic encryption is never used for LMTP over UNIX-domain sockets. The communications channel is already confidential without TLS, so the only potential benefit of TLS is authentication. Do not configure opportunistic TLS for LMTP deliveries over UNIX-domain sockets. Only configure TLS for LMTP over UNIX-domain sockets at the encrypt security level or higher. Attempts to configure opportunistic encryption of LMTP sessions will be ignored with a warning written to the mail logs. You can enable opportunistic TLS just for selected destinations. With the Postfix 2.3 and later TLS policy table, specify the "may" security level. With the obsolete per-site table, specify the "MAY" keyword. This is the most common security level for TLS protected SMTP sessions, stronger security is not generally available and, if needed, is typically only configured on a per-destination basis. See the section on TLS limitations above. Example: /etc/postfix/main.cf: smtp_tls_security_level = may Postfix 2.2 syntax: /etc/postfix/main.cf: smtp_use_tls = yes smtp_enforce_tls = no MMaannddaattoorryy TTLLSS eennccrryyppttiioonn At the "encrypt" TLS security level, messages are sent only over TLS encrypted sessions. The SMTP transaction is aborted unless the STARTTLS ESMTP feature is supported by the remote SMTP server. If no suitable servers are found, the message will be deferred. With Postfix 2.3 and later, mandatory TLS encryption can be configured by setting "smtp_tls_security_level = encrypt". Even though TLS encryption is always used, mail delivery continues even if the server certificate is untrusted or bears the wrong name. At this security level and higher, the smtp_tls_mandatory_protocols and smtp_tls_mandatory_ciphers configuration parameters determine the list of sufficiently secure SSL protocol versions and the minimum cipher strength. If the protocol or cipher requirements are not met, the mail transaction is aborted. The documentation for these parameters includes useful interoperability and security guidelines. With Postfix 2.2 and earlier, or when smtp_tls_security_level is set to its default (backwards compatible) empty value, the appropriate configuration settings are "smtp_enforce_tls = yes" and "smtp_tls_enforce_peername = no". For LMTP use the corresponding "lmtp_" parameters. Despite the potential for eliminating passive eavesdropping attacks, mandatory TLS encryption is not viable as a default security level for mail delivery to the public Internet. Most MX hosts do not support TLS at all, and some of those that do have broken implementations. On a host that delivers mail to the Internet, you should not configure mandatory TLS encryption as the default security level. You can enable mandatory TLS encryption just for specific destinations. With the Postfix 2.3 and later TLS policy table, specify the "encrypt" security level. With the obsolete per-site table, specify the "MUST_NOPEERMATCH" keyword. While the obsolete approach still works with Postfix 2.3, it is strongly discouraged: users of Postfix 2.3 and later should use the new TLS policy settings. Examples: In the example below, traffic to example.com and its sub-domains via the corresponding MX hosts always uses TLS. The protocol version will be "SSLv3" or "TLSv1" (the default setting of smtp_tls_mandatory_protocols excludes "SSLv2"). Only high or medium strength (i.e. 128 bit or better) ciphers will be used by default for all "encrypt" security level sessions. /etc/postfix/main.cf: smtp_tls_policy_maps = hash:/etc/postfix/tls_policy /etc/postfix/tls_policy: example.com encrypt .example.com encrypt Postfix 2.2 syntax (no support for sub-domains without resorting to regexp tables). With Postfix 2.3 and later, do not use the obsolete per-site table. /etc/postfix/main.cf: smtp_tls_per_site = hash:/etc/postfix/tls_per_site /etc/postfix/tls_per_site: example.com MUST_NOPEERMATCH In the next example, secure message submission is configured via the MSA " [example.net]:587". TLS sessions are encrypted without authentication, because this MSA does not possess an acceptable certificate. This MSA is known to be capable of "TLSv1" and "high" grade ciphers, so these are selected via the policy table. NNoottee:: the policy table lookup key is the verbatim next-hop specification from the recipient domain, transport(5) table or relayhost parameter, with any enclosing square brackets and optional port. Take care to be consistent: the suffixes ":smtp" or ":25" or no port suffix result in different policy table lookup keys, even though they are functionally equivalent nexthop specifications. Use at most one of these forms for all destinations. Below, the policy table has multiple keys, just in case the transport table entries are not specified consistently. /etc/postfix/main.cf: smtp_tls_policy_maps = hash:/etc/postfix/tls_policy /etc/services: submission 587/tcp msa # mail message submission /etc/postfix/tls_policy: [example.net]:587 encrypt protocols=TLSv1 ciphers=high [example.net]:msa encrypt protocols=TLSv1 ciphers=high [example.net]:submission encrypt protocols=TLSv1 ciphers=high Postfix 2.2 syntax: NNoottee:: Avoid policy lookups with the bare hostname (for example, "example.net"). Instead, use the destination (for example, "[example.net]:587"), as the per- site table lookup key (a recipient domain or MX-enabled transport nexthop with no port suffix may look like a bare hostname, but is still a suitable destination). With Postfix 2.3 and later, do not use the obsolete per-site table; use the new policy table instead. /etc/postfix/main.cf: smtp_tls_per_site = hash:/etc/postfix/tls_per_site /etc/postfix/tls_per_site: [example.net]:587 MUST_NOPEERMATCH CCeerrttiiffiiccaattee ffiinnggeerrpprriinntt vveerriiffiiccaattiioonn Certificate fingerprint verification is available with Postfix 2.5 and later. At this security level ("smtp_tls_security_level = fingerprint"), no trusted certificate authorities are used or required. The certificate trust chain, expiration date, ... are not checked. Instead, the smtp_tls_fingerprint_cert_match parameter or the "match" attribute in the policy table lists the valid "fingerprints" of the remote SMTP server certificate. If certificate fingerprints are exchanged securely, this is the strongest, and least scalable security level. The administrator needs to securely collect the fingerprints of the X.509 certificates of each peer server, store them into a local file, and update this local file whenever the peer server's public certificate changes. This may be feasible for an SMTP "VPN" connecting a small number of branch offices over the Internet, or for secure connections to a central mail hub. It works poorly if the remote SMTP server is managed by a third party, and its public certificate changes periodically without prior coordination with the verifying site. The digest algorithm used to calculate the fingerprint is selected by the ssmmttpp__ttllss__ffiinnggeerrpprriinntt__ddiiggeesstt parameter. In the policy table multiple fingerprints can be combined with a "|" delimiter in a single match attribute, or multiple match attributes can be employed. The ":" character is not used as a delimiter as it occurs between each pair of fingerprint (hexadecimal) digits. Example: fingerprint TLS security with an internal mailhub. Two matching fingerprints are listed. The relayhost may be multiple physical hosts behind a load-balancer, each with its own private/public key and self-signed certificate. Alternatively, a single relayhost may be in the process of switching from one set of private/public keys to another, and both keys are trusted just prior to the transition. relayhost = [mailhub.example.com] smtp_tls_security_level = fingerprint smtp_tls_fingerprint_digest = md5 smtp_tls_fingerprint_cert_match = 3D:95:34:51:24:66:33:B9:D2:40:99:C0:C1:17:0B:D1 EC:3B:2D:B0:5B:B1:FB:6D:20:A3:9D:72:F6:8D:12:35 Example: Certificate fingerprint verification with selected destinations. As in the example above, we show two matching fingerprints: /etc/postfix/main.cf: smtp_tls_policy_maps = hash:/etc/postfix/tls_policy smtp_tls_fingerprint_digest = md5 /etc/postfix/tls_policy: example.com fingerprint match=3D:95:34:51:24:66:33:B9:D2:40:99:C0:C1:17:0B:D1 match=EC:3B:2D:B0:5B:B1:FB:6D:20:A3:9D:72:F6:8D:12:35 MMaannddaattoorryy sseerrvveerr cceerrttiiffiiccaattee vveerriiffiiccaattiioonn At the "verify" TLS security level, messages are sent only over TLS encrypted sessions if the remote SMTP server certificate is valid (not expired or revoked, and signed by a trusted certificate authority) and where the server certificate name matches a known pattern. Mandatory server certificate verification can be configured by setting "smtp_tls_security_level = verify". The smtp_tls_verify_cert_match parameter can override the default "hostname" certificate name matching strategy. Fine-tuning the matching strategy is generally only appropriate for secure-channel destinations. With Postfix 2.2 and earlier, or when smtp_tls_security_level is set to its default (backwards compatible) empty value, the appropriate configuration settings are "smtp_enforce_tls = yes" and "smtp_tls_enforce_peername = yes". For LMTP use the corresponding "lmtp_" parameters. If the server certificate chain is trusted (see smtp_tls_CAfile and smtp_tls_CApath), any DNS names in the SubjectAlternativeName certificate extension are used to verify the remote SMTP server name. If no DNS names are specified, the certificate CommonName is checked. If you want mandatory encryption without server certificate verification, see above. Despite the potential for eliminating "man-in-the-middle" and other attacks, mandatory certificate trust chain and subject name verification is not viable as a default Internet mail delivery policy. Most MX hosts do not support TLS at all, and a significant portion of TLS enabled MTAs use self-signed certificates, or certificates that are signed by a private certificate authority. On a machine that delivers mail to the Internet, you should not configure mandatory server certificate verification as a default policy. Mandatory server certificate verification as a default security level may be appropriate if you know that you will only connect to servers that support RFC 2487 and that present verifiable server certificates. An example would be a client that sends all email to a central mailhub that offers the necessary STARTTLS support. In such cases, you can often use a secure-channel configuration instead. You can enable mandatory server certificate verification just for specific destinations. With the Postfix 2.3 and later TLS policy table, specify the "verify" security level. With the obsolete per-site table, specify the "MUST" keyword. While the obsolete approach still works with Postfix 2.3, it is strongly discouraged: users of Postfix 2.3 and later should use the new TLS policy settings. Example: In this example, the Postfix SMTP client encrypts all traffic to the example.com domain. The peer hostname is verified, but verification is vulnerable to DNS response forgery. Mail transmission to example.com recipients uses "high" grade ciphers. /etc/postfix/main.cf: indexed = ${default_database_type}:${config_directory}/ smtp_tls_CAfile = ${config_directory}/CAfile.pem smtp_tls_policy_maps = ${indexed}tls_policy /etc/postfix/tls_policy: example.com verify ciphers=high Postfix 2.2 syntax: /etc/postfix/main.cf: indexed = ${default_database_type}:${config_directory}/ smtp_tls_CAfile = ${config_directory}/CAfile.pem smtp_tls_per_site = ${indexed}tls_per_site /etc/postfix/tls_per_site: example.com MUST SSeeccuurree sseerrvveerr cceerrttiiffiiccaattee vveerriiffiiccaattiioonn At the secure TLS security level, messages are sent only over secure-channel TLS sessions where DNS forgery resistant server certificate verification succeeds. If no suitable servers are found, the message will be deferred. With Postfix 2.3 and later, secure-channels can be configured by setting "smtp_tls_security_level = secure". The smtp_tls_secure_cert_match parameter can override the default "nexthop, dot-nexthop" certificate match strategy. With Postfix 2.2 and earlier, or when smtp_tls_security_level is set to its default (backwards compatible) empty value, the appropriate configuration settings are "smtp_enforce_tls = yes" and "smtp_tls_enforce_peername = yes" with additional settings to harden peer certificate verification against forged DNS data. For LMTP, use the corresponding "lmtp_" parameters. If the server certificate chain is trusted (see smtp_tls_CAfile and smtp_tls_CApath), any DNS names in the SubjectAlternativeName certificate extension are used to verify the remote SMTP server name. If no DNS names are specified, the CommonName is checked. If you want mandatory encryption without server certificate verification, see above. Despite the potential for eliminating "man-in-the-middle" and other attacks, mandatory secure server certificate verification is not viable as a default Internet mail delivery policy. Most MX hosts do not support TLS at all, and a significant portion of TLS enabled MTAs use self-signed certificates, or certificates that are signed by a private certificate authority. On a machine that delivers mail to the Internet, you should not configure secure TLS verification as a default policy. Mandatory secure server certificate verification as a default security level may be appropriate if you know that you will only connect to servers that support RFC 2487 and that present verifiable server certificates. An example would be a client that sends all email to a central mailhub that offers the necessary STARTTLS support. You can enable secure TLS verification just for specific destinations. With the Postfix 2.3 and later TLS policy table, specify the "secure" security level. With the obsolete per-site table, specify the "MUST" keyword and harden the certificate verification against DNS forgery. While the obsolete approach still works with Postfix 2.3, it is strongly discouraged: users of Postfix 2.3 and later should use the new TLS policy settings. Examples: Secure-channel TLS without transport(5) table overrides: The Postfix SMTP client will encrypt all traffic and verify the destination name immune from forged DNS responses. MX lookups are still used to find the hostnames of the SMTP servers for example.com, but these hostnames are not used when checking the names in the server certificate(s). Rather, the requirement is that the MX hosts for example.com have trusted certificates with a subject name of example.com or a sub-domain, see the documentation for the smtp_tls_secure_cert_match parameter. The related domains example.co.uk and example.co.jp are hosted on the same MX hosts as the primary example.com domain, and traffic to these is secured by verifying the primary example.com domain in the server certificates. This frees the server administrator from needing the CA to sign certificates that list all the secondary domains. The downside is that clients that want secure channels to the secondary domains need explicit TLS policy table entries. Note, there are two ways to handle related domains. The first is to use the default routing for each domain, but add policy table entries to override the expected certificate subject name. The second is to override the next-hop in the transport table, and use a single policy table entry for the common nexthop. We choose the first approach, because it works better when domain ownership changes. With the second approach we securely deliver mail to the wrong destination, with the first approach, authentication fails and mail stays in the local queue, the first approach is more appropriate in most cases. /etc/postfix/main.cf: smtp_tls_CAfile = /etc/postfix/CAfile.pem smtp_tls_policy_maps = hash:/etc/postfix/tls_policy /etc/postfix/transport: /etc/postfix/tls_policy: example.com secure example.co.uk secure match=example.com:.example.com example.co.jp secure match=example.com:.example.com Secure-channel TLS with transport(5) table overrides: In this case traffic to example.com and its related domains is sent to a single logical gateway (to avoid a single point of failure, its name may resolve to one or more load-balancer addresses, or to the combined addresses of multiple physical hosts). All the physical hosts reachable via the gateway's IP addresses have the logical gateway name listed in their certificates. This secure-channel configuration can also be implemented via a hardened variant of the MUST policy in the obsolete per-site table. As stated above, this approach has the potential to mis-deliver email if the related domains change hands. /etc/postfix/main.cf: smtp_tls_CAfile = /etc/postfix/CAfile.pem transport_maps = hash:/etc/postfix/transport smtp_tls_policy_maps = hash:/etc/postfix/tls_policy /etc/postfix/transport: example.com smtp:[tls.example.com] example.co.uk smtp:[tls.example.com] example.co.jp smtp:[tls.example.com] /etc/postfix/tls_policy: [tls.example.com] secure match=tls.example.com Postfix 2.2.9 and later syntax: NNoottee:: Avoid policy lookups with the bare hostname (for example, "tls.example.com"). Instead, use the destination (for example, " [tls.example.com]") as the per-site table lookup key (a recipient domain or MX- enabled transport nexthop with no port suffix may look like a bare hostname, but is still a suitable destination). With Postfix 2.3 and later, do not use the obsolete per-site table; use the new policy table instead. /etc/postfix/main.cf: smtp_cname_overrides_servername = no smtp_tls_CAfile = /etc/postfix/CAfile.pem transport_maps = hash:/etc/postfix/transport smtp_tls_per_site = hash:/etc/postfix/tls_per_site /etc/postfix/transport: example.com smtp:[tls.example.com] example.co.uk smtp:[tls.example.com] example.co.jp smtp:[tls.example.com] /etc/postfix/tls_per_site: [tls.example.com] MUST TTLLSS ppoolliiccyy ttaabbllee The current TLS policy table was introduced with Postfix 2.3. For earlier releases, read the description of the obsolete Postfix 2.2 per-site table. A small fraction of servers offer STARTTLS but the negotiation consistently fails. With Postfix 2.3, so long as encryption is not enforced, the delivery is immediately retried with TLS disabled. You no longer need to explicitly disable TLS for the problem destinations. As soon as their TLS software or configuration is repaired, encryption will be used. The new policy table is specified via the smtp_tls_policy_maps parameter. This lists optional lookup tables with the Postfix SMTP client TLS security policy by next-hop destination. When $smtp_tls_policy_maps is not empty, the obsolete smtp_tls_per_site parameter is ignored (a warning is written to the logs if both parameter values are non-empty). The TLS policy table is indexed by the full next-hop destination, which is either the recipient domain, or the verbatim next-hop specified in the transport table, $local_transport, $virtual_transport, $relay_transport or $default_transport. This includes any enclosing square brackets and any non- default destination server port suffix. The LMTP socket type prefix (inet: or unix:) is not included in the lookup key. Only the next-hop domain, or $myhostname with LMTP over UNIX-domain sockets, is used as the nexthop name for certificate verification. The port and any enclosing square brackets are used in the table lookup key, but are not used for server name verification. When the lookup key is a domain name without enclosing square brackets or any : port suffix (typically the recipient domain), and the full domain is not found in the table, just as with the transport(5) table, the parent domain starting with a leading "." is matched recursively. This allows one to specify a security policy for a recipient domain and all its sub-domains. The lookup result is a security level, followed by an optional list of whitespace and/or comma separated name=value attributes that override related main.cf settings. The TLS security levels are described above. Below, we describe the corresponding table syntax: nnoonnee No TLS. No additional attributes are supported at this level. mmaayy Opportunistic TLS. The optional "ciphers", "exclude" and "protocols" attributes (available for opportunistic TLS with Postfix >= 2.6) override the "smtp_tls_ciphers", "smtp_tls_exclude_ciphers" and "smtp_tls_protocols" configuration parameters. eennccrryypptt Mandatory encryption. Mail is delivered only if the remote SMTP server offers STARTTLS and the TLS handshake succeeds. At this level and higher, the optional "protocols" attribute overrides the main.cf smtp_tls_mandatory_protocols parameter, the optional "ciphers" attribute overrides the main.cf smtp_tls_mandatory_ciphers parameter, and the optional "exclude" attribute (Postfix >= 2.6) overrides the main.cf smtp_tls_mandatory_exclude_ciphers parameter. ffiinnggeerrpprriinntt Certificate fingerprint verification. Available with Postfix 2.5 and later. At this security level, there are no trusted certificate authorities. The certificate trust chain, expiration date, ... are not checked. Instead, the optional mmaattcchh attribute, or else the main.cf ssmmttpp__ttllss__ffiinnggeerrpprriinntt__cceerrtt__mmaattcchh parameter, lists the valid fingerprints of the server certificate. The digest algorithm used to calculate fingerprints is selected by the ssmmttpp__ttllss__ffiinnggeerrpprriinntt__ddiiggeesstt parameter. Multiple fingerprints can be combined with a "|" delimiter in a single match attribute, or multiple match attributes can be employed. The ":" character is not used as a delimiter as it occurs between each pair of fingerprint (hexadecimal) digits. vveerriiffyy Mandatory server certificate verification. Mail is delivered only if the TLS handshake succeeds, if the remote SMTP server certificate can be validated (not expired or revoked, and signed by a trusted certificate authority), and if the server certificate name matches the optional "match" attribute (or the main.cf smtp_tls_verify_cert_match parameter value when no optional "match" attribute is specified). sseeccuurree Secure certificate verification. Mail is delivered only if the TLS handshake succeeds, if the remote SMTP server certificate can be validated (not expired or revoked, and signed by a trusted certificate authority), and if the server certificate name matches the optional "match" attribute (or the main.cf smtp_tls_secure_cert_match parameter value when no optional "match" attribute is specified). Notes: * The "match" attribute is especially useful to verify TLS certificates for domains that are hosted on a shared server. In that case, specify "match" rules for the shared server's name. While secure verification can also be achieved with manual routing overrides in Postfix transport(5) tables, that approach can deliver mail to the wrong host when domains are assigned to new gateway hosts. The "match" attribute approach avoids the problems of manual routing overrides; mail is deferred if verification of a new MX host fails. * When a policy table entry specifies multiple match patterns, multiple match strategies, or multiple protocols, these must be separated by colons. * The "exclude" attribute (Postfix >= 2.6) is used to disable ciphers that cause handshake failures with a specific mandatory TLS destination, without disabling the ciphers for all mandatory destinations. Alternatively, you can exclude ciphers that cause issues with multiple remote servers in main.cf, and selectively enable them on a per-destination basis in the policy table by setting a shorter or empty exclusion list. The per- destination "exclude" list preempts both the opportunistic and mandatory security level exclusions, so that all excluded ciphers can be enabled for known-good destinations. For non-mandatory TLS destinations that exhibit cipher-specific problems, Postfix will fall back to plain-text delivery. If plain-text is not acceptable make TLS mandatory and exclude the problem ciphers. Example: /etc/postfix/main.cf: smtp_tls_policy_maps = hash:/etc/postfix/tls_policy # Postfix 2.5 and later smtp_tls_fingerprint_digest = md5 /etc/postfix/tls_policy: example.edu none example.mil may example.gov encrypt protocols=SSLv3:TLSv1 ciphers=high example.com verify match=hostname:dot-nexthop protocols=SSLv3:TLSv1 ciphers=high example.net secure .example.net secure match=.example.net:example.net [mail.example.org]:587 secure match=nexthop # Postfix 2.5 and later [thumb.example.org] fingerprint match=EC:3B:2D:B0:5B:B1:FB:6D:20:A3:9D:72:F6:8D:12:35 match=3D:95:34:51:24:66:33:B9:D2:40:99:C0:C1:17:0B:D1 # Postfix 2.6 and later example.info may protocols=!SSLv2 ciphers=medium exclude=3DES NNoottee:: The "hostname" strategy if listed in a non-default setting of smtp_tls_secure_cert_match or in the "match" attribute in the policy table can render the "secure" level vulnerable to DNS forgery. Do not use the "hostname" strategy for secure-channel configurations in environments where DNS security is not assured. OObbssoolleettee ppeerr--ssiittee TTLLSS ppoolliiccyy ssuuppppoorrtt This section describes an obsolete per-site TLS policy mechanism. Unlike the Postfix 2.3 policy table mechanism, this uses as a policy lookup key a potentially untrusted server hostname, and lacks control over what names can appear in server certificates. Because of this, the obsolete mechanism is typically vulnerable to false DNS hostname information in MX or CNAME records. These attacks can be eliminated only with great difficulty. The new policy table makes secure-channel configurations easier and provides more control over the cipher and protocol selection for sessions with mandatory encryption. Avoid policy lookups with the bare hostname. Instead, use the full destination nexthop (enclosed in [] with a possible ":port" suffix) as the per-site table lookup key (a recipient domain or MX-enabled transport nexthop with no port suffix may look like a bare hostname, but is still a suitable destination). With Postfix 2.3 and later, use of the obsolete approach documented here is strongly discouraged: use the new policy table instead. Starting with Postfix 2.3, the underlying TLS enforcement levels are common to the obsolete per-site table and the new policy table. The main.cf smtp_tls_mandatory_ciphers and smtp_tls_mandatory_protocols parameters control the TLS ciphers and protocols for mandatory encryption regardless of which table is used. The smtp_tls_verify_cert_match parameter determines the match strategy for the obsolete "MUST" keyword in the same way as for the "verify" level in the new policy. With Postfix < 2.3, the obsolete smtp_tls_cipherlist parameter is also applied for opportunistic TLS sessions, and should be used with care, or not at all. Setting cipherlist restrictions that are incompatible with a remote SMTP server render that server unreachable, TLS handshakes are always attempted and always fail. When smtp_tls_policy_maps is empty (default) and smtp_tls_per_site is not empty, the per-site table is searched for a policy that matches the following information: remote SMTP server hostname This is simply the DNS name of the server that the Postfix SMTP client connects to; this name may be obtained from other DNS lookups, such as MX lookups or CNAME lookups. Use of the hostname lookup key is discouraged; always use the next-hop destination instead. next-hop destination This is normally the domain portion of the recipient address, but it may be overridden by information from the transport(5) table, from the relayhost parameter setting, or from the relay_transport setting. When it is not the recipient domain, the next-hop destination can have the Postfix-specific form "[name]", "[name]:port", "name" or "name:port". This is the recommended lookup key for per-site policy lookups (and incidentally for SASL password lookups). When both the hostname lookup and the next-hop lookup succeed, the host policy does not automatically override the next-hop policy. Instead, precedence is given to either the more specific or the more secure per-site policy as described below. The smtp_tls_per_site table uses a simple "name whitespace value" format. Specify host names or next-hop destinations on the left-hand side; no wildcards are allowed. On the right hand side specify one of the following keywords: NONE No TLS. This overrides a less specific "MAY" lookup result from the alternate host or next-hop lookup key, and overrides the global smtp_use_tls, smtp_enforce_tls, and smtp_tls_enforce_peername settings. MAY Opportunistic TLS. This has less precedence than a more specific result (including "NONE") from the alternate host or next-hop lookup key, and has less precedence than the more specific global "smtp_enforce_tls = yes" or "smtp_tls_enforce_peername = yes". MUST_NOPEERMATCH Mandatory TLS encryption. This overrides a less secure "NONE" or a less specific "MAY" lookup result from the alternate host or next-hop lookup key, and overrides the global smtp_use_tls, smtp_enforce_tls and smtp_tls_enforce_peername settings. MUST Mandatory server certificate verification. This overrides a less secure "NONE" and "MUST_NOPEERMATCH" or a less specific "MAY" lookup result from the alternate host or next-hop lookup key, and overrides the global smtp_use_tls, smtp_enforce_tls and smtp_tls_enforce_peername settings. The precedences between global (main.cf) and per-site TLS policies can be summarized as follows: * When neither the remote SMTP server hostname nor the next-hop destination are found in the smtp_tls_per_site table, the policy is based on smtp_use_tls, smtp_enforce_tls and smtp_tls_enforce_peername. Note: "smtp_enforce_tls = yes" and "smtp_tls_enforce_peername = yes" imply "smtp_use_tls = yes". * When both hostname and next-hop destination lookups produce a result, the more specific per-site policy (NONE, MUST, etc) overrides the less specific one (MAY), and the more secure per-site policy (MUST, etc) overrides the less secure one (NONE). * After the per-site policy lookups are combined, the result generally overrides the global policy. The exception is the less specific "MAY" per- site policy, which is overruled by the more specific global "smtp_enforce_tls = yes" with server certificate verification as specified with the smtp_tls_enforce_peername parameter. CClloossiinngg aa DDNNSS lloooopphhoollee wwiitthh oobbssoolleettee ppeerr--ssiittee TTLLSS ppoolliicciieess For a general discussion of TLS security for SMTP see TLS limitations above. What follows applies only to Postfix 2.2.9 and subsequent Postfix 2.2 patch levels. Do not use this approach with Postfix 2.3 and later; instead see the instructions under secure server certificate verification. As long as no secure DNS lookup mechanism is available, false hostnames in MX or CNAME responses can change Postfix's notion of the server hostname that is used for TLS policy lookup and server certificate verification. Even with a perfect match between the server hostname and the server certificate, there is no guarantee that Postfix is connected to the right server. To avoid this loophole, take all of the following steps: 1. Use a dedicated message delivery transport (for example, "securetls") as illustrated below. 2. Eliminate MX lookups. Specify local transport(5) table entries for sensitive domains with explicit securetls:[mailhost] or securetls: [mailhost]:port destinations (you can assure security of this table unlike DNS). This prevents false hostname information in DNS MX records from changing Postfix's notion of the server hostname that is used for TLS policy lookup and server certificate verification. The "securetls" transport is configured to enforce TLS with peername verification, and to disable the SMTP connection cache which could interfere with enforcement of smtp_tls_per_site policies. 3. Disallow CNAME hostname overrides. In main.cf, specify "smtp_cname_overrides_servername = no". This prevents false hostname information in DNS CNAME records from changing the server hostname that Postfix uses for TLS policy lookup and server certificate verification. This feature requires Postfix 2.2.9 or later. The default value is "no" starting with Postfix 2.3. Example: We give the non-default "securetls" transport an explicit master.cf process limit, so that we don't raise its process limit when raising $default_process_limit. The total process limit for *all* transports should stay somewhat under 1024 (the typical select() file descriptor limit); otherwise transports may be throttled under steady high load, compounding congestion. It is not uncommon at high volume sites to set the default process limit to 500 or more. We also default the "securetls" transport TLS security level to MUST, obviating the need for per-site table entries for secure-channel destinations. /etc/postfix/main.cf: transport_maps = hash:/etc/postfix/transport /etc/postfix/transport: example.com securetls:[tls.example.com] /etc/postfix/master.cf: securetls unix - - n - 100 smtp -o smtp_enforce_tls=yes -o smtp_tls_enforce_peername=yes DDiissccoovveerriinngg sseerrvveerrss tthhaatt ssuuppppoorrtt TTLLSS As we decide on a "per site" basis whether or not to use TLS, it would be good to have a list of sites that offered "STARTTLS". We can collect it ourselves with this option. If the smtp_tls_note_starttls_offer feature is enabled and a server offers STARTTLS while TLS is not already enabled for that server, the Postfix SMTP client logs a line as follows: postfix/smtp[pid]: Host offered STARTTLS: [hostname.example.com] Example: /etc/postfix/main.cf: smtp_tls_note_starttls_offer = yes SSeerrvveerr cceerrttiiffiiccaattee vveerriiffiiccaattiioonn ddeepptthh The server certificate verification depth is specified with the main.cf smtp_tls_scert_verifydepth parameter. The default verification depth is 9 (the OpenSSL default), for compatibility with Postfix versions before 2.5 where smtp_tls_scert_verifydepth was ignored. When you configure trust in a root CA, it is not necessary to explicitly trust intermediary CAs signed by the root CA, unless $smtp_tls_scert_verifydepth is less than the number of CAs in the certificate chain for the servers of interest. With a verify depth of 1 you can only verify certificates directly signed by a trusted CA, and all trusted intermediary CAs need to be configured explicitly. With a verify depth of 2 you can verify servers signed by a root CA or a direct intermediary CA (so long as the server is correctly configured to supply its intermediate CA certificate). Example: /etc/postfix/main.cf: smtp_tls_scert_verifydepth = 2 CClliieenntt--ssiiddee cciipphheerr ccoonnttrroollss The Postfix SMTP client supports 5 distinct cipher security levels as specified by the smtp_tls_mandatory_ciphers configuration parameter. This setting controls the minimum acceptable SMTP client TLS cipher grade for use with mandatory TLS encryption. The default value "medium" is suitable for most destinations with which you may want to enforce TLS, and is beyond the reach of today's crypt-analytic methods. See smtp_tls_policy_maps for information on how to configure ciphers on a per-destination basis. By default anonymous ciphers are allowed, and automatically disabled when remote SMTP server certificates are verified. If you want to disable anonymous ciphers even at the "encrypt" security level, set "smtp_tls_mandatory_exclude_ciphers = aNULL"; and to disable anonymous ciphers even with opportunistic TLS, set "smtp_tls_exclude_ciphers = aNULL". There is generally no need to take these measures. Anonymous ciphers save bandwidth and TLS session cache space, if certificates are ignored, there is little point in requesting them. The "smtp_tls_ciphers" configuration parameter (Postfix >= 2.6) provides control over the minimum cipher grade for opportunistic TLS. With Postfix < 2.6, the minimum opportunistic TLS cipher grade is always "export". With mandatory TLS encryption, the Postfix SMTP client will by default only use SSLv3 or TLSv1. SSLv2 is only used when TLS encryption is optional. The mandatory TLS protocol list is specified via the smtp_tls_mandatory_protocols configuration parameter. The corresponding smtp_tls_protocols parameter (Postfix >= 2.6) controls the SSL/TLS protocols used with opportunistic TLS. Example: /etc/postfix/main.cf: smtp_tls_mandatory_ciphers = medium smtp_tls_mandatory_exclude_ciphers = RC4, MD5 smtp_tls_exclude_ciphers = aNULL smtp_tls_mandatory_protocols = SSLv3, TLSv1 # Also available with Postfix >= 2.5: smtp_tls_mandatory_protocols = !SSLv2 # Also available with Postfix >= 2.6: smtp_tls_ciphers = export smtp_tls_protocols = !SSLv2 CClliieenntt--ssiiddee SSMMTTPPSS ssuuppppoorrtt Although the Postfix SMTP client by itself doesn't support TLS wrapper mode, it is relatively easy to forward a connection through the stunnel program if Postfix needs to deliver mail to some legacy system that doesn't support STARTTLS. Use one of the following two examples, to send only some remote mail, or to send all remote mail, to an SMTPS server. SSeennddiinngg aallll rreemmoottee mmaaiill ttoo aann SSMMTTPPSS sseerrvveerr The first example uses SMTPS to send all remote mail to a provider's mail server called "mail.example.com". A minimal stunnel.conf file is sufficient to set up a tunnel from local port 11125 to the remote destination "mail.example.com" and port "smtps". Postfix will later use this tunnel to connect to the remote server. /path/to/stunnel.conf: [smtp-tls-wrapper] accept = 11125 client = yes connect = mail.example.com:smtps To test this tunnel, use: $ telnet localhost 11125 This should produce the greeting from the remote SMTP server at mail.example.com. On the Postfix side, the relayhost feature sends all remote mail through the local stunnel listener on port 11125: /etc/postfix/main.cf: relayhost = [127.0.0.1]:11125 Use "postfix reload" to make the change effective. SSeennddiinngg oonnllyy mmaaiill ffoorr aa ssppeecciiffiicc ddeessttiinnaattiioonn vviiaa SSMMTTPPSS The second example will use SMTPS to send only mail for "example.com" via SMTPS. It uses the same stunnel configuration file as the first example, so it won't be repeated here. This time, the Postfix side uses a transport map to direct only mail for "example.com" through the tunnel: /etc/postfix/main.cf: transport_maps = hash:/etc/postfix/transport /etc/postfix/transport: example.com relay:[127.0.0.1]:11125 Use "postmap hash:/etc/postfix/transport" and "postfix reload" to make the change effective. MMiisscceellllaanneeoouuss cclliieenntt ccoonnttrroollss The smtp_starttls_timeout parameter limits the time of Postfix SMTP client write and read operations during TLS startup and shutdown handshake procedures. In case of problems the Postfix SMTP client tries the next network address on the mail exchanger list, and defers delivery if no alternative server is available. Example: /etc/postfix/main.cf: smtp_starttls_timeout = 300s TTLLSS mmaannaaggeerr ssppeecciiffiicc sseettttiinnggss The security of cryptographic software such as TLS depends critically on the ability to generate unpredictable numbers for keys and other information. To this end, the tlsmgr(8) process maintains a Pseudo Random Number Generator (PRNG) pool. This is queried by the smtp(8) and smtpd(8) processes when they initialize. By default, these daemons request 32 bytes, the equivalent to 256 bits. This is more than sufficient to generate a 128bit (or 168bit) session key. Example: /etc/postfix/main.cf: tls_daemon_random_bytes = 32 In order to feed its in-memory PRNG pool, the tlsmgr(8) reads entropy from an external source, both at startup and during run-time. Specify a good entropy source, like EGD or /dev/urandom; be sure to only use non-blocking sources (on OpenBSD, use /dev/arandom when tlsmgr(8) complains about /dev/urandom timeout errors). If the entropy source is not a regular file, you must prepend the source type to the source name: "dev:" for a device special file, or "egd:" for a source with EGD compatible socket interface. Examples (specify only one in main.cf): /etc/postfix/main.cf: tls_random_source = dev:/dev/urandom tls_random_source = egd:/var/run/egd-pool By default, tlsmgr(8) reads 32 bytes from the external entropy source at each seeding event. This amount (256bits) is more than sufficient for generating a 128bit symmetric key. With EGD and device entropy sources, the tlsmgr(8) limits the amount of data read at each step to 255 bytes. If you specify a regular file as entropy source, a larger amount of data can be read. Example: /etc/postfix/main.cf: tls_random_bytes = 32 In order to update its in-memory PRNG pool, the tlsmgr(8) queries the external entropy source again after a pseudo-random amount of time. The time is calculated using the PRNG, and is between 0 and the maximal time specified with tls_random_reseed_period. The default maximal time interval is 1 hour. Example: /etc/postfix/main.cf: tls_random_reseed_period = 3600s The tlsmgr(8) process saves the PRNG state to a persistent exchange file at regular times and when the process terminates, so that it can recover the PRNG state the next time it starts up. This file is created when it does not exist. Examples: /etc/postfix/main.cf: tls_random_exchange_name = /var/lib/postfix/prng_exch tls_random_prng_update_period = 3600s As of version 2.5, Postfix no longer uses root privileges when opening this file. The file should now be stored under the Postfix-owned data_directory. As a migration aid, an attempt to open the file under a non-Postfix directory is redirected to the Postfix-owned data_directory, and a warning is logged. If you wish to continue using a pre-existing PRNG state file, move it to the data_directory and change the ownership to the account specified with the mail_owner parameter. With earlier Postfix versions the default file location is under the Postfix configuration directory, which is not the proper place for information that is modified by Postfix. GGeettttiinngg ssttaarrtteedd,, qquuiicckk aanndd ddiirrttyy The following steps will get you started quickly. Because you sign your own Postfix public key certificate, you get TLS encryption but no TLS authentication. This is sufficient for testing, and for exchanging email with sites that you have no trust relationship with. For real authentication, your Postfix public key certificate needs to be signed by a recognized Certificate Authority, and Postfix needs to be configured with a list of public key certificates of Certificate Authorities, so that Postfix can verify the public key certificates of remote hosts. In the examples below, user input is shown in bboolldd font, and a "#" prompt indicates a super-user shell. * Become your own Certificate Authority, so that you can sign your own public keys. This example uses the CA.pl script that ships with OpenSSL. By default, OpenSSL installs this as /usr/local/ssl/misc/CA.pl, but your mileage may vary. The script creates a private key in ./demoCA/private/ cakey.pem and a public key in ./demoCA/cacert.pem. % //uussrr//llooccaall//ssssll//mmiisscc//CCAA..ppll --nneewwccaa CA certificate filename (or enter to create) Making CA certificate ... Using configuration from /etc/ssl/openssl.cnf Generating a 1024 bit RSA private key ....................++++++ .....++++++ writing new private key to './demoCA/private/cakey.pem' Enter PEM pass phrase:wwhhaatteevveerr * Create an unpassworded private key for host foo.porcupine.org and create an unsigned public key certificate. % ooppeennssssll rreeqq --nneeww --nnooddeess --kkeeyyoouutt ffoooo--kkeeyy..ppeemm --oouutt ffoooo--rreeqq..ppeemm --ddaayyss 336655 Using configuration from /etc/ssl/openssl.cnf Generating a 1024 bit RSA private key ........................................++++++ ....++++++ writing new private key to 'foo-key.pem' ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:UUSS State or Province Name (full name) [Some-State]:NNeeww YYoorrkk Locality Name (eg, city) []:WWeessttcchheesstteerr Organization Name (eg, company) [Internet Widgits Pty Ltd]:PPoorrccuuppiinnee Organizational Unit Name (eg, section) []: Common Name (eg, YOUR name) []:ffoooo..ppoorrccuuppiinnee..oorrgg Email Address []:wwiieettssee@@ppoorrccuuppiinnee..oorrgg Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []:wwhhaatteevveerr An optional company name []: * Sign the public key certificate for host foo.porcupine.org with the Certification Authority private key that we created a few steps ago. % ooppeennssssll ccaa --oouutt ffoooo--cceerrtt..ppeemm --iinnffiilleess ffoooo--rreeqq..ppeemm Using configuration from /etc/ssl/openssl.cnf Enter PEM pass phrase:wwhhaatteevveerr Check that the request matches the signature Signature ok The Subjects Distinguished Name is as follows countryName :PRINTABLE:'US' stateOrProvinceName :PRINTABLE:'New York' localityName :PRINTABLE:'Westchester' organizationName :PRINTABLE:'Porcupine' commonName :PRINTABLE:'foo.porcupine.org' emailAddress :IA5STRING:'wietse@porcupine.org' Certificate is to be certified until Nov 21 19:40:56 2005 GMT (365 days) Sign the certificate? [y/n]:yy 1 out of 1 certificate requests certified, commit? [y/n]yy Write out database with 1 new entries Data Base Updated * Install the host private key, the host public key certificate, and the Certification Authority certificate files. This requires super-user privileges. # ccpp ddeemmooCCAA//ccaacceerrtt..ppeemm ffoooo--kkeeyy..ppeemm ffoooo--cceerrtt..ppeemm //eettcc//ppoossttffiixx # cchhmmoodd 664444 //eettcc//ppoossttffiixx//ffoooo--cceerrtt..ppeemm //eettcc//ppoossttffiixx//ccaacceerrtt..ppeemm # cchhmmoodd 440000 //eettcc//ppoossttffiixx//ffoooo--kkeeyy..ppeemm * Configure Postfix, by adding the following to /etc/postfix/main.cf. It is generally best to not configure client certificates, unless there are servers which authenticate your mail submission via client certificates. Often servers that perform TLS client authentication will issue the required certificates signed by their own CA. If you configure the client certificate and key incorrectly, you will be unable to send mail to sites that request client certificate, but don't require them from all clients. /etc/postfix/main.cf: smtp_tls_CAfile = /etc/postfix/cacert.pem smtp_tls_session_cache_database = btree:/var/lib/postfix/smtp_tls_session_cache smtp_tls_security_level = may smtpd_tls_CAfile = /etc/postfix/cacert.pem smtpd_tls_cert_file = /etc/postfix/foo-cert.pem smtpd_tls_key_file = /etc/postfix/foo-key.pem smtpd_tls_received_header = yes smtpd_tls_session_cache_database = btree:/var/lib/postfix/smtpd_tls_session_cache tls_random_source = dev:/dev/urandom # Postfix 2.3 and later smtpd_tls_security_level = may # Obsolete, but still supported smtpd_use_tls = yes RReeppoorrttiinngg pprroobblleemmss Problems are preferably reported via . See http:// www.postfix.org/lists.html for subscription information. When reporting a problem, please be thorough in the report. Patches, when possible, are greatly appreciated too. CCrreeddiittss * TLS support for Postfix was originally developed by Lutz Jänicke at Cottbus Technical University. * Wietse Venema adopted the code, did some restructuring, and compiled this part of the documentation from Lutz's documents. * Victor Duchovni was instrumental with the re-implementation of the smtp_tls_per_site code in terms of enforcement levels, which simplified the implementation greatly. * Victor Duchovni implemented the fingerprint security level, added more sanity checks, and separated TLS connection management from security policy enforcement. The latter change simplified the code that verifies certificate signatures, certificate names, and certificate fingerprints. README_FILES/PGSQL_README000066600000010627150501202770010262 0ustar00PPoossttffiixx PPoossttggrreeSSQQLL HHoowwttoo ------------------------------------------------------------------------------- IInnttrroodduuccttiioonn The Postfix pgsql map type allows you to hook up Postfix to a PostgreSQL database. This implementation allows for multiple pgsql databases: you can use one for a virtual(5) table, one for an access(5) table, and one for an aliases (5) table if you want. You can specify multiple servers for the same database, so that Postfix can switch to a good database server if one goes bad. Busy mail servers using pgsql maps will generate lots of concurrent pgsql clients, so the pgsql server(s) should be run with this fact in mind. You can reduce the number of concurrent pgsql clients by using the Postfix proxymap(8) service. BBuuiillddiinngg PPoossttffiixx wwiitthh PPoossttggrreeSSQQLL ssuuppppoorrtt These instructions assume that you build Postfix from source code as described in the INSTALL document. Some modification may be required if you build Postfix from a vendor-specific source package. Note: to use pgsql with Debian GNU/Linux's Postfix, all you need to do is to install the postfix-pgsql package and you're done. There is no need to recompile Postfix. In order to build Postfix with pgsql map support, you specify -DHAS_PGSQL, the directory with the PostgreSQL header files, and the location of the libpq library file. For example: % make tidy % make -f Makefile.init makefiles \ 'CCARGS=-DHAS_PGSQL -I/usr/local/include/pgsql' \ 'AUXLIBS=-L/usr/local/lib -lpq' Then just run 'make'. CCoonnffiigguurriinngg PPoossttggrreeSSQQLL llooookkuupp ttaabblleess Once Postfix is built with pgsql support, you can specify a map type in main.cf like this: /etc/postfix/main.cf: alias_maps = pgsql:/etc/postfix/pgsql-aliases.cf The file /etc/postfix/pgsql-aliases.cf specifies lots of information telling postfix how to reference the pgsql database. For a complete description, see the pgsql_table(5) manual page. EExxaammppllee:: llooccaall aalliiaasseess # # pgsql config file for local(8) aliases(5) lookups # # # The hosts that Postfix will try to connect to hosts = host1.some.domain host2.some.domain # The user name and password to log into the pgsql server. user = someone password = some_password # The database name on the servers. dbname = customer_database # Postfix 2.2 and later The SQL query template. See pgsql_table(5). query = SELECT forw_addr FROM mxaliases WHERE alias='%s' AND status='paid' # For Postfix releases prior to 2.2. See pgsql_table(5) for details. select_field = forw_addr table = mxaliases where_field = alias # Don't forget the leading "AND"! additional_conditions = AND status = 'paid' UUssiinngg mmiirrrroorreedd ddaattaabbaasseess Sites that have a need for multiple mail exchangers may enjoy the convenience of using a networked mailer database, but do not want to introduce a single point of failure to their system. For this reason we've included the ability to have Postfix reference multiple hosts for access to a single pgsql map. This will work if sites set up mirrored pgsql databases on two or more hosts. Whenever queries fail with an error at one host, the rest of the hosts will be tried in random order. If no pgsql server hosts are reachable, then mail will be deferred until at least one of those hosts is reachable. CCrreeddiittss * This code is based upon the Postfix mysql map by Scott Cotton and Joshua Marcus, IC Group, Inc. * The PostgreSQL changes were done by Aaron Sethman. * Updates for Postfix 1.1.x and PostgreSQL 7.1+ and support for calling stored procedures were added by Philip Warner. * LaMont Jones was the initial Postfix pgsql maintainer. * Liviu Daia revised the configuration interface and added the main.cf configuration feature. * Liviu Daia revised the configuration interface and added the main.cf configuration feature. * Liviu Daia with further refinements from Jose Luis Tallon and Victor Duchovni developed the common query, result_format, domain and expansion_limit interface for LDAP, MySQL and PosgreSQL. * Leandro Santi updated the PostgreSQL client after the PostgreSQL developers made major database API changes in response to SQL injection problems, and made PQexec() handling more robust. README_FILES/OVERVIEW000066600000045111150501202770007621 0ustar00PPoossttffiixx AArrcchhiitteeccttuurree OOvveerrvviieeww ------------------------------------------------------------------------------- IInnttrroodduuccttiioonn This document presents an overview of the Postfix architecture, and provides pointers to descriptions of every Postfix command or server program. The text gives the general context in which each command or server program is used, and provides pointers to documents with specific usage examples and background information. Topics covered by this document: * How Postfix receives mail * How Postfix delivers mail * Postfix behind the scenes * Postfix support commands HHooww PPoossttffiixx rreecceeiivveess mmaaiill When a message enters the Postfix mail system, the first stop on the inside is the incoming queue. The figure below shows the main processes that are involved with new mail. Names followed by a number are Postfix commands or server programs, while unnumbered names inside shaded areas represent Postfix queues. trivial- rewrite(8) Network -> smtpd(8) ^ | \ | v Network -> qmqpd(8) -> cleanup(8) -> incoming / pickup(8) <- maildrop ^ | Local -> sendmail(1) -> postdrop(1) * Network mail enters Postfix via the smtpd(8) or qmqpd(8) servers. These servers remove the SMTP or QMQP protocol encapsulation, enforce some sanity checks to protect Postfix, and give the sender, recipients and message content to the cleanup(8) server. The smtpd(8) server can be configured to block unwanted mail, as described in the SMTPD_ACCESS_README document. * Local submissions are received with the Postfix sendmail(1) compatibility command, and are queued in the maildrop queue by the privileged postdrop(1) command. This arrangement even works while the Postfix mail system is not running. The local pickup(8) server picks up local submissions, enforces some sanity checks to protect Postfix, and gives the sender, recipients and message content to the cleanup(8) server. * Mail from internal sources is given directly to the cleanup(8) server. These sources are not shown in the figure, and include: mail that is forwarded by the local(8) delivery agent (see next section), messages that are returned to the sender by the bounce(8) server (see second-next section), and postmaster notifications about problems with Postfix. * The cleanup(8) server implements the final processing stage before mail is queued. It adds missing From: and other message headers, and transforms addresses as described in the ADDRESS_REWRITING_README document. Optionally, the cleanup(8) server can be configured to do light-weight content inspection with regular expressions as described in the BUILTIN_FILTER_README document. The cleanup(8) server places the result as a single file into the incoming queue, and notifies the queue manager (see next section) of the arrival of new mail. * The trivial-rewrite(8) server rewrites addresses to the standard "user@fully.qualified.domain" form, as described in the ADDRESS_REWRITING_README document. Postfix currently does not implement a rewriting language, but a lot can be done via table lookups and, if need be, regular expressions. HHooww PPoossttffiixx ddeelliivveerrss mmaaiill Once a message has reached the incoming queue the next step is to deliver it. The figure shows the main components of the Postfix mail delivery apparatus. Names followed by a number are Postfix commands or server programs, while unnumbered names inside shaded areas represent Postfix queues. trivial- smtp(8) -> Network rewrite(8) / - lmtp(8) -> Network ^ | | v / incoming -> active -> qmgr(8) --- local(8) -> File, command \ ^ | | v - virtual(8) -> File deferred \ pipe(8) -> Command * The queue manager (the qmgr(8) server process in the figure) is the heart of Postfix mail delivery. It contacts the smtp(8), lmtp(8), local(8), virtual(8), pipe(8), discard(8) or error(8) delivery agents, and sends a delivery request for one or more recipient addresses. The discard(8) and error(8) delivery agents are special: they discard or bounce all mail, and are not shown in the figure above. The queue manager maintains a small active queue with the messages that it has opened for delivery. The active queue acts as a limited window on potentially large incoming or deferred queues. The limited active queue prevents the queue manager from running out of memory under heavy load. The queue manager maintains a separate deferred queue for mail that cannot be delivered, so that a large mail backlog will not slow down normal queue accesses. The queue manager's strategy for delayed mail delivery attempts is described in the QSHAPE_README and TUNING_README documents. * The trivial-rewrite(8) server resolves each recipient address according to its local or remote address class, as defined in the ADDRESS_CLASS_README document. Additional routing information can be specified with the optional transport(5) table. The trivial-rewrite(8) server optionally queries the relocated(5) table for recipients whose address has changed; mail for such recipients is returned to the sender with an explanation. * The smtp(8) client looks up a list of mail exchangers for the destination host, sorts the list by preference, and tries each server in turn until it finds a server that responds. It then encapsulates the sender, recipient and message content as required by the SMTP protocol; this includes conversion of 8-bit MIME to 7-bit encoding. * The lmtp(8) client speaks a protocol similar to SMTP that is optimized for delivery to mailbox servers such as Cyrus. The advantage of this setup is that one Postfix machine can feed multiple mailbox servers over LMTP. The opposite is true as well: one mailbox server can be fed over LMTP by multiple Postfix machines. * The local(8) delivery agent understands UNIX-style mailboxes, qmail- compatible maildir files, Sendmail-style system-wide aliases(5) databases, and Sendmail-style per-user .forward files. Multiple local delivery agents can be run in parallel, but parallel delivery to the same user is usually limited. The local(8) delivery agent has hooks for alternative forms of local delivery: you can configure it to deliver to mailbox files in user home directories, you can configure it to delegate mailbox delivery to an external command such as procmail, or you can delegate delivery to a different Postfix delivery agent. * The virtual(8) delivery agent is a bare-bones delivery agent that delivers to UNIX-style mailbox or qmail-style maildir files only. This delivery agent can deliver mail for multiple domains, which makes it especially suitable for hosting lots of small domains on a single machine. This is described in the VIRTUAL_README document. * The pipe(8) mailer is the outbound interface to other mail processing systems (the Postfix sendmail(1) command being the inbound interface). The interface is UNIX compatible: it provides information on the command line and on the standard input stream, and expects a process exit status code as defined in . Examples of delivery via the pipe(8) mailer are in the MAILDROP_README and UUCP_README documents. PPoossttffiixx bbeehhiinndd tthhee sscceenneess The previous sections gave an overview of how Postfix server processes send and receive mail. These server processes rely on other server processes that do things behind the scenes. The text below attempts to visualize each service in its own context. As before, names followed by a number are Postfix commands or server programs, while unnumbered names inside shaded areas represent Postfix queues. * The resident master(8) server is the supervisor that keeps an eye on the well-being of the Postfix mail system. It is typically started at system boot time with the "postfix start" command, and keeps running until the system goes down. The master(8) server is responsible for starting Postfix server processes to receive and deliver mail, and for restarting servers that terminate prematurely because of some problem. The master(8) server is also responsible for enforcing the server process count limits as specified in the mmaasstteerr..ccff configuration file. The picture below gives the program hierarchy when Postfix is started up. Only some of the mail handling daemon processes are shown. postfix(1) | | postfix-script(1) / | \ | / \ postsuper(1) master(8) postlog(1) / | \ | / \ smtpd(8) qmgr(8) local(8) * The anvil(8) server implements client connection and request rate limiting for all smtpd(8) servers. The TUNING_README document provides guidance for dealing with mis-behaving SMTP clients. The anvil(8) service is available in Postfix version 2.2 and later. Network -> smtpd(8) <-> anvil(8) * The bounce(8), defer(8) and trace(8) services each maintain their own queue directory trees with per-message logfiles. Postfix uses this information when sending "failed", "delayed" or "success" delivery status notifications to the sender. The trace(8) service also implements support for the Postfix "sendmail -bv" and "sendmail -v" commands which produce reports about how Postfix delivers mail, and is available with Postfix version 2.1 and later. See DEBUG_README for examples. qmgr(8) Delivery cleanup(8) -> Postfix -> agents queue ^ | | | v v (Non-) bounce(8) Queue id, delivery <- defer(8) <- recipient, notice trace(8) status ^ | | v Per- message logfiles * The flush(8) servers maintain per-destination logs and implement both ETRN and "sendmail -qRdestination", as described in the ETRN_README document. This moves selected queue files from the deferred queue back to the incoming queue and requests their delivery. The flush(8) service is available with Postfix version 1.0 and later. incoming ^ deferred ^ | smtpd(8) Destination Deferred Delivery sendmail(1) - to flush -> flush(8) <- destination, - agents, postqueue(1) queue id qmgr(8) ^ | | v Per-dest- ination logs * The proxymap(8) servers provide read-only and read-write table lookup service to Postfix processes. This overcomes chroot restrictions, reduces the number of open lookup tables by sharing one open table among multiple processes, and implements single-updater tables. * The scache(8) server maintains the connection cache for the Postfix smtp(8) client. When connection caching is enabled for selected destinations, the smtp(8) client does not disconnect immediately after a mail transaction, but gives the connection to the connection cache server which keeps the connection open for a limited amount of time. The smtp(8) client continues with some other mail delivery request. Meanwhile, any smtp(8) process can ask the scache(8) server for that cached connection and reuse it for mail delivery. As a safety measure, Postfix limits the number of times that a connection may be reused. When delivering mail to a destination with multiple mail servers, connection caching can help to skip over a non-responding server, and thus dramatically speed up delivery. SMTP connection caching is available in Postfix version 2.2 and later. More information about this feature is in the CONNECTION_CACHE_README document. /-- smtp(8) --> Internet qmgr(8) | | \-- | smtp(8) --> Internet | ^ | scache(8) * The showq(8) servers list the Postfix queue status. This is the queue listing service that does the work for the mailq(1) and postqueue(1) commands. mailq(1) Postfix Output <- post- <- showq(8) <- queue queue(1) * The spawn(8) servers run non-Postfix commands on request, with the client connected via socket or FIFO to the command's standard input, output and error streams. You can find examples of its use in the SMTPD_POLICY_README document. * The tlsmgr(8) server runs when TLS (Transport Layer Security, formerly known as SSL) is turned on in the Postfix smtp(8) client or smtpd(8) server. This process has two duties: o Maintain the pseudo-random number generator (PRNG) that is used to seed the TLS engines in Postfix smtp(8) client or smtpd(8) server processes. The state of this PRNG is periodically saved to a file, and is read when tlsmgr(8) starts up. o Maintain the optional Postfix smtp(8) client or smtpd(8) server caches with TLS session keys. Saved keys can improve performance by reducing the amount of computation at the start of a TLS session. TLS support is available in Postfix version 2.2 and later. Information about the Postfix TLS implementation is in the TLS_README document. <---seed--- ---seed---> Network-> smtpd(8) tlsmgr(8) smtp(8) ->Network <-session-> <-session-> / | \ | / \ smtpd PRNG smtp session state session cache file cache * The verify(8) server verifies that a sender or recipient address is deliverable before the smtpd(8) server accepts it. The verify(8) server injects probe messages into the Postfix queue and processes status updates from delivery agents and/or queue manager. This process is described in the ADDRESS_VERIFICATION_README document. The verify(8) service is available with Postfix version 2.1 and later. qmgr(8) Delivery Network -> smtpd(8) <-> verify(8) -> cleanup(8) -> Postfix -> agents queue \ | / v \ / <- <- PPoossttffiixx ssuuppppoorrtt ccoommmmaannddss The Postfix architecture overview ends with a summary of command-line utilities for day-to-day use of the Postfix mail system. Besides the Sendmail-compatible sendmail(1), mailq(1), and newaliases(1) commands, the Postfix system comes with it own collection of command-line utilities. For consistency, these are all named postsomething. * The postfix(1) command controls the operation of the mail system. It is the interface for starting, stopping, and restarting the mail system, as well as for some other administrative operations. This command is reserved to the super-user. * The postalias(1) command maintains Postfix aliases(5) type databases. This is the program that does the work for the newaliases(1) command. * The postcat(1) command displays the contents of Postfix queue files. This is a limited, preliminary utility. This program is likely to be superseded by something more powerful that can also edit Postfix queue files. * The postconf(1) command displays or updates Postfix main.cf parameters and displays system dependent information about the supported file locking methods, and the supported types of lookup tables. * The postdrop(1) command is the mail posting utility that is run by the Postfix sendmail(1) command in order to deposit mail into the maildrop queue directory. * The postkick(1) command makes some Postfix internal communication channels available for use in, for example, shell scripts. * The postlock(1) command provides Postfix-compatible mailbox locking for use in, for example, shell scripts. * The postlog(1) command provides Postfix-compatible logging for shell scripts. * The postmap(1) command maintains Postfix lookup tables such as canonical (5), virtual(5) and others. It is a cousin of the UNIX makemap command. * The postmulti(1) command repeats the "postfix start" etc. command for each Postfix instance, and supports creation, deletion etc. of Postfix instances. For a tutorial, see MULTI_INSTANCE_README. * The postqueue(1) command is the privileged command that is run by Postfix sendmail(1) and mailq(1) in order to flush or list the mail queue. * The postsuper(1) command maintains the Postfix queue. It removes old temporary files, and moves queue files into the right directory after a change in the hashing depth of queue directories. This command is run at mail system startup time and when Postfix is restarted. README_FILES/BACKSCATTER_README000066600000030460150501202770011117 0ustar00PPoossttffiixx BBaacckkssccaatttteerr HHoowwttoo ------------------------------------------------------------------------------- OOvveerrvviieeww This document describes features that require Postfix version 2.0 or later. Topics covered in this document: * What is backscatter mail? * How do I block backscatter mail to random recipient addresses? * How do I block backscatter mail to real recipient addresses? o Blocking backscatter mail with forged mail server information o Blocking backscatter mail with forged sender information o Blocking backscatter mail with other forged information o Blocking backscatter mail from virus scanners The examples use Perl Compatible Regular Expressions (Postfix pcre: tables), but also provide a translation to POSIX regular expressions (Postfix regexp: tables). PCRE is preferred primarily because the implementation is often faster. WWhhaatt iiss bbaacckkssccaatttteerr mmaaiill?? When a spammer or worm sends mail with forged sender addresses, innocent sites are flooded with undeliverable mail notifications. This is called backscatter mail. With Postfix, you know that you're a backscatter victim when your logfile goes on and on like this: Dec 4 04:30:09 hostname postfix/smtpd[58549]: NOQUEUE: reject: RCPT from xxxxxxx[x.x.x.x]: 550 5.1.1 : Recipient address rejected: User unknown; from=<> to= proto=ESMTP helo= What you see are lots of "user unknown" errors with "from=<>". These are error reports from MAILER-DAEMONs elsewhere on the Internet. HHooww ddoo II bblloocckk bbaacckkssccaatttteerr mmaaiill ttoo rraannddoomm rreecciippiieenntt aaddddrreesssseess?? If your machine receives backscatter mail to random addresses, configure Postfix to reject all mail for non-existent recipients as described in the LOCAL_RECIPIENT_README and STANDARD_CONFIGURATION_README documentation. If your machine runs Postfix 2.0 and earlier, disable the "pause before reject" feature in the SMTP server. If your system is under stress then it should not waste time. /etc/postfix/main.cf: # Not needed with Postfix 2.1 and later. smtpd_error_sleep_time = 0 # Not needed with Postfix 2.4 and later. unknown_local_recipient_reject_code = 550 HHooww ddoo II bblloocckk bbaacckkssccaatttteerr mmaaiill ttoo rreeaall rreecciippiieenntt aaddddrreesssseess?? When backscatter mail passes the "unknown recipient" barrier, there still is no need to despair. Many mail systems are kind enough to attach the message headers of the undeliverable mail in the non-delivery notification. These message headers contain information that you can use to recognize and block forged mail. BBlloocckkiinngg bbaacckkssccaatttteerr mmaaiill wwiitthh ffoorrggeedd mmaaiill sseerrvveerr iinnffoorrmmaattiioonn Although my email address is "wietse@porcupine.org", all my mail systems announce themselves with the SMTP HELO command as "hostname.porcupine.org". Thus, if returned mail has a Received: message header like this: Received: from porcupine.org ... Then I know that this is almost certainly forged mail (almost; see next section for the fly in the ointment). Mail that is really sent by my systems looks like this: Received: from hostname.porcupine.org ... For the same reason the following message headers are very likely to be the result of forgery: Received: from host.example.com ([1.2.3.4] helo=porcupine.org) ... Received: from [1.2.3.4] (port=12345 helo=porcupine.org) ... Received: from host.example.com (HELO porcupine.org) ... Received: from host.example.com (EHLO porcupine.org) ... Some forgeries show up in the way that a mail server reports itself in Received: message headers. Keeping in mind that all my systems have a mail server name of hostname.porcupine.org, the following is definitely a forgery: Received: by porcupine.org ... Received: from host.example.com ( ... ) by porcupine.org ... Another frequent sign of forgery is the Message-ID: header. My systems produce a Message-ID: of . The following are forgeries, especially the first one: Message-ID: <1cb479435d8eb9.2beb1.qmail@porcupine.org> Message-ID: To block such backscatter I use header_checks and body_checks patterns like this: /etc/postfix/main.cf: header_checks = pcre:/etc/postfix/header_checks body_checks = pcre:/etc/postfix/body_checks /etc/postfix/header_checks: if /^Received:/ /^Received: +from +(porcupine\.org) +/ reject forged client name in Received: header: $1 /^Received: +from +[^ ]+ +\(([^ ]+ +[he]+lo=|[he]+lo +) (porcupine\.org)\)/ reject forged client name in Received: header: $2 /^Received:.* +by +(porcupine\.org)\b/ reject forged mail server name in Received: header: $1 endif /^Message-ID:.* ]*Received:/ /^[> ]*Received: +from +(porcupine\.org) / reject forged client name in Received: header: $1 /^[> ]*Received: +from +[^ ]+ +\(([^ ]+ +[he]+lo=|[he]+lo +) (porcupine\.org)\)/ reject forged client name in Received: header: $2 /^[> ]*Received:.* +by +(porcupine\.org)\b/ reject forged mail server name in Received: header: $1 endif /^[> ]*Message-ID:.* ]*Message-ID:.*@(porcupine\.org)/ reject forged domain name in Message-ID: header: $1 Notes: * The example uses pcre: tables mainly for speed; with minor modifications, you can use regexp: tables as explained below. * The example is simplified for educational purposes. In reality my patterns list multiple domain names, as "(domain|domain|...)". * The "\." matches "." literally. Without the "\", the "." would match any character. * The "\(" and "\)" match "(" and ")" literally. Without the "\", the "(" and ")" would be grouping operators. * The "\b" is used here to match the end of a word. If you use regexp: tables, specify "[[:>:]]" (on some systems you should specify "\>" instead; for details see your system documentation). * The "if /pattern/" and "endif" eliminate unnecessary matching attempts. DO NOT indent lines starting with /pattern/ between the "if" and "endif"! * The two "Message-ID:.* where example.com is the domain name part of the email address specified in Outlook's account settings for the user. Since many users configure their email addresses as username@example.com, messages with DSN turned on will trigger the REJECT action in the previous section. If you have such clients then you can to exclude their Message-ID strings with the two "Message-ID:.* ]*(From|Return-Path):.*\b(user@domain\.tld)\b/ reject forged sender address in $1: header: $2 Notes: * The example uses pcre: tables mainly for speed; with minor modifications, you can use regexp: tables as explained below. * The example is simplified for educational purposes. In reality, my patterns list multiple email addresses as "(user1@domain1\.tld|user2@domain2\.tld)". * The two "\b" as used in "\b(user@domain\.tld)\b" match the beginning and end of a word, respectively. If you use regexp: tables, specify "[[:<:]] and [[:>:]]" (on some systems you should specify "\< and \>" instead; for details see your system documentation). * The "\." matches "." literally. Without the "\", the "." would match any character. BBlloocckkiinngg bbaacckkssccaatttteerr mmaaiill wwiitthh ootthheerr ffoorrggeedd iinnffoorrmmaattiioonn Another sign of forgery can be found in the IP address that is recorded in Received: headers next to your HELO host or domain name. This information must be used with care, though. Some mail servers are behind a network address translator and never see the true client IP address. BBlloocckkiinngg bbaacckkssccaatttteerr mmaaiill ffrroomm vviirruuss ssccaannnneerrss With all the easily recognizable forgeries eliminated, there is one category of backscatter mail that remains, and that is notifications from virus scanner software. Unfortunately, some virus scanning software doesn't know that viruses forge sender addresses. To make matters worse, the software also doesn't know how to report a mail delivery problem, so that we cannot use the above techniques to recognize forgeries. Recognizing virus scanner mail is an error prone process, because there is a lot of variation in report formats. The following is only a small example of message header patterns. For a large collection of header and body patterns that recognize virus notification email, see http://www.dkuug.dk/keld/virus/ or http://www.t29.dk/antiantivirus.txt. /etc/postfix/header_checks: /^Subject: *Your email contains VIRUSES/ DISCARD virus notification /^Content-Disposition:.*VIRUS1_DETECTED_AND_REMOVED/ DISCARD virus notification /^Content-Disposition:.*VirusWarning.txt/ DISCARD virus notification Note: these documents haven't been updated since 2004, so they are useful only as a starting point. A plea to virus or spam scanner operators: please do not make the problem worse by sending return mail to forged sender addresses. You're only harassing innocent people. If you must return mail to the purported sender, please return the full message headers, so that the sender can filter out the obvious forgeries. README_FILES/QSHAPE_README000066600000110206150501202770010347 0ustar00PPoossttffiixx BBoottttlleenneecckk AAnnaallyyssiiss ------------------------------------------------------------------------------- PPuurrppoossee ooff tthhiiss ddooccuummeenntt This document is an introduction to Postfix queue congestion analysis. It explains how the qshape(1) program can help to track down the reason for queue congestion. qshape(1) is bundled with Postfix 2.1 and later source code, under the "auxiliary" directory. This document describes qshape(1) as bundled with Postfix 2.4. This document covers the following topics: * Introducing the qshape tool * Trouble shooting with qshape * Example 1: Healthy queue * Example 2: Deferred queue full of dictionary attack bounces * Example 3: Congestion in the active queue * Example 4: High volume destination backlog * Postfix queue directories o The "maildrop" queue o The "hold" queue o The "incoming" queue o The "active" queue o The "deferred" queue * Credits IInnttrroodduucciinngg tthhee qqsshhaappee ttooooll When mail is draining slowly or the queue is unexpectedly large, run qshape(1) as the super-user (root) to help zero in on the problem. The qshape(1) program displays a tabular view of the Postfix queue contents. * On the horizontal axis, it displays the queue age with fine granularity for recent messages and (geometrically) less fine granularity for older messages. * The vertical axis displays the destination (or with the "-s" switch the sender) domain. Domains with the most messages are listed first. For example, in the output below we see the top 10 lines of the (mostly forged) sender domain distribution for captured spam in the "hold" queue: $ qshape -s hold | head T 5 10 20 40 80 160 320 640 1280 1280+ TOTAL 486 0 0 1 0 0 2 4 20 40 419 yahoo.com 14 0 0 1 0 0 0 0 1 0 12 extremepricecuts.net 13 0 0 0 0 0 0 0 2 0 11 ms35.hinet.net 12 0 0 0 0 0 0 0 0 1 11 winnersdaily.net 12 0 0 0 0 0 0 0 2 0 10 hotmail.com 11 0 0 0 0 0 0 0 0 1 10 worldnet.fr 6 0 0 0 0 0 0 0 0 0 6 ms41.hinet.net 6 0 0 0 0 0 0 0 0 0 6 osn.de 5 0 0 0 0 0 1 0 0 0 4 * The "T" column shows the total (in this case sender) count for each domain. The columns with numbers above them, show counts for messages aged fewer than that many minutes, but not younger than the age limit for the previous column. The row labeled "TOTAL" shows the total count for all domains. * In this example, there are 14 messages allegedly from yahoo.com, 1 between 10 and 20 minutes old, 1 between 320 and 640 minutes old and 12 older than 1280 minutes (1440 minutes in a day). When the output is a terminal intermediate results showing the top 20 domains (-n option) are displayed after every 1000 messages (-N option) and the final output also shows only the top 20 domains. This makes qshape useful even when the deferred queue is very large and it may otherwise take prohibitively long to read the entire deferred queue. By default, qshape shows statistics for the union of both the incoming and active queues which are the most relevant queues to look at when analyzing performance. One can request an alternate list of queues: $ qshape deferred $ qshape incoming active deferred this will show the age distribution of the deferred queue or the union of the incoming active and deferred queues. Command line options control the number of display "buckets", the age limit for the smallest bucket, display of parent domain counts and so on. The "-h" option outputs a summary of the available switches. TTrroouubbllee sshhoooottiinngg wwiitthh qqsshhaappee Large numbers in the qshape output represent a large number of messages that are destined to (or alleged to come from) a particular domain. It should be possible to tell at a glance which domains dominate the queue sender or recipient counts, approximately when a burst of mail started, and when it stopped. The problem destinations or sender domains appear near the top left corner of the output table. Remember that the active queue can accommodate up to 20000 ($qmgr_message_active_limit) messages. To check whether this limit has been reached, use: $ qshape -s active (show sender statistics) If the total sender count is below 20000 the active queue is not yet saturated, any high volume sender domains show near the top of the output. With oqmgr(8) the active queue is also limited to at most 20000 recipient addresses ($qmgr_message_recipient_limit). To check for exhaustion of this limit use: $ qshape active (show recipient statistics) Having found the high volume domains, it is often useful to search the logs for recent messages pertaining to the domains in question. # Find deliveries to example.com # $ tail -10000 /var/log/maillog | egrep -i ': to=<.*@example\.com>,' | less # Find messages from example.com # $ tail -10000 /var/log/maillog | egrep -i ': from=<.*@example\.com>,' | less You may want to drill in on some specific queue ids: # Find all messages for a specific queue id. # $ tail -10000 /var/log/maillog | egrep ': 2B2173FF68: ' Also look for queue manager warning messages in the log. These warnings can suggest strategies to reduce congestion. $ egrep 'qmgr.*(panic|fatal|error|warning):' /var/log/maillog When all else fails try the Postfix mailing list for help, but please don't forget to include the top 10 or 20 lines of qshape(1) output. EExxaammppllee 11:: HHeeaalltthhyy qquueeuuee When looking at just the incoming and active queues, under normal conditions (no congestion) the incoming and active queues are nearly empty. Mail leaves the system almost as quickly as it comes in or is deferred without congestion in the active queue. $ qshape (show incoming and active queue status) T 5 10 20 40 80 160 320 640 1280 1280+ TOTAL 5 0 0 0 1 0 0 0 1 1 2 meri.uwasa.fi 5 0 0 0 1 0 0 0 1 1 2 If one looks at the two queues separately, the incoming queue is empty or perhaps briefly has one or two messages, while the active queue holds more messages and for a somewhat longer time: $ qshape incoming T 5 10 20 40 80 160 320 640 1280 1280+ TOTAL 0 0 0 0 0 0 0 0 0 0 0 $ qshape active T 5 10 20 40 80 160 320 640 1280 1280+ TOTAL 5 0 0 0 1 0 0 0 1 1 2 meri.uwasa.fi 5 0 0 0 1 0 0 0 1 1 2 EExxaammppllee 22:: DDeeffeerrrreedd qquueeuuee ffuullll ooff ddiiccttiioonnaarryy aattttaacckk bboouunncceess This is from a server where recipient validation is not yet available for some of the hosted domains. Dictionary attacks on the unvalidated domains result in bounce backscatter. The bounces dominate the queue, but with proper tuning they do not saturate the incoming or active queues. The high volume of deferred mail is not a direct cause for alarm. $ qshape deferred | head T 5 10 20 40 80 160 320 640 1280 1280+ TOTAL 2234 4 2 5 9 31 57 108 201 464 1353 heyhihellothere.com 207 0 0 1 1 6 6 8 25 68 92 pleazerzoneprod.com 105 0 0 0 0 0 0 0 5 44 56 groups.msn.com 63 2 1 2 4 4 14 14 14 8 0 orion.toppoint.de 49 0 0 0 1 0 2 4 3 16 23 kali.com.cn 46 0 0 0 0 1 0 2 6 12 25 meri.uwasa.fi 44 0 0 0 0 1 0 2 8 11 22 gjr.paknet.com.pk 43 1 0 0 1 1 3 3 6 12 16 aristotle.algonet.se 41 0 0 0 0 0 1 2 11 12 15 The domains shown are mostly bulk-mailers and all the volume is the tail end of the time distribution, showing that short term arrival rates are moderate. Larger numbers and lower message ages are more indicative of current trouble. Old mail still going nowhere is largely harmless so long as the active and incoming queues are short. We can also see that the groups.msn.com undeliverables are low rate steady stream rather than a concentrated dictionary attack that is now over. $ qshape -s deferred | head T 5 10 20 40 80 160 320 640 1280 1280+ TOTAL 2193 4 4 5 8 33 56 104 205 465 1309 MAILER-DAEMON 1709 4 4 5 8 33 55 101 198 452 849 example.com 263 0 0 0 0 0 0 0 0 2 261 example.org 209 0 0 0 0 0 1 3 6 11 188 example.net 6 0 0 0 0 0 0 0 0 0 6 example.edu 3 0 0 0 0 0 0 0 0 0 3 example.gov 2 0 0 0 0 0 0 0 1 0 1 example.mil 1 0 0 0 0 0 0 0 0 0 1 Looking at the sender distribution, we see that as expected most of the messages are bounces. EExxaammppllee 33:: CCoonnggeessttiioonn iinn tthhee aaccttiivvee qquueeuuee This example is taken from a Feb 2004 discussion on the Postfix Users list. Congestion was reported with the active and incoming queues large and not shrinking despite very large delivery agent process limits. The thread is archived at: http://groups.google.com/groups?th=636626c645f5bbde Using an older version of qshape(1) it was quickly determined that all the messages were for just a few destinations: $ qshape (show incoming and active queue status) T A 5 10 20 40 80 160 320 320+ TOTAL 11775 9996 0 0 1 1 42 94 221 1420 user.sourceforge.net 7678 7678 0 0 0 0 0 0 0 0 lists.sourceforge.net 2313 2313 0 0 0 0 0 0 0 0 gzd.gotdns.com 102 0 0 0 0 0 0 0 2 100 The "A" column showed the count of messages in the active queue, and the numbered columns showed totals for the deferred queue. At 10000 messages (Postfix 1.x active queue size limit) the active queue is full. The incoming was growing rapidly. With the trouble destinations clearly identified, the administrator quickly found and fixed the problem. It is substantially harder to glean the same information from the logs. While a careful reading of mailq(1) output should yield similar results, it is much harder to gauge the magnitude of the problem by looking at the queue one message at a time. EExxaammppllee 44:: HHiigghh vvoolluummee ddeessttiinnaattiioonn bbaacckklloogg When a site you send a lot of email to is down or slow, mail messages will rapidly build up in the deferred queue, or worse, in the active queue. The qshape output will show large numbers for the destination domain in all age buckets that overlap the starting time of the problem: $ qshape deferred | head T 5 10 20 40 80 160 320 640 1280 1280+ TOTAL 5000 200 200 400 800 1600 1000 200 200 200 200 highvolume.com 4000 160 160 320 640 1280 1440 0 0 0 0 ... Here the "highvolume.com" destination is continuing to accumulate deferred mail. The incoming and active queues are fine, but the deferred queue started growing some time between 1 and 2 hours ago and continues to grow. If the high volume destination is not down, but is instead slow, one might see similar congestion in the active queue. Active queue congestion is a greater cause for alarm; one might need to take measures to ensure that the mail is deferred instead or even add an access(5) rule asking the sender to try again later. If a high volume destination exhibits frequent bursts of consecutive connections refused by all MX hosts or "421 Server busy errors", it is possible for the queue manager to mark the destination as "dead" despite the transient nature of the errors. The destination will be retried again after the expiration of a $minimal_backoff_time timer. If the error bursts are frequent enough it may be that only a small quantity of email is delivered before the destination is again marked "dead". In some cases enabling static (not on demand) connection caching by listing the appropriate nexthop domain in a table included in "smtp_connection_cache_destinations" may help to reduce the error rate, because most messages will re-use existing connections. The MTA that has been observed most frequently to exhibit such bursts of errors is Microsoft Exchange, which refuses connections under load. Some proxy virus scanners in front of the Exchange server propagate the refused connection to the client as a "421" error. Note that it is now possible to configure Postfix to exhibit similarly erratic behavior by misconfiguring the anvil(8) service. Do not use anvil(8) for steady-state rate limiting, its purpose is (unintentional) DoS prevention and the rate limits set should be very generous! If one finds oneself needing to deliver a high volume of mail to a destination that exhibits frequent brief bursts of errors and connection caching does not solve the problem, there is a subtle workaround. * Postfix version 2.5 and later: o In master.cf set up a dedicated clone of the "smtp" transport for the destination in question. In the example below we will call it "fragile". o In master.cf configure a reasonable process limit for the cloned smtp transport (a number in the 10-20 range is typical). o IMPORTANT!!! In main.cf configure a large per-destination pseudo-cohort failure limit for the cloned smtp transport. /etc/postfix/main.cf: transport_maps = hash:/etc/postfix/transport fragile_destination_concurrency_failed_cohort_limit = 100 fragile_destination_concurrency_limit = 20 /etc/postfix/transport: example.com fragile: /etc/postfix/master.cf: # service type private unpriv chroot wakeup maxproc command fragile unix - - n - 20 smtp See also the documentation for default_destination_concurrency_failed_cohort_limit and default_destination_concurrency_limit. * Earlier Postfix versions: o In master.cf set up a dedicated clone of the "smtp" transport for the destination in question. In the example below we will call it "fragile". o In master.cf configure a reasonable process limit for the transport (a number in the 10-20 range is typical). o IMPORTANT!!! In main.cf configure a very large initial and destination concurrency limit for this transport (say 2000). /etc/postfix/main.cf: transport_maps = hash:/etc/postfix/transport initial_destination_concurrency = 2000 fragile_destination_concurrency_limit = 2000 /etc/postfix/transport: example.com fragile: /etc/postfix/master.cf: # service type private unpriv chroot wakeup maxproc command fragile unix - - n - 20 smtp See also the documentation for default_destination_concurrency_limit. The effect of this configuration is that up to 2000 consecutive errors are tolerated without marking the destination dead, while the total concurrency remains reasonable (10-20 processes). This trick is only for a very specialized situation: high volume delivery into a channel with multi-error bursts that is capable of high throughput, but is repeatedly throttled by the bursts of errors. When a destination is unable to handle the load even after the Postfix process limit is reduced to 1, a desperate measure is to insert brief delays between delivery attempts. * Postfix version 2.5 and later: o In master.cf set up a dedicated clone of the "smtp" transport for the problem destination. In the example below we call it "slow". o In main.cf configure a short delay between deliveries to the same destination. /etc/postfix/main.cf: transport_maps = hash:/etc/postfix/transport slow_destination_rate_delay = 1 /etc/postfix/transport: example.com slow: /etc/postfix/master.cf: # service type private unpriv chroot wakeup maxproc command slow unix - - n - - smtp See also the documentation for default_destination_rate_delay. This solution forces the Postfix smtp(8) client to wait for $slow_destination_rate_delay seconds between deliveries to the same destination. * Earlier Postfix versions: o In the transport map entry for the problem destination, specify a dead host as the primary nexthop. o In the master.cf entry for the transport specify the problem destination as the fallback_relay and specify a small smtp_connect_timeout value. /etc/postfix/main.cf: transport_maps = hash:/etc/postfix/transport /etc/postfix/transport: example.com slow:[dead.host] /etc/postfix/master.cf: # service type private unpriv chroot wakeup maxproc command slow unix - - n - 1 smtp -o fallback_relay=problem.example.com -o smtp_connect_timeout=1 -o smtp_connection_cache_on_demand=no This solution forces the Postfix smtp(8) client to wait for $smtp_connect_timeout seconds between deliveries. The connection caching feature is disabled to prevent the client from skipping over the dead host. PPoossttffiixx qquueeuuee ddiirreeccttoorriieess The following sections describe Postfix queues: their purpose, what normal behavior looks like, and how to diagnose abnormal behavior. TThhee ""mmaaiillddrroopp"" qquueeuuee Messages that have been submitted via the Postfix sendmail(1) command, but not yet brought into the main Postfix queue by the pickup(8) service, await processing in the "maildrop" queue. Messages can be added to the "maildrop" queue even when the Postfix system is not running. They will begin to be processed once Postfix is started. The "maildrop" queue is drained by the single threaded pickup(8) service scanning the queue directory periodically or when notified of new message arrival by the postdrop(1) program. The postdrop(1) program is a setgid helper that allows the unprivileged Postfix sendmail(1) program to inject mail into the "maildrop" queue and to notify the pickup(8) service of its arrival. All mail that enters the main Postfix queue does so via the cleanup(8) service. The cleanup service is responsible for envelope and header rewriting, header and body regular expression checks, automatic bcc recipient processing, milter content processing, and reliable insertion of the message into the Postfix "incoming" queue. In the absence of excessive CPU consumption in cleanup(8) header or body regular expression checks or other software consuming all available CPU resources, Postfix performance is disk I/O bound. The rate at which the pickup (8) service can inject messages into the queue is largely determined by disk access times, since the cleanup(8) service must commit the message to stable storage before returning success. The same is true of the postdrop(1) program writing the message to the "maildrop" directory. As the pickup service is single threaded, it can only deliver one message at a time at a rate that does not exceed the reciprocal disk I/O latency (+ CPU if not negligible) of the cleanup service. Congestion in this queue is indicative of an excessive local message submission rate or perhaps excessive CPU consumption in the cleanup(8) service due to excessive body_checks, or (Postfix >= 2.3) high latency milters. Note, that once the active queue is full, the cleanup service will attempt to slow down message injection by pausing $in_flow_delay for each message. In this case "maildrop" queue congestion may be a consequence of congestion downstream, rather than a problem in its own right. Note, you should not attempt to deliver large volumes of mail via the pickup(8) service. High volume sites should avoid using "simple" content filters that re- inject scanned mail via Postfix sendmail(1) and postdrop(1). A high arrival rate of locally submitted mail may be an indication of an uncaught forwarding loop, or a run-away notification program. Try to keep the volume of local mail injection to a moderate level. The "postsuper -r" command can place selected messages into the "maildrop" queue for reprocessing. This is most useful for resetting any stale content_filter settings. Requeuing a large number of messages using "postsuper -r" can clearly cause a spike in the size of the "maildrop" queue. TThhee ""hhoolldd"" qquueeuuee The administrator can define "smtpd" access(5) policies, or cleanup(8) header/ body checks that cause messages to be automatically diverted from normal processing and placed indefinitely in the "hold" queue. Messages placed in the "hold" queue stay there until the administrator intervenes. No periodic delivery attempts are made for messages in the "hold" queue. The postsuper(1) command can be used to manually release messages into the "deferred" queue. Messages can potentially stay in the "hold" queue longer than $maximal_queue_lifetime. If such "old" messages need to be released from the "hold" queue, they should typically be moved into the "maildrop" queue using "postsuper -r", so that the message gets a new timestamp and is given more than one opportunity to be delivered. Messages that are "young" can be moved directly into the "deferred" queue using "postsuper -H". The "hold" queue plays little role in Postfix performance, and monitoring of the "hold" queue is typically more closely motivated by tracking spam and malware, than by performance issues. TThhee ""iinnccoommiinngg"" qquueeuuee All new mail entering the Postfix queue is written by the cleanup(8) service into the "incoming" queue. New queue files are created owned by the "postfix" user with an access bitmask (or mode) of 0600. Once a queue file is ready for further processing the cleanup(8) service changes the queue file mode to 0700 and notifies the queue manager of new mail arrival. The queue manager ignores incomplete queue files whose mode is 0600, as these are still being written by cleanup. The queue manager scans the incoming queue bringing any new mail into the "active" queue if the active queue resource limits have not been exceeded. By default, the active queue accommodates at most 20000 messages. Once the active queue message limit is reached, the queue manager stops scanning the incoming (and deferred, see below) queue. Under normal conditions the incoming queue is nearly empty (has only mode 0600 files), with the queue manager able to import new messages into the active queue as soon as they become available. The incoming queue grows when the message input rate spikes above the rate at which the queue manager can import messages into the active queue. The main factors slowing down the queue manager are disk I/O and lookup queries to the trivial-rewrite service. If the queue manager is routinely not keeping up, consider not using "slow" lookup services (MySQL, LDAP, ...) for transport lookups or speeding up the hosts that provide the lookup service. If the problem is I/O starvation, consider striping the queue over more disks, faster controllers with a battery write cache, or other hardware improvements. At the very least, make sure that the queue directory is mounted with the "noatime" option if applicable to the underlying filesystem. The in_flow_delay parameter is used to clamp the input rate when the queue manager starts to fall behind. The cleanup(8) service will pause for $in_flow_delay seconds before creating a new queue file if it cannot obtain a "token" from the queue manager. Since the number of cleanup(8) processes is limited in most cases by the SMTP server concurrency, the input rate can exceed the output rate by at most "SMTP connection count" / $in_flow_delay messages per second. With a default process limit of 100, and an in_flow_delay of 1s, the coupling is strong enough to limit a single run-away injector to 1 message per second, but is not strong enough to deflect an excessive input rate from many sources at the same time. If a server is being hammered from multiple directions, consider raising the in_flow_delay to 10 seconds, but only if the incoming queue is growing even while the active queue is not full and the trivial-rewrite service is using a fast transport lookup mechanism. TThhee ""aaccttiivvee"" qquueeuuee The queue manager is a delivery agent scheduler; it works to ensure fast and fair delivery of mail to all destinations within designated resource limits. The active queue is somewhat analogous to an operating system's process run queue. Messages in the active queue are ready to be sent (runnable), but are not necessarily in the process of being sent (running). While most Postfix administrators think of the "active" queue as a directory on disk, the real "active" queue is a set of data structures in the memory of the queue manager process. Messages in the "maildrop", "hold", "incoming" and "deferred" queues (see below) do not occupy memory; they are safely stored on disk waiting for their turn to be processed. The envelope information for messages in the "active" queue is managed in memory, allowing the queue manager to do global scheduling, allocating available delivery agent processes to an appropriate message in the active queue. Within the active queue, (multi-recipient) messages are broken up into groups of recipients that share the same transport/nexthop combination; the group size is capped by the transport's recipient concurrency limit. Multiple recipient groups (from one or more messages) are queued for delivery grouped by transport/nexthop combination. The ddeessttiinnaattiioonn concurrency limit for the transports caps the number of simultaneous delivery attempts for each nexthop. Transports with a rreecciippiieenntt concurrency limit of 1 are special: these are grouped by the actual recipient address rather than the nexthop, yielding per-recipient concurrency limits rather than per-domain concurrency limits. Per-recipient limits are appropriate when performing final delivery to mailboxes rather than when relaying to a remote server. Congestion occurs in the active queue when one or more destinations drain slower than the corresponding message input rate. Input into the active queue comes both from new mail in the "incoming" queue, and retries of mail in the "deferred" queue. Should the "deferred" queue get really large, retries of old mail can dominate the arrival rate of new mail. Systems with more CPU, faster disks and more network bandwidth can deal with larger deferred queues, but as a rule of thumb the deferred queue scales to somewhere between 100,000 and 1,000,000 messages with good performance unlikely above that "limit". Systems with queues this large should typically stop accepting new mail, or put the backlog "on hold" until the underlying issue is fixed (provided that there is enough capacity to handle just the new mail). When a destination is down for some time, the queue manager will mark it dead, and immediately defer all mail for the destination without trying to assign it to a delivery agent. In this case the messages will quickly leave the active queue and end up in the deferred queue (with Postfix < 2.4, this is done directly by the queue manager, with Postfix >= 2.4 this is done via the "retry" delivery agent). When the destination is instead simply slow, or there is a problem causing an excessive arrival rate the active queue will grow and will become dominated by mail to the congested destination. The only way to reduce congestion is to either reduce the input rate or increase the throughput. Increasing the throughput requires either increasing the concurrency or reducing the latency of deliveries. For high volume sites a key tuning parameter is the number of "smtp" delivery agents allocated to the "smtp" and "relay" transports. High volume sites tend to send to many different destinations, many of which may be down or slow, so a good fraction of the available delivery agents will be blocked waiting for slow sites. Also mail destined across the globe will incur large SMTP command- response latencies, so high message throughput can only be achieved with more concurrent delivery agents. The default "smtp" process limit of 100 is good enough for most sites, and may even need to be lowered for sites with low bandwidth connections (no use increasing concurrency once the network pipe is full). When one finds that the queue is growing on an "idle" system (CPU, disk I/O and network not exhausted) the remaining reason for congestion is insufficient concurrency in the face of a high average latency. If the number of outbound SMTP connections (either ESTABLISHED or SYN_SENT) reaches the process limit, mail is draining slowly and the system and network are not loaded, raise the "smtp" and/or "relay" process limits! When a high volume destination is served by multiple MX hosts with typically low delivery latency, performance can suffer dramatically when one of the MX hosts is unresponsive and SMTP connections to that host timeout. For example, if there are 2 equal weight MX hosts, the SMTP connection timeout is 30 seconds and one of the MX hosts is down, the average SMTP connection will take approximately 15 seconds to complete. With a default per-destination concurrency limit of 20 connections, throughput falls to just over 1 message per second. The best way to avoid bottlenecks when one or more MX hosts is non-responsive is to use connection caching. Connection caching was introduced with Postfix 2.2 and is by default enabled on demand for destinations with a backlog of mail in the active queue. When connection caching is in effect for a particular destination, established connections are re-used to send additional messages, this reduces the number of connections made per message delivery and maintains good throughput even in the face of partial unavailability of the destination's MX hosts. If connection caching is not available (Postfix < 2.2) or does not provide a sufficient latency reduction, especially for the "relay" transport used to forward mail to "your own" domains, consider setting lower than default SMTP connection timeouts (1-5 seconds) and higher than default destination concurrency limits. This will further reduce latency and provide more concurrency to maintain throughput should latency rise. Setting high concurrency limits to domains that are not your own may be viewed as hostile by the receiving system, and steps may be taken to prevent you from monopolizing the destination system's resources. The defensive measures may substantially reduce your throughput or block access entirely. Do not set aggressive concurrency limits to remote domains without coordinating with the administrators of the target domain. If necessary, dedicate and tune custom transports for selected high volume destinations. The "relay" transport is provided for forwarding mail to domains for which your server is a primary or backup MX host. These can make up a substantial fraction of your email traffic. Use the "relay" and not the "smtp" transport to send email to these domains. Using the "relay" transport allocates a separate delivery agent pool to these destinations and allows separate tuning of timeouts and concurrency limits. Another common cause of congestion is unwarranted flushing of the entire deferred queue. The deferred queue holds messages that are likely to fail to be delivered and are also likely to be slow to fail delivery (time out). As a result the most common reaction to a large deferred queue (flush it!) is more than likely counter-productive, and typically makes the congestion worse. Do not flush the deferred queue unless you expect that most of its content has recently become deliverable (e.g. relayhost back up after an outage)! Note that whenever the queue manager is restarted, there may already be messages in the active queue directory, but the "real" active queue in memory is empty. In order to recover the in-memory state, the queue manager moves all the active queue messages back into the incoming queue, and then uses its normal incoming queue scan to refill the active queue. The process of moving all the messages back and forth, redoing transport table (trivial-rewrite(8) resolve service) lookups, and re-importing the messages back into memory is expensive. At all costs, avoid frequent restarts of the queue manager (e.g. via frequent execution of "postfix reload"). TThhee ""ddeeffeerrrreedd"" qquueeuuee When all the deliverable recipients for a message are delivered, and for some recipients delivery failed for a transient reason (it might succeed later), the message is placed in the deferred queue. The queue manager scans the deferred queue periodically. The scan interval is controlled by the queue_run_delay parameter. While a deferred queue scan is in progress, if an incoming queue scan is also in progress (ideally these are brief since the incoming queue should be short), the queue manager alternates between looking for messages in the "incoming" queue and in the "deferred" queue. This "round-robin" strategy prevents starvation of either the incoming or the deferred queues. Each deferred queue scan only brings a fraction of the deferred queue back into the active queue for a retry. This is because each message in the deferred queue is assigned a "cool-off" time when it is deferred. This is done by time- warping the modification time of the queue file into the future. The queue file is not eligible for a retry if its modification time is not yet reached. The "cool-off" time is at least $minimal_backoff_time and at most $maximal_backoff_time. The next retry time is set by doubling the message's age in the queue, and adjusting up or down to lie within the limits. This means that young messages are initially retried more often than old messages. If a high volume site routinely has large deferred queues, it may be useful to adjust the queue_run_delay, minimal_backoff_time and maximal_backoff_time to provide short enough delays on first failure (Postfix >= 2.4 has a sensibly low minimal backoff time by default), with perhaps longer delays after multiple failures, to reduce the retransmission rate of old messages and thereby reduce the quantity of previously deferred mail in the active queue. If you want a really low minimal_backoff_time, you may also want to lower queue_run_delay, but understand that more frequent scans will increase the demand for disk I/O. One common cause of large deferred queues is failure to validate recipients at the SMTP input stage. Since spammers routinely launch dictionary attacks from unrepliable sender addresses, the bounces for invalid recipient addresses clog the deferred queue (and at high volumes proportionally clog the active queue). Recipient validation is strongly recommended through use of the local_recipient_maps and relay_recipient_maps parameters. Even when bounces drain quickly they inundate innocent victims of forgery with unwanted email. To avoid this, do not accept mail for invalid recipients. When a host with lots of deferred mail is down for some time, it is possible for the entire deferred queue to reach its retry time simultaneously. This can lead to a very full active queue once the host comes back up. The phenomenon can repeat approximately every maximal_backoff_time seconds if the messages are again deferred after a brief burst of congestion. Perhaps, a future Postfix release will add a random offset to the retry time (or use a combination of strategies) to reduce the odds of repeated complete deferred queue flushes. CCrreeddiittss The qshape(1) program was developed by Victor Duchovni of Morgan Stanley, who also wrote the initial version of this document. README_FILES/STRESS_README000066600000047176150501202770010430 0ustar00PPoossttffiixx SSttrreessss--DDeeppeennddeenntt CCoonnffiigguurraattiioonn ------------------------------------------------------------------------------- OOvveerrvviieeww This document describes the symptoms of Postfix SMTP server overload. It presents permanent main.cf changes to avoid overload during normal operation, and temporary main.cf changes to cope with an unexpected burst of mail. This document makes specific suggestions for Postfix 2.5 and later which support stress-adaptive behavior, and for earlier Postfix versions that don't. Topics covered in this document: * Symptoms of Postfix SMTP server overload * Service more SMTP clients at the same time * Spend less time per SMTP client * Disconnect suspicious SMTP clients * Temporary measures for older Postfix releases * Automatic stress-adaptive behavior * Detecting support for stress-adaptive behavior * Forcing stress-adaptive behavior on or off * Other measures to off-load zombies * Credits SSyymmppttoommss ooff PPoossttffiixx SSMMTTPP sseerrvveerr oovveerrllooaadd Under normal conditions, the Postfix SMTP server responds immediately when an SMTP client connects to it; the time to deliver mail is noticeable only with large messages. Performance degrades dramatically when the number of SMTP clients exceeds the number of Postfix SMTP server processes. When an SMTP client connects while all Postfix SMTP server processes are busy, the client must wait until a server process becomes available. SMTP server overload may be caused by a surge of legitimate mail (example: a DNS registrar opens a new zone for registrations), by mistake (mail explosion caused by a forwarding loop) or by malice (worm outbreak, botnet, or other illegitimate activity). Symptoms of Postfix SMTP server overload are: * Remote SMTP clients experience a long delay before Postfix sends the "220 hostname.example.com ESMTP Postfix" greeting. o NOTE: Broken DNS configurations can also cause lengthy delays before Postfix sends "220 hostname.example.com ...". These delays also exist when Postfix is NOT overloaded. o NOTE: To avoid "overload" delays for end-user mail clients, enable the "submission" service entry in master.cf (present since Postfix 2.1), and tell users to connect to this instead of the public SMTP service. * The Postfix SMTP server logs an increased number of "lost connection after CONNECT" events. This happens because remote SMTP clients disconnect before Postfix answers the connection. o NOTE: A portscan for open SMTP ports can also result in "lost connection ..." logfile messages. * Postfix 2.3 and later logs a warning that all server ports are busy: Oct 3 20:39:27 spike postfix/master[28905]: warning: service "smtp" (25) has reached its process limit "30": new clients may experience noticeable delays Oct 3 20:39:27 spike postfix/master[28905]: warning: to avoid this condition, increase the process count in master.cf or reduce the service time per client Legitimate mail that doesn't get through during an episode of Postfix SMTP server overload is not necessarily lost. It should still arrive once the situation returns to normal, as long as the overload condition is temporary. SSeerrvviiccee mmoorree SSMMTTPP cclliieennttss aatt tthhee ssaammee ttiimmee One measure to avoid the "all server processes busy" condition is to service more SMTP clients simultaneously. For this you need to increase the number of Postfix SMTP server processes. This will improve the responsiveness for remote SMTP clients, as long as the server machine has enough hardware and software resources to run the additional processes, and as long as the file system can keep up with the additional load. * You increase the number of SMTP server processes either by increasing the default_process_limit in main.cf (line 3 below), or by increasing the SMTP server's "maxproc" field in master.cf (line 10 below). Either way, you need to issue a "postfix reload" command to make the change effective. * Process limits above 1000 require Postfix version 2.4 or later, and an operating system that supports kernel-based event filters (BSD kqueue(2), Linux epoll(4), or Solaris /dev/poll). * More processes use more memory. You can reduce the Postfix memory footprint by using cdb: lookup tables instead of Berkeley DB's hash: or btree: tables. 1 /etc/postfix/main.cf: 2 # Raise the global process limit, 100 since Postfix 2.0. 3 default_process_limit = 200 4 5 /etc/postfix/master.cf: 6 # ============================================================= 7 # service type private unpriv chroot wakeup maxproc command 8 # ============================================================= 9 # Raise the SMTP service process limit only. 10 smtp inet n - n - 200 smtpd * NOTE: older versions of the SMTPD_POLICY_README document contain a mistake: they configure a fixed number of policy daemon processes. When you raise the SMTP server's "maxproc" field in master.cf, SMTP server processes will report problems when connecting to policy server processes, because there aren't enough of them. Examples of errors are "connection refused" or "operation timed out". To fix, edit master.cf and specify a zero "maxproc" field in all policy server entries; see line 6 in the example below. Issue a "postfix reload" command to make the change effective. 1 /etc/postfix/master.cf: 2 # ============================================================= 3 # service type private unpriv chroot wakeup maxproc command 4 # ============================================================= 5 # Disable the policy service process limit. 6 policy unix - n n - 0 spawn 7 user=nobody argv=/some/where/policy-server SSppeenndd lleessss ttiimmee ppeerr SSMMTTPP cclliieenntt When increasing the number of SMTP server processes is not practical, you can improve Postfix server responsiveness by eliminating delays. When Postfix spends less time per SMTP session, the same number of SMTP server processes can service more clients in a given amount of time. * Eliminate non-functional RBL lookups (blocklists that are no longer in operation). These lookups can degrade performance. Postfix logs a warning when an RBL server does not respond. * Eliminate redundant RBL lookups (people often use multiple Spamhaus RBLs that include each other). To find out whether RBLs include other RBLs, look up the websites that document the RBL's policies. * Eliminate header_checks and body_checks, and keep just a few emergency patterns to block the latest worm explosion or backscatter mail. See BACKSCATTER_README for examples of the latter. * Group your header_checks and body_checks patterns to avoid unnecessary pattern matching operations: 1 /etc/postfix/header_checks: 2 if /^Subject:/ 3 /^Subject: virus found in mail from you/ reject 4 /^Subject: ..other../ reject 5 endif 6 7 if /^Received:/ 8 /^Received: from (postfix\.org) / reject forged client name in received header: $1 9 /^Received: from ..other../ reject .... 10 endif DDiissccoonnnneecctt ssuussppiicciioouuss SSMMTTPP cclliieennttss Under conditions of overload you can improve Postfix SMTP server responsiveness by hanging up on suspicious clients, so that other clients get a chance to talk to Postfix. * Use "521" SMTP reply codes (Postfix 2.6 and later) or "421" (Postfix 2.3- 2.5) to hang up on clients that that match botnet-related RBLs (see next bullet) or that match selected non-RBL restrictions such as SMTP access maps. The Postfix SMTP server will reject mail and disconnect without waiting for the remote SMTP client to send a QUIT command. * To hang up connections from blacklisted zombies, you can set specific Postfix SMTP server reject codes for specific RBLs, and for individual responses from specific RBLs. We'll use zen.spamhaus.org as an example; by the time you read this document, details may have changed. Right now, their documents say that a response of 127.0.0.10 or 127.0.0.11 indicates a dynamic client IP address, which means that the machine is probably running a bot of some kind. To give a 521 response instead of the default 554 response, use something like: 1 /etc/postfix/main.cf: 2 smtpd_client_restrictions = 3 permit_mynetworks 4 reject_rbl_client zen.spamhaus.org=127.0.0.10 5 reject_rbl_client zen.spamhaus.org=127.0.0.11 6 reject_rbl_client zen.spamhaus.org 7 8 rbl_reply_maps = hash:/etc/postfix/rbl_reply_maps 9 10 /etc/postfix/rbl_reply_maps: 11 # With Postfix 2.3-2.5 use "421" to hang up connections. 12 zen.spamhaus.org=127.0.0.10 521 4.7.1 Service unavailable; 13 $rbl_class [$rbl_what] blocked using 14 $rbl_domain${rbl_reason?; $rbl_reason} 15 16 zen.spamhaus.org=127.0.0.11 521 4.7.1 Service unavailable; 17 $rbl_class [$rbl_what] blocked using 18 $rbl_domain${rbl_reason?; $rbl_reason} Although the above example shows three RBL lookups (lines 4-6), Postfix will only do a single DNS query, so it does not affect the performance. * With Postfix 2.3-2.5, use reply code 421 (521 will not cause Postfix to disconnect). The down-side of replying with 421 is that it works only for zombies and other malware. If the client is running a real MTA, then it may connect again several times until the mail expires in its queue. When this is a problem, stick with the default 554 reply, and use "smtpd_hard_error_limit = 1" as described below. * You can automatically turn on the above overload measure with Postfix 2.5 and later, or with earlier releases that contain the stress-adaptive behavior source code patch from the mirrors listed at http:// www.postfix.org/download.html. Simply replace line above 8 with: 8 rbl_reply_maps = ${stress?hash:/etc/postfix/rbl_reply_maps} More information about automatic stress-adaptive behavior is in section "Automatic stress-adaptive behavior". TTeemmppoorraarryy mmeeaassuurreess ffoorr oollddeerr PPoossttffiixx rreelleeaasseess See the next section, "Automatic stress-adaptive behavior", if you are running Postfix version 2.5 or later, or if you have applied the source code patch for stress-adaptive behavior from the mirrors listed at http://www.postfix.org/ download.html. The following measures can be applied temporarily during overload. They still allow mmoosstt legitimate clients to connect and send mail, but may affect some legitimate clients. * Reduce smtpd_timeout (default: 300s). Experience on the postfix-users list from a variety of sysadmins shows that reducing the "normal" smtpd_timeout to 60s is unlikely to affect legitimate clients. However, it is unlikely to become the Postfix default because it's not RFC compliant. Setting smtpd_timeout to 10s (line 2 below) or even 5s under stress will still allow mmoosstt legitimate clients to connect and send mail, but may delay mail from some clients. No mail should be lost, as long as this measure is used only temporarily. * Reduce smtpd_hard_error_limit (default: 20). Setting this to 1 under stress (line 3 below) helps by disconnecting clients after a single error, giving other clients a chance to connect. However, this may cause significant delays with legitimate mail, such as a mailing list that contains a few no- longer-active user names that didn't bother to unsubscribe. No mail should be lost, as long as this measure is used only temporarily. * Use an smtpd_junk_command_limit of 1 instead of the default 100. This prevents clients from keeping idle connections open by repeatedly sending NOOP or RSET commands. 1 /etc/postfix/main.cf: 2 smtpd_timeout = 10 3 smtpd_hard_error_limit = 1 4 smtpd_junk_command_limit = 1 With these measures, no mail should be lost, as long as these measures are used only temporarily. The next section of this document introduces a way to automate this process. AAuuttoommaattiicc ssttrreessss--aaddaappttiivvee bbeehhaavviioorr Postfix version 2.5 introduces automatic stress-adaptive behavior. This is also available as a source code patch for Postfix versions 2.4 and 2.3 from the mirrors listed at http://www.postfix.org/download.html. It works as follows. When a "public" network service such as the SMTP server runs into an "all server ports are busy" condition, the Postfix master(8) daemon logs a warning, restarts the service (without interrupting existing network sessions), and runs the service with "-o stress=yes" on the server process command line: 80821 ?? S 0:00.24 smtpd -n smtp -t inet -u -c -o stress=yes Normally, the Postfix master(8) daemon runs such a service with "-o stress=" on the command line (i.e. with an empty parameter value): 83326 ?? S 0:00.28 smtpd -n smtp -t inet -u -c -o stress= Services that have local access only never have "-o stress" parameters on the command line. This includes services internal to Postfix such as the queue manager, and services that listen on a loopback interface only, such as after- filter SMTP services. The "stress" parameter value is the key to making main.cf parameter settings stress adaptive. The following settings are the default with Postfix 2.6 and later. With earlier Postfix versions that have stress-adaptive support, append the lines below to the main.cf file and issue a "postfix reload" command: 1 smtpd_timeout = ${stress?10}${stress:300}s 2 smtpd_hard_error_limit = ${stress?1}${stress:20} 3 smtpd_junk_command_limit = ${stress?1}${stress:100} Translation: * Line 1: under conditions of stress, use an smtpd_timeout value of 10 seconds instead of the default 300 seconds. Experience on the postfix-users list from a variety of sysadmins shows that reducing the "normal" smtpd_timeout to 60s is unlikely to affect legitimate clients. However, it is unlikely to become the Postfix default because it's not RFC compliant. Setting smtpd_timeout to 10s (line 2 below) or even 5s under stress will still allow most legitimate clients to connect and send mail, but may delay mail from some clients. No mail should be lost, as long as this measure is used only temporarily. * Line 2: under conditions of stress, use an smtpd_hard_error_limit of 1 instead of the default 20. This helps by disconnecting clients after a single error, giving other clients a chance to connect. However, this may cause significant delays with legitimate mail, such as a mailing list that contains a few no-longer-active user names that didn't bother to unsubscribe. No mail should be lost, as long as this measure is used only temporarily. * Line 3: under conditions of stress, use an smtpd_junk_command_limit of 1 instead of the default 100. This prevents clients from keeping idle connections open by repeatedly sending NOOP or RSET commands. The syntax of ${name?value} and ${name:value} is explained at the beginning of the postconf(5) manual page. NOTE: Please keep in mind that the stress-adaptive feature is a fairly desperate measure to keep ssoommee legitimate mail flowing under overload conditions. If a site is reaching the SMTP server process limit when there isn't an attack or bot flood occurring, then either the process limit needs to be raised or more hardware needs to be added. DDeetteeccttiinngg ssuuppppoorrtt ffoorr ssttrreessss--aaddaappttiivvee bbeehhaavviioorr To find out if your Postfix installation supports stress-adaptive behavior, use the "ps" command, and look for the smtpd processes. Postfix has stress-adaptive support when you see "-o stress=" or "-o stress=yes" command-line options. Remember that Postfix never enables stress-adaptive behavior on servers that listen on local addresses only. The following example is for FreeBSD or Linux. On Solaris, HP-UX and other System-V flavors, use "ps -ef" instead of "ps ax". $ ps ax|grep smtpd 83326 ?? S 0:00.28 smtpd -n smtp -t inet -u -c -o stress= 84345 ?? Ss 0:00.11 /usr/bin/perl /usr/libexec/postfix/smtpd- policy.pl You can't use postconf(1) to detect stress-adaptive support. The postconf(1) command ignores the existence of the stress parameter in main.cf, because the parameter has no effect there. Command-line "-o parameter" settings always take precedence over main.cf parameter settings. If you configure stress-adaptive behavior in main.cf when it isn't supported, nothing bad will happen. The processes will run as if the stress parameter always has an empty value. FFoorrcciinngg ssttrreessss--aaddaappttiivvee bbeehhaavviioorr oonn oorr ooffff You can manually force stress-adaptive behavior on, by adding a "-o stress=yes" command-line option in master.cf. This can be useful for testing overrides on the SMTP service. Issue "postfix reload" to make the change effective. Note: setting the stress parameter in main.cf has no effect for services that accept remote connections. 1 /etc/postfix/master.cf: 2 # ============================================================= 3 # service type private unpriv chroot wakeup maxproc command 4 # ============================================================= 5 # 6 smtp inet n - n - - smtpd 7 -o stress=yes 8 -o . . . To permanently force stress-adaptive behavior off with a specific service, specify "-o stress=" on its master.cf command line. This may be desirable for the "submission" service. Issue "postfix reload" to make the change effective. Note: setting the stress parameter in main.cf has no effect for services that accept remote connections. 1 /etc/postfix/master.cf: 2 # ============================================================= 3 # service type private unpriv chroot wakeup maxproc command 4 # ============================================================= 5 # 6 submission inet n - n - - smtpd 7 -o stress= 8 -o . . . OOtthheerr mmeeaassuurreess ttoo ooffff--llooaadd zzoommbbiieess OpenBSD spamd implements a daemon that handles all connections from "new" clients. Only well-behaved mail clients are allowed to talk to the mail server. Other clients are tarpitted, and will never get a chance to affect mail server performance. At some point in the future, Postfix may come with a simple front-end daemon that does basic greylisting and pipelining detection to keep zombies and other ratware away from Postfix itself. This would use the "pass" service type which has been available in stable Postfix releases since Postfix 2.5. CCrreeddiittss * Thanks to the postfix-users mailing list members for sharing early experiences with the stress-adaptive feature. * The RBL example and several other paragraphs of text were adapted from postfix-users postings by Noel Jones. * Wietse implemented stress-adaptive behavior as the smallest possible patch while he should be working on other things. README_FILES/ADDRESS_CLASS_README000066600000022516150501202770011406 0ustar00PPoossttffiixx AAddddrreessss CCllaasssseess ------------------------------------------------------------------------------- IInnttrroodduuccttiioonn Postfix version 2.0 introduces the concept of address classes. This is a way of grouping recipient addresses by their delivery method. The idea comes from discussions with Victor Duchovni. Although address classes introduced a few incompatibilities they also made it possible to improve the handling of hosted domains and of unknown recipients. This document provides information on the following topics: * What are address classes good for? * What address classes does Postfix implement? * Improvements compared to Postfix 1.1 * Incompatibilities with Postfix 1.1 WWhhaatt aarree aaddddrreessss ccllaasssseess ggoooodd ffoorr?? Why should you care about address classes? This is how Postfix decides what mail to accept, and how to deliver it. In other words, address classes are very important for the operation of Postfix. An address class is defined by three items. * The list of domains that are a member of the class: for example, all local domains, or all relay domains. * The default delivery transport. For example, the local, virtual or relay delivery transport (delivery transports are defined in master.cf). This helps to keep Postfix configurations simple, by avoiding the need for explicit routing information in transport maps. * The list of valid recipient addresses for that address class. The Postfix SMTP server rejects invalid recipients with "User unknown in table". This helps to keep the Postfix queue free of undeliverable MAILER-DAEMON messages. WWhhaatt aaddddrreessss ccllaasssseess ddooeess PPoossttffiixx iimmpplleemmeenntt?? Initially the list of address classes is hard coded, but this is meant to become extensible. The summary below describes the main purpose of each class, and what the relevant configuration parameters are. The local domain class. * Purpose: final delivery for traditional UNIX system accounts and traditional Sendmail-style aliases. This is typically used for the canonical domains of the machine. For a discussion of the difference between canonical domains, hosted domains and other domains, see the VIRTUAL_README file. * Domain names are listed with the mydestination parameter. This domain class also includes mail for user@[ipaddress] when the IP address is listed with the inet_interfaces or proxy_interfaces parameters. * Valid recipient addresses are listed with the local_recipient_maps parameter, as described in LOCAL_RECIPIENT_README. The Postfix SMTP server rejects invalid recipients with "User unknown in local recipient table". If the local_recipient_maps parameter value is empty, then the Postfix SMTP server accepts any address in the local domain class. * The mail delivery transport is specified with the local_transport parameter. The default value is llooccaall::$$mmyyhhoossttnnaammee for delivery with the local(8) delivery agent. The virtual alias domain class. * Purpose: hosted domains where each recipient address is aliased to a local UNIX system account or to a remote address. A virtual alias example is given in the VIRTUAL_README file. * Domain names are listed in virtual_alias_domains. The default value is $virtual_alias_maps for Postfix 1.1 compatibility. * Valid recipient addresses are listed with the virtual_alias_maps parameter. The Postfix SMTP server rejects invalid recipients with "User unknown in virtual alias table". The default value is $virtual_maps for Postfix 1.1 compatibility. * There is no mail delivery transport parameter. Every address must be aliased to some other address. The virtual mailbox domain class. * Purpose: final delivery for hosted domains where each recipient address can have its own mailbox, and where users do not need to have a UNIX system account. A virtual mailbox example is given in the VIRTUAL_README file. * Domain names are listed with the virtual_mailbox_domains parameter. The default value is $virtual_mailbox_maps for Postfix 1.1 compatibility. * Valid recipient addresses are listed with the virtual_mailbox_maps parameter. The Postfix SMTP server rejects invalid recipients with "User unknown in virtual mailbox table". If this parameter value is empty, the Postfix SMTP server accepts all recipients for domains listed in $virtual_mailbox_domains. * The mail delivery transport is specified with the virtual_transport parameter. The default value is vviirrttuuaall for delivery with the virtual(8) delivery agent. The relay domain class. * Purpose: mail forwarding to remote destinations that list your system as primary or backup MX host. For a discussion of the basic configuration details, see the BASIC_CONFIGURATION_README document. For a discussion of the difference between canonical domains, hosted domains and other domains, see the VIRTUAL_README file. * Domain names are listed with the relay_domains parameter. * Valid recipient addresses are listed with the relay_recipient_maps parameter. The Postfix SMTP server rejects invalid recipients with "User unknown in relay recipient table". If this parameter value is empty, the Postfix SMTP server accepts all recipients for domains listed with the relay_domains parameter. * The mail delivery transport is specified with the relay_transport parameter. The default value is rreellaayy which is a clone of the smtp(8) delivery agent. The default domain class. * Purpose: mail forwarding to the Internet on behalf of authorized clients. For a discussion of the basic configuration details, see the BASIC_CONFIGURATION_README file. For a discussion of the difference between canonical domains, hosted domains and other domains, see the VIRTUAL_README file. * This class has no destination domain table. * This class has no valid recipient address table. * The mail delivery transport is specified with the default_transport parameter. The default value is ssmmttpp for delivery with the smtp(8) delivery agent. IImmpprroovveemmeennttss ccoommppaarreedd ttoo PPoossttffiixx 11..11 Postfix 2.0 address classes made the following improvements possible over earlier Postfix versions: * You no longer need to specify all the virtual(8) mailbox domains in the Postfix transport map. The virtual(8) delivery agent has become a first- class citizen just like local(8) or smtp(8). * On mail gateway systems, address classes provide separation of inbound mail relay traffic ($relay_transport) from outbound traffic ($default_transport). This eliminates a problem where inbound mail deliveries could become resource starved in the presence of a high volume of outbound mail. * The SMTP server rejects unknown recipients in a more consistent manner than was possible with Postfix version 1. This is needed to keep undeliverable mail (and bounced undeliverable mail) out of the mail queue. This is controlled by the smtpd_reject_unlisted_recipient configuration parameter. * As of Postfix version 2.1, the SMTP server also rejects unknown sender addresses (i.e. addresses that it would reject as unknown recipient addresses). Sender "egress filtering" can help to slow down an email worm explosion. This is controlled by the smtpd_reject_unlisted_sender configuration parameter. IInnccoommppaattiibbiilliittiieess wwiitthh PPoossttffiixx 11..11 Postfix 2.0 address classes introduce a few incompatible changes in documented behavior. In order to ease the transitions, new parameters have default values that are backwards compatible. * The virtual_maps parameter is replaced by virtual_alias_maps (for address lookups) and by virtual_alias_domains (for the names of what were formerly called "Postfix-style virtual domains"). For backwards compatibility with Postfix version 1.1, the new virtual_alias_maps parameter defaults to $virtual_maps, and the new virtual_alias_domains parameter defaults to $virtual_alias_maps. * The virtual_mailbox_maps parameter now has a companion parameter called virtual_mailbox_domains (for the names of domains served by the virtual delivery agent). The virtual_mailbox_maps parameter is now used for address lookups only. For backwards compatibility with Postfix version 1.1, the new virtual_mailbox_domains parameter defaults to $virtual_mailbox_maps. * Introduction of the relay_recipient_maps parameter. The Postfix SMTP server can use this to block mail for relay recipients that don't exist. This list is empty by default, which means accept any recipient. * The local_recipient_maps feature is now turned on by default. The Postfix SMTP server uses this to reject mail for unknown local recipients. See the LOCAL_RECIPIENT_README file hints and tips. * Introduction of the relay delivery transport in master.cf. This helps to avoid mail delivery scheduling problems on inbound mail relays when there is a lot of outbound mail, but may require that you update your "defer_transports" setting. README_FILES/CDB_README000066600000005303150501202770007757 0ustar00PPoossttffiixx CCDDBB HHoowwttoo ------------------------------------------------------------------------------- IInnttrroodduuccttiioonn CDB (Constant DataBase) is an indexed file format designed by Daniel Bernstein. CDB is optimized exclusively for read access and guarantees that each record will be read in at most two disk accesses. This is achieved by forgoing support for incremental updates: no single-record inserts or deletes are supported. CDB databases can be modified only by rebuilding them completely from scratch, hence the "constant" qualifier in the name. Postfix CDB databases are specified as "cdb:name", where name specifies the CDB file name without the ".cdb" suffix (another suffix, ".tmp", is used temporarily while a CDB file is under construction). CDB databases are maintained with the postmap(1) or postalias(1) command. The DATABASE_README document has general information about Postfix databases. CDB support is available with Postfix 2.2 and later releases. This document describes how to build Postfix with CDB support. BBuuiillddiinngg PPoossttffiixx wwiitthh CCDDBB ssuuppppoorrtt These instructions assume that you build Postfix from source code as described in the INSTALL document. Some modification may be required if you build Postfix from a vendor-specific source package. Postfix is compatible with two CDB implementations: * The original cdb library from Daniel Bernstein, available from http:// cr.yp.to/cdb.html, and * tinycdb (version 0.5 and later) from Michael Tokarev, available from http:/ /www.corpit.ru/mjt/tinycdb.html. Tinycdb is preferred, since it is a bit faster, has additional useful functionality and is much simpler to use. To build Postfix after you have installed tinycdb, use something like: % make tidy % CDB=../../../tinycdb-0.5 % make -f Makefile.init makefiles "CCARGS=-DHAS_CDB -I$CDB" \ "AUXLIBS=$CDB/libcdb.a" % make Alternatively, for the D.J.B. version of CDB: % make tidy % CDB=../../../cdb-0.75 % make -f Makefile.init makefiles "CCARGS=-DHAS_CDB -I$CDB" \ "AUXLIBS=$CDB/cdb.a $CDB/alloc.a $CDB/buffer.a $CDB/unix.a $CDB/byte.a" % make After Postfix has been built with cdb support, you can use "cdb" tables wherever you can use read-only "hash", "btree" or "dbm" tables. However, the "ppoossttmmaapp --ii" (incremental record insertion) and "ppoossttmmaapp --dd" (incremental record deletion) command-line options are not available. For the same reason the "cdb" map type cannot be used to store the persistent address verification cache for the verify(8) service, or to store TLS session information for the tlsmgr(8) service. README_FILES/XFORWARD_README000066600000020443150501202770010625 0ustar00PPoossttffiixx XXFFOORRWWAARRDD HHoowwttoo ------------------------------------------------------------------------------- PPuurrppoossee ooff tthhee XXFFOORRWWAARRDD eexxtteennssiioonn ttoo SSMMTTPP When an SMTP server announces support for the XFORWARD command, an SMTP client may send information that overrides one or more client-related logging attributes. The XFORWARD command targets the following problem: * Logging after SMTP-based content filter. With the deployment of Internet- >MTA1->filter->MTA2 style content filter applications, the logging of client and message identifying information changes when MTA1 gives the mail to the content filter. To simplify the interpretation of MTA2 logging, it would help if MTA1 could forward remote client and/or message identifying information through the content filter to MTA2, so that the information could be logged as part of mail handling transactions. This extension is implemented as a separate EMSTP command, and can be used to transmit client or message attributes incrementally. It is not implemented by passing additional parameters via the MAIL FROM command, because doing so would require extending the MAIL FROM command length limit by another 600 or more characters beyond the space that is already needed to support other extensions such as AUTH and DSN. XXFFOORRWWAARRDD CCoommmmaanndd ssyynnttaaxx An example of a client-server conversation is given at the end of this document. In SMTP server EHLO replies, the keyword associated with this extension is XFORWARD. The keyword is followed by the names of the attributes that the XFORWARD implementation supports. After receiving the server's announcement for XFORWARD support, the client may send XFORWARD requests at any time except in the middle of a mail delivery transaction (i.e. between MAIL and RSET or DOT). The command may be pipelined when the server supports ESMTP command pipelining. The syntax of XFORWARD requests is described below. Upper case and quoted strings specify terminals, lowercase strings specify meta terminals, and SP is whitespace. Although command and attribute names are shown in upper case, they are in fact case insensitive. xforward-command = XFORWARD 1*( SP attribute-name"="attribute-value ) attribute-name = ( NAME | ADDR | PORT | PROTO | HELO | SOURCE ) attribute-value = xtext * Attribute values are xtext encoded as per RFC 1891. * The NAME attribute specifies the up-stream hostname, or [UNAVAILABLE] when the information is unavailable. The hostname may be a non-DNS hostname. * The ADDR attribute specifies the up-stream network address: a numerical IPv4 network address, an IPv6 address prefixed with IPV6:, or [UNAVAILABLE] when the address information is unavailable. Address information is not enclosed with []. * The PORT attribute specifies an up-stream client TCP port number in decimal, or [UNAVAILABLE] when the information is unavailable. * The PROTO attribute specifies the mail protocol for receiving mail from the up-stream host. This may be an SMTP or non-SMTP protocol name of up to 64 characters, or [UNAVAILABLE] when the information is unavailable. * The HELO attribute specifies the hostname that the up-stream host announced itself with (not necessarily via the SMTP HELO command), or [UNAVAILABLE] when the information is unavailable. The hostname may be a non-DNS hostname. * The SOURCE attribute specifies LOCAL when the message was received from a source that is local with respect to the up-stream host (for example, the message originated from the up-stream host itself), REMOTE for all other mail, or [UNAVAILABLE] when the information is unavailable. The down-stream MTA may decide to enable features such as header munging or address qualification with mail from local sources but not other sources. Note 1: an attribute-value element must not be longer than 255 characters (specific attributes may impose shorter lengths). After xtext decoding, attribute values must not contain control characters, non-ASCII characters, whitespace, or other characters that are special in message headers. Note 2: DNS hostnames can be up to 255 characters long. The XFORWARD client implementation must not send XFORWARD commands that exceed the 512 character limit for SMTP commands. Note 3: [UNAVAILABLE] may be specified in upper case, lower case or mixed case. Note 4: Postfix implementations prior to version 2.3 do not xtext encode attribute values. Servers that wish to interoperate with these older implementations should be prepared to receive unencoded information. XXFFOORRWWAARRDD SSeerrvveerr ooppeerraattiioonn The server maintains a set of XFORWARD attributes with forwarded information, in addition the current SMTP session attributes. Normally, all XFORWARD attributes are in the undefined state, and the server uses the current SMTP session attributes for logging purposes. Upon receipt of an initial XFORWARD command, the SMTP server initializes all XFORWARD attributes to [UNAVAILABLE]. With each valid XFORWARD command, the server updates XFORWARD attributes with the specified values. The server must not mix client attributes from XFORWARD with client attributes from the current SMTP session. At the end of each MAIL FROM transaction (i.e. RSET or DOT), the server resets all XFORWARD attributes to the undefined state, and is ready to receive another initial XFORWARD command. XXFFOORRWWAARRDD SSeerrvveerr rreeppllyy ccooddeess _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |CCooddee|MMeeaanniinngg | |_ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |250 |success | |_ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |421 |unable to proceed, disconnecting| |_ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |501 |bad command parameter syntax | |_ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |503 |mail transaction in progress | |_ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |550 |insufficient authorization | |_ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | XXFFOORRWWAARRDD EExxaammppllee In the following example, information sent by the client is shown in bold font. 220 server.example.com ESMTP Postfix EEHHLLOO cclliieenntt..eexxaammppllee..ccoomm 250-server.example.com 250-PIPELINING 250-SIZE 10240000 250-VRFY 250-ETRN 250-XFORWARD NAME ADDR PROTO HELO 250 8BITMIME XXFFOORRWWAARRDD NNAAMMEE==ssppiikkee..ppoorrccuuppiinnee..oorrgg AADDDDRR==116688..110000..118899..22 PPRROOTTOO==EESSMMTTPP 250 Ok XXFFOORRWWAARRDD HHEELLOO==ssppiikkee..ppoorrccuuppiinnee..oorrgg 250 Ok MMAAIILL FFRROOMM::<> 250 Ok RRCCPPTT TTOO::<> 250 Ok DDAATTAA 354 End data with . .. .. ..mmeessssaaggee ccoonntteenntt.. .. .. .. 250 Ok: queued as 3CF6B2AAE8 QQUUIITT 221 Bye SSeeccuurriittyy The XFORWARD command changes audit trails. Use of this command must be restricted to authorized clients. SSMMTTPP ccoonnnneeccttiioonn ccaacchhiinngg SMTP connection caching makes it possible to deliver multiple messages within the same SMTP session. The XFORWARD attributes are reset after the MAIL FROM transaction completes (after RSET or DOT), so there is no risk of information leakage. RReeffeerreenncceess Moore, K, "SMTP Service Extension for Delivery Status Notifications", RFC 1891, January 1996. README_FILES/INSTALL000066600000101337150501202770007464 0ustar00PPoossttffiixx IInnssttaallllaattiioonn FFrroomm SSoouurrccee CCooddee ------------------------------------------------------------------------------- 11 -- PPuurrppoossee ooff tthhiiss ddooccuummeenntt If you are using a pre-compiled version of Postfix, you should start with BASIC_CONFIGURATION_README and the general documentation referenced by it. INSTALL is only a bootstrap document to get Postfix up and running from scratch with the minimal number of steps; it should not be considered part of the general documentation. This document describes how to build, install and configure a Postfix system so that it can do one of the following: * Send mail only, without changing an existing Sendmail installation. * Send and receive mail via a virtual host interface, still without any change to an existing Sendmail installation. * Run Postfix instead of Sendmail. Topics covered in this document: 1. Purpose of this document 2. Typographical conventions 3. Documentation 4. Building on a supported system 5. Porting Postfix to an unsupported system 6. Installing the software after successful compilation 7. Configuring Postfix to send mail only 8. Configuring Postfix to send and receive mail via virtual interface 9. Running Postfix instead of Sendmail 10. Mandatory configuration file edits 11. To chroot or not to chroot 12. Care and feeding of the Postfix system 22 -- TTyyppooggrraapphhiiccaall ccoonnvveennttiioonnss In the instructions below, a command written as # command should be executed as the superuser. A command written as % command should be executed as an unprivileged user. 33 -- DDooccuummeennttaattiioonn Documentation is available as README files (start with the file README_FILES/ AAAREADME), as HTML web pages (point your browser to "html/index.html") and as UNIX-style manual pages. You should view the README files with a pager such as more(1) or less(1), because the files use backspace characters in order to produce bboolldd font. To print a README file without backspace characters, use the col(1) command. For example: % col -bx directly (which is not allowed) and overriding the __FD_SETSIZE macro. Beware, undocumented interfaces can change at any time and without warning. But wait, there is more: none of this will work unless the operating system is configured to handle thousands of connections. See the TUNING_README guide for examples of how to increase the number of open sockets or files. 44..66 -- CCoommppiilliinngg PPoossttffiixx,, aatt llaasstt If the command % make is successful, then you can proceed to install Postfix (section 6). If the command produces compiler error messages, it may be time to search the web or to ask the postfix-users@postfix.org mailing list, but be sure to search the mailing list archives first. Some mailing list archives are linked from http://www.postfix.org/. 55 -- PPoorrttiinngg PPoossttffiixx ttoo aann uunnssuuppppoorrtteedd ssyysstteemm Each system type that Postfix knows is identified by a unique name. Examples: SUNOS5, FREEBSD4, and so on. When porting Postfix to a new system, the first step is to choose a SYSTEMTYPE name for the new system. You must use a name that includes at least the major version of the operating system (such as SUNOS4 or LINUX2), so that different releases of the same system can be supported without confusion. Add a case statement to the "makedefs" shell script in the source code top- level directory that recognizes the new system reliably, and that emits the right system-specific information. Be sure to make the code robust against user PATH settings; if the system offers multiple UNIX flavors (e.g. BSD and SYSV) be sure to build for the native flavor, instead of the emulated one. Add an "#ifdef SYSTEMTYPE" section to the central util/sys_defs.h include file. You may have to invent new feature macro names. Please choose sensible feature macro names such as HAS_DBM or FIONREAD_IN_SYS_FILIO_H. I strongly recommend against using "#ifdef SYSTEMTYPE" in individual source files. While this may look like the quickest solution, it will create a mess when newer versions of the same SYSTEMTYPE need to be supported. You're likely to end up placing "#ifdef" sections all over the source code again. 66 -- IInnssttaalllliinngg tthhee ssooffttwwaarree aafftteerr ssuucccceessssffuull ccoommppiillaattiioonn This text describes how to install Postfix from source code. See the PACKAGE_README file if you are building a package for distribution to other systems. 66..11 -- SSaavvee eexxiissttiinngg SSeennddmmaaiill bbiinnaarriieess IMPORTANT: if you are REPLACING an existing Sendmail installation with Postfix, you may need to keep the old sendmail program running for some time in order to flush the mail queue. * Some systems implement a mail switch mechanism where different MTAs (Postfix, Sendmail, etc.) can be installed at the same time, while only one of them is actually being used. Examples of such switching mechanisms are the FreeBSD mailwrapper(8) or the Linux mail switch. In this case you should try to "flip" the switch to "Postfix" before installing Postfix. * If your system has no mail switch mechanism, execute the following commands (your sendmail, newaliases and mailq programs may be in a different place): # mv /usr/sbin/sendmail /usr/sbin/sendmail.OFF # mv /usr/bin/newaliases /usr/bin/newaliases.OFF # mv /usr/bin/mailq /usr/bin/mailq.OFF # chmod 755 /usr/sbin/sendmail.OFF /usr/bin/newaliases.OFF \ /usr/bin/mailq.OFF 66..22 -- CCrreeaattee aaccccoouunntt aanndd ggrroouuppss Before you install Postfix for the first time you need to create an account and a group: * Create a user account "postfix" with a user id and group id that are not used by any other user account. Preferably, this is an account that no-one can log into. The account does not need an executable login shell, and needs no existing home directory. My password and group file entries look like this: /etc/passwd: postfix:*:12345:12345:postfix:/no/where:/no/shell /etc/group: postfix:*:12345: Note: there should be no whitespace before "postfix:". * Create a group "postdrop" with a group id that is not used by any other user account. Not even by the postfix user account. My group file entry looks like: /etc/group: postdrop:*:54321: Note: there should be no whitespace before "postdrop:". 66..33 -- IInnssttaallll PPoossttffiixx To install or upgrade Postfix from compiled source code, run one of the following commands as the super-user: # make install (interactive version, first time install) # make upgrade (non-interactive version, for upgrades) * The interactive version ("make install") asks for pathnames for Postfix data and program files, and stores your preferences in the main.cf file. IIff yyoouu ddoonn''tt wwaanntt PPoossttffiixx ttoo oovveerrwwrriittee nnoonn--PPoossttffiixx ""sseennddmmaaiill"",, ""mmaaiillqq"" aanndd ""nneewwaalliiaasseess"" ffiilleess,, ssppeecciiffyy ppaatthhnnaammeess tthhaatt eenndd iinn ""..ppoossttffiixx"". * The non-interactive version ("make upgrade") needs the /etc/postfix/main.cf file from a previous installation. If the file does not exist, use interactive installation ("make install") instead. 66..44 -- CCoonnffiigguurree PPoossttffiixx Proceed to the section on how you wish to run Postfix on your particular machine: * Send mail only, without changing an existing Sendmail installation (section 7). * Send and receive mail via a virtual host interface, still without any change to an existing Sendmail installation (section 8). * Run Postfix instead of Sendmail (section 9). 77 -- CCoonnffiigguurriinngg PPoossttffiixx ttoo sseenndd mmaaiill oonnllyy If you are going to use Postfix to send mail only, there is no need to change your existing sendmail setup. Instead, set up your mail user agent so that it calls the Postfix sendmail program directly. Follow the instructions in the "Mandatory configuration file edits" in section 10, and review the "To chroot or not to chroot" text in section 11. You MUST comment out the "smtp inet" entry in /etc/postfix/master.cf, in order to avoid conflicts with the real sendmail. Put a "#" character in front of the line that defines the smtpd service: /etc/postfix/master.cf: #smtp inet n - n - - smtpd Start the Postfix system: # postfix start or, if you feel nostalgic, use the Postfix sendmail command: # sendmail -bd -qwhatever and watch your maillog file for any error messages. The pathname is /var/log/ maillog, /var/log/mail, /var/log/syslog, or something else. Typically, the pathname is defined in the /etc/syslog.conf file. % egrep '(reject|warning|error|fatal|panic):' /some/log/file Note: the most important error message is logged first. Later messages are not as useful. In order to inspect the mail queue, use one of the following commands: % mailq % sendmail -bp % postqueue -p See also the "Care and feeding" section 12 below. 88 -- CCoonnffiigguurriinngg PPoossttffiixx ttoo sseenndd aanndd rreecceeiivvee mmaaiill vviiaa vviirrttuuaall iinntteerrffaaccee Alternatively, you can use the Postfix system to send AND receive mail while leaving your Sendmail setup intact, by running Postfix on a virtual interface address. Simply configure your mail user agent to directly invoke the Postfix sendmail program. To create a virtual network interface address, study your system ifconfig manual page. The command syntax could be any of: # iiffccoonnffiigg llee00::11 <> nneettmmaasskk <> uupp # iiffccoonnffiigg eenn00 aalliiaass <> nneettmmaasskk 225555..225555..225555..225555 In the /etc/postfix/main.cf file, I would specify /etc/postfix/main.cf: myhostname = virtual.host.tld inet_interfaces = $myhostname mydestination = $myhostname Follow the instructions in the "Mandatory configuration file edits" in section 10, and review the "To chroot or not to chroot" text in section 11. Start the Postfix system: # postfix start or, if you feel nostalgic, use the Postfix sendmail command: # sendmail -bd -qwhatever and watch your maillog file for any error messages. The pathname is /var/log/ maillog, /var/log/mail, /var/log/syslog, or something else. Typically, the pathname is defined in the /etc/syslog.conf file. % egrep '(reject|warning|error|fatal|panic):' /some/log/file Note: the most important error message is logged first. Later messages are not as useful. In order to inspect the mail queue, use one of the following commands: % mailq % sendmail -bp % postqueue -p See also the "Care and feeding" section 12 below. 99 -- RRuunnnniinngg PPoossttffiixx iinnsstteeaadd ooff SSeennddmmaaiill Prior to installing Postfix you should save any existing sendmail program files as described in section 6. Be sure to keep the old sendmail running for at least a couple days to flush any unsent mail. To do so, stop the sendmail daemon and restart it as: # /usr/sbin/sendmail.OFF -q Note: this is old sendmail syntax. Newer versions use separate processes for mail submission and for running the queue. After you have visited the "Mandatory configuration file edits" section below, you can start the Postfix system with: # postfix start or, if you feel nostalgic, use the Postfix sendmail command: # sendmail -bd -qwhatever and watch your maillog file for any error messages. The pathname is /var/log/ maillog, /var/log/mail, /var/log/syslog, or something else. Typically, the pathname is defined in the /etc/syslog.conf file. % egrep '(reject|warning|error|fatal|panic):' /some/log/file Note: the most important error message is logged first. Later messages are not as useful. In order to inspect the mail queue, use one of the following commands: % mailq % sendmail -bp % postqueue -p See also the "Care and feeding" section 12 below. 1100 -- MMaannddaattoorryy ccoonnffiigguurraattiioonn ffiillee eeddiittss Note: the material covered in this section is covered in more detail in the BASIC_CONFIGURATION_README document. The information presented below is targeted at experienced system administrators. 1100..11 -- PPoossttffiixx ccoonnffiigguurraattiioonn ffiilleess By default, Postfix configuration files are in /etc/postfix. The two most important files are main.cf and master.cf; these files must be owned by root. Giving someone else write permission to main.cf or master.cf (or to their parent directories) means giving root privileges to that person. In /etc/postfix/main.cf, you will have to set up a minimal number of configuration parameters. Postfix configuration parameters resemble shell variables, with two important differences: the first one is that Postfix does not know about quotes like the UNIX shell does. You specify a configuration parameter as: /etc/postfix/main.cf: parameter = value and you use it by putting a "$" character in front of its name: /etc/postfix/main.cf: other_parameter = $parameter You can use $parameter before it is given a value (that is the second main difference with UNIX shell variables). The Postfix configuration language uses lazy evaluation, and does not look at a parameter value until it is needed at runtime. Whenever you make a change to the main.cf or master.cf file, execute the following command in order to refresh a running mail system: # postfix reload 1100..22 -- DDeeffaauulltt ddoommaaiinn ffoorr uunnqquuaalliiffiieedd aaddddrreesssseess First of all, you must specify what domain will be appended to an unqualified address (i.e. an address without @domain.tld). The "myorigin" parameter defaults to the local hostname, but that is probably OK only for very small sites. Some examples (use only one): /etc/postfix/main.cf: myorigin = $myhostname (send mail as "user@$myhostname") myorigin = $mydomain (send mail as "user@$mydomain") 1100..33 -- WWhhaatt ddoommaaiinnss ttoo rreecceeiivvee llooccaallllyy Next you need to specify what mail addresses Postfix should deliver locally. Some examples (use only one): /etc/postfix/main.cf: mydestination = $myhostname, localhost.$mydomain, localhost mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain mydestination = $myhostname The first example is appropriate for a workstation, the second is appropriate for the mailserver for an entire domain. The third example should be used when running on a virtual host interface. 1100..44 -- PPrrooxxyy//NNAATT iinntteerrffaaccee aaddddrreesssseess The proxy_interfaces parameter specifies all network addresses that Postfix receives mail on by way of a proxy or network address translation unit. You may specify symbolic hostnames instead of network addresses. IMPORTANT: You must specify your proxy/NAT external addresses when your system is a backup MX host for other domains, otherwise mail delivery loops will happen when the primary MX host is down. Example: host behind NAT box running a backup MX host. /etc/postfix/main.cf: proxy_interfaces = 1.2.3.4 (the proxy/NAT external network address) 1100..55 -- WWhhaatt llooccaall cclliieennttss ttoo rreellaayy mmaaiill ffrroomm If your machine is on an open network then you must specify what client IP addresses are authorized to relay their mail through your machine into the Internet. The default setting includes all subnetworks that the machine is attached to. This may give relay permission to too many clients. My own settings are: /etc/postfix/main.cf: mynetworks = 168.100.189.0/28, 127.0.0.0/8 1100..66 -- WWhhaatt rreellaayy ddeessttiinnaattiioonnss ttoo aacccceepptt ffrroomm ssttrraannggeerrss If your machine is on an open network then you must also specify whether Postfix will forward mail from strangers. The default setting will forward mail to all domains (and subdomains of) what is listed in $mydestination. This may give relay permission for too many destinations. Recommended settings (use only one): /etc/postfix/main.cf: relay_domains = (do not forward mail from strangers) relay_domains = $mydomain (my domain and subdomains) relay_domains = $mydomain, other.domain.tld, ... 1100..77 -- OOppttiioonnaall:: ccoonnffiigguurree aa ssmmaarrtt hhoosstt ffoorr rreemmoottee ddeelliivveerryy If you're behind a firewall, you should set up a relayhost. If you can, specify the organizational domain name so that Postfix can use DNS lookups, and so that it can fall back to a secondary MX host when the primary MX host is down. Otherwise just specify a hard-coded hostname. Some examples (use only one): /etc/postfix/main.cf: relayhost = $mydomain relayhost = [mail.$mydomain] The form enclosed with [] eliminates DNS MX lookups. By default, the SMTP client will do DNS lookups even when you specify a relay host. If your machine has no access to a DNS server, turn off SMTP client DNS lookups like this: /etc/postfix/main.cf: disable_dns_lookups = yes The STANDARD_CONFIGURATION_README file has more hints and tips for firewalled and/or dial-up networks. 1100..88 -- CCrreeaattee tthhee aalliiaasseess ddaattaabbaassee Postfix uses a Sendmail-compatible aliases(5) table to redirect mail for local (8) recipients. Typically, this information is kept in two files: in a text file /etc/aliases and in an indexed file /etc/aliases.db. The command "postconf alias_maps" will tell you the exact location of the text file. First, be sure to update the text file with aliases for root, postmaster and "postfix" that forward mail to a real person. Postfix has a sample aliases file /etc/postfix/aliases that you can adapt to local conditions. /etc/aliases: root: you postmaster: root postfix: root bin: root etcetera... Note: there should be no whitespace before the ":". Finally, build the indexed aliases file with one of the following commands: # newaliases # sendmail -bi 1111 -- TToo cchhrroooott oorr nnoott ttoo cchhrroooott Postfix daemon processes can be configured (via master.cf) to run in a chroot jail. The processes run at a fixed low privilege and with access only to the Postfix queue directories (/var/spool/postfix). This provides a significant barrier against intrusion. The barrier is not impenetrable, but every little bit helps. With the exception of Postfix daemons that deliver mail locally and/or that execute non-Postfix commands, every Postfix daemon can run chrooted. Sites with high security requirements should consider to chroot all daemons that talk to the network: the smtp(8) and smtpd(8) processes, and perhaps also the lmtp(8) client. The author's own porcupine.org mail server runs all daemons chrooted that can be chrooted. The default /etc/postfix/master.cf file specifies that no Postfix daemon runs chrooted. In order to enable chroot operation, edit the file /etc/postfix/ master.cf. Instructions are in the file. Note that a chrooted daemon resolves all filenames relative to the Postfix queue directory (/var/spool/postfix). For successful use of a chroot jail, most UNIX systems require you to bring in some files or device nodes. The examples/ chroot-setup directory in the source code distribution has a collection of scripts that help you set up Postfix chroot environments on different operating systems. Additionally, you almost certainly need to configure syslogd so that it listens on a socket inside the Postfix queue directory. Examples for specific systems: FreeBSD: # mkdir -p /var/spool/postfix/var/run # syslogd -l /var/spool/postfix/var/run/log Linux, OpenBSD: # mkdir -p /var/spool/postfix/dev # syslogd -a /var/spool/postfix/dev/log 1122 -- CCaarree aanndd ffeeeeddiinngg ooff tthhee PPoossttffiixx ssyysstteemm Postfix daemon processes run in the background, and log problems and normal activity to the syslog daemon. The names of logfiles are specified in /etc/ syslog.conf. At the very least you need something like: /etc/syslog.conf: mail.err /dev/console mail.debug /var/log/maillog IMPORTANT: the syslogd will not create files. You must create them before (re)starting syslogd. IMPORTANT: on Linux you need to put a "-" character before the pathname, e.g., -/var/log/maillog, otherwise the syslogd will use more system resources than Postfix does. Hopefully, the number of problems will be small, but it is a good idea to run every night before the syslog files are rotated: # postfix check # egrep '(reject|warning|error|fatal|panic):' /some/log/file * The first line (postfix check) causes Postfix to report file permission/ ownership discrepancies. * The second line looks for problem reports from the mail software, and reports how effective the relay and junk mail access blocks are. This may produce a lot of output. You will want to apply some postprocessing to eliminate uninteresting information. The DEBUG_README document describes the meaning of the "warning" etc. labels in Postfix logging. README_FILES/RESTRICTION_CLASS_README000066600000015327150501202770012130 0ustar00PPoossttffiixx PPeerr--CClliieenntt//UUsseerr//eettcc.. AAcccceessss CCoonnttrrooll ------------------------------------------------------------------------------- PPoossttffiixx rreessttrriiccttiioonn ccllaasssseess The Postfix SMTP server supports access restrictions such as reject_rbl_client or reject_unknown_client_hostname on the right-hand side of SMTP server access (5) tables. This allows you to implement different junk mail restrictions for different clients or users. Having to specify lists of access restrictions for every recipient becomes tedious quickly. Postfix restriction classes allow you to give easy-to-remember names to groups of UCE restrictions (such as "permissive", "restrictive", and so on). The real reason for the existence of Postfix restriction classes is more mundane: you can't specify a lookup table on the right-hand side of a Postfix access table. This is because Postfix needs to open lookup tables ahead of time, but the reader probably does not care about these low-level details. Example: /etc/postfix/main.cf: smtpd_restriction_classes = restrictive, permissive # With Postfix < 2.3 specify reject_unknown_client. restrictive = reject_unknown_sender_domain reject_unknown_client_hostname ... permissive = permit smtpd_recipient_restrictions = permit_mynetworks reject_unauth_destination check_recipient_access hash:/etc/postfix/recipient_access /etc/postfix/recipient_access: joe@my.domain permissive jane@my.domain restrictive With this in place, you can use "restrictive" or "permissive" on the right-hand side of your per-client, helo, sender, or recipient SMTPD access tables. The remainder of this document gives examples of how Postfix access restriction classes can be used to: * Shield an internal mailing list from outside posters, * Prevent external access by internal senders. These questions come up frequently, and the examples hopefully make clear that Postfix restriction classes aren't really the right solution. They should be used for what they were designed to do, different junk mail restrictions for different clients or users. PPrrootteeccttiinngg iinntteerrnnaall eemmaaiill ddiissttrriibbuuttiioonn lliissttss We want to implement an internal email distribution list. Something like all@our.domain.com, which aliases to all employees. My first thought was to use the aliases map, but that would lead to "all" being accessible from the "outside", and this is not desired... :-) Postfix can implement per-address access controls. What follows is based on the SMTP client IP address, and therefore is subject to IP spoofing. /etc/postfix/main.cf: smtpd_recipient_restrictions = check_recipient_access hash:/etc/postfix/access ...the usual stuff... /etc/postfix/access: all@my.domain permit_mynetworks,reject all@my.hostname permit_mynetworks,reject Specify ddbbmm instead of hhaasshh if your system uses ddbbmm files instead of ddbb files. To find out what map types Postfix supports, use the command ppoossttccoonnff --mm. Now, that would be sufficient when your machine receives all Internet mail directly from the Internet. That's unlikely if your network is a bit larger than an office. For example, your backup MX hosts would "launder" the client IP address of mail from the outside so it would appear to come from a trusted machine. In the general case you need two lookup tables: one table that lists destinations that need to be protected, and one table that lists domains that are allowed to send to the protected destinations. What follows is based on the sender SMTP envelope address, and therefore is subject to SMTP sender spoofing. /etc/postfix/main.cf: smtpd_recipient_restrictions = check_recipient_access hash:/etc/postfix/protected_destinations ...the usual stuff... smtpd_restriction_classes = insiders_only insiders_only = check_sender_access hash:/etc/postfix/insiders, reject /etc/postfix/protected_destinations: all@my.domain insiders_only all@my.hostname insiders_only /etc/postfix/insiders: my.domain OK matches my.domain and subdomains another.domain OK matches another.domain and subdomains Getting past this scheme is relatively easy, because all one has to do is to spoof the SMTP sender address. If the internal list is a low-volume one, perhaps it makes more sense to make it moderated. RReessttrriiccttiinngg wwhhaatt uusseerrss ccaann sseenndd mmaaiill ttoo ooffff--ssiittee ddeessttiinnaattiioonnss How can I configure Postfix in a way that some users can send mail to the internet and other users not. The users with no access should receive a generic bounce message. Please don't discuss whether such access restrictions are necessary, it was not my decision. Postfix has support for per-user restrictions. The restrictions are implemented by the SMTP server. Thus, users that violate the policy have their mail rejected by the SMTP server. Like this: 554 : Access denied The implementation uses two lookup tables. One table defines what users are restricted in where they can send mail, and the other table defines what destinations are local. It is left as an exercise for the reader to change this into a scheme where only some users have permission to send mail to off-site destinations, and where most users are restricted. The example assumes DB/DBM files, but this could also be done with LDAP or SQL. /etc/postfix/main.cf: smtpd_recipient_restrictions = check_sender_access hash:/etc/postfix/restricted_senders ...other stuff... smtpd_restriction_classes = local_only local_only = check_recipient_access hash:/etc/postfix/local_domains, reject /etc/postfix/restricted_senders: foo@domain local_only bar@domain local_only /etc/postfix/local_domains: this.domain OK matches this.domain and subdomains that.domain OK matches that.domain and subdomains Specify ddbbmm instead of hhaasshh if your system uses ddbbmm files instead of ddbb files. To find out what map types Postfix supports, use the command ppoossttccoonnff --mm. Note: this scheme does not authenticate the user, and therefore it can be bypassed in several ways: * By sending mail via a less restrictive mail relay host. * By sending mail as someone else who does have permission to send mail to off-site destinations. README_FILES/XCLIENT_README000066600000022613150501202770010500 0ustar00PPoossttffiixx XXCCLLIIEENNTT HHoowwttoo ------------------------------------------------------------------------------- PPuurrppoossee ooff tthhee XXCCLLIIEENNTT eexxtteennssiioonn ttoo SSMMTTPP When an SMTP server announces support for the XCLIENT command, an SMTP client may send information that overrides one or more client-related session attributes. The XCLIENT command targets the following problems: 1. Access control tests. SMTP server access rules are difficult to verify when decisions can be triggered only by remote clients. In order to facilitate access rule testing, an authorized SMTP client test program needs the ability to override the SMTP server's idea of the SMTP client hostname, network address, and other client information, for the entire duration of an SMTP session. 2. Client software that downloads mail from an up-stream mail server and injects it into a local MTA via SMTP. In order to take advantage of the local MTA's SMTP server access rules, the client software needs the ability to override the SMTP server's idea of the remote client name, client address and other information. Such information can typically be extracted from the up-stream mail server's Received: message header. 3. Post-filter access control and logging. With Internet->filter->MTA style content filter applications, the filter can be simplified if it can delegate decisions concerning mail relay and other access control to the MTA. This is especially useful when the filter acts as a transparent proxy for SMTP commands. This requires that the filter can override the MTA's idea of the SMTP client hostname, network address, and other information. XXCCLLIIEENNTT CCoommmmaanndd ssyynnttaaxx An example client-server conversation is given at the end of this document. In SMTP server EHLO replies, the keyword associated with this extension is XCLIENT. It is followed by the names of the attributes that the XCLIENT implementation supports. The XCLIENT command may be sent at any time, except in the middle of a mail delivery transaction (i.e. between MAIL and DOT, or MAIL and RSET). The XCLIENT command may be pipelined when the server supports ESMTP command pipelining. To avoid triggering spamware detectors, the command should be sent at the end of a command group. The syntax of XCLIENT requests is described below. Upper case and quoted strings specify terminals, lowercase strings specify meta terminals, and SP is whitespace. Although command and attribute names are shown in upper case, they are in fact case insensitive. xclient-command = XCLIENT 1*( SP attribute-name"="attribute-value ) attribute-name = ( NAME | ADDR | PORT | PROTO | HELO ) attribute-value = xtext * Attribute values are xtext encoded as per RFC 1891. * The NAME attribute specifies an SMTP client hostname (not an SMTP client address), [UNAVAILABLE] when client hostname lookup failed due to a permanent error, or [TEMPUNAVAIL] when the lookup error condition was transient. * The ADDR attribute specifies an SMTP client numerical IPv4 network address, an IPv6 address prefixed with IPV6:, or [UNAVAILABLE] when the address information is unavailable. Address information is not enclosed with []. * The PORT attribute specifies the SMTP client TCP port number as a decimal number, or [UNAVAILABLE] when the information is unavailable. * The PROTO attribute specifies either SMTP or ESMTP. * The HELO attribute specifies an SMTP HELO parameter value, or the value [UNAVAILABLE] when the information is unavailable. Note 1: syntactically valid NAME and HELO attribute-value elements can be up to 255 characters long. The client must not send XCLIENT commands that exceed the 512 character limit for SMTP commands. To avoid exceeding the limit the client should send the information in multiple XCLIENT commands; for example, send NAME and ADDR first, then HELO and PROTO. Note 2: [UNAVAILABLE], [TEMPUNAVAIL] and IPV6: may be specified in upper case, lower case or mixed case. Note 3: Postfix implementations prior to version 2.3 do not xtext encode attribute values. Servers that wish to interoperate with these older implementations should be prepared to receive unencoded information. Note 4: Postfix implementations prior to version 2.5 do not implement the PORT attribute. XXCCLLIIEENNTT SSeerrvveerr rreessppoonnssee Upon receipt of a correctly formatted XCLIENT command, the server resets state to the initial SMTP greeting protocol stage. Depending on the outcome of optional access decisions, the server responds with 220 or with a suitable rejection code. For practical reasons it is not always possible to reset the complete server state to the initial SMTP greeting protocol stage: * TLS session information may not be reset, because turning off TLS leaves the connection in an undefined state. Consequently, the server may not announce STARTTLS when TLS is already active, and access decisions may be influenced by client certificate information that was received prior to the XCLIENT command. * The SMTP server must not reset attributes that were received with the last XCLIENT command. This includes HELO or PROTO attributes. NOTE: Postfix implementations prior to version 2.3 do not jump back to the initial SMTP greeting protocol stage. These older implementations will not correctly simulate connection-level access decisions under some conditions. XXCCLLIIEENNTT sseerrvveerr rreeppllyy ccooddeess _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |CCooddee |MMeeaanniinngg | |_ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |220 |success | |_ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |421 |unable to proceed, disconnecting | |_ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |501 |bad command parameter syntax | |_ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |503 |mail transaction in progress | |_ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |550 |insufficient authorization | |_ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |other|connection rejected by connection-level access decision| |_ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | XXCCLLIIEENNTT EExxaammppllee In the example, the client impersonates a mail originating system by passing all SMTP client information via the XCLIENT command. Information sent by the client is shown in bold font. 220 server.example.com ESMTP Postfix EEHHLLOO cclliieenntt..eexxaammppllee..ccoomm 250-server.example.com 250-PIPELINING 250-SIZE 10240000 250-VRFY 250-ETRN 250-XCLIENT NAME ADDR PROTO HELO 250 8BITMIME XXCCLLIIEENNTT NNAAMMEE==ssppiikkee..ppoorrccuuppiinnee..oorrgg AADDDDRR==116688..110000..118899..22 220 server.example.com ESMTP Postfix EEHHLLOO ssppiikkee..ppoorrccuuppiinnee..oorrgg 250-server.example.com 250-PIPELINING 250-SIZE 10240000 250-VRFY 250-ETRN 250-XCLIENT NAME ADDR PROTO HELO 250 8BITMIME MMAAIILL FFRROOMM::<> 250 Ok RRCCPPTT TTOO::<> 250 Ok DDAATTAA 354 End data with . .. .. ..mmeessssaaggee ccoonntteenntt.. .. .. .. 250 Ok: queued as 763402AAE6 QQUUIITT 221 Bye SSeeccuurriittyy The XCLIENT command changes audit trails and/or SMTP client access permissions. Use of this command must be restricted to authorized SMTP clients. SSMMTTPP ccoonnnneeccttiioonn ccaacchhiinngg XCLIENT attributes persist until the end of an SMTP session. If one session is used to deliver mail on behalf of different SMTP clients, the XCLIENT attributes need to be reset as appropriate before each MAIL FROM command. RReeffeerreenncceess Moore, K, "SMTP Service Extension for Delivery Status Notifications", RFC 1891, January 1996. README_FILES/MAILDROP_README000066600000012250150501202770010575 0ustar00PPoossttffiixx ++ MMaaiillddrroopp HHoowwttoo ------------------------------------------------------------------------------- IInnttrroodduuccttiioonn This document discusses various options to plug the maildrop delivery agent into Postfix: * Direct delivery without the local delivery agent * Indirect delivery via the local delivery agent * Credits DDiirreecctt ddeelliivveerryy wwiitthhoouutt tthhee llooccaall ddeelliivveerryy aaggeenntt Postfix can be configured to deliver mail directly to maildrop, without using the local(8) delivery agent as an intermediate. This means that you do not get local aliases(5) expansion or $HOME/.forward file processing. You would typically do this for hosted domains with recipients that don't have UNIX home directories. The following example shows how to use maildrop for some.domain and for someother.domain. The example comes in two parts. Part 1 describes changes to the main.cf file: 1 /etc/postfix/main.cf: 2 maildrop_destination_recipient_limit = 1 3 virtual_mailbox_domains = some.domain someother.domain 4 virtual_transport = maildrop 5 virtual_mailbox_maps = hash:/etc/postfix/virtual_mailbox 6 virtual_alias_maps = hash:/etc/postfix/virtual_alias 7 8 /etc/postfix/virtual_mailbox: 9 user1@some.domain ...text here does not matter... 10 user2@some.domain ...text here does not matter... 11 user3@someother.domain ...text here does not matter... 12 13 /etc/postfix/virtual_alias: 14 postmaster@some.domain postmaster 15 postmaster@someother.domain postmaster * Line 2 is needed so that Postfix will provide one recipient at a time to the maildrop delivery agent. * Line 3 informs Postfix that some.domain and someother.domain are so-called virtual mailbox domains. Instead of listing the names in main.cf you can also list them in a file; see the virtual_mailbox_domains documentation for details. * Line 4 specifies that mail for some.domain and someother.domain should be delivered by the maildrop delivery agent. * Lines 5 and 8-11 specify what recipients the Postfix SMTP server should receive mail for. This prevents the mail queue from becoming clogged with undeliverable messages. Specify an empty value ("virtual_mailbox_maps =") to disable this feature. * Lines 6 and 13-15 redirect mail for postmaster to the local postmaster. RFC 821 requires that every domain has a postmaster address. The vmail userid as used below is the user that maildrop should run as. This would be the owner of the virtual mailboxes if they all have the same owner. If maildrop is suid (see maildrop documentation), then maildrop will change to the appropriate owner to deliver the mail. Note: Do not use the postfix user as the maildrop user. Part 2 describes changes to the master.cf file: /etc/postfix/master.cf: maildrop unix - n n - - pipe flags=ODRhu user=vmail argv=/path/to/maildrop -d ${recipient} The pipe(8) manual page gives a detailed description of the above command line arguments, and more. If you want to support user+extension@domain style addresses, use the following instead: /etc/postfix/master.cf: maildrop unix - n n - - pipe flags=ODRhu user=vmail argv=/path/to/maildrop -d ${user}@${nexthop} ${extension} ${recipient} ${user} ${nexthop} The mail is delivered to ${user}@${nexthop} (match key for maildrop userdb lookup). The ${extension} and the other address components are available to maildrop rules as $1, $2, $3, ... and can be omitted from master.cf or ignored by maildrop when not needed. IInnddiirreecctt ddeelliivveerryy vviiaa tthhee llooccaall ddeelliivveerryy aaggeenntt Postfix can be configured to deliver mail to maildrop via the local delivery agent. This is slightly less efficient than the "direct" approach discussed above, but gives you the convenience of local aliases(5) expansion and $HOME/.forward file processing. You would typically use this for domains that are listed in mydestination and that have users with a UNIX system account. To configure maildrop delivery for all UNIX system accounts: /etc/postfix/main.cf: mailbox_command = /path/to/maildrop -d ${USER} Note: ${USER} is spelled in upper case. To enable maildrop delivery for specific users only, you can use the Postfix local(8) delivery agent's mailbox_command_maps feature: /etc/postfix/main.cf: mailbox_command_maps = hash:/etc/postfix/mailbox_commands /etc/postfix/mailbox_commands: you /path/to/maildrop -d ${USER} Maildrop delivery for specific users is also possible by invoking it from the user's $HOME/.forward file: /home/you/.forward: "|/path/to/maildrop -d ${USER}" CCrreeddiittss * The original text was kindly provided by Russell Mosemann. * Victor Duchovni provided tips for supporting user+foo@domain addresses. * Tonni Earnshaw contributed text about delivery via the local(8) delivery agent. README_FILES/LDAP_README000066600000047515150501202770010122 0ustar00PPoossttffiixx LLDDAAPP HHoowwttoo ------------------------------------------------------------------------------- LLDDAAPP SSuuppppoorrtt iinn PPoossttffiixx Postfix can use an LDAP directory as a source for any of its lookups: aliases (5), virtual(5), canonical(5), etc. This allows you to keep information for your mail service in a replicated network database with fine-grained access controls. By not storing it locally on the mail server, the administrators can maintain it from anywhere, and the users can control whatever bits of it you think appropriate. You can have multiple mail servers using the same information, without the hassle and delay of having to copy it to each. Topics covered in this document: * Building Postfix with LDAP support * Configuring LDAP lookups * Example: aliases * Example: virtual domains/addresses * Example: expanding LDAP groups * Other uses of LDAP lookups * Notes and things to think about * Feedback * Credits BBuuiillddiinngg PPoossttffiixx wwiitthh LLDDAAPP ssuuppppoorrtt These instructions assume that you build Postfix from source code as described in the INSTALL document. Some modification may be required if you build Postfix from a vendor-specific source package. Note 1: Postfix no longer supports the LDAP version 1 interface. Note 2: to use LDAP with Debian GNU/Linux's Postfix, all you need is to install the postfix-ldap package and you're done. There is no need to recompile Postfix. You need to have LDAP libraries and include files installed somewhere on your system, and you need to configure the Postfix Makefiles accordingly. For example, to build the OpenLDAP libraries for use with Postfix (i.e. LDAP client code only), you could use the following command: % ./configure --without-kerberos --without-cyrus-sasl --without-tls \ --without-threads --disable-slapd --disable-slurpd \ --disable-debug --disable-shared If you're using the libraries from the UM distribution (http://www.umich.edu/ ~dirsvcs/ldap/ldap.html) or OpenLDAP (http://www.openldap.org), something like this in the top level of your Postfix source tree should work: % make tidy % make makefiles CCARGS="-I/usr/local/include -DHAS_LDAP" \ AUXLIBS="-L/usr/local/lib -lldap -L/usr/local/lib -llber" On Solaris 2.x you may have to specify run-time link information, otherwise ld.so will not find some of the shared libraries: % make tidy % make makefiles CCARGS="-I/usr/local/include -DHAS_LDAP" \ AUXLIBS="-L/usr/local/lib -R/usr/local/lib -lldap \ -L/usr/local/lib -R/usr/local/lib -llber" The 'make tidy' command is needed only if you have previously built Postfix without LDAP support. Instead of '/usr/local' specify the actual locations of your LDAP include files and libraries. Be sure to not mix LDAP include files and LDAP libraries of different versions!! If your LDAP libraries were built with Kerberos support, you'll also need to include your Kerberos libraries in this line. Note that the KTH Kerberos IV libraries might conflict with Postfix's lib/libdns.a, which defines dns_lookup. If that happens, you'll probably want to link with LDAP libraries that lack Kerberos support just to build Postfix, as it doesn't support Kerberos binds to the LDAP server anyway. Sorry about the bother. If you're using one of the Netscape LDAP SDKs, you'll need to change the AUXLIBS line to point to libldap10.so or libldapssl30.so or whatever you have, and you may need to use the appropriate linker option (e.g. '-R') so the executables can find it at runtime. CCoonnffiigguurriinngg LLDDAAPP llooookkuuppss In order to use LDAP lookups, define an LDAP source as a table lookup in main.cf, for example: alias_maps = hash:/etc/aliases, ldap:/etc/postfix/ldap-aliases.cf The file /etc/postfix/ldap-aliases.cf can specify a great number of parameters, including parameters that enable LDAP SSL and STARTTLS. For a complete description, see the ldap_table(5) manual page. EExxaammppllee:: llooccaall((88)) aalliiaasseess Here's a basic example for using LDAP to look up local(8) aliases. Assume that in main.cf, you have: alias_maps = hash:/etc/aliases, ldap:/etc/postfix/ldap-aliases.cf and in ldap:/etc/postfix/ldap-aliases.cf you have: server_host = ldap.example.com search_base = dc=example, dc=com Upon receiving mail for a local address "ldapuser" that isn't found in the / etc/aliases database, Postfix will search the LDAP server listening at port 389 on ldap.example.com. It will bind anonymously, search for any directory entries whose mailacceptinggeneralid attribute is "ldapuser", read the "maildrop" attributes of those found, and build a list of their maildrops, which will be treated as RFC822 addresses to which the message will be delivered. EExxaammppllee:: vviirrttuuaall ddoommaaiinnss//aaddddrreesssseess If you want to keep information for virtual lookups in your directory, it's only a little more complicated. First, you need to make sure Postfix knows about the virtual domain. An easy way to do that is to add the domain to the mailacceptinggeneralid attribute of some entry in the directory. Next, you'll want to make sure all of your virtual recipient's mailacceptinggeneralid attributes are fully qualified with their virtual domains. Finally, if you want to designate a directory entry as the default user for a virtual domain, just give it an additional mailacceptinggeneralid (or the equivalent in your directory) of "@fake.dom". That's right, no user part. If you don't want a catchall user, omit this step and mail to unknown users in the domain will simply bounce. In summary, you might have a catchall user for a virtual domain that looks like this: dn: cn=defaultrecipient, dc=fake, dc=dom objectclass: top objectclass: virtualaccount cn: defaultrecipient owner: uid=root, dc=someserver, dc=isp, dc=dom 1 -> mailacceptinggeneralid: fake.dom 2 -> mailacceptinggeneralid: @fake.dom 3 -> maildrop: realuser@real.dom 1: Postfix knows fake.dom is a valid virtual domain when it looks for this and gets something (the maildrop) back. 2: This causes any mail for unknown users in fake.dom to go to this entry ... 3: ... and then to its maildrop. Normal users might simply have one mailacceptinggeneralid and maildrop, e.g. "normaluser@fake.dom" and "normaluser@real.dom". EExxaammppllee:: eexxppaannddiinngg LLDDAAPP ggrroouuppss LDAP is frequently used to store group member information. There are a number of ways of handling LDAP groups. We will show a few examples in order of increasing complexity, but owing to the number of independent variables, we can only present a tiny portion of the solution space. We show how to: 1. query groups as lists of addresses; 2. query groups as lists of user objects containing addresses; 3. forward special lists unexpanded to a separate list server, for moderation or other processing; 4. handle complex schemas by controlling expansion and by treating leaf nodes specially, using features that are new in Postfix 2.4. The example LDAP entries and implied schema below show two group entries ("agroup" and "bgroup") and four user entries ("auser", "buser", "cuser" and "duser"). The group "agroup" has the users "auser" (1) and "buser" (2) as members via DN references in the multi-valued attribute "memberdn", and direct email addresses of two external users "auser@example.org" (3) and "buser@example.org" (4) stored in the multi-valued attribute "memberaddr". The same is true of "bgroup" and "cuser"/"duser" (6)/(7)/(8)/(9), but "bgroup" also has a "maildrop" attribute of "bgroup@mlm.example.com" (5): dn: cn=agroup, dc=example, dc=com objectclass: top objectclass: ldapgroup cn: agroup mail: agroup@example.com 1 -> memberdn: uid=auser, dc=example, dc=com 2 -> memberdn: uid=buser, dc=example, dc=com 3 -> memberaddr: auser@example.org 4 -> memberaddr: buser@example.org dn: cn=bgroup, dc=example, dc=com objectclass: top objectclass: ldapgroup cn: bgroup mail: bgroup@example.com 5 -> maildrop: bgroup@mlm.example.com 6 -> memberdn: uid=cuser, dc=example, dc=com 7 -> memberdn: uid=duser, dc=example, dc=com 8 -> memberaddr: cuser@example.org 9 -> memberaddr: duser@example.org dn: uid=auser, dc=example, dc=com objectclass: top objectclass: ldapuser uid: auser 10 -> mail: auser@example.com 11 -> maildrop: auser@mailhub.example.com dn: uid=buser, dc=example, dc=com objectclass: top objectclass: ldapuser uid: buser 12 -> mail: buser@example.com 13 -> maildrop: buser@mailhub.example.com dn: uid=cuser, dc=example, dc=com objectclass: top objectclass: ldapuser uid: cuser 14 -> mail: cuser@example.com dn: uid=duser, dc=example, dc=com objectclass: top objectclass: ldapuser uid: duser 15 -> mail: duser@example.com Our first use case ignores the "memberdn" attributes, and assumes that groups hold only direct "memberaddr" strings as in (3), (4), (8) and (9). The goal is to map the group address to the list of constituent "memberaddr" values. This is simple, ignoring the various connection related settings (hosts, ports, bind settings, timeouts, ...) we have: simple.cf: ... search_base = dc=example, dc=com query_filter = mail=%s result_attribute = memberaddr $ postmap -q agroup@example.com ldap:simple.cf auser@example.org,buser@example.org We search "dc=example, dc=com". The "mail" attribute is used in the query_filter to locate the right group, the "result_attribute" setting described in ldap_table(5) is used to specify that "memberaddr" values from the matching group are to be returned as a comma separated list. Always check tables using postmap(1) with the "-q" option, before deploying them into production use in main.cf. Our second use case instead expands "memberdn" attributes (1), (2), (6) and (7), follows the DN references and returns the "maildrop" of the referenced user entries. Here we use the "special_result_attribute" setting from ldap_table(5) to designate the "memberdn" attribute as holding DNs of the desired member entries. The "result_attribute" setting selects which attributes are returned from the selected DNs. It is important to choose a result attribute that is not also present in the group object, because result attributes are collected from both the group and the member DNs. In this case we choose "maildrop" and assume for the moment that groups never have a "maildrop" (the "bgroup" "maildrop" attribute is for a different use case). The returned data for "auser" and "buser" is from items (11) and (13) in the example data. special.cf: ... search_base = dc=example, dc=com query_filter = mail=%s result_attribute = maildrop special_result_attribute = memberdn $ postmap -q agroup@example.com ldap:special.cf auser@mailhub.example.com,buser@mailhub.example.com Note: if the desired member object result attribute is always also present in the group, you get surprising results: the expansion also returns the address of the group. This is a known limitation of Postfix releases prior to 2.4, and is addressed in the new with Postfix 2.4 "leaf_result_attribute" feature described in ldap_table(5). Our third use case has some groups that are expanded immediately, and other groups that are forwarded to a dedicated mailing list manager host for delayed expansion. This uses two LDAP tables, one for users and forwarded groups and a second for groups that can be expanded immediately. It is assumed that groups that require forwarding are never nested members of groups that are directly expanded. no_expand.cf: ... search_base = dc=example, dc=com query_filter = mail=%s result_attribute = maildrop expand.cf ... search_base = dc=example, dc=com query_filter = mail=%s result_attribute = maildrop special_result_attribute = memberdn $ postmap -q auser@example.com ldap:no_expand.cf ldap:expand.cf auser@mailhub.example.com $ postmap -q agroup@example.com ldap:no_expand.cf ldap:expand.cf auser@mailhub.example.com,buser@mailhub.example.com $ postmap -q bgroup@example.com ldap:no_expand.cf ldap:expand.cf bgroup@mlm.example.com Non-group objects and groups with delayed expansion (those that have a maildrop attribute) are rewritten to a single maildrop value. Groups that don't have a maildrop are expanded as the second use case. This admits a more elegant solution with Postfix 2.4 and later. Our final use case is the same as the third, but this time uses new features in Postfix 2.4. We now are able to use just one LDAP table and no longer need to assume that forwarded groups are never nested inside expanded groups. fancy.cf: ... search_base = dc=example, dc=com query_filter = mail=%s result_attribute = memberaddr special_result_attribute = memberdn terminal_result_attribute = maildrop leaf_result_attribute = mail $ postmap -q auser@example.com ldap:fancy.cf auser@mailhub.example.com $ postmap -q cuser@example.com ldap:fancy.cf cuser@example.com $ postmap -q agroup@example.com ldap:fancy.cf auser@mailhub.example.com,buser@mailhub.example.com,auser@example.org,buser@example.org $ postmap -q bgroup@example.com ldap:fancy.cf bgroup@mlm.example.com Above, delayed expansion is enabled via "terminal_result_attribute", which, if present, is used as the sole result and all other expansion is suppressed. Otherwise, the "leaf_result_attribute" is only returned for leaf objects that don't have a "special_result_attribute" (non-groups), while the "result_attribute" (direct member address of groups) is returned at every level of recursive expansion, not just the leaf nodes. This fancy example illustrates all the features of Postfix 2.4 group expansion. OOtthheerr uusseess ooff LLDDAAPP llooookkuuppss Other common uses for LDAP lookups include rewriting senders and recipients with Postfix's canonical lookups, for example in order to make mail leaving your site appear to be coming from "First.Last@example.com" instead of "userid@example.com". NNootteess aanndd tthhiinnggss ttoo tthhiinnkk aabboouutt * The bits of schema and attribute names used in this document are just examples. There's nothing special about them, other than that some are the defaults in the LDAP configuration parameters. You can use whatever schema you like, and configure Postfix accordingly. * You probably want to make sure that mailacceptinggeneralids are unique, and that not just anyone can specify theirs as postmaster or root, say. * An entry can have an arbitrary number of mailacceptinggeneralids or maildrops. Maildrops can also be comma-separated lists of addresses. They will all be found and returned by the lookups. For example, you could define an entry intended for use as a mailing list that looks like this (Warning! Schema made up just for this example): dn: cn=Accounting Staff List, dc=example, dc=com cn: Accounting Staff List o: example.com objectclass: maillist mailacceptinggeneralid: accountingstaff mailacceptinggeneralid: accounting-staff maildrop: mylist-owner maildrop: an-accountant maildrop: some-other-accountant maildrop: this, that, theother * If you use an LDAP map for lookups other than aliases, you may have to make sure the lookup makes sense. In the case of virtual lookups, maildrops other than mail addresses are pretty useless, because Postfix can't know how to set the ownership for program or file delivery. Your qquueerryy__ffiilltteerr should probably look something like this: query_filter = (&(mailacceptinggeneralid=%s)(!(|(maildrop="*|*") (maildrop="*:*")(maildrop="*/*")))) * And for that matter, even for aliases, you may not want users able to specify their maildrops as programs, includes, etc. This might be particularly pertinent on a "sealed" server where they don't have local UNIX accounts, but exist only in LDAP and Cyrus. You might allow the fun stuff only for directory entries owned by an administrative account, so that if the object had a program as its maildrop and weren't owned by "cn=root" it wouldn't be returned as a valid local user. This will require some thought on your part to implement safely, considering the ramifications of this type of delivery. You may decide it's not worth the bother to allow any of that nonsense in LDAP lookups, ban it in the qquueerryy__ffiilltteerr, and keep things like majordomo lists in local alias databases. query_filter = (&(mailacceptinggeneralid=%s)(!(|(maildrop="*|*") (maildrop="*:*")(maildrop="*/*"))(owner=cn=root, dc=your, dc=com))) * LDAP lookups are slower than local DB or DBM lookups. For most sites they won't be a bottleneck, but it's a good idea to know how to tune your directory service. * Multiple LDAP maps share the same LDAP connection if they differ only in their query related parameters: base, scope, query_filter, and so on. To take advantage of this, avoid spurious differences in the definitions of LDAP maps: host selection order, version, bind, tls parameters, ... should be the same for multiple maps whenever possible. FFeeeeddbbaacckk If you have questions, send them to postfix-users@postfix.org. Please include relevant information about your Postfix setup: LDAP-related output from postconf, which LDAP libraries you built with, and which directory server you're using. If your question involves your directory contents, please include the applicable bits of some directory entries. CCrreeddiittss * Manuel Guesdon: Spotted a bug with the timeout attribute. * John Hensley: Multiple LDAP sources with more configurable attributes. * Carsten Hoeger: Search scope handling. * LaMont Jones: Domain restriction, URL and DN searches, multiple result attributes. * Mike Mattice: Alias dereferencing control. * Hery Rakotoarisoa: Patches for LDAPv3 updating. * Prabhat K Singh: Wrote the initial Postfix LDAP lookups and connection caching. * Keith Stevenson: RFC 2254 escaping in queries. * Samuel Tardieu: Noticed that searches could include wildcards, prompting the work on RFC 2254 escaping in queries. Spotted a bug in binding. * Sami Haahtinen: Referral chasing and v3 support. * Victor Duchovni: ldap_bind() timeout. With fixes from LaMont Jones: OpenLDAP cache deprecation. Limits on recursion, expansion and search results size. LDAP connection sharing for maps differing only in the query parameters. * Liviu Daia: Support for SSL/STARTTLS. Support for storing map definitions in external files (ldap:/path/ldap.cf) needed to securely store passwords for plain auth. * Liviu Daia revised the configuration interface and added the main.cf configuration feature. * Liviu Daia with further refinements from Jose Luis Tallon and Victor Duchovni developed the common query, result_format, domain and expansion_limit interface for LDAP, MySQL and PosgreSQL. * Gunnar Wrobel provided a first implementation of a feature to limit LDAP search results to leaf nodes only. Victor generalized this into the Postfix 2.4 "leaf_result_attribute" feature. And of course Wietse. README_FILES/MYSQL_README000066600000010474150501202770010301 0ustar00PPoossttffiixx MMyySSQQLL HHoowwttoo ------------------------------------------------------------------------------- IInnttrroodduuccttiioonn The Postfix mysql map type allows you to hook up Postfix to a MySQL database. This implementation allows for multiple mysql databases: you can use one for a virtual(5) table, one for an access(5) table, and one for an aliases(5) table if you want. You can specify multiple servers for the same database, so that Postfix can switch to a good database server if one goes bad. Busy mail servers using mysql maps will generate lots of concurrent mysql clients, so the mysql server(s) should be run with this fact in mind. You can reduce the number of concurrent mysql clients by using the Postfix proxymap(8) service. BBuuiillddiinngg PPoossttffiixx wwiitthh MMyySSQQLL ssuuppppoorrtt These instructions assume that you build Postfix from source code as described in the INSTALL document. Some modification may be required if you build Postfix from a vendor-specific source package. Note: to use mysql with Debian GNU/Linux's Postfix, all you need is to install the postfix-mysql package and you're done. There is no need to recompile Postfix. The Postfix MySQL client utilizes the mysql client library, which can be obtained from: http://www.mysql.com/downloads/ http://sourceforge.net/projects/mysql/ In order to build Postfix with mysql map support, you will need to add - DHAS_MYSQL and -I for the directory containing the mysql headers, and the mysqlclient library (and libm) to AUXLIBS, for example: make -f Makefile.init makefiles \ 'CCARGS=-DHAS_MYSQL -I/usr/local/mysql/include' \ 'AUXLIBS=-L/usr/local/mysql/lib -lmysqlclient -lz -lm' On Solaris, use this instead: make -f Makefile.init makefiles \ 'CCARGS=-DHAS_MYSQL -I/usr/local/mysql/include' \ 'AUXLIBS=-L/usr/local/mysql/lib -R/usr/local/mysql/lib \ -lmysqlclient -lz -lm' Then, just run 'make'. This requires libz, the compression library. Older mysql implementations build without libz. UUssiinngg MMyySSQQLL ttaabblleess Once Postfix is built with mysql support, you can specify a map type in main.cf like this: alias_maps = mysql:/etc/postfix/mysql-aliases.cf The file /etc/postfix/mysql-aliases.cf specifies lots of information telling Postfix how to reference the mysql database. For a complete description, see the mysql_table(5) manual page. EExxaammppllee:: llooccaall aalliiaasseess # # mysql config file for local(8) aliases(5) lookups # # The user name and password to log into the mysql server. user = someone password = some_password # The database name on the servers. dbname = customer_database # For Postfix 2.2 and later The SQL query template. # See mysql_table(5) for details. query = SELECT forw_addr FROM mxaliases WHERE alias='%s' AND status='paid' # For Postfix releases prior to 2.2. See mysql_table(5) for details. select_field = forw_addr table = mxaliases where_field = alias # Don't forget the leading "AND"! additional_conditions = AND status = 'paid' AAddddiittiioonnaall nnootteess The MySQL configuration interface setup allows for multiple mysql databases: you can use one for a virtual table, one for an access table, and one for an aliases table if you want. Since sites that have a need for multiple mail exchangers may enjoy the convenience of using a networked mailer database, but do not want to introduce a single point of failure to their system, we've included the ability to have Postfix reference multiple hosts for access to a single mysql map. This will work if sites set up mirrored mysql databases on two or more hosts. Whenever queries fail with an error at one host, the rest of the hosts will be tried in random order. If no mysql server hosts are reachable, then mail will be deferred until at least one of those hosts is reachable. CCrreeddiittss * The initial version was contributed by Scott Cotton and Joshua Marcus, IC Group, Inc. * Liviu Daia revised the configuration interface and added the main.cf configuration feature. * Liviu Daia with further refinements from Jose Luis Tallon and Victor Duchovni developed the common query, result_format, domain and expansion_limit interface for LDAP, MySQL and PosgreSQL. README_FILES/ADDRESS_VERIFICATION_README000066600000046731150501202770012430 0ustar00PPoossttffiixx AAddddrreessss VVeerriiffiiccaattiioonn HHoowwttoo ------------------------------------------------------------------------------- WWAARRNNIINNGG The sender/recipient address verification feature described in this document is suitable only for low-traffic sites. It performs poorly under high load; excessive sender address verification activity may even cause your site to be blacklisted by some providers. See the "Limitations" section below for details. WWhhaatt PPoossttffiixx aaddddrreessss vveerriiffiiccaattiioonn ccaann ddoo ffoorr yyoouu Address verification is a feature that allows the Postfix SMTP server to block a sender (MAIL FROM) or recipient (RCPT TO) address until the address has been verified to be deliverable. The technique has obvious uses to reject junk mail with an unreplyable sender address. The technique may also be useful to block mail for undeliverable recipients, for example on a mail relay host that does not have a list of all the valid recipient addresses. This prevents undeliverable junk mail from entering the queue, so that Postfix doesn't have to waste resources trying to send MAILER- DAEMON messages back. This feature is available in Postfix version 2.1 and later. Topics covered in this document: * How address verification works * Limitations of address verification * Recipient address verification * Sender address verification for mail from frequently forged domains * Sender address verification for all email * Address verification database * Managing the address verification database * Controlling the routing of address verification probes * Forced probe routing examples * Limitations of forced probe routing HHooww aaddddrreessss vveerriiffiiccaattiioonn wwoorrkkss A Postfix MTA verifies a sender or recipient address by probing the nearest MTA for that address, without actually delivering mail. The nearest MTA could be the Postfix MTA itself, or it could be a remote MTA (SMTP interruptus). Probe messages are like normal mail, except that they are never delivered, deferred or bounced; probe messages are always discarded. Postfix Postfix Address Internet -> SMTP <-> verify <-> verification server server database | ^ probe delivery messages status v | Postfix Postfix queue -> delivery agents With Postfix address verification turned on, normal mail will suffer only a short delay of up to 6 seconds while an address is being verified for the first time. Once an address status is known, the status is cached and Postfix replies immediately. When verification takes too long the Postfix SMTP server defers the sender or recipient address with a 450 reply. Normal mail clients will connect again after some delay. The address verification delay is configurable with the main.cf address_verify_poll_count and address_verify_poll_delay parameters. See postconf(5) for details. LLiimmiittaattiioonnss ooff aaddddrreessss vveerriiffiiccaattiioonn * When verifying a remote address, Postfix probes the nearest MTA for that address, without actually delivering mail to it. If the nearest MTA accepts the address, then Postfix assumes that the address is deliverable. In reality, mail for a remote address can bounce AFTER the nearest MTA accepts the recipient address. * Some sites may blacklist you when you are probing them too often (a probe is an SMTP session that does not deliver mail), or when you are probing them too often for a non-existent address. This is one reason why you should use sender address verification sparingly, if at all, when your site receives lots of email. * Normally, address verification probe messages follow the same path as regular mail. However, some sites send mail to the Internet via an intermediate relayhost; this breaks address verification. See below, section "Controlling the routing of address verification probes", for how to override mail routing and for possible limitations when you have to do this. * Postfix assumes that an address is undeliverable when the nearest MTA for the address rejects the probe, regardless of the reason for rejection (client rejected, HELO rejected, MAIL FROM rejected, etc.). Thus, Postfix rejects mail when the sender's MTA rejects mail from your machine. This is a good thing. * Unfortunately, some major sites such as YAHOO do not reject unknown addresses in reply to the RCPT TO command, but report a delivery failure in response to end of DATA after a message is transferred. Postfix address verification does not work with such sites. * By default, Postfix probe messages have "double-bounce@$myorigin" as the sender address (with Postfix versions before 2.5, the default is "postmaster@$myorigin"). This is SAFE because the Postfix SMTP server does not reject mail for this address. You can change this into the null address ("address_verify_sender ="). This is UNSAFE because address probes will fail with mis-configured sites that reject MAIL FROM: <>, while probes from "postmaster@$myorigin" would succeed. RReecciippiieenntt aaddddrreessss vveerriiffiiccaattiioonn As mentioned earlier, recipient address verification may be useful to block mail for undeliverable recipients on a mail relay host that does not have a list of all valid recipient addresses. This can help to prevent the mail queue from filling up with MAILER-DAEMON messages. Recipient address verification is relatively straightforward and there are no surprises. If a recipient probe fails, then Postfix rejects mail for the recipient address. If a recipient probe succeeds, then Postfix accepts mail for the recipient address. However, recipient address verification probes can increase the load on down-stream MTAs when you're being flooded by backscatter bounces, or when some spammer is mounting a dictionary attack. By default, address verification results are not saved. To avoid probing the same address repeatedly, you can store the result in a persistent database as described later. /etc/postfix/main.cf: smtpd_recipient_restrictions = permit_mynetworks reject_unauth_destination ... reject_unknown_recipient_domain reject_unverified_recipient ... # Postfix 2.6 and later privacy feature. # unverified_recipient_reject_reason = Address lookup failed The "reject_unknown_recipient_domain" restriction blocks mail for non-existent domains. Putting this before "reject_unverified_recipient" avoids the overhead of generating unnecessary probe messages. The unverified_recipient_reject_code parameter (default 450) specifies the numerical Postfix SMTP server reply code when a recipient address is known to bounce. Change this setting into 550 when you trust Postfix's judgments. The following features are available in Postfix 2.6 and later. The unverified_recipient_defer_code parameter (default 450) specifies the numerical Postfix SMTP server reply code when a recipient address probe fails with some temporary error. Some sites insist on changing this into 250. NOTE: This change turns MX servers into backscatter sources when the load is high. The unverified_recipient_reject_reason parameter (default: empty) specifies fixed text that Postfix will send to remote SMTP clients, instead of sending actual address verification details. Do not specify the SMTP status code or enhanced status code. The unverified_recipient_tempfail_action parameter (default: defer_if_permit) specifies the Postfix SMTP server action when a recipient address verification probe fails with some temporary error. SSeennddeerr aaddddrreessss vveerriiffiiccaattiioonn ffoorr mmaaiill ffrroomm ffrreeqquueennttllyy ffoorrggeedd ddoommaaiinnss Only for very small sites, it is relatively safe to turn on sender address verification for specific domains that often appear in forged email. /etc/postfix/main.cf: smtpd_sender_restrictions = hash:/etc/postfix/sender_access unverified_sender_reject_code = 550 # Postfix 2.6 and later. # unverified_sender_defer_code = 250 # Note 1: Be sure to read the "Caching" section below! # Note 2: Avoid hash files here. Use btree instead. address_verify_map = btree:/var/lib/postfix/verify /etc/postfix/sender_access: aol.com reject_unverified_sender hotmail.com reject_unverified_sender bigfoot.com reject_unverified_sender ... etcetera ... At some point in cyberspace/time, a list of frequently forged MAIL FROM domains could be found at http://www.monkeys.com/anti-spam/filtering/sender-domain- validate.in. NOTE: One of the first things you might want to do is to turn on sender address verification for all your own domains. SSeennddeerr aaddddrreessss vveerriiffiiccaattiioonn ffoorr aallll eemmaaiill Unfortunately, sender address verification cannot simply be turned on for all email - you are likely to lose legitimate mail from mis-configured systems. You almost certainly will have to set up white lists for specific addresses, or even for entire domains. To find out how sender address verification would affect your mail, specify "warn_if_reject reject_unverified_sender" so that you can see what mail would be blocked: /etc/postfix/main.cf: smtpd_sender_restrictions = permit_mynetworks ... check_sender_access hash:/etc/postfix/sender_access reject_unknown_sender_domain warn_if_reject reject_unverified_sender ... # Postfix 2.6 and later. # unverified_sender_reject_reason = Address verification failed # Note 1: Be sure to read the "Caching" section below! # Note 2: Avoid hash files here. Use btree instead. address_verify_map = btree:/var/lib/postfix/verify This is also a good way to populate your cache with address verification results before you start to actually reject mail. The sender_access restriction is needed to whitelist domains or addresses that are known to be OK. Although Postfix will not mark a known-to-be-good address as bad after a probe fails, it is better to be safe than sorry. NOTE: You will have to whitelist sites such as securityfocus.com and other sites that operate mailing lists that use a different sender address for each posting (VERP). Such addresses pollute the address verification cache quickly, and generate unnecessary sender verification probes. /etc/postfix/sender_access securityfocus.com OK ... The "reject_unknown_sender_domain" restriction blocks mail from non-existent domains. Putting this before "reject_unverified_sender" avoids the overhead of generating unnecessary probe messages. The unverified_sender_reject_code parameter (default 450) specifies the numerical Postfix server reply code when a sender address is known to bounce. Change this setting into 550 when you trust Postfix's judgments. The following features are available in Postfix 2.6 and later. The unverified_sender_defer_code parameter (default 450) specifies the numerical Postfix SMTP server reply code when a sender address verification probe fails with some temporary error. Specify a valid 2xx or 4xx code. The unverified_sender_reject_reason parameter (default: empty) specifies fixed text that Postfix will send to remote SMTP clients, instead of sending actual addres verification details. Do not specify the SMTP status code or enhanced status code. The unverified_sender_tempfail_action parameter (default: defer_if_permit) specifies the Postfix SMTP server action when a sender address verification probe fails with some temporary error. AAddddrreessss vveerriiffiiccaattiioonn ddaattaabbaassee NOTE: By default, address verification information is not stored in a persistent file. You have to specify one in main.cf (see below). Persistent storage is off by default because it may need more disk space than is available in your file system. Address verification information is cached by the Postfix verify daemon. Postfix has a bunch of parameters that control the caching of positive and negative results. Refer to the verify(8) manual page for details. The address_verify_map (NOTE: singular) configuration parameter specifies an optional database for sender or recipient address verification results. If you don't specify a file, all address verification information is lost after "postfix reload" or "postfix stop". If your /var file system has sufficient space, try: /etc/postfix/main.cf: # Note: avoid hash files here. Use btree instead. address_verify_map = btree:/var/lib/postfix/verify NOTE 1: As of version 2.5, Postfix no longer uses root privileges when opening this file. The file should now be stored under the Postfix-owned data_directory. As a migration aid, an attempt to open the file under a non- Postfix directory is redirected to the Postfix-owned data_directory, and a warning is logged. If you wish to continue using a pre-existing database file, move it to the data_directory, and change ownership to the account specified with the mail_owner parameter. NOTE 2: Do not put this file in a file system that may run out of space. When the address verification table gets corrupted the world comes to an end and YOU will have to MANUALLY fix things as described in the next section. Meanwhile, you will not receive mail via SMTP. NOTE 3: The verify(8) daemon process will create a new database when none exists, and will open/create the file before it enters the chroot jail. MMaannaaggiinngg tthhee aaddddrreessss vveerriiffiiccaattiioonn ddaattaabbaassee The verify(8) manual page describes parameters that control how long information remains cached before it needs to be refreshed, and how long information can remain "unrefreshed" before it expires. Postfix uses different controls for positive results (address was accepted) and for negative results (address was rejected). Right now, no tools are provided to manage the address verification database. If the file gets too big, or if it gets corrupted, you can manually rename or delete the file and run "postfix reload". The new verify daemon process will then create a new database. CCoonnttrroolllliinngg tthhee rroouuttiinngg ooff aaddddrreessss vveerriiffiiccaattiioonn pprroobbeess By default, Postfix sends address verification probe messages via the same route as regular mail, because that normally produces the most accurate result. It's no good to verify a local address by connecting to your own SMTP port; that just triggers all kinds of mailer loop alarms. The same is true for any destination that your machine is best MX host for: hidden domains, virtual domains, etc. However, some sites have a complex infrastructure where mail is not sent directly to the Internet, but is instead given to an intermediate relayhost. This is a problem for address verification, because remote Internet addresses can be verified only when Postfix can access remote destinations directly. For this reason, Postfix allows you to override the routing parameters when it delivers an address verification probe message. First, the address_verify_relayhost parameter allows you to override the relayhost setting, and the address_verify_transport_maps parameter allows you to override the transport_maps setting. The address_verify_sender_dependent_relayhost_maps parameter does the same for sender-dependent relayhost selection. Second, each address class is given its own address verification version of the message delivery transport, as shown in the table below. Address classes are defined in the ADDRESS_CLASS_README file. _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |DDoommaaiinn lliisstt |RReegguullaarr ttrraannssppoorrtt|VVeerriiffyy ttrraannssppoorrtt | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |mydestination |local_transport |address_verify_local_transport | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |virtual_alias_domains |(not applicable) |(not applicable) | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |virtual_mailbox_domains|virtual_transport|address_verify_virtual_transport| |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |relay_domains |relay_transport |address_verify_relay_transport | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |(not applicable) |default_transport|address_verify_default_transport| |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | By default, the parameters that control delivery of address probes have the same value as the parameters that control normal mail delivery. FFoorrcceedd pprroobbee rroouuttiinngg eexxaammpplleess In a typical scenario one would override the relayhost setting for address verification probes and leave everything else alone: /etc/postfix/main.cf: relayhost = $mydomain address_verify_relayhost = ... Sites behind a network address translation box might have to use a different SMTP client that sends the correct hostname information: /etc/postfix/main.cf: relayhost = $mydomain address_verify_relayhost = address_verify_default_transport = direct_smtp /etc/postfix/master.cf: direct_smtp .. .. .. .. .. .. .. .. .. smtp -o smtp_helo_name=nat.box.tld LLiimmiittaattiioonnss ooff ffoorrcceedd pprroobbee rroouuttiinngg Inconsistencies can happen when probe messages don't follow the same path as regular mail. For example, a message can be accepted when it follows the regular route while an otherwise identical probe message is rejected when it follows the forced route. The opposite can happen, too, but is less likely. README_FILES/DSN_README000066600000010517150501202770010016 0ustar00PPoossttffiixx DDSSNN SSuuppppoorrtt ------------------------------------------------------------------------------- IInnttrroodduuccttiioonn Postfix version 2.3 introduces support for Delivery Status Notifications as described in RFC 3464. This gives senders control over successful and failed delivery notifications. Specifically, DSN support gives an email sender the ability to specify: * What notifications are sent: success, failure, delay, or none. Normally, Postfix informs the sender only when mail delivery is delayed or when delivery fails. * What content is returned in case of failure: only the message headers, or the full message. * An envelope ID that is returned as part of delivery status notifications. This identifies the message submission transaction, and must not be confused with the message ID, which identifies the message content. The implementation of DSN support involves extra parameters to the SMTP MAIL FROM and RCPT TO commands, as well as two Postfix sendmail command line options that provide a sub-set of the functions of the extra SMTP command parameters. This document has information on the following topics: * Restricting the scope of "success" notifications * Postfix sendmail command-line interface * Postfix VERP support compatibility RReessttrriiccttiinngg tthhee ssccooppee ooff ""ssuucccceessss"" nnoottiiffiiccaattiioonnss Just like reports of undeliverable mail, DSN reports of successful delivery can give away more information about the internal infrastructure than desirable. Unfortunately, disallowing "success" notification requests requires disallowing other DSN requests as well. The RFCs do not offer the option to negotiate feature subsets. This is not as bad as it sounds. When you turn off DSN for remote inbound mail, remote senders with DSN support will still be informed that their mail reached your Postfix gateway successfully; they just will not get successful delivery notices from your internal systems. Remote senders lose very little: they can no longer specify how Postfix should report delayed or failed delivery. Use the smtpd_discard_ehlo_keyword_address_maps feature if you wish to allow DSN requests from trusted clients but not from random strangers (see below for how to turn this off for all clients): /etc/postfix/main.cf: smtpd_discard_ehlo_keyword_address_maps = cidr:/etc/postfix/esmtp_access /etc/postfix/esmtp_access: # Allow DSN requests from local subnet only 192.168.0.0/28 silent-discard 0.0.0.0/0 silent-discard, dsn ::/0 silent-discard, dsn If you want to disallow all use of DSN requests from the network, use the smtpd_discard_ehlo_keywords feature: /etc/postfix/main.cf: smtpd_discard_ehlo_keywords = silent-discard, dsn PPoossttffiixx sseennddmmaaiill ccoommmmaanndd--lliinnee iinntteerrffaaccee Postfix has two Sendmail-compatible command-line options for DSN support. * The first option specifies what notifications are sent for mail that is submitted via the Postfix sendmail(1) command line: $ sseennddmmaaiill --NN ssuucccceessss,,ddeellaayy,,ffaaiilluurree ...... (one or more of these) $ sseennddmmaaiill --NN nneevveerr ...... (or just this by itself) The built-in default corresponds with "delay,failure". * The second option specifies an envelope ID which is reported in delivery status notifications for mail that is submitted via the Postfix sendmail(1) command line: $ sseennddmmaaiill --VV eennvveellooppee--iidd ...... Note: this conflicts with VERP support in older Postfix versions, as discussed in the next section. PPoossttffiixx VVEERRPP ssuuppppoorrtt ccoommppaattiibbiilliittyy With Postfix versions before 2.3, the sendmail(1) command uses the -V command- line option to request VERP-style delivery. In order to request VERP style delivery with Postfix 2.3 and later, you must specify -XV instead of -V. The Postfix 2.3 sendmail(1) command will recognize if you try to use -V for VERP-style delivery. It will do the right thing and will remind you of the new syntax. README_FILES/ULTRIX_README000066600000003722150501202770010421 0ustar00PPoossttffiixx aanndd UUllttrriixx ------------------------------------------------------------------------------- PPoossttffiixx oonn UUllttrriixx This document is probably only of historical value, because Ultrix version 4 dates from the early 1990s. However, as long as Wietse keeps Postfix alive for SunOS 4, it is likely to run on Ultrix 4 with very little change. Feedback is welcome if anyone actually still uses Postfix on any version of Ultrix. The source of this document is an email message by Christian von Roques that was sent on Jun 2, 1999. I've upgraded the MTA of our DECstation-3100 running Ultrix4.3a to postfix- 19990317-pl05 and am sending you the patches I needed to get it running under Ultrix. . . . One of the bugs of Ultrix's /bin/sh is that shell-variables set in arguments of `:' expand to garbage if expanded in here-documents. Using a different shell helps. I needed to replace all calls of ``sh .../makedefs'' by ``$(SHELL) .../makedefs'' in all the Makefile.in and am now able to use ``make SHELL=/bin/sh5'' or zsh. . . . Ultrix's FD_SET_SIZE is 4096, but getdtablesize() returns 64 by default, if not increased when building a new kernel. getrlimit() doesn't know RLIMIT_NOFILE. This makes event_init() always log the warning: `could allocate space for only 64 open files'. I just reduced the threshold from 256 to 64, but this is not good. The initial problem still remains: How to disable this warning on Ultrix without making the source ugly? To work around the first problem, all the Makefile.in files have been updated to use `$(SHELL)' instead of `sh'. So you only need to supply a non-default shell in order to eliminate Ultrix shell trouble. To work around the latter, util/sys_defs.h was updated for Ultrix, with a default FD_SETSIZE of 100. This should be sufficient for a workstation. Even in 1999, no-one would run a major mail hub on Ultrix 4. README_FILES/AAAREADME000066600000005320150501202770007611 0ustar00 PPoossttffiixx DDooccuummeennttaattiioonn ------------------------------------------------------------------------------- GGeenneerraall ccoonnffiigguurraattiioonn * BASIC_CONFIGURATION_README: Basic configuration * SOHO_README: Small/home office hints and tips * STANDARD_CONFIGURATION_README: Standard configuration examples * ADDRESS_REWRITING_README: Address rewriting * VIRTUAL_README: Virtual domain hosting * SASL_README: SASL Authentication * TLS_README: TLS Encryption and authentication * TLS_LEGACY_README: Legacy TLS support * IPV6_README: IP Version 6 Support * MULTI_INSTANCE_README: Multiple-instance management * INSTALL: Installation from source code PPrroobblleemm ssoollvviinngg * QSHAPE_README: Bottleneck analysis * STRESS_README: Stress-dependent configuration * TUNING_README: Performance tuning * DEBUG_README: Debugging strategies CCoonntteenntt iinnssppeeccttiioonn * CONTENT_INSPECTION_README: Content inspection overview * BACKSCATTER_README: Stopping backscatter mail * BUILTIN_FILTER_README: Built-in content inspection * FILTER_README: After-queue content filter * SMTPD_PROXY_README: Before-queue content filter * MILTER_README: Before-queue Milter applications SSMMTTPP RReellaayy aanndd aacccceessss ccoonnttrrooll * SMTPD_ACCESS_README: Relay/access control overview * SMTPD_POLICY_README: Access policy delegation * ADDRESS_VERIFICATION_README: Address verification * RESTRICTION_CLASS_README: Per-client/user/etc. access * ETRN_README: ETRN Support * UUCP_README: LAN connected via UUCP LLooookkuupp ttaabblleess ((ddaattaabbaasseess)) * DATABASE_README: Lookup table overview * DB_README: Berkeley DB Howto * CDB_README: CDB Howto * LDAP_README: LDAP Howto * MYSQL_README: MySQL Howto * PCRE_README: PCRE Howto * PGSQL_README: PostgreSQL Howto MMaaiilliinngg lliisstt ssuuppppoorrtt * VERP_README: VERP Support SSppeecciiffiicc eennvviirroonnmmeennttss * LINUX_README: Linux issues * NFS_README: NFS issues OOtthheerr mmaaiill ddeelliivveerryy aaggeennttss * MAILDROP_README: Maildrop OOtthheerr ttooppiiccss * OVERVIEW: Architecture overview * postconf(5): All main.cf parameters * LOCAL_RECIPIENT_README: Rejecting Unknown Local Recipients * ADDRESS_CLASS_README: Address Classes * CONNECTION_CACHE_README: Connection cache howto * DSN_README: Postfix DSN support * PACKAGE_README: Guidelines for Package Builders * SCHEDULER_README: Queue Scheduler * XCLIENT_README: XCLIENT Command * XFORWARD_README: XFORWARD Command README_FILES/ADDRESS_REWRITING_README000066600000125270150501202770012114 0ustar00PPoossttffiixx AAddddrreessss RReewwrriittiinngg ------------------------------------------------------------------------------- PPoossttffiixx aaddddrreessss rreewwrriittiinngg ppuurrppoossee Address rewriting is at the heart of the Postfix mail system. Postfix rewrites addresses for many different purposes. Some are merely cosmetic, and some are necessary to deliver correctly formatted mail to the correct destination. Examples of address rewriting in Postfix are: * Transform an incomplete address into a complete address. For example, transform "username" into "username@example.com", or transform "username@hostname" into "username@hostname.example.com". * Replace an address by an equivalent address. For example, replace "username@example.com" by "firstname.lastname@example.com" when sending mail, and do the reverse transformation when receiving mail. * Replace an internal address by an external address. For example, replace "username@localdomain.local" by "isp-account@isp.example" when sending mail from a home computer to the Internet. * Replace an address by multiple addresses. For example, replace the address of an alias by the addresses listed under that alias. * Determine how and where to deliver mail for a specific address. For example, deliver mail for "username@example.com" with the smtp(8) delivery agent, to the hosts that are listed in the DNS as the mail servers for the domain "example.com". Although Postfix currently has no address rewriting language, it can do surprisingly powerful address manipulation via table lookup. Postfix typically uses lookup tables with fixed strings to map one address to one or multiple addresses, and typically uses regular expressions to map multiple addresses to one or multiple addresses. Fixed-string lookup tables may be in the form of local files, or in the form of NIS, LDAP or SQL databases. The DATABASE_README document gives an introduction to Postfix lookup tables. Topics covered in this document: * To rewrite message headers or not, or to label as invalid * Postfix address rewriting overview * Address rewriting when mail is received o Rewrite addresses to standard form o Canonical address mapping o Address masquerading o Automatic BCC recipients o Virtual aliasing * Address rewriting when mail is delivered o Resolve address to destination o Mail transport switch o Relocated users table * Address rewriting with remote delivery o Generic mapping for outgoing SMTP mail * Address rewriting with local delivery o Local alias database o Local per-user .forward files o Local catch-all address * Debugging your address manipulations TToo rreewwrriittee mmeessssaaggee hheeaaddeerrss oorr nnoott,, oorr ttoo llaabbeell aass iinnvvaalliidd Postfix versions 2.1 and earlier always rewrite message header addresses, and append Postfix's own domain information to addresses that Postfix considers incomplete. While rewriting message header addresses is OK for mail with a local origin, it is undesirable for remote mail: * Message header address rewriting is frowned upon by mail standards, * Appending Postfix's own domain produces incorrect results with some incomplete addresses, * Appending Postfix's own domain sometimes creates the appearance that spam is sent by local users. Postfix versions 2.2 give you the option to either not rewrite message headers from remote SMTP clients at all, or to label incomplete addresses in such message headers as invalid. Here is how it works: * Postfix always rewrites message headers from local SMTP clients and from the Postfix sendmail command, and appends its own domain to incomplete addresses. The local_header_rewrite_clients parameter controls what SMTP clients Postfix considers local (by default, only local network interface addresses). * Postfix never rewrites message header addresses from remote SMTP clients when the remote_header_rewrite_domain parameter value is empty (the default setting). * Otherwise, Postfix rewrites message headers from remote SMTP clients, and appends the remote_header_rewrite_domain value to incomplete addresses. This feature can be used to append a reserved domain such as "domain.invalid", so that incomplete addresses cannot be mistaken for local addresses. PPoossttffiixx aaddddrreessss rreewwrriittiinngg oovveerrvviieeww The figure below zooms in on those parts of Postfix that are most involved with address rewriting activity. See the OVERVIEW document for an overview of the complete Postfix architecture. Names followed by a number are Postfix daemon programs, while unnumbered names represent Postfix queues or internal sources of mail messages. trivial- trivial- rewrite(8) rewrite(8) (std form) (resolve) ^ | ^ | | v | v smtpd(8) smtp(8) qmqpd(8) >- cleanup(8) -> incoming -> active -> qmgr(8) -< lmtp(8) pickup(8) local(8) ^ ^ | | | v bounces forwarding deferred notices The table below summarizes all Postfix address manipulations. If you're reading this document for the first time, skip forward to "Address rewriting when mail is received". Once you've finished reading the remainder of this document, the table will help you to quickly find what you need. _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |AAddddrreessss |SSccooppee |DDaaeemmoonn |GGlloobbaall ttuurrnn--oonn |SSeelleeccttiivvee ttuurrnn--ooffff ccoonnttrrooll | |mmaanniippuullaattiioonn| | |ccoonnttrrooll | | |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |Rewrite | |trivial-|append_at_myorigin, | | |addresses to|all mail|rewrite |append_dot_mydomain,|local_header_rewrite_clients,| |standard | |(8) |swap_bangpath, |remote_header_rewrite_domain | |form | | |allow_percent_hack | | |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |Canonical | |cleanup | |receive_override_options, | |address |all mail|(8) |canonical_maps |local_header_rewrite_clients,| |mapping | | | |remote_header_rewrite_domain | |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |Address | |cleanup | |receive_override_options, | |masquerading|all mail|(8) |masquerade_domains |local_header_rewrite_clients,| | | | | |remote_header_rewrite_domain | |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |Automatic | |cleanup |always_bcc, | | |BCC |new mail|(8) |sender_bcc_maps, |receive_override_options | |recipients | | |recipient_bcc_maps | | |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |Virtual |all mail|cleanup |virtual_alias_maps |receive_override_options | |aliasing | |(8) | | | |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |Resolve | |trivial-| | | |address to |all mail|rewrite |none |none | |destination | |(8) | | | |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |Mail | |trivial-| | | |transport |all mail|rewrite |transport_maps |none | |switch | |(8) | | | |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |Relocated | |trivial-| | | |users table |all mail|rewrite |relocated_maps |none | | | |(8) | | | |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |Generic |outgoing| | | | |mapping |SMTP |smtp(8) |smtp_generic_maps |none | |table |mail | | | | |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |Local alias |local | | | | |database |mail |local(8)|alias_maps |none | | |only | | | | |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |Local per- |local | | | | |user |mail |local(8)|forward_path |none | |.forward |only | | | | |files | | | | | |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |Local catch-|local | | | | |all address |mail |local(8)|luser_relay |none | | |only | | | | |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | AAddddrreessss rreewwrriittiinngg wwhheenn mmaaiill iiss rreecceeiivveedd The cleanup(8) server receives mail from outside of Postfix as well as mail from internal sources such as forwarded mail, undeliverable mail that is bounced to the sender, and postmaster notifications about problems with the mail system. The cleanup(8) server transforms the sender, recipients and message content into a standard form before writing it to an incoming queue file. The server cleans up sender and recipient addresses in message headers and in the envelope, adds missing message headers such as From: or Date: that are required by mail standards, and removes message headers such as Bcc: that should not be present. The cleanup(8) server delegates the more complex address manipulations to the trivial-rewrite(8) server as described later in this document. Address manipulations at this stage are: * Rewrite addresses to standard form * Canonical address mapping * Address masquerading * Automatic BCC recipients * Virtual aliasing RReewwrriittee aaddddrreesssseess ttoo ssttaannddaarrdd ffoorrmm Before the cleanup(8) daemon runs an address through any address mapping lookup table, it first rewrites the address to the standard "user@fully.qualified.domain" form, by sending the address to the trivial- rewrite(8) daemon. The purpose of rewriting to standard form is to reduce the number of entries needed in lookup tables. The Postfix trivial-rewrite(8) daemon implements the following hard-coded address manipulations: Rewrite "@hosta,@hostb:user@site" to "user@site" In case you wonder what this is, the address form above is called a route address, and specifies that mail for "user@site" be delivered via "hosta" and "hostb". Usage of this form has been deprecated for a long time. Postfix has no ability to handle route addresses, other than to strip off the route part. NOTE: Postfix versions 2.2 and later rewrite message headers from remote SMTP clients only if the client matches the local_header_rewrite_clients parameter, or if the remote_header_rewrite_domain configuration parameter specifies a non- empty value. To get the behavior before Postfix 2.2, specify "local_header_rewrite_clients = static:all". Rewrite "site!user" to "user@site" This feature is controlled by the boolean swap_bangpath parameter (default: yes). The purpose is to rewrite UUCP-style addresses to domain style. This is useful only when you receive mail via UUCP, but it probably does not hurt otherwise. NOTE: Postfix versions 2.2 and later rewrite message headers from remote SMTP clients only if the client matches the local_header_rewrite_clients parameter, or if the remote_header_rewrite_domain configuration parameter specifies a non- empty value. To get the behavior before Postfix 2.2, specify "local_header_rewrite_clients = static:all". Rewrite "user%domain" to "user@domain" This feature is controlled by the boolean allow_percent_hack parameter (default: yes). Typically, this is used in order to deal with monstrosities such as "user%domain@otherdomain". NOTE: Postfix versions 2.2 and later rewrite message headers from remote SMTP clients only if the client matches the local_header_rewrite_clients parameter, or if the remote_header_rewrite_domain configuration parameter specifies a non- empty value. To get the behavior before Postfix 2.2, specify "local_header_rewrite_clients = static:all". Rewrite "user" to "user@$myorigin" This feature is controlled by the boolean append_at_myorigin parameter (default: yes). You should never turn off this feature, because a lot of Postfix components expect that all addresses have the form "user@domain". NOTE: Postfix versions 2.2 and later rewrite message headers from remote SMTP clients only if the client matches the local_header_rewrite_clients parameter; otherwise they append the domain name specified with the remote_header_rewrite_domain configuration parameter, if one is specified. To get the behavior before Postfix 2.2, specify "local_header_rewrite_clients = static: all". If your machine is not the main machine for $myorigin and you wish to have some users delivered locally without going via that main machine, make an entry in the virtual alias table that redirects "user@$myorigin" to "user@$myhostname". See also the "delivering some users locally" section in the STANDARD_CONFIGURATION_README document. Rewrite "user@host" to "user@host.$mydomain" This feature is controlled by the boolean append_dot_mydomain parameter (default: yes). The purpose is to get consistent treatment of different forms of the same hostname. NOTE: Postfix versions 2.2 and later rewrite message headers from remote SMTP clients only if the client matches the local_header_rewrite_clients parameter; otherwise they append the domain name specified with the remote_header_rewrite_domain configuration parameter, if one is specified. To get the behavior before Postfix 2.2, specify "local_header_rewrite_clients = static: all". Some will argue that rewriting "host" to "host.domain" is bad. That is why it can be turned off. Others like the convenience of having Postfix's own domain appended automatically. Rewrite "user@site." to "user@site" (without the trailing dot). A single trailing dot is silently removed. However, an address that ends in multiple dots will be rejected as an invalid address. NOTE: Postfix versions 2.2 and later rewrite message headers from remote SMTP clients only if the client matches the local_header_rewrite_clients parameter, or if the remote_header_rewrite_domain configuration parameter specifies a non- empty value. To get the behavior before Postfix 2.2, specify "local_header_rewrite_clients = static:all". CCaannoonniiccaall aaddddrreessss mmaappppiinngg The cleanup(8) daemon uses the canonical(5) tables to rewrite addresses in message envelopes and in message headers. By default all header and envelope addresses are rewritten; this is controlled with the canonical_classes configuration parameter. NOTE: Postfix versions 2.2 and later rewrite message headers from remote SMTP clients only if the client matches the local_header_rewrite_clients parameter, or if the remote_header_rewrite_domain configuration parameter specifies a non- empty value. To get the behavior before Postfix 2.2, specify "local_header_rewrite_clients = static:all". Address rewriting is done for local and remote addresses. The mapping is useful to replace login names by "Firstname.Lastname" style addresses, or to clean up invalid domains in mail addresses produced by legacy mail systems. Canonical mapping is disabled by default. To enable, edit the canonical_maps parameter in the main.cf file and specify one or more lookup tables, separated by whitespace or commas. Example: /etc/postfix/main.cf: canonical_maps = hash:/etc/postfix/canonical /etc/postfix/canonical: wietse Wietse.Venema For static mappings as shown above, lookup tables such as hash:, ldap:, mysql: or pgsql: are sufficient. For dynamic mappings you can use regular expression tables. This requires that you become intimately familiar with the ideas expressed in regexp_table(5), pcre_table(5) and canonical(5). In addition to the canonical maps which are applied to both sender and recipient addresses, you can specify canonical maps that are applied only to sender addresses or to recipient addresses. Example: /etc/postfix/main.cf: sender_canonical_maps = hash:/etc/postfix/sender_canonical recipient_canonical_maps = hash:/etc/postfix/recipient_canonical The sender and recipient canonical maps are applied before the common canonical maps. The sender_canonical_classes and recipient_canonical_classes parameters control what addresses are subject to sender_canonical_maps and recipient_canonical_maps mappings, respectively. Sender-specific rewriting is useful when you want to rewrite ugly sender addresses to pretty ones, and still want to be able to send mail to the those ugly address without creating a mailer loop. Canonical mapping can be turned off selectively for mail received by smtpd(8), qmqpd(8), or pickup(8), by overriding main.cf settings in the master.cf file. This feature is available in Postfix version 2.1 and later. Example: /etc/postfix/master.cf: :10026 inet n - n - - smtpd -o receive_override_options=no_address_mappings Note: do not specify whitespace around the "=" here. AAddddrreessss mmaassqquueerraaddiinngg Address masquerading is a method to hide hosts inside a domain behind their mail gateway, and to make it appear as if the mail comes from the gateway itself, instead of from individual machines. NOTE: Postfix versions 2.2 and later rewrite message headers from remote SMTP clients only if the client matches the local_header_rewrite_clients parameter, or if the remote_header_rewrite_domain configuration parameter specifies a non- empty value. To get the behavior before Postfix 2.2, specify "local_header_rewrite_clients = static:all". Address masquerading is disabled by default, and is implemented by the cleanup (8) server. To enable, edit the masquerade_domains parameter in the main.cf file and specify one or more domain names separated by whitespace or commas. When Postfix tries to masquerade a domain, it processes the list from left to right, and processing stops at the first match. Example: /etc/postfix/main.cf: masquerade_domains = foo.example.com example.com strips "any.thing.foo.example.com" to "foo.example.com", but strips "any.thing.else.example.com" to "example.com". A domain name prefixed with "!" means do not masquerade this domain or its subdomains: /etc/postfix/main.cf: masquerade_domains = !foo.example.com example.com does not change "any.thing.foo.example.com" and "foo.example.com", but strips "any.thing.else.example.com" to "example.com". The masquerade_exceptions configuration parameter specifies what user names should not be subjected to address masquerading. Specify one or more user names separated by whitespace or commas. Example: /etc/postfix/main.cf: masquerade_exceptions = root By default, Postfix makes no exceptions. Subtle point: by default, address masquerading is applied only to message headers and to envelope sender addresses, but not to envelope recipients. This allows you to use address masquerading on a mail gateway machine, while still being able to forward mail from outside to users on individual machines. In order to subject envelope recipient addresses to masquerading, too, specify (Postfix version 1.1 and later): /etc/postfix/main.cf: masquerade_classes = envelope_sender, envelope_recipient, header_sender, header_recipient If you rewrite the envelope recipient like this, Postfix will no longer be able to send mail to individual machines. Address masquerading can be turned off selectively for mail received by smtpd (8), qmqpd(8), or pickup(8), by overriding main.cf settings in the master.cf file. This feature is available in Postfix version 2.1 and later. Example: /etc/postfix/master.cf: :10026 inet n - n - - smtpd -o receive_override_options=no_address_mappings Note: do not specify whitespace around the "=" here. AAuuttoommaattiicc BBCCCC rreecciippiieennttss After applying the canonical and masquerade mappings, the cleanup(8) daemon can generate optional BCC (blind carbon-copy) recipients. Postfix provides three mechanisms: always_bcc = address Deliver a copy of all mail to the specified address. In Postfix versions before 2.1, this feature is implemented by smtpd(8), qmqpd(8), or pickup(8). sender_bcc_maps = type:table Search the specified "type:table" lookup table with the envelope sender address for an automatic BCC address. This feature is available in Postfix 2.1 and later. recipient_bcc_maps = type:table Search the specified "type:table" lookup table with the envelope recipient address for an automatic BCC address. This feature is available in Postfix 2.1 and later. Note: automatic BCC recipients are produced only for new mail. To avoid mailer loops, automatic BCC recipients are not generated for mail that Postfix forwards internally, nor for mail that Postfix generates itself. Automatic BCC recipients (including always_bcc) can be turned off selectively for mail received by smtpd(8), qmqpd(8), or pickup(8), by overriding main.cf settings in the master.cf file. This feature is available in Postfix version 2.1 and later. Example: /etc/postfix/master.cf: :10026 inet n - n - - smtpd -o receive_override_options=no_address_mappings Note: do not specify whitespace around the "=" here. VViirrttuuaall aalliiaassiinngg Before writing the recipients to the queue file, the cleanup(8) daemon uses the optional virtual(5) alias tables to redirect mail for recipients. The mapping affects only envelope recipient addresses; it has no effect on message headers or envelope sender addresses. Virtual alias lookups are useful to redirect mail for virtual alias domains to real user mailboxes, and to redirect mail for domains that no longer exist. Virtual alias lookups can also be used to transform " Firstname.Lastname " back into UNIX login names, although it seems that local aliases may be a more appropriate vehicle. See the VIRTUAL_README document for an overview of methods to host virtual domains with Postfix. Virtual aliasing is disabled by default. To enable, edit the virtual_alias_maps parameter in the main.cf file and specify one or more lookup tables, separated by whitespace or commas. Example: /etc/postfix/main.cf: virtual_alias_maps = hash:/etc/postfix/virtual /etc/postfix/virtual: Wietse.Venema wietse Addresses found in virtual alias maps are subjected to another iteration of virtual aliasing, but are not subjected to canonical mapping, in order to avoid loops. For static mappings as shown above, lookup tables such as hash:, ldap:, mysql: or pgsql: are sufficient. For dynamic mappings you can use regular expression tables. This requires that you become intimately familiar with the ideas expressed in regexp_table(5), pcre_table(5) and virtual(5). Virtual aliasing can be turned off selectively for mail received by smtpd(8), qmqpd(8), or pickup(8), by overriding main.cf settings in the master.cf file. This feature is available in Postfix version 2.1 and later. Example: /etc/postfix/master.cf: :10026 inet n - n - - smtpd -o receive_override_options=no_address_mappings Note: do not specify whitespace around the "=" here. At this point the message is ready to be stored into the Postfix incoming queue. AAddddrreessss rreewwrriittiinngg wwhheenn mmaaiill iiss ddeelliivveerreedd The Postfix queue manager sorts mail according to its destination and gives it to Postfix delivery agents such as local(8), smtp(8), or lmtp(8). Just like the cleanup(8) server, the Postfix queue manager delegates the more complex address manipulations to the trivial-rewrite(8) server. Address manipulations at this stage are: * Resolve address to destination * Mail transport switch * Relocated users table Each Postfix delivery agent tries to deliver the mail to its destination, while encapsulating the sender, recipients, and message content according to the rules of the SMTP, LMTP, etc. protocol. When mail cannot be delivered, it is either returned to the sender or moved to the deferred queue and tried again later. Address manipulations when mail is delivered via the smtp(8) delivery agent: * Generic mapping for outgoing SMTP mail Address manipulations when mail is delivered via the local(8) delivery agent: * Local alias database * Local per-user .forward files * Local catch-all address The remainder of this document presents each address manipulation step in more detail, with specific examples or with pointers to documentation with examples. RReessoollvvee aaddddrreessss ttoo ddeessttiinnaattiioonn The Postfix qmgr(8) queue manager selects new mail from the incoming queue or old mail from the deferred queue, and asks the trivial-rewrite(8) address rewriting and resolving daemon where it should be delivered. As of version 2.0, Postfix distinguishes four major address classes. Each class has its own list of domain names, and each class has its own default delivery method, as shown in the table below. See the ADDRESS_CLASS_README document for the fine details. Postfix versions before 2.0 only distinguish between local delivery and everything else. _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |DDeessttiinnaattiioonn ddoommaaiinn lliisstt |DDeeffaauulltt ddeelliivveerryy mmeetthhoodd|AAvvaaiillaabbiilliittyy| |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ | |$mydestination, $inet_interfaces,|$local_transport |Postfix 1.0 | |$proxy_interfaces | | | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ | |$virtual_mailbox_domains |$virtual_transport |Postfix 2.0 | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ | |$relay_domains |$relay_transport |Postfix 2.0 | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ | |none |$default_transport |Postfix 1.0 | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ | MMaaiill ttrraannssppoorrtt sswwiittcchh Once the trivial-rewrite(8) daemon has determined a default delivery method it searches the optional transport(5) table for information that overrides the message destination and/or delivery method. Typical use of the transport(5) table is to send mail to a system that is not connected to the Internet, or to use a special SMTP client configuration for destinations that have special requirements. See, for example, the STANDARD_CONFIGURATION_README and UUCP_README documents, and the examples in the transport(5) manual page. Transport table lookups are disabled by default. To enable, edit the transport_maps parameter in the main.cf file and specify one or more lookup tables, separated by whitespace or commas. Example: /etc/postfix/main.cf: transport_maps = hash:/etc/postfix/transport RReellooccaatteedd uusseerrss ttaabbllee Next, the trivial-rewrite(8) address rewriting and resolving daemon runs each recipient through the relocated(5) database. This table provides information on how to reach users that no longer have an account, or what to do with mail for entire domains that no longer exist. When mail is sent to an address that is listed in this table, the message is returned to the sender with an informative message. The relocated(5) database is searched after transport(5) table lookups, in anticipation of transport(5) tables that can replace one recipient address by a different one. Lookups of relocated users are disabled by default. To enable, edit the relocated_maps parameter in the main.cf file and specify one or more lookup tables, separated by whitespace or commas. Example: /etc/postfix/main.cf: relocated_maps = hash:/etc/postfix/relocated /etc/postfix/relocated: username@example.com otheruser@elsewhere.tld As of Postfix version 2, mail for a relocated user will be rejected by the SMTP server with the reason "user has moved to otheruser@elsewhere.tld". Older Postfix versions will receive the mail first, and then return it to the sender as undeliverable, with the same reason. GGeenneerriicc mmaappppiinngg ffoorr oouuttggooiinngg SSMMTTPP mmaaiill Some hosts have no valid Internet domain name, and instead use a name such as localdomain.local. This can be a problem when you want to send mail over the Internet, because many mail servers reject mail addresses with invalid domain names. With the smtp_generic_maps parameter you can specify generic(5) lookup tables that replace local mail addresses by valid Internet addresses when mail leaves the machine via SMTP. The generic(5) mapping replaces envelope and header addresses, and is non-recursive. It does not happen when you send mail between addresses on the local machine. This feature is available in Postfix version 2.2 and later. Example: /etc/postfix/main.cf: smtp_generic_maps = hash:/etc/postfix/generic /etc/postfix/generic: his@localdomain.local hisaccount@hisisp.example her@localdomain.local heraccount@herisp.example @localdomain.local hisaccount+local@hisisp.example When mail is sent to a remote host via SMTP, this replaces his@localdomain.local by his ISP mail address, replaces her@localdomain.local by her ISP mail address, and replaces other local addresses by his ISP account, with an address extension of +local (this example assumes that the ISP supports "+" style address extensions). LLooccaall aalliiaass ddaattaabbaassee When mail is to be delivered locally, the local(8) delivery agent runs each local recipient name through the aliases(5) database. The mapping does not affect addresses in message headers. Local aliases are typically used to implement distribution lists, or to direct mail for standard aliases such as postmaster to real people. The table can also be used to map "Firstname.Lastname" addresses to login names. Alias lookups are enabled by default. The default configuration depends on the operating system environment, but it is typically one of the following: /etc/postfix/main.cf: alias_maps = hash:/etc/aliases alias_maps = dbm:/etc/aliases, nis:mail.aliases The pathname of the alias database file is controlled with the alias_database configuration parameter. The value is system dependent. Usually it is one of the following: /etc/postfix/main.cf: alias_database = hash:/etc/aliases (4.4BSD, LINUX) alias_database = dbm:/etc/aliases (4.3BSD, SYSV<4) alias_database = dbm:/etc/mail/aliases (SYSV4) An aliases(5) file can specify that mail should be delivered to a local file, or to a command that receives the message in the standard input stream. For security reasons, deliveries to command and file destinations are performed with the rights of the alias database owner. A default userid, default_privs, is used for deliveries to commands or files in "root"-owned aliases. LLooccaall ppeerr--uusseerr ..ffoorrwwaarrdd ffiilleess With delivery via the local(8) deliver agent, users can control their own mail delivery by specifying destinations in a file called .forward in their home directories. The syntax of these files is the same as with the local aliases(5) file, except that the left-hand side of the alias (lookup key and colon) are not present. LLooccaall ccaattcchh--aallll aaddddrreessss When the local(8) delivery agent finds that a message recipient does not exist, the message is normally returned to the sender ("user unknown"). Sometimes it is desirable to forward mail for non-existing recipients to another machine. For this purpose you can specify an alternative destination with the luser_relay configuration parameter. Alternatively, mail for non-existent recipients can be delegated to an entirely different message transport, as specified with the fallback_transport configuration parameter. For details, see the local(8) delivery agent documentation. Note: if you use the luser_relay feature in order to receive mail for non-UNIX accounts, then you must specify: /etc/postfix/main.cf: local_recipient_maps = (i.e. empty) in the main.cf file, otherwise the Postfix SMTP server will reject mail for non-UNIX accounts with "User unknown in local recipient table". See the LOCAL_RECIPIENT_README file for more information on this. luser_relay can specify one address. It is subjected to "$name" expansions. Examples: $user@other.host The bare username, without address extension, is prepended to "@other.host". For example, mail for "username+foo" is sent to "username@other.host". $local@other.host The entire original recipient localpart, including address extension, is prepended to "@other.host". For example, mail for "username+foo" is sent to "username+foo@other.host". sysadmin+$user The bare username, without address extension, is appended to "sysadmin". For example, mail for "username+foo" is sent to "sysadmin+username". sysadmin+$local The entire original recipient localpart, including address extension, is appended to "sysadmin". For example, mail for "username+foo" is sent to "sysadmin+username+foo". DDeebbuuggggiinngg yyoouurr aaddddrreessss mmaanniippuullaattiioonnss Postfix version 2.1 and later can produce mail delivery reports for debugging purposes. These reports not only show sender/recipient addresses after address rewriting and alias expansion or forwarding, they also show information about delivery to mailbox, delivery to non-Postfix command, responses from remote SMTP servers, and so on. Postfix can produce two types of mail delivery reports for debugging: * What-if: report what would happen, but do not actually deliver mail. This mode of operation is requested with: $ //uussrr//ssbbiinn//sseennddmmaaiill --bbvv aaddddrreessss...... Mail Delivery Status Report will be mailed to . * What happened: deliver mail and report successes and/or failures, including replies from remote SMTP servers. This mode of operation is requested with: $ //uussrr//ssbbiinn//sseennddmmaaiill --vv aaddddrreessss...... Mail Delivery Status Report will be mailed to . These reports contain information that is generated by Postfix delivery agents. Since these run as daemon processes and do not interact with users directly, the result is sent as mail to the sender of the test message. The format of these reports is practically identical to that of ordinary non-delivery notifications. As an example, below is the delivery report that is produced with the command "sendmail -bv postfix-users@postfix.org". The first part of the report contains human-readable text. In this case, mail would be delivered via mail.cloud9.net, and the SMTP server replies with "250 Ok". Other reports may show delivery to mailbox, or delivery to non-Postfix command. Content-Description: Notification Content-Type: text/plain This is the mail system at host spike.porcupine.org. Enclosed is the mail delivery report that you requested. The mail system : delivery via mail.cloud9.net[168.100.1.4]: 250 2.1.5 Ok The second part of the report is in machine-readable form, and includes the following information: * The envelope sender address (wietse@porcupine.org). * The envelope recipient address (postfix-users@postfix.org). If the recipient address was changed by Postfix then Postfix also includes the original recipient address. * The delivery status. Some details depend on Postfix version. The example below is for Postfix version 2.3 and later. Content-Description: Delivery report Content-Type: message/delivery-status Reporting-MTA: dns; spike.porcupine.org X-Postfix-Queue-ID: 84863BC0E5 X-Postfix-Sender: rfc822; wietse@porcupine.org Arrival-Date: Sun, 26 Nov 2006 17:01:01 -0500 (EST) Final-Recipient: rfc822; postfix-users@postfix.org Action: deliverable Status: 2.1.5 Remote-MTA: dns; mail.cloud9.net Diagnostic-Code: smtp; 250 2.1.5 Ok The third part of the report contains the message that Postfix would have delivered, including From: and To: message headers, so that you can see any effects of address rewriting on those. Mail submitted with "sendmail -bv" has no body content so none is shown in the example below. Content-Description: Message Content-Type: message/rfc822 Received: by spike.porcupine.org (Postfix, from userid 1001) id 84863BC0E5; Sun, 26 Nov 2006 17:01:01 -0500 (EST) Subject: probe To: postfix-users@postfix.org Message-Id: <20061126220101.84863BC0E5@spike.porcupine.org> Date: Sun, 26 Nov 2006 17:01:01 -0500 (EST) From: wietse@porcupine.org (Wietse Venema) README_FILES/LOCAL_RECIPIENT_README000066600000013230150501202770011621 0ustar00RReejjeeccttiinngg UUnnkknnoowwnn LLooccaall RReecciippiieennttss wwiitthh PPoossttffiixx ------------------------------------------------------------------------------- IInnttrroodduuccttiioonn As of Postfix version 2.0, the Postfix SMTP server rejects mail for unknown recipients in local domains (domains that match $mydestination or the IP addresses in $inet_interfaces or $proxy_interfaces) with "User unknown in local recipient table". This feature was optional with earlier Postfix versions. The good news is that this keeps undeliverable mail out of your queue, so that your mail queue is not clogged up with undeliverable MAILER-DAEMON messages. The bad news is that it may cause mail to be rejected when you upgrade from a Postfix system that was not configured to reject mail for unknown local recipients. This document describes what steps are needed in order to reject unknown local recipients correctly. * Configuring local_recipient_maps in main.cf * When you need to change the local_recipient_maps setting in main.cf * Local recipient table format CCoonnffiigguurriinngg llooccaall__rreecciippiieenntt__mmaappss iinn mmaaiinn..ccff The local_recipient_maps parameter specifies lookup tables with all names or addresses of local recipients. A recipient address is local when its domain matches $mydestination, $inet_interfaces or $proxy_interfaces. If a local username or address is not listed in $local_recipient_maps, then the Postfix SMTP server will reject the address with "User unknown in local recipient table". The default setting, shown below, assumes that you use the default Postfix local(8) delivery agent for local delivery, where recipients are either UNIX accounts or local aliases: /etc/postfix/main.cf: local_recipient_maps = proxy:unix:passwd.byname $alias_maps To turn off unknown local recipient rejects by the SMTP server, specify: /etc/postfix/main.cf: local_recipient_maps = That is, an empty value. With this setting, the Postfix SMTP server will not reject mail with "User unknown in local recipient table". DDoonn''tt ddoo tthhiiss oonn ssyysstteemmss tthhaatt rreecceeiivvee mmaaiill ddiirreeccttllyy ffrroomm tthhee IInntteerrnneett.. WWiitthh ttooddaayy''ss wwoorrmmss aanndd vviirruusseess,, PPoossttffiixx wwiillll bbeeccoommee aa bbaacckkssccaatttteerr ssoouurrccee:: iitt aacccceeppttss mmaaiill ffoorr nnoonn-- eexxiisstteenntt rreecciippiieennttss aanndd tthheenn ttrriieess ttoo rreettuurrnn tthhaatt mmaaiill aass ""uunnddeelliivveerraabbllee"" ttoo tthhee oofftteenn ffoorrggeedd sseennddeerr aaddddrreessss. WWhheenn yyoouu nneeeedd ttoo cchhaannggee tthhee llooccaall__rreecciippiieenntt__mmaappss sseettttiinngg iinn mmaaiinn..ccff * Problem: you don't use the default Postfix local(8) delivery agent for domains matching $mydestination, $inet_interfaces, or $proxy_interfaces. For example, you redefined the "local_transport" setting in main.cf. Solution: your local_recipient_maps setting needs to specify a database that lists all the known user names or addresses for that delivery agent. For example, if you deliver users in $mydestination etc. domains via the virtual(8) delivery agent, specify: /etc/postfix/main.cf mydestination = $myhostname localhost.$mydomain localhost ... local_transport = virtual local_recipient_maps = $virtual_mailbox_maps If you use a different delivery agent for $mydestination etc. domains, see the section "Local recipient table format" below for a description of how the table should be populated. * Problem: you use the mailbox_transport or fallback_transport feature of the Postfix local(8) delivery agent in order to deliver mail to non-UNIX accounts. Solution: you need to add the database that lists the non-UNIX users: /etc/postfix/main.cf local_recipient_maps = proxy:unix:passwd.byname, $alias_maps, See the section "Local recipient table format" below for a description of how the table should be populated. * Problem: you use the luser_relay feature of the Postfix local delivery agent. Solution: you must disable the local_recipient_maps feature completely, so that Postfix accepts mail for all local addresses: /etc/postfix/main.cf local_recipient_maps = LLooccaall rreecciippiieenntt ttaabbllee ffoorrmmaatt If you use local files in postmap(1) format, then local_recipient_maps expects the following table format: * In the left-hand side, specify a bare username, an "@domain.tld" wild-card, or specify a complete "user@domain.tld" address. * You have to specify something on the right-hand side of the table, but the value is ignored by local_recipient_maps. If you use lookup tables based on NIS, LDAP, MYSQL, or PGSQL, then local_recipient_maps does the same queries as for local files in postmap(1) format, and expects the same results. With regular expression tables, Postfix only queries with the full recipient address, and not with the bare username or the "@domain.tld" wild-card. NOTE: a lookup table should always return a result when the address exists, and should always return "not found" when the address does not exist. In particular, a zero-length result does not count as a "not found" result. README_FILES/IPV6_README000066600000027352150501202770010123 0ustar00PPoossttffiixx IIPPvv66 SSuuppppoorrtt ------------------------------------------------------------------------------- IInnttrroodduuccttiioonn Postfix 2.2 introduces support for the IPv6 (IP version 6) protocol. IPv6 support for older Postfix versions was available as an add-on patch. The section "Compatibility with Postfix <2.2 IPv6 support" below discusses the differences between these implementations. The main feature of interest is that IPv6 uses 128-bit IP addresses instead of the 32-bit addresses used by IPv4. It can therefore accommodate a much larger number of hosts and networks without ugly kluges such as NAT. A side benefit of the much larger address space is that it makes random network scanning impractical. Postfix uses the same SMTP protocol over IPv6 as it already uses over the older IPv4 network, and does AAAA record lookups in the DNS in addition to the older A records. Information about IPv6 can be found at http://www.ipv6.org/. This document provides information on the following topics: * Supported platforms * Configuration * Known limitations * Compatibility with Postfix <2.2 IPv6 support * IPv6 Support for unsupported platforms * Credits SSuuppppoorrtteedd PPllaattffoorrmmss Postfix version 2.2 supports IPv4 and IPv6 on the following platforms: * AIX 5.1+ * Darwin 7.3+ * FreeBSD 4+ * Linux 2.4+ * NetBSD 1.5+ * OpenBSD 2+ * Solaris 8+ * Tru64Unix V5.1+ On other platforms Postfix will simply use IPv4 as it has always done. See below for tips how to port Postfix IPv6 support to other environments. CCoonnffiigguurraattiioonn Postfix IPv6 support introduces two new main.cf configuration parameters, and introduces an important change in address syntax notation in match lists such as mynetworks or debug_peer_list. Postfix IPv6 address syntax is a little tricky, because there are a few places where you must enclose an IPv6 address inside "[]" characters, and a few places where you must not. It is a good idea to use "[]" only in the few places where you have to. Check out the postconf(5) manual whenever you do IPv6 related configuration work with Postfix. * Instead of hard-coding 127.0.0.1 and ::1 loopback addresses in master.cf, specify "inet_interfaces = loopback-only" in main.cf. This way you can use the same master.cf file regardless of whether or not Postfix will run on an IPv6-enabled system. * The first new parameter is called inet_protocols. This specifies what protocols Postfix will use when it makes or accepts network connections, and also controls what DNS lookups Postfix will use when it makes network connections. /etc/postfix/main.cf: # You must stop/start Postfix after changing this parameter. inet_protocols = ipv4 (DEFAULT: enable IPv4 only) inet_protocols = all (enable IPv4, and IPv6 if supported) inet_protocols = ipv4, ipv6 (enable both IPv4 and IPv6) inet_protocols = ipv6 (enable IPv6 only) By default, Postfix uses IPv4 only, because most systems aren't attached to an IPv6 network. o On systems with combined IPv4/IPv6 stacks, attempts to deliver mail via IPv6 would always fail with "network unreachable", and those attempts would only slow down Postfix. o Linux kernels don't even load IPv6 protocol support by default. Any attempt to use it would fail immediately. Note 1: you must stop and start Postfix after changing the inet_protocols configuration parameter. Note 2: if you see error messages like the following, then you're running Linux and need to turn on IPv6 in the kernel: see http://www.ipv6.org/ for hints and tips. Unlike other systems, Linux does not have a combined stack for IPv4 and IPv6, and IPv6 protocol support is not loaded by default. postconf: warning: inet_protocols: IPv6 support is disabled: Address family not supported by protocol postconf: warning: inet_protocols: configuring for IPv4 support only Note 3: on older Linux and Solaris systems, the setting "inet_protocols = ipv6" will not prevent Postfix from accepting IPv4 connections. Postfix will present the client IP addresses in IPv6 format, though. In all other cases, Postfix always presents IPv4 client IP addresses in the traditional dotted quad IPv4 format. * The other new parameter is smtp_bind_address6. This sets the local interface address for outgoing IPv6 SMTP connections, just like the smtp_bind_address parameter does for IPv4: /etc/postfix/main.cf: smtp_bind_address6 = 2001:240:587:0:250:56ff:fe89:1 * If you left the value of the mynetworks parameter at its default (i.e. no mynetworks setting in main.cf) Postfix will figure out by itself what its network addresses are. This is what a typical setting looks like: % postconf mynetworks mynetworks = 127.0.0.0/8 168.100.189.0/28 [::1]/128 [fe80::]/10 [2001: 240:587::]/64 If you did specify the mynetworks parameter value in main.cf, you need update the mynetworks value to include the IPv6 networks the system is in. Be sure to specify IPv6 address information inside "[]", like this: /etc/postfix/main.cf: mynetworks = ...IPv4 networks... [::1]/128 [2001:240:587::]/64 ... NNOOTTEE:: wwhheenn ccoonnffiigguurriinngg PPoossttffiixx mmaattcchh lliissttss ssuucchh aass mmyynneettwwoorrkkss oorr ddeebbuugg__ppeeeerr__lliisstt,, yyoouu mmuusstt ssppeecciiffyy IIPPvv66 aaddddrreessss iinnffoorrmmaattiioonn iinnssiiddee ""[[]]"" iinn tthhee mmaaiinn..ccff ppaarraammeetteerr vvaalluuee aanndd iinn ffiilleess ssppeecciiffiieedd wwiitthh aa ""//ffiillee//nnaammee"" ppaatttteerrnn.. IIPPvv66 aaddddrreesssseess ccoonnttaaiinn tthhee ""::"" cchhaarraacctteerr,, aanndd wwoouulldd ootthheerrwwiissee bbee ccoonnffuusseedd wwiitthh aa ""ttyyppee::ttaabbllee"" ppaatttteerrnn.. KKnnoowwnn LLiimmiittaattiioonnss * The order of IPv6/IPv4 outgoing connection attempts is not yet configurable. Currently, IPv6 is tried before IPv4. * Postfix currently does not support DNSBL (real-time blackhole list) lookups for IPv6 client IP addresses; currently there are no blacklists that cover the IPv6 address space. * IPv6 does not have class A, B, C, etc. networks. With IPv6 networks, the setting "mynetworks_style = class" has the same effect as the setting "mynetworks_style = subnet". * On Tru64Unix and AIX, Postfix can't figure out the local subnet mask and always assumes a /128 network. This is a problem only with "mynetworks_style = subnet" and no explicit mynetworks setting in main.cf. CCoommppaattiibbiilliittyy wwiitthh PPoossttffiixx <<22..22 IIPPvv66 ssuuppppoorrtt Postfix version 2.2 IPv6 support is based on the Postfix/IPv6 patch by Dean Strik and others, but differs in a few minor ways. * main.cf: The inet_interfaces parameter does not support the notation "ipv6: all" or "ipv4:all". Use the inet_protocols parameter instead. * main.cf: Specify "inet_protocols = all" or "inet_protocols = ipv4, ipv6" in order to enable both IPv4 and IPv6 support. * main.cf: The inet_protocols parameter also controls what DNS lookups Postfix will attempt to make when delivering or receiving mail. * main.cf: Specify "inet_interfaces = loopback-only" to listen on loopback network interfaces only. * The lmtp_bind_address and lmtp_bind_address6 features were omitted. The Postfix LMTP client will be absorbed into the SMTP client, so there is no reason to keep adding features to the LMTP client. * The SMTP server now requires that IPv6 addresses in SMTP commands are specified as [ipv6:ipv6address], as described in RFC 2821. * The IPv6 network address matching code was rewritten from the ground up, and is expected to be closer to the specification. The result may be incompatible with the Postfix/IPv6 patch. IIPPvv66 SSuuppppoorrtt ffoorr uunnssuuppppoorrtteedd ppllaattffoorrmmss Getting Postfix IPv6 working on other platforms involves the following steps: * Specify how Postfix should find the local network interfaces. Postfix needs this information to avoid mailer loops and to find out if mail for user@ [ipaddress] is a local or remote destination. If your system has the getifaddrs() routine then add the following to your platform-specific section in src/util/sys_defs.h: #ifndef NO_IPV6 # define HAS_IPV6 # define HAVE_GETIFADDRS #endif Otherwise, if your system has the SIOCGLIF ioctl() command in /usr/include/ */*.h, add the following to your platform-specific section in src/util/ sys_defs.h: #ifndef NO_IPV6 # define HAS_IPV6 # define HAS_SIOCGLIF #endif Otherwise, Postfix will have to use the old SIOCGIF commands and get along with reduced IPv6 functionality (it won't be able to figure out your IPv6 netmasks, which are needed for "mynetworks_style = subnet". Add this to your platform-specific section in src/util/sys_defs.h: #ifndef NO_IPV6 # define HAS_IPV6 #endif * Test if Postfix can figure out its interface information. After compiling Postfix in the usual manner, step into the src/util directory and type "mmaakkee iinneett__aaddddrr__llooccaall". Running this file by hand should produce all the interface addresses and network masks, for example: % make % cd src/util % make inet_addr_local [... some messages ...] % ./inet_addr_local [... some messages ...] ./inet_addr_local: inet_addr_local: configured 2 IPv4 addresses ./inet_addr_local: inet_addr_local: configured 4 IPv6 addresses 168.100.189.2/255.255.255.224 127.0.0.1/255.0.0.0 fe80:1::2d0:b7ff:fe88:2ca7/ffff:ffff:ffff:ffff:: 2001:240:587:0:2d0:b7ff:fe88:2ca7/ffff:ffff:ffff:ffff:: fe80:5::1/ffff:ffff:ffff:ffff:: ::1/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff The above is for an old FreeBSD machine. Other systems produce slightly different results, but you get the idea. If none of all this produces a usable result, send email to the postfix- users@postfix.org mailing list and we'll try to help you through this. CCrreeddiittss The following information is in part based on information that was compiled by Dean Strik. * Mark Huizer wrote the original Postfix IPv6 patch. * Jun-ichiro 'itojun' Hagino of the KAME project made substantial improvements. Since then, we speak of the KAME patch. * The PLD Linux Distribution ported the code to other stacks (notably USAGI). We speak of the PLD patch. A very important feature of the PLD patch was that it can work with Lutz Jaenicke's TLS patch for Postfix. * Dean Strik extended IPv6 support to platforms other than KAME and USAGI, updated the patch to keep up with Postfix development, and provided a combined IPv6 + TLS patch. Information about his effort can be found on Dean Strik's Postfix website at http://www.ipnet6.org/postfix/. * Wietse Venema took Dean Strik's IPv6 patch, merged it into Postfix 2.2, and took the opportunity to eliminate all IPv4-specific code from Postfix that could be removed. For systems without IPv6 support in the kernel and system libraries, Postfix has a simple compatibility layer, so that it will use IPv4 as before. README_FILES/DATABASE_README000066600000032405150501202770010536 0ustar00PPoossttffiixx LLooookkuupp TTaabbllee OOvveerrvviieeww ------------------------------------------------------------------------------- OOvveerrvviieeww This document covers the following topics: * The Postfix lookup table model * Postfix lists versus tables * Preparing Postfix for LDAP or SQL lookups * Maintaining Postfix lookup table files * Updating Berkeley DB files safely * Postfix lookup table types TThhee PPoossttffiixx llooookkuupp ttaabbllee mmooddeell Postfix uses lookup tables to store and look up information for access control, address rewriting and even for content filtering. All Postfix lookup tables are specified as "type:table", where "type" is one of the database types described under "Postfix lookup table types" at the end of this document, and where "table" is the lookup table name. The Postfix documentation uses the terms "database" and "lookup table" for the same thing. Examples of lookup tables that appear often in the Postfix documentation: /etc/postfix/main.cf: alias_maps = hash:/etc/postfix/aliases (local aliasing) header_checks = regexp:/etc/postfix/header_checks (content filtering) transport_maps = hash:/etc/postfix/transport (routing table) virtual_alias_maps = hash:/etc/postfix/virtual (address rewriting) All Postfix lookup tables store information as (key, value) pairs. This interface may seem simplistic at first, but it turns out to be very powerful. The (key, value) query interface completely hides the complexities of LDAP or SQL from Postfix. This is a good example of connecting complex systems with simple interfaces. Benefits of the Postfix (key, value) query interface: * You can implement Postfix lookup tables first with local Berkeley DB files and then switch to LDAP or MySQL without any impact on the Postfix configuration itself, as described under "Preparing Postfix for LDAP or SQL lookups" below. * You can use Berkeley DB files with fixed lookup strings for simple address rewriting operations and you can use regular expression tables for the more complicated work. In other words, you don't have to put everything into the same table. PPoossttffiixx lliissttss vveerrssuuss ttaabblleess Most Postfix lookup tables are used to look up information. Examples are address rewriting (the lookup string is the old address, and the result is the new address) or access control (the lookup string is the client, sender or recipient, and the result is an action such as "reject"). With some tables, however, Postfix needs to know only if the lookup key exists. The lookup result itself is not used. Examples are the local_recipient_maps that determine what local recipients Postfix accepts in mail from the network, the mydestination parameter that specifies what domains Postfix delivers locally, or the mynetworks parameter that specifies the IP addresses of trusted clients or client networks. Technically, these are lists, not tables. Despite the difference, Postfix lists are described here because they use the same underlying infrastructure as Postfix lookup tables. PPrreeppaarriinngg PPoossttffiixx ffoorr LLDDAAPP oorr SSQQLL llooookkuuppss LDAP and SQL are complex systems. Trying to set up both Postfix and LDAP or SQL at the same time is definitely not a good idea. You can save yourself a lot of time by implementing Postfix first with local files such as Berkeley DB. Local files have few surprises, and are easy to debug with the postmap(1) command: % ppoossttmmaapp --qq iinnffoo@@eexxaammppllee..ccoomm hhaasshh:://eettcc//ppoossttffiixx//vviirrttuuaall Once you have local files working properly you can follow the instructions in ldap_table(5), mysql_table(5) or pgsql_table(5) and replace local file lookups with LDAP or SQL lookups. When you do this, you should use the postmap(1) command again, to verify that database lookups still produce the exact same results as local file lookup: % ppoossttmmaapp --qq iinnffoo@@eexxaammppllee..ccoomm llddaapp:://eettcc//ppoossttffiixx//vviirrttuuaall..ccff Be sure to exercise all the partial address or parent domain queries that are documented under "table search order" in the relevant manual page: access(5), canonical(5), virtual(5), transport(5), or under the relevant configuration parameter: mynetworks, relay_domains, parent_domain_matches_subdomains. MMaaiinnttaaiinniinngg PPoossttffiixx llooookkuupp ttaabbllee ffiilleess When you make changes to a database while the mail system is running, it would be desirable if Postfix avoids reading information while that information is being changed. It would also be nice if you can change a database without having to execute "postfix reload", in order to force Postfix to use the new information. Each time you do "postfix reload" Postfix loses a lot of performance. * If you change a network database such as LDAP, NIS or SQL, there is no need to execute "postfix reload". The LDAP, NIS or SQL server takes care of read/write access conflicts and gives the new data to Postfix once that data is available. * If you change a regexp: or pcre: file then Postfix may or may not pick up the file changes immediately. This is because a Postfix process reads the entire file into memory once and never examines the file again. o If the file is used by a short-running process such as smtpd(8), cleanup(8) or local(8), there is no need to execute "postfix reload" after making a change. o If the file is being used by a long-running process such as trivial- rewrite(8) on a busy server it may be necessary to execute "postfix reload". * If you change a local file based database such as DBM or Berkeley DB, there is no need to execute "postfix reload". Postfix uses file locking to avoid read/write access conflicts, and whenever a Postfix daemon process notices that a file has changed it will terminate before handling the next client request, so that a new process can initialize with the new database. UUppddaattiinngg BBeerrkkeelleeyy DDBB ffiilleess ssaaffeellyy Although Postfix uses file locking to avoid access conflicts while updating Berkeley DB or other local database files, you still have a problem when the update fails because the disk is full or because something else happens. This is because commands such as postmap(1) or postalias(1) overwrite existing files. If the update fails in the middle then you have no usable database, and Postfix will stop working. This is not an issue with the CDB database type available with Postfix 2.2 and later: CDB creates a new file, and renames the file upon successful completion. With multi-file databases such as DBM, there is no simple solution. With Berkeley DB and other "one file" databases, it is possible to add some extra robustness by using "mv" to REPLACE an existing database file instead of overwriting it: # ppoossttmmaapp aacccceessss..iinn &&&& mmvv aacccceessss..iinn..ddbb aacccceessss..ddbb This converts the input file "access.in" into the output file "access.in.db", and replaces the file "access.db" only when the postmap(1) command was successful. Of course typing such commands becomes boring quickly, and this is why people use "make" instead, as shown below. User input is shown in bold font. # ccaatt MMaakkeeffiillee all: aliases.db access.db virtual.db ...etcetera... # Note 1: commands are specified after a TAB character. # Note 2: use postalias(1) for local aliases, postmap(1) for the rest. aliases.db: aliases.in postalias aliases.in mv aliases.in.db aliases.db access.db: access.in postmap access.in mv access.in.db access.db virtual.db: virtual.in postmap virtual.in mv virtual.in.db virtual.db ...etcetera... # vvii aacccceessss..iinn ...editing session not shown... # mmaakkee postmap access.in mv access.in.db access.db # The "make" command updates only the files that have changed. In case of error, the "make" command will stop and will not invoke the "mv" command, so that Postfix will keep using the existing database file as if nothing happened. PPoossttffiixx llooookkuupp ttaabbllee ttyyppeess To find out what database types your Postfix system supports, use the "ppoossttccoonnff --mm" command. Here is a list of database types that are often supported: bbttrreeee A sorted, balanced tree structure. This is available only on systems with support for Berkeley DB databases. Database files are created with the postmap(1) or postalias(1) command. The lookup table name as used in "btree:table" is the database file name without the ".db" suffix. ccddbb A read-optimized structure with no support for incremental updates. Database files are created with the postmap(1) or postalias(1) command. The lookup table name as used in "cdb:table" is the database file name without the ".cdb" suffix. This feature is available with Postfix 2.2 and later. cciiddrr A table that associates values with Classless Inter-Domain Routing (CIDR) patterns. The table format is described in cidr_table(5). ddbbmm An indexed file type based on hashing. This is available only on systems with support for DBM databases. Database files are created with the postmap(1) or postalias(1) command. The lookup table name as used in "dbm:table" is the database file name without the ".dir" or ".pag" suffix. eennvviirroonn The UNIX process environment array. The lookup key is the variable name. The lookup table name in "environ:table" is ignored. hhaasshh An indexed file type based on hashing. This is available only on systems with support for Berkeley DB databases. Database files are created with the postmap(1) or postalias(1) command. The database name as used in "hash:table" is the database file name without the ".db" suffix. llddaapp (read-only) Perform lookups using the LDAP protocol. Configuration details are given in the ldap_table(5). mmyyssqqll (read-only) Perform MySQL database lookups. Configuration details are given in mysql_table(5). nneettiinnffoo (read-only) Perform Netinfo database lookups. nniiss (read-only) Perform NIS database lookups. nniisspplluuss (read-only) Perform NIS+ database lookups. Configuration details are given in nisplus_table(5). ppccrree (read-only) A lookup table based on Perl Compatible Regular Expressions. The file format is described in pcre_table(5). The lookup table name as used in "pcre:table" is the name of the regular expression file. ppggssqqll (read-only) Perform PostgreSQL database lookups. Configuration details are given in pgsql_table(5). pprrooxxyy (read-only) Access information via the Postfix proxymap(8) service. The lookup table name syntax is "proxy:type:table". rreeggeexxpp (read-only) A lookup table based on regular expressions. The file format is described in regexp_table(5). The lookup table name as used in "regexp: table" is the name of the regular expression file. ssddbbmm An indexed file type based on hashing. This is available only on systems with support for SDBM databases. Database files are created with the postmap(1) or postalias(1) command. The lookup table name as used in "sdbm:table" is the database file name without the ".dir" or ".pag" suffix. ssttaattiicc (read-only) Always returns its lookup table name as lookup result. For example, the lookup table "static:foobar" always returns the string "foobar" as lookup result. ttccpp Access information through a TCP/IP server. The protocol is described in tcp_table(5). The lookup table name is "tcp:host:port" where "host" specifies a symbolic hostname or a numeric IP address, and "port" specifies a symbolic service name or a numeric port number. This protocol is not available in the stable Postfix release. uunniixx (read-only) A limited way to query the UNIX authentication database. The following tables are implemented: uunniixx::ppaasssswwdd..bbyynnaammee The table is the UNIX password database. The key is a login name. The result is a password file entry in passwd(5) format. uunniixx::ggrroouupp..bbyynnaammee The table is the UNIX group database. The key is a group name. The result is a group file entry in group(5) format. Other lookup table types may be available depending on how Postfix was built. With some Postfix distributions the list is dynamically extensible as support for lookup tables is dynamically linked into Postfix. README_FILES/DEBUG_README000066600000043323150501202770010221 0ustar00PPoossttffiixx DDeebbuuggggiinngg HHoowwttoo ------------------------------------------------------------------------------- PPuurrppoossee ooff tthhiiss ddooccuummeenntt This document describes how to debug parts of the Postfix mail system when things do not work according to expectation. The methods vary from making Postfix log a lot of detail, to running some daemon processes under control of a call tracer or debugger. The text assumes that the Postfix main.cf and master.cf configuration files are stored in directory /etc/postfix. You can use the command "ppoossttccoonnff ccoonnffiigg__ddiirreeccttoorryy" to find out the actual location of this directory on your machine. Listed in order of increasing invasiveness, the debugging techniques are as follows: * Look for obvious signs of trouble * Debugging Postfix from inside * Try turning off chroot operation in master.cf * Verbose logging for specific SMTP connections * Record the SMTP session with a network sniffer * Making Postfix daemon programs more verbose * Manually tracing a Postfix daemon process * Automatically tracing a Postfix daemon process * Running daemon programs with the interactive ddd debugger * Running daemon programs with the interactive gdb debugger * Running daemon programs under a non-interactive debugger * Unreasonable behavior * Reporting problems to postfix-users@postfix.org LLooookk ffoorr oobbvviioouuss ssiiggnnss ooff ttrroouubbllee Postfix logs all failed and successful deliveries to a logfile. The file is usually called /var/log/maillog or /var/log/mail; the exact pathname is defined in the /etc/syslog.conf file. When Postfix does not receive or deliver mail, the first order of business is to look for errors that prevent Postfix from working properly: % eeggrreepp ''((wwaarrnniinngg||eerrrroorr||ffaattaall||ppaanniicc))::'' //ssoommee//lloogg//ffiillee || mmoorree Note: the most important message is near the BEGINNING of the output. Error messages that come later are less useful. The nature of each problem is indicated as follows: * "ppaanniicc" indicates a problem in the software itself that only a programmer can fix. Postfix cannot proceed until this is fixed. * "ffaattaall" is the result of missing files, incorrect permissions, incorrect configuration file settings that you can fix. Postfix cannot proceed until this is fixed. * "eerrrroorr" reports an error condition. For safety reasons, a Postfix process will terminate when more than 13 of these happen. * "wwaarrnniinngg" indicates a non-fatal error. These are problems that you may not be able to fix (such as a broken DNS server elsewhere on the network) but may also indicate local configuration errors that could become a problem later. DDeebbuuggggiinngg PPoossttffiixx ffrroomm iinnssiiddee Postfix version 2.1 and later can produce mail delivery reports for debugging purposes. These reports not only show sender/recipient addresses after address rewriting and alias expansion or forwarding, they also show information about delivery to mailbox, delivery to non-Postfix command, responses from remote SMTP servers, and so on. Postfix can produce two types of mail delivery reports for debugging: * What-if: report what would happen, but do not actually deliver mail. This mode of operation is requested with: % //uussrr//ssbbiinn//sseennddmmaaiill --bbvv aaddddrreessss...... Mail Delivery Status Report will be mailed to . * What happened: deliver mail and report successes and/or failures, including replies from remote SMTP servers. This mode of operation is requested with: % //uussrr//ssbbiinn//sseennddmmaaiill --vv aaddddrreessss...... Mail Delivery Status Report will be mailed to . These reports contain information that is generated by Postfix delivery agents. Since these run as daemon processes that cannot interact with users directly, the result is sent as mail to the sender of the test message. The format of these reports is practically identical to that of ordinary non-delivery notifications. For a detailed example of a mail delivery status report, see the debugging section at the end of the ADDRESS_REWRITING_README document. TTrryy ttuurrnniinngg ooffff cchhrroooott ooppeerraattiioonn iinn mmaasstteerr..ccff A common mistake is to turn on chroot operation in the master.cf file without going through all the necessary steps to set up a chroot environment. This causes Postfix daemon processes to fail due to all kinds of missing files. The example below shows an SMTP server that is configured with chroot turned off: /etc/postfix/master.cf: # ============================================================= # service type private unpriv cchhrroooott wakeup maxproc command # (yes) (yes) ((yyeess)) (never) (100) # ============================================================= smtp inet n - nn - - smtpd Inspect master.cf for any processes that have chroot operation not turned off. If you find any, save a copy of the master.cf file, and edit the entries in question. After executing the command "ppoossttffiixx rreellooaadd", see if the problem has gone away. If turning off chrooted operation made the problem go away, then congratulations. Leaving Postfix running in this way is adequate for most sites. If you prefer chrooted operation, see the Postfix BASIC_CONFIGURATION_README file for information about how to prepare Postfix for chrooted operation. VVeerrbboossee llooggggiinngg ffoorr ssppeecciiffiicc SSMMTTPP ccoonnnneeccttiioonnss In /etc/postfix/main.cf, list the remote site name or address in the debug_peer_list parameter. For example, in order to make the software log a lot of information to the syslog daemon for connections from or to the loopback interface: /etc/postfix/main.cf: debug_peer_list = 127.0.0.1 You can specify one or more hosts, domains, addresses or net/masks. To make the change effective immediately, execute the command "ppoossttffiixx rreellooaadd". RReeccoorrdd tthhee SSMMTTPP sseessssiioonn wwiitthh aa nneettwwoorrkk ssnniiffffeerr This example uses ttccppdduummpp. In order to record a conversation you need to specify a large enough buffer with the "--ss" option or else you will miss some or all of the packet payload. # ttccppdduummpp --ww //ffiillee//nnaammee --ss 00 hhoosstt eexxaammppllee..ccoomm aanndd ppoorrtt 2255 Older tcpdump versions don't support "--ss 00"; in that case, use "--ss 22000000" instead. Run this for a while, stop with Ctrl-C when done. To view the data use a binary viewer, eetthheerreeaall, or good old lleessss. MMaakkiinngg PPoossttffiixx ddaaeemmoonn pprrooggrraammss mmoorree vveerrbboossee Append one or more "--vv" options to selected daemon definitions in /etc/postfix/ master.cf and type "ppoossttffiixx rreellooaadd". This will cause a lot of activity to be logged to the syslog daemon. For example, to make the Postfix SMTP server process more verbose: /etc/postfix/master.cf: smtp inet n - n - - smtpd -v To diagnose problems with address rewriting specify a "--vv" option for the cleanup(8) and/or trivial-rewrite(8) daemon, and to diagnose problems with mail delivery specify a "--vv" option for the qmgr(8) or oqmgr(8) queue manager, or for the lmtp(8), local(8), pipe(8), smtp(8), or virtual(8) delivery agent. MMaannuuaallllyy ttrraacciinngg aa PPoossttffiixx ddaaeemmoonn pprroocceessss Many systems allow you to inspect a running process with a system call tracer. For example: # ttrraaccee --pp pprroocceessss--iidd (SunOS 4) # ssttrraaccee --pp pprroocceessss--iidd (Linux and many others) # ttrruussss --pp pprroocceessss--iidd (Solaris, FreeBSD) # kkttrraaccee --pp pprroocceessss--iidd (generic 4.4BSD) Even more informative are traces of system library calls. Examples: # llttrraaccee --pp pprroocceessss--iidd (Linux, also ported to FreeBSD and BSD/OS) # ssoottrruussss --pp pprroocceessss--iidd (Solaris) See your system documentation for details. Tracing a running process can give valuable information about what a process is attempting to do. This is as much information as you can get without running an interactive debugger program, as described in a later section. AAuuttoommaattiiccaallllyy ttrraacciinngg aa PPoossttffiixx ddaaeemmoonn pprroocceessss Postfix can attach a call tracer whenever a daemon process starts. Call tracers come in several kinds. 1. System call tracers such as ttrraaccee, ttrruussss, ssttrraaccee, or kkttrraaccee. These show the communication between the process and the kernel. 2. Library call tracers such as ssoottrruussss and llttrraaccee. These show calls of library routines, and give a better idea of what is going on within the process. Append a --DD option to the suspect command in /etc/postfix/master.cf, for example: /etc/postfix/master.cf: smtp inet n - n - - smtpd -D Edit the debugger_command definition in /etc/postfix/main.cf so that it invokes the call tracer of your choice, for example: /etc/postfix/main.cf: debugger_command = PATH=/bin:/usr/bin:/usr/local/bin; (truss -p $process_id 2>&1 | logger -p mail.info) & sleep 5 Type "ppoossttffiixx rreellooaadd" and watch the logfile. RRuunnnniinngg ddaaeemmoonn pprrooggrraammss wwiitthh tthhee iinntteerraaccttiivvee dddddd ddeebbuuggggeerr If you have X Windows installed on the Postfix machine, then an interactive debugger such as dddddd can be convenient. Edit the debugger_command definition in /etc/postfix/main.cf so that it invokes dddddd: /etc/postfix/main.cf: debugger_command = PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin ddd $daemon_directory/$process_name $process_id & sleep 5 Be sure that ggddbb is in the command search path, and export XXAAUUTTHHOORRIITTYY so that X access control works, for example: % sseetteennvv XXAAUUTTHHOORRIITTYY ~~//..XXaauutthhoorriittyy (csh syntax) $ eexxppoorrtt XXAAUUTTHHOORRIITTYY==$$HHOOMMEE//..XXaauutthhoorriittyy (sh syntax) Append a --DD option to the suspect daemon definition in /etc/postfix/master.cf, for example: /etc/postfix/master.cf: smtp inet n - n - - smtpd -D Stop and start the Postfix system. This is necessary so that Postfix runs with the proper XXAAUUTTHHOORRIITTYY and DDIISSPPLLAAYY settings. Whenever the suspect daemon process is started, a debugger window pops up and you can watch in detail what happens. RRuunnnniinngg ddaaeemmoonn pprrooggrraammss wwiitthh tthhee iinntteerraaccttiivvee ggddbb ddeebbuuggggeerr If you have the screen command installed on the Postfix machine, then you can run an interactive debugger such as ggddbb as follows. Edit the debugger_command definition in /etc/postfix/main.cf so that it runs ggddbb inside a detached ssccrreeeenn session: /etc/postfix/main.cf: debugger_command = PATH=/bin:/usr/bin:/sbin:/usr/sbin; export PATH; HOME=/root; export HOME; screen -e^tt -dmS $process_name gdb $daemon_directory/$process_name $process_id & sleep 2 Be sure that ggddbb is in the command search path. Append a --DD option to the suspect daemon definition in /etc/postfix/master.cf, for example: /etc/postfix/master.cf: smtp inet n - n - - smtpd -D Execute the command "ppoossttffiixx rreellooaadd" and wait until a daemon process is started (you can see this in the maillog file). Then attach to the screen, and debug away: # HOME=/root screen -r gdb) continue gdb) where RRuunnnniinngg ddaaeemmoonn pprrooggrraammss uunnddeerr aa nnoonn--iinntteerraaccttiivvee ddeebbuuggggeerr If you do not have X Windows installed on the Postfix machine, or if you are not familiar with interactive debuggers, then you can try to run ggddbb in non- interactive mode, and have it print a stack trace when the process crashes. Edit the debugger_command definition in /etc/postfix/main.cf so that it invokes the ggddbb debugger: /etc/postfix/main.cf: debugger_command = PATH=/bin:/usr/bin:/usr/local/bin; export PATH; (echo cont; echo where; sleep 8640000) | gdb $daemon_directory/$process_name $process_id 2>&1 >$config_directory/$process_name.$process_id.log & sleep 5 Append a --DD option to the suspect daemon in /etc/postfix/master.cf, for example: /etc/postfix/master.cf: smtp inet n - n - - smtpd -D Type "ppoossttffiixx rreellooaadd" to make the configuration changes effective. Whenever a suspect daemon process is started, an output file is created, named after the daemon and process ID (for example, smtpd.12345.log). When the process crashes, a stack trace (with output from the "wwhheerree" command) is written to its logfile. UUnnrreeaassoonnaabbllee bbeehhaavviioorr Sometimes the behavior exhibited by Postfix just does not match the source code. Why can a program deviate from the instructions given by its author? There are two possibilities. * The compiler has erred. This rarely happens. * The hardware has erred. Does the machine have ECC memory? In both cases, the program being executed is not the program that was supposed to be executed, so anything could happen. There is a third possibility: * Bugs in system software (kernel or libraries). Hardware-related failures usually do not reproduce in exactly the same way after power cycling and rebooting the system. There's little Postfix can do about bad hardware. Be sure to use hardware that at the very least can detect memory errors. Otherwise, Postfix will just be waiting to be hit by a bit error. Critical systems deserve real hardware. When a compiler makes an error, the problem can be reproduced whenever the resulting program is run. Compiler errors are most likely to happen in the code optimizer. If a problem is reproducible across power cycles and system reboots, it can be worthwhile to rebuild Postfix with optimization disabled, and to see if optimization makes a difference. In order to compile Postfix with optimizations turned off: % mmaakkee ttiiddyy % mmaakkee mmaakkeeffiilleess OOPPTT== This produces a set of Makefiles that do not request compiler optimization. Once the makefiles are set up, build the software: % mmaakkee % ssuu Password: # mmaakkee iinnssttaallll If the problem goes away, then it is time to ask your vendor for help. RReeppoorrttiinngg pprroobblleemmss ttoo ppoossttffiixx--uusseerrss@@ppoossttffiixx..oorrgg The people who participate on postfix-users@postfix.org are very helpful, especially if YOU provide them with sufficient information. Remember, these volunteers are willing to help, but their time is limited. When reporting a problem, be sure to include the following information. * A summary of the problem. Please do not just send some logging without explanation of what YOU believe is wrong. * Complete error messages. Please use cut-and-paste, or use attachments, instead of reciting information from memory. * Postfix logging. See the text at the top of the DEBUG_README document to find out where logging is stored. Please do not frustrate the helpers by word wrapping the logging. If the logging is more than a few kbytes of text, consider posting an URL on a web or ftp site. * Consider using a test email address so that you don't have to reveal email addresses or passwords of innocent people. * If you can't use a test email address, please anonymize email addresses and host names consistently. Replace each letter by "A", each digit by "D" so that the helpers can still recognize syntactical errors. * Output from "ppoossttccoonnff --nn". Please do not send your main.cf file, or 500+ lines of ppoossttccoonnff output. * Better, provide output from the ppoossttffiinnggeerr tool. This can be found at http: //ftp.wl0.org/SOURCES/postfinger. * If the problem is SASL related, consider including the output from the ssaassllffiinnggeerr tool. This can be found at http://postfix.state-of-mind.de/ patrick.koetter/saslfinger/. * If the problem is about too much mail in the queue, consider including output from the qqsshhaappee tool, as described in the QSHAPE_README file. * If the problem is protocol related (connections time out, or an SMTP server complains about syntax errors etc.) consider recording a session with ttccppdduummpp, as described in the DEBUG_README document. README_FILES/MULTI_INSTANCE_README000066600000124631150501202770011553 0ustar00MMaannaaggiinngg mmuullttiippllee PPoossttffiixx iinnssttaanncceess oonn aa ssiinnggllee hhoosstt ------------------------------------------------------------------------------- OOvveerrvviieeww This document is a guide to managing multiple Postfix instances on a single host using the postmulti(1) instance manager. Multi-instance support is available with Postfix version 2.6 and later. See the postfix-wrapper(5) manual page for background on the instance management framework, and on how to deploy a custom instance manager. Topics covered in this document: * Why multiple Postfix instances * Null-client instances versus service instances * Multi-instance walk-through * Components of a Postfix system * The default Postfix instance * Instance groups * Multi-instance configuration parameters * Using the postmulti(1) command * Credits WWhhyy mmuullttiippllee PPoossttffiixx iinnssttaanncceess Postfix is a general-purpose mail system that can be configured to serve a variety of needs. Examples of Postfix applications are: * Local mail submission for shell users and system processes. * Incoming (MX host) email from the Internet. * Outbound mail relay for a corporate network. * Authenticated submission for roaming users. * Before/after content-filter mail. A single Postfix configuration can provide many or all of these services, but a complex interplay of settings may be required, for example with master.cf options overriding main.cf settings. In this document we take the view that multiple Postfix instances may be a simpler way to configure a multi-function Postfix system. With multiple Postfix instances, each instance has its own directories for configuration, queue and data files, but it shares all Postfix program and documentation files with other instances. Since there is no single right way to configure your system, we recommend that you choose what makes you most comfortable. If different Postfix services don't involve incompatible main.cf or master.cf settings, and if they can be combined together without complex tricks, then a single monolithic configuration may be the simplest approach. The purpose of multi-instance support in Postfix is not to force you to create multiple Postfix instances, but rather to give you a choice. Multiple instances give you the freedom to tune each Postfix instance to a single task that it does well and to combine instances into complete systems. With the introduction of the postmulti(1) utility and the reduction of the per- instance configuration footprint of a secondary Postfix instance to just a main.cf and master.cf file (other files are now in shared locations), we hope that multiple instances will be easier to use than ever before. NNuullll--cclliieenntt iinnssttaanncceess vveerrssuuss sseerrvviiccee iinnssttaanncceess In the multi-instance approach to configuring Postfix, the first simplification is with the default local-submission Postfix instance. Most UNIX systems require support for email submission with the sendmail(1) command so that system processes such as cron jobs can send status reports, and so that system users can send email with command-line utilities. Such email can be handled with a null-client Postfix configuration that forwards all mail to a central mail hub. The null client will typically either not run an SMTP listener at all (master_service_disable = inet), or it will listen only on the loopback interface (inet_interfaces = loopback-only). When implementing specialized servers for inbound Internet email, outbound MTAs, internal mail hubs, and so on, we recommend using a null client for local submission and creating single-function secondary Postfix instances to serve the specialized needs. Note: usually, you need to use different "myhostname" settings when you run multiple instances on the same host. Otherwise, there will be false "mail loops back to myself" alarms when one instance tries to send mail into another instance. Typically, the null-client instance will use the system's hostname, and other instances will use their own dedicated "myhostname" settings. Different names are not needed when instances send mail to each other with a protocol other than SMTP, or with SMTP over a TCP port other than 25 as is usual with SMTP-based content filters. MMuullttii--iinnssttaannccee wwaallkk--tthhrroouugghh Before discussing the fine details of multi-instance operation we first show the steps for creating a border mail server. This server has with a null-client Postfix instance for local submission, an input Postfix instance to receive mail from the Internet, plus an advanced SMTP content-filter and an output Postfix instance to deliver filtered email to its internal destination. SSeettttiinngg uupp tthhee nnuullll--cclliieenntt PPoossttffiixx iinnssttaannccee On a border mail hub, while mail from the Internet requires a great deal of scrutiny, locally submitted messages are typically limited to mail from cron jobs and other system services. In this regard the border MTA is not different from other Unix hosts in your environment. For this reason, it will submit locally-generated email to the internal mail hub. We start the construction of the border mail server with the default instance, which will be a local- submission null client: /etc/postfix/main.cf: # We are mta1.example.com # myhostname = mta1.example.com mydomain = example.com # Flat user-account namespace in example.com: # # user@example.com not user@host.example.com # myorigin = $mydomain # Postfix 2.6+, disable inet services, specifically disable smtpd(8) # master_service_disable = inet # No local delivery: # mydestination = local_transport = error:5.1.1 Mailbox unavailable alias_database = alias_maps = local_recipient_maps = # Send everything to the internal mailhub # relayhost = [mailhub.example.com] # Indexed table macro: # (use "hash", ... when cdb is not available) # default_database_type = cdb indexed = ${default_database_type}:${config_directory}/ # Expose origin host of mail from "root", ... # smtp_generic_maps = ${indexed}generic # Send messages addressed to "root", ... to the MTA support team # virtual_alias_maps = ${indexed}virtual /etc/postfix/generic: # The smarthost supports "+" addressing (recipient_delimiter = +). # Mail from "root" exposes the origin host, without replies # and bounces going back to the same host. # # On clustered MTAs this file is typically machine-built from # a template file. The build process expands the template into # "mtaadmin+root=mta1" # root mtaadmin+root=mta1 /etc/postfix/virtual: # Caretaker aliases: # root mtaadmin postmaster root You would typically also add a Makefile, to automatically run postmap(1) commands when source files change. This Makefile also creates a "generic" database when none exists. /etc/postfix/Makefile: MTAADMIN=mtaadmin all: virtual.cdb generic.cdb generic: Makefile @echo Creating $@ @rm -f $@.tmp @printf '%s\t%s+root=%s\n' root $MTAADMIN `uname -n` > $@.tmp @mv $@.tmp generic %.cdb: % postmap cdb:$< Construct the "virtual" and "generic" databases (the latter is created by running "make"), then start and test the null-client: # cd /etc/postfix; make # postfix start # sendmail -i -f root -t < XVERP MAIL FROM: XVERP=+= The first form uses the default main.cf VERP delimiters, the second form overrides them explicitly. The values shown are the recommended ones. VVEERRPP ssuuppppoorrtt iinn tthhee PPoossttffiixx sseennddmmaaiill ccoommmmaanndd The Postfix sendmail command has a -V flag to request VERP style delivery. Specify one of the following two forms: Postfix 2.3 and later: % sendmail -XV -f owner-listname .... % sendmail -XV+= -f owner-listname .... Postfix 2.2 and earlier (Postfix 2.3 understands the old syntax for backwards compatibility, but will log a warning that reminds you of the new syntax): % sendmail -V -f owner-listname .... % sendmail -V+= -f owner-listname .... The first form uses the default main.cf VERP delimiters, the second form overrides them explicitly. The values shown are the recommended ones. VVEERRPP ssuuppppoorrtt iinn tthhee PPoossttffiixx QQMMQQPP sseerrvveerr When the Postfix QMQP server receives mail with an envelope sender address of the form: listname-@your.domain-@[] Postfix generates sender addresses "listname-user=domain@your.domain", using "- =" as the VERP delimiters because qmail/ezmlm expect this. More generally, a sender address of "prefix@origin-@[]" requests VERP style delivery with sender addresses of the form "prefixuser=domain@origin". However, Postfix allows only VERP delimiters that are specified with the verp_delimiter_filter parameter. In particular, the "=" delimiter is required for qmail compatibility (see the qmail addresses(5) manual page for details). README_FILES/DB_README000066600000015636150501202770007666 0ustar00PPoossttffiixx BBeerrkkeelleeyy DDBB HHoowwttoo ------------------------------------------------------------------------------- IInnttrroodduuccttiioonn Postfix uses databases of various kinds to store and look up information. Postfix databases are specified as "type:name". Berkeley DB implements the Postfix database type "hash" and "btree". The name of a Postfix Berkeley DB database is the name of the database file without the ".db" suffix. Berkeley DB databases are maintained with the postmap(1) command. Note: Berkeley DB version 4 is not supported by Postfix versions before 2.0. This document describes: 1. How to build Postfix on systems without Berkeley DB library. 2. How to build Postfix on BSD or Linux systems with multiple Berkeley DB versions. 3. How to tweak performance. 4. Missing pthread library trouble. BBuuiillddiinngg PPoossttffiixx oonn ssyysstteemmss wwiitthhoouutt BBeerrkkeelleeyy DDBB Some UNIXes ship without Berkeley DB support; for historical reasons these use DBM files instead. A problem with DBM files is that they can store only limited amounts of data. To build Postfix with Berkeley DB support you need to download and install the source code from http://www.oracle.com/database/berkeley-db/. Warning: some Linux system libraries use Berkeley DB, as do some third-party libraries such as SASL. If you compile Postfix with a different Berkeley DB implementation, then every Postfix program will dump core because either the system library, the SASL library, or Postfix itself ends up using the wrong version. The more recent Berkeley DB versions have a compile-time switch, "--with- uniquename", which renames the symbols so that multiple versions of Berkeley DB can co-exist in the same application. Although wasteful, this may be the only way to keep things from falling apart. To build Postfix after you installed the Berkeley DB from source code, use something like: % make tidy % make makefiles CCARGS="-DHAS_DB -I/usr/local/BerkeleyDB/include" \ AUXLIBS="-L/usr/local/BerkeleyDB/lib -ldb" % make Solaris needs this: % make tidy % make makefiles CCARGS="-DHAS_DB -I/usr/local/BerkeleyDB/include" \ AUXLIBS="-R/usr/local/BerkeleyDB/lib -L/usr/local/BerkeleyDB/lib -ldb" % make The exact pathnames depend on the Berkeley DB version, and on how it was installed. Warning: the file format produced by Berkeley DB version 1 is not compatible with that of versions 2 and 3 (versions 2 and 3 have the same format). If you switch between DB versions, then you may have to rebuild all your Postfix DB files. Warning: if you use Berkeley DB version 2 or later, do not enable DB 1.85 compatibility mode. Doing so would break fcntl file locking. Warning: if you use Perl to manipulate Postfix's Berkeley DB files, then you need to use the same Berkeley DB version in Perl as in Postfix. BBuuiillddiinngg PPoossttffiixx oonn BBSSDD ssyysstteemmss wwiitthh mmuullttiippllee BBeerrkkeelleeyy DDBB vveerrssiioonnss Some BSD systems ship with multiple Berkeley DB implementations. Normally, Postfix builds with the default DB version that ships with the system. To build Postfix on BSD systems with a non-default DB version, use a variant of the following commands: % make tidy % make makefiles CCARGS=-I/usr/include/db3 AUXLIBS=-ldb3 % make Warning: the file format produced by Berkeley DB version 1 is not compatible with that of versions 2 and 3 (versions 2 and 3 have the same format). If you switch between DB versions, then you may have to rebuild all your Postfix DB files. Warning: if you use Berkeley DB version 2 or later, do not enable DB 1.85 compatibility mode. Doing so would break fcntl file locking. Warning: if you use Perl to manipulate Postfix's Berkeley DB files, then you need to use the same Berkeley DB version in Perl as in Postfix. BBuuiillddiinngg PPoossttffiixx oonn LLiinnuuxx ssyysstteemmss wwiitthh mmuullttiippllee BBeerrkkeelleeyy DDBB vveerrssiioonnss Some Linux systems ship with multiple Berkeley DB implementations. Normally, Postfix builds with the default DB version that ships with the system. Warning: some Linux system libraries use Berkeley DB. If you compile Postfix with a non-default Berkeley DB implementation, then every Postfix program will dump core because either the system library or Postfix itself ends up using the wrong version. On Linux, you need to edit the makedefs script in order to specify a non- default DB library. The reason is that the location of the default db.h include file changes randomly between vendors and between versions, so that Postfix has to choose the file for you. Warning: the file format produced by Berkeley DB version 1 is not compatible with that of versions 2 and 3 (versions 2 and 3 have the same format). If you switch between DB versions, then you may have to rebuild all your Postfix DB files. Warning: if you use Berkeley DB version 2 or later, do not enable DB 1.85 compatibility mode. Doing so would break fcntl file locking. Warning: if you use Perl to manipulate Postfix's Berkeley DB files, then you need to use the same Berkeley DB version in Perl as in Postfix. TTwweeaakkiinngg ppeerrffoorrmmaannccee Postfix provides two configuration parameters that control how much buffering memory Berkeley DB will use. * berkeley_db_create_buffer_size (default: 16 MBytes per table). This setting is used by the commands that maintain Berkeley DB files: postalias(1) and postmap(1). For "hash" files, create performance degrades rapidly unless the memory pool is O(file size). For "btree" files, create performance is good with sorted input even for small memory pools, but with random input degrades rapidly unless the memory pool is O(file size). * berkeley_db_read_buffer_size (default: 128 kBytes per table). This setting is used by all other Postfix programs. The buffer size is adequate for reading. If the cache is smaller than the table, random read performance is hardly cache size dependent, except with btree tables, where the cache size must be large enough to contain the entire path from the root node. Empirical evidence shows that 64 kBytes may be sufficient. We double the size to play safe, and to anticipate changes in implementation and bloat. MMiissssiinngg pptthhrreeaadd lliibbrraarryy ttrroouubbllee When building Postfix fails with: undefined reference to `pthread_condattr_setpshared' undefined reference to `pthread_mutexattr_destroy' undefined reference to `pthread_mutexattr_init' undefined reference to `pthread_mutex_trylock' Add the "-lpthread" library to the "make makefiles" command. % make makefiles .... AUXLIBS="... -lpthread" More information is available at http://www.oracle.com/database/berkeley-db/. README_FILES/NFS_README000066600000011357150501202770010023 0ustar00PPoossttffiixx aanndd NNFFSS ------------------------------------------------------------------------------- PPoossttffiixx ssuuppppoorrtt ssttaattuuss ffoorr NNFFSS What is the status of support for Postfix on NFS? The answer is that Postfix itself is supported when you use NFS, but there is no promise that an NFS- related problem will promptly receive a Postfix workaround, or that a workaround will even be possible. That said, Postfix will in many cases work very well on NFS, because Postfix implements a number of workarounds (see below). Good NFS implementations seldom if ever give problems with Postfix, so Wietse recommends that you spend your money wisely. PPoossttffiixx ffiillee lloocckkiinngg aanndd NNFFSS For the Postfix mail queue, it does not matter how well NFS file locking works. The reason is that you cannot share Postfix queues among multiple running Postfix instances. You can use NFS to switch a Postfix mail queue from one NFS client to another one, but only one NFS client can access a Postfix mail queue at any particular point in time. For mailbox file sharing with NFS, your options are to use ffccnnttll (kernel locks), ddoottlloocckk (username.lock files), to use both locking methods simultaneously, or to switch to maildir format. The maildir format uses one file per message and needs no file locking support in Postfix or in other mail software. Many sites that use mailbox format play safe and use both locking methods simultaneously. /etc/postfix/main.cf: virtual_mailbox_lock = fcntl, dotlock mailbox_delivery_lock = fcntl, dotlock PPoossttffiixx NNFFSS wwoorrkkaarroouunnddss The list below summarizes the workarounds that exist for running Postfix on NFS as of the middle of 2003. As a reminder, Postfix itself is still supported when it runs on NFS, but there is no promise that an NFS-related problem will promptly receive a Postfix workaround, or that a workaround will even be possible. * Problem: when renaming a file, the operation may succeed but report an error anyway[1]. Workaround: when rename(old, new) reports an error, Postfix checks if the new name exists and the old name is gone. If the check succeeds, Postfix assumes that the rename() operation completed normally. * Problem: when creating a directory, the operation may succeed but report an error anyway[1]. Workaround: when mkdir(new) reports an EEXIST error, Postfix checks if the new name resolves to a directory. If the check succeeds, Postfix assumes that the mkdir() operation completed normally. * Problem: when creating a hardlink to a file, the operation may succeed but report an error anyway[1]. Workaround: when link(old, new) fails, Postfix compares the device and inode number of the old and new files. When the two files are identical, Postfix assumes that the link() operation completed normally. * Problem: when creating a dotlock (username.lock) file, the operation may succeed but report an error anyway[1]. Workaround: in this case, the only safe action is to back off and try again later. * Problem: when a file server's "time of day" clock is not synchronized with the client's "time of day" clock, email deliveries are delayed by a minute or more. Workaround: Postfix explicitly sets file time stamps to avoid delays with new mail (Postfix uses "last modified" file time stamps to decide when a queue file is ready for delivery). [1] How can an operation succeed and report an error anyway? Suppose that an NFS server executes a client request successfully, and that the server's reply to the client is lost. After some time the client retransmits the request to the server. Normally, the server remembers that it already completed the request (it keeps a list of recently-completed requests and replies), and simply retransmits the reply. However, when the server has rebooted or when it has been very busy, the server no longer remembers that it already completed the request, and repeats the operation. This causes no problems with file read/write requests (they contain a file offset and can therefore be repeated safely), but fails with non- idempotent operations. For example, when the server executes a retransmitted rename() request, the server reports an ENOENT error because the old name does not exist; and when the server executes a retransmitted link(), mkdir() or create() request, the server reports an EEXIST error because the name already exists. Thus, successful, non-idempotent, NFS operations will report false errors when the server reply is lost, the client retransmits the request, and the server does not remember that it already completed the request. README_FILES/FILTER_README000066600000066055150501202770010367 0ustar00PPoossttffiixx AAfftteerr--QQuueeuuee CCoonntteenntt FFiilltteerr ------------------------------------------------------------------------------- IInnttrroodduuccttiioonn This document requires Postfix version 2.1 or later. Normally, Postfix receives mail, stores it in the mail queue and then delivers it. With the external content filter described here, mail is filtered AFTER it is queued. This approach decouples mail receiving processes from mail filtering processes, and gives you maximal control over how many filtering processes you are willing to run in parallel. The after-queue content filter is meant to be used as follows: Network or -> Postfix -> CCoonntteenntt -> Postfix -> Network or local users queue ffiilltteerr queue local mailbox This document describes implementations that use a single Postfix instance for everything: receiving, filtering and delivering mail. Applications that use two separate Postfix instances will be covered by a later version of this document. The after-queue content filter is not to be confused with the approaches described in the SMTPD_PROXY_README or MILTER_README documents, where incoming SMTP mail is filtered BEFORE it is stored into the Postfix queue. This document describes two approaches to content filter all email, as well as several options to filter mail selectively: * Principles of operation * Simple content filter o Simple content filter example o Simple content filter performance o Simple content filter limitations o Turning off the simple content filter * Advanced content filter o Advanced content filter example o Advanced content filter performance o Turning off the advanced content filter * Selective content filtering o Filtering mail from outside users only o Different filters for different domains o FILTER actions in access or header/body tables PPrriinncciipplleess ooff ooppeerraattiioonn An after-queue content filter receives unfiltered mail from Postfix (as described further below) and can do one of the following: 1. Re-inject the mail back into Postfix, perhaps after changing content and/or destination. 2. Discard or quarantine the mail. 3. Reject the mail (by sending a suitable status code back to Postfix). Postfix will send the mail back to the sender address. NOTE: in this time of mail worms and forged spam, it is a VERY BAD IDEA to send viruses back to the sender address, because the sender address is almost certainly not the originator. It is better to discard known viruses, and to quarantine material that is suspect so that a human can decide what to do with it. SSiimmppllee ccoonntteenntt ffiilltteerr eexxaammppllee The first example is simple to set up, but has major limitations that will be addressed in a second example. Postfix receives unfiltered mail from the network with the smtpd(8) server, and delivers unfiltered mail to a content filter with the Postfix pipe(8) delivery agent. The content filter injects filtered mail back into Postfix with the Postfix sendmail(1) command, so that Postfix can deliver it to the final destination. This means that mail submitted via the Postfix sendmail(1) command cannot be content filtered. In the figure below, names followed by a number represent Postfix commands or daemon programs. See the OVERVIEW document for an introduction to the Postfix architecture. Unfiltered -> smtpd(8) qmgr(8) local(8) -> Filtered >- cleanup(8) -> Postfix -< smtp(8) -> Filtered pickup(8) queue pipe(8) ^ | | v maildrop Postfix Postfix Content queue <- postdrop <- sendmail <- filter (1) (1) The content filter can be a simple shell script like this: 1 #!/bin/sh 2 3 # Simple shell-based filter. It is meant to be invoked as follows: 4 # /path/to/script -f sender recipients... 5 6 # Localize these. The -G option does nothing before Postfix 2.3. 7 INSPECT_DIR=/var/spool/filter 8 SENDMAIL="/usr/sbin/sendmail -G -i" # NEVER NEVER NEVER use "-t" here. 9 10 # Exit codes from 11 EX_TEMPFAIL=75 12 EX_UNAVAILABLE=69 13 14 # Clean up when done or when aborting. 15 trap "rm -f in.$$" 0 1 2 3 15 16 17 # Start processing. 18 cd $INSPECT_DIR || { 19 echo $INSPECT_DIR does not exist; exit $EX_TEMPFAIL; } 20 21 cat >in.$$ || { 22 echo Cannot save mail to file; exit $EX_TEMPFAIL; } 23 24 # Specify your content filter here. 25 # filter smtpd(8) qmgr(8) smtp(8) -> Filtered >- cleanup(8) -> Postfix -< Unfiltered -> pickup(8) queue local(8) -> Filtered ^ | | v smtpd(8) smtp(8) 10026 ^ | | v content filter 10025 The example given here filters all mail, including mail that arrives via SMTP and mail that is locally submitted via the Postfix sendmail command (local submissions enter Postfix via the pickup(8) server; to keep the figure simple we omit local submission details). See examples near the end of this document for how to exclude local users from filtering, or how to configure a destination dependent content filter. You can expect to lose about a factor of two in Postfix performance for mail that arrives and leaves via SMTP, provided that the content filter creates no temporary files. Each temporary file created by the content filter adds another factor to the performance loss. AAddvvaanncceedd ccoonntteenntt ffiilltteerr:: rreeqquueessttiinngg tthhaatt aallll mmaaiill iiss ffiilltteerreedd To enable the advanced content filter method for all mail, specify in main.cf: /etc/postfix/main.cf: content_filter = scan:localhost:10025 receive_override_options = no_address_mappings * The "content_filter" line causes Postfix to add one content filter request record to each incoming mail message, with content "scan:localhost:10025". The content filter request records are added by the smtpd(8) and pickup(8) servers (and qmqpd(8) if you decide to enable this service). * Content filter requests are stored in queue files; this is how Postfix keeps track of what mail needs filtering. When a queue file contains a content filter request, the queue manager will deliver the mail to the specified content filter regardless of its final destination. * The "receive_override_options" line disables address manipulation before the content filter, so that the content filter sees the original mail addresses instead of the result of virtual alias expansion, canonical mapping, automatic bcc, address masquerading, etc. AAddvvaanncceedd ccoonntteenntt ffiilltteerr:: sseennddiinngg uunnffiilltteerreedd mmaaiill ttoo tthhee ccoonntteenntt ffiilltteerr In this example, "scan" is an instance of the Postfix SMTP client with slightly different configuration parameters. This is how one would set up the service in the Postfix master.cf file: /etc/postfix/master.cf: # ============================================================= # service type private unpriv chroot wakeup maxproc command # (yes) (yes) (yes) (never) (100) # ============================================================= scan unix - - n - 10 smtp -o smtp_send_xforward_command=yes -o disable_mime_output_conversion=yes -o smtp_generic_maps= * This runs up to 10 content filters in parallel. Instead of a limit of 10 concurrent processes, use whatever process limit is feasible for your machine. Content inspection software can gobble up a lot of system resources, so you don't want to have too much of it running at the same time. * With "-o smtp_send_xforward_command=yes", the scan transport will try to forward the original client name and IP address through the content filter to the after-filter smtpd process, so that filtered mail is logged with the real client name IP address. See smtp(8) and XFORWARD_README for more information. * The "-o disable_mime_output_conversion=yes" is a workaround that prevents the breaking of domainkeys and other digital signatures. This is needed because some SMTP-based content filters don't announce 8BITMIME support, even though they can handle 8-bit mail. * The "-o smtp_generic_maps=" is a workaround that prevents local address rewriting with generic(5) maps. Such rewriting should happen only when mail is sent out to the Internet. AAddvvaanncceedd ccoonntteenntt ffiilltteerr:: rruunnnniinngg tthhee ccoonntteenntt ffiilltteerr The content filter can be set up with the Postfix spawn service, which is the Postfix equivalent of inetd. For example, to instantiate up to 10 content filtering processes on localhost port 10025: /etc/postfix/master.cf: # =================================================================== # service type private unpriv chroot wakeup maxproc command # (yes) (yes) (yes) (never) (100) # =================================================================== localhost:10025 inet n n n - 10 spawn user=filter argv=/path/to/filter localhost 10026 * "filter" is a dedicated local user account. The user will never log in, and can be given a "*" password and non-existent shell and home directory. This user handles all potentially dangerous mail content - that is why it should be a separate account. * By default, Postfix will terminate a command that runs longer than command_time_limit seconds (default: 1000s). This is a safety measure that prevents filters from running forever. If you want to have your filter listening on port localhost:10025 instead of Postfix, then you must run your filter as a stand-alone program, and must not use the Postfix spawn service. AAddvvaanncceedd ffiilltteerr:: iinnjjeeccttiinngg mmaaiill bbaacckk iinnttoo PPoossttffiixx The job of the content filter is to either bounce mail with a suitable diagnostic, or to feed the mail back into Postfix through a dedicated listener on port localhost 10026. The simplest content filter just copies SMTP commands and data between its inputs and outputs. If it has a problem, all it has to do is to reply to an input of `.' from Postfix with `550 content rejected', and to disconnect without sending `.' on the connection that injects mail back into Postfix. /etc/postfix/master.cf: # =================================================================== # service type private unpriv chroot wakeup maxproc command # (yes) (yes) (yes) (never) (100) # =================================================================== localhost:10026 inet n - n - 10 smtpd -o content_filter= - o receive_override_options=no_unknown_recipient_checks,no_header_body_checks,no_milters -o smtpd_helo_restrictions= -o smtpd_client_restrictions= -o smtpd_sender_restrictions= -o smtpd_recipient_restrictions=permit_mynetworks,reject -o mynetworks=127.0.0.0/8 -o smtpd_authorized_xforward_hosts=127.0.0.0/8 * NOTE: do not use spaces around the "=" or "," characters. * NOTE: the SMTP server must not have a smaller process limit than the "filter" master.cf entry. * The "-o content_filter=" overrides main.cf settings, and requests no content filtering for mail from the content filter. This is required or else mail will loop. * The "-o receive_override_options" overrides main.cf settings to avoid duplicating work that was already done before the content filter. These options are complementary to the options that are specified in main.cf: o We specify "no_unknown_recipient_checks" to disable attempts to find out if a recipient is unknown. o We specify "no_header_body_checks" to disable header/body checks. o We specify "no_milters" to disable Milter applications (this option is available only in Postfix 2.3 and later). o We don't specify "no_address_mappings" here. This enables virtual alias expansion, canonical mappings, address masquerading, and other address mappings after the content filter. The main.cf setting of "receive_override_options" disables these mappings before the content filter. These receive override options are either implemented by the SMTP server itself, or they are passed on to the cleanup server. * The "-o smtpd_xxx_restrictions" and "-o mynetworks=127.0.0.0/8" override main.cf settings. They turn off junk mail controls that would only waste time here. * With "-o smtpd_authorized_xforward_hosts=127.0.0.0/8", the scan transport will try to forward the original client name and IP address to the after- filter smtpd process, so that filtered mail is logged with the real client name and IP address. See XFORWARD_README and smtpd(8). AAddvvaanncceedd ccoonntteenntt ffiilltteerr ppeerrffoorrmmaannccee With the "sandwich" approach to content filtering described here, it is important to match the filter concurrency to the available CPU, memory and I/ O resources. Too few content filter processes and mail accumulates in the active queue even with low traffic volume; too much concurrency and Postfix ends up deferring mail destined for the content filter because processes fail due to insufficient resources. Currently, content filter performance tuning is a process of trial and error; analysis is handicapped because filtered and unfiltered messages share the same queue. As mentioned in the introduction of this document, content filtering with multiple Postfix instances will be covered in a future version. TTuurrnniinngg ooffff tthhee aaddvvaanncceedd ccoonntteenntt ffiilltteerr To turn off "advanced" content filtering: * Delete or comment out the two following main.cf lines. The other changes made for advanced content filtering have no effect when content filtering is turned off. /etc/postfix/main.cf: content_filter = scan:localhost:10025 receive_override_options = no_address_mappings * Execute "ppoossttssuuppeerr --rr AALLLL" to remove content filter request records from existing queue files. * Execute another "ppoossttffiixx rreellooaadd". FFiilltteerriinngg mmaaiill ffrroomm oouuttssiiddee uusseerrss oonnllyy The easiest approach is to configure ONE Postfix instance with multiple SMTP server IP addresses in master.cf: * Two SMTP server IP addresses for mail from inside users only, with content filtering turned off. /etc/postfix.master.cf: # ================================================================== # service type private unpriv chroot wakeup maxproc command # (yes) (yes) (yes) (never) (100) # ================================================================== 1.2.3.4:smtp inet n - n - - smtpd -o smtpd_client_restrictions=permit_mynetworks,reject 127.0.0.1:smtp inet n - n - - smtpd -o smtpd_client_restrictions=permit_mynetworks,reject * One SMTP server address for mail from outside users with content filtering turned on. /etc/postfix.master.cf: # ================================================================= # service type private unpriv chroot wakeup maxproc command # (yes) (yes) (yes) (never) (100) # ================================================================= 1.2.3.5:smtp inet n - n - - smtpd -o content_filter=filter-service:filter-destination -o receive_override_options=no_address_mappings After this, you can follow the same procedure as outlined in the "advanced" or "simple" content filtering examples above, except that you must not specify "content_filter" or "receive_override_options" in the main.cf file. DDiiffffeerreenntt ffiilltteerrss ffoorr ddiiffffeerreenntt ddoommaaiinnss If you are an MX service provider and want to apply different content filters for different domains, you can configure ONE Postfix instance with multiple SMTP server IP addresses in master.cf. Each address provides a different content filter service. /etc/postfix.master.cf: # ================================================================= # service type private unpriv chroot wakeup maxproc command # (yes) (yes) (yes) (never) (100) # ================================================================= # SMTP service for domains that are filtered with service1:dest1 1.2.3.4:smtp inet n - n - - smtpd -o content_filter=service1:dest1 -o receive_override_options=no_address_mappings # SMTP service for domains that are filtered with service2:dest2 1.2.3.5:smtp inet n - n - - smtpd -o content_filter=service2:dest2 -o receive_override_options=no_address_mappings After this, you can follow the same procedure as outlined in the "advanced" or "simple" content filtering examples above, except that you must not specify "content_filter" or "receive_override_options" in the main.cf file. Set up MX records in the DNS that route each domain to the proper SMTP server instance. FFIILLTTEERR aaccttiioonnss iinn aacccceessss oorr hheeaaddeerr//bbooddyy ttaabblleess The above filtering configurations are static. Mail that follows a given path is either always filtered or it is never filtered. As of Postfix 2.0 you can also turn on content filtering on the fly. To turn on content filtering with an access(5) table rule: /etc/postfix/access: whatever FILTER foo:bar To turn on content filtering with a header_checks(5) or body_checks(5) table pattern: /etc/postfix/header_checks: /whatever/ FILTER foo:bar You can do this in smtpd access maps as well as the cleanup server's header/ body_checks. This feature must be used with great care: you must disable all the UCE features in the after-filter smtpd and cleanup daemons or else you will have a content filtering loop. Limitations: * FILTER actions from smtpd access maps and header/body_checks take precedence over filters specified with the main.cf content_filter parameter. * If a message triggers more than one filter action, only the last one takes effect. * The same content filter is applied to all the recipients of a given message. README_FILES/SMTPD_PROXY_README000066600000024740150501202770011265 0ustar00PPoossttffiixx BBeeffoorree--QQuueeuuee CCoonntteenntt FFiilltteerr ------------------------------------------------------------------------------- WWAARRNNIINNGG The before-queue content filtering feature described in this document is suitable only for low-traffic sites. See the "Pros and Cons" section below for details. TThhee PPoossttffiixx bbeeffoorree--qquueeuuee ccoonntteenntt ffiilltteerr ffeeaattuurree As of version 2.1, the Postfix SMTP server can forward all incoming mail to a content filtering proxy server that inspects all mail BEFORE it is stored in the Postfix mail queue. It is roughly equivalent in capabilities to the approach described in MILTER_README, except that the latter uses a dedicated protocol instead of SMTP. The before-queue content filter is meant to be used as follows: Postfix BBeeffoorree Postfix Postfix Postfix smtp Internet -> SMTP -> qquueeuuee -> SMTP -> cleanup -> queue -< local server ffiilltteerr server server virtual The before-queue content filter is not to be confused with the approach described in the FILTER_README document, where mail is filtered AFTER it is stored in the Postfix mail queue. This document describes the following topics: * Principles of operation * Pros and cons of before-queue content filtering * Configuring the Postfix SMTP pass-through proxy feature * Configuration parameters * How Postfix talks to the before-queue content filter PPrriinncciipplleess ooff ooppeerraattiioonn The before-filter Postfix SMTP server accepts connections from the Internet and does the usual relay access control, SASL authentication, TLS negotiation, RBL lookups, rejecting non-existent sender or recipient addresses, etc. The before- queue filter receives unfiltered mail content from Postfix and does one of the following: 1. Re-inject the mail back into Postfix via SMTP, perhaps after changing its content and/or destination. 2. Discard or quarantine the mail. 3. Reject the mail by sending a suitable SMTP status code back to Postfix. Postfix passes the status back to the remote SMTP client. This way, Postfix does not have to send a bounce message. The after-filter Postfix SMTP server receives mail from the content filter. From then on Postfix processes the mail as usual. The before-queue content filter described here works just like the after-queue content filter described in the FILTER_README document. In many cases you can use the same software, within the limitations as discussed in the "Pros and Cons" section below. PPrrooss aanndd ccoonnss ooff bbeeffoorree--qquueeuuee ccoonntteenntt ffiilltteerriinngg * Pro: Postfix can reject mail before the incoming SMTP mail transfer completes, so that Postfix does not have to send rejected mail back to the sender (which is usually forged anyway). Mail that is not accepted remains the responsibility of the remote SMTP client. * Con: The remote SMTP client expects an SMTP reply within a deadline. As the system load increases, fewer and fewer CPU cycles remain available to answer within the deadline, and eventually you either have to stop accepting mail or you have to stop filtering mail. It is for this reason that the before-queue content filter can be used only on low-traffic sites. * Con: Content filtering software can use lots of memory resources. In order to not run out of memory you have to reduce the number of before-filter SMTP server processes so that a burst of mail will not drive your system into the ground with too many content filter processes. This, in turn, means that SMTP clients have to wait for a long time before they receive service. CCoonnffiigguurriinngg tthhee PPoossttffiixx SSMMTTPP ppaassss--tthhrroouugghh pprrooxxyy ffeeaattuurree In the following example, the before-filter Postfix SMTP server gives mail to a content filter that listens on localhost port 10025. The after-filter Postfix SMTP server receives mail from the content filter via localhost port 10026. From then on mail is processed as usual. The content filter itself is not described here. You can use any filter that is SMTP enabled. For non-SMTP capable content filtering software, Bennett Todd's SMTP proxy implements a nice PERL/SMTP content filtering framework. See: http:/ /bent.latency.net/smtpprox/. Postfix Postfix filter on SMTP server Postfix Postfix Internet -> SMTP server -> localhost -> on -> cleanup -> incoming on port 25 port 10025 localhost server queue port 10026 This is configured by editing the master.cf file: /etc/postfix/master.cf: # ============================================================= # service type private unpriv chroot wakeup maxproc command # (yes) (yes) (yes) (never) (100) # ============================================================= # # Before-filter SMTP server. Receive mail from the network and # pass it to the content filter on localhost port 10025. # smtp inet n - n - 20 smtpd -o smtpd_proxy_filter=127.0.0.1:10025 -o smtpd_client_connection_count_limit=10 # # After-filter SMTP server. Receive mail from the content filter # on localhost port 10026. # 127.0.0.1:10026 inet n - n - - smtpd -o smtpd_authorized_xforward_hosts=127.0.0.0/8 -o smtpd_client_restrictions= -o smtpd_helo_restrictions= -o smtpd_sender_restrictions= -o smtpd_recipient_restrictions=permit_mynetworks,reject -o smtpd_data_restrictions= -o mynetworks=127.0.0.0/8 -o receive_override_options=no_unknown_recipient_checks Note: do not specify spaces around the "=" or "," characters. The before-filter SMTP server entry is a modified version of the default Postfix SMTP server entry that is normally configured at the top of the master.cf file: * The number of SMTP sessions is reduced from the default 100 to only 20. This prevents a burst of mail from running your system into the ground with too many content filter processes. * The "-o smtpd_client_connection_count_limit=10" prevents one SMTP client from using up all 20 SMTP server processes. This limit is not necessary if you receive all mail from a trusted relay host. Note: this setting is available in Postfix version 2.2 and later. Earlier Postfix versions will ignore it. * The "-o smtpd_proxy_filter=127.0.0.1:10025" tells the before filter SMTP server that it should give incoming mail to the content filter that listens on localhost TCP port 10025. * Postfix 2.3 supports both TCP and UNIX-domain filters. The above filter could be specified as "inet:127.0.0.1:10025". To specify a UNIX-domain filter, specify "unix:pathname". A relative pathname is interpreted relative to the Postfix queue directory. The after-filter SMTP server is a new master.cf entry: * The "127.0.0.1:10026" makes the after-filter SMTP server listen on the localhost address only, without exposing it to the network. NEVER expose the after-filter SMTP server to the Internet :-) * The "-o smtpd_authorized_xforward_hosts=127.0.0.0/8" allows the after- filter SMTP server to receive remote SMTP client information from the before filter SMTP server, so that the after-filter Postfix daemons log the remote SMTP client information instead of logging localhost[127.0.0.1]. * The other after-filter SMTP server settings avoid duplication of work that is already done in the "before filter" SMTP server. By default, the filter has 100 seconds to do its work. If it takes longer then Postfix gives up and reports an error to the remote SMTP client. You can increase this time limit (see configuration parameter section below) but doing so is pointless because you can't control when the remote SMTP client times out. CCoonnffiigguurraattiioonn ppaarraammeetteerrss Parameters that control proxying: * smtpd_proxy_filter (syntax: host:port): The host and TCP port of the before-queue content filter. When no host or host: is specified here, localhost is assumed. * smtpd_proxy_timeout (default: 100s): Timeout for connecting to the before- queue content filter and for sending and receiving commands and data. All proxy errors are logged to the maillog file. For privacy reasons, all the remote SMTP client sees is "451 Error: queue file write error". It would not be right to disclose internal details to strangers. * smtpd_proxy_ehlo (default: $myhostname): The hostname to use when sending an EHLO command to the before-queue content filter. HHooww PPoossttffiixx ttaallkkss ttoo tthhee bbeeffoorree--qquueeuuee ccoonntteenntt ffiilltteerr The before-filter Postfix SMTP server connects to the content filter, delivers one message, and disconnects. While sending mail into the content filter, Postfix speaks ESMTP but uses no command pipelining. Postfix generates its own EHLO, XFORWARD (for logging the remote client IP address instead of localhost [127.0.0.1]), DATA and QUIT commands, and forwards unmodified copies of all the MAIL FROM and RCPT TO commands that the before-filter Postfix SMTP server didn't reject itself. Postfix sends no other SMTP commands. The content filter should accept the same MAIL FROM and RCPT TO command syntax as the before-filter Postfix SMTP server, and should forward the commands without modification to the after-filter SMTP server. If the content filter or after-filter SMTP server does not support all the ESMTP features that the before-filter Postfix SMTP server supports, then the missing features must be turned off in the before-filter Postfix SMTP server with the smtpd_discard_ehlo_keywords parameter. When the filter rejects content, it should send a negative SMTP response back to the before-filter Postfix SMTP server, and it should abort the connection with the after-filter Postfix SMTP server without completing the SMTP conversation with the after-filter Postfix SMTP server. README_FILES/PACKAGE_README000066600000012721150501202770010424 0ustar00GGuuiiddeelliinneess ffoorr PPaacckkaaggee BBuuiillddeerrss ------------------------------------------------------------------------------- PPuurrppoossee ooff tthhiiss ddooccuummeenntt This document has hints and tips for those who manage their own Postfix distribution for internal use, and for those who maintain Postfix distributions for general use. GGeenneerraall ddiissttrriibbuuttiioonnss:: pplleeaassee pprroovviiddee aa ssmmaallll ddeeffaauulltt mmaaiinn..ccff ffiillee The installed main.cf file must be small. PLEASE resist the temptation to list all parameters in the main.cf file. Postfix is supposed to be easy to configure. Listing all parameters in main.cf defeats the purpose. It is an invitation for hobbyists to make random changes without understanding what they do, and gets them into endless trouble. GGeenneerraall ddiissttrriibbuuttiioonnss:: pplleeaassee iinncclluuddee RREEAADDMMEE oorr HHTTMMLL ffiilleess Please provide the applicable README or HTML files. They are referenced by the Postfix manual pages and by other files. Without README or HTML files, Postfix will be difficult if not impossible to configure. PPoossttffiixx IInnssttaallllaattiioonn ppaarraammeetteerrss Postfix installation is controlled by a dozen installation parameters. See the postfix-install and post-install files for details. Most parameters have system-dependent default settings that are configurable at compile time, as described in the INSTALL file. PPrreeppaarriinngg aa pprree--bbuuiilltt ppaacckkaaggee ffoorr ddiissttrriibbuuttiioonn ttoo ootthheerr ssyysstteemmss You can build a Postfix package on a machine that does not have Postfix installed on it. All you need is Postfix source code and a compilation environment that is compatible with the target system. You can build a pre-built Postfix package as an unprivileged user. First compile Postfix. After successful compilation, execute: % mmaakkee ppaacckkaaggee With Postfix versions before 2.2 you must invoke the post-install script directly (% sshh ppoosstt--iinnssttaallll). You will be prompted for installation parameters. Specify an install_root directory other than /. The mail_owner and setgid_group installation parameter settings will be recorded in the main.cf file, but they won't take effect until the package is unpacked and installed on the destination machine. If you want to fully automate this process, specify all the non-default installation parameters on the command line: % mmaakkee nnoonn--iinntteerraaccttiivvee--ppaacckkaaggee iinnssttaallll__rroooott==//ssoommee//wwhheerree... With Postfix versions before 2.2 you must invoke the post-install script directly (% sshh ppoosstt--iinnssttaallll --nnoonn--iinntteerraaccttiivvee iinnssttaallll__rroooott......). BBeeggiinn SSeeccuurriittyy AAlleerrtt WWhheenn bbuuiillddiinngg aann aarrcchhiivvee ffoorr ddiissttrriibbuuttiioonn,, bbee ssuurree ttoo aarrcchhiivvee oonnllyy ffiilleess aanndd ssyymmbboolliicc lliinnkkss,, nnoott tthheeiirr ppaarreenntt ddiirreeccttoorriieess.. OOtthheerrwwiissee,, uunnppaacckkiinngg aa pprree--bbuuiilltt PPoossttffiixx ppaacckkaaggee mmaayy mmeessss uupp ppeerrmmiissssiioonn aanndd//oorr oowwnneerrsshhiipp ooff ssyysstteemm ddiirreeccttoorriieess ssuucchh aass // //eettcc //uussrr //uussrr//bbiinn //vvaarr //vvaarr//ssppooooll aanndd ssoo oonn.. TThhiiss iiss eessppeecciiaallllyy aann iissssuuee iiff yyoouu eexxeeccuutteedd ppoossttffiixx--iinnssttaallll ((sseeee aabboovvee)) aass aann uunnpprriivviilleeggeedd uusseerr.. EEnndd SSeeccuurriittyy AAlleerrtt Thus, to tar up the pre-built package, take the following steps: % cd INSTALL_ROOT % rm -f SOMEWHERE/outputfile % find . \! -type d -print | xargs tar rf SOMEWHERE/outputfile % gzip SOMEWHERE/outputfile This way you will not include any directories that might cause trouble upon extraction. IInnssttaalllliinngg aa pprree--bbuuiilltt PPoossttffiixx ppaacckkaaggee * To unpack a pre-built Postfix package, execute the equivalent of: # umask 022 # gzip -d /dev/null do sleep 10 done If you have disabled spontaneous SMTP mail delivery, you also need to run the "sseennddmmaaiill --qq" command every now and then while the dialup link is up, so that newly-posted mail is flushed from the queue. PPoossttffiixx oonn hhoossttss wwiitthhoouutt aa rreeaall IInntteerrnneett hhoossttnnaammee This section is for hosts that don't have their own Internet hostname. Typically these are systems that get a dynamic IP address via DHCP or via dialup. Postfix will let you send and receive mail just fine between accounts on a machine with a fantasy name. However, you cannot use a fantasy hostname in your email address when sending mail into the Internet, because no-one would be able to reply to your mail. In fact, more and more sites refuse mail addresses with non-existent domain names. Note: the following information is Postfix version dependent. To find out what Postfix version you have, execute the command "ppoossttccoonnff mmaaiill__vveerrssiioonn". SSoolluuttiioonn 11:: PPoossttffiixx vveerrssiioonn 22..22 aanndd llaatteerr Postfix 2.2 uses the generic(5) address mapping to replace local fantasy email addresses by valid Internet addresses. This mapping happens ONLY when mail leaves the machine; not when you send mail between users on the same machine. The following example presents additional configuration. You need to combine this with basic configuration information as discussed the first half of this document. 1 /etc/postfix/main.cf: 2 smtp_generic_maps = hash:/etc/postfix/generic 3 4 /etc/postfix/generic: 5 his@localdomain.local hisaccount@hisisp.example 6 her@localdomain.local heraccount@herisp.example 7 @localdomain.local hisaccount+local@hisisp.example When mail is sent to a remote host via SMTP: * Line 5 replaces his@localdomain.local by his ISP mail address, * Line 6 replaces her@localdomain.local by her ISP mail address, and * Line 7 replaces other local addresses by his ISP account, with an address extension of +local (this example assumes that the ISP supports "+" style address extensions). Specify ddbbmm instead of hhaasshh if your system uses ddbbmm files instead of ddbb files. To find out what lookup tables Postfix supports, use the command "ppoossttccoonnff --mm". Execute the command "ppoossttmmaapp //eettcc//ppoossttffiixx//ggeenneerriicc" whenever you change the generic table. SSoolluuttiioonn 22:: PPoossttffiixx vveerrssiioonn 22..11 aanndd eeaarrlliieerr The solution with older Postfix systems is to use valid Internet addresses where possible, and to let Postfix map valid Internet addresses to local fantasy addresses. With this, you can send mail to the Internet and to local fantasy addresses, including mail to local fantasy addresses that don't have a valid Internet address of their own. The following example presents additional configuration. You need to combine this with basic configuration information as discussed the first half of this document. 1 /etc/postfix/main.cf: 2 myhostname = hostname.localdomain 3 mydomain = localdomain 4 5 canonical_maps = hash:/etc/postfix/canonical 6 7 virtual_alias_maps = hash:/etc/postfix/virtual 8 9 /etc/postfix/canonical: 10 your-login-name your-account@your-isp.com 11 12 /etc/postfix/virtual: 13 your-account@your-isp.com your-login-name Translation: * Lines 2-3: Substitute your fantasy hostname here. Do not use a domain name that is already in use by real organizations on the Internet. See RFC 2606 for examples of domain names that are guaranteed not to be owned by anyone. * Lines 5, 9, 10: This provides the mapping from "your-login- name@hostname.localdomain" to "your-account@your-isp.com". This part is required. * Lines 7, 12, 13: Deliver mail for "your-account@your-isp.com" locally, instead of sending it to the ISP. This part is not required but is convenient. Specify ddbbmm instead of hhaasshh if your system uses ddbbmm files instead of ddbb files. To find out what lookup tables Postfix supports, use the command "ppoossttccoonnff --mm". Execute the command "ppoossttmmaapp //eettcc//ppoossttffiixx//ccaannoonniiccaall" whenever you change the canonical table. Execute the command "ppoossttmmaapp //eettcc//ppoossttffiixx//vviirrttuuaall" whenever you change the virtual table. README_FILES/SCHEDULER_README000066600000202071150501202770010706 0ustar00PPoossttffiixx QQuueeuuee SScchheedduulleerr ------------------------------------------------------------------------------- OOvveerrvviieeww The queue manager is by far the most complex part of the Postfix mail system. It schedules delivery of new mail, retries failed deliveries at specific times, and removes mail from the queue after the last delivery attempt. There are two major classes of mechanisms that control the operation of the queue manager. Topics covered by this document: * Concurrency scheduling, concerned with the number of concurrent deliveries to a specific destination, including decisions on when to suspend deliveries after persistent failures. * Preemptive scheduling, concerned with the selection of email messages and recipients for a given destination. * Credits, something this document would not be complete without. CCoonnccuurrrreennccyy sscchheedduulliinngg The following sections document the Postfix 2.5 concurrency scheduler, after a discussion of the limitations of the existing concurrency scheduler. This is followed by results of medium-concurrency experiments, and a discussion of trade-offs between performance and robustness. The material is organized as follows: * Drawbacks of the existing concurrency scheduler * Summary of the Postfix 2.5 concurrency feedback algorithm * Summary of the Postfix 2.5 "dead destination" detection algorithm * Pseudocode for the Postfix 2.5 concurrency scheduler * Results for delivery to concurrency limited servers * Discussion of concurrency limited server results * Limitations of less-than-1 per delivery feedback * Concurrency configuration parameters DDrraawwbbaacckkss ooff tthhee eexxiissttiinngg ccoonnccuurrrreennccyy sscchheedduulleerr From the start, Postfix has used a simple but robust algorithm where the per- destination delivery concurrency is decremented by 1 after delivery failed due to connection or handshake failure, and incremented by 1 otherwise. Of course the concurrency is never allowed to exceed the maximum per-destination concurrency limit. And when a destination's concurrency level drops to zero, the destination is declared "dead" and delivery is suspended. Drawbacks of +/-1 concurrency feedback per delivery are: * Overshoot due to exponential delivery concurrency growth with each pseudo- cohort(*). This can be an issue with high-concurrency channels. For example, with the default initial concurrency of 5, concurrency would proceed over time as (5-10-20). * Throttling down to zero concurrency after a single pseudo-cohort(*) failure. This was especially an issue with low-concurrency channels where a single failure could be sufficient to mark a destination as "dead", causing the suspension of further deliveries to the affected destination. (*) A pseudo-cohort is a number of delivery requests equal to a destination's delivery concurrency. The revised concurrency scheduler has a highly modular structure. It uses separate mechanisms for per-destination concurrency control and for "dead destination" detection. The concurrency control in turn is built from two separate mechanisms: it supports less-than-1 feedback per delivery to allow for more gradual concurrency adjustments, and it uses feedback hysteresis to suppress concurrency oscillations. And instead of waiting for delivery concurrency to throttle down to zero, a destination is declared "dead" after a configurable number of pseudo-cohorts reports connection or handshake failure. SSuummmmaarryy ooff tthhee PPoossttffiixx 22..55 ccoonnccuurrrreennccyy ffeeeeddbbaacckk aallggoorriitthhmm We want to increment a destination's delivery concurrency when some (not necessarily consecutive) number of deliveries complete without connection or handshake failure. This is implemented with positive feedback g(N) where N is the destination's delivery concurrency. With g(N)=1 feedback per delivery, concurrency increases by 1 after each positive feedback event; this gives us the old scheduler's exponential growth in time. With g(N)=1/N feedback per delivery, concurrency increases by 1 after an entire pseudo-cohort N of positive feedback reports; this gives us linear growth in time. Less-than- 1 feedback per delivery and integer truncation naturally give us hysteresis, so that transitions to larger concurrency happen every 1/g(N) positive feedback events. We want to decrement a destination's delivery concurrency when some (not necessarily consecutive) number of deliveries complete after connection or handshake failure. This is implemented with negative feedback f(N) where N is the destination's delivery concurrency. With f(N)=1 feedback per delivery, concurrency decreases by 1 after each negative feedback event; this gives us the old scheduler's behavior where concurrency is throttled down dramatically after a single pseudo-cohort failure. With f(N)=1/N feedback per delivery, concurrency backs off more gently. Again, less-than-1 feedback per delivery and integer truncation naturally give us hysteresis, so that transitions to lower concurrency happen every 1/f(N) negative feedback events. However, with negative feedback we introduce a subtle twist. We "reverse" the negative hysteresis cycle so that the transition to lower concurrency happens at the bbeeggiinnnniinngg of a sequence of 1/f(N) negative feedback events. Otherwise, a correction for overload would be made too late. This makes the choice of f(N) relatively unimportant, as borne out by measurements later in this document. In summary, the main ingredients for the Postfix 2.5 concurrency feedback algorithm are a) the option of less-than-1 positive feedback per delivery to avoid overwhelming servers, b) the option of less-than-1 negative feedback per delivery to avoid giving up too fast, c) feedback hysteresis to avoid rapid oscillation, and d) a "reverse" hysteresis cycle for negative feedback, so that it can correct for overload quickly. SSuummmmaarryy ooff tthhee PPoossttffiixx 22..55 ""ddeeaadd ddeessttiinnaattiioonn"" ddeetteeccttiioonn aallggoorriitthhmm We want to suspend deliveries to a specific destination after some number of deliveries suffers connection or handshake failure. The old scheduler declares a destination "dead" when negative (-1) feedback throttles the delivery concurrency down to zero. With less-than-1 feedback per delivery, this throttling down would obviously take too long. We therefore have to separate "dead destination" detection from concurrency feedback. This is implemented by introducing the concept of pseudo-cohort failure. The Postfix 2.5 concurrency scheduler declares a destination "dead" after a configurable number of pseudo- cohorts suffers from connection or handshake failures. The old scheduler corresponds to the special case where the pseudo-cohort failure limit is equal to 1. PPsseeuuddooccooddee ffoorr tthhee PPoossttffiixx 22..55 ccoonnccuurrrreennccyy sscchheedduulleerr The pseudo code shows how the ideas behind new concurrency scheduler are implemented as of November 2007. The actual code can be found in the module qmgr/qmgr_queue.c. Types: Each destination has one set of the following variables int concurrency double success double failure double fail_cohorts Feedback functions: N is concurrency; x, y are arbitrary numbers in [0..1] inclusive positive feedback: g(N) = x/N | x/sqrt(N) | x negative feedback: f(N) = y/N | y/sqrt(N) | y Initialization: concurrency = initial_concurrency success = 0 failure = 0 fail_cohorts = 0 After success: fail_cohorts = 0 Be prepared for feedback > hysteresis, or rounding error success += g(concurrency) while (success >= 1) Hysteresis 1 concurrency += 1 Hysteresis 1 failure = 0 success -= 1 Hysteresis 1 Be prepared for overshoot if (concurrency > concurrency limit) concurrency = concurrency limit Safety: Don't apply positive feedback unless concurrency < busy_refcount + init_dest_concurrency otherwise negative feedback effect could be delayed After failure: if (concurrency > 0) fail_cohorts += 1.0 / concurrency if (fail_cohorts > cohort_failure_limit) concurrency = 0 if (concurrency > 0) Be prepared for feedback > hysteresis, rounding errors failure -= f(concurrency) while (failure < 0) concurrency -= 1 Hysteresis 1 failure += 1 Hysteresis 1 success = 0 Be prepared for overshoot if (concurrency < 1) concurrency = 1 RReessuullttss ffoorr ddeelliivveerryy ttoo ccoonnccuurrrreennccyy--lliimmiitteedd sseerrvveerrss Discussions about the concurrency scheduler redesign started early 2004, when the primary goal was to find alternatives that did not exhibit exponential growth or rapid concurrency throttling. No code was implemented until late 2007, when the primary concern had shifted towards better handling of server concurrency limits. For this reason we measure how well the new scheduler does this job. The table below compares mail delivery performance of the old +/- 1 feedback per delivery with several less-than-1 feedback functions, for different limited-concurrency server scenarios. Measurements were done with a FreeBSD 6.2 client and with FreeBSD 6.2 and various Linux servers. Server configuration: * The mail flow was slowed down with 1 second latency per recipient ("smtpd_client_restrictions = sleep 1"). The purpose was to make results less dependent on hardware details, by avoiding slow-downs by queue file I/ O, logging I/O, and network I/O. * Concurrency was limited by the server process limit ("default_process_limit = 5" and "smtpd_client_event_limit_exceptions = static:all"). Postfix was stopped and started after changing the process limit, because the same number is also used as the backlog argument to the listen(2) system call, and "postfix reload" does not re-issue this call. * Mail was discarded with "local_recipient_maps = static:all" and "local_transport = discard". The discard action in access maps or header/ body checks could not be used as it fails to update the in_flow_delay counters. Client configuration: * Queue file overhead was minimized by sending one message to a virtual alias that expanded into 2000 different remote recipients. All recipients were accounted for according to the maillog file. The virtual_alias_expansion_limit setting was increased to avoid complaints from the cleanup(8) server. * The number of deliveries was maximized with "smtp_destination_recipient_limit = 2". A smaller limit would cause Postfix to schedule the concurrency per recipient instead of domain, which is not what we want. * Maximum concurrency was limited with "smtp_destination_concurrency_limit = 20", and initial_destination_concurrency was set to the same value. * The positive and negative concurrency feedback hysteresis was 1. Concurrency was incremented by 1 at the END of 1/feedback steps of positive feedback, and was decremented by 1 at the START of 1/feedback steps of negative feedback. * The SMTP client used the default 30s SMTP connect timeout and 300s SMTP greeting timeout. IImmppaacctt ooff tthhee 3300ss SSMMTTPP ccoonnnneecctt ttiimmeeoouutt The first results are for a FreeBSD 6.2 server, where our artificially low listen(2) backlog results in a very short kernel queue for established connections. The table shows that all deferred deliveries failed due to a 30s connection timeout, and none failed due to a server greeting timeout. This measurement simulates what happens when the server's connection queue is completely full under load, and the TCP engine drops new connections. cclliieenntt sseerrvveerr ffeeeeddbbaacckk ccoonnnneeccttiioonn ppeerrcceennttaaggee cclliieenntt ttiimmeedd--oouutt iinn lliimmiitt lliimmiitt ssttyyllee ccaacchhiinngg ddeeffeerrrreedd ccoonnccuurrrreennccyy ccoonnnneecctt// aavveerraaggee//ssttddddeevv ggrreeeettiinngg ------------------------------------------------------------------------- 20 5 1/N no 9.9 19.4 0.49 198 - 20 5 1/N yes 10.3 19.4 0.49 206 - 20 5 1/sqrt(N) no 10.4 19.6 0.59 208 - 20 5 1/sqrt(N) yes 10.6 19.6 0.61 212 - 20 5 1 no 10.1 19.5 1.29 202 - 20 5 1 yes 10.8 19.3 1.57 216 - ------------------------------------------------------------------------- A busy server with a completely full connection queue. N is the client delivery concurrency. Failed deliveries time out after 30s without completing the TCP handshake. See text for a discussion of results. IImmppaacctt ooff tthhee 330000ss SSMMTTPP ggrreeeettiinngg ttiimmeeoouutt The next table shows results for a Fedora Core 8 server (results for RedHat 7.3 are identical). In this case, the artificially small listen(2) backlog argument does not impact our measurement. The table shows that practically all deferred deliveries fail after the 300s SMTP greeting timeout. As these timeouts were 10x longer than with the first measurement, we increased the recipient count (and thus the running time) by a factor of 10 to keep the results comparable. The deferred mail percentages are a factor 10 lower than with the first measurement, because the 1s per-recipient delay was 1/300th of the greeting timeout instead of 1/30th of the connection timeout. cclliieenntt sseerrvveerr ffeeeeddbbaacckk ccoonnnneeccttiioonn ppeerrcceennttaaggee cclliieenntt ttiimmeedd--oouutt iinn lliimmiitt lliimmiitt ssttyyllee ccaacchhiinngg ddeeffeerrrreedd ccoonnccuurrrreennccyy ccoonnnneecctt// aavveerraaggee//ssttddddeevv ggrreeeettiinngg ------------------------------------------------------------------------- 20 5 1/N no 1.16 19.8 0.37 - 230 20 5 1/N yes 1.36 19.8 0.36 - 272 20 5 1/sqrt(N) no 1.21 19.9 0.23 4 238 20 5 1/sqrt(N) yes 1.36 20.0 0.23 - 272 20 5 1 no 1.18 20.0 0.16 - 236 20 5 1 yes 1.39 20.0 0.16 - 278 ------------------------------------------------------------------------- A busy server with a non-full connection queue. N is the client delivery concurrency. Failed deliveries complete at the TCP level, but time out after 300s while waiting for the SMTP greeting. See text for a discussion of results. IImmppaacctt ooff aaccttiivvee sseerrvveerr ccoonnccuurrrreennccyy lliimmiitteerr The final concurrency-limited result shows what happens when SMTP connections don't time out, but are rejected immediately with the Postfix server's smtpd_client_connection_count_limit feature (the server replies with a 421 status and disconnects immediately). Similar results can be expected with concurrency limiting features built into other MTAs or firewalls. For this measurement we specified a server concurrency limit and a client initial destination concurrency of 5, and a server process limit of 10; all other conditions were the same as with the first measurement. The same result would be obtained with a FreeBSD or Linux server, because the "pushing back" is done entirely by the receiving side. cclliieenntt sseerrvveerr ffeeeeddbbaacckk ccoonnnneeccttiioonn ppeerrcceennttaaggee cclliieenntt tthheeoorreettiiccaall lliimmiitt lliimmiitt ssttyyllee ccaacchhiinngg ddeeffeerrrreedd ccoonnccuurrrreennccyy ddeeffeerr rraattee aavveerraaggee//ssttddddeevv ------------------------------------------------------------------------- 20 5 1/N no 16.5 5.17 0.38 1/6 20 5 1/N yes 16.5 5.17 0.38 1/6 20 5 1/sqrt(N) no 24.5 5.28 0.45 1/4 20 5 1/sqrt(N) yes 24.3 5.28 0.46 1/4 20 5 1 no 49.7 5.63 0.67 1/2 20 5 1 yes 49.7 5.68 0.70 1/2 ------------------------------------------------------------------------- A server with active per-client concurrency limiter that replies with 421 and disconnects. N is the client delivery concurrency. The theoretical defer rate is 1/(1+roundup(1/feedback)). This is always 1/2 with the fixed +/-1 feedback per delivery; with the concurrency-dependent feedback variants, the defer rate decreases with increasing concurrency. See text for a discussion of results. DDiissccuussssiioonn ooff ccoonnccuurrrreennccyy--lliimmiitteedd sseerrvveerr rreessuullttss All results in the previous sections are based on the first delivery runs only; they do not include any second etc. delivery attempts. It's also worth noting that the measurements look at steady-state behavior only. They don't show what happens when the client starts sending at a much higher or lower concurrency. The first two examples show that the effect of feedback is negligible when concurrency is limited due to congestion. This is because the initial concurrency is already at the client's concurrency maximum, and because there is 10-100 times more positive than negative feedback. Under these conditions, it is no surprise that the contribution from SMTP connection caching is also negligible. In the last example, the old +/-1 feedback per delivery will defer 50% of the mail when confronted with an active (anvil-style) server concurrency limit, where the server hangs up immediately with a 421 status (a TCP-level RST would have the same result). Less aggressive feedback mechanisms fare better than more aggressive ones. Concurrency-dependent feedback fares even better at higher concurrencies than shown here, but has limitations as discussed in the next section. LLiimmiittaattiioonnss ooff lleessss--tthhaann--11 ppeerr ddeelliivveerryy ffeeeeddbbaacckk Less-than-1 feedback is of interest primarily when sending large amounts of mail to destinations with active concurrency limiters (servers that reply with 421, or firewalls that send RST). When sending small amounts of mail per destination, less-than-1 per-delivery feedback won't have a noticeable effect on the per-destination concurrency, because the number of deliveries to the same destination is too small. You might just as well use zero per-delivery feedback and stay with the initial per-destination concurrency. And when mail deliveries fail due to congestion instead of active concurrency limiters, the measurements above show that per-delivery feedback has no effect. With large amounts of mail you might just as well use zero per-delivery feedback and start with the maximal per-destination concurrency. The scheduler with less-than-1 concurrency feedback per delivery solves a problem with servers that have active concurrency limiters. This works only because feedback is handled in a peculiar manner: positive feedback will increment the concurrency by 1 at the eenndd of a sequence of events of length 1/ feedback, while negative feedback will decrement concurrency by 1 at the bbeeggiinnnniinngg of such a sequence. This is how Postfix adjusts quickly for overshoot without causing lots of mail to be deferred. Without this difference in feedback treatment, less-than-1 feedback per delivery would defer 50% of the mail, and would be no better in this respect than the old +/-1 feedback per delivery. Unfortunately, the same feature that corrects quickly for concurrency overshoot also makes the scheduler more sensitive for noisy negative feedback. The reason is that one lonely negative feedback event has the same effect as a complete sequence of length 1/feedback: in both cases delivery concurrency is dropped by 1 immediately. As a worst-case scenario, consider multiple servers behind a load balancer on a single IP address, and no backup MX address. When 1 out of K servers fails to complete the SMTP handshake or drops the connection, a scheduler with 1/N (N = concurrency) feedback stops increasing its concurrency once it reaches a concurrency level of about K, even though the good servers behind the load balancer are perfectly capable of handling more traffic. This noise problem gets worse as the amount of positive feedback per delivery gets smaller. A compromise is to use fixed less-than-1 positive feedback values instead of concurrency-dependent positive feedback. For example, to tolerate 1 of 4 bad servers in the above load balancer scenario, use positive feedback of 1/4 per "good" delivery (no connect or handshake error), and use an equal or smaller amount of negative feedback per "bad" delivery. The downside of using concurrency-independent feedback is that some of the old +/-1 feedback problems will return at large concurrencies. Sites that must deliver mail at non-trivial per-destination concurrencies will require special configuration. CCoonnccuurrrreennccyy ccoonnffiigguurraattiioonn ppaarraammeetteerrss The Postfix 2.5 concurrency scheduler is controlled with the following configuration parameters, where "transport_foo" provides a transport-specific parameter override. All parameter default settings are compatible with earlier Postfix versions. PPaarraammeetteerr nnaammee PPoossttffiixx DDeessccrriippttiioonn vveerrssiioonn --------------------------------------------------------------------------- Initial per- initial_destination_concurrency all destination transport_initial_destination_concurrency 2.5 delivery concurrency Maximum per- default_destination_concurrency_limit all destination transport_destination_concurrency_limit all delivery concurrency Per- destination positive feedback default_destination_concurrency_positive_feedback 2.5 amount, per transport_destination_concurrency_positive_feedback 2.5 delivery that does not fail with connection or handshake failure Per- destination negative feedback default_destination_concurrency_negative_feedback 2.5 amount, per transport_destination_concurrency_negative_feedback 2.5 delivery that fails with connection or handshake failure Number of failed pseudo- cohorts after default_destination_concurrency_failed_cohort_limit 2.5 which a transport_destination_concurrency_failed_cohort_limit 2.5 destination is declared "dead" and delivery is suspended Enable verbose destination_concurrency_feedback_debug 2.5 logging of concurrency scheduler activity --------------------------------------------------------------------------- PPrreeeemmppttiivvee sscchheedduulliinngg The following sections describe the new queue manager and its preemptive scheduler algorithm. Note that the document was originally written to describe the changes between the new queue manager (in this text referred to as nqmgr, the name it was known by before it became the default queue manager) and the old queue manager (referred to as oqmgr). This is why it refers to oqmgr every so often. This document is divided into sections as follows: * The structures used by nqmgr * What happens when nqmgr picks up the message - how it is assigned to transports, jobs, peers, entries * How the entry selection works * How the preemption works - what messages may be preempted and how and what messages are chosen to preempt them * How destination concurrency limits affect the scheduling algorithm * Dealing with memory resource limits TThhee ssttrruuccttuurreess uusseedd bbyy nnqqmmggrr Let's start by recapitulating the structures and terms used when referring to queue manager and how it operates. Many of these are partially described elsewhere, but it is nice to have a coherent overview in one place: * Each message structure represents one mail message which Postfix is to deliver. The message recipients specify to what destinations is the message to be delivered and what transports are going to be used for the delivery. * Each recipient entry groups a batch of recipients of one message which are all going to be delivered to the same destination. * Each transport structure groups everything what is going to be delivered by delivery agents dedicated for that transport. Each transport maintains a set of queues (describing the destinations it shall talk to) and jobs (referencing the messages it shall deliver). * Each transport queue (not to be confused with the on-disk active queue or incoming queue) groups everything what is going be delivered to given destination (aka nexthop) by its transport. Each queue belongs to one transport, so each destination may be referred to by several queues, one for each transport. Each queue maintains a list of all recipient entries (batches of message recipients) which shall be delivered to given destination (the todo list), and a list of recipient entries already being delivered by the delivery agents (the busy list). * Each queue corresponds to multiple peer structures. Each peer structure is like the queue structure, belonging to one transport and referencing one destination. The difference is that it lists only the recipient entries which all originate from the same message, unlike the queue structure, whose entries may originate from various messages. For messages with few recipients, there is usually just one recipient entry for each destination, resulting in one recipient entry per peer. But for large mailing list messages the recipients may need to be split to multiple recipient entries, in which case the peer structure may list many entries for single destination. * Each transport job groups everything it takes to deliver one message via its transport. Each job represents one message within the context of the transport. The job belongs to one transport and message, so each message may have multiple jobs, one for each transport. The job groups all the peer structures, which describe the destinations the job's message has to be delivered to. The first four structures are common to both nqmgr and oqmgr, the latter two were introduced by nqmgr. These terms are used extensively in the text below, feel free to look up the description above anytime you'll feel you have lost a sense what is what. WWhhaatt hhaappppeennss wwhheenn nnqqmmggrr ppiicckkss uupp tthhee mmeessssaaggee Whenever nqmgr moves a queue file into the active queue, the following happens: It reads all necessary information from the queue file as oqmgr does, and also reads as many recipients as possible - more on that later, for now let's just pretend it always reads all recipients. Then it resolves the recipients as oqmgr does, which means obtaining (address, nexthop, transport) triple for each recipient. For each triple, it finds the transport; if it does not exist yet, it instantiates it (unless it's dead). Within the transport, it finds the destination queue for given nexthop; if it does not exist yet, it instantiates it (unless it's dead). The triple is then bound to given destination queue. This happens in qmgr_resolve() and is basically the same as in oqmgr. Then for each triple which was bound to some queue (and thus transport), the program finds the job which represents the message within that transport's context; if it does not exist yet, it instantiates it. Within the job, it finds the peer which represents the bound destination queue within this jobs context; if it does not exist yet, it instantiates it. Finally, it stores the address from the resolved triple to the recipient entry which is appended to both the queue entry list and the peer entry list. The addresses for same nexthop are batched in the entries up to recipient_concurrency limit for that transport. This happens in qmgr_assign() and apart from that it operates with job and peer structures it is basically the same as in oqmgr. When the job is instantiated, it is enqueued on the transport's job list based on the time its message was picked up by nqmgr. For first batch of recipients this means it is appended to the end of the job list, but the ordering of the job list by the enqueue time is important as we will see shortly. [Now you should have pretty good idea what is the state of the nqmgr after couple of messages was picked up, what is the relation between all those job, peer, queue and entry structures.] HHooww tthhee eennttrryy sseelleeccttiioonn wwoorrkkss Having prepared all those above mentioned structures, the task of the nqmgr's scheduler is to choose the recipient entries one at a time and pass them to the delivery agent for corresponding transport. Now how does this work? The first approximation of the new scheduling algorithm is like this: foreach transport (round-robin-by-transport) do if transport busy continue if transport process limit reached continue foreach transport's job (in the order of the transport's job list) do foreach job's peer (round-robin-by-destination) if peer->queue->concurrency < peer->queue->window return next peer entry. done done done Now what is the "order of the transport's job list"? As we know already, the job list is by default kept in the order the message was picked up by the nqmgr. So by default we get the top-level round-robin transport, and within each transport we get the FIFO message delivery. The round-robin of the peers by the destination is perhaps of little importance in most real-life cases (unless the recipient_concurrency limit is reached, in one job there is only one peer structure for each destination), but theoretically it makes sure that even within single jobs, destinations are treated fairly. [By now you should have a feeling you really know how the scheduler works, except for the preemption, under ideal conditions - that is, no recipient resource limits and no destination concurrency problems.] HHooww tthhee pprreeeemmppttiioonn wwoorrkkss As you might perhaps expect by now, the transport's job list does not remain sorted by the job's message enqueue time all the time. The most cool thing about nqmgr is not the simple FIFO delivery, but that it is able to slip mail with little recipients past the mailing-list bulk mail. This is what the job preemption is about - shuffling the jobs on the transport's job list to get the best message delivery rates. Now how is it achieved? First I have to tell you that there are in fact two job lists in each transport. One is the scheduler's job list, which the scheduler is free to play with, while the other one keeps the jobs always listed in the order of the enqueue time and is used for recipient pool management we will discuss later. For now, we will deal with the scheduler's job list only. So, we have the job list, which is first ordered by the time the jobs' messages were enqueued, oldest messages first, the most recently picked one at the end. For now, let's assume that there are no destination concurrency problems. Without preemption, we pick some entry of the first (oldest) job on the queue, assign it to delivery agent, pick another one from the same job, assign it again, and so on, until all the entries are used and the job is delivered. We would then move onto the next job and so on and on. Now how do we manage to sneak in some entries from the recently added jobs when the first job on the job list belongs to a message going to the mailing-list and has thousands of recipient entries? The nqmgr's answer is that we can artificially "inflate" the delivery time of that first job by some constant for free - it is basically the same trick you might remember as "accumulation of potential" from the amortized complexity lessons. For example, instead of delivering the entries of the first job on the job list every time a delivery agent becomes available, we can do it only every second time. If you view the moments the delivery agent becomes available on a timeline as "delivery slots", then instead of using every delivery slot for the first job, we can use only every other slot, and still the overall delivery efficiency of the first job remains the same. So the delivery 11112222 becomes 1.1.1.1.2.2.2.2 (1 and 2 are the imaginary job numbers, . denotes the free slot). Now what do we do with free slots? As you might have guessed, we will use them for sneaking the mail with little recipients in. For example, if we have one four-recipient mail followed by four one recipients mail, the delivery sequence (that is, the sequence in which the jobs are assigned to the delivery slots) might look like this: 12131415. Hmm, fine for sneaking in the single recipient mail, but how do we sneak in the mail with more than one recipient? Say if we have one four-recipient mail followed by two two-recipient mails? The simple answer would be to use delivery sequence 12121313. But the problem is that this does not scale well. Imagine you have mail with thousand recipients followed by mail with hundred recipients. It is tempting to suggest the delivery sequence like 121212...., but alas! Imagine there arrives another mail with say ten recipients. But there are no free slots anymore, so it can't slip by, not even if it had just only one recipients. It will be stuck until the hundred-recipient mail is delivered, which really sucks. So, it becomes obvious that while inflating the message to get free slots is great idea, one has to be really careful of how the free slots are assigned, otherwise one might corner himself. So, how does nqmgr really use the free slots? The key idea is that one does not have to generate the free slots in a uniform way. The delivery sequence 111...1 is no worse than 1.1.1.1, in fact, it is even better as some entries are in the first case selected earlier than in the second case, and none is selected later! So it is possible to first "accumulate" the free delivery slots and then use them all at once. It is even possible to accumulate some, then use them, then accumulate some more and use them again, as in 11..1.1 . Let's get back to the one hundred recipient example. We now know that we could first accumulate one hundred free slots, and only after then to preempt the first job and sneak the one hundred recipient mail in. Applying the algorithm recursively, we see the hundred recipient job can accumulate ten free delivery slots, and then we could preempt it and sneak in the ten-recipient mail... Wait wait wait! Could we? Aren't we overinflating the original one thousand recipient mail? Well, despite it looks so at the first glance, another trick will allow us to answer "no, we are not!". If we had said that we will inflate the delivery time twice at maximum, and then we consider every other slot as a free slot, then we would overinflate in case of the recursive preemption. BUT! The trick is that if we use only every n-th slot as a free slot for n>2, there is always some worst inflation factor which we can guarantee not to be breached, even if we apply the algorithm recursively. To be precise, if for every k>1 normally used slots we accumulate one free delivery slot, than the inflation factor is not worse than k/(k-1) no matter how many recursive preemptions happen. And it's not worse than (k+1)/k if only non-recursive preemption happens. Now, having got through the theory and the related math, let's see how nqmgr implements this. Each job has so called "available delivery slot" counter. Each transport has a transport_delivery_slot_cost parameter, which defaults to default_delivery_slot_cost parameter which is set to 5 by default. This is the k from the paragraph above. Each time k entries of the job are selected for delivery, this counter is incremented by one. Once there are some slots accumulated, job which requires no more than that number of slots to be fully delivered can preempt this job. [Well, the truth is, the counter is incremented every time an entry is selected and it is divided by k when it is used. Or even more true, there is no division, the other side of the equation is multiplied by k. But for the understanding it's good enough to use the above approximation of the truth.] OK, so now we know the conditions which must be satisfied so one job can preempt another one. But what job gets preempted, how do we choose what job preempts it if there are several valid candidates, and when does all this exactly happen? The answer for the first part is simple. The job whose entry was selected the last time is so called current job. Normally, it is the first job on the scheduler's job list, but destination concurrency limits may change this as we will see later. It is always only the current job which may get preempted. Now for the second part. The current job has certain amount of recipient entries, and as such may accumulate at maximum some amount of available delivery slots. It might have already accumulated some, and perhaps even already used some when it was preempted before (remember a job can be preempted several times). In either case, we know how many are accumulated and how many are left to deliver, so we know how many it may yet accumulate at maximum. Every other job which may be delivered by less than that number of slots is a valid candidate for preemption. How do we choose among them? The answer is - the one with maximum enqueue_time/recipient_entry_count. That is, the older the job is, the more we should try to deliver it in order to get best message delivery rates. These rates are of course subject to how many recipients the message has, therefore the division by the recipient (entry) count. No one shall be surprised that message with n recipients takes n times longer to deliver than message with one recipient. Now let's recap the previous two paragraphs. Isn't it too complicated? Why don't the candidates come only among the jobs which can be delivered within the number of slots the current job already accumulated? Why do we need to estimate how much it has yet to accumulate? If you found out the answer, congratulate yourself. If we did it this simple way, we would always choose the candidate with least recipient entries. If there were enough single recipient mails coming in, they would always slip by the bulk mail as soon as possible, and the two and more recipients mail would never get a chance, no matter how long they have been sitting around in the job list. This candidate selection has interesting implication - that when we choose the best candidate for preemption (this is done in qmgr_choose_candidate()), it may happen that we may not use it for preemption immediately. This leads to an answer to the last part of the original question - when does the preemption happen? The preemption attempt happens every time next transport's recipient entry is to be chosen for delivery. To avoid needless overhead, the preemption is not attempted if the current job could never accumulate more than transport_minimum_delivery_slots (defaults to default_minimum_delivery_slots which defaults to 3). If there is already enough accumulated slots to preempt the current job by the chosen best candidate, it is done immediately. This basically means that the candidate is moved in front of the current job on the scheduler's job list and decreasing the accumulated slot counter by the amount used by the candidate. If there is not enough slots... well, I could say that nothing happens and the another preemption is attempted the next time. But that's not the complete truth. The truth is that it turns out that it is not really necessary to wait until the jobs counter accumulates all the delivery slots in advance. Say we have ten-recipient mail followed by two two-recipient mails. If the preemption happened when enough delivery slot accumulate (assuming slot cost 2), the delivery sequence becomes 11112211113311. Now what would we get if we would wait only for 50% of the necessary slots to accumulate and we promise we would wait for the remaining 50% later, after we get back to the preempted job? If we use such slot loan, the delivery sequence becomes 11221111331111. As we can see, it makes it no considerably worse for the delivery of the ten-recipient mail, but it allows the small messages to be delivered sooner. The concept of these slot loans is where the transport_delivery_slot_discount and transport_delivery_slot_loan come from (they default to default_delivery_slot_discount and default_delivery_slot_loan, whose values are by default 50 and 3, respectively). The discount (resp. loan) specifies how many percent (resp. how many slots) one "gets in advance", when the number of slots required to deliver the best candidate is compared with the number of slots the current slot had accumulated so far. And it pretty much concludes this chapter. [Now you should have a feeling that you pretty much understand the scheduler and the preemption, or at least that you will have it after you read the last chapter couple more times. You shall clearly see the job list and the preemption happening at its head, in ideal delivery conditions. The feeling of understanding shall last until you start wondering what happens if some of the jobs are blocked, which you might eventually figure out correctly from what had been said already. But I would be surprised if your mental image of the scheduler's functionality is not completely shattered once you start wondering how it works when not all recipients may be read in-core. More on that later.] HHooww ddeessttiinnaattiioonn ccoonnccuurrrreennccyy lliimmiittss aaffffeecctt tthhee sscchheedduulliinngg aallggoorriitthhmm The nqmgr uses the same algorithm for destination concurrency control as oqmgr. Now what happens when the destination limits are reached and no more entries for that destination may be selected by the scheduler? From user's point of view it is all simple. If some of the peers of a job can't be selected, those peers are simply skipped by the entry selection algorithm (the pseudo-code described before) and only the selectable ones are used. If none of the peers may be selected, the job is declared a "blocker job". Blocker jobs are skipped by the entry selection algorithm and they are also excluded from the candidates for preemption of current job. Thus the scheduler effectively behaves as if the blocker jobs didn't exist on the job list at all. As soon as at least one of the peers of a blocker job becomes unblocked (that is, the delivery agent handling the delivery of the recipient entry for given destination successfully finishes), the job's blocker status is removed and the job again participates in all further scheduler actions normally. So the summary is that the users don't really have to be concerned about the interaction of the destination limits and scheduling algorithm. It works well on its own and there are no knobs they would need to control it. From a programmer's point of view, the blocker jobs complicate the scheduler quite a lot. Without them, the jobs on the job list would be normally delivered in strict FIFO order. If the current job is preempted, the job preempting it is completely delivered unless it is preempted itself. Without blockers, the current job is thus always either the first job on the job list, or the top of the stack of jobs preempting the first job on the job list. The visualization of the job list and the preemption stack without blockers would be like this: first job-> 1--2--3--5--6--8--... <- job list on job list | 4 <- preemption stack | current job-> 7 In the example above we see that job 1 was preempted by job 4 and then job 4 was preempted by job 7. After job 7 is completed, remaining entries of job 4 are selected, and once they are all selected, job 1 continues. As we see, it's all very clean and straightforward. Now how does this change because of blockers? The answer is: a lot. Any job may become blocker job at any time, and also become normal job again at any time. This has several important implications: 1. The jobs may be completed in arbitrary order. For example, in the example above, if the current job 7 becomes blocked, the next job 4 may complete before the job 7 becomes unblocked again. Or if both 7 and 4 are blocked, then 1 is completed, then 7 becomes unblocked and is completed, then 2 is completed and only after that 4 becomes unblocked and is completed... You get the idea. [Interesting side note: even when jobs are delivered out of order, from single destination's point of view the jobs are still delivered in the expected order (that is, FIFO unless there was some preemption involved). This is because whenever a destination queue becomes unblocked (the destination limit allows selection of more recipient entries for that destination), all jobs which have peers for that destination are unblocked at once.] 2. The idea of the preemption stack at the head of the job list is gone. That is, it must be possible to preempt any job on the job list. For example, if the jobs 7, 4, 1 and 2 in the example above become all blocked, job 3 becomes the current job. And of course we do not want the preemption to be affected by the fact that there are some blocked jobs or not. Therefore, if it turns out that job 3 might be preempted by job 6, the implementation shall make it possible. 3. The idea of the linear preemption stack itself is gone. It's no longer true that one job is always preempted by only one job at one time (that is directly preempted, not counting the recursively nested jobs). For example, in the example above, job 1 is directly preempted by only job 4, and job 4 by job 7. Now assume job 7 becomes blocked, and job 4 is being delivered. If it accumulates enough delivery slots, it is natural that it might be preempted for example by job 8. Now job 4 is preempted by both job 7 AND job 8 at the same time. Now combine the points 2) and 3) with point 1) again and you realize that the relations on the once linear job list became pretty complicated. If we extend the point 3) example: jobs 7 and 8 preempt job 4, now job 8 becomes blocked too, then job 4 completes. Tricky, huh? If I illustrate the relations after the above mentioned examples (but those in point 1)), the situation would look like this: v- parent adoptive parent -> 1--2--3--5--... <- "stack" level 0 | | parent gone -> ? 6 <- "stack" level 1 / \ children -> 7 8 ^- child <- "stack" level 2 ^- siblings Now how does nqmgr deal with all these complicated relations? Well, it maintains them all as described, but fortunately, all these relations are necessary only for purposes of proper counting of available delivery slots. For purposes of ordering the jobs for entry selection, the original rule still applies: "the job preempting the current job is moved in front of the current job on the job list". So for entry selection purposes, the job relations remain as simple as this: 7--8--1--2--6--3--5--.. <- scheduler's job list order The job list order and the preemption parent/child/siblings relations are maintained separately. And because the selection works only with the job list, you can happily forget about those complicated relations unless you want to study the nqmgr sources. In that case the text above might provide some helpful introduction to the problem domain. Otherwise I suggest you just forget about all this and stick with the user's point of view: the blocker jobs are simply ignored. [By now, you should have a feeling that there is more things going under the hood than you ever wanted to know. You decide that forgetting about this chapter is the best you can do for the sake of your mind's health and you basically stick with the idea how the scheduler works in ideal conditions, when there are no blockers, which is good enough.] DDeeaalliinngg wwiitthh mmeemmoorryy rreessoouurrccee lliimmiittss When discussing the nqmgr scheduler, we have so far assumed that all recipients of all messages in the active queue are completely read into the memory. This is simply not true. There is an upper bound on the amount of memory the nqmgr may use, and therefore it must impose some limits on the information it may store in the memory at any given time. First of all, not all messages may be read in-core at once. At any time, only qmgr_message_active_limit messages may be read in-core at maximum. When read into memory, the messages are picked from the incoming and deferred message queues and moved to the active queue (incoming having priority), so if there is more than qmgr_message_active_limit messages queued in the active queue, the rest will have to wait until (some of) the messages in the active queue are completely delivered (or deferred). Even with the limited amount of in-core messages, there is another limit which must be imposed in order to avoid memory exhaustion. Each message may contain huge amount of recipients (tens or hundreds of thousands are not uncommon), so if nqmgr read all recipients of all messages in the active queue, it may easily run out of memory. Therefore there must be some upper bound on the amount of message recipients which are read into the memory at the same time. Before discussing how exactly nqmgr implements the recipient limits, let's see how the sole existence of the limits themselves affects the nqmgr and its scheduler. The message limit is straightforward - it just limits the size of the lookahead the nqmgr's scheduler has when choosing which message can preempt the current one. Messages not in the active queue simply are not considered at all. The recipient limit complicates more things. First of all, the message reading code must support reading the recipients in batches, which among other things means accessing the queue file several times and continuing where the last recipient batch ended. This is invoked by the scheduler whenever the current job has space for more recipients, subject to transport's refill_limit and refill_delay parameters. It is also done any time when all in-core recipients of the message are dealt with (which may also mean they were deferred) but there are still more in the queue file. The second complication is that with some recipients left unread in the queue file, the scheduler can't operate with exact counts of recipient entries. With unread recipients, it is not clear how many recipient entries there will be, as they are subject to per-destination grouping. It is not even clear to what transports (and thus jobs) the recipients will be assigned. And with messages coming from the deferred queue, it is not even clear how many unread recipients are still to be delivered. This all means that the scheduler must use only estimates of how many recipients entries there will be. Fortunately, it is possible to estimate the minimum and maximum correctly, so the scheduler can always err on the safe side. Obviously, the better the estimates, the better results, so it is best when we are able to read all recipients in-core and turn the estimates into exact counts, or at least try to read as many as possible to make the estimates as accurate as possible. The third complication is that it is no longer true that the scheduler is done with a job once all of its in-core recipients are delivered. It is possible that the job will be revived later, when another batch of recipients is read in core. It is also possible that some jobs will be created for the first time long after the first batch of recipients was read in core. The nqmgr code must be ready to handle all such situations. And finally, the fourth complication is that the nqmgr code must somehow impose the recipient limit itself. Now how does it achieve it? Perhaps the easiest solution would be to say that each message may have at maximum X recipients stored in-core, but such solution would be poor for several reasons. With reasonable qmgr_message_active_limit values, the X would have to be quite low to maintain reasonable memory footprint. And with low X lots of things would not work well. The nqmgr would have problems to use the transport_destination_recipient_limit efficiently. The scheduler's preemption would be suboptimal as the recipient count estimates would be inaccurate. The message queue file would have to be accessed many times to read in more recipients again and again. Therefore it seems reasonable to have a solution which does not use a limit imposed on per-message basis, but which maintains a pool of available recipient slots, which can be shared among all messages in the most efficient manner. And as we do not want separate transports to compete for resources whenever possible, it seems appropriate to maintain such recipient pool for each transport separately. This is the general idea, now how does it work in practice? First we have to solve little chicken-and-egg problem. If we want to use the per-transport recipient pools, we first need to know to what transport(s) is the message assigned. But we will find that out only after we read in the recipients first. So it is obvious that we first have to read in some recipients, use them to find out to what transports is the message to be assigned, and only after that we can use the per-transport recipient pools. Now how many recipients shall we read for the first time? This is what qmgr_message_recipient_minimum and qmgr_message_recipient_limit values control. The qmgr_message_recipient_minimum value specifies how many recipients of each message we will read for the first time, no matter what. It is necessary to read at least one recipient before we can assign the message to a transport and create the first job. However, reading only qmgr_message_recipient_minimum recipients even if there are only few messages with few recipients in-core would be wasteful. Therefore if there is less than qmgr_message_recipient_limit recipients in-core so far, the first batch of recipients may be larger than qmgr_message_recipient_minimum - as large as is required to reach the qmgr_message_recipient_limit limit. Once the first batch of recipients was read in core and the message jobs were created, the size of the subsequent recipient batches (if any - of course it's best when all recipients are read in one batch) is based solely on the position of the message jobs on their corresponding transports' job lists. Each transport has a pool of transport_recipient_limit recipient slots which it can distribute among its jobs (how this is done is described later). The subsequent recipient batch may be as large as the sum of all recipient slots of all jobs of the message permits (plus the qmgr_message_recipient_minimum amount which always applies). For example, if a message has three jobs, first with 1 recipient still in-core and 4 recipient slots, second with 5 recipient in-core and 5 recipient slots, and third with 2 recipients in-core and 0 recipient slots, it has 1+5+2=7 recipients in-core and 4+5+0=9 jobs' recipients slots in total. This means that we could immediately read 2+qmgr_message_recipient_minimum more recipients of that message in core. The above example illustrates several things which might be worth mentioning explicitly: first, note that although the per-transport slots are assigned to particular jobs, we can't guarantee that once the next batch of recipients is read in core, that the corresponding amounts of recipients will be assigned to those jobs. The jobs lend its slots to the message as a whole, so it is possible that some jobs end up sponsoring other jobs of their message. For example, if in the example above the 2 newly read recipients were assigned to the second job, the first job sponsored the second job with 2 slots. The second notable thing is the third job, which has more recipients in-core than it has slots. Apart from sponsoring by other job we just saw it can be result of the first recipient batch, which is sponsored from global recipient pool of qmgr_message_recipient_limit recipients. It can be also sponsored from the message recipient pool of qmgr_message_recipient_minimum recipients. Now how does each transport distribute the recipient slots among its jobs? The strategy is quite simple. As most scheduler activity happens on the head of the job list, it is our intention to make sure that the scheduler has the best estimates of the recipient counts for those jobs. As we mentioned above, this means that we want to try to make sure that the messages of those jobs have all recipients read in-core. Therefore the transport distributes the slots "along" the job list from start to end. In this case the job list sorted by message enqueue time is used, because it doesn't change over time as the scheduler's job list does. More specifically, each time a job is created and appended to the job list, it gets all unused recipient slots from its transport's pool. It keeps them until all recipients of its message are read. When this happens, all unused recipient slots are transferred to the next job (which is now in fact now first such job) on the job list which still has some recipients unread, or eventually back to the transport pool if there is no such job. Such transfer then also happens whenever a recipient entry of that job is delivered. There is also a scenario when a job is not appended to the end of the job list (for example it was created as a result of second or later recipient batch). Then it works exactly as above, except that if it was put in front of the first unread job (that is, the job of a message which still has some unread recipients in queue file), that job is first forced to return all of its unused recipient slots to the transport pool. The algorithm just described leads to the following state: The first unread job on the job list always gets all the remaining recipient slots of that transport (if there are any). The jobs queued before this job are completely read (that is, all recipients of their message were already read in core) and have at maximum as many slots as they still have recipients in-core (the maximum is there because of the sponsoring mentioned before) and the jobs after this job get nothing from the transport recipient pool (unless they got something before and then the first unread job was created and enqueued in front of them later - in such case the also get at maximum as many slots as they have recipients in- core). Things work fine in such state for most of the time, because the current job is either completely read in-core or has as much recipient slots as there are, but there is one situation which we still have to take care of specially. Imagine if the current job is preempted by some unread job from the job list and there are no more recipient slots available, so this new current job could read only batches of qmgr_message_recipient_minimum recipients at a time. This would really degrade performance. For this reason, each transport has extra pool of transport_extra_recipient_limit recipient slots, dedicated exactly for this situation. Each time an unread job preempts the current job, it gets half of the remaining recipient slots from the normal pool and this extra pool. And that's it. It sure does sound pretty complicated, but fortunately most people don't really have to care how exactly it works as long as it works. Perhaps the only important things to know for most people are the following upper bound formulas: Each transport has at maximum max( qmgr_message_recipient_minimum * qmgr_message_active_limit + *_recipient_limit + *_extra_recipient_limit, qmgr_message_recipient_limit ) recipients in core. The total amount of recipients in core is max( qmgr_message_recipient_minimum * qmgr_message_active_limit + sum( *_recipient_limit + *_extra_recipient_limit ), qmgr_message_recipient_limit ) where the sum is over all used transports. And this terribly complicated chapter concludes the documentation of nqmgr scheduler. [By now you should theoretically know the nqmgr scheduler inside out. In practice, you still hope that you will never have to really understand the last or last two chapters completely, and fortunately most people really won't. Understanding how the scheduler works in ideal conditions is more than good enough for vast majority of users.] CCrreeddiittss * Wietse Venema designed and implemented the initial queue manager with per- domain FIFO scheduling, and per-delivery +/-1 concurrency feedback. * Patrik Rak designed and implemented preemption where mail with fewer recipients can slip past mail with more recipients in a controlled manner, and wrote up its documentation. * Wietse Venema initiated a discussion with Patrik Rak and Victor Duchovni on alternatives for the +/-1 feedback scheduler's aggressive behavior. This is when K/N feedback was reviewed (N = concurrency). The discussion ended without a good solution for both negative feedback and dead site detection. * Victor Duchovni resumed work on concurrency feedback in the context of concurrency-limited servers. * Wietse Venema then re-designed the concurrency scheduler in terms of the simplest possible concepts: less-than-1 concurrency feedback per delivery, forward and reverse concurrency feedback hysteresis, and pseudo-cohort failure. At this same time, concurrency feedback was separated from dead site detection. * These simplifications, and their modular implementation, helped to develop further insights into the different roles that positive and negative concurrency feedback play, and helped to identify some worst-case scenarios. README_FILES/ETRN_README000066600000026636150501202770010153 0ustar00PPoossttffiixx EETTRRNN HHoowwttoo ------------------------------------------------------------------------------- PPuurrppoossee ooff tthhee PPoossttffiixx ffaasstt EETTRRNN sseerrvviiccee The SMTP ETRN command was designed for sites that have intermittent Internet connectivity. With ETRN, a site can tell the mail server of its provider to "Please deliver all my mail now". The SMTP server searches the queue for mail to the customer, and delivers that mail bbyy ccoonnnneeccttiinngg ttoo tthhee ccuussttoommeerr''ss SSMMTTPP sseerrvveerr. The mail is not delivered via the connection that was used for sending ETRN. As of version 1.0, Postfix has a fast ETRN implementation that does not require Postfix to examine every queue file. Instead, Postfix maintains a record of what queue files contain mail for destinations that are configured for ETRN service. ETRN service is no longer available for domains that aren't configured for the service. This document provides information on the following topics: * Using the Postfix fast ETRN service * How Postfix fast ETRN works * Postfix fast ETRN service limitations * Configuring the Postfix fast ETRN service * Configuring a domain for ETRN service only * Testing the Postfix fast ETRN service Other documents with information on this subject: * flush(8), flush service implementation UUssiinngg tthhee PPoossttffiixx ffaasstt EETTRRNN sseerrvviiccee The following is an example SMTP session that shows how an SMTP client requests the ETRN service. Client commands are shown in bold font. 220 my.server.tld ESMTP Postfix HHEELLOO mmyy..cclliieenntt..ttlldd 250 Ok EETTRRNN ssoommee..ccuussttoommeerr..ddoommaaiinn 250 Queuing started QQUUIITT 221 Bye As mentioned in the introduction, the mail is delivered by connecting to the customer's SMTP server; it is not sent over the connection that was used to send the ETRN command. The Postfix operator can request delivery for a specific customer by using the command "sendmail -qRdestination" and, with Postfix version 1.1 and later, "postqueue -sdestination". Access to this feature is controlled with the authorized_flush_users configuration parameter (Postfix version 2.2 and later). HHooww PPoossttffiixx ffaasstt EETTRRNN wwoorrkkss When a Postfix delivery agent decides that mail must be delivered later, it sends the destination domain name and the queue file name to the flush(8) daemon which maintains per-destination logfiles with file names of queued mail. These logfiles are kept below $queue_directory/flush. Per-destination logfiles are maintained only for destinations that are listed with the $fast_flush_domains parameter and that have syntactically valid domain names. Postfix Postfix One logfile delivery -(domain, queue ID)-> flush -(queue ID)-> per eligible agent daemon domain When Postfix receives a request to "deliver mail for a domain now", the flush (8) daemon moves all deferred queue files that are listed for that domain to the incoming queue, and requests that the queue manager deliver them. In order to force delivery, the queue manager temporarily ignores the lists of undeliverable destinations: the volatile in-memory list of dead domains, and the list of message delivery transports specified with the defer_transports configuration parameter. PPoossttffiixx ffaasstt EETTRRNN sseerrvviiccee lliimmiittaattiioonnss The design of the flush(8) server and of the flush queue introduce a few limitations that should not be an issue unless you want to turn on fast ETRN service for every possible destination. * The flush(8) daemon maintains per-destination logfiles with queue file names. When a request to "deliver mail now" arrives, Postfix will attempt to deliver all recipients in the queue files that have mail for the destination in question. This does not perform well with queue files that have recipients in many different domains, such as queue files with outbound mailing list traffic. * The flush(8) daemon maintains per-destination logfiles only for destinations listed with $fast_flush_domains. With other destinations you cannot request delivery with "sendmail -qRdestination" or, with Postfix version 1.1 and later, "postqueue -sdestination". * Up to and including early versions of Postfix version 2.1, the "fast flush" service may not deliver some messages if the request to "deliver mail now" is received while a deferred queue scan is already in progress. The reason is that the queue manager does not ignore the volatile in-memory list of dead domains, and the list of message delivery transports specified with the defer_transports configuration parameter. * Up to and including Postfix version 2.3, the "fast flush" service may not deliver some messages if the request to "deliver mail now" arrives while an incoming queue scan is already in progress. CCoonnffiigguurriinngg tthhee PPoossttffiixx ffaasstt EETTRRNN sseerrvviiccee The behavior of the flush(8) daemon is controlled by parameters in the main.cf configuration file. By default, Postfix "fast ETRN" service is available only for destinations that Postfix is willing to relay mail to: /etc/postfix/main.cf: fast_flush_domains = $relay_domains smtpd_etrn_restrictions = permit_mynetworks, reject Notes: * The relay_domains parameter specifies what destinations Postfix will relay to. For destinations that are not eligible for the "fast ETRN" service, Postfix replies with an error message. * The smtpd_etrn_restrictions parameter limits what clients may execute the ETRN command. By default, any client has permission. To enable "fast ETRN" for some other destination, specify: /etc/postfix/main.cf: fast_flush_domains = $relay_domains, some.other.domain To disable "fast ETRN", so that Postfix rejects all ETRN requests and so that it maintains no per-destination logfiles, specify: /etc/postfix/main.cf: fast_flush_domains = CCoonnffiigguurriinngg aa ddoommaaiinn ffoorr EETTRRNN sseerrvviiccee oonnllyy While an "ETRN" customer is off-line, Postfix will make spontaneous attempts to deliver mail to it. These attempts are separated in time by increasing time intervals, ranging from $minimal_backoff_time to $maximal_backoff_time, and should not be a problem unless a lot of mail is queued. To prevent Postfix from making spontaneous delivery attempts you can configure Postfix to always defer mail for the "ETRN" customer. Mail is delivered only after the ETRN command or with "sendmail -q", with "sendmail -qRdomain", or with "postqueue -sdomain"(Postfix version 1.1 and later only), In the example below we configure an "etrn-only" delivery transport which is simply a duplicate of the "smtp" and "relay" mail delivery transports. The only difference is that mail destined for this delivery transport is deferred as soon as it arrives. 1 /etc/postfix/master.cf: 2 # ============================================================= 3 # service type private unpriv chroot wakeup maxproc command 4 # (yes) (yes) (yes) (never) (100) 5 # ============================================================= 6 smtp unix - - n - - smtp 7 relay unix - - n - - smtp 8 etrn-only unix - - n - - smtp 9 10 /etc/postfix/main.cf: 11 relay_domains = customer.tld ...other domains... 12 defer_transports = etrn-only 13 transport_maps = hash:/etc/postfix/transport 14 15 /etc/postfix/transport: 16 customer.tld etrn-only:[mailhost.customer.tld] Translation: * Line 8: The "etrn-only" mail delivery service is a copy of the "smtp" and "relay" service. * Line 11: Don't forget to authorize relaying for this customer, either via relay_domains or with the permit_mx_backup feature. * Line 12: The "etrn-only" mail delivery service is configured so that spontaneous mail delivery is disabled. * Lines 13-16: Mail for the customer is given to the "etrn-only" mail delivery service. * Line 16: The "[mailhost.customer.tld]" turns off MX record lookups; you must specify this if your Postfix server is the primary MX host for the customer's domain. TTeessttiinngg tthhee PPoossttffiixx ffaasstt EETTRRNN sseerrvviiccee By default, "fast ETRN" service is enabled for all domains that match $relay_domains. If you run Postfix with "fast ETRN" service for the very first time, you need to run "sendmail -q" once in order to populate the per-site deferred mail logfiles. If you omit this step, no harm is done. The logfiles will eventually become populated as Postfix routinely attempts to deliver delayed mail, but that will take a couple hours. After the "sendmail -q" command has completed all delivery attempts (this can take a while), you're ready to test the "fast ETRN" service. To test the "fast ETRN" service, telnet to the Postfix SMTP server from a client that is allowed to execute ETRN commands (by default, that's every client), and type the commands shown in boldface: 220 my.server.tld ESMTP Postfix HHEELLOO mmyy..cclliieenntt..ttlldd 250 Ok EETTRRNN ssoommee..ccuussttoommeerr..ddoommaaiinn 250 Queuing started where "some.customer.domain" is the name of a domain that has a non-empty logfile somewhere under $queue_directory/flush. In the maillog file, you should immediately see a couple of logfile records, as evidence that the queue manager has opened queue files: Oct 2 10:51:19 myhostname postfix/qmgr[51999]: 682E8440A4: from=, size=12345, nrcpt=1 (queue active) Oct 2 10:51:19 myhostname postfix/qmgr[51999]: 02249440B7: from=, size=4711, nrcpt=1 (queue active) What happens next depends on whether the destination is reachable. If it's not reachable, the mail queue IDs will be added back to the some.customer.domain logfile under $queue_directory/flush. Repeat the exercise with some other destination that your server is willing to relay to (any domain listed in $relay_domains), but that has no mail queued. The text in bold face stands for the commands that you type: 220 my.server.tld ESMTP Postfix HHEELLOO mmyy..cclliieenntt..ttlldd 250 Ok EETTRRNN ssoommee..ootthheerr..ccuussttoommeerr..ddoommaaiinn 250 Queuing started This time, the "ETRN"" command should trigger NO mail deliveries at all. If this triggers delivery of all mail, then you used the wrong domain name, or "fast ETRN" service is turned off. Finally, repeat the exercise with a destination that your mail server is not willing to relay to. It does not matter if your server has mail queued for that destination. 220 my.server.tld ESMTP Postfix HHEELLOO mmyy..cclliieenntt..ttlldd 250 Ok EETTRRNN nnoott..aa..ccuussttoommeerr..ddoommaaiinn 459 : service unavailable In this case, Postfix should reject the request as shown above. README_FILES/TLS_LEGACY_README000066600000146726150501202770011074 0ustar00PPoossttffiixx lleeggaaccyy TTLLSS SSuuppppoorrtt ------------------------------------------------------------------------------- NNOOTTEE This document describes an old TLS user interface that is based on a third- party TLS patch by Lutz Jänicke. As of Postfix version 2.3, the old user interface still exists to allow migration from earlier Postfix releases, but its functionality is frozen. WWhhaatt PPoossttffiixx TTLLSS ssuuppppoorrtt ddooeess ffoorr yyoouu Transport Layer Security (TLS, formerly called SSL) provides certificate-based authentication and encrypted sessions. An encrypted session protects the information that is transmitted with SMTP mail or with SASL authentication. Postfix version 2.2 introduces support for TLS as described in RFC 3207. TLS Support for older Postfix versions was available as an add-on patch. The section "Compatibility with Postfix < 2.2 TLS support" below discusses the differences between these implementations. Topics covered in this document: * How Postfix TLS support works * Building Postfix with TLS support * SMTP Server specific settings * SMTP Client specific settings * TLS manager specific settings * Reporting problems * Compatibility with Postfix < 2.2 TLS support * Credits And last but not least, for the impatient: * Getting started, quick and dirty HHooww PPoossttffiixx TTLLSS ssuuppppoorrtt wwoorrkkss The diagram below shows the main elements of the Postfix TLS architecture and their relationships. Colored boxes with numbered names represent Postfix daemon programs. Other colored boxes represent storage elements. * The smtpd(8) server implements the SMTP over TLS server side. * The smtp(8) client implements the SMTP over TLS client side. * The tlsmgr(8) server maintains the pseudo-random number generator (PRNG) that seeds the TLS engines in the smtpd(8) server and smtp(8) client processes, and maintains the TLS session key cache files. <---seed--- ---seed---> Network-> smtpd(8) tlsmgr(8) smtp(8) ->Network <-session-> <-session-> / | \ | / \ smtpd PRNG smtp session state session key cache file key cache BBuuiillddiinngg PPoossttffiixx wwiitthh TTLLSS ssuuppppoorrtt To build Postfix with TLS support, first we need to generate the make(1) files with the necessary definitions. This is done by invoking the command "make makefiles" in the Postfix top-level directory and with arguments as shown next. NNOOTTEE:: DDoo nnoott uussee GGnnuu TTLLSS.. IItt wwiillll ssppoonnttaanneeoouussllyy tteerrmmiinnaattee aa PPoossttffiixx ddaaeemmoonn pprroocceessss wwiitthh eexxiitt ssttaattuuss ccooddee 22,, iinnsstteeaadd ooff aalllloowwiinngg PPoossttffiixx ttoo 11)) rreeppoorrtt tthhee eerrrroorr ttoo tthhee mmaaiilllloogg ffiillee,, aanndd ttoo 22)) pprroovviiddee ppllaaiinntteexxtt sseerrvviiccee wwhheerree tthhiiss iiss aapppprroopprriiaattee.. * If the OpenSSL include files (such as ssl.h) are in directory /usr/include/ openssl, and the OpenSSL libraries (such as libssl.so and libcrypto.so) are in directory /usr/lib: % mmaakkee ttiiddyy # if you have left-over files from a previous build % mmaakkee mmaakkeeffiilleess CCCCAARRGGSS==""--DDUUSSEE__TTLLSS"" AAUUXXLLIIBBSS==""--llssssll --llccrryyppttoo"" * If the OpenSSL include files (such as ssl.h) are in directory /usr/local/ include/openssl, and the OpenSSL libraries (such as libssl.so and libcrypto.so) are in directory /usr/local/lib: % mmaakkee ttiiddyy # if you have left-over files from a previous build % mmaakkee mmaakkeeffiilleess CCCCAARRGGSS==""--DDUUSSEE__TTLLSS --II//uussrr//llooccaall//iinncclluuddee"" \\ AAUUXXLLIIBBSS==""--LL//uussrr//llooccaall//lliibb --llssssll --llccrryyppttoo"" On Solaris, specify the -R option as shown below: % mmaakkee ttiiddyy # if you have left-over files from a previous build % mmaakkee mmaakkeeffiilleess CCCCAARRGGSS==""--DDUUSSEE__TTLLSS --II//uussrr//llooccaall//iinncclluuddee"" \\ AAUUXXLLIIBBSS==""--RR//uussrr//llooccaall//lliibb --LL//uussrr//llooccaall//lliibb --llssssll --llccrryyppttoo"" If you need to apply other customizations (such as Berkeley DB databases, MySQL, PosgreSQL, LDAP or SASL), see the respective Postfix README documents, and combine their "make makefiles" instructions with the instructions above: % mmaakkee ttiiddyy # if you have left-over files from a previous build % mmaakkee mmaakkeeffiilleess CCCCAARRGGSS==""--DDUUSSEE__TTLLSS \\ ((ootthheerr --DD oorr --II ooppttiioonnss))"" \\ AAUUXXLLIIBBSS==""--llssssll --llccrryyppttoo \\ ((ootthheerr --ll ooppttiioonnss ffoorr lliibbrraarriieess iinn //uussrr//lliibb)) \\ ((--LL//ppaatthh//nnaammee ++ --ll ooppttiioonnss ffoorr ootthheerr lliibbrraarriieess))"" To complete the build process, see the Postfix INSTALL instructions. Postfix has TLS support turned off by default, so you can start using Postfix as soon as it is installed. SSMMTTPP SSeerrvveerr ssppeecciiffiicc sseettttiinnggss Topics covered in this section: * Server-side certificate and private key configuration * Server-side TLS activity logging * Enabling TLS in the Postfix SMTP server * Client certificate verification * Supporting AUTH over TLS only * Server-side TLS session cache * Server access control * Server-side cipher controls * Miscellaneous server controls SSeerrvveerr--ssiiddee cceerrttiiffiiccaattee aanndd pprriivvaattee kkeeyy ccoonnffiigguurraattiioonn In order to use TLS, the Postfix SMTP server needs a certificate and a private key. Both must be in "pem" format. The private key must not be encrypted, meaning: the key must be accessible without password. Both certificate and private key may be in the same file. Both RSA and DSA certificates are supported. Typically you will only have RSA certificates issued by a commercial CA. In addition, the tools supplied with OpenSSL will by default issue RSA certificates. You can have both at the same time, in which case the cipher used determines which certificate is presented. For Netscape and OpenSSL clients without special cipher choices, the RSA certificate is preferred. In order for remote SMTP clients to check the Postfix SMTP server certificates, the CA certificate (in case of a certificate chain, all CA certificates) must be available. You should add these certificates to the server certificate, the server certificate first, then the issuing CA(s). Example: the certificate for "server.dom.ain" was issued by "intermediate CA" which itself has a certificate issued by "root CA". Create the server.pem file with: % ccaatt sseerrvveerr__cceerrtt..ppeemm iinntteerrmmeeddiiaattee__CCAA..ppeemm >> sseerrvveerr..ppeemm A Postfix SMTP server certificate supplied here must be usable as SSL server certificate and hence pass the "openssl verify -purpose sslserver ..." test. A client that trusts the root CA has a local copy of the root CA certificate, so it is not necessary to include the root CA certificate here. Leaving it out of the "server.pem" file reduces the overhead of the TLS exchange. If you want the Postfix SMTP server to accept remote SMTP client certificates issued by these CAs, append the root certificate to $smtpd_tls_CAfile or install it in the $smtpd_tls_CApath directory. When you configure trust in a root CA, it is not necessary to explicitly trust intermediary CAs signed by the root CA, unless $smtpd_tls_ccert_verifydepth is less than the number of CAs in the certificate chain for the clients of interest. With a verify depth of 1 you can only verify certificates directly signed by a trusted CA, and all trusted intermediary CAs need to be configured explicitly. With a verify depth of 2 you can verify clients signed by a root CA or a direct intermediary CA (so long as the client is correctly configured to supply its intermediate CA certificate). RSA key and certificate examples: /etc/postfix/main.cf: smtpd_tls_cert_file = /etc/postfix/server.pem smtpd_tls_key_file = $smtpd_tls_cert_file Their DSA counterparts: /etc/postfix/main.cf: smtpd_tls_dcert_file = /etc/postfix/server-dsa.pem smtpd_tls_dkey_file = $smtpd_tls_dcert_file To verify a remote SMTP client certificate, the Postfix SMTP server needs to trust the certificates of the issuing certification authorities. These certificates in "pem" format can be stored in a single $smtpd_tls_CAfile or in multiple files, one CA per file in the $smtpd_tls_CApath directory. If you use a directory, don't forget to create the necessary "hash" links with: # $$OOPPEENNSSSSLL__HHOOMMEE//bbiinn//cc__rreehhaasshh //ppaatthh//ttoo//ddiirreeccttoorryy The $smtpd_tls_CAfile contains the CA certificates of one or more trusted CAs. The file is opened (with root privileges) before Postfix enters the optional chroot jail and so need not be accessible from inside the chroot jail. Additional trusted CAs can be specified via the $smtpd_tls_CApath directory, in which case the certificates are read (with $mail_owner privileges) from the files in the directory when the information is needed. Thus, the $smtpd_tls_CApath directory needs to be accessible inside the optional chroot jail. When you configure Postfix to request client certificates (by setting $smtpd_tls_ask_ccert = yes), any certificates in $smtpd_tls_CAfile are sent to the client, in order to allow it to choose an identity signed by a CA you trust. If no $smtpd_tls_CAfile is specified, no preferred CA list is sent, and the client is free to choose an identity signed by any CA. Many clients use a fixed identity regardless of the preferred CA list and you may be able to reduce TLS negotiation overhead by installing client CA certificates mostly or only in $smtpd_tls_CApath. In the latter case you need not specify a $smtpd_tls_CAfile. Note, that unless client certificates are used to allow greater access to TLS authenticated clients, it is best to not ask for client certificates at all, as in addition to increased overhead some clients (notably in some cases qmail) are unable to complete the TLS handshake when client certificates are requested. Example: /etc/postfix/main.cf: smtpd_tls_CAfile = /etc/postfix/CAcert.pem smtpd_tls_CApath = /etc/postfix/certs SSeerrvveerr--ssiiddee TTLLSS aaccttiivviittyy llooggggiinngg To get additional information about Postfix SMTP server TLS activity you can increase the loglevel from 0..4. Each logging level also includes the information that is logged at a lower logging level. 0 Disable logging of TLS activity. 1 Log TLS handshake and certificate information. 2 Log levels during TLS negotiation. 3 Log hexadecimal and ASCII dump of TLS negotiation process 4 Log hexadecimal and ASCII dump of complete transmission after STARTTLS Use loglevel 3 only in case of problems. Use of loglevel 4 is strongly discouraged. Example: /etc/postfix/main.cf: smtpd_tls_loglevel = 0 To include information about the protocol and cipher used as well as the client and issuer CommonName into the "Received:" message header, set the smtpd_tls_received_header variable to true. The default is no, as the information is not necessarily authentic. Only information recorded at the final destination is reliable, since the headers may be changed by intermediate servers. Example: /etc/postfix/main.cf: smtpd_tls_received_header = yes EEnnaabblliinngg TTLLSS iinn tthhee PPoossttffiixx SSMMTTPP sseerrvveerr By default, TLS is disabled in the Postfix SMTP server, so no difference to plain Postfix is visible. Explicitly switch it on using "smtpd_use_tls = yes". Example: /etc/postfix/main.cf: smtpd_use_tls = yes With this, Postfix SMTP server announces STARTTLS support to SMTP clients, but does not require that clients use TLS encryption. Note: when an unprivileged user invokes "sendmail -bs", STARTTLS is never offered due to insufficient privileges to access the server private key. This is intended behavior. You can ENFORCE the use of TLS, so that the Postfix SMTP server announces STARTTLS and accepts no mail without TLS encryption, by setting "smtpd_enforce_tls = yes". According to RFC 2487 this MUST NOT be applied in case of a publicly-referenced Postfix SMTP server. This option is off by default and should only seldom be used. Example: /etc/postfix/main.cf: smtpd_enforce_tls = yes TLS is sometimes used in the non-standard "wrapper" mode where a server always uses TLS, instead of announcing STARTTLS support and waiting for clients to request TLS service. Some clients, namely Outlook [Express] prefer the "wrapper" mode. This is true for OE (Win32 < 5.0 and Win32 >=5.0 when run on a port<>25 and OE (5.01 Mac on all ports). It is strictly discouraged to use this mode from main.cf. If you want to support this service, enable a special port in master.cf and specify "- o smtpd_tls_wrappermode = yes" as an smtpd(8) command line option. Port 465 (smtps) was once chosen for this feature. Example: /etc/postfix/master.cf: smtps inet n - n - - smtpd -o smtpd_tls_wrappermode=yes -o smtpd_sasl_auth_enable=yes CClliieenntt cceerrttiiffiiccaattee vveerriiffiiccaattiioonn To receive a remote SMTP client certificate, the Postfix SMTP server must explicitly ask for one (any contents of $smtpd_tls_CAfile are also sent to the client as a hint for choosing a certificate from a suitable CA). Unfortunately, Netscape clients will either complain if no matching client certificate is available or will offer the user client a list of certificates to choose from. Additionally some MTAs (notably some versions of qmail) are unable to complete TLS negotiation when client certificates are requested, and abort the SMTP session. So this option is "off" by default. You will however need the certificate if you want to use certificate based relaying with, for example, the permit_tls_clientcerts feature. Example: /etc/postfix/main.cf: smtpd_tls_ask_ccert = no You may also decide to REQUIRE a remote SMTP client certificate before allowing TLS connections. This feature is included for completeness, and implies "smtpd_tls_ask_ccert = yes". Please be aware, that this will inhibit TLS connections without a proper client certificate and that it makes sense only when non-TLS submission is disabled (smtpd_enforce_tls = yes). Otherwise, clients could bypass the restriction by simply not using STARTTLS at all. When TLS is not enforced, the connection will be handled as if only "smtpd_tls_ask_ccert = yes" is specified, and a warning is logged. Example: /etc/postfix/main.cf: smtpd_tls_req_ccert = no A client certificate verification depth of 1 is sufficient if the certificate is directly issued by a CA listed in the CA file. The default value (5) should also suffice for longer chains (root CA issues special CA which then issues the actual certificate...) Example: /etc/postfix/main.cf: smtpd_tls_ccert_verifydepth = 5 SSuuppppoorrttiinngg AAUUTTHH oovveerr TTLLSS oonnllyy Sending AUTH data over an unencrypted channel poses a security risk. When TLS layer encryption is required (smtpd_enforce_tls = yes), the Postfix SMTP server will announce and accept AUTH only after the TLS layer has been activated with STARTTLS. When TLS layer encryption is optional (smtpd_enforce_tls = no), it may however still be useful to only offer AUTH when TLS is active. To maintain compatibility with non-TLS clients, the default is to accept AUTH without encryption. In order to change this behavior, set "smtpd_tls_auth_only = yes". Example: /etc/postfix/main.cf: smtpd_tls_auth_only = no SSeerrvveerr--ssiiddee TTLLSS sseessssiioonn ccaacchhee The Postfix SMTP server and the remote SMTP client negotiate a session, which takes some computer time and network bandwidth. By default, this session information is cached only in the smtpd(8) process actually using this session and is lost when the process terminates. To share the session information between multiple smtpd(8) processes, a persistent session cache can be used. You can specify any database type that can store objects of several kbytes and that supports the sequence operator. DBM databases are not suitable because they can only store small objects. The cache is maintained by the tlsmgr(8) process, so there is no problem with concurrent access. Session caching is highly recommended, because the cost of repeatedly negotiating TLS session keys is high. Example: /etc/postfix/main.cf: smtpd_tls_session_cache_database = btree:/etc/postfix/smtpd_scache As of version 2.5, Postfix will no longer maintain this file in a directory with non-Postfix ownership. As a migration aid, attempts to open such files are redirected to the Postfix-owned $data_directory, and a warning is logged. Cached Postfix SMTP server session information expires after a certain amount of time. Postfix/TLS does not use the OpenSSL default of 300s, but a longer time of 3600sec (=1 hour). RFC 2246 recommends a maximum of 24 hours. Example: /etc/postfix/main.cf: smtpd_tls_session_cache_timeout = 3600s SSeerrvveerr aacccceessss ccoonnttrrooll Postfix TLS support introduces three additional features for Postfix SMTP server access control: permit_tls_clientcerts Allow the remote SMTP client SMTP request if the client certificate passes verification, and if its fingerprint is listed in the list of client certificates (see relay_clientcerts discussion below). permit_tls_all_clientcerts Allow the remote client SMTP request if the client certificate passes verification. check_ccert_access type:table If the client certificate passes verification, use its fingerprint as a key for the specified access(5) table. The permit_tls_all_clientcerts feature must be used with caution, because it can result in too many access permissions. Use this feature only if a special CA issues the client certificates, and only if this CA is listed as trusted CA. If other CAs are trusted, any owner of a valid client certificate would be authorized. The permit_tls_all_clientcerts feature can be practical for a specially created email relay server. It is however recommended to stay with the permit_tls_clientcerts feature and list all certificates via $relay_clientcerts, as permit_tls_all_clientcerts does not permit any control when a certificate must no longer be used (e.g. an employee leaving). Example: /etc/postfix/main.cf: smtpd_recipient_restrictions = ... permit_tls_clientcerts reject_unauth_destination ... The Postfix list manipulation routines give special treatment to whitespace and some other characters, making the use of certificate names impractical. Instead we use the certificate fingerprints as they are difficult to fake but easy to use for lookup. Postfix lookup tables are in the form of (key, value) pairs. Since we only need the key, the value can be chosen freely, e.g. the name of the user or host. Example: /etc/postfix/main.cf: relay_clientcerts = hash:/etc/postfix/relay_clientcerts /etc/postfix/relay_clientcerts: D7:04:2F:A7:0B:8C:A5:21:FA:31:77:E1:41:8A:EE:80 lutzpc.at.home SSeerrvveerr--ssiiddee cciipphheerr ccoonnttrroollss To influence the Postfix SMTP server cipher selection scheme, you can give cipherlist string. A detailed description would go to far here; please refer to the OpenSSL documentation. If you don't know what to do with it, simply don't touch it and leave the (openssl-)compiled in default! DO NOT USE " to enclose the string, specify just the string!!! Example: /etc/postfix/main.cf: smtpd_tls_cipherlist = DEFAULT If you want to take advantage of ciphers with EDH, DH parameters are needed. Instead of using the built-in DH parameters for both 1024bit and 512bit, it is better to generate "own" parameters, since otherwise it would "pay" for a possible attacker to start a brute force attack against parameters that are used by everybody. For this reason, the parameters chosen are already different from those distributed with other TLS packages. To generate your own set of DH parameters, use: % ooppeennssssll ggeennddhh --oouutt //eettcc//ppoossttffiixx//ddhh__11002244..ppeemm --22 --rraanndd //vvaarr//rruunn//eeggdd--ppooooll 11002244 % ooppeennssssll ggeennddhh --oouutt //eettcc//ppoossttffiixx//ddhh__551122..ppeemm --22 --rraanndd //vvaarr//rruunn//eeggdd--ppooooll 551122 Examples: /etc/postfix/main.cf: smtpd_tls_dh1024_param_file = /etc/postfix/dh_1024.pem smtpd_tls_dh512_param_file = /etc/postfix/dh_512.pem MMiisscceellllaanneeoouuss sseerrvveerr ccoonnttrroollss The smtpd_starttls_timeout parameter limits the time of Postfix SMTP server write and read operations during TLS startup and shutdown handshake procedures. Example: /etc/postfix/main.cf: smtpd_starttls_timeout = 300s SSMMTTPP CClliieenntt ssppeecciiffiicc sseettttiinnggss Topics covered in this section: * Client-side certificate and private key configuration * Client-side TLS activity logging * Client-side TLS session cache * Enabling TLS in the Postfix SMTP client * Requiring TLS encryption * Disabling server certificate verification * Per-site TLS policies * Closing a DNS loophole with per-site TLS policies * Discovering servers that support TLS * Server certificate verification depth * Client-side cipher controls * Miscellaneous client controls CClliieenntt--ssiiddee cceerrttiiffiiccaattee aanndd pprriivvaattee kkeeyy ccoonnffiigguurraattiioonn During TLS startup negotiation the Postfix SMTP client may present a certificate to the remote SMTP server. The Netscape client is rather clever here and lets the user select between only those certificates that match CA certificates offered by the remote SMTP server. As the Postfix SMTP client uses the "SSL_connect()" function from the OpenSSL package, this is not possible and we have to choose just one certificate. So for now the default is to use _no_ certificate and key unless one is explicitly specified here. Both RSA and DSA certificates are supported. You can have both at the same time, in which case the cipher used determines which certificate is presented. It is possible for the Postfix SMTP client to use the same key/certificate pair as the Postfix SMTP server. If a certificate is to be presented, it must be in "pem" format. The private key must not be encrypted, meaning: it must be accessible without password. Both parts (certificate and private key) may be in the same file. In order for remote SMTP servers to verify the Postfix SMTP client certificates, the CA certificate (in case of a certificate chain, all CA certificates) must be available. You should add these certificates to the client certificate, the client certificate first, then the issuing CA(s). Example: the certificate for "client.example.com" was issued by "intermediate CA" which itself has a certificate of "root CA". Create the client.pem file with: % ccaatt cclliieenntt__cceerrtt..ppeemm iinntteerrmmeeddiiaattee__CCAA..ppeemm >> cclliieenntt..ppeemm A Postfix SMTP client certificate supplied here must be usable as SSL client certificate and hence pass the "openssl verify -purpose sslclient ..." test. A server that trusts the root CA has a local copy of the root CA certificate, so it is not necessary to include the root CA certificate here. Leaving it out of the "client.pem" file reduces the overhead of the TLS exchange. If you want the Postfix SMTP client to accept remote SMTP server certificates issued by these CAs, append the root certificate to $smtp_tls_CAfile or install it in the $smtp_tls_CApath directory. When you configure trust in a root CA, it is not necessary to explicitly trust intermediary CAs signed by the root CA, unless $smtp_tls_scert_verifydepth is less than the number of CAs in the certificate chain for the servers of interest. With a verify depth of 1 you can only verify certificates directly signed by a trusted CA, and all trusted intermediary CAs need to be configured explicitly. With a verify depth of 2 you can verify servers signed by a root CA or a direct intermediary CA (so long as the server is correctly configured to supply its intermediate CA certificate). RSA key and certificate examples: /etc/postfix/main.cf: smtp_tls_cert_file = /etc/postfix/client.pem smtp_tls_key_file = $smtp_tls_cert_file Their DSA counterparts: /etc/postfix/main.cf: smtp_tls_dcert_file = /etc/postfix/client-dsa.pem smtp_tls_dkey_file = $smtp_tls_dcert_file To verify a remote SMTP server certificate, the Postfix SMTP client needs to trust the certificates of the issuing certification authorities. These certificates in "pem" format can be stored in a single $smtp_tls_CAfile or in multiple files, one CA per file in the $smtp_tls_CApath directory. If you use a directory, don't forget to create the necessary "hash" links with: # $$OOPPEENNSSSSLL__HHOOMMEE//bbiinn//cc__rreehhaasshh //ppaatthh//ttoo//ddiirreeccttoorryy The $smtp_tls_CAfile contains the CA certificates of one or more trusted CAs. The file is opened (with root privileges) before Postfix enters the optional chroot jail and so need not be accessible from inside the chroot jail. Additional trusted CAs can be specified via the $smtp_tls_CApath directory, in which case the certificates are read (with $mail_owner privileges) from the files in the directory when the information is needed. Thus, the $smtp_tls_CApath directory needs to be accessible inside the optional chroot jail. The choice between $smtp_tls_CAfile and $smtp_tls_CApath is a space/time tradeoff. If there are many trusted CAs, the cost of preloading them all into memory may not pay off in reduced access time when the certificate is needed. Example: /etc/postfix/main.cf: smtp_tls_CAfile = /etc/postfix/CAcert.pem smtp_tls_CApath = /etc/postfix/certs CClliieenntt--ssiiddee TTLLSS aaccttiivviittyy llooggggiinngg To get additional information about Postfix SMTP client TLS activity you can increase the loglevel from 0..4. Each logging level also includes the information that is logged at a lower logging level. 0 Disable logging of TLS activity. 1 Log TLS handshake and certificate information. 2 Log levels during TLS negotiation. 3 Log hexadecimal and ASCII dump of TLS negotiation process 4 Log hexadecimal and ASCII dump of complete transmission after STARTTLS Example: /etc/postfix/main.cf: smtp_tls_loglevel = 0 CClliieenntt--ssiiddee TTLLSS sseessssiioonn ccaacchhee The remote SMTP server and the Postfix SMTP client negotiate a session, which takes some computer time and network bandwidth. By default, this session information is cached only in the smtp(8) process actually using this session and is lost when the process terminates. To share the session information between multiple smtp(8) processes, a persistent session cache can be used. You can specify any database type that can store objects of several kbytes and that supports the sequence operator. DBM databases are not suitable because they can only store small objects. The cache is maintained by the tlsmgr(8) process, so there is no problem with concurrent access. Session caching is highly recommended, because the cost of repeatedly negotiating TLS session keys is high. Future Postfix SMTP servers may limit the number of sessions that a client is allowed to negotiate per unit time. Example: /etc/postfix/main.cf: smtp_tls_session_cache_database = btree:/etc/postfix/smtp_scache As of version 2.5, Postfix will no longer maintain this file in a directory with non-Postfix ownership. As a migration aid, attempts to open such files are redirected to the Postfix-owned $data_directory, and a warning is logged. Cached Postfix SMTP client session information expires after a certain amount of time. Postfix/TLS does not use the OpenSSL default of 300s, but a longer time of 3600s (=1 hour). RFC 2246 recommends a maximum of 24 hours. Example: /etc/postfix/main.cf: smtp_tls_session_cache_timeout = 3600s EEnnaabblliinngg TTLLSS iinn tthhee PPoossttffiixx SSMMTTPP cclliieenntt By default, TLS is disabled in the Postfix SMTP client, so no difference to plain Postfix is visible. If you enable TLS, the Postfix SMTP client will send STARTTLS when TLS support is announced by the remote SMTP server. When the server accepts the STARTTLS command, but the subsequent TLS handshake fails, and no other server is available, the Postfix SMTP client defers the delivery attempt, and the mail stays in the queue. After a handshake failure, the communications channel is in an indeterminate state and cannot be used for non-TLS deliveries. Example: /etc/postfix/main.cf: smtp_use_tls = yes RReeqquuiirriinngg TTLLSS eennccrryyppttiioonn You can ENFORCE the use of TLS, so that the Postfix SMTP client will not deliver mail over unencrypted connections. In this mode, the remote SMTP server hostname must match the information in the remote server certificate, and the server certificate must be issued by a CA that is trusted by the Postfix SMTP client. If the remote server certificate doesn't verify or the remote SMTP server hostname doesn't match, and no other server is available, the delivery attempt is deferred and the mail stays in the queue. The remote SMTP server hostname is verified against all names provided as dNSNames in the SubjectAlternativeName. If no dNSNames are specified, the CommonName is checked. Verification may be turned off with the smtp_tls_enforce_peername option which is discussed below. Enforcing the use of TLS is useful if you know that you will only connect to servers that support RFC 2487 _and_ that present server certificates that meet the above requirements. An example would be a client only sends email to one specific mailhub that offers the necessary STARTTLS support. Example: /etc/postfix/main.cf: smtp_enforce_tls = yes DDiissaabblliinngg sseerrvveerr cceerrttiiffiiccaattee vveerriiffiiccaattiioonn As of RFC 2487 the requirements for hostname checking for MTA clients are not set. When TLS is required (smtp_enforce_tls = yes), the option smtp_tls_enforce_peername can be set to "no" to disable strict remote SMTP server hostname checking. In this case, the mail delivery will proceed regardless of the CommonName etc. listed in the certificate. Despite the potential for eliminating "man-in-the-middle" and other attacks, mandatory certificate/peername verification is not viable as a default Internet mail delivery policy at this time. A significant fraction of TLS enabled MTAs uses self-signed certificates, or certificates that are signed by a private certificate authority. On a machine that delivers mail to the Internet, if you set smtp_enforce_tls = yes, you should probably also set smtp_tls_enforce_peername = no. You can use the per-site TLS policies (see below) to enable full peer verification for specific destinations that are known to have verifiable TLS server certificates. Example: /etc/postfix/main.cf: smtp_enforce_tls = yes smtp_tls_enforce_peername = no PPeerr--ssiittee TTLLSS ppoolliicciieess A small fraction of servers offer STARTTLS but the negotiation consistently fails, leading to mail aging out of the queue and bouncing back to the sender. In such cases, you can use the per-site policies to disable TLS for the problem sites. Alternatively, you can enable TLS for just a few specific sites and not enable it for all sites. The smtp_tls_per_site table is searched for a policy that matches the following information: remote SMTP server hostname This is simply the DNS name of the server that the Postfix SMTP client connects to; this name may be obtained from other DNS lookups, such as MX lookups or CNAME lookups. next-hop destination This is normally the domain portion of the recipient address, but it may be overruled by information from the transport(5) table, from the relayhost parameter setting, or from the relay_transport setting. When it's not the recipient domain, the next-hop destination can have the Postfix-specific form "[name]", [name]:port", "name" or "name:port". When both the hostname lookup and the next-hop lookup succeed, the host policy does not automatically override the next-hop policy. Instead, precedence is given to either the more specific or the more secure per-site policy as described below. The smtp_tls_per_site table uses a simple "name whitespace value" format. Specify host names or next-hop destinations on the left-hand side; no wildcards are allowed. On the right hand side specify one of the following keywords: NONE Don't use TLS at all. This overrides a less specific MMAAYY lookup result from the alternate host or next-hop lookup key, and overrides the global smtp_use_tls, smtp_enforce_tls, and smtp_tls_enforce_peername settings. MAY Try to use TLS if the server announces support, otherwise use the unencrypted connection. This has less precedence than a more specific result (including NNOONNEE) from the alternate host or next-hop lookup key, and has less precedence than the more specific global "smtp_enforce_tls = yes" or "smtp_tls_enforce_peername = yes". MUST_NOPEERMATCH Require TLS encryption, but do not require that the remote SMTP server hostname matches the information in the remote SMTP server certificate, or that the server certificate was issued by a trusted CA. This overrides a less secure NNOONNEE or a less specific MMAAYY lookup result from the alternate host or next-hop lookup key, and overrides the global smtp_use_tls, smtp_enforce_tls and smtp_tls_enforce_peername settings. MUST Require TLS encryption, require that the remote SMTP server hostname matches the information in the remote SMTP server certificate, and require that the remote SMTP server certificate was issued by a trusted CA. This overrides a less secure NNOONNEE and MMUUSSTT__NNOOPPEEEERRMMAATTCCHH or a less specific MMAAYY lookup result from the alternate host or next-hop lookup key, and overrides the global smtp_use_tls, smtp_enforce_tls and smtp_tls_enforce_peername settings. The precedences between global (main.cf) and per-site TLS policies can be summarized as follows: * When neither the remote SMTP server hostname nor the next-hop destination are found in the smtp_tls_per_site table, the policy is based on smtp_use_tls, smtp_enforce_tls and smtp_tls_enforce_peername. Note: "smtp_enforce_tls = yes" and "smtp_tls_enforce_peername = yes" imply "smtp_use_tls = yes". * When both hostname and next-hop destination lookups produce a result, the more specific per-site policy (NONE, MUST, etc) overrides the less specific one (MAY), and the more secure per-site policy (MUST, etc) overrides the less secure one (NONE). * After the per-site policy lookups are combined, the result generally overrides the global policy. The exception is the less specific MMAAYY per- site policy, which is overruled by the more specific global "smtp_enforce_tls = yes" with server certificate verification as specified with the smtp_tls_enforce_peername parameter. CClloossiinngg aa DDNNSS lloooopphhoollee wwiitthh ppeerr--ssiittee TTLLSS ppoolliicciieess As long as no secure DNS lookup mechanism is available, false hostnames in MX or CNAME responses can change the server hostname that Postfix uses for TLS policy lookup and server certificate verification. Even with a perfect match between the server hostname and the server certificate, there is no guarantee that Postfix is connected to the right server. To avoid this loophole take the following steps: * Eliminate MX lookups. Specify local transport(5) table entries for sensitive domains with explicit smtp:[mailhost] or smtp:[mailhost]:port destinations (you can assure security of this table unlike DNS); in the smtp_tls_per_site table specify the value MMUUSSTT for the key [mailhost] or smtp:[mailhost]:port. This prevents false hostname information in DNS MX records from changing the server hostname that Postfix uses for TLS policy lookup and server certificate verification. * Disallow CNAME hostname overrides. In main.cf specify "smtp_cname_overrides_servername = no". This prevents false hostname information in DNS CNAME records from changing the server hostname that Postfix uses for TLS policy lookup and server certificate verification. This feature requires Postfix 2.2.9 or later. Example: /etc/postfix/main.cf: smtp_tls_per_site = hash:/etc/postfix/tls_per_site relayhost = [msa.example.net]:587 /etc/postfix/tls_per_site: # relayhost exact nexthop match [msa.example.net]:587 MUST # TLS should not be used with the example.org MX hosts. example.org NONE # TLS should not be used with the host smtp.example.com. smtp.example.com NONE DDiissccoovveerriinngg sseerrvveerrss tthhaatt ssuuppppoorrtt TTLLSS As we decide on a "per site" basis whether or not to use TLS, it would be good to have a list of sites that offered "STARTTLS". We can collect it ourselves with this option. If the smtp_tls_note_starttls_offer feature is enabled and a server offers STARTTLS while TLS is not already enabled for that server, the Postfix SMTP client logs a line as follows: postfix/smtp[pid]: Host offered STARTTLS: [hostname.example.com] Example: /etc/postfix/main.cf: smtp_tls_note_starttls_offer = yes SSeerrvveerr cceerrttiiffiiccaattee vveerriiffiiccaattiioonn ddeepptthh When verifying a remote SMTP server certificate, a verification depth of 1 is sufficient if the certificate is directly issued by a CA specified with smtp_tls_CAfile or smtp_tls_CApath. The default value of 5 should also suffice for longer chains (root CA issues special CA which then issues the actual certificate...) Example: /etc/postfix/main.cf: smtp_tls_scert_verifydepth = 5 CClliieenntt--ssiiddee cciipphheerr ccoonnttrroollss To influence the Postfix SMTP client cipher selection scheme, you can give cipherlist string. A detailed description would go to far here; please refer to the OpenSSL documentation. If you don't know what to do with it, simply don't touch it and leave the (openssl-)compiled in default! DO NOT USE " to enclose the string, specify just the string!!! Example: /etc/postfix/main.cf: smtp_tls_cipherlist = DEFAULT MMiisscceellllaanneeoouuss cclliieenntt ccoonnttrroollss The smtp_starttls_timeout parameter limits the time of Postfix SMTP client write and read operations during TLS startup and shutdown handshake procedures. In case of problems the Postfix SMTP client tries the next network address on the mail exchanger list, and defers delivery if no alternative server is available. Example: /etc/postfix/main.cf: smtp_starttls_timeout = 300s TTLLSS mmaannaaggeerr ssppeecciiffiicc sseettttiinnggss The security of cryptographic software such as TLS depends critically on the ability to generate unpredictable numbers for keys and other information. To this end, the tlsmgr(8) process maintains a Pseudo Random Number Generator (PRNG) pool. This is queried by the smtp(8) and smtpd(8) processes when they initialize. By default, these daemons request 32 bytes, the equivalent to 256 bits. This is more than sufficient to generate a 128bit (or 168bit) session key. Example: /etc/postfix/main.cf: tls_daemon_random_bytes = 32 In order to feed its in-memory PRNG pool, the tlsmgr(8) reads entropy from an external source, both at startup and during run-time. Specify a good entropy source, like EGD or /dev/urandom; be sure to only use non-blocking sources (on OpenBSD, use /dev/arandom when tlsmgr(8) complains about /dev/urandom timeout errors). If the entropy source is not a regular file, you must prepend the source type to the source name: "dev:" for a device special file, or "egd:" for a source with EGD compatible socket interface. Examples (specify only one in main.cf): /etc/postfix/main.cf: tls_random_source = dev:/dev/urandom tls_random_source = egd:/var/run/egd-pool By default, tlsmgr(8) reads 32 bytes from the external entropy source at each seeding event. This amount (256bits) is more than sufficient for generating a 128bit symmetric key. With EGD and device entropy sources, the tlsmgr(8) limits the amount of data read at each step to 255 bytes. If you specify a regular file as entropy source, a larger amount of data can be read. Example: /etc/postfix/main.cf: tls_random_bytes = 32 In order to update its in-memory PRNG pool, the tlsmgr(8) queries the external entropy source again after a pseudo-random amount of time. The time is calculated using the PRNG, and is between 0 and the maximal time specified with tls_random_reseed_period. The default maximal time interval is 1 hour. Example: /etc/postfix/main.cf: tls_random_reseed_period = 3600s The tlsmgr(8) process saves the PRNG state to a persistent exchange file at regular times and when the process terminates, so that it can recover the PRNG state the next time it starts up. This file is created when it does not exist. Its default location is under the Postfix configuration directory, which is not the proper place for information that is modified by Postfix. Instead, the file location should probably be on the /var partition (but nnoott inside the chroot jail). Examples: /etc/postfix/main.cf: tls_random_exchange_name = /etc/postfix/prng_exch tls_random_prng_update_period = 3600s GGeettttiinngg ssttaarrtteedd,, qquuiicckk aanndd ddiirrttyy The following steps will get you started quickly. Because you sign your own Postfix public key certificate, you get TLS encryption but no TLS authentication. This is sufficient for testing, and for exchanging email with sites that you have no trust relationship with. For real authentication, your Postfix public key certificate needs to be signed by a recognized Certificate Authority, and Postfix needs to be configured with a list of public key certificates of Certificate Authorities, so that Postfix can verify the public key certificates of remote hosts. In the examples below, user input is shown in bboolldd font, and a "#" prompt indicates a super-user shell. * Become your own Certificate Authority, so that you can sign your own public keys. This example uses the CA.pl script that ships with OpenSSL. By default, OpenSSL installs this as /usr/local/ssl/misc/CA.pl, but your mileage may vary. The script creates a private key in ./demoCA/private/ cakey.pem and a public key in ./demoCA/cacert.pem. % //uussrr//llooccaall//ssssll//mmiisscc//CCAA..ppll --nneewwccaa CA certificate filename (or enter to create) Making CA certificate ... Using configuration from /etc/ssl/openssl.cnf Generating a 1024 bit RSA private key ....................++++++ .....++++++ writing new private key to './demoCA/private/cakey.pem' Enter PEM pass phrase:wwhhaatteevveerr * Create an unpassworded private key for host FOO and create an unsigned public key certificate. % ooppeennssssll rreeqq --nneeww --nnooddeess --kkeeyyoouutt FFOOOO--kkeeyy..ppeemm --oouutt FFOOOO--rreeqq..ppeemm --ddaayyss 336655 Using configuration from /etc/ssl/openssl.cnf Generating a 1024 bit RSA private key ........................................++++++ ....++++++ writing new private key to 'FOO-key.pem' ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:UUSS State or Province Name (full name) [Some-State]:NNeeww YYoorrkk Locality Name (eg, city) []:WWeessttcchheesstteerr Organization Name (eg, company) [Internet Widgits Pty Ltd]:PPoorrccuuppiinnee Organizational Unit Name (eg, section) []: Common Name (eg, YOUR name) []:FFOOOO Email Address []:wwiieettssee@@ppoorrccuuppiinnee..oorrgg Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []:wwhhaatteevveerr An optional company name []: * Sign the public key certificate for host FOO with the Certification Authority private key that we created a few steps ago. % ooppeennssssll ccaa --oouutt FFOOOO--cceerrtt..ppeemm --iinnffiilleess FFOOOO--rreeqq..ppeemm Uing configuration from /etc/ssl/openssl.cnf Enter PEM pass phrase:wwhhaatteevveerr Check that the request matches the signature Signature ok The Subjects Distinguished Name is as follows countryName :PRINTABLE:'US' stateOrProvinceName :PRINTABLE:'New York' localityName :PRINTABLE:'Westchester' organizationName :PRINTABLE:'Porcupine' commonName :PRINTABLE:'FOO' emailAddress :IA5STRING:'wietse@porcupine.org' Certificate is to be certified until Nov 21 19:40:56 2005 GMT (365 days) Sign the certificate? [y/n]:yy 1 out of 1 certificate requests certified, commit? [y/n]yy Write out database with 1 new entries Data Base Updated * Install the host private key, the host public key certificate, and the Certification Authority certificate files. This requires super-user privileges. # ccpp ddeemmooCCAA//ccaacceerrtt..ppeemm FFOOOO--kkeeyy..ppeemm FFOOOO--cceerrtt..ppeemm //eettcc//ppoossttffiixx # cchhmmoodd 664444 //eettcc//ppoossttffiixx//FFOOOO--cceerrtt..ppeemm //eettcc//ppoossttffiixx//ccaacceerrtt..ppeemm # cchhmmoodd 440000 //eettcc//ppoossttffiixx//FFOOOO--kkeeyy..ppeemm * Configure Postfix, by adding the following to /etc/postfix/main.cf. smtp_tls_CAfile = /etc/postfix/cacert.pem smtp_tls_cert_file = /etc/postfix/FOO-cert.pem smtp_tls_key_file = /etc/postfix/FOO-key.pem smtp_tls_session_cache_database = btree:/var/run/smtp_tls_session_cache smtp_use_tls = yes smtpd_tls_CAfile = /etc/postfix/cacert.pem smtpd_tls_cert_file = /etc/postfix/FOO-cert.pem smtpd_tls_key_file = /etc/postfix/FOO-key.pem smtpd_tls_received_header = yes smtpd_tls_session_cache_database = btree:/var/run/ smtpd_tls_session_cache smtpd_use_tls = yes tls_random_source = dev:/dev/urandom RReeppoorrttiinngg pprroobblleemmss When reporting a problem, please be thorough in the report. Patches, when possible, are greatly appreciated too. Please differentiate when possible between: * Problems in the TLS code: * Problems in vanilla Postfix: CCoommppaattiibbiilliittyy wwiitthh PPoossttffiixx <<22..22 TTLLSS ssuuppppoorrtt Postfix version 2.2 TLS support is based on the Postfix/TLS patch by Lutz Jänicke, but differs in a few minor ways. * main.cf: Specify "btree" instead of "sdbm" for TLS session cache databases. TLS session cache databases are now accessed only by the tlsmgr(8) process, so there are no more concurrency issues. Although Postfix has an sdbm client, the sdbm library (1000 lines of code) is not included with Postfix. TLS session caches can use any database that can store objects of several kbytes or more, and that implements the sequence operation. In most cases, btree databases should be adequate. NOTE: You cannot use dbm databases. TLS session objects are too large. * master.cf: Specify "unix" instead of "fifo" as the tlsmgr service type. The smtp(8) and smtpd(8) processes now use a client-server protocol in order to access the tlsmgr(8) pseudo-random number generation (PRNG) pool, and in order to access the TLS session cache databases. Such a protocol cannot be run across fifos. * smtp_tls_per_site: the MUST_NOPEERMATCH per-site policy cannot override the global "smtp_tls_enforce_peername = yes" setting. * smtp_tls_per_site: a combined (NONE + MAY) lookup result for (hostname and next-hop destination) produces counter-intuitive results for different main.cf settings. TLS is enabled with "smtp_tls_enforce_peername = no", but it is disabled when both "smtp_enforce_tls = yes" and "smtp_tls_enforce_peername = yes". The smtp_tls_per_site limitations were removed by the end of the Postfix 2.2 support cycle. CCrreeddiittss * TLS support for Postfix was originally developed by Lutz Jänicke at Cottbus Technical University. * Wietse Venema adopted the code, did some restructuring, and compiled this part of the documentation from Lutz's documents. * Victor Duchovni was instrumental with the re-implementation of the smtp_tls_per_site code in terms of enforcement levels, which simplified the implementation greatly. README_FILES/BUILTIN_FILTER_README000066600000033702150501202770011546 0ustar00 PPoossttffiixx BBuuiilltt--iinn CCoonntteenntt IInnssppeeccttiioonn ------------------------------------------------------------------------------- BBuuiilltt--iinn ccoonntteenntt iinnssppeeccttiioonn iinnttrroodduuccttiioonn Postfix supports a built-in filter mechanism that examines message header and message body content, one line at a time, before it is stored in the Postfix queue. The filter is usually implemented with POSIX or PCRE regular expressions, as described in the header_checks(5) manual page. The original purpose of the built-in filter is to stop an outbreak of specific email worms or viruses, and it does this job well. The filter has also helped to block bounced junk email, bounced email from worms or viruses, and notifications from virus detection systems. Information about this secondary application is given in the BACKSCATTER_README document. Because the built-in filter is optimized for stopping specific worms and virus outbreaks, it has limitations that make it NOT suitable for general junk email and virus detection. For that, you should use one of the external content inspection methods that are described in the FILTER_README, SMTPD_PROXY_README and MILTER_README documents. The following diagram gives an over-all picture of how Postfix built-in content inspection works: Postmaster notifications | v Network or -> BBuuiilltt--iinn -> Postfix -> Delivery -> Network or local users ffiilltteerr queue agents local mailbox ^ | | v Undeliverable mail Forwarded mail The picture makes clear that the filter works while Postfix is receiving new mail. This means that Postfix can reject mail from the network without having to return undeliverable mail to the originator address (which is often spoofed anyway). However, this ability comes at a price: if mail inspection takes too much time, then the remote client will time out, and the client may send the same message repeatedly. Topics covered by this document: * What mail is subjected to header/body checks * Limitations of Postfix header/body checks * Preventing daily mail status reports from being blocked * Configuring header/body checks for mail from outside users only * Configuring header/body checks for mail to some domains only WWhhaatt mmaaiill iiss ssuubbjjeecctteedd ttoo hheeaaddeerr//bbooddyy cchheecckkss Postfix header/body checks are implemented by the cleanup(8) server before it injects mail into the incoming queue. The diagram below zooms in on the cleanup (8) server, and shows that this server handles mail from many different sources. In order to keep the diagram readable, the sources of postmaster notifications are not shown, because they can be produced by many Postfix daemon processes. bounce(8) (undeliverable) ssmmttppdd((88)) | ((nneettwwoorrkk)) \ v qqmmqqppdd((88)) -\ cleanup(8) -> incoming ((nneettwwoorrkk)) -/ queue ppiicckkuupp((88)) / ^ ((llooccaall)) | local(8) (forwarded) For efficiency reasons, only mail that enters from outside of Postfix is inspected with header/body checks. It would be inefficient to filter already filtered mail again, and it would be undesirable to block postmaster notifications. The table below summarizes what mail is and is not subject to header/body checks. _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |MMeessssaaggee ttyyppee |SSoouurrccee |HHeeaaddeerr//bbooddyy cchheecckkss??| |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |Undeliverable mail|bounce(8)|No | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |Network mail |smtpd(8) |Configurable | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |Network mail |qmqpd(8) |Configurable | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |Local submission |pickup(8)|Configurable | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |Local forwarding |local(8) |No | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |Postmaster notice |many |No | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | How does Postfix decide what mail needs to be filtered? It would be clumsy to make the decision in the cleanup(8) server, as this program receives mail from so many different sources. Instead, header/body checks are requested by the source. Examples of how to turn off header/body checks for mail received with smtpd(8), qmqpd(8) or pickup(8) are given below under "Configuring header/body checks for mail from outside users only" and "Configuring header/body checks for mail to some domains only". LLiimmiittaattiioonnss ooff PPoossttffiixx hheeaaddeerr//bbooddyy cchheecckkss * Header/body checks do not decode message headers or message body content. For example, if text in the message body is BASE64 encoded (RFC 2045) then your regular expressions will have to match the BASE64 encoded form. Likewise, message headers with encoded non-ASCII characters (RFC 2047) need to be matched in their encoded form. * Header/body checks cannot filter on a combination of message headers or body lines. Header/body checks examine content one message header at a time, or one message body line at a time, and cannot carry a decision over to the next message header or body line. * Header/body checks cannot depend on the recipient of a message. o One message can have multiple recipients, and all recipients of a message receive the same treatment. Workarounds have been proposed that involve selectively deferring some recipients of multi-recipient mail, but that results in poor SMTP performance and does not work for non- SMTP mail. o Some sources of mail send the headers and content ahead of the recipient information. It would be inefficient to buffer up an entire message before deciding if it needs to be filtered, and it would be clumsy to filter mail and to buffer up all the actions until it is known whether those actions need to be executed. * Despite warnings, some people try to use the built-in filter feature for general junk email and/or virus blocking, using hundreds or even thousands of regular expressions. This can result in catastrophic performance failure. The symptoms are as follows: o The cleanup(8) processes use up all available CPU time in order to process the regular expressions, and/or they use up all available memory so that the system begins to swap. This slows down all incoming mail deliveries. o As Postfix needs more and more time to receive an email message, the number of simultaneous SMTP sessions increases to the point that the SMTP server process limit is reached. o While all SMTP server processes are waiting for the cleanup(8) servers to finish, new SMTP clients have to wait until an SMTP server process becomes available. This causes mail deliveries to time out before they have even begun. The remedy for this type of performance problem is simple: don't use header/body checks for general junk email and/or virus blocking, and don't filter mail before it is queued. When performance is a concern, use an external content filter that runs after mail is queued, as described in the FILTER_README document. PPrreevveennttiinngg ddaaiillyy mmaaiill ssttaattuuss rreeppoorrttss ffrroomm bbeeiinngg bblloocckkeedd The following is quoted from Jim Seymour's Pflogsumm FAQ at http:// jimsun.linxnet.com/downloads/pflogsumm-faq.txt. Pflogsumm is a program that analyzes Postfix logs, including the logging from rejected mail. If these logs contain text that was rejected by Postfix body_checks patterns, then the logging is also likely to be rejected by those same body_checks patterns. This problem does not exist with header_checks patterns, because those are not applied to the text that is part of the mail status report. You configure Postfix to do body checks, Postfix does its thing, Pflogsumm reports it and Postfix catches the same string in the Pflogsumm report. There are several solutions to this. Wolfgang Zeikat contributed this: #!/usr/bin/perl use MIME::Lite; ### Create a new message: $msg = MIME::Lite->new( From => 'your@send.er', To => 'your@recipie.nt', # Cc => 'some@other.com, some@more.com', Subject => 'pflogsumm', Date => `date`, Type => 'text/plain', Encoding => 'base64', Path => '/tmp/pflogg', ); $msg->send; Where "/tmp/pflogg" is the output of Pflogsumm. This puts Pflogsumm's output in a base64 MIME attachment. Note by Wietse: if you run this on a machine that is accessible by untrusted users, it is safer to store the Pflogsumm report in a directory that is not world writable. In a follow-up to a thread in the postfix-users mailing list, Ralf Hildebrandt noted: "mpack does the same thing." And it does. Which tool one should use is a matter of preference. Other solutions involve additional body_checks rules that make exceptions for daily mail status reports, but this is not recommended. Such rules slow down all mail and complicate Postfix maintenance. CCoonnffiigguurriinngg hheeaaddeerr//bbooddyy cchheecckkss ffoorr mmaaiill ffrroomm oouuttssiiddee uusseerrss oonnllyy The following information applies to Postfix 2.1 and later. Earlier Postfix versions do not support the receive_override_options feature. The easiest approach is to configure ONE Postfix instance with multiple SMTP server IP addresses in master.cf: * Two SMTP server IP addresses for mail from inside users only, with header/ body filtering turned off, and a local mail pickup service with header/body filtering turned off. /etc/postfix.master.cf: # ================================================================== # service type private unpriv chroot wakeup maxproc command # (yes) (yes) (yes) (never) (100) # ================================================================== 1.2.3.4:smtp inet n - n - - smtpd -o receive_override_options=no_header_body_checks 127.0.0.1:smtp inet n - n - - smtpd -o receive_override_options=no_header_body_checks pickup fifo n - n 60 1 pickup -o receive_override_options=no_header_body_checks * Add some firewall rule to prevent access to 1.2.3.4:smtp from the outside world. * One SMTP server address for mail from outside users with header/body filtering turned on via main.cf. /etc/postfix.master.cf: # ================================================================= # service type private unpriv chroot wakeup maxproc command # (yes) (yes) (yes) (never) (100) # ================================================================= 1.2.3.5:smtp inet n - n - - smtpd CCoonnffiigguurriinngg hheeaaddeerr//bbooddyy cchheecckkss ffoorr mmaaiill ttoo ssoommee ddoommaaiinnss oonnllyy The following information applies to Postfix 2.1. Earlier Postfix versions do not support the receive_override_options feature. If you are MX service provider and want to apply disable head/body checks for some domains, you can configure ONE Postfix instance with multiple SMTP server IP addresses in master.cf. Each address provides a different service. /etc/postfix.master.cf: # ================================================================= # service type private unpriv chroot wakeup maxproc command # (yes) (yes) (yes) (never) (100) # ================================================================= # SMTP service for domains with header/body checks turned on. 1.2.3.4:smtp inet n - n - - smtpd # SMTP service for domains with header/body checks turned off. 1.2.3.5:smtp inet n - n - - smtpd -o receive_override_options=no_header_body_checks Once this is set up you can configure MX records in the DNS that route each domain to the proper SMTP server instance. README_FILES/CONNECTION_CACHE_README000066600000021727150501202770011721 0ustar00PPoossttffiixx CCoonnnneeccttiioonn CCaacchhee ------------------------------------------------------------------------------- IInnttrroodduuccttiioonn This document describes the Postfix connection cache implementation, which is available with Postfix version 2.2 and later. Topics covered in this document: * What SMTP connection caching can do for you * Connection cache implementation * Connection cache configuration * Connection cache safety mechanisms * Connection cache limitations * Connection cache statistics WWhhaatt SSMMTTPP ccoonnnneeccttiioonn ccaacchhiinngg ccaann ddoo ffoorr yyoouu With SMTP connection caching, Postfix can deliver multiple messages over the same SMTP connection. By default, Postfix 2.2 reuses an SMTP connection automatically when a destination has high volume of mail in the active queue. SMTP Connection caching is a performance feature. Whether or not it actually improves performance depends on the conditions: * SMTP Connection caching can greatly improve performance when delivering mail to a destination with multiple mail servers, because it can help Postfix to skip over a non-responding server. * Otherwise, the benefits of SMTP connection caching are minor: it eliminates the latency of the TCP handshake (SYN, SYN+ACK, ACK), plus the latency of the SMTP initial handshake (220 greeting, EHLO command, EHLO response). * SMTP Connection caching gives no gains with respect to SMTP session tear- down. The Postfix smtp(8) client normally does not wait for the server's reply to the QUIT command, and it never waits for the TCP final handshake to complete. * SMTP Connection caching introduces some overhead: the client needs to send an RSET command to find out if a connection is still usable, before it can send the next MAIL FROM command. For other potential issues with SMTP connection caching, see the discussion of limitations at the end of this document. CCoonnnneeccttiioonn ccaacchhee iimmpplleemmeennttaattiioonn For an overview of how Postfix delivers mail, see the Postfix architecture OVERVIEW document. The Postfix connection cache is shared among Postfix mail delivering processes. This maximizes the opportunity to reuse an open connection. Other MTAs such as Sendmail or exim have a non-shared connection cache. Here, a connection can be reused only by the mail delivering process that creates the connection. To get the same performance improvement as with a shared connection cache, non-shared connections need to be kept open for a longer time. The scache(8) server, introduced with Postfix version 2.2, maintains the shared connection cache. With Postfix version 2.2, only the smtp(8) client has support to access this cache. /-- smtp(8) --> Internet qmgr(8) | | \-- | smtp(8) --> Internet | ^ | scache(8) When SMTP connection caching is enabled (see next section), the smtp(8) client does not disconnect after a mail transaction, but gives the connection to the scache(8) server which keeps the connection open for a limited amount of time. After handing over the open connection to the scache(8) server, the smtp(8) client continues with some other mail delivery request. Meanwhile, any smtp(8) client process can ask the scache(8) server for that cached connection and reuse it for mail delivery. The connection cache can be searched by destination domain name (the right-hand side of the recipient address) and by the IP address of the host at the other end of the connection. This allows Postfix to reuse a connection even when the remote host is mail server for domains with different names. CCoonnnneeccttiioonn ccaacchhee ccoonnffiigguurraattiioonn The Postfix smtp(8) client supports two connection caching strategies: * On-demand connection caching. This is enabled by default, and is controlled with the smtp_connection_cache_on_demand configuration parameter. When this feature is enabled, the Postfix smtp(8) client automatically saves a connection to the connection cache when a destination has a high volume of mail in the active queue. Example: /etc/postfix/main.cf: smtp_connection_cache_on_demand = yes * Per-destination connection caching. This is enabled by explicitly listing specific destinations with the smtp_connection_cache_destinations configuration parameter. After completing delivery to a selected destination, the Postfix smtp(8) client always saves the connection to the connection cache. Specify a comma or white space separated list of destinations or pseudo- destinations: o if mail is sent without a relay host: a domain name (the right-hand side of an email address, without the [] around a numeric IP address), o if mail is sent via a relay host: a relay host name (without the [] or non-default TCP port), as specified in main.cf or in the transport map, o a /file/name with domain names and/or relay host names as defined above, o a "type:table" with domain names and/or relay host names on the left- hand side. The right-hand side result from "type:table" lookups is ignored. Examples: /etc/postfix/main.cf: smtp_connection_cache_destinations = $relayhost smtp_connection_cache_destinations = hotmail.com, ... smtp_connection_cache_destinations = static:all (not recommended) CCoonnnneeccttiioonn ccaacchhee ssaaffeettyy mmeecchhaanniissmmss Connection caching must be used wisely. It is anti-social to keep an unused SMTP connection open for a significant amount of time, and it is unwise to send huge numbers of messages through the same connection. In order to avoid problems with SMTP connection caching, Postfix implements the following safety mechanisms: * The Postfix scache(8) server keeps a connection open for only a limited time. The time limit is specified with the smtp_connection_cache_time_limit and with the connection_cache_ttl_limit configuration parameters. This prevents anti-social behavior. * The Postfix smtp(8) client reuses a session for only a limited number of times. This avoids triggering bugs in implementations that do not correctly handle multiple deliveries per session. With Postfix 2.2 the use count is limited with the smtp_connection_cache_reuse_limit configuration parameter. With Postfix 2.3 this is replaced by a time limit which is specified with the smtp_connection_reuse_time_limit parameter. In addition, Postfix 2.3 logs the use count of multiply-used connections, as shown in the following example: Nov 3 16:04:31 myname postfix/smtp[30840]: 19B6B2900FE: to=, orig_to=, relay=mail.example.com[1.2.3.4], ccoonnnn__uussee==22, delay=0.22, delays=0.04/0.01/0.05/0.1, dsn=2.0.0, status=sent (250 2.0.0 Ok) * The connection cache explicitly labels each cached connection with destination domain and IP address information. A connection cache lookup succeeds only when the correct information is specified. This prevents mis- delivery of mail. CCoonnnneeccttiioonn ccaacchhee lliimmiittaattiioonnss Postfix SMTP connection caching conflicts with certain applications: * The Postfix shared connection cache cannot be used with TLS, because saved TLS session information can be used only when a new connection is created (this limitation does not exist in connection caching implementations that reuse a connection only in the process that creates it). For this reason, the Postfix smtp(8) client always closes the connection after completing an attempt to deliver mail over TLS. * Postfix connection caching currently does not support multiple SASL accounts per mail server. Specifically, Postfix connection caching assumes that a SASL credential is valid for all hostnames or domain names that deliver via the same mail server IP address and TCP port, and assume that the SASL credential does not depend on the message originator. CCoonnnneeccttiioonn ccaacchhee ssttaattiissttiiccss The scache(8) connection cache server logs statistics about the peak cache size and the cache hit rates. This information is logged every connection_cache_status_update_time seconds, when the process terminates after the maximal idle time is exceeded, or when Postfix is reloaded. * Hit rates for connection cache lookups by domain will tell you how useful connection caching is. * Connection cache lookups by network address will always fail, unless you're sending mail to different domains that share the same MX hosts. * No statistics are logged when no attempts are made to access the connection cache. README_FILES/UUCP_README000066600000012221150501202770010140 0ustar00PPoossttffiixx aanndd UUUUCCPP ------------------------------------------------------------------------------- UUssiinngg UUUUCCPP oovveerr TTCCPP Despite a serious lack of sex-appeal, email via UUCP over TCP is a practical option for sites without permanent Internet connections, and for sites without a fixed IP address. For first-hand information, see the following guides: * Jim Seymour's guide for using UUCP over TCP at http://jimsun.LinxNet.com/ jdp/uucp_over_tcp/index.html, * Craig Sanders's guide for SSL-encrypted UUCP over TCP using stunnel at http://taz.net.au/postfix/uucp/. Here's a graphical description of what this document is about: LAN to Internet Local network <---> UUCP <--- UUCP ---> to UUCP <---> Internet Gateway Gateway And here's the table of contents of this document: * Setting up a Postfix Internet to UUCP gateway * Setting up a Postfix LAN to UUCP gateway SSeettttiinngg uupp aa PPoossttffiixx IInntteerrnneett ttoo UUUUCCPP ggaatteewwaayy Here is how to set up a machine that sits on the Internet and that forwards mail to a LAN that is connected via UUCP. See the LAN to UUCP gateway section for the other side of the story. * You need an rrmmaaiill program that extracts the sender address from mail that arrives via UUCP, and that feeds the mail into the Postfix sseennddmmaaiill command. Most UNIX systems come with an rrmmaaiill utility. If you're in a pinch, try the one bundled with the Postfix source code in the aauuxxiilliiaarryy// rrmmaaiill directory. * Define a pipe(8) based mail delivery transport for delivery via UUCP: /etc/postfix/master.cf: uucp unix - n n - - pipe flags=F user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient) This runs the uuuuxx command to place outgoing mail into the UUCP queue after replacing $nexthop by the next-hop hostname (the receiving UUCP host) and after replacing $recipient by the recipients. The pipe(8) delivery agent executes the uuuuxx command without assistance from the shell, so there are no problems with shell meta characters in command-line parameters. * Specify that mail for example.com, should be delivered via UUCP, to a host named uucp-host: /etc/postfix/transport: example.com uucp:uucp-host .example.com uucp:uucp-host See the transport(5) manual page for more details. * Execute the command "ppoossttmmaapp //eettcc//ppoossttffiixx//ttrraannssppoorrtt" whenever you change the ttrraannssppoorrtt file. * Enable ttrraannssppoorrtt table lookups: /etc/postfix/main.cf: transport_maps = hash:/etc/postfix/transport Specify ddbbmm instead of hhaasshh if your system uses ddbbmm files instead of ddbb files. To find out what map types Postfix supports, use the command "ppoossttccoonnff --mm". * Add example.com to the list of domains that your site is willing to relay mail for. /etc/postfix/main.cf: relay_domains = example.com ...other relay domains... See the relay_domains configuration parameter description for details. * Execute the command "ppoossttffiixx rreellooaadd" to make the changes effective. SSeettttiinngg uupp aa PPoossttffiixx LLAANN ttoo UUUUCCPP ggaatteewwaayy Here is how to relay mail from a LAN via UUCP to the Internet. See the Internet to UUCP gateway section for the other side of the story. * You need an rrmmaaiill program that extracts the sender address from mail that arrives via UUCP, and that feeds the mail into the Postfix sseennddmmaaiill command. Most UNIX systems come with an rrmmaaiill utility. If you're in a pinch, try the one bundled with the Postfix source code in the aauuxxiilliiaarryy// rrmmaaiill directory. * Specify that all remote mail must be sent via the uuuuccpp mail transport to your UUCP gateway host, say, uucp-gateway: /etc/postfix/main.cf: relayhost = uucp-gateway default_transport = uucp Postfix 2.0 and later also allows the following more succinct form: /etc/postfix/main.cf: default_transport = uucp:uucp-gateway * Define a pipe(8) based message delivery transport for mail delivery via UUCP: /etc/postfix/master.cf: uucp unix - n n - - pipe flags=F user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient) This runs the uuuuxx command to place outgoing mail into the UUCP queue. It substitutes the next-hop hostname (uucp-gateway, or whatever you specified) and the recipients before executing the command. The uuuuxx command is executed without assistance from the shell, so there are no problems with shell meta characters. * Execute the command "ppoossttffiixx rreellooaadd" to make the changes effective. README_FILES/CONTENT_INSPECTION_README000066600000006445150501202770012244 0ustar00PPoossttffiixx CCoonntteenntt IInnssppeeccttiioonn ------------------------------------------------------------------------------- Postfix supports three content inspection methods, ranging from light-weight one-line-at-a-time scanning before mail is queued, to heavy duty machinery that does sophisticated content analysis after mail is queued. Each approach serves a different purpose. bbeeffoorree qquueeuuee,, bbuuiilltt--iinn,, lliigghhtt--wweeiigghhtt This method inspects mail BEFORE it is stored in the queue, and uses Postfix's built-in message header and message body inspection. Although the main purpose is to stop a specific flood of mail from worms or viruses, it is also useful to block a flood of bounced junk email and email notifications from virus detection systems. The built-in regular expressions are not meant to implement general SPAM and virus detection. For that, you should use one of the content inspection methods described below. Details are described in the BUILTIN_FILTER_README and BACKSCATTER_README documents. aafftteerr qquueeuuee,, eexxtteerrnnaall,, hheeaavvyy--wweeiigghhtt This method inspects mail AFTER it is stored in the queue, and uses standard protocols such as SMTP or "pipe to command and wait for exit status". After-queue inspection allows you to use content filters of arbitrary complexity without causing timeouts while receiving mail, and without running out of memory resources under a peak load. Details of this approach are in the FILTER_README document. bbeeffoorree qquueeuuee,, eexxtteerrnnaall,, mmeeddiiuumm--wweeiigghhtt The following two methods inspect mail BEFORE it is stored in the queue. * The first method uses the SMTP protocol, and is described in the SMTPD_PROXY_README document. This approach is available with Postfix version 2.1 and later. * The second method uses the Sendmail 8 Milter protocol, and is described in the MILTER_README document. This approach is available with Postfix version 2.3 and later. Although these approaches appear to be attractive, they have some serious limitations that you need to be aware of. First, content inspection software must finish in a limited amount of time; if content inspection needs too much time then incoming mail deliveries will time out. Second, content inspection software must run in a limited amount of memory; if content inspection needs too much memory then software will crash under a peak load. Before-queue inspection limits the peak load that your system can handle, and limits the sophistication of the content filter that you can use. The more sophisticated content filtering software is not built into Postfix for good reasons: writing an MTA requires different skills than writing a SPAM or virus killer. Postfix encourages the use of external filters and standard protocols because this allows you to choose the best MTA and the best content inspection software for your purpose. Information about external content inspection software can be found on the Postfix website at http:// www.postfix.org/, and on the postfix-users@postfix.org mailing list. README_FILES/VIRTUAL_README000066600000056452150501202770010530 0ustar00PPoossttffiixx VViirrttuuaall DDoommaaiinn HHoossttiinngg HHoowwttoo ------------------------------------------------------------------------------- PPuurrppoossee ooff tthhiiss ddooccuummeenntt This document requires Postfix version 2.0 or later. This document gives an overview of how Postfix can be used for hosting multiple Internet domains, both for final delivery on the machine itself and for the purpose of forwarding to destinations elsewhere. The text not only describes delivery mechanisms that are built into Postfix, but also gives pointers for using non-Postfix mail delivery software. The following topics are covered: * Canonical versus hosted versus other domains * Local files versus network databases * As simple as can be: shared domains, UNIX system accounts * Postfix virtual ALIAS example: separate domains, UNIX system accounts * Postfix virtual MAILBOX example: separate domains, non-UNIX accounts * Non-Postfix mailbox store: separate domains, non-UNIX accounts * Mail forwarding domains * Mailing lists * Autoreplies CCaannoonniiccaall vveerrssuuss hhoosstteedd vveerrssuuss ootthheerr ddoommaaiinnss Most Postfix systems are ffiinnaall ddeessttiinnaattiioonn for only a few domain names. These include the hostnames and [the IP addresses] of the machine that Postfix runs on, and sometimes also include the parent domain of the hostname. The remainder of this document will refer to these domains as the canonical domains. They are usually implemented with the Postfix local domain address class, as defined in the ADDRESS_CLASS_README file. Besides the canonical domains, Postfix can be configured to be ffiinnaall ddeessttiinnaattiioonn for any number of additional domains. These domains are called hosted, because they are not directly associated with the name of the machine itself. Hosted domains are usually implemented with the virtual alias domain address class and/or with the virtual mailbox domain address class, as defined in the ADDRESS_CLASS_README file. But wait! There is more. Postfix can be configured as a backup MX host for other domains. In this case Postfix is nnoott tthhee ffiinnaall ddeessttiinnaattiioonn for those domains. It merely queues the mail when the primary MX host is down, and forwards the mail when the primary MX host becomes available. This function is implemented with the relay domain address class, as defined in the ADDRESS_CLASS_README file. Finally, Postfix can be configured as a transit host for sending mail across the internet. Obviously, Postfix is not final destination for such mail. This function is available only for authorized clients and/or users, and is implemented by the default domain address class, as defined in the ADDRESS_CLASS_README file. LLooccaall ffiilleess vveerrssuuss nneettwwoorrkk ddaattaabbaasseess The examples in this text use table lookups from local files such as DBM or Berkeley DB. These are easy to debug with the ppoossttmmaapp command: Example: postmap -q info@example.com hash:/etc/postfix/virtual See the documentation in LDAP_README, MYSQL_README and PGSQL_README for how to replace local files by databases. The reader is strongly advised to make the system work with local files before migrating to network databases, and to use the ppoossttmmaapp command to verify that network database lookups produce the exact same results as local file lookup. Example: postmap -q info@example.com ldap:/etc/postfix/virtual.cf AAss ssiimmppllee aass ccaann bbee:: sshhaarreedd ddoommaaiinnss,, UUNNIIXX ssyysstteemm aaccccoouunnttss The simplest method to host an additional domain is to add the domain name to the domains listed in the Postfix mydestination configuration parameter, and to add the user names to the UNIX password file. This approach makes no distinction between canonical and hosted domains. Each username can receive mail in every domain. In the examples we will use "example.com" as the domain that is being hosted on the local Postfix machine. /etc/postfix/main.cf: mydestination = $myhostname localhost.$mydomain ... example.com The limitations of this approach are: * A total lack of separation: mail for info@my.host.name is delivered to the same UNIX system account as mail for info@example.com. * With users in the UNIX password file, administration of large numbers of users becomes inconvenient. The examples that follow provide solutions for both limitations. PPoossttffiixx vviirrttuuaall AALLIIAASS eexxaammppllee:: sseeppaarraattee ddoommaaiinnss,, UUNNIIXX ssyysstteemm aaccccoouunnttss With the approach described in this section, every hosted domain can have its own info etc. email address. However, it still uses UNIX system accounts for local mailbox deliveries. With virtual alias domains, each hosted address is aliased to a local UNIX system account or to a remote address. The example below shows how to use this mechanism for the example.com domain. 1 /etc/postfix/main.cf: 2 virtual_alias_domains = example.com ...other hosted domains... 3 virtual_alias_maps = hash:/etc/postfix/virtual 4 5 /etc/postfix/virtual: 6 postmaster@example.com postmaster 7 info@example.com joe 8 sales@example.com jane 9 # Uncomment entry below to implement a catch-all address 10 # @example.com jim 11 ...virtual aliases for more domains... Notes: * Line 2: the virtual_alias_domains setting tells Postfix that example.com is a so-called virtual alias domain. If you omit this setting then Postfix will reject mail (relay access denied) or will not be able to deliver it (mail for example.com loops back to myself). NEVER list a virtual alias domain name as a mydestination domain! * Lines 3-8: the /etc/postfix/virtual file contains the virtual aliases. With the example above, mail for postmaster@example.com goes to the local postmaster, while mail for info@example.com goes to the UNIX account joe, and mail for sales@example.com goes to the UNIX account jane. Mail for all other addresses in example.com is rejected with the error message "User unknown". * Line 10: the commented out entry (text after #) shows how one would implement a catch-all virtual alias that receives mail for every example.com address not listed in the virtual alias file. This is not without risk. Spammers nowadays try to send mail from (or mail to) every possible name that they can think of. A catch-all mailbox is likely to receive many spam messages, and many bounces for spam messages that were sent in the name of anything@example.com. Execute the command "ppoossttmmaapp //eettcc//ppoossttffiixx//vviirrttuuaall" after changing the virtual file, and execute the command "ppoossttffiixx rreellooaadd" after changing the main.cf file. Note: virtual aliases can resolve to a local address or to a remote address, or both. They don't have to resolve to UNIX system accounts on your machine. More details about the virtual alias file are given in the virtual(5) manual page, including multiple addresses on the right-hand side. Virtual aliasing solves one problem: it allows each domain to have its own info mail address. But there still is one drawback: each virtual address is aliased to a UNIX system account. As you add more virtual addresses you also add more UNIX system accounts. The next section eliminates this problem. PPoossttffiixx vviirrttuuaall MMAAIILLBBOOXX eexxaammppllee:: sseeppaarraattee ddoommaaiinnss,, nnoonn--UUNNIIXX aaccccoouunnttss As a system hosts more and more domains and users, it becomes less desirable to give every user their own UNIX system account. With the Postfix virtual(8) mailbox delivery agent, every recipient address can have its own virtual mailbox. Unlike virtual alias domains, virtual mailbox domains do not need the clumsy translation from each recipient addresses into a different address, and owners of a virtual mailbox address do not need to have a UNIX system account. The Postfix virtual(8) mailbox delivery agent looks up the user mailbox pathname, uid and gid via separate tables that are searched with the recipient's mail address. Maildir style delivery is turned on by terminating the mailbox pathname with "/". If you find the idea of multiple tables bothersome, remember that you can migrate the information (once it works), to an SQL database. If you take that route, be sure to review the "local files versus databases" section at the top of this document. Here is an example of a virtual mailbox domain "example.com": 1 /etc/postfix/main.cf: 2 virtual_mailbox_domains = example.com ...more domains... 3 virtual_mailbox_base = /var/mail/vhosts 4 virtual_mailbox_maps = hash:/etc/postfix/vmailbox 5 virtual_minimum_uid = 100 6 virtual_uid_maps = static:5000 7 virtual_gid_maps = static:5000 8 virtual_alias_maps = hash:/etc/postfix/virtual 9 10 /etc/postfix/vmailbox: 11 info@example.com example.com/info 12 sales@example.com example.com/sales/ 13 # Comment out the entry below to implement a catch-all. 14 # @example.com example.com/catchall 15 ...virtual mailboxes for more domains... 16 17 /etc/postfix/virtual: 18 postmaster@example.com postmaster Notes: * Line 2: The virtual_mailbox_domains setting tells Postfix that example.com is a so-called virtual mailbox domain. If you omit this setting then Postfix will reject mail (relay access denied) or will not be able to deliver it (mail for example.com loops back to myself). NEVER list a virtual MAILBOX domain name as a mydestination domain! NEVER list a virtual MAILBOX domain name as a virtual ALIAS domain! * Line 3: The virtual_mailbox_base parameter specifies a prefix for all virtual mailbox pathnames. This is a safety mechanism in case someone makes a mistake. It prevents mail from being delivered all over the file system. * Lines 4, 10-15: The virtual_mailbox_maps parameter specifies the lookup table with mailbox (or maildir) pathnames, indexed by the virtual mail address. In this example, mail for info@example.com goes to the mailbox at /var/mail/vhosts/example.com/info while mail for sales@example.com goes to the maildir located at /var/mail/vhosts/example.com/sales/. * Line 5: The virtual_minimum_uid specifies a lower bound on the mailbox or maildir owner's UID. This is a safety mechanism in case someone makes a mistake. It prevents mail from being written to sensitive files. * Lines 6, 7: The virtual_uid_maps and virtual_gid_maps parameters specify that all the virtual mailboxes are owned by a fixed uid and gid 5000. If this is not what you want, specify lookup tables that are searched by the recipient's mail address. * Line 14: The commented out entry (text after #) shows how one would implement a catch-all virtual mailbox address. Be prepared to receive a lot of spam, as well as bounced spam that was sent in the name of anything@example.com. NEVER put a virtual MAILBOX wild-card in the virtual ALIAS file!! * Lines 8, 17, 18: As you see, it is possible to mix virtual aliases with virtual mailboxes. We use this feature to redirect mail for example.com's postmaster address to the local postmaster. You can use the same mechanism to redirect an address to a remote address. * Line 18: This example assumes that in main.cf, $myorigin is listed under the mydestination parameter setting. If that is not the case, specify an explicit domain name on the right-hand side of the virtual alias table entries or else mail will go to the wrong domain. Execute the command "ppoossttmmaapp //eettcc//ppoossttffiixx//vviirrttuuaall" after changing the virtual file, execute "ppoossttmmaapp //eettcc//ppoossttffiixx//vvmmaaiillbbooxx" after changing the vmailbox file, and execute the command "ppoossttffiixx rreellooaadd" after changing the main.cf file. Note: mail delivery happens with the recipient's UID/GID privileges specified with virtual_uid_maps and virtual_gid_maps. Postfix 2.0 and earlier will not create mailDIRs in world-writable parent directories; you must create them in advance before you can use them. Postfix may be able to create mailBOX files by itself, depending on parent directory write permissions, but it is safer to create mailBOX files ahead of time. More details about the virtual mailbox delivery agent are given in the virtual (8) manual page. NNoonn--PPoossttffiixx mmaaiillbbooxx ssttoorree:: sseeppaarraattee ddoommaaiinnss,, nnoonn--UUNNIIXX aaccccoouunnttss This is a variation on the Postfix virtual mailbox example. Again, every hosted address can have its own mailbox. While non-Postfix software is being used for final delivery, some Postfix concepts are still needed in order to glue everything together. For additional background on this glue you may want to take a look at the virtual mailbox domain class as defined in the ADDRESS_CLASS_README file. The text in this section describes what things should look like from Postfix's point of view. See CYRUS_README or MAILDROP_README for specific information about Cyrus or about Courier maildrop. Here is an example for a hosted domain example.com that delivers to a non- Postfix delivery agent: 1 /etc/postfix/main.cf: 2 virtual_transport = ...see below... 3 virtual_mailbox_domains = example.com ...more domains... 4 virtual_mailbox_maps = hash:/etc/postfix/vmailbox 5 virtual_alias_maps = hash:/etc/postfix/virtual 6 7 /etc/postfix/vmailbox: 8 info@example.com whatever 9 sales@example.com whatever 10 # Comment out the entry below to implement a catch-all. 11 # Configure the mailbox store to accept all addresses. 12 # @example.com whatever 13 ...virtual mailboxes for more domains... 14 15 /etc/postfix/virtual: 16 postmaster@example.com postmaster Notes: * Line 2: With delivery to a non-Postfix mailbox store for hosted domains, the virtual_transport parameter usually specifies the Postfix LMTP client, or the name of a master.cf entry that executes non-Postfix software via the pipe delivery agent. Typical examples (use only one): virtual_transport = lmtp:unix:/path/name (uses UNIX-domain socket) virtual_transport = lmtp:hostname:port (uses TCP socket) virtual_transport = maildrop: (uses pipe(8) to command) Postfix comes ready with support for LMTP. And an example maildrop delivery method is already defined in the default Postfix master.cf file. See the MAILDROP_README document for more details. * Line 3: The virtual_mailbox_domains setting tells Postfix that example.com is delivered via the virtual_transport that was discussed in the previous paragraph. If you omit this virtual_mailbox_domains setting then Postfix will either reject mail (relay access denied) or will not be able to deliver it (mail for example.com loops back to myself). NEVER list a virtual MAILBOX domain name as a mydestination domain! NEVER list a virtual MAILBOX domain name as a virtual ALIAS domain! * Lines 4, 7-13: The virtual_mailbox_maps parameter specifies the lookup table with all valid recipient addresses. The lookup result value is ignored by Postfix. In the above example, info@example.com and sales@example.com are listed as valid addresses; other mail for example.com is rejected with "User unknown" by the Postfix SMTP server. It's left up to the non-Postfix delivery agent to reject non-existent recipients from local submission or from local alias expansion. If you intend to use LDAP, MySQL or PgSQL instead of local files, be sure to review the "local files versus databases" section at the top of this document! * Line 12: The commented out entry (text after #) shows how one would inform Postfix of the existence of a catch-all address. Again, the lookup result is ignored by Postfix. NEVER put a virtual MAILBOX wild-card in the virtual ALIAS file!! Note: if you specify a wildcard in virtual_mailbox_maps, then you still need to configure the non-Postfix mailbox store to receive mail for any address in that domain. * Lines 5, 15, 16: As you see above, it is possible to mix virtual aliases with virtual mailboxes. We use this feature to redirect mail for example.com's postmaster address to the local postmaster. You can use the same mechanism to redirect any addresses to a local or remote address. * Line 16: This example assumes that in main.cf, $myorigin is listed under the mydestination parameter setting. If that is not the case, specify an explicit domain name on the right-hand side of the virtual alias table entries or else mail will go to the wrong domain. Execute the command "ppoossttmmaapp //eettcc//ppoossttffiixx//vviirrttuuaall" after changing the virtual file, execute "ppoossttmmaapp //eettcc//ppoossttffiixx//vvmmaaiillbbooxx" after changing the vmailbox file, and execute the command "ppoossttffiixx rreellooaadd" after changing the main.cf file. MMaaiill ffoorrwwaarrddiinngg ddoommaaiinnss Some providers host domains that have no (or only a few) local mailboxes. The main purpose of these domains is to forward mail elsewhere. The following example shows how to set up example.com as a mail forwarding domain: 1 /etc/postfix/main.cf: 2 virtual_alias_domains = example.com ...other hosted domains... 3 virtual_alias_maps = hash:/etc/postfix/virtual 4 5 /etc/postfix/virtual: 6 postmaster@example.com postmaster 7 joe@example.com joe@somewhere 8 jane@example.com jane@somewhere-else 9 # Uncomment entry below to implement a catch-all address 10 # @example.com jim@yet-another-site 11 ...virtual aliases for more domains... Notes: * Line 2: The virtual_alias_domains setting tells Postfix that example.com is a so-called virtual alias domain. If you omit this setting then Postfix will reject mail (relay access denied) or will not be able to deliver it (mail for example.com loops back to myself). NEVER list a virtual alias domain name as a mydestination domain! * Lines 3-11: The /etc/postfix/virtual file contains the virtual aliases. With the example above, mail for postmaster@example.com goes to the local postmaster, while mail for joe@example.com goes to the remote address joe@somewhere, and mail for jane@example.com goes to the remote address jane@somewhere-else. Mail for all other addresses in example.com is rejected with the error message "User unknown". * Line 10: The commented out entry (text after #) shows how one would implement a catch-all virtual alias that receives mail for every example.com address not listed in the virtual alias file. This is not without risk. Spammers nowadays try to send mail from (or mail to) every possible name that they can think of. A catch-all mailbox is likely to receive many spam messages, and many bounces for spam messages that were sent in the name of anything@example.com. Execute the command "ppoossttmmaapp //eettcc//ppoossttffiixx//vviirrttuuaall" after changing the virtual file, and execute the command "ppoossttffiixx rreellooaadd" after changing the main.cf file. More details about the virtual alias file are given in the virtual(5) manual page, including multiple addresses on the right-hand side. MMaaiilliinngg lliissttss The examples that were given above already show how to direct mail for virtual postmaster addresses to a local postmaster. You can use the same method to direct mail for any address to a local or remote address. There is one major limitation: virtual aliases and virtual mailboxes can't directly deliver to mailing list managers such as majordomo. The solution is to set up virtual aliases that direct virtual addresses to the local delivery agent: /etc/postfix/main.cf: virtual_alias_maps = hash:/etc/postfix/virtual /etc/postfix/virtual: listname-request@example.com listname-request listname@example.com listname owner-listname@example.com owner-listname /etc/aliases: listname: "|/some/where/majordomo/wrapper ..." owner-listname: ... listname-request: ... This example assumes that in main.cf, $myorigin is listed under the mydestination parameter setting. If that is not the case, specify an explicit domain name on the right-hand side of the virtual alias table entries or else mail will go to the wrong domain. More information about the Postfix local delivery agent can be found in the local(8) manual page. Why does this example use a clumsy virtual alias instead of a more elegant transport mapping? The reason is that mail for the virtual mailing list would be rejected with "User unknown". In order to make the transport mapping work one would still need a bunch of virtual alias or virtual mailbox table entries. * In case of a virtual alias domain, there would need to be one identity mapping from each mailing list address to itself. * In case of a virtual mailbox domain, there would need to be a dummy mailbox for each mailing list address. AAuuttoorreepplliieess In order to set up an autoreply for virtual recipients while still delivering mail as normal, set up a rule in a virtual alias table: /etc/postfix/main.cf: virtual_alias_maps = hash:/etc/postfix/virtual /etc/postfix/virtual: user@domain.tld user@domain.tld, user@domain.tld@autoreply.mydomain.tld This delivers mail to the recipient, and sends a copy of the mail to the address that produces automatic replies. The address can be serviced on a different machine, or it can be serviced locally by setting up a transport map entry that pipes all mail for autoreply.mydomain.tld into some script that sends an automatic reply back to the sender. DO NOT list autoreply.mydomain.tld in mydestination! /etc/postfix/main.cf: transport_maps = hash:/etc/postfix/transport /etc/postfix/transport: autoreply.mydomain.tld autoreply: /etc/postfix/master.cf: # ============================================================= # service type private unpriv chroot wakeup maxproc command # (yes) (yes) (yes) (never) (100) # ============================================================= autoreply unix - n n - - pipe flags= user=nobody argv=/path/to/autoreply $sender $mailbox This invokes /path/to/autoreply with the sender address and the user@domain.tld recipient address on the command line. For more information, see the pipe(8) manual page, and the comments in the Postfix master.cf file. README_FILES/RELEASE_NOTES000066600000030566150501202770010413 0ustar00The stable Postfix release is called postfix-2.6.x where 2=major release number, 6=minor release number, x=patchlevel. The stable release never changes except for patches that address bugs or emergencies. Patches change the patchlevel and the release date. New features are developed in snapshot releases. These are called postfix-2.7-yyyymmdd where yyyymmdd is the release date (yyyy=year, mm=month, dd=day). Patches are never issued for snapshot releases; instead, a new snapshot is released. The mail_release_date configuration parameter (format: yyyymmdd) specifies the release date of a stable release or snapshot release. If you upgrade from Postfix 2.4 or earlier, read RELEASE_NOTES-2.5 before proceeding. Major changes - multi-instance support -------------------------------------- [Feature 20090121] Support for managing multiple Postfix instances. This can automatically apply your "postfix start" etc. command to multiple Postfix instances, including upgrades to new Postfix versions. Multi-instance support allows you to do the following and more: - Simplify post-queue content filter configuration by using separate Postfix instances before and after the filter. This simplifies trouble shooting and performance tuning. - Implement per-user content filters (or no filter) via transport map lookups instead of content_filter settings. Mail for some users can be sent directly from the before-filter instance to the after-filter instance. - Test new configuration settings (on a different server IP address or TCP port) without disturbing production instances. - Each additional Postfix instance uses a few files and directories, plus memory for an extra master daemon and queue manager. The pickup daemon is needed only if you use local submission or "postsuper -r". Best of all, nothing changes when you use only one Postfix instance. The MULTI_INSTANCE_README file presents an introduction to multi-instance management. Multi-instance support is based on an API that is described in the postfix-wrapper(5) manual page. Major changes - milter support ------------------------------ [Feature 20090428] The following improvements have been made to the Milter implementation: - Improved compatibility of the {mail_addr} and {rcpt_addr} macros. - Support for the {mail_host}, {mail_mailer}, {rcpt_host} and {rcpt_mailer} macros. - Milter applications can now request rejected recipients with the SMFIP_RCPT_REJ feature. Rejected recipients are reported with {rcpt_mailer} = "error", {rcpt_host} = enhanced status code, and {rcpt_addr} = descriptive text. This feature requires "milter_protocol = 6" or higher (default as of Postfix 2.6). - Milters can now replace the envelope sender address with the SMFIR_CHGFROM request, and can add recipients with SMFIR_ADDRCPT_PAR. These implementations ignore ESMTP command parameters and log a warning message as follows: warning: 100B22B3293: cleanup_chg_from: ignoring ESMTP arguments "whatever" warning: 100B22B3293: cleanup_add_rcpt: ignoring ESMTP arguments "whatever" [Incompat 20090428] The default milter_protocol setting is increased from 2 to 6; this enables all available features up to and including Sendmail 8.14.0. The new milter_protocol setting may break compatibility with older Milter libraries or applications, and may cause Postfix to log warning messages such as: warning: milter inet:host:port: can't read packet header: Unknown error : 0 warning: milter inet:host:port: can't read packet header: Success warning: milter inet:host:port: can't read SMFIC_DATA reply packet header: No such file or directory To restore compatibility, specify "milter_protocol = 2" in main.cf. Major changes - security ------------------------ [Incompat 20080726] When a mailbox file is not owned by its recipient, the local and virtual delivery agents now log a warning and defer delivery. Specify "strict_mailbox_ownership = no" to ignore such ownership discrepancies. Major changes - smtp server --------------------------- [Feature 20080212] check_reverse_client_hostname_access, to make access decisions based on the unverified client hostname. For safety reasons an OK result is not allowed. [Feature 20090210] With "reject_tempfail_action = defer", the Postfix SMTP server immediately replies with a 4xx status after some temporary error, instead of executing an implicit "defer_if_permit" action. [Feature 20090215] The Postfix SMTP server automatically hangs up after replying with "521". This makes overload handling more effective. See also RFC 1846 for prior art on this topic. [Feature 20090228] The Postfix SMTP server maintains a per-session "improper command pipelining detected" flag. This flag can be tested at any time with reject_unauth_pipelining, and is raised whenever a client command is followed by unexpected commands or message content. The Postfix SMTP server logs the first command pipelining transgression as "improper command pipelining after from []". [Feature 20090212] Stress-dependent behavior is enabled by default. Under conditions of overload, smtpd_timeout is reduced from 300s to 10s, smtpd_hard_error_limit is reduced from 20 to 1, and smtpd_junk_command_limit is reduced from 100 to 1. This will reduce the impact of overload for most legitimate mail. [Feature 20080629] The Postfix SMTP server's SASL authentication was re-structured. With "smtpd_tls_auth_only = yes", SASL support is now activated only after a successful TLS handshake. Earlier Postfix SMTP server versions could complain about unavailable SASL mechanisms during the plaintext phase of the SMTP protocol. [Incompat 20080510] In the policy delegation protocol, certificate common name attributes are now xtext encoded UTF-8. The xtext decoded attributes may contain any UTF-8 value except non-printable ASCII characters. Major changes - performance --------------------------- [Feature 20090215] The Postfix SMTP server automatically hangs up after replying with "521". This makes overload handling more effective. See also RFC 1846 for prior art on this topic. [Feature 20090212] Stress-dependent behavior is enabled by default. Under conditions of overload, smtpd_timeout is reduced from 300s to 10s, smtpd_hard_error_limit is reduced from 20 to 1, and smtpd_junk_command_limit is reduced from 100 to 1. This will reduce the negative impact of server overload for most legitimate mail. [Feature 20090109] Specify "tcp_windowsize = 65535" (or less) to work around routers with broken TCP window scaling implementations. This is perhaps more convenient than collecting tcpdump output and tuning kernel parameters by hand. With Postfix TCP servers (smtpd(8), qmqpd(8)), this feature is implemented by the Postfix master(8) daemon. To change this parameter without stopping Postfix, you need to first terminate all Postfix TCP servers: # postconf -e master_service_disable=inet # postfix reload This immediately terminates all processes that accept network connections. Then you enable Postfix TCP servers with the updated tcp_windowsize setting: # postconf -e tcp_windowsize=65535 master_service_disable= # postfix reload If you skip these steps with a running Postfix system, then the tcp_windowsize change will work only for Postfix TCP clients (smtp(8), lmtp(8)). Of course you can also do "postfix stop" and "postfix start", but that is more disruptive. Major changes - tls ------------------- [Incompat 20090428] The Postfix SMTP client(!) no longer tries to use the obsolete SSLv2 protocol by default, as this may prevent the use of modern SSL features. Lack of SSLv2 support should never be a problem, since SSLv3 was defined in 1996, and TLSv1 in 1999. You can undo the change by specifying empty main.cf values for smtp_tls_protocols and lmtp_tls_protocols. The Postfix SMTP server maintains SSLv2 support for backwards compatibility with ancient clients. [Feature 20081010] Controls for the protocols and ciphers that Postfix will use with opportunistic TLS. The smtp_tls_protocols, smtp_tls_ciphers, and equivalent parameters for lmtp and smtpd provide global settings; the SMTP client TLS policy table provides ciphers and protocols settings for specific peers. Code by Victor Duchovni. Details are given in the TLS_README and postconf(5) documents. [Feature 20081108] Elliptic curve support. This requires OpenSSL version 0.9.9 or later. Major changes - address verification ------------------------------------ [Incompat 20080428] Postfix SMTP server replies for address verification have changed. unverified_recipient_reject_code and unverified_sender_reject_code now handle "5XX" rejects only. The "4XX" rejects are now controlled with unverified_sender_defer_code and unverified_recipient_defer_code. [Feature 20080428] Finer control over the way Postfix reports address verification failures to remote SMTP clients. - unverified_sender/recipient_defer_code: the numerical Postfix SMTP server reply code when address verification failed due to some temporary error. - unverified_sender/recipient_reject_reason: fixed text that Postfix will send to the remote SMTP client, instead of sending actual address verification details. Major changes - dsn ------------------- [Feature 20090307] New "lmtp_assume_final = yes" flag to send correct DSN "success" notifications when LMTP delivery is "final" as opposed to delivery into a content filter. Major changes - file organization --------------------------------- [Incompat 20080207] According to discussions on the mailing list, too many people are breaking newly installed Postfix by overwriting the new /etc/postfix files with versions from an older release, and end up with a broken configuration that cannot repair itself. For this reason, postfix-script, postfix-files and post-install are moved away from /etc/postfix to $daemon_directory. Major changes - header rewriting -------------------------------- [Incompat 20090330] Postfix now adds (Resent-) From:, Date:, Message-ID: or To: headers only when clients match $local_header_rewrite_clients. Specify "always_add_missing_headers = yes" for backwards compatibility. Adding such headers can break DKIM signatures that cover headers that are not present. For compatibility with existing logfile processing software, Postfix will log ``message-id=<>'' for messages without Message-Id header. Major changes - lmtp client --------------------------- [Feature 20090307] New "lmtp_assume_final = yes" flag to send correct DSN "success" notifications when LMTP delivery is "final" as opposed to delivery into a content filter. Major changes - logging ----------------------- [Incompat 20090330] Postfix now adds (Resent-) From:, Date:, Message-ID: or To: headers only when clients match $local_header_rewrite_clients. Specify "always_add_missing_headers = yes" for backwards compatibility. Adding such headers can break DKIM signatures that cover headers that are not present. This changes the appearance of Postfix logging: to preserve compatibility with existing logfile processing software, Postfix will log ``message-id=<>'' for messages without Message-Id header. Major changes - mime -------------------- [Feature 20080324] When the "postmap -q -" command reads lookup keys from standard input, it now understands RFC822 and MIME message format. Specify -h or -b to use headers or body lines as lookup keys, and specify -hm or -bm to simulate header_checks or body_checks. Major changes - miscellaneous ----------------------------- [Feature 20090109] Support to selectively disable master(8) listener ports by service type or by service name + type. Specify a list of service types ("inet", "unix", "fifo", or "pass") or "name.type" tuples, where "name" is the first field of a master.cf entry and "type" is a service type. Examples: to turn off the main SMTP listener port, use "master_service_disable = smtp.inet"; to turn off all TCP/IP listeners, use "master_service_disable = inet". Changing this parameter requires "postfix reload". Major changes - sasl -------------------- [Feature 20090418] The Postfix SMTP server passes more information to the Dovecot authentication server: the "TLS is active" flag, the server IP address, and the client IP address. [Feature 20080629] The Postfix SMTP server's SASL authentication was re-structured. With "smtpd_tls_auth_only = yes", SASL support is now activated only after a successful TLS handshake. Earlier Postfix SMTP server versions could complain about unavailable SASL mechanisms during the plaintext phase of the SMTP protocol. README_FILES/TUNING_README000066600000057415150501202770010406 0ustar00 PPoossttffiixx PPeerrffoorrmmaannccee TTuunniinngg ------------------------------------------------------------------------------- PPuurrppoossee ooff PPoossttffiixx ppeerrffoorrmmaannccee ttuunniinngg The hints and tips in this document help you improve the performance of Postfix systems that already work. If your Postfix system is unable to receive or deliver mail, then you need to solve those problems first, using the DEBUG_README document as guidance. For tuning external content filter performance, first read the respective information in the FILTER_README and SMTPD_PROXY_README documents. Then make sure to avoid latency in the content filter code. As much as possible avoid performing queries against external data sources with a high or highly variable delay. Your content filter will run with a small concurrency to avoid CPU/ memory starvation, and if any latency creeps in, content filter throughput will suffer. High volume environments should avoid RBL lookups, complex database queries and so on. Topics on mail receiving performance: * General mail receiving performance tips * Doing more work with your SMTP server processes * Slowing down SMTP clients that make many errors * Measures against clients that make too many connections Topics on mail delivery performance: * General mail delivery performance tips * Tuning the frequency of deferred mail delivery attempts * Tuning the number of simultaneous deliveries * Tuning the number of recipients per delivery Other Postfix performance tuning topics: * Tuning the number of Postfix processes * Tuning the number of processes on the system * Tuning the number of open files or sockets The following tools can be used to measure mail system performance under artificial loads. They are normally not installed with Postfix. * smtp-source, SMTP/LMTP message generator * smtp-sink, SMTP/LMTP message dump * qmqp-source, QMQP message generator * qmqp-sink, QMQP message dump GGeenneerraall mmaaiill rreecceeiivviinngg ppeerrffoorrmmaannccee ttiippss * Read and understand the maildrop queue, incoming queue, and active queue discussions in the QSHAPE_README document. * Run a local name server to reduce slow-down due to DNS lookups. If you run multiple Postfix systems, point each local name server to a shared forwarding server to reduce the number of lookups across the upstream network link. * Eliminate unnecessary LDAP lookups, by specifying a domain filter. This eliminates lookups for addresses in remote domains, and eliminates lookups of partial addresses. See ldap_table(5) for details. When Postfix responds slowly to SMTP clients: * Look for obvious signs of trouble as described in the DEBUG_README document, and eliminate those problems first. * Turn off your header_checks and body_checks patterns and see if the problem goes away. * Turn off chroot operation as described in the DEBUG_README document and see if the problem goes away. * If Postfix logs the SMTP client as "unknown" then you have a name service problem: the name server is bad, or the resolv.conf file contains bad information, or some packet filter is blocking the DNS requests or replies. * If the number of smtpd(8) processes has reached the process limit as specified in master.cf, new SMTP clients must wait until a process becomes available. Increase the number of processes if memory permits. See the instructions given under "Tuning the number of Postfix processes". DDooiinngg mmoorree wwoorrkk wwiitthh yyoouurr SSMMTTPP sseerrvveerr pprroocceesssseess With Postfix versions 2.0 and earlier, the smtpd(8) server pauses before reporting an error to an SMTP client. The idea is called tar pitting. However, these delays also slow down Postfix. When the smtpd(8) server replies slowly, sessions take more time, so that more smtpd(8) server processes are needed to handle the load. When your Postfix smtpd(8) server process limit is reached, new clients must wait until a server process becomes available. This means that all clients experience poor performance. You can speed up the handling of smtpd(8) server error replies by turning off the delay: /etc/postfix/main.cf: # Not needed with Postfix 2.1 smtpd_error_sleep_time = 0 With the above setting, Postfix 2.0 and earlier can serve more SMTP clients with the same number SMTP server processes. The next section describes how Postfix deals with clients that make a large number of errors. SSlloowwiinngg ddoowwnn SSMMTTPP cclliieennttss tthhaatt mmaakkee mmaannyy eerrrroorrss The Postfix smtpd(8) server maintains a per-session error count. The error count is reset when a message is transferred successfully, and is incremented when a client request is unrecognized or unimplemented, when a client request violates access restrictions, or when some other error happens. As the per-session error count increases, the smtpd(8) server changes behavior and begins to insert delays into the responses. The idea is to slow down a run- away client in order to limit resource usage. The behavior is Postfix version dependent. IMPORTANT: These delays slow down Postfix, too. When too much delay is configured, the number of simultaneous SMTP sessions will increase until it reaches the smtpd(8) server process limit, and new SMTP clients must wait until an smtpd(8) server process becomes available. Postfix version 2.1 and later: * When the error count reaches $smtpd_soft_error_limit (default: 10), the Postfix smtpd(8) server delays all non-error and error responses by $smtpd_error_sleep_time seconds (default: 1 second). * When the error count reaches $smtpd_hard_error_limit (default: 20) the Postfix smtpd(8) server breaks the connection. Postfix version 2.0 and earlier: * When the error count is less than $smtpd_soft_error_limit (default: 10) the Postfix smtpd(8) server delays all error replies by $smtpd_error_sleep_time (1 second with Postfix 2.0, 5 seconds with Postfix 1.1 and earlier). * When the error count reaches $smtpd_soft_error_limit, the Postfix smtpd(8) server delays all responses by "error count" seconds or $smtpd_error_sleep_time, whichever is more. * When the error count reaches $smtpd_hard_error_limit (default: 20) the Postfix smtpd(8) server breaks the connection. MMeeaassuurreess aaggaaiinnsstt cclliieennttss tthhaatt mmaakkee ttoooo mmaannyy ccoonnnneeccttiioonnss Note: these features use the Postfix anvil(8) service, introduced with Postfix version 2.2. The Postfix smtpd(8) server can limit the number of simultaneous connections from the same SMTP client, as well as the connection rate and the rate of certain SMTP commands from the same client. These statistics are maintained by the anvil(8) server (translation: if anvil(8) breaks, then connection limits stop working). IMPORTANT: These limits must not be used to regulate legitimate traffic: mail will suffer grotesque delays if you do so. The limits are designed to protect the smtpd(8) server against abuse by out-of-control clients. smtpd_client_connection_count_limit (default: 50) The maximum number of connections that an SMTP client may make simultaneously. smtpd_client_connection_rate_limit (default: no limit) The maximum number of connections that an SMTP client may make in the time interval specified with anvil_rate_time_unit (default: 60s). smtpd_client_message_rate_limit (default: no limit) The maximum number of message delivery requests that an SMTP client may make in the time interval specified with anvil_rate_time_unit (default: 60s). smtpd_client_recipient_rate_limit (default: no limit) The maximum number of recipient addresses that an SMTP client may specify in the time interval specified with anvil_rate_time_unit (default: 60s). smtpd_client_new_tls_session_rate_limit (default: no limit) The maximum number of new TLS sessions (without using the TLS session cache) that an SMTP client may negotiate in the time interval specified with anvil_rate_time_unit (default: 60s). smtpd_client_event_limit_exceptions (default: $mynetworks) SMTP clients that are excluded from connection and rate limits specified above. GGeenneerraall mmaaiill ddeelliivveerryy ppeerrffoorrmmaannccee ttiippss * Read and understand the maildrop queue, incoming queue, active queue and deferred queue discussions in the QSHAPE_README document. * In case of slow delivery, run the qshape tool as described in the QSHAPE_README document. * Submit multiple recipients per message instead of submitting messages with only a few recipients. * Submit mail via SMTP instead of /usr/sbin/sendmail. You may have to adjust the smtpd_recipient_limit parameter setting. * Don't overwhelm the disk with mail submissions. Optimize the mail submission rate by tuning the number of parallel submissions and/or by tuning the Postfix in_flow_delay parameter setting. * Run a local name server to reduce slow-down due to DNS lookups. If you run multiple Postfix systems, point each local name server to a shared forwarding server to reduce the number of lookups across the upstream network link. * Reduce the smtp_connect_timeout and smtp_helo_timeout values so that Postfix does not waste lots of time connecting to non-responding remote SMTP servers. * Use a dedicated mail delivery transport for problematic destinations, with reduced timeouts and with adjusted concurrency. See "Tuning the number of simultaneous deliveries" below. * Use a fallback_relay host for mail that cannot be delivered upon the first attempt. This "graveyard" machine can use shorter retry times for difficult to reach destinations. See "Tuning the frequency of deferred mail delivery attempts" below. * Speed up disk updates with a large (64MB) persistent write cache. This allows disk updates to be sorted for optimal access speed without compromising file system integrity when the system crashes. * Use a solid-state disk (a persistent RAM disk). This is an expensive solution that should be used in combination with short SMTP timeouts and a fallback_relay "graveyard" machine that delivers mail for problem destinations. TTuunniinngg tthhee nnuummbbeerr ooff ssiimmuullttaanneeoouuss ddeelliivveerriieess Although Postfix can be configured to run 1000 SMTP client processes at the same time, it is rarely desirable that it makes 1000 simultaneous connections to the same remote system. For this reason, Postfix has safety mechanisms in place to avoid this so-called "thundering herd" problem. The Postfix queue manager implements the analog of the TCP slow start flow control strategy: when delivering to a site, send a small number of messages first, then increase the concurrency as long as all goes well; reduce concurrency in the face of congestion. * The initial_destination_concurrency parameter (default: 5) controls how many messages are initially sent to the same destination before adapting delivery concurrency. Of course, this setting is effective only as long as it does not exceed the process limit and the destination concurrency limit for the specific mail transport channel. * The default_destination_concurrency_limit parameter (default: 20) controls how many messages may be sent to the same destination simultaneously. You can override this setting for specific message delivery transports by taking the name of the master.cf entry and appending "_destination_concurrency_limit". Examples of transport specific concurrency limits are: * The local_destination_concurrency_limit parameter (default: 2) controls how many messages are delivered simultaneously to the same local recipient. The recommended limit is low because delivery to the same mailbox must happen sequentially, so massive parallelism is not useful. Another good reason to limit delivery concurrency to the same recipient: if the recipient has an expensive shell command in her .forward file, or if the recipient is a mailing list manager, you don't want to run too many instances of those processes at the same time. * The default smtp_destination_concurrency_limit of 20 seems enough to noticeably load a system without bringing it to its knees. Be careful when changing this to a much larger number. The above default values of the concurrency limits work well in a broad range of situations. Knee-jerk changes to these parameters in the face of congestion can actually make problems worse. Specifically, large destination concurrencies should never be the default. They should be used only for transports that deliver mail to a small number of high volume domains. A common situation where high concurrency is called for is on gateways relaying a high volume of mail from between the Internet and an intranet mail environment. Approximately half the mail (assuming equal volumes inbound and outbound) will be destined for the internal mail hubs. Since the internal mail hubs will be receiving all external mail exclusively from the gateway, it is reasonable to configure the gateway to make greater demands on the capacity of the internal SMTP servers. The tuning of the inbound concurrency limits need not be trial and error. A high volume capable mailhub should be able to easily handle 50 or 100 (rather than the default 20) simultaneous connections, especially if the gateway forwards to multiple MX hosts. When all MX hosts are up and accepting connections in a timely fashion, throughput will be high. If any MX host is down and completely unresponsive, the average connection latency rises to at least 1/N * $smtp_connection_timeout, if there are N MX hosts. This limits throughput to at most the destination concurrency * N / $smtp_connection_timeout. For example, with a destination concurrency of 100 and 2 MX hosts, each host will handle up to 50 simultaneous connections. If one MX host is down and the default SMTP connection timeout is 30s, the throughput limit is 100 * 2 / 30 ~= 6 messages per second. This suggests that high volume destinations with good connectivity and multiple MX hosts need a lower connection timeout, values as low as 5s or even 1s can be used to prevent congestion when one or more, but not all MX hosts are down. If necessary, set a higher transport_destination_concurrency_limit (in main.cf since this is a queue manager parameter) and a lower smtp_connection_timeout (with a "-o" override in master.cf since this parameter has no per-transport name) for the relay transport and any transports dedicated for specific high volume destinations. TTuunniinngg tthhee nnuummbbeerr ooff rreecciippiieennttss ppeerr ddeelliivveerryy The default_destination_recipient_limit parameter (default: 50) controls how many recipients a Postfix delivery agent will send with each copy of an email message. You can override this setting for specific Postfix delivery agents. For example, "uucp_destination_recipient_limit = 100" would limit the number of recipients per UUCP delivery to 100. If an email message exceeds the recipient limit for some destination, the Postfix queue manager breaks up the list of recipients into smaller lists. Postfix will attempt to send multiple copies of the message in parallel. IMPORTANT: Be careful when increasing the recipient limit per message delivery; some smtpd(8) servers abort the connection when they run out of memory or when a hard recipient limit is reached, so that the message will never be delivered. The smtpd_recipient_limit parameter (default: 1000) controls how many recipients the Postfix smtpd(8) server will take per delivery. The default limit is more than any reasonable SMTP client would send. The limit exists to protect the local mail system against a run-away client. TTuunniinngg tthhee ffrreeqquueennccyy ooff ddeeffeerrrreedd mmaaiill ddeelliivveerryy aatttteemmppttss When a Postfix delivery agent (smtp(8), local(8), etc.) is unable to deliver a message it may blame the message itself, or it may blame the receiving party. * When the delivery agent blames the message, the queue manager gives the queue file a time stamp into the future, so it won't be looked at for a while. By default, the amount of time to cool down is the amount of time that has passed since the message arrived. This results in so-called exponential backoff behavior. * When the delivery agent blames the receiving party (for example a local recipient user, or a remote host), the queue manager not only advances the queue file time stamp, but also puts the receiving party on a "dead" list so that it will be skipped for some amount of time. This process is governed by a bunch of little parameters. queue_run_delay (default: 300 seconds; before Postfix 2.4: 1000s) How often the queue manager scans the queue for deferred mail. minimal_backoff_time (default: 300 seconds; before Postfix 2.4: 1000s) The minimal amount of time a message won't be looked at, and the minimal amount of time to stay away from a "dead" destination. maximal_backoff_time (default: 4000 seconds) The maximal amount of time a message won't be looked at after a delivery failure. maximal_queue_lifetime (default: 5 days) How long a message stays in the queue before it is sent back as undeliverable. Specify 0 for mail that should be returned immediately after the first unsuccessful delivery attempt. bounce_queue_lifetime (default: 5 days, available with Postfix version 2.1 and later) How long a MAILER-DAEMON message stays in the queue before it is considered undeliverable. Specify 0 for mail that should be tried only once. qmgr_message_recipient_limit (default: 20000) The size of many in-memory queue manager data structures. Among others, this parameter limits the size of the short-term, in-memory list of "dead" destinations. Destinations that don't fit the list are not added. IMPORTANT: If you increase the frequency of deferred mail delivery attempts, or if you flush the deferred mail queue frequently, then you may find that Postfix mail delivery performance actually becomes worse. The symptoms are as follows: * The active queue becomes saturated with mail that has delivery problems. New mail enters the active queue only when an old message is deferred. This is a slow process that usually requires timing out one or more SMTP connections. * All available Postfix delivery agents become occupied trying to connect to unreachable sites etc. New mail has to wait until a delivery agent becomes available. This is a slow process that usually requires timing out one or more SMTP connections. When mail is being deferred frequently, fixing the problem is always better than increasing the frequency of delivery attempts. However, if you can control only the delivery attempt frequency, consider using a dedicated fallback_relay "graveyard" machine for bad destinations, so that these destinations do not ruin the performance of normal mail deliveries. TTuunniinngg tthhee nnuummbbeerr ooff PPoossttffiixx pprroocceesssseess The default_process_limit configuration parameter gives direct control over how many daemon processes Postfix will run. As of Postfix 2.0 the default limit is 100 smtp client processes, 100 smtp server processes, and so on. This may overwhelm systems with little memory, as well as networks with low bandwidth. You can change the global process limit by specifying a non-default default_process_limit in the main.cf file. For example, to run up to 10 smtp client processes, 10 smtp server processes, and so on: /etc/postfix/main.cf: default_process_limit = 10 You need to execute "postfix reload" to make the change effective. The limits are enforced by the Postfix master(8) daemon which does not automatically read main.cf when it changes. You can override the process limit for specific Postfix daemons by editing the master.cf file. For example, if you do not wish to receive 100 SMTP messages at the same time, but do not want to change the process limits for local mail deliveries, you could specify: /etc/postfix/master.cf: # ==================================================================== # service type private unpriv chroot wakeup maxproc command + args # (yes) (yes) (yes) (never) (100) # ==================================================================== . . . smtp inet n - - - 10 smtpd . . . TTuunniinngg tthhee nnuummbbeerr ooff pprroocceesssseess oonn tthhee ssyysstteemm * MacOS X will run out of process slots when you increase Postfix process limits. The following works with OSX 10.4 and OSX 10.5. MacOS X kernel parameters can be specified in /etc/sysctl.conf. /etc/sysctl.conf: kern.maxproc=2048 kern.maxprocperuid=2048 Unfortunately these can't simply be set on the fly with "sysctl -w". You also have to set the following in /etc/launchd.conf so that the root user after boot will have the right process limit (2048). Otherwise you have to always run ulimit -u 2048 as root, then start a user shell, and then start processes for things to take effect. /etc/launchd.conf: limit maxproc 2048 Once these are in place, reboot the system. After that, the limits will stay in place. TTuunniinngg tthhee nnuummbbeerr ooff ooppeenn ffiilleess oorr ssoocckkeettss When Postfix opens too many files or sockets, processes will abort with fatal errors, and the system may log "file table full" errors. * Depending on your Postfix and operating system versions you may need to recompile Postfix if you need more than 1024 file descriptors per process: o No recompilation is needed for Postfix version 2.4 and later, when it was compiled for systems that support BSD kqueue(2) (FreeBSD 4.1, NetBSD 2.0, OpenBSD 2.9), Solaris 8 /dev/poll, or Linux 2.6 epoll(4). o Otherwise, Postfix needs to be recompiled to override the default FD_SETSIZE value. * Reduce the number of processes as described under "Tuning the number of Postfix processes" above. Fewer processes need fewer open files and sockets. * Configure the kernel for more open files and sockets. The details are extremely system dependent and change with the operating system version. Be sure to verify the following information with your system tuning guide: o Some FreeBSD kernel parameters can be specified in /boot/loader.conf, and some can be specified in /etc/sysctl.conf or changed with sysctl commands. Which is which depends on the version. kern.ipc.maxsockets="5000" kern.ipc.nmbclusters="65536" kern.maxproc="2048" kern.maxfiles="16384" kern.maxfilesperproc="16384" o Linux kernel parameters can be specified in /etc/sysctl.conf or changed with sysctl commands: fs.file-max=16384 kernel.threads-max=2048 o Solaris kernel parameters can be specified in /etc/system, as described in the Solaris FAQ entry titled "How can I increase the number of file descriptors per process?" * set hard limit on file descriptors set rlim_fd_max = 4096 * set soft limit on file descriptors set rlim_fd_cur = 1024 README_FILES/BASIC_CONFIGURATION_README000066600000051350150501202770012302 0ustar00PPoossttffiixx BBaassiicc CCoonnffiigguurraattiioonn ------------------------------------------------------------------------------- IInnttrroodduuccttiioonn Postfix has several hundred configuration parameters that are controlled via the main.cf file. Fortunately, all parameters have sensible default values. In many cases, you need to configure only two or three parameters before you can start to play with the mail system. Here's a quick introduction to the syntax: * Postfix configuration files The text below assumes that you already have Postfix installed on the system, either by compiling the source code yourself (as described in the INSTALL file) or by installing an already compiled version. This document covers basic Postfix configuration. Information about how to configure Postfix for specific applications such as mailhub, firewall or dial- up client can be found in the STANDARD_CONFIGURATION_README file. But don't go there until you already have covered the material presented below. The first parameters of interest specify the machine's identity and role in the network. * What domain name to use in outbound mail * What domains to receive mail for * What clients to relay mail from * What destinations to relay mail to * What delivery method: direct or indirect The default values for many other configuration parameters are derived from just these. The next parameter of interest controls the amount of mail sent to the local postmaster: * What trouble to report to the postmaster Be sure to set the following correctly if you're behind a proxy or network address translator, and you are running a backup MX host for some other domain: * Proxy/NAT external network addresses Postfix daemon processes run in the background, and log problems and normal activity to the syslog daemon. Here are a few things that you need to be aware of: * What you need to know about Postfix logging If your machine has unusual security requirements you may want to run Postfix daemon processes inside a chroot environment. * Running Postfix daemon processes chrooted If you run Postfix on a virtual network interface, or if your machine runs other mailers on virtual interfaces, you'll have to look at the other parameters listed here as well: * My own hostname * My own domain name * My own network addresses PPoossttffiixx ccoonnffiigguurraattiioonn ffiilleess By default, Postfix configuration files are in /etc/postfix. The two most important files are main.cf and master.cf; these files must be owned by root. Giving someone else write permission to main.cf or master.cf (or to their parent directories) means giving root privileges to that person. In /etc/postfix/main.cf you will have to set up a minimal number of configuration parameters. Postfix configuration parameters resemble shell variables, with two important differences: the first one is that Postfix does not know about quotes like the UNIX shell does. You specify a configuration parameter as: /etc/postfix/main.cf: parameter = value and you use it by putting a "$" character in front of its name: /etc/postfix/main.cf: other_parameter = $parameter You can use $parameter before it is given a value (that is the second main difference with UNIX shell variables). The Postfix configuration language uses lazy evaluation, and does not look at a parameter value until it is needed at runtime. Postfix uses database files for access control, address rewriting and other purposes. The DATABASE_README file gives an introduction to how Postfix works with Berkeley DB, LDAP or SQL and other types. Here is a common example of how Postfix invokes a database: /etc/postfix/main.cf: virtual_alias_maps = hash:/etc/postfix/virtual Whenever you make a change to the main.cf or master.cf file, execute the following command as root in order to refresh a running mail system: # postfix reload WWhhaatt ddoommaaiinn nnaammee ttoo uussee iinn oouuttbboouunndd mmaaiill The myorigin parameter specifies the domain that appears in mail that is posted on this machine. The default is to use the local machine name, $myhostname, which defaults to the name of the machine. Unless you are running a really small site, you probably want to change that into $mydomain, which defaults to the parent domain of the machine name. For the sake of consistency between sender and recipient addresses, myorigin also specifies the domain name that is appended to an unqualified recipient address. Examples (specify only one of the following): /etc/postfix/main.cf: myorigin = $myhostname (default: send mail as "user@$myhostname") myorigin = $mydomain (probably desirable: "user@$mydomain") WWhhaatt ddoommaaiinnss ttoo rreecceeiivvee mmaaiill ffoorr The mydestination parameter specifies what domains this machine will deliver locally, instead of forwarding to another machine. The default is to receive mail for the machine itself. See the VIRTUAL_README file for how to configure Postfix for hosted domains. You can specify zero or more domain names, "/file/name" patterns and/or "type: table" lookup tables (such as hash:, btree:, nis:, ldap:, or mysql:), separated by whitespace and/or commas. A "/file/name" pattern is replaced by its contents; "type:table" requests that a table lookup is done and merely tests for existence: the lookup result is ignored. IMPORTANT: If your machine is a mail server for its entire domain, you must list $mydomain as well. Example 1: default setting. /etc/postfix/main.cf: mydestination = $myhostname localhost.$mydomain localhost Example 2: domain-wide mail server. /etc/postfix/main.cf: mydestination = $myhostname localhost.$mydomain localhost $mydomain Example 3: host with multiple DNS A records. /etc/postfix/main.cf: mydestination = $myhostname localhost.$mydomain localhost www.$mydomain ftp.$mydomain Caution: in order to avoid mail delivery loops, you must list all hostnames of the machine, including $myhostname, and localhost.$mydomain. WWhhaatt cclliieennttss ttoo rreellaayy mmaaiill ffrroomm By default, Postfix will forward mail from clients in authorized network blocks to any destination. Authorized networks are defined with the mynetworks configuration parameter. The default is to authorize all clients in the IP subnetworks that the local machine is attached to. IMPORTANT: If your machine is connected to a wide area network then your default mynetworks setting may be too friendly. Examples (specify only one of the following): /etc/postfix/main.cf: mynetworks_style = subnet (default: authorize subnetworks) mynetworks_style = host (safe: authorize local machine only) mynetworks = 127.0.0.0/8 (safe: authorize local machine only) mynetworks = 127.0.0.0/8 168.100.189.2/32 (authorize local machine) You can specify the trusted networks in the main.cf file, or you can let Postfix do the work for you. The default is to let Postfix do the work. The result depends on the mynetworks_style parameter value. * Specify "mynetworks_style = host" when Postfix should forward mail from only the local machine. * Specify "mynetworks_style = subnet" (the default) when Postfix should forward mail from SMTP clients in the same IP subnetworks as the local machine. On Linux, this works correctly only with interfaces specified with the "ifconfig" command. * Specify "mynetworks_style = class" when Postfix should forward mail from SMTP clients in the same IP class A/B/C networks as the local machine. Don't do this with a dialup site - it would cause Postfix to "trust" your entire provider's network. Instead, specify an explicit mynetworks list by hand, as described below. Alternatively, you can specify the mynetworks list by hand, in which case Postfix ignores the mynetworks_style setting. To specify the list of trusted networks by hand, specify network blocks in CIDR (network/mask) notation, for example: /etc/postfix/main.cf: mynetworks = 168.100.189.0/28, 127.0.0.0/8 You can also specify the absolute pathname of a pattern file instead of listing the patterns in the main.cf file. WWhhaatt ddeessttiinnaattiioonnss ttoo rreellaayy mmaaiill ttoo By default, Postfix will forward mail from strangers (clients outside authorized networks) to authorized remote destinations only. Authorized remote destinations are defined with the relay_domains configuration parameter. The default is to authorize all domains (and subdomains) of the domains listed with the mydestination parameter. Examples (specify only one of the following): /etc/postfix/main.cf: relay_domains = $mydestination (default) relay_domains = (safe: never forward mail from strangers) relay_domains = $mydomain (forward mail to my domain and subdomains) WWhhaatt ddeelliivveerryy mmeetthhoodd:: ddiirreecctt oorr iinnddiirreecctt By default, Postfix tries to deliver mail directly to the Internet. Depending on your local conditions this may not be possible or desirable. For example, your system may be turned off outside office hours, it may be behind a firewall, or it may be connected via a provider who does not allow direct mail to the Internet. In those cases you need to configure Postfix to deliver mail indirectly via a relay host. Examples (specify only one of the following): /etc/postfix/main.cf: relayhost = (default: direct delivery to Internet) relayhost = $mydomain (deliver via local mailhub) relayhost = [mail.$mydomain] (deliver via local mailhub) relayhost = [mail.isp.tld] (deliver via provider mailhub) The form enclosed with [] eliminates DNS MX lookups. Don't worry if you don't know what that means. Just be sure to specify the [] around the mailhub hostname that your ISP gave to you, otherwise mail may be mis-delivered. The STANDARD_CONFIGURATION_README file has more hints and tips for firewalled and/or dial-up networks. WWhhaatt ttrroouubbllee ttoo rreeppoorrtt ttoo tthhee ppoossttmmaasstteerr You should set up a postmaster alias in the aliases(5) table that directs mail to a human person. The postmaster address is required to exist, so that people can report mail delivery problems. While you're updating the aliases(5) table, be sure to direct mail for the super-user to a human person too. /etc/aliases: postmaster: you root: you Execute the command "newaliases" after changing the aliases file. Instead of / etc/aliases, your alias file may be located elsewhere. Use the command "postconf alias_maps" to find out. The Postfix system reports problems to the postmaster alias. You may not be interested in all types of trouble reports, so this reporting mechanism is configurable. The default is to report only serious problems (resource, software) to postmaster: Default setting: /etc/postfix/main.cf: notify_classes = resource, software The meaning of the classes is as follows: bounce Inform the postmaster of undeliverable mail. Either send the postmaster a copy of undeliverable mail that is returned to the sender, or send a transcript of the SMTP session when Postfix rejected mail. For privacy reasons, the postmaster copy of undeliverable mail is truncated after the original message headers. This implies "2bounce" (see below). See also the luser_relay feature. The notification is sent to the address specified with the bounce_notice_recipient configuration parameter (default: postmaster). 2bounce When Postfix is unable to return undeliverable mail to the sender, send it to the postmaster instead (without truncating the message after the primary headers). The notification is sent to the address specified with the 2bounce_notice_recipient configuration parameter (default: postmaster). delay Inform the postmaster of delayed mail. In this case, the postmaster receives message headers only. The notification is sent to the address specified with the delay_notice_recipient configuration parameter (default: postmaster). policy Inform the postmaster of client requests that were rejected because of (UCE) policy restrictions. The postmaster receives a transcript of the SMTP session. The notification is sent to the address specified with the error_notice_recipient configuration parameter (default: postmaster). protocol Inform the postmaster of protocol errors (client or server side) or attempts by a client to execute unimplemented commands. The postmaster receives a transcript of the SMTP session. The notification is sent to the address specified with the error_notice_recipient configuration parameter (default: postmaster). resource Inform the postmaster of mail not delivered due to resource problems (for example, queue file write errors). The notification is sent to the address specified with the error_notice_recipient configuration parameter (default: postmaster). software Inform the postmaster of mail not delivered due to software problems. The notification is sent to the address specified with the error_notice_recipient configuration parameter (default: postmaster). PPrrooxxyy//NNAATT eexxtteerrnnaall nneettwwoorrkk aaddddrreesssseess Some mail servers are connected to the Internet via a network address translator (NAT) or proxy. This means that systems on the Internet connect to the address of the NAT or proxy, instead of connecting to the network address of the mail server. The NAT or proxy forwards the connection to the network address of the mail server, but Postfix does not know this. If you run a Postfix server behind a proxy or NAT, you need to configure the proxy_interfaces parameter and specify all the external proxy or NAT addresses that Postfix receives mail on. You may specify symbolic hostnames instead of network addresses. IMPORTANT: You must specify your proxy/NAT external addresses when your system is a backup MX host for other domains, otherwise mail delivery loops will happen when the primary MX host is down. Example: host behind NAT box running a backup MX host. /etc/postfix/main.cf: proxy_interfaces = 1.2.3.4 (the proxy/NAT external network address) WWhhaatt yyoouu nneeeedd ttoo kknnooww aabboouutt PPoossttffiixx llooggggiinngg Postfix daemon processes run in the background, and log problems and normal activity to the syslog daemon. The syslogd process sorts events by class and severity, and appends them to logfiles. The logging classes, levels and logfile names are usually specified in /etc/syslog.conf. At the very least you need something like: /etc/syslog.conf: mail.err /dev/console mail.debug /var/log/maillog After changing the syslog.conf file, send a "HUP" signal to the syslogd process. IMPORTANT: many syslogd implementations will not create files. You must create files before (re)starting syslogd. IMPORTANT: on Linux you need to put a "-" character before the pathname, e.g., -/var/log/maillog, otherwise the syslogd process will use more system resources than Postfix. Hopefully, the number of problems will be small, but it is a good idea to run every night before the syslog files are rotated: # postfix check # egrep '(reject|warning|error|fatal|panic):' /some/log/file * The first line (postfix check) causes Postfix to report file permission/ ownership discrepancies. * The second line looks for problem reports from the mail software, and reports how effective the relay and junk mail access blocks are. This may produce a lot of output. You will want to apply some postprocessing to eliminate uninteresting information. The DEBUG_README document describes the meaning of the "warning" etc. labels in Postfix logging. RRuunnnniinngg PPoossttffiixx ddaaeemmoonn pprroocceesssseess cchhrrooootteedd Postfix daemon processes can be configured (via the master.cf file) to run in a chroot jail. The processes run at a fixed low privilege and with file system access limited to the Postfix queue directories (/var/spool/postfix). This provides a significant barrier against intrusion. The barrier is not impenetrable (chroot limits file system access only), but every little bit helps. With the exception of Postfix daemons that deliver mail locally and/or that execute non-Postfix commands, every Postfix daemon can run chrooted. Sites with high security requirements should consider to chroot all daemons that talk to the network: the smtp(8) and smtpd(8) processes, and perhaps also the lmtp(8) client. The author's own porcupine.org mail server runs all daemons chrooted that can be chrooted. The default /etc/postfix/master.cf file specifies that no Postfix daemon runs chrooted. In order to enable chroot operation, edit the file /etc/postfix/ master.cf, and follow instructions in the file. When you're finished, execute "postfix reload" to make the change effective. Note that a chrooted daemon resolves all filenames relative to the Postfix queue directory (/var/spool/postfix). For successful use of a chroot jail, most UNIX systems require you to bring in some files or device nodes. The examples/ chroot-setup directory in the source code distribution has a collection of scripts that help you set up Postfix chroot environments on different operating systems. Additionally, you almost certainly need to configure syslogd so that it listens on a socket inside the Postfix queue directory. Examples of syslogd command line options that achieve this for specific systems: FreeBSD: syslogd -l /var/spool/postfix/var/run/log Linux, OpenBSD: syslogd -a /var/spool/postfix/dev/log MMyy oowwnn hhoossttnnaammee The myhostname parameter specifies the fully-qualified domain name of the machine running the Postfix system. $myhostname appears as the default value in many other Postfix configuration parameters. By default, myhostname is set to the local machine name. If your local machine name is not in fully-qualified domain name form, or if you run Postfix on a virtual interface, you will have to specify the fully-qualified domain name that the mail system should use. Alternatively, if you specify mydomain in main.cf, then Postfix will use its value to generate a fully-qualified default value for the myhostname parameter. Examples (specify only one of the following): /etc/postfix/main.cf: myhostname = host.local.domain (machine name is not FQDN) myhostname = host.virtual.domain (virtual interface) myhostname = virtual.domain (virtual interface) MMyy oowwnn ddoommaaiinn nnaammee The mydomain parameter specifies the parent domain of $myhostname. By default, it is derived from $myhostname by stripping off the first part (unless the result would be a top-level domain). Conversely, if you specify mydomain in main.cf, then Postfix will use its value to generate a fully-qualified default value for the myhostname parameter. Examples (specify only one of the following): /etc/postfix/main.cf: mydomain = local.domain mydomain = virtual.domain (virtual interface) MMyy oowwnn nneettwwoorrkk aaddddrreesssseess The inet_interfaces parameter specifies all network interface addresses that the Postfix system should listen on; mail addressed to "user@[network address]" will be delivered locally, as if it is addressed to a domain listed in $mydestination. You can override the inet_interfaces setting in the Postfix master.cf file by prepending an IP address to a server name. The default is to listen on all active interfaces. If you run mailers on virtual interfaces, you will have to specify what interfaces to listen on. IMPORTANT: If you run MTAs on virtual interfaces you must specify explicit inet_interfaces values for the MTA that receives mail for the machine itself: this MTA should never listen on the virtual interfaces or you would have a mailer loop when a virtual MTA is down. Example: default setting. /etc/postfix/main.cf: inet_interfaces = all Example: host running one or more virtual mailers. For each Postfix instance, specify only one of the following. /etc/postfix/main.cf: inet_interfaces = virtual.host.tld (virtual Postfix) inet_interfaces = $myhostname localhost... (non-virtual Postfix) Note: you need to stop and start Postfix after changing this parameter. README_FILES/SMTPD_ACCESS_README000066600000036646150501202770011315 0ustar00PPoossttffiixx SSMMTTPP rreellaayy aanndd aacccceessss ccoonnttrrooll ------------------------------------------------------------------------------- IInnttrroodduuccttiioonn The Postfix SMTP server receives mail from the network and is exposed to the big bad world of junk email and viruses. This document introduces the built-in and external methods that control what SMTP mail Postfix will accept, what mistakes to avoid, and how to test your configuration. Topics covered in this document: * Relay control, junk mail control, and per-user policies * Restrictions that apply to all SMTP mail * Getting selective with SMTP access restriction lists * Delayed evaluation of SMTP access restriction lists * Dangerous use of smtpd_recipient_restrictions * SMTP access rule testing RReellaayy ccoonnttrrooll,, jjuunnkk mmaaiill ccoonnttrrooll,, aanndd ppeerr--uusseerr ppoolliicciieess In a distant past, the Internet was a friendly environment. Mail servers happily forwarded mail on behalf of anyone towards any destination. On today's Internet, spammers abuse servers that forward mail from arbitrary systems, and abused systems end up on anti-spammer blacklists. See, for example, the information on http://www.mail-abuse.org/ and other websites. By default, Postfix has a moderately restrictive approach to mail relaying. Postfix forwards mail only from clients in trusted networks, or to domains that are configured as authorized relay destinations. For a description of the default policy, see the smtpd_recipient_restrictions parameter in the postconf (5) manual page, and the information that is referenced from there. Most of the Postfix SMTP server access controls are targeted at stopping junk email. * Protocol oriented: some SMTP server access controls block mail by being very strict with respect to the SMTP protocol; these catch poorly implemented and/or poorly configured junk email software, as well as email worms that come with their own non-standard SMTP client implementations. Protocol-oriented access controls become less useful over time as spammers and worm writers learn to read RFC documents. * Blacklist oriented: some SMTP server access controls query blacklists with known to be bad sites such as open mail relays, open web proxies, and home computers that have been compromised and that are under remote control by criminals. The effectiveness of these blacklists depends on how complete and how up to date they are. * Threshold oriented: some SMTP server access controls attempt to raise the bar by either making the client do more work (greylisting) or by asking for a second opinion (SPF and sender/recipient address verification). The greylisting and SPF policies are implemented externally, and are the subject of the SMTPD_POLICY_README document. Sender/recipient address verification is the subject of the ADDRESS_VERIFICATION_README document. Unfortunately, all junk mail controls have the possibility of falsely rejecting legitimate mail. This can be a problem for sites with many different types of users. For some users it is unacceptable when any junk email slips through, while for other users the world comes to an end when a single legitimate email message is blocked. Because there is no single policy that is "right" for all users, Postfix supports different SMTP access restrictions for different users. This is described in the RESTRICTION_CLASS_README document. RReessttrriiccttiioonnss tthhaatt aappppllyy ttoo aallll SSMMTTPP mmaaiill Besides the restrictions that can be made configurable per client or per user as described in the next section, Postfix implements a few restrictions that apply to all SMTP mail. * The built-in header_checks and body_checks content restrictions, as described in the BUILTIN_FILTER_README document. This happens while Postfix receives mail, before it is stored in the incoming queue. * The external before-queue content restrictions, as described in the SMTPD_PROXY_README document. This happens while Postfix receives mail, before it is stored in the incoming queue. * Requiring that the client sends the HELO or EHLO command before sending the MAIL FROM or ETRN command. This may cause problems with home-grown applications that send mail. For this reason, the requirement is disabled by default ("smtpd_helo_required = no"). * Disallowing illegal syntax in MAIL FROM or RCPT TO commands. This may cause problems with home-grown applications that send mail, and with ancient PC mail clients. For this reason, the requirement is disabled by default ("strict_rfc821_envelopes = no"). o Disallowing RFC 822 address syntax (example: "MAIL FROM: the dude "). o Disallowing addresses that are not enclosed with <> (example: "MAIL FROM: dude@example.com"). * Rejecting mail from a non-existent sender address. This form of egress filtering helps to slow down worms and other malware, but may cause problems with home-grown software that sends out mail software with an unreplyable address. For this reason the requirement is disabled by default ("smtpd_reject_unlisted_sender = no"). * Rejecting mail for a non-existent recipient address. This form of ingress filtering helps to keep the mail queue free of undeliverable MAILER-DAEMON messages. This requirement is enabled by default ("smtpd_reject_unlisted_recipient = yes"). GGeettttiinngg sseelleeccttiivvee wwiitthh SSMMTTPP aacccceessss rreessttrriiccttiioonn lliissttss Postfix allows you to specify lists of access restrictions for each stage of the SMTP conversation. Individual restrictions are described in the postconf(5) manual page. Examples of simple restriction lists are: /etc/postfix/main.cf: # Allow connections from trusted networks only. smtpd_client_restrictions = permit_mynetworks, reject # Don't talk to mail systems that don't know their own hostname. # With Postfix < 2.3, specify reject_unknown_hostname. smtpd_helo_restrictions = reject_unknown_helo_hostname # Don't accept mail from domains that don't exist. smtpd_sender_restrictions = reject_unknown_sender_domain # Whitelisting: local clients may specify any destination domain. smtpd_recipient_restrictions = permit_mynetworks, reject_unauth_destination # Block clients that speak too early. smtpd_data_restrictions = reject_unauth_pipelining # Enforce mail volume quota via policy service callouts. smtpd_end_of_data_restrictions = check_policy_service unix:private/policy Each restriction list is evaluated from left to right until some restriction produces a result of PERMIT, REJECT or DEFER (try again later). The end of the list is equivalent to a PERMIT result. By placing a PERMIT restriction before a REJECT restriction you can make exceptions for specific clients or users. This is called whitelisting; the fourth example above allows mail from local networks but otherwise rejects mail to arbitrary destinations. The table below summarizes the purpose of each SMTP access restriction list. All lists use the exact same syntax; they differ only in the time of evaluation and in the effect of a REJECT or DEFER result. _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |RReessttrriiccttiioonn lliisstt nnaammee |SSttaattuuss |EEffffeecctt ooff RREEJJEECCTT oorr DDEEFFEERR rreessuulltt| |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |smtpd_client_restrictions |Optional|Reject all client commands | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |smtpd_helo_restrictions |Optional|Reject HELO/EHLO information | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |smtpd_sender_restrictions |Optional|Reject MAIL FROM information | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |smtpd_recipient_restrictions |Required|Reject RCPT TO information | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |smtpd_data_restrictions |Optional|Reject DATA command | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |smtpd_end_of_data_restrictions|Optional|Reject END-OF-DATA command | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |smtpd_etrn_restrictions |Optional|Reject ETRN command | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | DDeellaayyeedd eevvaalluuaattiioonn ooff SSMMTTPP aacccceessss rreessttrriiccttiioonn lliissttss Early Postfix versions evaluated SMTP access restrictions lists as early as possible. The client restriction list was evaluated before Postfix sent the "220 $myhostname..." greeting banner to the SMTP client, the helo restriction list was evaluated before Postfix replied to the HELO (EHLO) command, the sender restriction list was evaluated before Postfix replied to the MAIL FROM command, and so on. This approach turned out to be difficult to use. Current Postfix versions postpone the evaluation of client, helo and sender restriction lists until the RCPT TO or ETRN command. This behavior is controlled by the smtpd_delay_reject parameter. Restriction lists are still evaluated in the proper order of (client, helo, etrn) or (client, helo, sender, recipient, data, or end-of-data) restrictions. When a restriction list (example: client) evaluates to REJECT or DEFER the other restriction lists (example: helo, sender, etc.) are skipped. Around the time that smtpd_delay_reject was introduced, Postfix was also changed to support mixed restriction lists that combine information about the client, helo, sender and recipient or etrn command. Benefits of delayed restriction evaluation, and of restriction mixing: * Some SMTP clients do not expect a negative reply early in the SMTP session. When the bad news is postponed until the RCPT TO reply, the client goes away as it is supposed to, instead of hanging around until a timeout happens, or worse, going into an endless connect-reject-connect loop. * Postfix can log more useful information. For example, when Postfix rejects a client name or address and delays the action until the RCPT TO command, it can log the sender and the recipient address. This is more useful than logging only the client hostname and IP address and not knowing whose mail was being blocked. * Mixing is needed for complex whitelisting policies. For example, in order to reject local sender addresses in mail from non-local clients, you need to be able to mix restrictions on client information with restrictions on sender information in the same restriction list. Without this ability, many per-user access restrictions would be impossible to express. DDaannggeerroouuss uussee ooff ssmmttppdd__rreecciippiieenntt__rreessttrriiccttiioonnss By now the reader may wonder why we need smtpd client, helo or sender restrictions, when their evaluation is postponed until the RCPT TO or ETRN command. Some people recommend placing ALL the access restrictions in the smtpd_recipient_restrictions list. Unfortunately, this can result in too permissive access. How is this possible? The purpose of the smtpd_recipient_restrictions feature is to control how Postfix replies to the RCPT TO command. If the restriction list evaluates to REJECT or DEFER, the recipient address is rejected; no surprises here. If the result is PERMIT, then the recipient address is accepted. And this is where surprises can happen. Here is an example that shows when a PERMIT result can result in too much access permission: 1 /etc/postfix/main.cf: 2 smtpd_recipient_restrictions = 3 permit_mynetworks 4 check_helo_access hash:/etc/postfix/helo_access 5 reject_unknown_helo_hostname 6 reject_unauth_destination 7 8 /etc/postfix/helo_access: 9 localhost.localdomain PERMIT Line 5 rejects mail from hosts that don't specify a proper hostname in the HELO command (with Postfix < 2.3, specify reject_unknown_hostname). Lines 4 and 9 make an exception to allow mail from some machine that announces itself with "HELO localhost.localdomain". The problem with this configuration is that smtpd_recipient_restrictions evaluates to PERMIT for EVERY host that announces itself as "localhost.localdomain", making Postfix an open relay for all such hosts. In order to avoid surprises like these with smtpd_recipient_restrictions, you should place non-recipient restrictions AFTER the reject_unauth_destination restriction, not before. In the above example, the HELO based restrictions should be placed AFTER reject_unauth_destination, or better, the HELO based restrictions should be placed under smtpd_helo_restrictions where they can do no harm. SSMMTTPP aacccceessss rruullee tteessttiinngg Postfix has several features that aid in SMTP access rule testing: soft_bounce This is a safety net that changes SMTP server REJECT actions into DEFER (try again later) actions. This keeps mail queued that would otherwise be returned to the sender. Specify "soft_bounce = yes" in the main.cf file to prevent the Postfix SMTP server from rejecting mail permanently, by changing all 5xx SMTP reply codes into 4xx. warn_if_reject This is a different safety net that changes SMTP server REJECT actions into warnings. Instead of rejecting a command, Postfix logs what it would reject. Specify "warn_if_reject" in an SMTP access restriction list, before the restriction that you want to test without actually rejecting mail. XCLIENT With this Postfix 2.1 feature, authorized SMTP clients can impersonate other systems, so that you can do realistic SMTP access rule tests. Examples of how to impersonate other systems for access rule testing are given at the end of the XCLIENT_README document. README_FILES/SMTPD_POLICY_README000066600000046575150501202770011355 0ustar00PPoossttffiixx SSMMTTPP AAcccceessss PPoolliiccyy DDeelleeggaattiioonn ------------------------------------------------------------------------------- PPuurrppoossee ooff PPoossttffiixx SSMMTTPP aacccceessss ppoolliiccyy ddeelleeggaattiioonn The Postfix SMTP server has a number of built-in mechanisms to block or accept mail at specific SMTP protocol stages. As of version 2.1, Postfix can delegate policy decisions to an external server that runs outside Postfix. With this policy delegation mechanism, a simple greylist policy can be implemented with only a dozen lines of Perl, as is shown at the end of this document. A complete example can be found in the Postfix source code, in the directory examples/smtpd-policy. Another example of policy delegation is the SPF policy server at http:// www.openspf.org/Software. Policy delegation is now the preferred method for adding policies to Postfix. It's much easier to develop a new feature in few lines of Perl, Python, Ruby, or TCL, than trying to do the same in C code. The difference in performance will be unnoticeable except in the most demanding environments. On active systems a policy daemon process is used multiple times, for up to $max_use incoming SMTP connections. This document covers the following topics: * Policy protocol description * Policy client/server configuration * Example: greylist policy server * Greylisting mail from frequently forged domains * Greylisting all your mail * Routine greylist maintenance * Example Perl greylist server PPrroottooccooll ddeessccrriippttiioonn The Postfix policy delegation protocol is really simple. The client request is a sequence of name=value attributes separated by newline, and is terminated by an empty line. The server reply is one name=value attribute and it, too, is terminated by an empty line. Here is an example of all the attributes that the Postfix SMTP server sends in a delegated SMTPD access policy request: PPoossttffiixx vveerrssiioonn 22..11 aanndd llaatteerr:: request=smtpd_access_policy protocol_state=RCPT protocol_name=SMTP helo_name=some.domain.tld queue_id=8045F2AB23 sender=foo@bar.tld recipient=bar@foo.tld recipient_count=0 client_address=1.2.3.4 client_name=another.domain.tld reverse_client_name=another.domain.tld instance=123.456.7 PPoossttffiixx vveerrssiioonn 22..22 aanndd llaatteerr:: sasl_method=plain sasl_username=you sasl_sender= size=12345 ccert_subject=solaris9.porcupine.org ccert_issuer=Wietse+20Venema ccert_fingerprint=C2:9D:F4:87:71:73:73:D9:18:E7:C2:F3:C1:DA:6E:04 PPoossttffiixx vveerrssiioonn 22..33 aanndd llaatteerr:: encryption_protocol=TLSv1/SSLv3 encryption_cipher=DHE-RSA-AES256-SHA encryption_keysize=256 etrn_domain= PPoossttffiixx vveerrssiioonn 22..55 aanndd llaatteerr:: stress= [empty line] Notes: * The "request" attribute is required. In this example the request type is "smtpd_access_policy". * The order of the attributes does not matter. The policy server should ignore any attributes that it does not care about. * When the same attribute name is sent more than once, the server may keep the first value or the last attribute value. * When an attribute value is unavailable, the client either does not send the attribute, sends the attribute with an empty value ("name="), or sends a zero value ("name=0") in the case of a numerical attribute. * The "recipient" attribute is available in the "RCPT TO" stage. It is also available in the "DATA" and "END-OF-MESSAGE" stages if Postfix accepted only one recipient for the current message. * The "recipient_count" attribute (Postfix 2.3 and later) is non-zero only in the "DATA" and "END-OF-MESSAGE" stages. It specifies the number of recipients that Postfix accepted for the current message. * The client address is an IPv4 dotted quad in the form 1.2.3.4 or it is an IPv6 address in the form 1:2:3::4:5:6. * For a discussion of the differences between reverse and verified client_name information, see the reject_unknown_client_hostname discussion in the postconf(5) document. * An attribute name must not contain "=", null or newline, and an attribute value must not contain null or newline. * The "instance" attribute value can be used to correlate different requests regarding the same message delivery. These requests are sent over the same policy connection (unless the policy daemon terminates the connection). Once Postfix sends a query with a different instance attribute over that same policy connection, the previous message delivery is either completed or aborted. * The "size" attribute value specifies the message size that the client specified in the MAIL FROM command (zero if none was specified). With Postfix 2.2 and later, it specifies the actual message size when the client sends the END-OF-DATA command. * The "sasl_*" attributes (Postfix 2.2 and later) specify information about how the client was authenticated via SASL. These attributes are empty in case of no SASL authentication. * The "ccert_*" attributes (Postfix 2.2 and later) specify information about how the client was authenticated via TLS. These attributes are empty in case of no certificate authentication. As of Postfix 2.2.11 these attribute values are encoded as xtext: some characters are represented by +XX, where XX is the two-digit hexadecimal representation of the character value. With Postfix 2.6 and later, the decoded string is an UTF-8 string without non- printable ASCII characters. * The "encryption_*" attributes (Postfix 2.3 and later) specify information about how the connection is encrypted. With plaintext connections the protocol and cipher attributes are empty and the keysize is zero. * The "etrn_domain" attribute is defined only in the context of the ETRN command, and specifies the ETRN command parameter. * The "stress" attribute is either empty or "yes". See the STRESS_README document for further information. The following is specific to SMTPD delegated policy requests: * Protocol names are ESMTP or SMTP. * Protocol states are CONNECT, EHLO, HELO, MAIL, RCPT, DATA, END-OF-MESSAGE, VRFY or ETRN; these are the SMTP protocol states where the Postfix SMTP server makes an OK/REJECT/HOLD/etc. decision. The policy server replies with any action that is allowed in a Postfix SMTPD access(5) table. Example: action=defer_if_permit Service temporarily unavailable [empty line] This causes the Postfix SMTP server to reject the request with a 450 temporary error code and with text "Service temporarily unavailable", if the Postfix SMTP server finds no reason to reject the request permanently. In case of trouble the policy server must not send a reply. Instead the server must log a warning and disconnect. Postfix will retry the request at some later time. PPoolliiccyy cclliieenntt//sseerrvveerr ccoonnffiigguurraattiioonn The Postfix delegated policy client can connect to a TCP socket or to a UNIX- domain socket. Examples: inet:127.0.0.1:9998 unix:/some/where/policy unix:private/policy The first example specifies that the policy server listens on a TCP socket at 127.0.0.1 port 9998. The second example specifies an absolute pathname of a UNIX-domain socket. The third example specifies a pathname relative to the Postfix queue directory; use this for policy servers that are spawned by the Postfix master daemon. To create a policy service that listens on a UNIX-domain socket called "policy", and that runs under control of the Postfix spawn(8) daemon, you would use something like this: 1 /etc/postfix/master.cf: 2 policy unix - n n - 0 spawn 3 user=nobody argv=/some/where/policy-server 4 5 /etc/postfix/main.cf: 6 smtpd_recipient_restrictions = 7 ... 8 reject_unauth_destination 9 check_policy_service unix:private/policy 10 ... 11 policy_time_limit = 3600 NOTES: * Lines 2, 11: the Postfix spawn(8) daemon by default kills its child process after 1000 seconds. This is too short for a policy daemon that may need to run for as long as the SMTP server process that talks to it. The default time limit is overruled in main.cf with an explicit "policy_time_limit" setting. The name of the parameter is the name of the master.cf entry ("policy") concatenated with the "_time_limit" suffix. See spawn(8) for more information about the time limit parameter. * Line 2: specify a "0" process limit instead of the default "-", to avoid "connection refused" and other problems when the smtpd process limit exceeds the default_process_limit setting. * Lines 8, 9: always specify "check_policy_service" AFTER "reject_unauth_destination" or else your system could become an open relay. * Solaris UNIX-domain sockets do not work reliably. Use TCP sockets instead: 1 /etc/postfix/master.cf: 2 127.0.0.1:9998 inet n n n - 0 spawn 3 user=nobody argv=/some/where/policy-server 4 5 /etc/postfix/main.cf: 6 smtpd_recipient_restrictions = 7 ... 8 reject_unauth_destination 9 check_policy_service inet:127.0.0.1:9998 10 ... 11 127.0.0.1:9998_time_limit = 3600 Other configuration parameters that control the client side of the policy delegation protocol: * smtpd_policy_service_max_idle (default: 300s): The amount of time before the Postfix SMTP server closes an unused policy client connection. * smtpd_policy_service_max_ttl (default: 1000s): The amount of time before the Postfix SMTP server closes an active policy client connection. * smtpd_policy_service_timeout (default: 100s): The time limit to connect to, send to or receive from a policy server. EExxaammppllee:: ggrreeyylliisstt ppoolliiccyy sseerrvveerr Greylisting is a defense against junk email that is described at http:// www.greylisting.org/. The idea was discussed on the postfix-users mailing list one year before it was popularized. The file examples/smtpd-policy/greylist.pl in the Postfix source tree implements a simplified greylist policy server. This server stores a time stamp for every (client, sender, recipient) triple. By default, mail is not accepted until a time stamp is more than 60 seconds old. This stops junk mail with randomly selected sender addresses, and mail that is sent through randomly selected open proxies. It also stops junk mail from spammers that change their IP address frequently. Copy examples/smtpd-policy/greylist.pl to /usr/libexec/postfix or whatever location is appropriate for your system. In the greylist.pl Perl script you need to specify the location of the greylist database file, and how long mail will be delayed before it is accepted. The default settings are: $database_name="/var/mta/greylist.db"; $greylist_delay=60; The /var/mta directory (or whatever you choose) should be writable by "nobody", or by whatever username you configure below in master.cf for the policy service. Example: # mkdir /var/mta # chown nobody /var/mta Note: DO NOT create the greylist database in a world-writable directory such as /tmp or /var/tmp, and DO NOT create the greylist database in a file system that may run out of space. Postfix can survive "out of space" conditions with the mail queue and with the mailbox store, but it cannot survive a corrupted greylist database. If the file becomes corrupted you may not be able to receive mail at all until you delete the file by hand. The greylist.pl Perl script can be run under control by the Postfix master daemon. For example, to run the script as user "nobody", using a UNIX-domain socket that is accessible by Postfix processes only: 1 /etc/postfix/master.cf: 2 policy unix - n n - 0 spawn 3 user=nobody argv=/usr/bin/perl /usr/libexec/postfix/greylist.pl 4 5 /etc/postfix/main.cf: 6 policy_time_limit = 3600 Notes: * Line 3: Specify "greylist.pl -v" for verbose logging of each request and reply. * Lines 2, 6: the Postfix spawn(8) daemon by default kills its child process after 1000 seconds. This is too short for a policy daemon that may run for as long as an SMTP client is connected to an SMTP server process. The default time limit is overruled in main.cf with an explicit "policy_time_limit" setting. The name of the parameter is the name of the master.cf entry ("policy") concatenated with the "_time_limit" suffix. * Line 2: specify a "0" process limit instead of the default "-", to avoid "connection refused" and other problems when the smtpd process limit exceeds the default_process_limit setting. On Solaris you must use inet: style sockets instead of unix: style, as detailed in the "Policy client/server configuration" section above. 1 /etc/postfix/master.cf: 2 127.0.0.1:9998 inet n n n - 0 spawn 3 user=nobody argv=/usr/bin/perl /usr/libexec/postfix/greylist.pl 4 5 /etc/postfix/main.cf: 6 127.0.0.1:9998_time_limit = 3600 To invoke this service you would specify "check_policy_service inet:127.0.0.1: 9998". GGrreeyylliissttiinngg mmaaiill ffrroomm ffrreeqquueennttllyy ffoorrggeedd ddoommaaiinnss It is relatively safe to turn on greylisting for specific domains that often appear in forged email. At some point in cyberspace/time a list of frequently forged MAIL FROM domains could be found at http://www.monkeys.com/anti-spam/ filtering/sender-domain-validate.in. 1 /etc/postfix/main.cf: 2 smtpd_recipient_restrictions = 3 reject_unlisted_recipient 4 ... 5 reject_unauth_destination 6 check_sender_access hash:/etc/postfix/sender_access 7 ... 8 smtpd_restriction_classes = greylist 9 greylist = check_policy_service unix:private/policy 10 11 /etc/postfix/sender_access: 12 aol.com greylist 13 hotmail.com greylist 14 bigfoot.com greylist 15 ... etcetera ... NOTES: * Line 9: On Solaris you must use inet: style sockets instead of unix: style, as detailed in the "Example: greylist policy server" section above. * Line 6: Be sure to specify "check_sender_access" AFTER "reject_unauth_destination" or else your system could become an open mail relay. * Line 3: With Postfix 2.0 snapshot releases, "reject_unlisted_recipient" is called "check_recipient_maps". Postfix 2.1 understands both forms. * Line 3: The greylist database gets polluted quickly with bogus addresses. It helps if you protect greylist lookups with other restrictions that reject unknown senders and/or recipients. GGrreeyylliissttiinngg aallll yyoouurr mmaaiill If you turn on greylisting for all mail you will almost certainly want to make exceptions for mailing lists that use one-time sender addresses, because such mailing lists can pollute your greylist database relatively quickly. 1 /etc/postfix/main.cf: 2 smtpd_recipient_restrictions = 3 reject_unlisted_recipient 4 ... 5 reject_unauth_destination 6 check_sender_access hash:/etc/postfix/sender_access 7 check_policy_service unix:private/policy 8 ... 9 10 /etc/postfix/sender_access: 11 securityfocus.com OK 12 ... NOTES: * Line 7: On Solaris you must use inet: style sockets instead of unix: style, as detailed in the "Example: greylist policy server" section above. * Lines 6-7: Be sure to specify check_sender_access and check_policy_service AFTER reject_unauth_destination or else your system could become an open mail relay. * Line 3: The greylist database gets polluted quickly with bogus addresses. It helps if you precede greylist lookups with restrictions that reject unknown senders and/or recipients. RRoouuttiinnee ggrreeyylliisstt mmaaiinntteennaannccee The greylist database grows over time, because the greylist server never removes database entries. If left unattended, the greylist database will eventually run your file system out of space. When the status file size exceeds some threshold you can simply rename or remove the file without adverse effects; Postfix automatically creates a new file. In the worst case, new mail will be delayed by an hour or so. To lessen the impact, rename or remove the file in the middle of the night at the beginning of a weekend. EExxaammppllee PPeerrll ggrreeyylliisstt sseerrvveerr This is the Perl subroutine that implements the example greylist policy. It is part of a general purpose sample policy server that is distributed with the Postfix source as examples/smtpd-policy/greylist.pl. # # greylist status database and greylist time interval. DO NOT create the # greylist status database in a world-writable directory such as /tmp # or /var/tmp. DO NOT create the greylist database in a file system # that can run out of space. # $database_name="/var/mta/greylist.db"; $greylist_delay=60; # # Auto-whitelist threshold. Specify 0 to disable, or the number of # successful "come backs" after which a client is no longer subject # to greylisting. # $auto_whitelist_threshold = 10; # # Demo SMTPD access policy routine. The result is an action just like # it would be specified on the right-hand side of a Postfix access # table. Request attributes are available via the %attr hash. # sub smtpd_access_policy { my($key, $time_stamp, $now); # Open the database on the fly. open_database() unless $database_obj; # Search the auto-whitelist. if ($auto_whitelist_threshold > 0) { $count = read_database($attr{"client_address"}); if ($count > $auto_whitelist_threshold) { return "dunno"; } } # Lookup the time stamp for this client/sender/recipient. $key = lc $attr{"client_address"}."/".$attr{"sender"}."/".$attr{"recipient"}; $time_stamp = read_database($key); $now = time(); # If new request, add this client/sender/recipient to the database. if ($time_stamp == 0) { $time_stamp = $now; update_database($key, $time_stamp); } # The result can be any action that is allowed in a Postfix access(5) map. # # To label the mail, return ``PREPEND headername: headertext'' # # In case of success, return ``DUNNO'' instead of ``OK'', so that the # check_policy_service restriction can be followed by other restrictions. # # In case of failure, return ``DEFER_IF_PERMIT optional text...'', # so that mail can still be blocked by other access restrictions. # syslog $syslog_priority, "request age %d", $now - $time_stamp if $verbose; if ($now - $time_stamp > $greylist_delay) { # Update the auto-whitelist. if ($auto_whitelist_threshold > 0) { update_database($attr{"client_address"}, $count + 1); } return "dunno"; } else { return "defer_if_permit Service temporarily unavailable"; } } README_FILES/MILTER_README000066600000111142150501202770010362 0ustar00PPoossttffiixx bbeeffoorree--qquueeuuee MMiilltteerr ssuuppppoorrtt ------------------------------------------------------------------------------- IInnttrroodduuccttiioonn Postfix implements support for the Sendmail version 8 Milter (mail filter) protocol. This protocol is used by applications that run outside the MTA to inspect SMTP events (CONNECT, DISCONNECT), SMTP commands (HELO, MAIL FROM, etc.) as well as mail content (headers and body). All this happens before mail is queued. The reason for adding Milter support to Postfix is that there exists a large collection of applications, not only to block unwanted mail, but also to verify authenticity (examples: DomainKeys Identified Mail (DKIM), SenderID+SPF and DomainKeys) or to digitally sign mail (examples: DomainKeys Identified Mail (DKIM), DomainKeys). Having yet another Postfix-specific version of all that software is a poor use of human and system resources. The Milter protocol has evolved over time, and different Postfix versions implement different feature sets. See the workarounds and limitations sections at the end of this document for differences between Postfix and Sendmail implementations. This document provides information on the following topics: * How Milter applications plug into Postfix * Building Milter applications * Running Milter applications * Configuring Postfix * Workarounds * Limitations HHooww MMiilltteerr aapppplliiccaattiioonnss pplluugg iinnttoo PPoossttffiixx The Postfix Milter implementation uses two different lists of mail filters: one list of filters for SMTP mail only, and one list of filters for non-SMTP mail. The two lists have different capabilities, which is unfortunate. Avoiding this would require major restructuring of Postfix. * The SMTP-only filters handle mail that arrives via the Postfix smtpd(8) server. They are typically used to filter unwanted mail and to sign mail from authorized SMTP clients. You specify SMTP-only Milter applications with the smtpd_milters parameter as described in a later section. Mail that arrives via the Postfix smtpd(8) server is not filtered by the non-SMTP filters that are described next. * The non-SMTP filters handle mail that arrives via the Postfix sendmail(1) command-line or via the Postfix qmqpd(8) server. They are typically used to digitally sign mail only. Although non-SMTP filters can be used to filter unwanted mail, they have limitations compared to the SMTP-only filters. You specify non-SMTP Milter applications with the non_smtpd_milters parameter as described in a later section. For those who are familiar with the Postfix architecture, the figure below shows how Milter applications plug into Postfix. Names followed by a number are Postfix commands or server programs, while unnumbered names inside shaded areas represent Postfix queues. To avoid clutter, the path for local submission is simplified (the OVERVIEW document has a more complete description of the Postfix architecture). SMTP-only non-SMTP filters filters ^ | | v ^ | | | Network -> smtpd(8) | | | v \ Network -> qmqpd(8) -> cleanup(8) -> incoming / pickup(8) : Local -> sendmail(1) BBuuiillddiinngg MMiilltteerr aapppplliiccaattiioonnss Milter applications have been written in C, JAVA and Perl, but this document deals with C applications only. For these, you need an object library that implements the Sendmail 8 Milter protocol. Postfix currently does not provide such a library, but Sendmail does. * The first option is to use a pre-compiled library. Some systems install the Sendmail libmilter library by default. With other systems, libmilter may be provided by a package (called "sendmail-devel" on some Linux systems). Once libmilter is installed, applications such as dkim-milter and sid- milter build out of the box without requiring any tinkering: $ ggzzccaatt ddkkiimm--mmiilltteerr--xx..yy..zz..ttaarr..ggzz || ttaarr xxff -- $ ccdd ddkkiimm--mmiilltteerr--xx..yy..zz $ mmaakkee [...lots of output omitted...] * The other option is to build the libmilter library from Sendmail source code: $ ggzzccaatt sseennddmmaaiill--xx..yy..zz..ttaarr..ggzz || ttaarr xxff -- $ ccdd sseennddmmaaiill--xx..yy..zz//lliibbmmiilltteerr $ mmaakkee [...lots of output omitted...] After building your own libmilter library, follow the installation instructions in the Milter application source distribution to specify the location of the libmilter include files and object library. Typically, these settings are configured in a file named sid-filter/Makefile.m4 or similar: APPENDDEF(`confINCDIRS', `-I/some/where/sendmail-x.y.z/include') APPENDDEF(`confLIBDIRS', `-L/some/where/sendmail-x.y.z/obj.systemtype/ libmilter') Then build the Milter application. RRuunnnniinngg MMiilltteerr aapppplliiccaattiioonnss To run a Milter application, see the documentation of the filter for options. A typical command looks like this: # //ssoommee//wwhheerree//ddkkiimm--ffiilltteerr --uu uusseerriidd --pp iinneett::ppoorrttnnuummbbeerr@@llooccaallhhoosstt ......ootthheerr ooppttiioonnss...... Please specify a userid value that isn't used for other applications (not "postfix", not "www", etc.). CCoonnffiigguurriinngg PPoossttffiixx Like Sendmail, Postfix has a lot of configuration options that control how it talks to Milter applications. With the initial Postfix Milter protocol implementation, many options are global, that is, they apply to all Milter applications. Future Postfix versions may support per-Milter timeouts, per- Milter error handling, etc. Information in this section: * SMTP-Only Milter applications * Non-SMTP Milter applications * Milter error handling * Milter protocol version * Milter protocol timeouts * Sendmail macro emulation SSMMTTPP--OOnnllyy MMiilltteerr aapppplliiccaattiioonnss The SMTP-only Milter applications handle mail that arrives via the Postfix smtpd(8) server. They are typically used to filter unwanted mail, and to sign mail from authorized SMTP clients. Mail that arrives via the Postfix smtpd(8) server is not filtered by the non-SMTP filters that are described in the next section. NOTE: Do not use the header_checks(5) IGNORE action to remove Postfix's own Received: message header. This causes problems with mail signing filters. Instead, keep Postfix's own Received: message header and use the header_checks (5) REPLACE action to sanitize information. You specify SMTP-only Milter applications (there can be more than one) with the smtpd_milters parameter. Each Milter application is identified by the name of its listening socket; other Milter configuration options will be discussed in later sections. Milter applications are applied in the order as specified, and the first Milter application that rejects a command will override the responses from other Milter applications. /etc/postfix/main.cf: # Milters for mail that arrives via the smtpd(8) server. # See below for socket address syntax. smtpd_milters = inet:localhost:portnumber ...other filters... The general syntax for listening sockets is as follows: uunniixx::pathname Connect to the local UNIX-domain server that is bound to the specified pathname. If the smtpd(8) or cleanup(8) process runs chrooted, an absolute pathname is interpreted relative to the Postfix queue directory. iinneett::host::port Connect to the specified TCP port on the specified local or remote host. The host and port can be specified in numeric or symbolic form. NOTE: Postfix syntax differs from Milter syntax which has the form iinneett::port@@host. NNoonn--SSMMTTPP MMiilltteerr aapppplliiccaattiioonnss The non-SMTP Milter applications handle mail that arrives via the Postfix sendmail(1) command-line or via the Postfix qmqpd(8) server. They are typically used to digitally sign mail. Although non-SMTP filters can be used to filter unwanted mail, there are limitations as discussed later in this section. Mail that arrives via the Postfix smtpd(8) server is not filtered by the non-SMTP filters. NOTE: Do not use the header_checks(5) IGNORE action to remove Postfix's own Received: message header. This causes problems with mail signing filters. Instead, keep Postfix's own Received: message header and use the header_checks (5) REPLACE action to sanitize information. You specify non-SMTP Milter applications with the non_smtpd_milters parameter. This parameter uses the same syntax as the smtpd_milters parameter in the previous section. As with the SMTP-only filters, you can specify more than one Milter application; they are applied in the order as specified, and the first Milter application that rejects a command will override the responses from the other applications. /etc/postfix/main.cf: # Milters for non-SMTP mail. # See below for socket address syntax. non_smtpd_milters = inet:localhost:portnumber ...other filters... There's one small complication when using Milter applications for non-SMTP mail: there is no SMTP session. To keep Milter applications happy, the Postfix cleanup(8) server actually has to simulate the SMTP client CONNECT and DISCONNECT events, and the SMTP client EHLO, MAIL FROM, RCPT TO and DATA commands. * When new mail arrives via the sendmail(1) command line, the Postfix cleanup (8) server pretends that the mail arrives with ESMTP from "localhost" with IP address "127.0.0.1". The result is very similar to what happens with command line submissions in Sendmail version 8.12 and later, although Sendmail uses a different mechanism to achieve this result. * When new mail arrives via the qmqpd(8) server, the Postfix cleanup(8) server pretends that the mail arrives with ESMTP, and uses the QMQPD client hostname and IP address. * When old mail is re-injected into the queue with "postsuper -r", the Postfix cleanup(8) server uses the same client information that was used when the mail arrived as new mail. This generally works as expected, with only one exception: non-SMTP filters must not REJECT or TEMPFAIL simulated RCPT TO commands. When a non_smtpd_milters application REJECTs or TEMPFAILs a recipient, Postfix will report a configuration error, and mail will stay in the queue. None of this is a problem for mail filters that digitally sign mail. MMiilltteerr eerrrroorr hhaannddlliinngg The milter_default_action parameter specifies how Postfix handles Milter application errors. The default action is to respond with a temporary error status, so that the client will try again later. Specify "accept" if you want to receive mail as if the filter does not exist, and "reject" to reject mail with a permanent status. The "quarantine" action is like "accept" but freezes the message in the "hold" queue, and is available with Postfix 2.6 or later. /etc/postfix/main.cf: # What to do in case of errors? Specify accept, reject, tempfail, # or quarantine (Postfix 2.6 or later). milter_default_action = tempfail MMiilltteerr pprroottooccooll vveerrssiioonn As Postfix is not built with the Sendmail libmilter library, you may need to configure the Milter protocol version that Postfix should use. The default version is 6 (before Postfix 2.6 the default version is 2). /etc/postfix/main.cf: # Postfix >= 2.6 milter_protocol = 6 # 2.3 <= Postfix <= 2.5 milter_protocol = 2 If the Postfix milter_protocol setting specifies a too low version, the libmilter library will log an error message like this: application name: st_optionneg[xxxxx]: 0xyy does not fulfill action requirements 0xzz The remedy is to increase the Postfix milter_protocol version number. See, however, the limitations section below for features that aren't supported by Postfix. If the Postfix milter_protocol setting specifies a too high version, the libmilter library simply hangs up without logging a warning, and you see a Postfix warning message like one of the following: warning: milter inet:host:port: can't read packet header: Unknown error : 0 warning: milter inet:host:port: can't read packet header: Success warning: milter inet:host:port: can't read SMFIC_DATA reply packet header: No such file or directory The remedy is to lower the Postfix milter_protocol version number. MMiilltteerr pprroottooccooll ttiimmeeoouuttss Postfix uses different time limits at different Milter protocol stages. The table shows the timeout settings and the corresponding protocol stages (EOH = end of headers; EOM = end of message). _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |PPoossttffiixx ppaarraammeetteerr |TTiimmee lliimmiitt|MMiilltteerr pprroottooccooll ssttaaggee | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |milter_connect_timeout|30s |CONNECT | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |milter_command_timeout|30s |HELO, MAIL, RCPT, DATA, UNKNOWN| |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |milter_content_timeout|300s |HEADER, EOH, BODY, EOM | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | Beware: 30s may be too short for Milter applications that do lots of DNS lookups. However, if you increase the above timeouts too much, remote SMTP clients may hang up and mail may be delivered multiple times. This is an inherent problem with before-queue filtering. SSeennddmmaaiill mmaaccrroo eemmuullaattiioonn Postfix emulates a limited number of Sendmail macros, as shown in the table. Some macro values depend on whether a recipient is rejected (rejected recipients are available on request by the Milter application). Different macros are available at different Milter protocol stages (EOH = end-of-header, EOM = end-of-message); their availability is not always the same as in Sendmail. See the workarounds section below for solutions. _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |SSeennddmmaaiill mmaaccrroo |MMiilltteerr pprroottooccooll ssttaaggee |DDeessccrriippttiioonn | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |i |DATA, EOH, EOM |Queue ID, also Postfix | | | |queue file name | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |j |Always |Value of myhostname | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |_ |Always |The validated client name | | | |and address | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |{auth_authen} |MAIL, DATA, EOH, EOM |SASL login name | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |{auth_author} |MAIL, DATA, EOH, EOM |SASL sender | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |{auth_type} |MAIL, DATA, EOH, EOM |SASL login method | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |{client_addr} |Always |Client IP address | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |{client_connections}|CONNECT |Connection concurrency for| | | |this client | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | | |Client hostname | | | |When address -> name | |{client_name} |Always |lookup or name -> address | | | |verification fails: | | | |"unknown" | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |{client_port} |Always (Postfix >=2.5) |Client TCP port | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | | |Client name from address -| |{client_ptr} |CONNECT, HELO, MAIL, DATA|> name lookup | | | |When address -> name | | | |lookup fails: "unknown" | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |{cert_issuer} |HELO, MAIL, DATA, EOH, |TLS client certificate | | |EOM |issuer | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |{cert_subject} |HELO, MAIL, DATA, EOH, |TLS client certificate | | |EOM |subject | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |{cipher_bits} |HELO, MAIL, DATA, EOH, |TLS session key size | | |EOM | | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |{cipher} |HELO, MAIL, DATA, EOH, |TLS cipher | | |EOM | | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |{daemon_name} |Always |value of | | | |milter_macro_daemon_name | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |{mail_addr} |MAIL |Sender address | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |{mail_host} |MAIL (Postfix >= 2.6, |Sender next-hop | | |only with smtpd_milters) |destination | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |{mail_mailer} |MAIL (Postfix >= 2.6, |Sender mail delivery | | |only with smtpd_milters) |transport | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | | |Recipient address | |{rcpt_addr} |RCPT |With rejected recipient: | | | |descriptive text | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | | |Recipient next-hop | |{rcpt_host} |RCPT (Postfix >= 2.6, |destination | | |only with smtpd_milters) |With rejected recipient: | | | |enhanced status code | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | | |Recipient mail delivery | |{rcpt_mailer} |RCPT (Postfix >= 2.6, |transport | | |only with smtpd_milters) |With rejected recipient: | | | |"error" | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |{tls_version} |HELO, MAIL, DATA, EOH, |TLS protocol version | | |EOM | | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |v |Always |value of milter_macro_v | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | Postfix sends specific sets of macros at different Milter protocol stages. The sets are configured with the parameters as described in the table (EOH = end of headers; EOM = end of message). The protocol version is a number that Postfix sends at the beginning of the Milter protocol handshake. As of Sendmail 8.14.0, Milter applications can specify what macros they want to receive at different Milter protocol stages. An application-specified list takes precedence over a Postfix-specified list. _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |PPoossttffiixx ppaarraammeetteerr |MMiilltteerr pprroottooccooll|MMiilltteerr pprroottooccooll ssttaaggee| | |vveerrssiioonn | | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |milter_connect_macros |2 or higher |CONNECT | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |milter_helo_macros |2 or higher |HELO/EHLO | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |milter_mail_macros |2 or higher |MAIL FROM | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |milter_rcpt_macros |2 or higher |RCPT TO | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |milter_data_macros |4 or higher |DATA | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |milter_end_of_header_macros |6 or higher |EOH | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |milter_end_of_data_macros |2 or higher |EOM | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |milter_unknown_command_macros|3 or higher |unknown command | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | WWoorrkkaarroouunnddss * To avoid breaking DKIM etc. signatures with an SMTP-based content filter, update the before-filter SMTP client in master.cf, and add a line with "- o disable_mime_output_conversion=yes" (note: no spaces around the "="). For details, see the advanced content filter example. /etc/postfix/master.cf: # ============================================================= # service type private unpriv chroot wakeup maxproc command # (yes) (yes) (yes) (never) (100) # ============================================================= scan unix - - n - 10 smtp -o smtp_send_xforward_command=yes -o disable_mime_output_conversion=yes -o smtp_generic_maps= * Some Milter applications use the "{if_addr}" macro to recognize local mail; this macro does not exist in Postfix. Workaround: use the "{client_addr}" macro instead. * Some Milter applications log a warning that looks like this: sid-filter[36540]: WARNING: sendmail symbol 'i' not available And they may insert an ugly message header with "unknown-msgid" like this: X-SenderID: Sendmail Sender-ID Filter vx.y.z host.example.com The problem is that Milter applications expect that the queue ID is known before the MTA accepts the MAIL FROM (sender) command. Postfix does not choose a queue ID, which is used as the queue file name, until after it accepts the first valid RCPT TO (recipient) command. If you experience the ugly header problem, see if a recent version of the Milter application fixes it. For example, current versions of dkim-filter and dk-filter already have code that looks up the Postfix queue ID at a later protocol stage, and sid-filter version 1.0.0 no longer includes the queue ID in the message header. To fix the ugly message header, you will need to add code that looks up the Postfix queue ID at some later point im time. The example below adds the lookup after the end-of-message. o Edit the filter source file (typically named xxx-filter/xxx-filter.c or similar). o Look up the mlfi_eom() function and add code near the top shown as bboolldd text below: dfc = cc->cctx_msg; assert(dfc != NULL); //** DDeetteerrmmiinnee tthhee jjoobb IIDD ffoorr llooggggiinngg.. **// iiff ((ddffcc-->>mmccttxx__jjoobbiidd ==== 00 |||| ssttrrccmmpp((ddffcc-->>mmccttxx__jjoobbiidd,, JJOOBBIIDDUUNNKKNNOOWWNN)) ==== 00)) {{ cchhaarr **jjoobbiidd == ssmmffii__ggeettssyymmvvaall((ccttxx,, ""ii""));; iiff ((jjoobbiidd !!== 00)) ddffcc-->>mmccttxx__jjoobbiidd == jjoobbiidd;; }} NOTES: o Different mail filters use slightly different names for variables. If the above code does not compile, look elsewhere in the mail filter source file for code that looks up the "i" macro value, and copy that code. o This change fixes only the ugly message header, but not the WARNING message. Fortunately, many Milters log that message only once. LLiimmiittaattiioonnss This section lists limitations of the Postfix Milter implementation. Some limitations will be removed as the implementation is extended over time. Of course the usual limitations of before-queue filtering will always apply. See the CONTENT_INSPECTION_README document for a discussion. * The Milter protocol has evolved over time. Therefore, different Postfix versions implement different feature sets. _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |PPoossttffiixx|SSuuppppoorrtteedd MMiilltteerr rreeqquueessttss | |_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | 2.6 |All Milter requests of Sendmail 8.14.0 (see notes below). | |_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | |All Milter requests of Sendmail 8.14.0, except: | | |SMFIP_RCPT_REJ (report rejected recipients to the mail filter), | | 2.5 |SMFIR_CHGFROM (replace sender, with optional ESMTP parameters), | | |SMFIR_ADDRCPT_PAR (add recipient, with optional ESMTP | | |parameters). | |_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | 2.4 |All Milter requests of Sendmail 8.13.0. | |_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | 2.3 |All Milter requests of Sendmail 8.13.0, except: | | |SMFIR_REPLBODY (replace message body). | |_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | * For Milter applications that are written in C, you need to use the Sendmail libmilter library. * Postfix has TWO sets of mail filters: filters that are used for SMTP mail only (specified with the smtpd_milters parameter), and filters for non-SMTP mail (specified with the non_smtpd_milters parameter). The non-SMTP filters are primarily for local submissions. When mail is filtered by non_smtpd_milters, the Postfix cleanup(8) server has to simulate SMTP client requests. This works as expected, with only one exception: non_smtpd_milters must not REJECT or TEMPFAIL simulated RCPT TO commands. When this rule is violated, Postfix will report a configuration error, and mail will stay in the queue. * Postfix currently does not apply content filters to mail that is forwarded or aliased internally, or to mail that is generated internally such as bounces or Postmaster notifications. This may be a problem when you want to apply a signing Milter to such mail. * When you use the before-queue content filter for incoming SMTP mail (see SMTPD_PROXY_README), Milter applications have access only to the SMTP command information; they have no access to the message header or body, and cannot make modifications to the message or to the envelope. * Postfix 2.6 ignores the optional ESMTP parameters in requests to replace the sender (SMFIR_CHGFROM) or to append a recipient (SMFIR_ADDRCPT_PAR). Postfix logs a warning message when a Milter application supplies such ESMTP parameters: warning: queue-id: cleanup_chg_from: ignoring ESMTP arguments "whatever" warning: queue-id: cleanup_add_rcpt: ignoring ESMTP arguments "whatever" * Postfix 2.3 does not implement requests to replace the message body. Milter applications log a warning message when they need this unsupported operation: st_optionneg[134563840]: 0x3d does not fulfill action requirements 0x1e The solution is to use Postfix version 2.4 or later. * Most Milter configuration options are global. Future Postfix versions may support per-Milter timeouts, per-Milter error handling, etc. COMPATIBILITY000066600000005621150501202770006507 0ustar00.forward yes (empty files; can enable/disable mail to /file or |command) /usr/mail yes (compile time option) /usr/spool/mail yes (compile time option) /var/mail yes (compile time option) /var/spool/mail yes (compile time option) :include: yes (mail to /file and |command is off by default) address probing yes (optional persistent database) aliases yes (can enable/disable mail to /file or |command) bare newlines yes (but will send CRLF) blacklisting yes (client name/addr; helo hostname; mail from; rcpt to) connection caching yes (SMTP shared cache; LMTP shared cache) content filter yes (before and after queue, internal and external) db tables yes (compile time option) dbm tables yes (compile time option) delivered-to yes (configurable with prepend_delivered_header) dsn yes enhanced status codes yes errors-to: no (removed with Postfix 2.2) esmtp yes etrn support yes (per-destination log for authorized destinations only) fcntl locking yes (runtime configurable) flock locking yes (runtime configurable) genericstable yes (Postfix 2.2 generic(5) table) greylist yes (delegated policy script) home mailbox yes ident lookup no ipv6 yes (compatibility for ipv4-only systems) ldap tables yes (contributed) lmtp support yes (client only) luser relay yes m4 config no mail to command yes (configurable for .forward, aliases, :include:) mail to file yes (configurable for .forward, aliases, :include:) maildir yes (in home, system mailspool, /file/name/ alias) mailertable yes (it's called transport) mailq yes majordomo yes (edit approve script to delete /^delivered-to:/i) milter yes (except body replacement) mime yes (including 8bit to quoted-printable conversion) mysql tables yes (contributed) netinfo tables yes (contributed) newaliases yes (main alias database only) nis tables yes nis+ tables yes (contributed) no <> in smtp yes (most common address forms) pgsql tables yes (contributed) pipeline option yes (SMTP server and client; LMTP client) pop/imap no qmqp server yes (with verp support) rbl support yes return-receipt: no (use DSN NOTIFY=SUCCESS) rhsbl support yes sasl support yes (compile time option) sendmail -bt no sendmail -bv yes (sends delivery report via email) sendmail -q yes sendmail -qRxxx yes (for domains specified in fast_flush_domains) sendmail -qSxxx no sendmail -qtime ignored sendmail -v yes (sends delivery report via email) sendmail.cf no (uses table-driven address rewriting) size option yes, server and client smarthost yes (specify relayhost in main.cf) spf yes (delegated policy script) starttls yes (compile time option) tcp wrapper no (use built-in blacklist facility) user+extension yes (also: .forward+extension) user-extension yes (also: .forward-extension) user.lock yes (runtime configurable) uucp support yes (sends user@domain recipients) verp support yes (delimiters are configurable) virtual domains yes (via local delivery agent and via dedicated delivery agent) year 2000 safe yes TLS_ACKNOWLEDGEMENTS000066600000004413150501202770007550 0ustar00- Walcir Fontanini * tested on Solaris 2.5 and and reported missing "snprintf()" -> was fixed in pfixtls-0.1.2 * contributed the script to add fingerprints contributed/fp.csh - Matti Aarnio (www.zmailer.org) * updated pfixtls_dump to need fewer strcat and strcpy calls. - Cerebus * Missing variable initialization in client mode enable STARTTLS negotiation even when not wanted. -> fixed in pfixtls-0.2.8 - Bodo Moeller * The SSL connection was not shut down at the end of the session, because SSL_CTX_set_quiet_shutdown() was set. This however did not mean "do a quiet shutdown" but "do not shutdown SSL". -> fixed in pfixtls-0.3.3 - Jeff Johnson * noted that the patch code will not compile with SSL disabled anymore, because a ´#ifdef HAS_SSL #endif´ encapsulation was missing in smtp/smtp_connect.c. This must have been in since the very beginning of client mode support (0.2.x). -> fixed in 0.3.6 - Craig Sanders * noted that the Received: header does not contain sufficient information whether a client certificate was not requested or not presented. He also reminded me that the session cache must be cleared when experimenting with the setup and certificates, what is not explained in the documenation. -> fixed in 0.4.4 - Claus Assmann * pointed out that the Received: header logging about the TLS state violated RFC822. The TLS information must be in comment form "(info)". -> fixed in 0.6.3 - Wietse Venema * uncounted important suggestions to start the integration into the Postfix mainstream code. * code adjustments in the dict_*() database code to allow easier inclusion and use for session caching, and this is only the beginning :-) -> started reprogramming Postfix/TLS to fit both Wietse's and my requirements as of 0.6.0 - Damien Miller * Found mismatch between documentation and code with regard to logging. -> fixed in 0.6.6 - Deti Fliegl * Provided an initial patch to support SubjectAlternativeName/dNSName checks. -> added in 0.8.14