среда, 24 октября 2007 г.

ftp-proxy в freebsd

Дело было ранней зимой. Требовалось обеспечить доступ из интернета к ftp-серверу в локальной сети. Сперва решил тупо перенаправить на него порт 21 и порты выше 1025, но выглядело это не очень красиво.
В результате было решено поднять на шлюзе прокси-сервер для протокола ftp (ftp-proxy - портированный из openbsd вместе с pf) и настроить его для работы в обратную сторону.

Что нужно сделать:
1. Добавить в файл /etc/inetd.conf строку:
ftp-proxy stream tcp nowait root /usr/libexec/ftp-proxy ftp-proxy -R <local-ftp-server> -S <local-net-if>

где
<local-ftp-server> - ip-адрес внутреннего ftp-сервера,
<local-net-if> - ip-адрес внутреннего интерфейса шлюза.
2. Настроить параметры запуска inetd в /etc/rc.conf:
inetd_enable="YES"
inetd_flags="-wW -c 60 -a 80.xx.yy.zz"

где 80.xx.yy.zz - внешний ip-адрес шлюза.
3. Настроить pf:
rdr on $ext_if proto tcp from any to $ext_ip port ftp tag TRAF_FTP -> 80.xx.yy.zz port 8021
< ... skip ... >
pass in on $ext_if reply-to proto tcp tagged TRAF_FTP flags S/SA keep state
pass out on $ext_if proto tcp from $ext_ip to any flags S/SA user proxy keep state
pass in on $ext_if proto tcp from any to $ext_ip flags S/SA user proxy keep state
pass out on $int_if proto tcp from $int_ip to any flags S/SA user proxy keep state
pass in on $int_if proto tcp from any to $int_ip flags S/SA user proxy keep state
где
$int_if - локальный интерфейс,
$int_ip - ip-адрес локального интерфейса,
$ext_if - внешний интерфейс,
$ext_ip - ip-адрес внешнего интерфейса,
proxy - имя пользователя ftp-proxy.
4. Запустить inetd.
# /etc/rc.d/inetd start

Прокси-сервер может работать в пассивном режиме. Работу в активном режиме не проверял.

P.S. Данные настройки действительны для семейства FreeBSD 6.x

понедельник, 22 октября 2007 г.

Особенности Qemu

День потратил чтобы соединиться из установленной в Qemu windows-машины к vpn-серверу на одноименной платформе. Долго пытался понять почему соединения отваливаются сразу после авторизации.
Оказалось до банального просто. Qemu я запускал от своего имени (не root) с параметром -net user и поэтому наружу могли идти только пакеты протоколов TCP и UDP, а все другие отбрасывались - в том числе пакеты icmp и gre протоколов.
Чтобы преодолеть данное препятствие qemu стал запускать с tap-интерфейсом:
qemu -hda windows-disk.img -cdrom Windows-image.iso \
-net nic,model=rtl8139 -net tap,ifname=tap0,script=qemu-if-1.sh


где qemu-if-1.sh - скрипт настройки tap-интерфейса
$ cat > qemu-if-1.sh
#!/bin/sh
/sbin/ifconfig tap0 inet 10.0.3.1 netmask 255.255.255.0

$ chmod +x qemu-if-1.sh

Qemu следует запускать от имени пользователя root, чтобы поднялся tap-интерфейс. И в нашем случае виртуальную машину надо вручную настроить на ip-адрес из диапазона 10.0.3.0/24, с шлюзом по адресу 10.0.3.1.

Как сетевой карте присвоить другой MAC-адрес?

Иногда над сетевым интерфейсом до его инициализации требуется сделать некоторые операции. Например - присвоить отличный от заводского MAC-адрес.
Поступаем следующим образом:
1. Создаем файл /etc/start_if.if0, где if0 - имя вашего сетевого интерфейса.
# cat >
/etc/start_if.if0
/sbin/ifconfig if0 ether zz:50:yy:x4:d9:xx

# chmod +x
/etc/start_if.if0
2. Перезагружаем машину.

Больше никаких дополнительных действий не требуется. Скрипт будет найден и исполнен без вашего участия.

Русский подкаст с новостями о GNU/Linux

Недавно читая блог , посвященный дистрибутиву Debian, наткнулся на новость о русском подкасте. Причем подкаст именно с новостями из мира линукса, что немало меня удивило, и ведет подкаст skid (интересный ник - ничего в голову, кроме "республики Шкид", не приходит :).
На сайте подкаста уже выложены три передачи. Прослушать их можно с помощью, например, программы Rhythmbox (подписавшись на rss-ленту) или же просто скачать с сайта.

среда, 10 октября 2007 г.

Интеграция почтового сервера Exim c MS Active Directory

Интеграция почтового сервера Exim c MS Active Directory

Версии ПО:
ОС: FreeBSD 6.2
Почтовый сервер: exim 4.63
СУБД: mysql-server-5.0.27
POP3 и IMAP сервер, с хранением почты в СУБД: dbmail-2.2.2_1
Антиспам-фильтр: dspam-3.6.8_1
Антивирусное ПО: clamav-0.90_3
ПО авторизации:
cyrus-sasl-saslauthd-2.1.22
cyrus-sasl-ldapdb-2.1.22
Библиотека ПО для работы с графикой: gd-2.0.33_4,1
Веб-сервер:
apache-2.0.59
mod_perl2-2.0.3_1,3
CPAN-модули для работы с графикой:
bsdpan-GD-2.35
bsdpan-GD-Graph3d-0.63
bsdpan-GDGraph-1.4308

