пятница, 28 декабря 2007 г.

Пиарю Firefox :)

Добавил в блог кнопку со ссылкой на новый сайт www.spreadfirefox.com. Пиарю свой любимый браузер Firefox :)

четверг, 20 декабря 2007 г.

Монтирование разделов при запуске Jail

В rc.conf есть два интересных параметра, позволяющих при запуске jail монтировать необходимые разделы:
jail_<jail_name>_mount_enable="YES"
jail_<jail_name>_fstab="/path/to/fstab/file"

jail_<jail_name>_mount_enable разрешает монтировать разделы по списку в файле, указанного в jail_<jail_name>_fstab.
Формат файла идентичен формату /etc/fstab. Все пути к монтируемым точкам внутри jail задаются относительно корня основной системы.

Монтирование можно применить для усиления защиты jail при их взломе. Например, в случае если система в jail будет скомпрометирована, то злоумышленник не сможет подменить системные утилиты т.к. папки /usr/bin или /usr/lib примонтированы только чтения и не могут быть изменены.

Для этого нужно:
1. Создать папки:
▪ для jail-машин /opt/jail
▪ папку для конфигурационных файлов /opt/jail/conf
▪ папку Base для базового jail /opt/jail/Base

2. В папке Base создать базовый jail и настроить его (Например установить дополнительные и настроить пакеты perl5/sudo/etc, прописать DNS сервер).

3. Потом воспользоваться приведенным ниже скриптом new-jail.conf, предварительно изменив переменные J и JAIL_EXAMPLE (если у вас другое размещение jail).
Запуск скрипта от имени пользователя root:
# JAIL=New-jail-name ./new-jail.sh
Скрипт создает точки монтирования папок и копирует etc, var и usr/local из базового скрипта в новый jail. Потом в /opt/jail/conf создается файл в формате fstab и производится попытка записи параметров jail в /etc/rc.conf. Если /etc/rc.conf недоступен для записи, скрипт выводит список параметров.

Скрипт new-jail.conf:

#!/bin/sh
J="/opt/jail"
JAIL=${JAIL:?'$JAIL is not set'}
JAIL_LOWER="`echo $JAIL | /usr/bin/tr A-Z a-z`"
JAILDIR="$J/$JAIL"
JAIL_EXAMPLE="$J/Base"
DIR_EMPTY="dev proc media cdrom mnt boot rescue root usr usr/home usr/src usr/ports"
DIR_MOUNT="bin lib libexec sbin usr/bin usr/include usr/lib usr/libdata usr/libexec usr/sbin usr/share"
#Jail directory
echo -n "Checking $JAILDIR directory... "
if [ ! -e $JAILDIR ];
then {
/bin/mkdir -p $JAILDIR;
echo "created.";
}
else echo "already exists.";
fi;
# Empty directories
echo -n "Creating empty directories: $DIR_EMPTY... "
for dir in $DIR_EMPTY; do /bin/mkdir -p $JAILDIR/$dir; done;
echo "ok.";
# Mount points
echo -n "Creating mount points: $DIR_MOUNT... "
/usr/bin/touch $J/conf/$JAIL.fstab
echo "# Generated on `/bin/date`" >> $J/conf/$JAIL.fstab
for dir in $DIR_MOUNT;
do {
/bin/mkdir -p $JAILDIR/$dir;
printf "$JAIL_EXAMPLE/$dir\t$JAILDIR/$dir\tnullfs\tro\t0\t0\n" >> $J/conf/$JAIL.fstab;
} done;
echo "ok.";
echo "The fstab file created: $J/conf/$JAIL.fstab"
# Symbolic links
/bin/ln -s usr/home $JAILDIR/home
# Temporary directory
echo -n "Creating tmp... "
/bin/mkdir $JAILDIR/tmp
/bin/chmod ugo=rwx $JAILDIR/tmp
echo "ok.";
# Directories from $JAIL_EXAMPLE
echo -n "Copying files... "
/bin/cp -pR $JAIL_EXAMPLE/etc $JAILDIR/
/bin/cp -pR $JAIL_EXAMPLE/var $JAILDIR/
/bin/cp -pR $JAIL_EXAMPLE/usr/local $JAILDIR/usr/

