An Example of Postfix Mail System on Ubuntu Server 9.10
Once time I had to make a corporate mail system with some special requirements.
- copying of all sended messages to the special e-mail folder
- restriction of multi-volume archives
- flexible message size restrictions
At first I made it on Exim, but there was a big problem - It hasn't the Delivery Status Notification function.
I tryed to fix it by unoffical patch (http://sourceforge.net/projects/eximdsn/) but it didn't help me.
So I decided to make the next system:
Ubuntu Server 9.10
MTA - Postix
Database - MySQL
POP3/IMAP server - Dovecot
Antivirus - ClamAV
Antispam - Spamassassin, Razor, Pyzor
Web Interface - Postfixadmin
Restrictions - Apolicy
Install Ubuntu with LAMP, DNS and OpenSSH, than update it and install all required software.
# aptitude update
# aptitude upgrade
# aptitude install mc htop dovecot-postfix postfix-mysql amavisd-new clamav razor pyzor spamassassin
Configure Dovecot:
# nano /etc/dovecot/dovecot-postfix.conf
base_dir = /var/run/dovecot/
protocols = imap pop3
listen = *
disable_plaintext_auth = no
shutdown_clients = yes
log_path = /var/log/dovecot.log
info_log_path = /var/log/dovecot.log
log_timestamp = "%Y-%m-%d %H:%M:%S "
login_dir = /var/run/dovecot/login
login_chroot = yes
login_user = dovecot
login_process_size = 64
login_process_per_connection = yes
login_processes_count = 3
login_max_processes_count = 128
login_max_connections = 256
login_greeting = Hell-o!.
login_log_format_elements = user=<%u> method=%m rip=%r lip=%l %c
login_log_format = %$: %s
mail_location = maildir:/var/mail/%d/%n
mail_privileged_group = mail
mail_access_groups = mail
first_valid_uid = 7
first_valid_gid = 7
protocol imap {
imap_client_workarounds = delay-newmail outlook-idle netscape-eoh tb-extra-mailbox-sep
}
protocol pop3 {
pop3_uidl_format = %08Xu%08Xv
pop3_client_workarounds = outlook-no-nuls oe-ns-eoh
}
protocol managesieve {
sieve=~/.dovecot.sieve
sieve_storage=~/sieve
}
protocol lda {
postmaster_address = admin@domain.ru
mail_plugin_dir = /usr/lib/dovecot/modules/lda
auth_socket_path = /var/run/dovecot/auth-master
}
auth default {
mechanisms = plain login cram-md5
passdb sql {
args = /etc/dovecot/dovecot-sql.conf
}
userdb passwd {
}
userdb sql {
args = /etc/dovecot/dovecot-sql.conf
}
socket listen {
master {
path = /var/run/dovecot/auth-master
mode = 0660
user = dovecot
group = mail
}
client {
path = /var/run/dovecot/auth-client
mode = 0660
user = postfix
group = postfix
}
}
}
# nano /etc/dovecot/dovecot-sql.conf
driver = mysql
connect = host=localhost dbname=mail user=mail password=password
default_pass_scheme = MD5
password_query = SELECT `username` as `user`, `password` FROM `mailbox` WHERE `username` = '%n@%d' AND `active`='1'
user_query = SELECT `maildir` AS `home`, 8 AS `uid`, 8 AS `gid` FROM `mailbox` WHERE `username` = '%n@%d' AND `active`='1'
Configure Postfix:
# nano /etc/postfix/main.cf
biff = no
append_dot_mydomain = no
readme_directory = no
alias_database = hash:/etc/aliases
alias_maps = hash:/etc/aliases
# Virtual mailbox settings
virtual_mailbox_base = /var/mail
virtual_mailbox_domains = proxy:mysql:/etc/postfix/mysql_virtual_domains_maps.cf
virtual_mailbox_maps = proxy:mysql:/etc/postfix/mysql_virtual_mailbox_maps.cf
virtual_alias_maps = proxy:mysql:/etc/postfix/mysql_virtual_alias_maps.cf
virtual_mailbox_limit_maps = proxy:mysql:/etc/postfix/mysql_virtual_mailbox_limit_maps.cf
# Network settings
mydomain = domain.ru
myhostname = mail.domain.ru
myorigin = $mydomain
#mydestination = $myhostname, localhost, localhost.$myhostname, localhost.$mydomain, $mydomain, 063.su, furgonz.ru, domain.net
mydestination = $myhostname, localhost, localhost.$myhostname, localhost.$mydomain
mynetworks = 127.0.0.0/8, 192.168.0.0/16
smtp_helo_name=$myhostname
smtpd_banner = $myhostname ESMTP Mail Server
inet_protocols = ipv4
inet_interfaces = all
# Dovecot transport
mailbox_transport = dovecot
mailbox_command = /usr/lib/dovecot/deliver
dovecot_destination_recipient_limit = 1
virtual_transport = dovecot
# Mailbox settings
mailbox_size_limit = 1024000000
message_size_limit = 10240000
virtual_mailbox_base = /var/mail
recipient_delimiter = +
# Restrictions
smtpd_client_restrictions = permit_mynetworks,
check_client_access mysql:/etc/postfix/mysql_virtual_alias_maps.cf,
reject_unknown_client_hostname,
reject_unauth_pipelining
smtpd_recipient_restrictions = check_policy_service inet:127.0.0.1:10001,
permit_mynetworks,
reject_unauth_destination,
reject_invalid_hostname,
reject_non_fqdn_hostname,
reject_non_fqdn_sender,
reject_non_fqdn_recipient,
reject_unknown_sender_domain,
reject_unknown_recipient_domain,
reject_unauth_pipelining,
permit_auth_destination,
reject_unlisted_recipient,
reject_unauth_destination,
reject_rbl_client opm.blitzed.org,
reject_rbl_client list.dsbl.org,
reject_rbl_client zen.spamhaus.org,
reject_rbl_client dul.dnsbl.sorbs.net,
reject_rbl_client dnsbl.njabl.org,
reject_rbl_client dynablock.njabl.org,
reject_rbl_client bl.spamcop.net,
reject_rbl_client bl.csma.biz,
reject_rbl_client dnsbl.sorbs.net,
reject_rbl_client smtp.dnsbl.sorbs.net,
reject_rbl_client combined.njabl.org,
reject_rbl_client rbl.majordomo.ru,
smtpd_sender_restrictions = check_policy_service inet:127.0.0.1:10001,
permit_mynetworks,
check_sender_access hash:/etc/postfix/sender_access,
reject_unknown_sender_domain,
reject_unlisted_sender,
reject_non_fqdn_sender
smtpd_helo_restrictions = permit_mynetworks,
check_helo_access hash:/etc/postfix/helo_access,
reject_invalid_helo_hostname,
reject_unknown_helo_hostname,
reject_non_fqdn_helo_hostname
smtpd_data_restrictions = permit_mynetworks,
reject_multi_recipient_bounce,
reject_unauth_pipelining
smtpd_etrn_restrictions = permit_mynetworks,reject
header_checks = regexp:/etc/postfix/header_checks
sender_bcc_maps = hash:/etc/postfix/sender_bcc_maps
#recipient_bcc_maps = hash:/etc/postfix/recipient_bcc_maps
strict_rfc821_envelopes = yes
smtpd_reject_unlisted_sender = yes
smtpd_reject_unlisted_recipient=yes
disable_vrfy_command = yes
show_user_unknown_table_name = no
smtpd_helo_required = yes
smtp_always_send_ehlo = yes
smtp_never_send_ehlo=no
smtpd_delay_reject=no
address_verify_sender= <>
address_verify_negative_cache=yes
address_verify_poll_count=1
address_verify_positive_expire_time=31d
address_verify_positive_refresh_time=7d
address_verife_negative_expire_time=3d
address_verify_negative_refresh_time=3h
allow_untrusted_routing=no
resolve_null_domain=no
resolve_numeric_domain=no
smtpd_recipient_limit=100
smtp_quote_rfc821_envelope=yes
smtpd_soft_error_limit = 2
smtpd_error_sleep_time = ${stress?0}${stress:10s}
smtpd_hard_error_limit = ${stress?3}${stress:20}
smtpd_timeout = ${stress?30}${stress:300}
# Timeouts RFC 2821
smtpd_timeout=5m
smtpd_starttls_timeout=5m
smtp_mail_timeout=5m
smtp_rcpt_timeout=5m
smtp_data_init_timeout=2m
smtp_data_xfer_timeout=3m
smtp_data_done_timeout=10m
maximal_queue_lifetime=4d
bounce_queue_lifetime=4d
queue_run_delay=30m
minimal_backoff_time=3h
maximal_backoff_time=5h
# Amavis
content_filter = smtp-amavis:[127.0.0.1]:10024
/etc/postfix/master.cf
#
# Postfix master process configuration file. For details on the format
# of the file, see the master(5) manual page (command: "man 5 master").
#
# Do not forget to execute "postfix reload" after editing this file.
#
# ==========================================================================
# service type private unpriv chroot wakeup maxproc command + args
# (yes) (yes) (yes) (never) (100)
# ==========================================================================
smtp inet n - n - - smtpd
#submission inet n - - - - smtpd
# -o smtpd_tls_security_level=encrypt
# -o smtpd_sasl_auth_enable=yes
# -o smtpd_client_restrictions=permit_sasl_authenticated,reject
# -o milter_macro_daemon_name=ORIGINATING
#smtps inet n - - - - smtpd
# -o smtpd_tls_wrappermode=yes
# -o smtpd_sasl_auth_enable=yes
# -o smtpd_client_restrictions=permit_sasl_authenticated,reject
# -o milter_macro_daemon_name=ORIGINATING
#628 inet n - - - - qmqpd
pickup fifo n - - 60 1 pickup
cleanup unix n - - - 0 cleanup
qmgr fifo n - n 300 1 qmgr
#qmgr fifo n - - 300 1 oqmgr
tlsmgr unix - - - 1000? 1 tlsmgr
rewrite unix - - - - - trivial-rewrite
bounce unix - - - - 0 bounce
defer unix - - - - 0 bounce
trace unix - - - - 0 bounce
verify unix - - - - 1 verify
flush unix n - - 1000? 0 flush
proxymap unix - - n - - proxymap
proxywrite unix - - n - 1 proxymap
smtp unix - - - - - smtp
# When relaying mail as backup MX, disable fallback_relay to avoid MX loops
relay unix - - - - - smtp
-o smtp_fallback_relay=
# -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
showq unix n - - - - showq
error unix - - - - - error
retry unix - - - - - error
discard unix - - - - - discard
local unix - n n - - local
virtual unix - n n - - virtual
lmtp unix - - - - - lmtp
anvil unix - - - - 1 anvil
scache unix - - - - 1 scache
#
# ====================================================================
# Interfaces to non-Postfix software. Be sure to examine the manual
# pages of the non-Postfix software to find out what options it wants.
#
# Many of the following services use the Postfix pipe(8) delivery
# agent. See the pipe(8) man page for information about ${recipient}
# and other message envelope options.
# ====================================================================
#
# maildrop. See the Postfix MAILDROP_README file for details.
# Also specify in main.cf: maildrop_destination_recipient_limit=1
#
maildrop unix - n n - - pipe
flags=DRhu user=vmail argv=/usr/bin/maildrop -d ${recipient}
#
# See the Postfix UUCP_README file for configuration details.
#
uucp unix - n n - - pipe
flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)
#
# Other external delivery methods.
#
ifmail unix - n n - - pipe
flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient)
bsmtp unix - n n - - pipe
flags=Fq. user=bsmtp argv=/usr/lib/bsmtp/bsmtp -t$nexthop -f$sender $recipient
scalemail-backend unix - n n - 2 pipe
flags=R user=scalemail argv=/usr/lib/scalemail/bin/scalemail-store ${nexthop} ${user} ${extension}
mailman unix - n n - - pipe
flags=FR user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py
${nexthop} ${user}
# delivery through dovecot
dovecot unix - n n - - pipe
flags=DRhu user=mail:mail argv=/usr/lib/dovecot/deliver -d $(recipient)
# Amavis -o receive_override_options=no_header_body_checks,no_unknown_recipient_checks
smtp-amavis unix - - - - 2 smtp
-o smtp_data_done_timeout=1200
-o smtp_send_xforward_command=yes
-o disable_dns_lookups=yes
-o max_use=20
127.0.0.1:10025 inet n - - - - smtpd
-o content_filter=
-o local_recipient_maps=
-o relay_recipient_maps=
-o smtpd_restriction_classes=
-o smtpd_delay_reject=no
-o smtpd_client_restrictions=permit_mynetworks,reject
-o smtpd_helo_restrictions=
-o smtpd_sender_restrictions=
-o smtpd_recipient_restrictions=permit_mynetworks,reject
-o smtpd_data_restrictions=reject_unauth_pipelining
-o smtpd_end_of_data_restrictions=
-o mynetworks=127.0.0.0/8
-o smtpd_error_sleep_time=0
-o smtpd_soft_error_limit=1001
-o smtpd_hard_error_limit=1000
-o smtpd_client_connection_count_limit=0
-o smtpd_client_connection_rate_limit=0
-o receive_override_options=no_header_body_checks,no_unknown_recipient_checks
Main files and their functions:
Restrict file extensions.
# nano /etc/postfix/header_checks
/^(.*)name=\"(.*)\.(exe|bat|cmd|mp3|avi|asf|mov|part1)\"$/ REJECT Attachment type not allowed. File "$2" has unacceptable extension: "$3"
Don't use our server name.
# nano /etc/postfix/helo_access
mail.domain.ru REJECT Don't use my server name!
Copy messages to defined e-mail folder
# nano /etc/postfix/recipient_bcc_maps
@domain1.ru audit@domain.ru
@domain2.ru audit@domain.ru
# nano /etc/postfix/sender_bcc_maps
@domain1.ru audit@domain.ru
@domain2.ru audit@domain.ru
Black and White sender lists.
# nano /etc/postfix/sender_access
@superjob.ru OK
@spammer.ru REJECT
Don't forget to do this for every file:
# postmap /etc/postfix/header_checks
MySQL files:
# nano /etc/postfix/mysql_virtual_alias_maps.cf
user = mail
password = password
hosts = localhost
dbname = mail
table = alias
select_field = goto
where_field = address
additional_conditions = and active = '1'
query = SELECT goto FROM alias WHERE address='%s' AND active = '1'
# nano /etc/postfix/mysql_virtual_domains_maps.cf
user = mail
password = password
hosts = localhost
dbname = mail
table = domain
select_field = domain
where_field = domain
additional_conditions = and backupmx = '0' and active = '1'
query = SELECT domain FROM domain WHERE domain='%s' AND backupmx = '0' AND active = '1'
# nano /etc/postfix/mysql_virtual_mailbox_limit_maps.cf
user = mail
password = password
hosts = localhost
dbname = mail
table = mailbox
select_field = quota
where_field = username
additional_conditions = and active = '1'
query = SELECT quota FROM mailbox WHERE username='%s' AND active = '1'
# nano /etc/postfix/mysql_virtual_mailbox_maps.cf
user = mail
password = password
hosts = localhost
dbname = mail
table = mailbox
select_field = CONCAT(domain,'/',maildir)
where_field = username
additional_conditions = and active = '1'
query = SELECT CONCAT(domain,'/',maildir) FROM mailbox WHERE username='%s' AND active = '1'
Configure Amavis:
# nano /etc/amavis/conf.d/15-content_filter_mode
use strict;
@bypass_virus_checks_maps = (
\%bypass_virus_checks, \@bypass_virus_checks_acl, \$bypass_virus_checks_re);
@bypass_spam_checks_maps = (
\%bypass_spam_checks, \@bypass_spam_checks_acl, \$bypass_spam_checks_re);
1; # ensure a defined return
nano /etc/amavis/conf.d/20-debian_defaults
$final_spam_destiny D_DISCARD;
/etc/spamassassin/local.cf
rewrite_header Subject *****SPAM*****
report_safe 1
trusted_networks 192.168.
required_score 5.0
use_bayes 1
bayes_auto_learn 1
bayes_ignore_header X-Bogosity
bayes_ignore_header X-Spam-Flag
bayes_ignore_header X-Spam-Status
skip_rbl_checks 0
use_razor2 1
use_pyzor 1
dns_available yes
## Optional Score Increases
score SPF_FAIL 10.000
score SPF_HELO_FAIL 10.000
score RAZOR2_CHECK 2.500
score PYZOR_CHECK 2.500
score BAYES_99 4.300
score BAYES_95 3.500
score BAYES_80 3.000
whitelist_from @host.superjob.ru
Change permissions:
# chmod -R 770 /var/mail
# chmod u+s /usr/lib/dovecot/deliver
# chmod -R 777 /var/lib/amavis/tmp
# usermod -a -G amavis mail
# usermod -a -G amavis dovecot
# usermod -a -G amavis clamav
# usermod -a -G amavis postfix
# usermod -a -G clamav dovecot
# usermod -a -G dovecot amavis
Make a base:
# mysql -p
mysql> create database mail;
mysql> grant all on mail.* to mail identified by 'password';
mysql> bye
Download Postfixadmin from there: http://sourceforge.net/projects/postfixadmin/
Unpack files into /var/www/, restart Apache, edit config.inc.php and go to http://your-ip/setup.php.
Download Apolicy: http://download.gna.org/apolicy/apolicy-0.73.tar.gz
Unpack files into /usr/src/ and install it:
# aptitude install python-ipy python-dns python-twisted-core python-twisted-bin python-spf
# cd /usr/src/apolicy-0.73
# python setup.py install
# cp ./debian/apolicy.init /etc/init.d/apolicy
# update-rc.d apolicy defaults
# /etc/init.d/apolicy start
Fix errors:
# mkdir /usr/lib/python2.6/dist-packages/apolicy
# cp /usr/src/apolicy-0.73/build/lib.linux-x86_64-2.6/apolicy/* /usr/lib/python2.6/dist-packages/apolicy
Check installation:
# /etc/init.d/apolicy start
# /etc/init.d/apolicy restart
# lsof -i | grep twistd
Configure Apolicy:
# nano /etc/apolicy/policy.conf
acl local_domains sender @domain.ru
acl local_domains sender @domain2.ru
acl privileged_users sender admin@domain.ru
acl privileged_users sender office@domain.ru
acl 1mb size 1024000
action deny_max_1mb REJECT Sorry, but You can't sent more than 1mb
access local_domains !privileged_users 1mb deny_max_1mb
Check our mail system:
# telnet localhost 110
Trying ::1...
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
+OK Hell-o!.
# telnet localhost 25
Trying ::1...
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 mail.domain.ru ESMTP Mail Server
If something isn't working - check the logs, there are a lot of interesting!