Все программное обеспечение было установленно из портов ОС FreeBSD 6.2, за исключением нескольких CPAN-модулей.
Установка вышеперечисленного ПО производилась в следующем порядке:
1. почтовый сервер;
2. ПО авторизации;
3. СУБД;
4. POP3 и IMAP сервер;
5. антивирус;
6. антиспам-фильтр;
7. веб-сервер.
1. Установка почтового сервера.

Перед установкой почтового сервера в папке /usr/ports/mail/exim создал файл sys.mk со следующим содержимым:
WITH_CONTENT_SCAN = yes
WITH_MYSQL = yes
WITH_MYSQL_VER = 50
WITH_SASLAUTHD = yes
WITH_OPENLDAP = yes
WITH_OPENLDAP_VER = 23
WITH_AUTH_SASL = yes
Ну а далее просто make install clean или portinstall mail/exim.
Потом начинаем править конфигурационный файл /usr/local/etc/exim/configure:

<...skip...>
######################################################################
# MAIN CONFIGURATION SETTINGS #
######################################################################
# 192.168.0.1 - это адрес вашего контроллера домена, где LDAP-сервер
# доступен по 3268 порту.
ldap_default_servers = <; 192.168.0.1:3268
# В Active Directory нужно создать пользователя "Exim" с паролем "password".
# Стоит обратить внимание на то, что свойство "Выводимое имя"
# пользователя должно быть именно "Exim", иначе почтовый сервер не сможет
# авторизоваться в LDAP-сервере контроллера домена.
LDAP_AD_BINDDN = "CN=Exim,CN=Users,DC=domain,DC=com"
LDAP_AD_PASS = password
LDAP_AD_BASE_DN = "CN=Users,DC=domain,DC=com"
# Макрос для организации запросов к LDAP-серверу.
LDAP_AD_MAIL_RCPT = \
user=LDAP_AD_BINDDN \
pass=LDAP_AD_PASS \
ldap:///DC=domain,DC=com?mail?sub?(&(|(objectClass=top)(objectClass=user)\
(objectClass=organizationalPerson)(objectClass=person))\
(mail=${quote_ldap:${local_part}@${domain}}))

# Скрываем версию ПО
smtp_banner = "$primary_hostname, ESMTP EXIM"

# Некоторые почтовые клиенты в HELO радостно пишут имя windows-машин
# со знаком "_" и тут же отпинываются почтовым сервером. Разрешаем использование
# этого знака.
helo_allow_chars = _

# Пишем логи по дням - удобно для последующего "разбора полетов".
log_file_path = /var/log/exim/exim-%s-%D.log
log_selector = +all
SYSLOG_LONG_LINES = yes

# ourdomain.ru - это доменная зона, куда будут приходить ваши письма.
primary_hostname = mail.ourdomain.ru
domainlist local_domains = ourdomain.ru
hostlist relay_from_hosts = 127.0.0.1
qualify_domain = ourdomain.ru

# Пытаемся распознать имя только тех хостов которые не в локальной сети.
host_lookup = !192.168.0.0/24

# Объявление блока для проверки имени хоста
acl_smtp_connect = acl_check_host

# Объявление блока для проверки HELO отправителя
acl_smtp_helo = acl_check_helo

# Делаем этот параметр равный нулю, чтобы сервер не пытался опросить ident хоста.
rfc1413_query_timeout = 0s

<...skip...>

######################################################################
# ACL CONFIGURATION #
# Specifies access control lists for incoming SMTP mail #
######################################################################

begin acl
### Проверка HELO отправителя
acl_check_helo:
accept hosts = 192.168.0.0/24 : 127.0.0.1
accept hosts = wildlsearch;/usr/local/etc/exim/list/white-hosts

# Отпинываем пользователей, указавших в HELO числа
drop message = Invalid HELO/EHLO data
condition = ${if match {$sender_helo_name}{\N^-?[0-9]+$\N}{yes}{no}}

# Отпинываем пользователей, указавших в HELO ip-address
drop message = HELO/EHLO should not be the ip-address
condition = ${if match {$sender_helo_name}{\N^(\d+\.){3}\d+$\N}{yes}{no}}

# Отпинываем пользователей, указавших в HELO адреса, подпадающих
# под список /usr/local/etc/exim/list/spam-hosts
drop message = Spam blocking
condition = ${lookup {$sender_helo_name}wildlsearch{/usr/local/etc/exim/list/spam-hosts}{yes}{no}}
accept

### Проверка имени хоста отправителя
acl_check_host:
# Правило разрешающее указанные в списке хосты
accept hosts = wildlsearch;/usr/local/etc/exim/list/white-hosts

# Отпинываем пользователей с хостами, подпадающими
# под список /usr/local/etc/exim/list/spam-hosts
drop message = Spam blocking
hosts = !192.168.0.0/24 : !127.0.0.1 : \
wildlsearch;/usr/local/etc/exim/list/spam-hosts

# Отпинываем пользователей с хостами, подпадающими
# под список ip-адресов /usr/local/etc/exim/list/net.blocked
drop message = This ip-address in our blacklist
hosts = net32-lsearch;/usr/local/etc/exim/list/net.blocked

drop message = This ip-address in our blacklist
hosts = net24-lsearch;/usr/local/etc/exim/list/net.blocked