/bin/rm -f $JAILDIR/var/{tmp,run}/*
for i in `/usr/bin/find -E $JAILDIR/var/log -type f \
-and -regex ".*\.[0-9]+(\..*|$)" -print`;
do /bin/rm -f $i; done;
for i in `/usr/bin/find $JAILDIR/var/log -type f -print`;
do /usr/bin/touch /dev/null > $i; done;

echo "ok.";
echo
echo The jail \'$JAIL\' created.
echo
if [ -w /etc/rc.conf ];
then {
/usr/bin/sed -Ei .bck '/^[\s]*jail_list=/s#jail_list="([^"]*)"#jail_list="\1 '${JAIL_LOWER}'"#g' /etc/rc.conf
echo >> /etc/rc.conf
echo \#\# ${JAIL} >> /etc/rc.conf
echo jail_${JAIL_LOWER}_rootdir=\"$J/${JAIL}\" \
>> /etc/rc.conf
echo jail_${JAIL_LOWER}_hostname=\"${JAIL}.local\" \
>> /etc/rc.conf
echo \# Don\'t forget add ip-address in \'.local\' domain zone \
>> /etc/rc.conf
echo jail_${JAIL_LOWER}_ip=\"127.0.0.xxx\" \
>> /etc/rc.conf
echo jail_${JAIL_LOWER}_interface=\"lo0\" \
>> /etc/rc.conf
echo jail_${JAIL_LOWER}_devfs_enable=\"YES\" \
>> /etc/rc.conf
echo jail_${JAIL_LOWER}_exec_start=\"/bin/sh /etc/rc\" \
>> /etc/rc.conf
echo jail_${JAIL_LOWER}_exec_stop=\"/bin/sh /etc/rc.shutdown\" \
>> /etc/rc.conf
echo jail_${JAIL_LOWER}_mount_enable=\"YES\" \
>> /etc/rc.conf
echo jail_${JAIL_LOWER}_fstab=\"$J/conf/${JAIL}.fstab\" \
>> /etc/rc.conf
}
else echo "Put in /etc/rc.conf:";
fi;
echo jail_${JAIL_LOWER}_rootdir=\"$J/${JAIL}\"
echo jail_${JAIL_LOWER}_hostname=\"${JAIL}.local\"
echo \# Don\'t forget add ip-address of jail in \'.local\' domain zone
echo jail_${JAIL_LOWER}_ip=\"127.0.0.xxx\"
echo jail_${JAIL_LOWER}_interface=\"lo0\"
echo jail_${JAIL_LOWER}_devfs_enable=\"YES\"
echo jail_${JAIL_LOWER}_exec_start=\"/bin/sh /etc/rc\"
echo jail_${JAIL_LOWER}_exec_stop=\"/bin/sh /etc/rc.shutdown\"
echo jail_${JAIL_LOWER}_mount_enable=\"YES\"
echo jail_${JAIL_LOWER}_fstab=\"$J/conf/${JAIL}.fstab\"

вторник, 18 декабря 2007 г.

CURL: Хитрости нашего пруда

< поскипан нудный и долгий рассказ про взаимоотношения провайдеров нашего городка >

У локальных (городских) хранилищ файлов все несколько попроще, чем например в http://www.depositfiles.com, и их вполне можно заюзать в несложных shell-скриптах. Например чтобы одной командой кинуть файл в хранилище я сделал такой алиас (shell: tcsh):

$ cat >> ~/.tcshrc
alias lg_up sh -c "'"'file="\!*"; \
[ -z "$file" ] && exit; \
/usr/local/bin/curl -F userfile=@$file -F action=1 -F \
agreelicense=checkbox http://share.service.ru/upload.php | \
grep -oE "http://share\.service\.ru/[0-9]+" | head -n 1'"'"

Если файл успешно закачался - выдается ссылка на него.
Пример использования: lg_up <имя_файла>

Можно пойти еще дальше и написать скрипт, который по заранее созданному списку выкачивает файлы с интернета и кидает их в хранилище. А пользователю отправляется письмо со ссылками на файлы в хранилище. Примерно так (download.sh)


#!/bin/bash

wget=$(which wget);
curl=$(which curl);
if [ -z "$wget" ] || [ -z "$curl" ]; then exit 1; fi;

curl_path='http://share.server.ru/upload.php'

if [ -f "$1" ];
then {
if [ ! -z "$2" ];
then {
limit="--limit-rate=$2";
} fi;
list=$(< $1);
pwd=$(pwd);
IFS="
";

for i in $list;
do {
echo "Качаем файл по адресу: $i";
file="$(echo -n "$i" | grep -oE '[^/]+$')";
if [ ! -z "$file" ];
then {
$wget --tries=3 -nv $limit -O $pwd/"$file" "$i"
if [ -f "$pwd/$file" ] && [ -s "$pwd/$file" ];
then {
url=`$curl -F userfile=@$pwd/$file -F action=1 \
-F agreelicense=checkbox $curl_path | \
grep -oE 'http://share\.server\.ru/[0-9]+' | \
head -n 1`;

echo "Файл $file доступен по адресу: $url";
};
else {
echo "Файл $file не существует или пуст";
} fi;
};
else {
echo "Неверное имя файла";
} fi;
echo;
} done;
};
else {
echo "Не задан файл со списком";
} fi;


А используется так: ./download.sh <файл со списком> | mail -s 'Downloaded files' my@mail.ru

среда, 12 декабря 2007 г.

Как распрощаться с Windows?

Все гениальное - просто. Как именно? Смотрите тут :)

1 января 2008 года вступит в силу часть IV Гражданского кодекса Российской Федерации

С 1 января 2008 года, все архивы музыки, фильмов и другого медийного контента на который распространяется «Закон об авторских и смежных правах», будут вне закона - если только их владельцы не купят специальную лицензию. Подробнее тут и тут.

Что народ думает по этому поводу? Мне лично пока фиолетово: фильмы не смотрю и музыку не слушаю.

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

Статья про софтварные патенты

Написано на простом и понятном языке. Смотреть тут: http://docs.google.com/View?docid=df35c2hq_18cp4d53dq (автор: Зуев Федор Леонидович)

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

Российская система распознавания текстов CuneiForm станет открытой

Хочется чтобы нас всегда с утра так радовали. В www.cybersecurity.ru опубликована новость о грядущем открытии компанией Cognitive Technologies исходных кодов своей некогда популярной программы CuneiForm. Становится вдвойне радостно если учесть, что сейчас практически нет опенсурцной альтернативы проприетарным программам для распознавания текстов (с поддержкой русского языка).
Хочется надеяться, что 12 декабря новость подтвердится и нам больше не придется пользоваться варезной и падучей в Wine программой FineReader.

Не допустим позора! Скажем нет OOXML!

6 декабря сего года на один из моих почтовых ящиков пришло письмо такого содержания
«Dear Petr Sleptsov,
You signed the <no>OOXML petition, a movement backed now by more than 70.000 supporters worldwide. Our effort to influence the OOXML (Office Open XML) standardization process has been an astonishing success so far. We aim for at least 100.000 signatures in February when the Geneva Ballot Resolution Meeting (BRM) will convene with the aim to resolve comments.

Microsoft is trying by all means to get its "standard" adopted without substantial changes despite of its thousands of officially reported technical flaws and the pre-existence of ISO 26300:2006 (OpenDocument, ODF) as the most appropriate international standard for the representation of office documents.

By next Tuesday Dec 11 2007 delegates from your National Standards Body GOST who will participate in the BRM have to be announced to ISO. At least Portugal and Ireland will be represented by Microsoft. In many other countries, we know that Microsoft gold partners are proposing themselves as heads of national delegations. Many of them will prevail if we do not take action.

Will you let Microsoft represent your country at Geneva and decide the future of OOXML?

You can make a difference and call now GOST at +7-495-2364044 and help us to find out:

a. Who will represent GOST on DIS 29500 at the Ballot Resolution Meeting in Geneva?
b. When will the decision on delegates be made and if GOST is aware of the Dec 11 deadline?
c. Does your national delegates for the BRM are independent enough from Microsoft?
d. Does the responsible Committee of GOST for DIS 29500 work on resolution proposals for all the 3500 comments tabled or - if at all - only for the national comments that they submitted?

Please report your findings by replying to this email, we will update this page with the members of each national delegation:

http://www.noooxml.org/brm

More things that you can do to help our effort against this broken standard proposal:

1. Join our mailing list and get in touch with many other activists: http://lists.ffii.org/mailman/listinfo/noooxml-club
2. Become a member of FFII, the worldwide association leading the <no>OOXML campaign: http://action.ffii.org/member_application
3. Become a member of DIGISTAN, the organization for the promotion of true digital open standards worldwide; please indicate your interests to: members@digistan.org
4. Blog about OOXML which shapes the public debate; blogging has been instrumental to our success in Sweden for example;
5. support our campaign work with financial means:
http://www.noooxml.org/donations

Best regards,

--
Benjamin Henrion <bhenrion@ffii.org>
<no>OOXML Campaign leader»

что можно перевести так:
«
С двадцать пятое по двадцать девятое декабря в Женеве будет проходить "BRM" - Ballot Resolution Meeting, встреча делегаций восьмидесяти семи стран, которые принимали участие в голосовании об OOXML второго сентября 2007 года. До одиннадцатого декабря страны должны представить информацию о составе своих делегаций: имена главы делегации и двух его помощников.

Сегодня письмо с риторическим вопросом "Можете ли вы позволить Microsoft представлять Россию на голосовании о будущем OOXML?" получили те, кто подписывал петицию против OOXML. Бенджамин Хэнрион (Benjamin Henrion), чьим именем подписана рассылка, призывает небезразличных не допустить повторения сентябрьского позора, позвонить в Российское Федеральное агенство по техническому урегулированию и метрологии (в письме даже указан номер: +7-495-2364044), с тем, чтобы уточнить следующие моменты:
• Кто будет представлять Россию на февральском BRM в Женеве?
• Когда будет вынесено решение о составе делегации, не обеспокоено ли ФАТУиМ близостью дэдлайна для этого решения - одиннадцатого декабря?
• В достаточной ли мере делегация окажется независимой от Microsoft?
• Отвечает ли ФАТУиМ за то, что им были рассмотрены все три с половиной тысячи комментариев к формату, написанных другими странами при первом голосовании?
» (текст перевода: http://www.linux.org.ru/view-message.jsp?msgid=2323188)

В общем нас призывают не допустить сентябрьского позора и знать в лицо тех, кого в случае повторного позора нужно повесить на доске позора (извиняюсь за тавтологию).

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

Samba внутри jail + MS AD

На сервере был поднят веб-сервер с сайтом компании и поддерживать его поручили мне. Так как мне очень не хотелось перегонять файлы по FTP туда и обратно, решил поднять сервер Samba и через его шары рулить файлами сайта. И дизайнерам будет проще править дизайн. Чтобы не засорять систему поднял jail для Samba.

Порядок действий внутри созданного jail:
1. cd /usr/ports/net/samba3
2. в make config отметил:

[X] LDAP         With LDAP support
[X] ADS With Active Directory support
[X] WINBIND With WinBIND support
[X] UTMP With UTMP accounting support
[X] MSDFS With MSDFS support
[X] POPT With system-wide POPT library

3. И далее установил командой make install.
4. Настроил Kerberos5:
# cat > /etc/krb5.conf
[libdefaults]
default_realm = MY-DOMAIN.LOCAL
dns_lookup_realm = false
dns_lookup_kdc = false

[realms]
MY-DOMAIN.LOCAL = {
kdc = MY-DOMAIN.LOCAL
admin_server = MY-DOMAIN.LOCAL
kpasswd_server = 192.168.0.1
default_domain = my-domain.local
}

[domain_realm]
.my-domain.local = MY-DOMAIN.LOCAL

[logging]
default = FILE:/var/log/kerberos/krb5libs.log
kdc = FILE:/var/log/kerberos/krb5kdc.log
admin_server = FILE:/var/log/kerberos/kadmind.log
Где my-domain.local домен MS Active Directory.
Проверяем:
# kinit root
root@MY-DOMAIN.LOCAL's Password:
kinit: NOTICE: ticket renewable lifetime is 1 week

Если выходит другое сообщение - проверяем файл конфигурации.

4. Файл конфигурации Samba:
# cat > /usr/local/etc/smb.conf
[global]
# Имя домена
workgroup = MY-DOMAIN
realm = MY-DOMAIN.LOCAL
server string = Samba Server

# Машина в Active Directory
security = ads
hosts allow = 192.168.0.
# Принтеры нам не нужны
load printers = no
show add printer wizard = no

log file = /var/log/samba/log.%m
# Контроллеры домена
password server = pdc.my-domain.local bdc.my-domain.local

# Имя samba сервера
netbios name = FILESRV

# IP-адрес jail
bind interfaces only = yes
interfaces = 192.168.0.23/24

auth methods = winbind
idmap uid = 10000-20000
idmap gid = 10000-20000
winbind enum users = Yes
winbind enum groups = Yes
winbind use default domain = Yes
winbind refresh tickets = Yes
case sensitive = No
hide unreadable = Yes
socket options = TCP_NODELAY
dns proxy = no
display charset = koi8-r
unix charset = koi8-r
dos charset = cp866
[homes]
comment = Home Directories
browseable = no
writable = yes
[printers]
comment = All Printers
path = /var/spool/samba
browseable = no
guest ok = no
writable = no
printable = yes

4. Правим /etc/hosts:
192.168.0.23 FILESRV FILESRV.MY-DOMAIN.LOCAL
Иначе машина не войдет в домен.

5. Правим /etc/resolv.conf:
search my-domain.local
nameserver 192.168.0.xxx

Где 192.168.0.xxx ip-адрес DNS Active Directory.

6. Правим /etc/nsswitch.conf:
« ... skip ... »
group: files winbind
passwd: files winbind

« ... skip ... »

7. Вгоняем машину в домен:
# net ads join -U root
Если машина вошла в домен, на всякий случай проверяем:
# wbinfo -u
« ... Список пользователей домена ... »
# wbinfo -g
« ... Список групп домена ... »

8. Запускаем Samba:
# /usr/local/etc/rc.d/samba start

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

Найдена критическая уязвимость всех версий Windows

Я просто не мог пройти мимо. Вот выдержка из текста новости CNews: «Теоретически, один человек мог взять под контроль ПК по всему миру - украсть данные, пароли, управлять интернет-траффиком, распространять спам или вирусы. Уязвимость демонстрировалась Бо Батлером (Beau Butler) на конференции по ИБ Kiwicon в Новой Зеландии на прошлой неделе...»
Только подозреваю что нашли «не баг, а фичу» - универсальный черный ход для САМИЗНАЕТЕКОГО. Подозрение особенно сильно после августовских событий с несанкционированным обновлением Windows. После признания этого факта потом Microsoft отмазывалась тем, что в скрытых обновлениях Windows виновата Live OneCare. Но чуть ранее пела совсем другое, что-то про обновления для самой Windows Update, без которых эта служба не могла жить. И уж совсем весело, если узнать что данный баг/фича не затрагивает компьютеры в далекой Северной Америке (попросту говоря в США).

воскресенье, 25 ноября 2007 г.

Сброс буфера системных сообщений FreeBSD

Сбросить буфер системных сообщений (вывод команды dmesg) можно с помощью sysctl:
# sysctl kern.msgbuf_clear=0

пятница, 23 ноября 2007 г.

Подгонка всплывающего окна под размер изображения

Как подогнать размер всплывающих окон браузеров под размер показываемого изображения? Сегодня задался именно таким вопросом и наклепал работающий в Mozilla Firefox и в Internet Explorer скрипт.

Я бы хотел отметить один нюанс, который нужно учесть для работоспособности скрипта в Internet Explorer. Если задать DOCTYPE отличный от "<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN>" то document.body.ClientHeight возвращает размер изображения вместо размера окна браузера, в результате высота окна не меняется. Функции img_popup() передается URL изображения.

function img_popup (image_path) {
var ph = window.open("", "popup_img", "location=0,toolbar=0,resize=0,status=0,scrollbars=0");
ph.document.write('<'+'!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"'+'>');
ph.document.write('<'+'html'+'>');
ph.document.write('<'+'head'+'><'+'title'+'><'+'/title'+'>');
ph.document.write('<'+'style type="text/css"'+'>body { text-align: center; margin: 0px; padding: 0px; }<'+'/style'+'>');
ph.document.write('<'+'script language="javascript" type="text/javascript"'+'>');
ph.document.write('window.onload = function ()');
ph.document.write('{ var a_img = document.getElementById("auto_img");');
ph.document.write('var NS = (navigator.appName == "Netscape") ? true : false;');
ph.document.write(
'if (a_img && NS) '
+'{ window.resizeTo(a_img.width + window.outerWidth - window.innerWidth, '
+'a_img.height + window.outerHeight - window.innerHeight); }'
);
ph.document.write(
'else { '
+ 'var x_ = a_img.width - document.body.clientWidth;'
+ 'var y_ = a_img.height - document.body.clientHeight;'
+ 'window.resizeBy(x_, y_);'
+ '}}'
);
ph.document.write('<'+'/script'+'><'+'/head'+'>');
ph.document.write(
'<'+'body'+'><'+'img id="auto_img" '
+'src=' + image_path + '" '
+'border="0" align="center" /'+'><'+'/body'+'><'+'/html'+'>'
);
ph.document.close();
}

Ссылки пишутся примерно так:
<a href="/path/to/big_image.jpg" onClick="img_popup('/path/to/big_image.jpg'); return false;"><img src="/path/to/thumbnail.jpg" border="0"/></a>

вторник, 20 ноября 2007 г.

sftp

Раньше для закачивания файлов на сервер изощрялся как мог: ftp на сервере поднимал; на веб-сервере каком-нибудь выкладывал, чтоб потом оттуда скачать. Про SFTP (secured file transfer protocol) я конечно знал, но по необъяснимой мне причине ниразу им не пользовался.
Сегодня таки вспомнил о нем и решил попробовать. Оказалось что им просто пользоваться - почти как FTP. Ничего дополнительно на сервер ставить не нужно, т.к. он работает через SSH-сервер системы.

Синтаксис запуска: $ sftp -h
usage: sftp [-1Cv] [-B buffer_size] [-b batchfile] [-F ssh_config]
[-o ssh_option] [-P sftp_server_path] [-R num_requests]
[-S program] [-s subsystem | sftp_server] host
sftp [[user@]host[:file [file]]]
sftp [[user@]host[:dir[/]]]
sftp -b batchfile [user@]host

Команды sftp:
sftp> ls - смотреть список файлов на удаленном сервере.
sftp> lls - смотреть локальный список файлов.
sftp> lcd - изменить текущий локальный каталог.
sftp> cd - изменить текущий каталог на удаленном сервере.
sftp> put - положить файл на удаленный сервер.
sftp> get - скачать файл с удаленного сервера.
sftp> help - помощь по командам.

Из Windows доступ к серверу по
sftp можно получить посредством программы EngInSite DataFreeway.

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

Копирование писем в Exim.

Перейдите в секцию ROUTERS файла конфигурации /usr/local/etc/exim/configure и перед роутером dnslookup добавьте:
archive_all:
driver = accept
transport = tr_archive_all
unseen

В секции TRANSPORTS добавьте:
tr_archive_all:
driver = appendfile
maildir_format
mode = 0660
mode_fail_narrower = false
envelope_to_add = true
return_path_add = true
directory = /var/mail/archive@domain.com

Перезагрузите Exim. Теперь вся входящая и исходящая почта будет сохраняться в директории
/var/mail/archive@domain.com.

пятница, 2 ноября 2007 г.

ASUS GigaX 1024P

На работе купили коммутатор ASUS GigaX 1024P (польстились на то, что он по описанию управляемый и в принципе недорогой - 4900 рублей). В итоге нас ожидало несколько сюрпризов:
1. В идущей с коммутатором книжке отсутствовал даже намек на управляемость этого девайса.
2. Путем долгого гугления выяснил что коммутатор управляется неким ПО Centralized Network Managment. На сайте производителя (http://www.asus.com/) сперва не нашел никакого упоминания этого ПО. Потратив час на поиски, таки нашел (причем только под нелюбимую мною платформу Windows) и установил.
3. При попытке соединиться с коммутатором тот запросил пароль, который я естественно не знаю. Гугл тоже не знал. Зато узнал как сбросить пароль, только не решился на такой шаг. Решил для начала попробовать примеры, которые выдает CNM при попытке авторизоваться с пустым паролем (3112, 2379, A123) и, к моему удивлению, один подошел.

среда, 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