Поднимаем почтарь с балансировкой.
Добавлено: 01 ноя 2011, 15:54
Что у меня есть:
- 1. фаерволл (FreeBSD 7.4)
2. 2 сервака за ним (RHEL 6.1)
3. SAN под хранилищем всего юзерского файла (можно также юзать nfs, DRBD, fuse-sshfs)
4. руки средней кривости
5. мозги слегка побитые плесенью
Часть 1 - SMTP
В качестве smtp-сервера я выбрал Exim - имхо он полегче, пошустрее да и при больших нагрузках не проседает. Если кому-либо критично юзать postfix - это ваше право, но в этом случае можно пропустить эту часть и много чего из последующих. Если же кто-то решится поднять smtp на sendmail... сочувствую в общем. Данные о пользователях и пр. будем хранить в MySQL (конечно не самый лучший выбор по сравнению с PostgreSQL, но что остается делать если все "крутые" кодеры кроме него и MSSQL ничего более не знают?). MySQL у нас крутится пока на одном из хостов, этот хост также резольвится скажем как mysql.myhost.kg, MySQL прослушивает все интерфейсы на стандартном порту. Домены у нас myhost.kg и mail.myhost.kg.Итак, ставим все что нам нужно.
Код: Выделить всё
yum install mysql-server mysql-client clamav clamd exim exim-mysql
Код: Выделить всё
yum remove postfix
Переносим туда все с чем exim будет работать
Код: Выделить всё
export EXIM=/srv/data/mail
mkdir $EXIM/etc
mv /etc/exim/exim.conf $EXIM/etc
mkdir $EXIM/var
mkdir $EXIM/var/spool
mv /var/spool/exim $EXIM/var/spool/
mv /var/spool/mail $EXIM/var/spool/
ln -s $EXIM/var/spool/mail /var/spool/mail
ln -s $EXIM/var/spool/exim /var/spool/exim
Код: Выделить всё
export EXIM=/srv/data/mail
mkdir $EXIM/etc
rm -f /etc/exim/exim.conf
rm -rf /var/spool/exim
rm -rf /var/spool/mail
ln -s $EXIM/var/spool/mail /var/spool/mail
ln -s $EXIM/var/spool/exim /var/spool/exim
Код: Выделить всё
primary_hostname = mail.myhost.kg
domainlist local_domains = ${lookup mysql{SELECT domain FROM domains \
WHERE domain='${domain}' AND \
(type='LOCAL' OR type='VIRTUAL')}}
domainlist relay_to_domains = ${lookup mysql{SELECT domain FROM domains \
WHERE domain='${domain}' AND type='RELAY'}}
hostlist spamers = ${lookup mysql{SELECT senders FROM blacklist_host WHERE \
senders='${sender_host_address}'}}
hostlist relay_from_hosts = localhost : 127.0.0.1 : 192.168.50.0/24
GET_QUOTA=${lookup mysql{SELECT quota FROM users \
WHERE login='${local_part}' AND domain='${domain}'}{${value}M}}
MAILDIR_SIZE=${eval:${sg{${sg{${readfile{/srv/data/mail/var/spool/exim/$domain/$local_part/maildirsize}\
{\n}}}{\N^.+?\n\N}{}}}{\N(?s)\s+-?\d+\n\N}{+}}0+500K}
daemon_smtp_ports = 25 : 465
tls_on_connect_ports = 465
tls_advertise_hosts = *
tls_certificate = /etc/pki/tls/private/exim.pem
tls_privatekey = /etc/pki/tls/private/exim.pem
log_selector = \
+all_parents \
+lost_incoming_connection \
+received_sender \
+received_recipients \
+smtp_confirmation \
+smtp_syntax_error \
+smtp_connection \
+smtp_protocol_error \
-queue_run
syslog_timestamp = no
acl_smtp_rcpt = acl_check_rcpt
acl_smtp_data = acl_check_data
av_scanner = clamd:/var/run/clamav/clamd.sock
trusted_users = lighttpd
qualify_domain = myhost.kg
allow_domain_literals = false
exim_user = exim
exim_group = exim
never_users = bin
delay_warning = 4h:8h:24h:48h
return_size_limit = 50k
host_lookup = *
rfc1413_hosts = *
rfc1413_query_timeout = 0s
smtp_enforce_sync = true
syslog_duplication = false
allow_mx_to_ip
ignore_bounce_errors_after = 2d
timeout_frozen_after = 2d
message_size_limit = 200M
smtp_accept_max = 1000
smtp_accept_max_per_connection = 50
smtp_accept_max_per_host = 20
smtp_connect_backlog = 50
smtp_accept_queue_per_connection = 30
remote_max_parallel = 15
split_spool_directory = true
#Инклюдим файлик кодорый ДОЛЖЕН лежать не на хранилище, ибо у машин все же разные ипы.
.include /etc/exim/host.conf"
# Подключение к MySQL: хост/база_данных/пользователь/пароль
hide mysql_servers = mysql.myhost.kg/mail/exim/exim_password
begin acl
acl_check_rcpt:
deny message = "Illegal characters are in an address."
domains = +local_domains
local_parts = ^[.] : ^.*[@%!/|]
deny message = "Illegal characters are in an address."
domains = !+local_domains
local_parts = ^[./|] : ^.*[@%!] : ^.*/\\.\\./
deny message = "All email from *.orange.fr - discarded!"
condition = ${if match{$sender_helo_name}{.orange.fr}{yes}{no}}
deny message = "All email from *.mdp2.net - discarded!"
condition = ${if match{$sender_helo_name}{.mdp2.net}{yes}{no}}
deny message = "All email from *.mail.comcast.net - discarded!"
condition = ${if match{$sender_helo_name}{.mail.comcast.net}{yes}{no}}
deny message = "All email from *.libero.it - discarded!"
condition = ${if match{$sender_helo_name}{.libero.it}{yes}{no}}
deny message = "All email from *.ono.com - discarded!"
condition = ${if match{$sender_helo_name}{.ono.com}{yes}{no}}
deny message = "All email from *.wanadoo.fr - discarded!"
condition = ${if match{$sender_helo_name}{.wanadoo.fr}{yes}{no}}
accept senders=${lookup mysql{SELECT senders FROM whitelist \
WHERE senders='${quote_mysql:$sender_address}' \
OR senders='*@${quote_mysql:$sender_address_domain}' LIMIT 1}}
deny message = "Your address in banlist!"
senders=${lookup mysql{SELECT senders FROM blacklist \
WHERE senders='${quote_mysql:$sender_address}' \
OR senders='*@${quote_mysql:$sender_address_domain}' LIMIT 1}}
deny hosts = +spamers
message = "Host rejected by spamers list on rbl.ispalternativa.net.ua!"
accept authenticated = *
deny message = "HELO/EHLO required by SMTP RFC"
condition = ${if eq{$sender_helo_name}{}{yes}{no}}
deny condition = ${if match{$sender_helo_name}{\N^\d+$\N}{yes}{no}}
hosts = !127.0.0.1:!localhost:*
message = "There can not be only numbers in HELO!"
deny condition = ${if eq{$sender_address}{}{yes}{no}}
hosts = +relay_from_hosts
message = "Your message have not return address"
deny message = "The use of IP is forbidden in HELO!"
hosts = *:!+relay_from_hosts
condition = ${if eq{$sender_helo_name}\
{$sender_host_address}{true}{false}}
deny condition = ${if eq{$sender_helo_name}\
{$interface_address}{yes}{no}}
hosts = !127.0.0.1 : !localhost : *
message = "The use of my IP is forbidden!"
deny message = "Dynamic hosts is forbidden!"
condition = ${if match{$sender_host_name}\
{adsl|dialup|pool|peer|dhcp} {yes}{no}}
deny message = rejected because $sender_host_address \
is in a black list at $dnslist_domain\n$dnslist_text
hosts = !+relay_from_hosts
!authenticated = *
log_message = found in $dnslist_domain
dnslists = bl.spamcop.net : \
cbl.abuseat.org : \
dnsbl.njabl.org : \
sbl-xbl.spamhaus.org : \
pbl.spamhaus.org
drop message = Rejected - Sender Verify Failed
log_message = Rejected - Sender Verify Failed
hosts = *
!verify = sender/no_details/callout=2m,defer_ok
!condition = ${if eq{$sender_verify_failure}{}}
accept domains = +local_domains
endpass
message = $acl_verify_message
verify = recipient
accept domains = +relay_to_domains
endpass
message = "Unrouteable address!"
verify = recipient/callout=30s,defer_ok,use_postmaster
accept hosts = +relay_from_hosts
accept authenticated = *
deny message = relay not permitted
accept
acl_check_data:
deny message = This message contains a virus ($malware_name).
demime = *
malware = */defer_ok
accept
begin routers
dnslookup:
driver = dnslookup
domains = ! +local_domains
transport = remote_smtp
ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8
no_more
system_aliases:
driver = redirect
allow_fail
allow_defer
data = ${lookup mysql{SELECT recipients FROM aliases \
WHERE (local_part='${local_part}' AND domain='${domain}') \
OR (local_part='*' AND domain='$domain')ORDER BY local_part='*' \
LIMIT 1}}
userforward:
driver = redirect
check_local_user=false
file = /srv/data/mail/var/spool/exim/$domain/$local_part/forward
user = exim
group = exim
allow_filter
no_verify
no_expn
check_ancestor
file_transport = address_file
pipe_transport = address_pipe
reply_transport = address_reply
condition = ${if exists{/srv/data/mail/var/spool/exim/$domain/$local_part/forward}{yes}{no}}
virtual_user_quota_defer:
driver = redirect
domains = +local_domains
condition = ${if and{\
{exists{/srv/data/mail/var/spool/exim/$domain/$local_part}}\
{exists{/srv/data/mail/var/spool/exim/$domain/$local_part/maildirsize}}\
{>{GET_QUOTA}{0}}\
{>={MAILDIR_SIZE}{GET_QUOTA}}\
} }
data = :fail: Over quota!
verify_sender = false
allow_fail
virtual_localuser:
driver = accept
domains = ${lookup mysql{SELECT domain from domains \
WHERE domain='${domain}'}}
local_parts = ${lookup mysql{SELECT login from users \
WHERE login='${local_part}' AND domain='${domain}'}}
transport = local_delivery
cannot_route_message = Unknown user
begin transports
remote_smtp:
driver = smtp
local_delivery:
driver = appendfile
maildir_use_size_file
check_string = ""
create_directory
delivery_date_add
directory = ${lookup mysql{SELECT \
LOWER(CONCAT('/srv/data/mail/var/spool/exim/$domain/',login)) FROM users \
WHERE login='${local_part}' AND domain='${domain}';}}
directory_mode = 770
envelope_to_add
group = mail
maildir_format
maildir_tag = ,S=$message_size
message_prefix = ""
message_suffix = ""
mode = 0660
quota = ${lookup mysql{SELECT quota FROM users \
WHERE login='${local_part}' AND domain='${domain}'}{${value}M}}
quota_size_regex = S=(\d+)$
quota_warn_threshold = 80%
return_path_add
address_pipe:
driver = pipe
return_output
address_file:
driver = appendfile
delivery_date_add
envelope_to_add
return_path_add
address_reply:
driver = autoreply
null_transport:
driver = appendfile
file = /dev/null
begin retry
begin rewrite
begin authenticators
fixed_login:
driver = plaintext
public_name = LOGIN
server_prompts = Username:: : Password::
server_condition = "${if and { \
{!eq{$1}{}} \
{!eq{$2}{}} \
{crypteq{$2}{\\{crypt\\}${lookup mysql{SELECT \
password FROM users \
WHERE login='${local_part:$1}' \
AND domain='${domain:$1}' AND \
smtp_auth='1'}{$value}fail}}} \
} {yes}{no}}"
server_set_id = $1
fixed_plain:
driver = plaintext
public_name = PLAIN
server_prompts = :
server_condition = "${if and { \
{!eq{$2}{}} \
{!eq{$3}{}} \
{crypteq{$3}{\\{crypt\\}${lookup mysql{SELECT \
password FROM users \
WHERE login='${local_part:$2}' \
AND domain='${domain:$2}' AND \
smtp_auth='1'}{$value}fail}}} \
} {yes}{no}}"
server_set_id = $2
Код: Выделить всё
smtp_banner = "$primary_hostname ESMTP srv1.myhost.kg" # Внесем ясность
local_interfaces = 127.0.0.1 : 192.168.50.1 #192.168.50.3 соответственно для второй машины
Код: Выделить всё
mysqladmin password <пароль рута>
mysql -uroot -p<пароль рута>
mysql> CREATE DATABASE mail;
mysql> grant all on mail.* to 'exim'@'192.168.50.1' identified by 'exim_password';
mysql> grant all on mail.* to 'exim'@'192.168.50.3' identified by 'exim_password';
mysql> grant all on mail.* to 'exim'@'localhost' identified by 'exim_password';
Код: Выделить всё
wget http://muff.kiev.ua/files/exim.sql
Заливаем измененный дамп в муську:
Код: Выделить всё
mysql -u exim -pexim_password mail < exim.sql
Код: Выделить всё
mysql> use exim;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> INSERT INTO `mail`.`aliases` (`local_part`, `domain`, `recipients`) VALUES ('root', 'myhost.kg', 'raven@myhost.kg');
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO `mail`.`blacklist` (`senders`, `when_added`) VALUES ('helenaVIP@mail.ru', CURDATE());
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO `mail`.`blacklist_host` (`senders`, `when_add`) VALUES ('12.134.36.100', CURDATE());
Query OK, 1 row affected (0.01 sec)
mysql> INSERT INTO `mail`.`domains` (`domain`, `type`) VALUES ('myhost.kg', 'LOCAL');
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO `mail`.`users` (`login`, `name`, `password`, `uid`, `gid`, `domain`, `quota`, `status`, `smtp_auth`) VALUES ('raven', 'Raven. System administrator', ENCRYPT('password-here'), '26', '6', 'myhost.kg', '150', '1', '1');
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO `mail`.`users` (`login`, `name`, `password`, `uid`, `gid`, `domain`, `quota`, `status`, `smtp_auth`) VALUES ('test', 'Test User', ENCRYPT('password-here'), '27', '6', 'myhost.kg', '150', '1', '1');
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO `mail`.`whitelist` (`senders`) VALUES ('admin@sysadmins.el.kg');
Query OK, 1 row affected (0.00 sec)
Код: Выделить всё
scp /etc/pki/tls/private/exim.pem root@192.168.50.1:/etc/pki/tls/private/
root@192.168.50.1's password:
exim.pem 100% 1704 1.7KB/s 00:00
Код: Выделить всё
service clamd start
service exim start
chkconfig exim on
chkconfig clamd on
Код: Выделить всё
telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 mail.myhost.kg ESMTP srv1.myhost.kg
ehlo mail.myhost.kg
250-mail.myhost.kg Hello mail.myhost.kg [127.0.0.1]
250-SIZE 209715200
250-PIPELINING
250-AUTH LOGIN PLAIN
250-STARTTLS
250 HELP
mail from: root@myhost.kg
250 OK
rcpt to: test@myhost.kg
250 Accepted
data
354 Enter message, ending with "." on a line by itself
raven send test message
.
250 OK id=1RL9wZ-0004CM-10
quit
221 mail.myhost.kg closing connection
Connection closed by foreign host.