drop message = This ip-address in our blacklist
hosts = net16-lsearch;/usr/local/etc/exim/list/net.blocked

accept

<...skip...>

# В блоке проверки получателя (acl_check_rcpt) раскомментируем строку
require verify = csa

# И после него добавляем правило, запрещающее без авторизации отправлять
# письма от имени наших пользователей
deny !authenticated = *
condition = ${if eq{$sender_address_domain}{ourdomain.ru}{yes}{no}}
message = Sorry, authorization required

<...skip...>

# В блоке проверки содержимого письма (acl_check_data) добавляем правило,
# блокирующее письма с потенциально опасным содержимым
deny message = Contains ".$found_extension" file (blacklisted).
demime = exe:com:vbs:bat:pif:scr:js:cab:wsh:msi:hta:\
vb:vbe:jse:cpl:reg:msp:msi:mst

<...skip...>

######################################################################
# 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

<...skip...>

# Теперь добавляем роутеры для проверки пользователей в Active Directory
# Этот роутер должен стоять после "dnslookup".
adsi_check:
driver = redirect
domains = +local_domains
allow_fail
allow_defer
# forbid_file
# forbid_pipe

# Проверяем наличие запрошенного ящика в Active Directory
data = ${lookup ldap {LDAP_AD_MAIL_RCPT}\
{${local_part}@${domain}} {:fail: User unknown}}
redirect_router = local_adsi_user

local_adsi_user:
driver = accept
# local_part_suffix = +* : -*
# local_part_suffix_optional
transport = local_adsi_delivery
cannot_route_message = Unknown user

<...skip...>

######################################################################
# TRANSPORTS CONFIGURATION #
######################################################################
# ORDER DOES NOT MATTER #
# Only one appropriate transport is called for each delivery. #
######################################################################
begin transports

<...skip...>

# Тут порядок размещения транспортов уже не играет роли
### Local delivery
local_adsi_delivery:
driver = appendfile
file = /var/mail/$local_part
delivery_date_add
envelope_to_add
return_path_add
group = mail
user = mailnull
mode = 0660
no_mode_fail_narrower


Примеры файлов со списками, которые были упомянуты в конфигурационном файле:
# cat > /usr/local/etc/exim/list/white-hosts
*.rmt.ru
smtp-9.masterhost.ru

# cat > /usr/local/etc/exim/list/spam-hosts
\N^[a-fA-F0-9]{10,}(\.[^\.]+){2,}\N
\N^\d+\.\d+\.\d+\.\d+\.\w+\N
\N^.*?[\w\d]+[\.\-](\w*\d+[\-x]){2,}\w*\d+\.[\w\d]\N
\N^\w+\d{5,}[\w]*[\.\-]\N
\N^\d+\.ya1\.ru\N
nat.sitc.ru
\N^(\d+[\-\.]){2,}[\d\w]+\N
\N^.*?\b(client|dial(ed)?|vpn|modem|dhcp|[dD]ynamic|[iI][pP]|pool|catv|ppp|cable|[xav]?dsl)(\d+\w*)?(\.[^\.]+){2,}$\N
*.comcast.net
\N^([xav]?dsl|client|ppp|dial(ed)?|vpn|dhcp|di(al)?up|[xav]?dsl|modem|pool|catv|tomts|host|[uU][sS][eE][rR])[\d]*[\-\.]?\d+\.\N
*.merr.com
*.wanadoo.fr
\N^(\w+\d+[\-\.]){2,}\N
\N^\w+\d+\.neoline\.com\.br$\N
rsveg.plus.com
*.virtua.com.br
*.door.net
*.utoronto.ca
*.venti.pl
*.t-dialin.net
\N^([\d\w]+[\-\.]){2,}\d+[\-\.]\N
*.fortech.lv
*.tpnet.pl
*.1000lecie.pl
*.superb.net
*.chello.nl
*.mobille.tv
*.upc.cz
*.wroc.pl
*.vnet.ee
*.astral.ro
*.bellnexxia.net
*.mynet.net
*.sgci.com
*.shawcable.com
*.ne.jp
*.co.jp
*.oleane.fr
*.wanadoo.co.uk
*.pppool.de
*.bah-bonn.de
*.unict.it
*.interpc.pl
*.retevision.es
*.contactel.cz
*.ufmg.br
*.racsa.co.cr
mail.holzmann.de
*.hananet.net

В этом файле следующий формат данных. Маски сетей пишутся по одному на строку в формате AAA.BBB.CCC.DDD/XX,
где XX - должен быть кратным восьми и больше восьми. Примеры: AAA.BBB.0.0/16, AAA.BBB.CCC.0/24 или AAA.BBB.CCC.DDD/32
# cat > /usr/local/etc/exim/list/net.blocked
219.128.0.0/16
219.129.0.0/16
219.130.0.0/16
219.131.0.0/16
219.132.0.0/16
219.133.0.0/16
219.134.0.0/16
219.135.0.0/16
219.136.0.0/16
219.137.0.0/16

Настраиваем профили пользователей в домене - пишем их электронные адреса в соответствующем поле. Тут надо заметить что в моем случае надо чтобы имя пользователя электронного адреса совпадало с его именем входа - т.е. если в домене он demiurg то адрес должен быть как demiurg@ourdomain.ru. Иначе в будущем могут быть глюки.
Потом проверяем конфигурацию почтового сервера командой exim -bh 80.73.64.248 (под root). Почтовый сервер начнет имитировать SMTP-диалог с указанным хостом и одновременно выводить отладочную информацию о ходе обработки команд и данных.
Например такой диалог:
*< Ответ сервера
*> Наши команды

