Почтовая система на базе MTA exim Всеволод Стахов ln -sf /usr/local/sbin/exim /usr/libexec/sendmail databases/pogstgresql7 mail/exim make WITH_PGSQL=yo mail/p5-Mail-SpamAssassin security/clamav mail/courier-imap make WITH_CRAM=yo WITH_POSTGRESQL=yo mail/squirrelmail # passwd pgsql # su pgsql % psql CREATE DATABASE users; \c users CREATE TABLE accounts ( uid serial NOT NULL, login character varying(128), "password" character varying(128), maildir character varying(255), gecos character varying(255), gid integer DEFAULT 150, home character varying(255), mailquota integer DEFAULT 20 ); ALTER TABLE ONLY accounts ADD CONSTRAINT uid_k PRIMARY KEY (uid); ALTER TABLE ONLY accounts ADD CONSTRAINT login_k UNIQUE (login); CREATE TABLE aliases ( mail character varying(128) NOT NULL, alias character varying(128) ); ALTER TABLE ONLY aliases ADD CONSTRAINT mail_k PRIMARY KEY (mail); ${lookup{$var_to_search}lsearch{/path/to/file}} $список -> ${lookup список} -> ${lookup {$var_to_search} driver{driver_arguments}} $var_to_search: значение domainlist domains = ${lookup{$sender_host_address} lsearch{/some/file}} 192.168.3.4: domain1 : domain2 : ... 192.168.1.9: domain3 : domain4 : ... ${lookup driver{query}{action_if_query_succeed} {action_if_query_failed}} domainlist domains = ${lookup pgsql{select domains from domains where sender='$sender_host_address'}{$value}fail} ldap_default_servers = 127.0.0.1::389 ${lookup ldap{ldap://ldap.test.ru/dc=${domain},ou=mail, o=tehnopark?mail?sub?(&(objectClass=inetOrgPerson) (mail=${local_part}@${domain}))}{$value} fail} ${lookup ldap {user="cn=manager,o=tehnopark of innovation,c=RU" pass=secret ldap:///o=tehnopark%20of%20innovation,c=RU?sn?sub?(cn=foo)} {$value}fail} ########################################################## # Runtime configuration file for Exim # ########################################################## # Здесь мы определяем макросы, описывающие различные пути CONFIG_PREFIX=/usr/local/etc/exim ACL_PREFIX=CONFIG_PREFIX/acls CERTDIR=CONFIG_PREFIX/certs # Здесь мы указываем, где находить наш PostgreSQL-сервер, # соединение осуществляется через локальный сокет, команда # hide помогает спрятать эту настройку при вызове exim -bP, # когда exim выводит все конфигурационные опции в стандартный # вывод. Учтите, что сам /usr/local/etc/exim/configure должен # иметь владельца root:wheel и иметь права доступа 0600, что # отличается от того, что принято по умолчанию (0644) hide pgsql_servers = (/tmp/.s.PGSQL.5432)/users/pgsql/pAsSwOrD # Тут мы описываем списки доменов # Local_domains включает домены, считающиеся локальными, то # есть те домены, для которых exim делает локальную доставку, # для остальных доменов почта доставляется по MX записям в DNS. # Обратите внимание на дополнительные файлы ACL_PREFIX/localdomains # и ACL_PREFIX/hostingdomains, в которых перечислены домены, # разделенные переводом строки (то есть по одному домену на # каждую строку) domainlist local_domains = unona.test.ru : ACL_PREFIX/localdomains : ACL_PREFIX/hostingdomains # Дополнительная настройка domainlist hosting_domains = ACL_PREFIX/hostingdomains # Список хостов, почту на которые мы явно отвергаем hostlist host_reject = ACL_PREFIX/hostreject domainlist relay_to_domains = # Список адресов, с которых разрешена передача почты во # внешний мир hostlist relay_from_hosts = localhost : 192.168.1.0/24 : ACL_PREFIX/relayfromhosts # Проверка получателя acl_smtp_rcpt = acl_check_rcptъ # Проверка mime содержимого acl_smtp_mime = acl_check_mime # Проверка на спам и вирусы acl_smtp_data = acl_check_virus # Здесь мы описываем наш антивирус av_scanner = clamd:127.0.0.1 3310 # И spamassasin spamd_address = 127.0.0.1 783 # Настройки пользователя и группы по умолчанию exim_user = mailnull exim_group = mail # Никогда не осуществляем доставку под рутом - root должен # быть алиасом на другого локального пользователя. Кстати, # это обязательное условие, заданное еще на этапе компиляции never_users = root # Настройки директории для очереди spool_directory = /var/spool/exim # Разделяем spool_directory на несколько более маленьких, # аналог хеш-таблицы, ускоряет обработку spool split_spool_directory # Пытаемся сделать соответствие прямой и обратной зоны DNS # для каждого хоста. Несколько затратно, но весьма полезно host_lookup = * # Убираем проверку identd на клиентской стороне. Из-за # неправильно настроенных firewall это часто вызывает # длительные тайм-ауты, кроме того, этот сервис поднят # не у многих rfc1413_query_timeout = 0s # Указываем кое-какие лимиты (их назначение ясно из названия) smtp_accept_max = 50 smtp_connect_backlog = 40 smtp_accept_max_per_host = 10 smtp_accept_queue = 22 smtp_accept_queue_per_connection = 10 recipients_max = 16 recipients_max_reject = true message_size_limit = 16M accept_8bitmime # Игнорируем сообщения, которые приходят нам же, давность # которых более 12 часов ignore_bounce_errors_after = 12h # Удаляем замороженные сообщения, давность которых больше # недели. timeout_frozen_after = 7d # Настройки TLS tls_certificate = CERTDIR/mailed.crt tls_privatekey = CERTDIR/mailed.key tls_advertise_hosts = * tls_verify_certificates = * # Следующая опция закомментирована, но весьма полезна, # позволяя авторизироваться # только через безопасный ssl-канал #auth_advertise_hosts = ${if eq{$tls_cipher}{}{}{*}} ########################################################## # ACL CONFIGURATION # # Specifies access control lists for incoming SMTP mail # ########################################################## begin acl # Этот список доступа описывает проверки, осуществляемые # при вызове любой RCPT-команды acl_check_rcpt: # Вначале проверяем достоверность отправителя require verify = sender # Принимаем соединения от локальных MUA (то есть не через TCP/IP) accept hosts = : ########################################################## # Проверка соответствия почтового адреса стандарту deny message = Restricted characters in address domains = +local_domains local_parts = ^[.] : ^.*[@%!/|] accept domains = +local_domains # Здесь прописаны так называемые dnsbl, то есть черные # списки MTA с открытым релеем, мы проверяем IP-адрес # отправителя на соответствие таким спискам и блокируем письмо, # если отправитель был найден в таком списке deny message = host is listed in $dnslist_domain dnslists = blackholes.mail-abuse.org: dialups.mail-abuse.org: relays.mail-abuse.org: relays.ordb.org: work.drbl.caravan.ru: dul.ru:sbl.spamhaus.org # Правило на проверку всех почтовых адресов, кроме локальных # (менее строгое) deny message = Restricted characters in address domains = !+local_domains local_parts = ^[./|] : ^.*[@%!] : ^.*/\\.\\./ ########################################################## # Принимаем почту для пользователя postmaster локальных # доменов, не взирая на отправителя accept local_parts = postmaster domains = +local_domains # Deny unless the sender address can be verified accept domains = +local_domains endpass verify = recipient # Если домен в списке relay_to_domains, то разрешаем релей accept domains = +relay_to_domains endpass verify = recipient accept domains = +hosting_domains endpass verify = recipient accept hosts = +relay_from_hosts # Принимаем любые соединения, которые были успешно # авторизованы accept authenticated = * # Реализация нашего бан-листа deny hosts = +host_reject message = You are banned. Go away. # Запрещаем все, что не разрешено, закрывая тем самым релей # для спамеров deny message = relay not permitted # Список доступа для проверки mime-частей сообщения acl_check_mime: # Произодим декодирование mime-сообщений. Полезно для # дальнейшей проверки на вирусы warn decode = default # Можно очень быстро отсеять сообщения, просто запретив # некоторые mime-вложения, чаще всего содержащие вирусы, # хотя, конечно, это не панацея deny message = Blacklisted file extension detected condition = ${if match {${lc:$mime_filename}}{\N(\.wav|\.cpl|\.pif|\.bat|\.scr|\.lnk|\.com)$\N} {1}{0}} # Много ли у нас людей, знающих китайский? А вот китайского # спама это поубавит deny message = Sorry, noone speaks chinese here condition = ${if eq{$mime_charset}{gb2312}{1}{0}} accept # Проверка содержимого на вирусы и спам acl_check_virus: # Мы не запрещаем письма со спамом, а просто добавляем # заголовок, содержащий количество спамерских очков, # а пользователь на своей стороне уже просто настраивает # свои фильтры. Так мы исключаем жалобы со стороны # пользователей о потерянных письмах warn message = X-Spam-Score: $spam_score ($spam_bar) spam = nobody:true # Добавляем заголовки, указывающие, что письма были проверены # SpamAsssasin warn message = X-Spam-Scanned: Yes warn message = X-Spam-Scanner: SpamAssassin running on mail.test.ru # Вот что-что, а вирусы нам не нужны deny message = Message rejected: virus found. Your message was successfully trashed. hosts = * malware = * accept ########################################################## # ROUTERS CONFIGURATION # # Specifies how addresses are handled # ########################################################## # THE ORDER IN WHICH THE ROUTERS ARE DEFINED IS IMPORTANT!# # An address is passed to each router in turn until it is accepted. # ################################################################### begin routers # Роутер, осуществляющий поиск по MX-записям в DNS dnslookup: driver = dnslookup domains = ! +local_domains transport = remote_smtp ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8 no_more # Все останльные роутеры обслуживают доставку локальной почты # Драйвер алиасов пользователя. Обратите внимание на lookup # в pgsql-базе. Что интересно, этот lookup работает даже для # иерархических алиасов, например, postmaster -> root -> # cebka -> cebka@jet.msk.su Также определяются транспорты # для передачи почты в файл (>/path/to/file) и в pipe # (|/usr/local/libexec/slocal) system_aliases: driver = redirect allow_fail allow_defer data = ${lookup pgsql{select alias from aliases where mail ='$local_part@$domain'}{$value}fail} user = mailnull group = mail file_transport = address_file pipe_transport = address_pipe # Для локальных пользователей также создаем возможность # перенаправления почты через ~/.forward-файл. Если включена # директива allow_filter, то в .forward-файле можно # использовать язык sieve-фильтров. Для подробностей # см. документацию на www.exim.org, т.к. на рассмотрение # этой темы уйдет слишком много времени userforward: driver = redirect check_local_user file = $home/.forward no_verify no_expn check_ancestor # allow_filter file_transport = address_file pipe_transport = address_pipe reply_transport = address_reply condition = ${if exists{$home/.forward} {yes} {no} } # Локальная доставка, если данный пользователь найден в базе localuser: driver = accept condition = ${lookup pgsql {select uid from accounts where login = '$local_part@$domain'}{yes}{no}} transport = local_delivery cannot_route_message = Unknown user #################################################### # TRANSPORTS CONFIGURATION # #################################################### # ORDER DOES NOT MATTER # # Only one appropriate transport is called for each delivery. # #################################################### begin transports # Драйвер для доставки через соединения с удаленными # smtp-серверами remote_smtp: driver = smtp # Этот транспорт доставляет почту в локальные maildir. Путь # к maildir хранится опять же в таблице accounts. Разрешения # на директорию 0700 для возможности работы с данными # директориями imap-сервера. При этом владельцем является # группа и пользователь из accounts (потому при включении # записей в эту таблицу надо начинать значения uid # с достаточно большого числа, например, 2000 и пересекаться # с реальными пользователями оно должно, только если реальному # пользователю нужен локальный доступ к maildir). # Также из таблицы accounts извлекаются данные о размере # квоты, и устанавливается порог в 75% от квоты, когда # пользователю посылается указанное предупреждение об подходе # к порогу квоты local_delivery: driver = appendfile directory = ${lookup pgsql{select maildir from accounts where login = '$local_part@$domain'}{$value}fail} create_directory directory_mode = 0770 maildir_format delivery_date_add envelope_to_add return_path_add group = ${lookup pgsql{select gid from accounts where login = '$local_part@$domain'}{$value}fail} user = ${lookup pgsql{select uid from accounts where login = '$local_part@$domain'}{$value}fail} mode = 0660 no_mode_fail_narrower quota = ${lookup pgsql{select mailquota from accounts ї where login = '$local_part@$domain'}{$value}fail}M quota_warn_message = "\ To: $local_part@domain\n\ From: postmaster@test.ru\n\ Subject: Your maildir is going full\n\ This message is automaticaly gnerated by your mail server.\n\ This means, that your mailbox is 75% full. If you would \n\ override this limit new mail would not be delivered to you!\n" quota_warn_threshold = 75% # Транспорт, осуществляющий доставку в pipe address_pipe: driver = pipe return_output # Транспорт, осуществляющий доставку прямо в файл address_file: driver = appendfile delivery_date_add envelope_to_add return_path_add # Этот транспорт используется для автоматического ответа на # сообщения об ошибках address_reply: driver = autoreply ########################################################## # RETRY CONFIGURATION # ########################################################## begin retry # Настройки по умолчанию, которые я не трогал, управляют # интервалом повторной передачи сообщений # This single retry rule applies to all domains and all # errors. It specifies retries every 15 minutes for 2 hours, # then increasing retry intervals, starting at 1 hour and # increasing each time by a factor of 1.5, up to 16 hours, # then retries every 6 hours until 4 days have passed since # the first failed delivery. # Address or Domain Error Retries # ----------------- ----- ------- * * F,2h,15m; G,16h,1h,1.5; F,4d,6h ########################################################## # REWRITE CONFIGURATION # ########################################################## begin rewrite # Создаем правило по переписыванию заголовка To: с *@test.ru # на локальный smart-host - @unona.test.ru. Это было сделано # для локальных пользователей, по идее с хранением # пользователей в postgres уже не нужно, показано для примера. *@test.ru $1@unona.test.ru T ########################################################## # AUTHENTICATION CONFIGURATION # ########################################################## # Описания аутентификации begin authenticators # CRAM-MD5-аутентификация, требует наличия пароля в открытом # виде, имя пользователя должно быть в формате user@domain, # как оно хранится в таблице accounts lookup_cram: driver = cram_md5 public_name = CRAM-MD5 server_secret = ${lookup pgsql {select password from accounts where login='$1'}{$value}fail} server_set_id = $1 # LOGIN-аутентификация - не требует хранения пароля # в открытом виде, однако, по сети пароль передается # в открытом виде - требуется лишь выполнение условия # server_condition - $1 - имя пользователя, а $2 - пароль. # LOGIN безопасен только при установлении ssl-соединения. login: driver = plaintext public_name = LOGIN server_prompts = Username:: : Password:: server_condition = ${lookup pgsql {select login from accounts where login='$1' and password='$2'}{yes}{no}} server_set_id = $1 ########################################################## # CONFIGURATION FOR local_scan() # ########################################################## # If you have built Exim to include a local_scan() function # that contains tables for private options, you can define # those options here. Remember to uncomment the "begin" # line. It is commented by default because it provokes # an error with Exim binaries that are not built with # LOCAL_SCAN_HAS_OPTIONS set in the Local/Makefile. # begin local_scan # End of Exim configuration file # openssl genrsa -out mailed.key 2048 # openssl req -new -x509 -key mailed.key -days 365 -out mailed.crt exim -bd -d+all sendmail_enable="NONE" exim_enable="YES" # А также для spamassasin и clamav: clamav_clamd_enable="YES" spamd_enable="YES" sendmail /usr/local/sbin/exim send-mail /usr/local/sbin/exim mailq /usr/local/sbin/exim newaliases /usr/local/sbin/exim hoststat /usr/local/sbin/exim purgestat /usr/local/sbin/exim TCPSocket 3310 TCPAddr 127.0.0.1 [ req_dn ] C=RU ST=Moskow region L=Moskow O=Tehnopark OU=Internet technologies CN=test.ru emailAddress=postmaster@test.ru cd /usr/local/share/courier-imap/ ./mkimapdcert cd /usr/local/etc/courier-imap/ cp authdaemonrc.dist authdaemonrc authmodulelist="authpgsql" # Соединяемся с СУБД через локальный сокет (не указан адрес) PGSQL_PORT 5432 PGSQL_USERNAME pgsql PGSQL_PASSWORD pAsSwOrD PGSQL_DATABASE users # Настройки таблицы для аутентификации, здесь мы указываем, # в каких полях таблицы хранятся различные пользовательские # данные: PGSQL_USER_TABLE accounts PGSQL_CLEAR_PWFIELD password DEFAULT_DOMAIN test.ru PGSQL_UID_FIELD uid PGSQL_GID_FIELD gid PGSQL_LOGIN_FIELD login PGSQL_HOME_FIELD home PGSQL_NAME_FIELD gecos PGSQL_MAILDIR_FIELD maildir # imapd слушает только на локальном адресе, для внешних # соединений мы будем использовать imapd-ssl ADDRESS=127.0.0.1 # По умолчанию в NO, делаем в YES, чтобы imapd мог запускаться IMAPDSTART=YES IMAPDSSLSTART=YES # mv courier-imap-imapd-ssl.sh.sample courier-imap-imapd-ssl.sh # mv courier-imap-imapd.sh.sample courier-imap-imapd.sh # chmod 1777 /var/spool/squirrelmail/attach # chmod 1777 /var/spool/squirrelmail/pref Настройка почтовой системы на базе Postfix + Dovecot + PostgreSQL + Amavisd-new + SpamAssassin + ClamAV Рустам Атнагулов [root@mosqit /]# apt-get install postfix postfix-pgsql postgresql postgresql-server dovecot amavisd clamav spamassasin [root@mosqit /]# groupadd -g 5000 mailuser [root@mosqit /]# adduser -d /var/spool/mail -M -g mailuser -s /sbin/nologin -u 5000 mailuser [root@mosqit /]# createuser -U postgres [root@mosqit /]# psql -U postgres template1 [root@mosqit /]# createdb -U postgres mails CREATE TABLE "public"."users" ( "userid" VARCHAR(128) NOT NULL, "password" VARCHAR(128), "realname" VARCHAR(128), "uid" INTEGER NOT NULL, "gid" INTEGER NOT NULL, "home" VARCHAR(128) NOT NULL, "mail" VARCHAR(255), CONSTRAINT "users_pkey" PRIMARY KEY("userid") ) WITHOUT OIDS; grant select on users to mailuser; CREATE TABLE "public"."aliases" ( "alias" VARCHAR(128) NOT NULL, "dest" VARCHAR(128) NOT NULL, "comment" TEXT DEFAULT ''::text ) WITH OIDS; grant select on aliases to mailuser; [root@mosqit /]# /usr/bin/psql -U postgres mails < createtable.sql [root@mosqit /]# service postgresql start main.cf: # Задаем имя нашего почтового узла myhostname = testdomain.ru # Имя нашего домена, если не указывать, то по умолчанию # выставится минус первый компонент имени узла mydomain = testdomain.ru myorigin = $myhostname # RECEIVING MAIL # Здесь задаем, на каких сетевых интерфейсах будет работать # Postfix, в моем случае на всех inet_interfaces = all # Список доменов, на которые будет осуществляться доставка # через local transport mydestination = localhost, $myhostname, localhost.$mydomain, $config_directory/mydestination # REJECTING MAIL FOR UNKNOWN LOCAL USERS # Здесь мы указываем, что пользователей testdomain.ru нужно # просматривать в $virtual_maibox_maps local_recipient_maps = $virtual_maibox_maps unknown_local_recipient_reject_code = 550 # TRUST AND RELAY CONTROL # здесь указываем, кому разрешен relay, т.е. пользователям # обслуживаемой сети mynetworks = 127.0.0.0/8, 10.70.1.0/24 # Задаем директорию, где будет храниться почта mail_spool_directory = /var/spool/mail mailbox_command = /usr/bin/procmail -a $DOMAIN -d $LOGNAME # Наш почтовый сервер требует сначала комманду helo smtpd_helo_required = yes transport_maps = hash:/etc/postfix/transport.cf # Задаем директорию, где будет храниться почта # из виртуальных доменов virtual_mailbox_base = /var/spool/mail/ # Просмотр таблиц с целью проверки действительности адреса virtual_mailbox_maps = pgsql:/etc/postfix/mailbox.pgsql virtual_alias_maps = pgsql:/etc/postfix/aliases.pgsql # Использую статические uid & gid; 5000 – это mailuser virtual_uid_maps = static:5000 virtual_gid_maps = static:5000 virtual_minimum_uid = 5000 # INSTALL-TIME CONFIGURATION INFORMATION readme_directory = /etc/postfix/README_FILES sample_directory = /etc/postfix/samples sendmail_path = /usr/sbin/sendmail setgid_group = postdrop command_directory = /usr/sbin manpage_directory = /usr/share/man daemon_directory = /usr/lib/postfix newaliases_path = /usr/bin/newaliases mailq_path = /usr/bin/mailq queue_directory = /var/spool/postfix mail_owner = postfix # Этот параметр относится к Amavisd # Пока комментируем, чтобы можно было проверить # работоспособность postfix. #content_filter=smtp-amavis:[127.0.0.1]:10024 master.cf: #======================================================================================= # service type Type Private Unpriv Chroot wakeup maxproc command + args # (yes) (yes) (yes) (yes) (never) (100) #======================================================================================= smtp inet n - - - - smtpd pickup fifo n - - 60 1 pickup cleanup unix n - - - 0 cleanup qmgr fifo n - - 300 1 qmgr rewrite unix - - - - - trivial-rewrite bounce unix - - - - 0 bounce defer unix - - - - 0 bounce flush unix n - - 1000 0 flush proxymap unix - - n - - proxymap smtp unix - - - - - smtp relay unix - - - - - smtp showq unix n - - - - showq error unix - - - - - error local unix - n n - - local virtual unix - n n - - virtual lmtp unix - - - - - lmtp # далее относится к amavisd smtp-amavis unix - - n - 2 smtp -o smtp_data_done_timeout=1200 -o smtp_send_xforward_command=yes -o disable_dns_lookups=yes 127.0.0.1:10025 inet n - n - - smtpd -o content_filter= -o relay_recipient_maps= -o smtpd_restriction_classes= -o smtpd_client_restrictions= -o smtpd_helo_restrictions= -o smtpd_sender_restrictions= -o smtpd_recipient_restrictions=permit_mynetworks,reject -o mynetworks=127.0.0.0/8 -o strict_rfc821_envelopes=yes -o smtpd_error_sleep_time=0 -o smtpd_soft_error_limit=1001 -o smtpd_hard_error_limit=1000 aliases.pgsql: hosts = localhost user = mailuser password = topsecret dbname = mails table = aliases select_field = dest where_field = alias mailbox.pgsql: hosts = localhost user = mailuser password = topsecret dbname = mails table = users select_field = home where_field = userid transport.cf: testdomain.ru virtual: another.domain.ru virtual: [root@mosqit /]# service postfix start [root@mosqit /]# telnet 127.0.0.1 25 add_mailuser.bash: #! /bin/bash basedir=/var/spool/mail echo "Введите e-mail в виде name@domain" read email pos=`expr match "$email" '[a-z1-9A-Z.]*@'` if [ $pos = "0" ] then echo "Неправильное имя пользователя" exit fi domain=${email:$pos} name=${email:0:($pos-1)} cd $basedir/$domain/$name &> /dev/null if [ $? = "0" ]; then echo 'Такой пользователь существует !! ' exit fi cd $basedir/$domain &> /dev/null if [ $? = "1" ]; then echo 'Такого домена не существует' exit fi echo "Введите полное имя " read fullname echo "Введите пароль " read pass echo "пароль $pass" echo -E "INSERT INTO public.users (userid, password, realname, uid, gid, home, mail) VALUES ('$email', '$pass', '$fullname', '42', '42','$domain/$name/inbox', NULL);" | /usr/bin/psql -U postgres mails mkdir $basedir/$domain/$name touch $basedir/$domain/$name/inbox chmod 600 $basedir/$domain/$name/inbox chmod 700 $basedir/$domain/$name chown postfix:postfix $basedir/$domain/$name -R ls $basedir/$domain/$name/inbox &> /dev/null if [ $? = "1" ]; then echo 'Ошибочка вышла! ' exit fi echo "Пользователь создан успешно" del_mailuser.bash: #! /bin/bash basedir=/var/spool/mail echo "Введите e-mail, который хотите удалить в виде name@domain" read email pos=`expr match "$email" '[a-z1-9A-Z.]*@'` if [ $pos = "0" ] then echo "Неправильное имя пользователя" exit fi domain=${email:$pos} name=${email:0:($pos-1)} cd $basedir/$domain/$name &> /dev/null if [ $? = "1" ]; then echo 'Такой пользователь не существует !! ' exit fi echo "DELETE from public.users where userid='$email';" | usr/bin/psql -U postgres mails rm -rf $basedir/$domain/$name &> /dev/null cd $basedir/$domain/$name &> /dev/null echo $? if [ $? = "0" ]; then echo 'Ошибочка вышла! ' exit fi echo "Пользователь удален успешно" add_alias.bash: #! /bin/bash echo "Введите aliasname виде name@domain" read aliasname pos=`expr match "$aliasname" '[a-z1-9A-Z.]*@'` if [ $pos = "0" ] then echo "Неправильный aliasname" exit fi echo "Введите destination в виде name@domain" read dest pos=`expr match "$dest" '[a-z1-9A-Z.]*@'` if [ $pos = "0" ] then echo "Неправильный destination" exit fi echo "Введите комментарий" read comment echo -E "INSERT INTO public.aliases (email, alias, comment) VALUES ('$aliasname', '$dest', '$comment');" | /usr/bin/psql -U postgres mails echo "Alias создан успешно" [root@mosqit /]# add_mailuser.bash [root@mosqit /]# service postfix restart [root@mosqit /]# telnet 127.0.0.1 25 [root@mosqit /]# service clamd start [root@mosqit /]# service amavisd start [root@mosqit /]# telnet 127.0.0.1 10024 [root@mosqit /]# service postfix restart dovecot.conf: # Протоколы, которые мы используем protocols = imap imaps pop3 pop3s ## IMAP login process login = imap ## POP3 login process login = pop3 ## Mail processes first_valid_uid = 5000 # Путь к директории, где хранится почта, где %d – # имя домена, %n – имя пользователя default_mail_env = mbox:/var/spool/mail/%d/%n/:INDEX=/var/spool/mail/%d/%n mbox_locks = fcntl flock ## Authentication processes auth = default auth_mechanisms = plain auth_userdb = pgsql /etc/dovecot/pgsql.conf auth_passdb = pgsql /etc/dovecot/pgsql.conf # root т.к. использовать порты до 1024 порта может только root auth_user = root [ req ] default_bits = 1024 encrypt_key = yes distinguished_name = req_dn x509_extensions = cert_type prompt = no [ req_dn ] # country (2 letter code) C=RU # State or Province Name (full name) ST=Bashkortostan # Locality Name (eg. city) L=Ufa # Organization (eg. company) O=Home Organizations. # Organizational Unit Name (eg. section) OU=POP3 IMAP server # Common Name (*.example.com is also possible) CN=testdomain.ru # E-mail contact emailAddress=master@testdomain.ru [ cert_type ] nsCertType = server [root@mosqit /]# /usr/share/dovecot/mkcert.sh connect = host = localhost dbname = mails user = mailuser password = secret default_pass_scheme = PLAIN password_query = SELECT password FROM users WHERE userid = '%u' user_query = SELECT '/var/spool/mail/'|| home, uid, gid FROM users WHERE userid = '%u' [root@mosqit /]# service dovecot start «Кто стучится в дверь ко мне…» Обзор системы поддержки списков рассылок GNU Mailman Андрей Маркелов gunzip mailman.tar.gz tar –xvf mailman.tar useradd mailman mkdir /usr/local/mailman chgrp mailman /usr/local/mailman chmod a+rx,g+ws /usr/local/mailman cd /tmp/mailman-2.1.5/ ./configure --with-cgi-gid=apache --with-mail-gid=mail make install cd /usr/local/mailman ./bin/check_perms ScriptAlias /mailman/ /usr/local/mailman/cgi-bin/ Alias /pipermail/ /usr/local/mailman/archives/public AddDefaultCharset Off cp /usr/local/mailman/icons/* /var/www/icons service httpd restart ./bin/newlist mailman test: "|/usr/local/mailman/mail/mailman post test" test-admin: "|/usr/local/mailman/mail/mailman admin test" test-bounces: "|/usr/local/mailman/mail/mailman bounces test" test-confirm: "|/usr/local/mailman/mail/mailman confirm test" test-join: "|/usr/local/mailman/mail/mailman join test" test-leave: "|/usr/local/mailman/mail/mailman leave test" test-owner: "|/usr/local/mailman/mail/mailman owner test" test-request: "|/usr/local/mailman/mail/mailman request test" test-subscribe: "|/usr/local/mailman/mail/mailman subscribe test" test-unsubscribe: "|/usr/local/mailman/mail/mailman unsubscribe test" cd /etc/smrsh/ ln –s /usr/local/mailman/mail/mailman mailman cd /usr/local/mailman/cron crontab –u mailman crontab.in cd .. ./bin/mailmanctl start cp scripts/mailman /etc/init.d/mailman chkconfig –add mailman ./bin/config_list –I data/sitelist.cfg mailman ./bin/mmsitepass Как различать и считать маркированный трафик? Павел Закляков iptables -A PREROUTING -t mangle -i eth0 -j MARK --set-mark 6 iptables -A PREROUTING -t mangle -i eth0 -s 217.26.176.0/20 -j MARK --set-mark 7 iptables -A PREROUTING -t mangle -i eth0 -s 217.146.192.0/20 -j MARK --set-mark 7 iptables -A FORWARD -d 192.168.0.5 -m mark --mark 6 iptables -A FORWARD -d 192.168.0.5 -m mark --mark 7 tc filter add dev eth0 parent 1:0 prio 0 protocol ip handle 6 fw flowid 1:6 tc filter add dev eth0 parent 1:0 prio 0 protocol ip handle 7 fw flowid 1:7 iptables -A FORWARD -d 192.168.0.5 -m dscp --dscp 0x18 iptables -N user-chain iptables -A FORWARD -d 192.168.0.5 -m tos --tos Normal-Service -j user-chain iptables -A FORWARD -d 192.168.0.5 -m dscp --dscp 0x18 iptables -t mangle -A PREROUTING -j TOS --set-tos 0 iptables -t mangle -A FORWARD -j TOS --set-tos 0 iptables -A FORWARD -d 192.168.0.5 -m dscp --dscp 0x18 iptables ... -m u32 --u32 "Start&Mask=Range" iptables ... -m u32 --u32 "5&0xFF=0:3" iptables ... -m ttl --ttl-lt 4 iptables -A FORWARD -d 192.168.0.5 -m dscp --dscp 0x18 iptables -A FORWARD -m u32 --u32 "0&0x00FF0000=0x00600000" -d 192.168.0.5 iptables -A FORWARD -m u32 --u32 "0&0x00600000=0x00600000" -d 192.168.0.5 iptables -A FORWARD -m u32 --u32 "0&0x00600000>>16=0x60" -d 192.168.0.5 PostgreSQL: первые шаги Сергей Супрунов CONFIGURE_ARGS+= --enable-locale --enable-multibyte=KOI8 --enable-recode # make && make install # make –DWITH_TESTS # make install ./configure --enable-locale --enable-multibyte=KOI8 --enable-recode # su –l pgsql –c “initdb –E KOI8” # su –l pgsql –c “initdb –E KOI8 –D /var/databases/postgres/data” $ /usr/local/bin/postmaster –D /usr/local/pgsql/data $ /usr/local/bin/pg_ctl –D /usr/local/pgsql/data –l logfile start $ psql –U pgsql template1 $ psql –U test test # pg_ctl reload Упрощаем себе жизнь с Webmin Сергей Яремчук #/usr/local/webmin-1.140/changepass.pl /etc/webmin пользователь новый_пароль # /etc/webmin/stop && /etc/webmin/start service webmin { user = root env = LANG= port = 10000 socket_type = stream protocol = tcp wait = no disable = no type = UNLISTED server = /usr/local/webmin-1.140/miniserv.pl server_args = /etc/webmin/miniserv.conf } FreeBSD tips: ARP в «заморозке» Сергей Супрунов # arp –an | awk –v OFS=”\t” ‘{print(substr($2, 2, length($2)-2), $4)}’ > ethers # arp –d –a # arp –f /usr/local/etc/ethers #!/bin/sh # Static ARP-table loader case $1 in start) arp -d -a > /dev/null arp -f /usr/local/etc/ethers > /dev/null echo 'Static ARP-table is loaded' ;; stop) arp -d -a > /dev/null echo 'Static ARP-table is unloaded' ;; restart) arp -d -a > /dev/null arp -f /usr/local/etc/ethers > /dev/null echo 'Static ARP-table is reloaded' ;; status) arp -an ;; *) echo "Usage: `basename $0` {start|stop|restart|status}" >&2 ;; esac exit 0 Строим шлюз с Luinux Сергей Яремчук # cp /usr/share/keymaps/i386/qwerty/ru4.kmap.gz/etc/console/boottime.kmap.gz #/etc/init.d/keymap.sh reload #ifconfig a #mcedit /etc/network/interfaces auto lo iface lo inet loopback #теперь для eth0 указываем нужный статический IP-адрес auto eth0 iface eth0 inet static adress 190.2.34.100 netmask 255.255.255.0 #mcedit /etc/resolv.conf search nameserver ip_adress_your_provider_primary_dns nameserver ip_adress_your_provider_secondary_dns #/etc/init.d/hostname.sh #/etc/init.d/networking restart #update-rc.d mldonkey remove #cd /var/opt/mkcdrec/ #make clean #make CD-ROM #scp root@192.168.1.1:/tmp/CDrec.iso #cdrecord -v speed=4 dev=0,0 CDrec.iso #/etc/init.d/packetfilter stop #/etc/init.d/packetfilter start «Стальной глаз на страже жизни» HA-кластер LifeKeeper компании SteelEye Антон Борисов # rpm -ih HADR-RedHat-2.4.18-14-4.4.2-3.i386.rpm [root@pc-box1 java]# rpm -ih jre-1.3.1.i386.rpm # cd licensing/ # rpm -ih steeleye-lkLIC-4.4.2-3.i386.rpm steeleye-lk-4.4.2-2.i386.rpm steeleye-lkIP-4.4.2-2.i386.rpm steeleye-lkAPA-4.4.0-1.i386.rpm steeleye-lkMAN-4.4.2-2.i386.rpm steeleye-lkGUI-4.4.2-2.i386.rpm steeleye-lkRAW-4.4.2-2.i386.rpm steeleye-lkHLP-4.4.2-2.i386.rpm [root@pc-box1]# rpm -ih steeleye-lk* 10.0.0.100 pc-box1 10.0.0.101 bb-box1 10.0.0.200 pc-box2 10.0.0.201 bb-box2 10.0.0.150 triton [root@pc-box1]# /opt/LifeKeeper/bin/lkGUIapp [anthony@pc-box1 anthony]$ /sbin/ifconfig [root@pc-box2]# /opt/LifeKeeper/bin/perform_action -a restore -t ip-triton-tag [anthony@pc-box1 anthony]$ nmap -v triton [root@pc-box2 html]# /opt/LifeKeeper/bin/lcdrcp index.html pc-box1:/var/www/html [root@pc-box1 bin]# ./perform_action -a restore -t apache-tag app_create -d pc-box1 -a apache-tag app_list -d pc-box1 Управление файловыми серверами Иван Коробко ReDim [Preserve] array_name(subscripts) [, varname(subscripts)] ... Пример1: For i=Lbound(Array_) to Ubound(Array_) Msgbox Array_(i) Next Пример 2: Dim Array(100) …………………… For j=0 to 100 For i=0 to 100 If StrComp(Array_sort(i),Array_sort(i+1),0)=1 Then temp=Array(i) Array (i)=Array(i+1) Array(i+1)=temp End if Next Next Пример 3: Text="" i=0 Dim Array() FileName="cache.ini" Set fso = CreateObject("Scripting.FileSystemObject") If fso.FileExists(filename) Then Set Fline = fso.OpenTextFile(FileName) Do While Not (Fline.atEndOfStream) redim preserve array(i) Array(i)= Fline.ReadLine i=i+1 Loop Else Text="File Not Found" End If For i=lbound(array) to ubound(array) Text=Text+cstr(array(i))+vbCrLf ‘ vbCrLf=chr(13)+chr(10)=ENTER Next MsgBox Text Пример 4: For i=lbound(array) to ubound(array) len1=instr(cstr(array(i)),"=") msgbox "len1: "&len1 if len(cstr(array(i)))<>0 then value=left(cstr(array(i)), len1-1) msgbox "value: "& value Select Case value Case "Symbol" path1=right(cstr(array(i)), len(cstr(array(i)))-len1) Case "Path_To_Root" path2=right(cstr(array(i)), len(cstr(array(i)))-len1) Case "Label_FileName" path3=right(cstr(array(i)), len(cstr(array(i)))-len1) Case "Cache_FileName" path4=right(cstr(array(i)), len(cstr(array(i)))-len1) End Select End if Next MsgBox path1+chr(13)+ path2+chr(13)+ path3+chr(13)+ path4+chr(13) Пример 5: Path=”C:\RootFolder” Temp=”” Set fso=Wscript.CreateObject("Scripting.FileSystemObject") Set oFolder=fso.GetFolder(path) Set oFolders=oFolder.SubFolders For Each oF In oFolders Temp=Temp+cstr(oF.Path)+chr(13)+chr(10) Next MsgBox Temp Пример 6: Path=”C:\RootFolder” i=0 Dim Array() 'Объявление динамического массива Set fso=Wscript.CreateObject("Scripting.FileSystemObject") Set oFolder=fso.GetFolder(path) Set oFolders=oFolder.SubFolders ' Изменение размера динамического массива Redim Preserve Array(oFolders.count) For Each of In oFolders Array(i)=cstr(oF.Path) ' Запись элементов в массив i=i+1 Next 'Чтение элементов массива Temp=”” For i=Lbound(Array) to Ubound(Array) Temp=Temp+cstr(Array(i))+chr(13)+chr(10) Next MsgBox Temp Пример 7: Шаблон рекурсивной функции ……….. ' Вызов функции RecFolder в теле сценария RecFolder index, path ……….. Function Recfolder (idx, path) ……….. ……….. ……….. Call Recfolder (idx+1, path) ……….. End Function Пример 8: text= “____________” set fso = CreateObject("Scripting.FileSystemObject") set MyFile = fso.CreateTextFile(strFileName, True, TRUE) ‘ В текстовый файл записывается значение переменной «text» MyFile.WriteLine(text) MyFile.Close net use s: \\server\software AT \\Server 20:00 /interactive /every:M,T,W,Th,F,S,Su C:\InetPub\Soft\Data\Service.vbs Пример 9: Листинг файла default.htm Программное обеспечение Пример 10: Пример 11:
set search_t= Request.QueryString(«Search_Text») Пример 12: <% %> Пример 13:

Название < INPUT TYPE="radio" VALUE="2" NAME="radGrp">Описание < INPUT TYPE ="radio" VALUE="3" NAME="radGrp">Размещение
Пример 14: set radio_=Request.QueryString("radGrp") set search_= Request.QueryString("Search_Text") Пример 15: Select case radio_ Case "1" If instr(ucase(cstr(array_(i,0))), ucase(search_)) then T=T+cstr(array_data(i,0)))+… End If Case "2" If instr(ucase(cstr(array_data(i,1))), ucase(search_)) then T=T+cstr(array_data(i,0)))+… End If …… End Select Русификация FreeDOS Вадим Дружин set COMPILER=TC2 set TC2_BASE=c:\tc201 set XCPU=86 set XFAT=16 :- set COMPILER=WATCOM :- if not \%WATCOM% == \ goto watcom_defined :- set WATCOM=c:\watcom :- set PATH=%PATH%;%WATCOM%\binw :- set XCPU=386 :- set XFAT=32 set XNASM=c:\bin\nasm16 ® set XNASM=c:\nasm\nasm set XUPX=upx --8086 –best ® set XUPX=c:\upx\upx --8086 --best set PATH=%PATH%;%WATCOM%\binw set PATH=%PATH%;%WATCOM%\binw;%WATCOM%\binnt Техника внедрения кода в РЕ-файлы и методы его удаления Крис Касперски mov esi, fs:[0]/lodsd/lodsd mov eax, fs:[30h]/mov eax, [eax + 0Ch]/mov esi, [eax + 1Ch]/lodsd/mov ebx, [eax + 08h] CALL $+5/POP EBP e_lfanew + SizeOfOptionalHeader + 14h + NumberOfSections*40 Листинг 1. Дизассемблерный фрагмент X-кода, внедренного в заголовок (все комментарии принадлежат Иде) HEADER:01000300 ; The code at 01000000-01000600 is hidden from normal disassembly HEADER:01000300 ; and was loaded because the user ordered to load it explicitly HEADER:01000300 ; HEADER:01000300 ; <<<< IT MAY CONTAIN TROJAN HORSES, VIRUSES, AND DO HARMFUL THINGS >>> HEADER:01000300 ; HEADER:01000300 public start HEADER:01000300 start: HEADER:01000300 call $+5 HEADER:01000305 pop ebp HEADER:01000306 mov esi, fs:0 HEADER:0100030C lodsd HEADER:0100030D push ebp HEADER:0100030E lodsd HEADER:0100030F push eax Листинг 2. Так выглядит таблица секций файла notepad.exe Number Name v_size RVA r_size r_offst flag 1 .text 00065CA 0001000 0006600 0000600 60000020 2 .data 0001944 0008000 0000600 0006C00 C0000040 3 .rsrc 0006000 000A000 0005400 0007200 40000040 Листинг 3. Внедрение X-кода в регулярные цепочки .0100A708: 9C pushfd .0100A709: 60 pushad .0100A70A: E80B000000 call .00100A71A --- (1) .0100A70F: 64678B260000 mov esp,fs:[00000] .0100A715: 6467FF360000 push d,fs:[00000] .0100A71B: 646789260000 mov fs:[00000],esp .0100A721: E800000000 call .00100A726 --- (2) .0100A726: 5D pop ebp .0100A727: 83ED23 sub ebp,023 ;"#" .0100A72A: EB2B jmps .00100A757 -------- (3) … .0100A757: EB0E jmps .00100A767 -------- (1) … .0100A767: 8BC5 mov eax,ebp .0100A769: EB2C jmps .00100A797 -------- (1) … .0100A797: EB5E jmps .00100A7F7 -------- (1) … .0100A7F7: EB5E jmps .00100A857 -------- (1) … .0100A857: EB3E jmps .00100A897 -------- (1) … .0100A897: EB3D jmps .00100A8D6 -------- (1) … .0100A8D6: EB0D jmps .00100A8E5 -------- (1) … .0100A8E5: 2D00200000 sub eax,000002000 ;" " .0100A8EA: 89857E070000 mov [ebp][00000077E],eax .0100A8F0: 50 push eax .0100A8F1: 0500100000 add eax,000001000 ;" > " .0100A8F6: 89857E070000 mov [ebp][00000077E],eax .0100A8FC: 50 push eax .0100A8FD: 0500100000 add eax,000001000 ;" > " .0100A902: EB31 jmps .00100A935 -------- (1) INT 2Eh.EAX=067h/INT 2Eh.EAX = 9Ch