# exim -bh 80.73.64.248
**** SMTP testing session as if from host 80.73.62.248
**** but without any ident (RFC 1413) callback.
**** This is not for real!

>>> host in hosts_connection_nolog? no (option unset)
LOG: SMTP connection from [80.73.62.248]
>>> host in host_lookup? yes (end of list)
... skip ...
>>> accept: condition test succeeded
*< 220 mail.dbki.ru, ESMTP EXIM
*> HELO sakha.ru
>>> sakha.ru in helo_lookup_domains? no (end of list)
>>> using ACL "acl_check_helo"
>>> processing "accept"
>>> check hosts = 192.168.0.0/24 : 127.0.0.1
... skip ...
*< 250 mail.dbki.ru Hello sakha.ru [80.73.62.248]

# Вводим фиктивный адрес отправителя
*> MAIL FROM: demiurg@sakha.ru
*< 250 OK

# Вводим РЕАЛЬНЫЙ адрес получателя
*> RCPT TO: demiurg@ourdomain.ru
>>> using ACL "acl_check_rcpt"
... skip ...
>>> processing "accept"
>>> accept: condition test succeeded

# Если все правильно настроили то должно выйти "250 Accepted",
# если иное - то начинаем проверять конфиг.
*< 250 Accepted

# Выходим
*> QUIT

2. Установка ПО авторизации.

Настраиваем SMTP-авторизацию
для этого ставим cyrus-sasl-saslauthd-2.1.22
# portinstall security/cyrus-sasl2-saslauthd

После установки создаем конфигурационный файл
# cat > /usr/local/etc/saslauthd.conf
ldap_servers: ldap://192.168.0.1:3268/
ldap_bind_dn: CN=Exim,CN=Users,DC=domain,DC=com
ldap_bind_pw: password
ldap_version: 3
ldap_search_base: CN=Users,DC=domain,DC=com
ldap_filter: (sAMAccountName=%u)
#ldap_filter: (mail=%u)
ldap_debug: -1

Правим конфиг почтового сервера /usr/local/etc/exim.configure:
######################################################################
# AUTHENTICATION CONFIGURATION #
######################################################################
begin authenticators

### Добавляем
plain:
driver = plaintext
public_name = PLAIN
server_condition = ${if saslauthd{{$2}{$3}}{1}{0}}
server_set_id = $2

login:
driver = plaintext
public_name = LOGIN
server_prompts = "Username:: : Password::"
server_condition = ${if saslauthd{{$1}{$2}}{1}{0}}
server_set_id = $1

в /etc/rc.conf добавляем:
sendmail_enable="NO"
sendmail_submit_enable="NO"
exim_enable="YES"
saslauthd_enable="YES"
saslauthd_flags="-a ldap"

Также правим файл /etc/mail/mailer.conf:
sendmail /usr/local/sbin/exim
send-mail /usr/local/sbin/exim
mailq /usr/local/sbin/exim -bp
newaliases /usr/local/sbin/exim -bi
hoststat /usr/local/sbin/exim
purgestat /usr/local/sbin/exim

3. Установка СУБД.

Подробности установки СУБД MySQL 5.0 расписывать не буду, так как она стандартна.

4. Установка POP3 и IMAP сервера.

Следующим шагом ставим DBMail 2.2.2
# cd /usr/ports/mail/dbmail
# make config

отмечаем:
[X] MYSQL Build with MySQL support (хранение почты в mySQL)
[X] SIEVE Build w. support for Sieve mail sorting language (на всякий случай :)
[X] LDAP Build with support for LDAP authentication (ищем пользователей в Active Directory)

и далее
# make install clean

Создаем БД в MySQL:
$ mysql -u root -p
mysql> create database dbmail;
mysql> GRANT SELECT,INSERT,DELETE,UPDATE ON `dbmail`.* to 'dbmail'@'localhost' IDENTIFIED BY 'password';
mysql> use dbmail;
mysql> source /usr/local/share/dbmail/mysql/create_tables.mysql
mysql> flush privileges;

Меняем настройки в конфигурационном файле /usr/local/etc/dbmail.conf:
driver = mysql
authdriver = ldap
sqlsocket = /var/run/mysql.sock

user = dbmail
pass = password
db = dbmail

[LDAP]
# Секция описана полностью, на всякий случай.
PORT = 3268
VERSION = 3
HOSTNAME = 192.168.0.1
BASE_DN = cn=Users,dc=domain,dc=com
BIND_DN = cn=Exim,cn=Users,dc=domain,dc=com

BIND_PW = password
SCOPE = SubTree
USER_OBJECTCLASS = top,person,organizationalPerson,user
#USER_OBJECTCLASS = top,account,dbmailUser
#FORW_OBJECTCLASS = top,account,dbmailForwardingAddress
CN_STRING = sAMAccountName
FIELD_PASSWD = userPassword
FIELD_UID = sAMAccountName
FIELD_NID = uSNCreated
MIN_NID = 10000
MAX_NID = 15000
FIELD_CID = primaryGroupID
MIN_CID = 10000
MAX_CID = 15000
FIELD_MAIL = mail
#FIELD_QUOTA = mailQuota
#FIELD_FWDTARGET = mailForwardingAddress

не забываем про /etc/rc.conf и добавляем туда:
dbmail_imapd_enable="YES"

Снова правим /usr/local/etc/exim/configure:
# Меняем роутер adsi_check
adsi_check:
driver = redirect
domains = +local_domains
allow_fail
allow_defer
forbid_file
forbid_pipe

data = ${lookup ldap {LDAP_AD_MAIL_RCPT}\
{${local_part}@${domain}} {:fail: User unknown}}
redirect_router = dbmailuser

# После роутера adsi_check добавляем
dbmailuser:
driver = accept
condition = ${lookup ldap {LDAP_AD_MAIL_RCPT} {yes}{no}}
transport = dbmail_delivery
cannot_route_message = Unknown user

# Добавляем транспорт dbmail_delivery
dbmail_delivery:
driver = pipe
delivery_date_add
envelope_to_add
return_path_add
check_string =
command = /usr/local/sbin/dbmail-smtp -d $local_part@$domain
group = mail
message_prefix = ""
message_suffix = ""
path="/bin:/sbin:/usr/local/bin:/usr/local/sbin"

Теперь запускаем exim, saslauthd и dbmail:
# /usr/local/etc/rc.d/saslauthd start
# /usr/local/etc/rc.d/exim.sh start
# /usr/local/etc/rc.d/dbmail-imapd start

и пробуем отправить/принять почту (не забывайте про SMTP-авторизацию). Если не получается смотрим в логи и устраняем причину.

5. Установка антивирусного ПО.

На данном этапе все должно работать без уговоров :) Теперь будем прикручивать антивирус Clamav, распространяемый под свободной лицензией.
# cd /usr/ports/security/clamav
# make all install clean

Правим конфигурационный файл /usr/local/etc/exim/configure:
# Правим av_scanner
av_scanner = clamd:/var/run/clamav/clamd

# В блоке проверки контента (acl_check_data) добавляем
deny malware = *
message = This message contains a virus ($malware_name).

Правим конфигурационный файл /usr/local/etc/clamd.conf:
LogFile /var/log/clamav/clamd.log
PidFile /var/run/clamav/clamd.pid
DatabaseDirectory /var/db/clamav
LocalSocket /var/run/clamav/clamd
FixStaleSocket yes
User mailnull
AllowSupplementaryGroups yes
AlgorithmicDetection yes
ScanPE yes
ScanELF yes
DetectBrokenExecutables yes
ScanOLE2 yes
ScanMail yes
MailFollowURLs no
ScanHTML yes
ScanArchive yes

Правим конфигурационный файл /usr/local/etc/freshclam.conf:
DatabaseDirectory /var/db/clamav
UpdateLogFile /var/log/clamav/freshclam.log
PidFile /var/run/clamav/freshclam.pid
DatabaseOwner mailnull
AllowSupplementaryGroups yes
DatabaseMirror database.clamav.net
NotifyClamd /usr/local/etc/clamd.conf

Теперь меняем владельца некоторых папок антивируса:
# chown -R mailnull:mail /var/log/clamav /var/db/clamav /var/run/clamav

И добавляем в /etc/rc.conf:
clamav_clamd_enable="YES"
clamav_freshclam_enable="YES"

Запускаем антивирус (clamd и freshclam), рестартуем почтовый сервер и наслаждаемся жизнью :)

5. Установка антиспам-фильтра.

Ставим антиспам-фильтр:
# cd /usr/ports/mail/dspam
# make config

и отмечаем: SYSLOG, DEBUG, DAEMON, MYSQL50, HASH, VIRT_USERS, LONG_USERNAMES, EXIM_LDA, CGI
и далее:
# make all install clean

Создаем базу данных для dspam:
$mysql -u root -p
mysql> create database dspam;
mysql> use dspam;
mysql> grant all on dspam.* to dspam@'localhost' identified by 'password';
mysql> source /usr/local/share/examples/dspam/mysql/mysql_objects-speed.sql
mysql> source /usr/local/share/examples/dspam/mysql/virtual_users.sql
mysql> flush privileges;

Правим конфиг /usr/local/etc/dspam.conf:
StorageDriver /usr/local/lib/libmysql_drv.so
StorageDriver /usr/local/lib/libhash_drv.so
TrustedDeliveryAgent "/usr/local/sbin/exim -oMr spam-scanned" # Exim
Trust root
Trust dspam
Trust mail
Trust mailnull
Feature noise
Feature chained
Preference "signatureLocation=headers"
Preference "showFactors=on"
Preference "spamAction=tag"
Preference "spamSubject=SPAM"
MySQLServer /tmp/mysql.sock
MySQLUser dspam
MySQLPass password
MySQLDb dspam
MySQLConnectionCache 1000
HashConnectionCache 10
HashConnectionCache 100
IgnoreHeader X-Spam-Status
IgnoreHeader X-Spam-Score
IgnoreHeader X-Spam-Report
IgnoreHeader X-Spam-Scanned
IgnoreHeader X-Virus-Scanner-Result
IgnoreHeader Date
IgnoreHeader Envelope-to
IgnoreHeader Delivery-date
IgnoreHeader Received
IgnoreHeader User-Agent
IgnoreHeader Content-Type
IgnoreHeader Content-Transfer-Encoding
IgnoreHeader To
TrainPristine on

Потом создаем группу и пользователя dspam:
# pw add group dspam
# pw add user dspam -s /bin/nologin -g dspam -d /nonexistent

Теперь добавляем добавляем пользователя ghost в Active Directory, также и как пользователя Exim.
и создаем файл /var/db/dspam/group с таким содержанием:
primary:classification: ghost@ourdomain.ru

Далее меняем владельца папок dspam
#chown -R dspam:dspam /var/db/dspam /var/log/dspam /usr/local/bin/dspam

И правим в последний раз конфиг
/usr/local/etc/exim/configure:
# Добавляем перед роутером adsi_check новые роутеры
### Spam checking
dspam_addspam_router:
driver = accept
domains = +local_domains
local_part_prefix = spam-
transport = dspam_addspam_transport

dspam_notspam_router:
driver = accept
domains = +local_domains
local_part_prefix = notspam-
transport = dspam_notspam_transport

dspam_spamscan_router:
driver = accept
domains = +local_domains
no_verify
condition = "${if and {{!eq {$received_protocol}{spam-scanned}} {!eq {$received_protocol}{local}} } {1}{0}}"
transport = dspam_spamcheck_transport
require_files = /usr/local/bin/dspam
address_test = false

local_delivery_spam_router:
driver = accept
domains = +local_domains
condition = ${if match{$h_X-DSPAM-Result:}{Spam}}
transport = local_delivery_spam_transport
no_more

# Также в конфиг добавляем новый транспорт
### Spam transport
dspam_addspam_transport:
driver = pipe
command = "/usr/local/bin/dspam --user $local_part --class=spam --source=error"
return_path_add = false
return_fail_output = true
log_output = true
home_directory = "/var/db/dspam"
current_directory = "/var/db/dspam"
user = dspam
group = dspam

dspam_notspam_transport:
driver = pipe
command = "/usr/local/bin/dspam --user $local_part --class=innocent --source=error --deliver=innocent %u"
return_path_add = false
return_fail_output = true
log_output = true
home_directory = "/var/db/dspam"
current_directory = "/var/db/dspam"
user = dspam
group = dspam

dspam_spamcheck_transport:
driver = pipe
command = /usr/local/bin/dspam --deliver=innocent --user "$local_part" -- %u
user = dspam
group = dspam
return_path_add = false
log_output = true
return_fail_output = true
headers_remove = X-DSPAM-Result

# Тут создается специальная папка, доступная пользователю по IMAP,
# куда складывается помеченный спам для
# последующего осмотра и разбора.
local_delivery_spam_transport:
driver = pipe
command = /usr/local/sbin/dbmail-smtp -d $local_part@$domain -m 'Spam'
message_prefix =
message_suffix =
delivery_date_add
envelope_to_add
return_path_add

Рестартуем exim и снова радуемся жизни :) Если порадоваться не получилось - читаем от начала и все проверяем.

6. Установка веб-сервера apache2 и веб-интерфейса dspam.
# cd /usr/ports/www/apache20
# make WITH_SUEXEC_MODULES=yes all install clean
# cd /usr/ports/www/mod_perl2; make install clean

Этот порт нужен для авторизации в веб-интерфейсе
# cd /usr/ports/www/mod_auth_imap2; make install clean

Cтавим порт /usr/ports/graphics/gd и недостающие CPAN-модули (чтобы веб-интерфейс dspam мог рисовать графики)
# cpan -i GD::Graph3D
# cpan -i GD::Graph

Не знаю почему, но при установке dspam веб-интерфейс не инсталлировался. Хотя видимо так случилось от того, что веб-сервер еще не был установлен. :) Поэтому её пришлось вручную вытаскивать из тарбалла и копировать в папку /usr/local/www/data/dspam. В итоге у меня в папке оказались следующие файлы и папки:
admin.cgi
configure.pl
graph.cgi
admingraph.cgi
default.prefs
rgb.txt
admins
dspam-logo-small.gif
templates
base.css
dspam.cgi

Правим файл configure.pl:

$CONFIG{'LOCAL_DOMAIN'} = "ourdomain.ru";

После копирования меняем владельца папки - иначе SUEXEC будет активно ругаться и не даст запустить скрипты:

# chown -R dspam:dspam /usr/local/www/data/dspam

А в конфиг /usr/local/etc/apache2/httpd.conf добавляем:


# Активируем модуль авторизации по IMAP
LoadModule auth_imap_module libexec/apache2/mod_auth_imap.so

# Активируем модуль SUEXEC
LoadModule suexec_module libexec/apache2/mod_suexec.so
#
SuexecUserGroup dspam dspam

<Directory "/usr/local/www/data/dspam">
Auth_IMAP_Enabled on
AuthName "Authorization"
AuthType basic
Require valid-user
# Параметры для авторизации пользователей по IMAP
Auth_IMAP_Authoritative on
Auth_IMAP_Server 127.0.0.1
Auth_IMAP_Port 143
Auth_IMAP_Log on

Options FollowSymLinks ExecCGI
AllowOverride All
Order allow,deny
Allow from all
DirectoryIndex admin.cgi
AddHandler cgi-script .cgi
<IfModule mod_perl.c>
PerlSendHeader On
AddHandler perl-script .cgi
PerlHandler Apache::Registry
</IfModule>
</Directory>

Запускаем apache2 и радуемся жизни :)
Всё.

Блокирование баннеров в Squid 2.6

Squid при блокировании нежелательного контента во многих случаях может обходиться без разношерстных редиректоров. В частности, Squid может блокировать баннеры и вместо отображения стандартного текстового предупреждения перенаправить запрос пользователя на веб-сервер с пустым gif-рисунком.

Пример куска конфига прокси-сервера Squid:
Пишем сюда (в файл /usr/local/etc/squid/url.whitelist, по одному домену на строку) доменные имена тех сайтов которые мы не хотим блокировать.
Сюда же следует добавить адрес веб-сервера где размещается контент, куда перенаправляется блокированный запрос пользователя.

acl WHITELIST dstdomain "/usr/local/etc/squid/url.whitelist"
Блокирование баннеров по доменному имени. Строка вроде example.com запретит только этот домен, оставив доступными домены www.example.com или big.friend.example.com. Если вместо example.com написать .example.com будут блокированы сам домен и все его поддомены.
acl BANNER dstdomain "/usr/local/etc/squid/url.banner"
Блокирование баннеров с помощью регулярных выражений regex (не pcre).
acl BANNER_REGEX url_regex "/usr/local/etc/squid/url.banner-regex"
Блокируем порно по тому же принципу как и баннеры
acl PORNO dstdomain "/usr/local/etc/squid/url.porno"
acl PORNO_REGEX url_regex "/usr/local/etc/squid/url.porno-regex"
Блокируем фреймы
acl BANNER_IFRAME dstdomain "/usr/local/etc/squid/url.banner.iframe"
acl BANNER_IFRAME_REGEX url_regex "/usr/local/etc/squid/url.banner.iframe-regex"
Применение запретов. Приведенные ниже правила http_access deny размещаются ДО разрешающих правил http_access allow.
http_access deny !WHITELIST BANNER
http_access deny !WHITELIST BANNER_REGEX
http_access deny !WHITELIST BANNER_IFRAME
http_access deny !WHITELIST BANNER_IFRAME_REGEX
http_access deny !WHITELIST PORNO
http_access deny !WHITELIST PORNO_REGEX
Блокируем соединения CONNECT, на всякий случай.
http_access deny CONNECT !WHITELIST BANNER
http_access deny CONNECT !WHITELIST BANNER_REGEX
http_access deny CONNECT !WHITELIST BANNER_IFRAME
http_access deny CONNECT !WHITELIST BANNER_IFRAME_REGEX
http_access deny CONNECT !WHITELIST PORNO
http_access deny CONNECT !WHITELIST PORNO_REGEX
И сами предупреждения, etc.
deny_info http://192.168.0.9/null.gif BANNER
deny_info http://192.168.0.9/null.gif CONNECT BANNER
deny_info http://192.168.0.9/null.gif BANNER_REGEX
deny_info http://192.168.0.9/null.gif CONNECT BANNER_REGEX
deny_info http://192.168.0.9/null.html BANNER_IFRAME
deny_info http://192.168.0.9/null.html BANNER_IFRAME_REGEX
deny_info http://192.168.0.9/null.html CONNECT BANNER_IFRAME
deny_info http://192.168.0.9/null.html CONNECT BANNER_IFRAME_REGEX
deny_info http://192.168.0.9/no-porno.gif PORNO
deny_info http://192.168.0.9/no-porno.gif CONNECT PORNO
deny_info http://192.168.0.9/no-porno.gif PORNO_REGEX
deny_info http://192.168.0.9/no-porno.gif CONNECT PORNO_REGEX
Теперь создаем и заполняем заявленные в конфиге файлы:
• /usr/local/etc/squid/url.whitelist
192.168.0.9
internal-server.local
• /usr/local/etc/squid/url.banner
.ad.adriver.ru
pics.rbc.ru
.ad.membrana.ru
bs.yandex.ru
pics.imho.ru
body.imho.ru
content.medialand.ru
.spylog.com
counter.yadro.ru
.advideo.bb.ru
.tns-counter.ru
• /usr/local/etc/squid/url.banner-regex
^http://r\.mail\.ru/(cl)?b[[:digit:]]+
^http://images\.rambler\.ru/upl/
/banners?[[:digit:]]*[x?/\.]
[[:<:]]hit[[:digit:]]+\.hotlog\.ru
/(count(er)?|cnt|hit)[[:digit:]]*[\.?]
/[aA]d(v(erts?)?|s)?[[:digit:]]*[?/\.]
^http://(www\.)?sunradio\.ru/upload/bx/
^http://(www\.)?nnm\.ru/ban/
^http://(www\.)?java2phone\.ru/pict/b
^http://([[:alpha:]]+[[:digit:]]*\.)+bigmir\.net
^http://[[:alpha:]]+[[:digit:]]*\.[[:digit:]]+mdn\.net/viewad/
^http://(www\.)?nasvyazi\.ru/img/banner_
^http://(www\.)?games\.ru/b/
^http://(www\.)?computerra\.ru/upload/bx/
^http://(www\.)?finbs\.ru/Upload/
^http://(www\.)?torrents\.ru/forum/bn/
^http://(www\.)?powerclip\.ru/baner/
^http://(www\.)?nnm\.ru/rec/[[:digit:]]+/banner
^http://[[:alpha:]-]+\.nnm\.ru/rec/[[:digit:]]+/
^http://i\.ru-board\.com/temp/
^http://adserv\.top500\.org/b/
^http://([[:alpha:]-]+\.)+traf\.spb\.ru/(upload|b)/
^http://([[:alpha:]-]+\.)*inf\.by/i/b/
^http://(www\.)?gzt\.ru/files/
^http://([[:alnum:]]+\.)*ru-board\.com/board/temp/
^http://(www\.)?rb\.ru/img/content/ushki/
• /usr/local/etc/squid/url.banner.iframe
clck.yandex.ru
.engine.awaps.net
.begun.ru
.adv.aport.ru
.tr.1big.ru
• /usr/local/etc/squid/url.banner.iframe-regex
/iframe/
[[:<:]]pagead[[:digit:]]+\.googlesyndication\.com
• /usr/local/etc/squid/url.porno
.porndiller.com
.meatmembers.com
.xvideos.com
.livesexlist.com
.brothasfuckteens.com
.nexxx.com
.creamed-whores.com
.juggmovieplanet.com
• /usr/local/etc/squid/url.porno-regex
porno|xxx|adult
После внесения изменений перезагрузите прокси-сервер:
# squid -k reconfigure

понедельник, 8 октября 2007 г.

Компилирование модулей ядра FreeBSD

Практически любой системный администратор, который сталкивался с FreeBSD, компилировал ядро под себя, выбрасывая оттуда лишние "детали" или вставляя недостающие. Между тем выброшенная из ядра "деталька" никуда не девается и при повторной компиляции превращается в модуль (за редким исключением), который всегда можно подгрузить.
Бороться с этим можно с помощью опций в файле make.conf:
# не компилировать все модули

NO_MODULES="YES"
# компилировать только указанные модули
# названия модулей пишутся через пробел
MODULES_OVERRIDE=acpi ipfw
# компилировать все модули, за исключением указанных

WITHOUT_MODULES=pf ntfs_iconv

четверг, 4 октября 2007 г.

Быстрое создание jail-машины в FreeBSD

Нам понадобится первый установочный диск FreeBSD 6.2 и немного свободного времени. Предполагается что наша jail-машина будет размещена в директории /var/jail.
Список действий:
1. Создать директорию /var/jail/machine для jail-машины;
2. Смонтировать установочный диск и распаковать базовые файлы в директорию jail-машины:
# mount /cdrom
для bash:
# DESTDIR=/var/jail/machine /cdrom/6.2-RELEASE/base/install.sh
для csh:
# env DESTDIR=/var/jail/machine /cdrom/6.2-RELEASE/base/install.sh
3. Создать пустой файл /var/jail/machine/etc/fstab:
# touch /var/jail/machine/etc/fstab
4. Создать файл /var/jail/machine/etc/rc.conf со следующим содержанием:
# Запускаем sshd
sshd_enable="YES"
sendmail_enable="NONE"
syslogd_flags="-ss"
rpcbind_enable="NO"
network_interfaces=""
5. Теперь требуется создать непривилегированного пользователя и изменить пароль пользователя root.
Входим в каталог jail-машины
# chroot /var/jail/machine /bin/csh
Создаем пользователя
# adduser
Меняем пароль пользователя root
# passwd
# exit
6. В файл /etc/rc.conf основной системы добавить:
# Разрешаем запуск jail-машин
jail_enable="YES"
# Запрещаем им менять свое имя
jail_set_hostname_allow="NO"
# Перечисляем jail-машины в системе.
jail_list="machine"

# Jail-машина "machine"
# Корневая директория
jail_machine_rootdir="/var/jail/machine"
# Имя
jail_machine_hostname="machine.local"
# IP-адрес
jail_machine_ip="192.168.0.10"
# На какой сетевой интерфейс будет цепляться jail-машина
jail_machine_interface="ed0"
# монтируем файловую систему devfs внутри jail-машины.
jail_machine_devfs_enable="YES"
# Скрипты запуска и останова
jail_machine_exec_start="/bin/sh /etc/rc"
jail_machine_exec_stop="/bin/sh /etc/rc.shutdown"
7. Кроме того требуется все запускаемые сервисы основной системы привязать к его ip-адресам (не должны слушаться порты на ip-адресах jail-машин).
Например, в rc.conf:
# Супер-сервер inetd
inetd_enable="YES"
# Слушает порт только на 192.168.0.1
inetd_flags="-wW -a 192.168.0.1"
# Syslogd
syslogd_enable="YES"
# Не слушать порты
syslogd_flags="-ss"
8. Запускаем созданную jail-машину:
# /etc/rc.d/jail start

среда, 3 октября 2007 г.

Отключение сообщений об arp-пакетах не на том сетевом интерфейсе

Когда в сервер, выполняющий роль шлюза (freebsd 6.2), вставил вторую сетевую карту (подключились ко второму провайдеру по адсл) и пустил соответствующий трафик к адсл-модему через локальную сеть (было проблематично протягивать дополнительный кабель до сервера и его просто воткнули в свободный порт коммутатора) в /var/log/messages и в dmesg начали сыпаться сообщения вроде "Oct 5 12:10:05 firewall kernel: arp: 192.168.0.4 is on xl0 but got reply from 00:0a:01:fc:16:d7 on xl1".
Некоторое время мирился с их существованием, но потом все-таки решил избавиться от них. Решение состоит в том, что нужно изменить параметр sysctl:
# sysctl net.link.ether.inet.log_arp_wrong_iface=0

Для того, чтобы каждый раз не вводить с консоли просто добавьте эту строку в sysctl.conf:
net.link.ether.inet.log_arp_wrong_iface=0