четверг, 24 ноября 2011 г.

Настройка квот в Dovecot и Postfix с хранением счётчиков и правил в словаре MySQL

Уже третий день подряд мучился с настройкой квот в Dovecot прямо на работающем сервере. Мучился очень аккуратно и имея в запасе бэкапы рабочих конфигураций на начало каждого дня.

Хранение счётчиков квот в MySQL настроил быстро, формирование правил квот по данным из MySQL тоже настроил быстро. Однако после настройки текущие значения счётчиков квот становились отрицательными и со временем только уменьшались. Я сразу подумал, что POP3-сервер обновляет счётчики квот, т.к. его задача лишь забирать почту из ящика, а вот LDA (агент локальной доставки) - не обновляет, т.к. именно он кладёт почту в ящики и должен увеличивать значения счётчиков.

В конечном итоге оказалось, что вместо LDA delivery из Dovecot по-прежнему используется LDA virtual из Postfix. Произошло это потому что действие настройки virtual_transport = dovecot перекрывается настройкой transport_maps = mysql:/etc/postfix/sql/transport.cf, где для тестируемого домена был настроен транспорт virtual. Здесь можно поблагодарить Вьетце Венема за отличную документацию - это я прочитал прямо в man 5 postconf. Dovecot практически не документирован, а вики-страницы с Howto по настройке различных фишек Dovecot за документацию я не считаю.

После исправления значения транспорта в базе данных возникло ещё несколько проблем:
1. В настройках LDA Dovecot не был указан параметр postmaster_address,
2. Не был настроен сокет /var/run/dovecot/auth-master,
3. Имена каталогов, в которые LDA delivery из Dovecot складывал почту, были строчными, а имена существующих каталогов почтовых ящиков, в которые складывал почту LDA virtual из Postfix, содержали символы в разном регистре.

Проблемы решались следующим образом:
1. Указан параметр postmaster_address,
2. Прописана секция master в секции socket listen из секции auth default,
3.1. Добавлены буквы L в настройке mail_location, которые указывают принудительно использовать нижний регистр для каталогов почтовых ящиков.
3.2. Использована команда rename 'y/A-Z/a-z/' * для того, чтобы переименовать каталоги почтовых ящиков. Некоторые каталоги, из которых уже успели попробовать забрать почту, пришлось обрабатывать вручную - нужно было перенести письма из старых каталогов в новые, а старые затем удалить.

Итоговые конфигурационные файлы Dovecot помещаю сюда, чтобы в следующий раз не наступать на те же грабли:
protocols = pop3
disable_plaintext_auth = no
log_timestamp = "%Y-%m-%d %H:%M:%S "
mail_location = maildir:/var/mail/virtual/%Ld/%Ln
first_valid_uid = 999
first_valid_gid = 999

dict {
  quotadict = mysql:/etc/dovecot/dovecot-dict-mysql.conf
}
plugin {
  quota = dict:user::proxy::quotadict
  # Квота по умолчанию - объём ящика 1 гигабайт,
  # не более 1000 писем в ящике
  # Эта квота заменяется квотой, найденной в БД
  quota_rule = *:storage=1G:messages=1000
}
protocol pop3 {
  mail_plugins = quota
  mail_executable = /etc/dovecot/pop-update-lastlog.sh
}
protocol lda {
  # Ящик администратора почтовой системы
  postmaster_address = postadmin@domain.tld
  mail_plugins = quota
}

# Домен по умолчанию для пользователей, пытающихся
# аутентифицироваться в Dovecot без указания домена
auth_default_realm = domain.tld

auth default {
  mechanisms = plain login
  passdb sql {
    args = /etc/dovecot/dovecot-mysql.conf
  }
  userdb sql {
    args = /etc/dovecot/dovecot-mysql.conf
  }
  socket listen {
    client {
      path = /var/spool/postfix/private/auth
      mode = 0660
      user = postfix
      group = postfix
    }
    master {
      path = /var/run/dovecot/auth-master
      mode = 0660
      user = vmail
      group = vmail
    }
  }
}
Уже знакомый скрипт /etc/dovecot/pop-before-smtp.sh для аутентификации POP before SMTP:
#!/bin/sh

mysql -uuser -ppassword -h127.0.0.1 mail <<END
UPDATE users SET lasttime = NOW(), lastip='$IP' WHERE login = '$USER';
END
exec /usr/lib/dovecot/pop3 "$@"
Файл настроек для хранения счётчиков квот в БД MySQL /etc/dovecot/dovecot-dict-mysq.conf:
connect = host=127.0.0.1 dbname=mail user=user password=password
map {
  pattern = priv/quota/storage
  table = users
  username_field = login
  value_field = bytes
}
map {
  pattern = priv/quota/messages
  table = users
  username_field = login
  value_field = messages
}
Файл настроек для проверки учётных данных пользователя и его квот по таблице в БД MySQL /etc/dovecot/dovecot-mysql.conf:
driver = mysql
connect = host=127.0.0.1 dbname=mail user=user password=password
default_pass_scheme = CRYPT
password_query = SELECT password \
                 FROM users \
                 WHERE login = '%u'
user_query = SELECT CONCAT(SUBSTRING_INDEX(login, '@', -1), '/', SUBSTRING_INDEX(login, '@', 1), '/'), \
                    999 AS uid, \
                    999 AS gid, \
                    CONCAT('*:bytes=', max_bytes, ':messages=', max_messages) AS quota_rule \
             FROM users \
             WHERE login = '%u'
В настройки postfix добавлен LDA delivery из Dovecot, в файл /etc/postfix/master.cf добавлены две строчки:
dovecot unix - n n - - pipe
flags=DRhu user=vmail:vmail argv=/usr/lib/dovecot/deliver -f ${sender} -d ${recipient}
Столбцы со счётчиками и со значениями квот для пользователей добавлены с помощью четырёх SQL-запросов:
ALTER TABLE users ADD COLUMN bytes bigint default 0;
ALTER TABLE users ADD COLUMN messages integer default 0;
ALTER TABLE users ADD COLUMN max_bytes bigint default 1073741824;
ALTER TABLE users ADD COLUMN max_messages bigint default 1000;
Значения квот по умолчанию можете поменять на свои. Я поставил ограничения в 1 гигабайт на общий объём ящика и не более 1000 писем в одном почтовом ящике.

В таком виде Dovecot не будет принимать от Postfix письма для адресатов, превысивших квоту. Но такие письма будут просто попадать в очередь отложенных писем Postfix. Нужно же, чтобы письмо не занимало дисковое пространство ни в почтовом ящике получателя, ни в очереди отложенных писем, а отклонялось сразу же с соответствующим сообщением отправителю о том, что адресат превысил квоту.

Для этого нужно настроить проверку квот при приёме почты самим Postfix'ом. Для этого воспользуемся правилом check_recipient_access mysql:/etc/postfix/sql/quotas.cf, которое нужно поместить в том числе до правил permit_mynetworks и permit_sasl_authenticated. Если поместить его после этих двух проверок, то квоты получателя просто не будут проверяться, если отправитель аутентифицировался на почтовом сервере или он отправляет почту из доверенной сети.

Файл /etc/postfix/sql/quotas.cf для проверки квоты получателя:
user = user
password = password
dbname = mail
hosts = 127.0.0.1
query = SELECT '452 Mailbox is over quota'
        FROM users
        WHERE login = '%s'
          AND ((bytes >= max_bytes AND max_bytes > 0)
            OR (messages >= max_messages AND max_messages > 0))
О расширенных статусах REJECT я прочитал в man 5 access, а подходящий код статуса подобрал в RFC2821 на этой странице: http://tools.ietf.org/html/rfc2821.

В случае если квота по объёму или по количеству сообщений равна нулю, то этот SQL-запрос такую квоту не проверяет. Таким образом значения 0 в полях max_bytes или max_messages означают, что ограничение по этому параметру не действует.

При попытке отправить письмо на ящик, превысивший квоту, Outlook Express сообщает следующее:
Не удается отправить сообщение, поскольку сервер отказался принять адрес одного из получателей. В письме был указан адрес: 'user@domain.tld'. Тема 'test1', Учетная запись: 'mail', Сервер: 'domain.tld', Протокол: SMTP, Ответ сервера: '452 4.7.1 <user@domain.tld>: Recipient address rejected: Mailbox is over quota', Порт: 25, Защита (SSL): Нет, Ошибка сервера: 452, Код ошибки: 0x800CCC79

четверг, 17 ноября 2011 г.

Обновление времени последнего входа пользователя dovecot и авторизация POP before SMTP

Захотел сделать так, чтобы Dovecot, при подключении пользователя по протоколу POP3, отмечал в базе данных текущее время. Нужно это для того, чтобы определить, какими ящиками давно не пользуются. Нашёл такую вот страницу в wiki Dovecot: http://wiki.dovecot.org/PostLoginScripting.

Для начала нужно узнать текущее значение mail_executable. Для этого воспользуемся командой:
# dovecot -a | grep mail_executable
У меня это значение равно /usr/lib/dovecot/pop3. Именно это значение мы и заменим, так чтобы наш скрипт вызывался до этой программы, обновлял информацию в базе данных, а затем запускал первоначальную программу.

Скрипт /etc/dovecot/pop-update-lastlog.sh, обновляющий информацию в базе данных:
#!/bin/sh

mysql -uuser -ppassword -h127.0.0.1 mail <<END
UPDATE users SET lasttime = NOW(), lastip='$IP' WHERE login = '$USER';
END
exec /usr/lib/dovecot/pop3 "$@"
Установил на него права доступа чтобы простые пользователи не смогли узнать пароль от базы данных и чтобы этот скрипт мог выполняться:
# chmod +x,o= pop-update-lastlog.sh
Затем этот скрипт я прописал в /etc/dovecot.conf:
protocol pop3 {
  mail_executable = /etc/dovecot/pop-update-lastlog.sh
}
Затем добавил пару столбцов в базу данных (структура базы данных - самодельная, не взята от какого-либо веб-интерфейса администрирования):
$ mail -uuser -ppassword mail <<END
ALTER TABLE users ADD COLUMN lasttime datetime DEFAULT '1900-01-01 00:00:00';
ALTER TABLE users ADD COLUMN lastip varchar(32) DEFAULT '0.0.0.0';
END
И перезапустил dovecot:
# /etc/init.d/dovecot restart
В базе данных начали появляться отметки о времени последнего входа и об IP-адресе клиента, с которого входили последний раз.

Если у вас настроен также imap-сервер, вы можете создать для него похожий скрипт.

Дополнение от 18 ноября 2011 года. Информацию из таблиц можно использовать для авторизации POP before SMTP в Postfix (перед отправкой почты по SMTP нужно авторизоваться на POP-сервере).

В /etc/postfix/main.cf можно прописать следующее:
mynetworks = 127.0.0.1/8, mysql:/etc/postfix/sql/pop-before-smtp.cf
А в файле /etc/postfix/sql/pop-before-smtp.cf указать запрос и параметры подключения к базе данных:
user = user
password = password
dbname = mail
hosts = 127.0.0.1
query = SELECT DISTINCT lastip
        FROM users
        WHERE lastip = '%s'
          AND ADDTIME(lasttime, '0:1:0') > NOW()
Запрос возвращает IP-адрес только в том случае, если этот IP-адрес аутентифицировался на POP-сервере в течение последней минуты. В случае, если этот IP-адрес в течение последней минуты аутентифицировался на нескольких учётных записях POP-сервера, то возвращается только один IP-адрес.

Не забудьте защитить прописанные в файле пароли доступа к базе данных почтового сервера от обычных пользователей:
# chmod o= pop-before-smtp.cf
Попробовал - POP before SMTP действительно работает. Если с момента последнего подключения к POP серверу прошло не больше минуты, то почта отправляется. Если больше или ровно минута - то почта уже не уходит. Получилось такое вот, на мой взгляд, довольно изящное решение.

пятница, 11 ноября 2011 г.

Перенос Windows XP на другой диск средствами Linux

Для начала хочу предупредить, что это не точная инструкция как и что делать. Это описание ключевых моментов, для правильного применения которых нужно ещё приложить собственную голову. Если вы не уверены в своих силах, то лучше воспользуйтесь специализированными программами (Acronis True Image или Norton Ghost), а не этим способом, который описывает только средства из Linux.

Перенос средствами Linux оказался не настолько простым делом, как это могло показаться первоначально. Не буду рассказывать обо всём, что мне довелось попробовать и на какие грабли наступить, я просто резюмирую весь полученный опыт.

У меня стоит загрузчик GRUB2, но почему-то не стояло очень важного компонента - os-prober. Он умеет при подсовывании ему дискового раздела определять, что за операционная система там стоит. Его наличие позволит упростить настройку GRUB2. Также, поскольку мы будем переносить систему Windows XP с раздела NTFS на раздел NTFS, нам потребуется пакет ntfsprogs. Ну и если у вас ещё нет раздела на диске, в который вы хотите перенести Windows, вам могут потребоваться fdisk и/или parted. Полезным может оказаться и модуль ntfs-3g для монтирования NTFS-раздела в режиме записи.
# apt-get install os-prober ntfsprogs hexedit
Останавливаться на создании раздела для Windows я не стану, т.к. это дело тривиальное и, на мой взгляд, не требующее объяснений.

Первым делом скопируем NTFS-раздел. Делается это командой ntfsclone:
# ntfsclone --overwrite /dev/sdb3 /dev/sda1
/dev/sda1 - это исходный раздел с Windows,
/dev/sdb3 - это целевой раздел, на который мы переносим систему.
БУДЬТЕ ВНИМАТЕЛЬНЫ, ничего не перепутайте! Посмотреть, какие разделы есть на дисках, можно с помощью команды:
# fdisk -l
Если возникают сомнения, смонтируйте разделы и убедитесь в том, что вы точно знаете, с какого на какой раздел нужно перенести систему. У меня таких проблем не было, т.к. диска было всего два, на одном из дисков было аж 6 разделов, а на другом - только 1, поэтому перепутать их было трудно.

После клонирования мы получим раздел в точности повторяющий исходный. Ловушка заключается в том, что загрузчик Windows, располагающийся в начале раздела (NTFS Boot Record), содержит в себе информацию о геометрии диска, положении раздела и о серийном номере этого раздела.

На данном этапе мне помогла статья Relocating Windows to a new Hard Drive, в которой есть ссылка на исходный текст простенькой программы, которая исправляет загрузчик NTFS так, чтобы он узнал о новой геометрии диска. Эту программу я на всякий случай скопировал себе и разместил тут: ntfsreloc.c

Соберём её (для этого может потребоваться установить компилятор языка Си, который у меня уже стоял, т.к. я иногда на нём пишу сам):
$ gcc -o ntfsreloc ntfsreloc.c
Теперь её нужно запустить:
# ntfsreloc -w -p /dev/sdb3
Затем нужно смонтировать диск и исправить в файле boot.ini в корневом каталоге номер раздела, с которого будет грузиться Windows. Раньше у меня это был раздел №1, а теперь - №3.
[boot loader]
timeout=30
default=multi(0)disk(0)rdisk(0)partition(3)\WINDOWS
[operating systems]
multi(0)disk(0)rdisk(0)partition(3)\WINDOWS="Microsoft Windows XP Professional RU" /noexecute=optin /fastdetect
Теперь нужно исправить карту дисков GRUB, которая находится в файле /boot/grub/device.map:
(fd0)   /dev/fd0
(hd0)   /dev/disk/by-id/ata-WDC_WD10EADS-65L5B1_WD-WCAU4A888959
(hd1)   /dev/disk/by-id/ata-ST34313A_6CR0J30R
Диском (hd0) должен быть тот, на который мы переносим систему. Или можно исправить номер диска в файле boot.ini Windows, так чтобы номер загрузочного диска совпадал с номером диска в device.map. Полезно также перед этим настроить привязку дисков в /etc/fstab к UUID раздела или к метке раздела, чтобы в случае путаницы с номерами дисков Linux всё-таки загрузился. Практически во всех современных системах Linux это уже так, т.к. с заменой драйвера IDE на унифицированный драйвер дисков, номер, под которым определится диск, стал непредсказуем.

Дальше нужно обновить конфигурацию GRUB2:
# update-grub
И можно перезагружаться. При первой загрузке нам потребуются оба диска, т.к. в реестре Windows сохранилась привязка к идентификатору прежнего диска. После загрузки системы запускаем regedit и редактируем раздел HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices. В нём нужно поменять буквы дисков C и того, который по содержимому идентичен диску C. У меня это были диски C и D. Сделал я это в три приёма:
C -> Z
D -> C
Z -> D
После этого завершаем работу, отключаем старый диск и пробуем загрузиться снова. Если всё было сделано правильно, система загрузится с нового диска.

Я таким образом смог отключить противно свистящий старый диск, на котором у меня стоял Windows XP. Сама эта заметка является, по сути, продолжением предыдущей: Настройка fancontrol - демона управления вентиляторами компьютера.

Желаю вам удачного переноса Windows!

P.S. 21 декабря 2013 года. Вместо программы ntfsreloc можно воспользоваться программой partclone.ntfsfixboot из пакета partclone. В этом случае вместо команды
# ntfsreloc -w -p /dev/sdb3
можно воспользоваться командой
# partclone.ntfsfixboot -w /dev/sdb3

Настройка fancontrol - демона управления вентиляторами компьютера

Надоело слушать постоянное жужжание домашнего компьютера, поэтому решил заняться вопросом. Первым делом были закуплены и установлены тихие вентиляторы на процессор и корпус.

Шум хоть и стал меньше, меня он всё равно не устроил. Компьютер и, соответственно, корпус у меня 2006 года, поэтому что-либо совсем уж тихое найти было сложновато. Опытным путём было выяснено, что больше всего шума даёт корпусной вентилятор (для этого достаточно на секунду остановить все вентиляторы поочерёдно пальцем или другим подходящим предметом). Поскольку на вентиляторе имелся не только стандартный 3-контактный разъём, но и разъём Molex, нашлось простое решение - перекинуть контакты, так чтобы снизилось питающее вентилятор напряжение. Подробнее это можно увидеть в разделе "Подключение вентиляторов" из статьи "Конструируем систему охлаждения компьютера". Жёлтый провод я всё-же воткнул в 3-контактный разъём на положенное место, дабы следить за скоростью вращения вентилятора, о чем будет написано чуть ниже.

Вторым кандидатом на настройку стал вентилятор процессора. В BIOS я узнал, что моя материнская плата поддерживает функцию PWM - управление скоростью вращения вентилятора в зависимости от показаний температурного датчика. Простейшее трёхскоростное управление я настроил прямо из BIOS, и если оно вас устроит, то нужды настраивать fancontrol в принципе нет. Меня эти три режима не устроили, захотелось более плавного разгона вентилятора по мере нагревания процессора.

Поскольку я пользуюсь Linux (Debian 6), то и настраивать управление будем в нём.

Первым делом, установим пакет для слежения за сенсорами и запустим обнаружение сенсоров:
# apt-get install lm-sensors
# sensors-detect
Отвечаем на все вопросы буквой y. Это важно, т.к. на один из вопросов ответ по умолчанию - n. Без этого пункта у меня не находились сенсоры материнской платы.
Now follows a summary of the probes I have just done.
Just press ENTER to continue: 

Driver `it87':
* ISA bus, address 0x290
Chip `ITE IT8712F Super IO Sensors' (confidence: 9)

Driver `k8temp' (autoloaded):
* Chip `AMD K8 thermal sensors' (confidence: 9)

To load everything that is needed, add this to /etc/modules:
#----cut here----
# Chip drivers
it87
#----cut here----
If you have some drivers built into your kernel, the list above will
contain too many modules. Skip the appropriate ones!
Теперь можно заглянуть в /etc/modules и проверить, появились ли там новые модули, добавленные sensors-detect.

Чтобы не перезагружать систему, загрузим эти модули вручную. У меня был добавлен модуль it87, поэтому я подгружаю его:
# modprobe it87
Теперь можно посмотреть информацию, предоставляемую сенсорами:
$ sensors

k8temp-pci-00c3
Adapter: PCI adapter
Core0 Temp:  +32.0°C                                    

it8712-isa-0290
Adapter: ISA adapter
in0:         +1.07 V  (min =  +0.00 V, max =  +4.08 V)   
in1:         +2.58 V  (min =  +0.00 V, max =  +4.08 V)   
in2:         +3.33 V  (min =  +0.00 V, max =  +4.08 V)   
in3:         +2.21 V  (min =  +0.00 V, max =  +4.08 V)   
in4:         +3.02 V  (min =  +0.00 V, max =  +4.08 V)   
in5:         +1.76 V  (min =  +0.00 V, max =  +4.08 V)   
in6:         +2.00 V  (min =  +0.00 V, max =  +4.08 V)   
in7:         +2.35 V  (min =  +0.00 V, max =  +4.08 V)   
Vbat:        +4.08 V
fan1:          0 RPM  (min =    0 RPM, div = 8)
fan3:       1670 RPM  (min =    0 RPM, div = 8)
temp1:       +25.0°C  (low  = +127.0°C, high = +127.0°C)  sensor = thermistor
temp2:       +29.0°C  (low  = +127.0°C, high = +60.0°C)  sensor = thermistor
temp3:       +70.0°C  (low  = +127.0°C, high = +127.0°C)  sensor = thermistor
cpu0_vid:   +1.100 V
У меня есть сенсоры температуры на процессоре и на материнской плате (не знаю, в каких именно местах).

Теперь установим пакет для управления скоростью вращения вентиляторов.
# apt-get install fancontrol
И запустим программу для автоматизированной настройки fancontrol:
# pwmconfig
Программа сразу после запуска сообщает информацию об обнаруженных ею сенсорах температуры, устройствах управления вентиляторами и сенсорах скорости вращения вентиляторов:
Found the following devices:
hwmon0/device is k8temp
hwmon1/device is it8712

Found the following PWM controls:
hwmon1/device/pwm1
hwmon1/device/pwm2
hwmon1/device/pwm3

Giving the fans some time to reach full speed...
Found the following fan sensors:
hwmon1/device/fan1_input     current speed: 2556 RPM
hwmon1/device/fan3_input     current speed: 1654 RPM
Лучше всего сразу куда-нибудь скопировать эту информацию, чтобы понимать, что за устройства программа имеет в виду, когда спрашивает вас о чём-то. Например, для меня было важно, что hwmon0/device - это процессор, а hwmon1/device - это материнская плата.

Дальше программа по очереди пытается остановить каждый из вентиляторов и пытается по сенсорам вращения вентиляторов установить соответствие между устройством управления скоростью вращения вентилятора и связанным с ним сенсором.

У меня было обнаружено только одно соответствие:
Testing pwm control hwmon1/device/pwm1 ...
hwmon1/device/fan1_input ... speed was 2556 now 0
It appears that fan hwmon1/device/fan1_input
is controlled by pwm hwmon1/device/pwm1
После этого программа предложила составить таблицу соответствия между значениями управляющего байта (от 0 до 255) и скоростью вращения вентилятора:
Would you like to generate a detailed correlation (y)?
Я ответил утвердительно.
PWM 255 FAN 2596
PWM 240 FAN 2596
PWM 225 FAN 2556
PWM 210 FAN 2556
PWM 195 FAN 2556
PWM 180 FAN 2556
PWM 165 FAN 2596
PWM 150 FAN 2556
PWM 135 FAN 2556
PWM 120 FAN 2596
PWM 105 FAN 2596
PWM 90 FAN 2596
PWM 75 FAN 2556
PWM 60 FAN 2556
PWM 45 FAN 2445
PWM 30 FAN 2280
PWM 28 FAN 2250
PWM 26 FAN 2191
PWM 24 FAN 2163
PWM 22 FAN 2109
PWM 20 FAN 2057
PWM 18 FAN 1985
PWM 16 FAN 1917
PWM 14 FAN 1834
PWM 12 FAN 1721
PWM 10 FAN 1622
PWM 8 FAN 1493
PWM 6 FAN 1339
PWM 4 FAN 1171
PWM 2 FAN 964
PWM 0 FAN 0
Fan Stopped at PWM = 0
Программа не обнаружила, каким из вентиляторов управляло устройство hwmon1/device/pwm2 и спросила меня, слышал или видел ли я, что какой-то из вентиляторов во время теста останавливался.
Did you see/hear a fan stopping during the above test (n)?
Я этого не видел и не заметил уменьшения шума, поэтому ответил n.

То же самое произошло и с устройством hwmon1/device/pwm3. Я также ответил n.

Затем программа говорит о том, что программа fancontrol может следить за температурой устройств, управляя скоростью вращения вентиляторов. pwmconfig предлагает мне настроить fancontrol. Я соглашаюсь.
The fancontrol script can automatically respond to temperature changes
of your system by changing fanspeeds.
Do you want to set up its configuration file now (y)?
Задаёт вопрос о том, где должен находиться файл конфигурации fancontrol. Можно нажать enter и тем самым согласиться на предложенный файл, а можно ввести другое имя файла.
What should be the path to your fancontrol config file (/etc/fancontrol)?
Дальше программа предлагает настроить устройство управления только одним из вентиляторов, для которого установлено соответствие канала управления и сенсора скорости вращения.
Select fan output to configure, or other action:
1) hwmon1/device/pwm1  3) Just quit       5) Show configuration
2) Change INTERVAL     4) Save and quit
Пункт 2 позволяет настроить периодичность проверки температуры и коррекции скорости вращения.

Пункт 3 позволяет просто выйти.

Пункт 4 - сохранить настройки и выйти.

Пункт 5 - показать конфигурацию.

Выбираем пункт 1, чтобы указать, какой из сенсоров температуры следует использовать для управления вентилятором. У меня таких сенсоров 4, я выбираю первый из них, который соответствует сенсору температуры на процессоре.
Select a temperature sensor as source for hwmon1/device/pwm1:
1) hwmon0/device/temp1_input
2) hwmon1/device/temp1_input
3) hwmon1/device/temp2_input
4) hwmon1/device/temp3_input
5) None (Do not affect this PWM output)
select (1-n):
Остальные сенсоры - это сенсоры температуры на материнской плате. Их положение мне неизвестно, да и управлять больше у меня нечем, кроме как скоростью вращения вентилятора на процессоре. Есть ещё корпусной вентилятор, но он, судя по тестам pwmconfig, фактически не управляется.

Дальше нужно ответить на несколько простых вопросов. Нам понадобится составленная выше таблица зависимости скорости вращения вентилятора от значения управляющего сигнала и немного здравого смысла. Судя по таблице, вентилятор работает на максимальной скорости уже при значении сигнала управления 105. Останавливается он при значении 2, а запускается при значении 4 (это я смог узнать только пробуя разные значения этого параметра в конфигурации fancontrol).

Как я выбирал предельные температуры? Очень просто - температура воздуха дома сейчас около 30 градусов Цельсия (на системнике висит магнит с термометром). Не вижу смысла насиловать кулер, заставляя его охлаждать процессор простым обдувом комнатным воздухом до 30 градусов или ниже - это просто невозможно. Накидываю 5 градусов и считаю такую температуру процессора нормальной. Пока температруа процессора ниже 35 градусов, включать охлаждение особого смысла нет. Включать его на полную мощность следует только при той температуре, при которой BIOS начнёт предупреждать о перегреве звуковым сигналом. У меня это 60 градусов Цельсия. Пока не достигнута эта температура, разгоняем вентилятор плавно, не в полную силу.

Enter the low temperature (degree C)
below which the fan should spin at minimum speed (20): 35
Указать самую высокую температуру, выше которой вентилятор должен включаться на полную мощность.
Enter the high temperature (degree C)
over which the fan should spin at maximum speed (60): 60
Минимальное значение канала управления, при котором вентилятор останавливается.
Enter the minimum PWM value (0-255)
at which the fan STOPS spinning (press t to test) (100): 2
Минимальное значение канала управления, при котором вентилятор начинает вращаться.
Enter the minimum PWM value (4-255)
at which the fan STARTS spinning (press t to test) (150): 4
Значение канала управления, если температура ниже минимальной.
Enter the PWM value (0-4) to use when the temperature
is below the low temperature limit (0): 0
Значение канала управления, если температура выше максимальной.
Enter the PWM value (4-255) to use when the temperature
is over the high temperature limit (255): 105
Теперь можно посмотреть конфигурацию (пункт 5) или сохранить изменения и закончить настройку (пункт 4). Можно снова ответить на вопросы, выбрав канал управления из списка.

Все эти настройки вносятся в файл /etc/fancontrol, где их можно отредактировать вручную:
# Configuration file generated by pwmconfig, changes will be lost
INTERVAL=5
DEVPATH=hwmon0=devices/pci0000:00/0000:00:18.3 hwmon1=devices/platform/it87.656
DEVNAME=hwmon0=k8temp hwmon1=it8712
FCTEMPS= hwmon1/device/pwm1=hwmon0/device/temp1_input
FCFANS= hwmon1/device/pwm1=hwmon1/device/fan1_input
MINTEMP= hwmon1/device/pwm1=35
MAXTEMP= hwmon1/device/pwm1=60
MINSTART= hwmon1/device/pwm1=4
MINSTOP= hwmon1/device/pwm1=2
MAXPWM=hwmon1/device/pwm1=105
Осталось только запустить службу fancontrol и вентиляторы будут управляться автоматически:
# /etc/init.d/fancontrol start
Самое главное, что нужно от pwmconfig - это установить соответствие между сенсорами скорости вращения вентилятора, температуры и каналом управления скоростью вращения вентилятора. Остальное можно настраивать уже простым редактированием файла /etc/fancontrol с последующим перезапуском демона fancontrol. Следить за индикаторами можно с помощью команд watch sensors. Именно таким образом я настроил подходящие параметры fancontrol.

С такими настройками я могу редактировать тексты при полностью остановленном вентиляторе. При полной загрузке процессора температура его поднимается до 45 градусов и держится на этом уровне стараниями fancontrol.

Я пользуюсь XFCE и нашёл для него два интересных плагина для более удобного наблюдения за температурой и процессором: xfce4-cpufreq-plugin и xfce4-sensors-plugin.

Установим их вместе с другими рекомендованными пакетами:
# apt-get install xfce4-cpufreq-plugin xfce4-sensors-plugin xsensors hddtemp cpufreq
Дальше их нужно просто добавить в панель и настроить. Всё это делается через меню панели.

Рядом с двумя индикаторами температур (процессора и жёсткого диска) удобно разместился индикатор текущей частоты процессора. Мой процессор умеет вдвое уменьшать свою рабочую частоту, когда он не сильно загружен - с 2 Гигагерц до 1 Гигагерца.

Впрочем, я не стремлюсь превратить свой компьютер в кабину самолёта, поэтому эти апплеты будут висеть в панели лишь некоторое время, пока конфигурация может потребовать доработки. Затем я скорее всего уберу эти апплеты, поскольку никакой жизненно важной информации они не предоставляют.

После всех этих манипуляций самым громким источником шума стал старенький жёсткий диск Seagate на 4,3 Гигабайта, на котором у меня установлена Windows XP. Во время работы он издаёт раздражающий свист. Осталось перенести Windows XP на менее шумный жёсткий диск WD на 1 Терабайт, где у меня установлена основная система - Debian GNU/Linux 6.0.

Неожиданно, сделать это оказалось непросто. Но об этом - в следующей заметке.

среда, 26 октября 2011 г.

Настройка FastCGI и PHP с индивидуальными правами пользователей

Перевод статьи: Setup FastCGI and PHP with individual user permissions

Автор: silverjam и другие.

Примечания переводчика: для порядка я иногда перевожу материалы, которыми собираюсь воспользоваться. Начав делать этот перевод, я сразу же пожалел о том, что ввязался в это гиблое дело - статья разжёвывает элементарные вещи вроде заведения пользователей, групп, членство в группах и права доступа. Ну и запуск сценариев инициализации из cron'а я, конечно, не одобряю. Кроме того, автор использовал FreeBSD 6.2, в которой существовало ограничение на максимальное количество групп для одного пользователя. В качестве решения автор предлагает перейти на FreeBSD 8.0, однако я думаю, что есть по меньшей мере ещё два решения: 1. воспользоваться TCP-сокетами, вместо сокетов домена Unix, 2. воспользоваться каким-нибудь дистрибутивом Linux.

Перво-наперво отметим, что этот рецепт является только примером, поэтому не предъявляйте претензий, если предпочитаете делать такие вещи другим способом, или рассердили клиентов или что-то в этом роде...

Execwrap или php-fpm можно использовать в тех же целях, но этот рецепт не касается этих методов.

Замечание: Этот рецепт работает только на операционных системах типа Unix. Я не знаю, как сделать подобное на Windows.

Введение

Запуск хостинга веб-сайтов для обслуживания индивидуальных пользователей/клиентов потребует дополнительного доведения до ума настроек вашего веб-сервера.

Для начала, нужно назначить каждому пользователю собственную учётную запись на веб-сервере. Пользователь загрузит файлы своих скриптов PHP в его собственный виртуальный корневой каталог документов.

Нужно, чтобы все файлы скриптов PHP выполнялись с правами того же пользователя, который управляет этим виртуальным узлом. Если это так, то можно быть уверенным, что ни один из пользователей не сможет увидеть чужие скрипты PHP.

Рассмотрим следующий скрипт PHP, выполняемый на веб-сервере без индивидуальных разрешений пользователя (не пытайтесь сделать это, поскольку вы можете кончить тем, что полиция постучится в вашу дверь!):
<?php
  $filename = "/path_to_other_users_vhost_root/index.php";
  $handle = fopen($filename, "rb");
  $contents = fread($handle, filesize($filename));
  fclose($handle);
  echo $contents;
?>
Этот сценарий прочитает и покажет исходный код скрипта PHP какого-то другого пользователя. Исходный код может содержать пароли, используемые для подключения к пользовательским базам данных MySQL, или другую интересную информацию. Можно даже сделать скрипт PHP, который сможет перезаписать файлы в каталогах пользователя другого виртуального узла!

Мы хотим этого избежать!

Как насчёт встроенного в PHP безопасного режима safe_mode?

Я не хочу сказать что-то плохое о PHP, но я не рекомендую использовать PHP с возможностями встроенного безопасного режима safe_mode. (Обратитесь к документации по safe_mode на php.net за более подробным описанием.)

Однако, некоторые настройки php.ini могут предотвратить или замедлить большинство видов атак без необходимости изменять исходный код. Для предотвращения удалённого доступа из php воспользуйтесь allow_url_fopen, а для предотвращения вставки удалённых файлов в php вы можете воспользоваться allow_url_include. Настройка open_basedir - это хороший способ усложнить работу взломщика, но этот способ не заменит разрешений пользователей. Для замедления некоторых видов угона сеансов можно отключить опцию session.use_trans_sid.

Но всё же будет лучше, если положиться на возможности ограничения доступа пользователей, встроенные в операционную систему.

Установка

Подразумевается, что на сервере уже установлены Lighttpd и PHP с поддержкой FastCGI. (Как установить PHP с поддержкой FastCGI.)

Чтобы выполнить установку, нужно войти под пользователем root.

1. Добавим пользователей в операционную систему

(Это необходимо только в том случае, если пользователи ещё не добавлены.)

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

Предположим, что таких пользователей три (fred, george и ron).

Выполним следующие команды:
# useradd fred
# useradd george
# useradd ron
2. Добавим группы пользователей в операционную систему

Нужно добавить по одной группе для каждого из добавленных выше пользователей. Для простоты назовём группы так же, как и пользователей:

Выполним следующие команды:
# groupadd fred
# groupadd george
# groupadd ron
Теперь нужно добавить каждого пользователя в его группу. В каждой группе пользователей будет два члена: сам пользователь и пользователь демона lighttpd.

Группы пользователей можно настроить, отредактировав файл /etc/group в любом текстовом редакторе.

Файл должен выглядеть примерно так (номера групп могут отличаться):
... [пропущенные строки]
fred:x:441:fred,lighttpd
george:x:442:george,lighttpd
ron:x:443:ron,lighttpd
Можно также воспользоваться командой sed:
# sed -i "s/^\(fred.*\)$/\1,fred,lighttpd/g" /etc/group
# sed -i "s/^\(george.*\)$/\1,george,lighttpd/g" /etc/group
# sed -i "s/^\(ron.*\)$/\1,ron,lighttpd/g" /etc/group
Эти команды добавят самого пользователя и пользователя lighttpd в группы.

3. Настроим структуру файловой системы

Предположим, что мы хотим сохранить все связанные с веб-сервером файлы виртуальных узлов в подкаталогах "/var/www". (Конечно, вы можете выбрать другое место, просто удостоверьтесь, что созданные пользователи имеют права на чтение и выполнение их каталогов. (Например, "chmod 755 /var/www && chown root:root /var/www").

3.1 Создадим корневой каталог

Теперь, создадим два каталога: один для нескольких сценариев запуска, к которому будет иметь доступ только пользователь root, и другой для всех виртуальных узлов:

Выполним следующие команды:
# cd /var/www
# mkdir fastcgi
# mkdir vhosts
# chown lighttpd:lighttpd *
# chmod 755 *
# ls -l /var/www
drwxr-xr-x 2 lighttpd lighttpd 4096 Feb 15 12:17 fastcgi
drwxr-xr-x 9 lighttpd lighttpd 4096 Feb 15 11:21 vhosts
3.2 Создадим каталог для каждого из виртуальных узлов

Теперь создадим каталог для каждого из виртуальных узлов в каталоге "/var/www/vhosts" и зададим соответствующие права для их пользователей:

Выполним следующие команды:
# cd /var/www/vhosts
# mkdir fred-weasley.com
# mkdir george-weasley.com
# mkdir ron-weasley.com
# chown fred:fred fred-weasley.com
# chown george:george george-weasley.com
# chown ron:ron ron-weasley.com
# chmod 750 *
# ls -l /var/www/vhosts
drwxr-x--- 7 fred fred 4096 Feb 15 20:18 fred-weasley.com
drwxr-x--- 6 george george 4096 Feb 15 11:02 george-weasley.com
drwxr-x--- 6 ron ron 4096 Feb 15 11:23 ron-weasley.com
Теперь у нас есть три каталога, в которых три пользователя не могут увидеть файлы друг друга, однако демон lighttpd может видеть их все.

3.3 Создадим структуру каталогов для каждого виртуального узла

Теперь нужно создать структуру каталогов для каждого виртуального узла:

Выполним следующие команды:
# cd /var/www/vhosts/fred-weasley.com
# mkdir html
# mkdir includes (не обязательно)
# mkdir logs
# chown fred:fred *
# chown lighttpd:fred logs
# chmod 750 *
# ls -l /var/www/vhosts/fred-weasley.com
drwxr-x--- 14 fred fred 4096 Feb 17 11:55 html
drwxr-x--- 2 fred fred 4096 Feb 15 12:05 includes
drwxr-x--- 2 lighttpd fred 4096 Feb 15 11:11 logs
Нужно повторить эти команды для каждого из пользователей виртуального узла, заменяя имя пользователя "fred" на имя соответствующего пользователя.

3.4 Создадим каталог FastCGI для каждого пользователя

Теперь мы готовы приступить к самому интересному!

Теперь, перейдём в каталог "/var/www/fastcgi", где мы хотим создать каталог каждого из пользователей. (Когда мы закончим, эти каталоги будут содержать сокеты процессов сервера FastCGI):

Выполним следующие команды:
# cd /var/www/fastcgi
# mkdir fred
# mkdir george
# mkdir ron
# chown fred:fred fred
# chown george:george george
# chown ron:ron ron
# chmod 750 *
# ls -l /var/www/fastcgi
drwxr-x--- 7 fred fred 4096 Feb 15 20:18 fred
drwxr-x--- 6 george george 4096 Feb 15 11:02 george
drwxr-x--- 6 ron ron 4096 Feb 15 11:23 ron
(Отметим, что пользователь lighttpd может читать все каталоги, в то время как три пользователя имеют доступ только к собственным каталогам.)

4. Создадим скрипт запуска FastCGI для каждого пользователя

Создадим каталог, который будет содержать все скрипты запуска FastCGI, выполнив следующие команды:
# cd /var/www/fastcgi
# mkdir startup
# chmod 750 startup
# ls -l /var/www/fastcgi
drwxr-x--- 7 fred fred 4096 Feb 15 20:18 fred
drwxr-x--- 6 george george 4096 Feb 15 11:02 george
drwxr-x--- 6 ron ron 4096 Feb 15 11:23 ron
drwxr-x--- 6 root root 4096 Feb 15 11:23 startup
Теперь, перейдём в каталог "/var/www/fastcgi/startup", создадим скрипт запуска для пользователя fred (давайте назовём его fred-startup.sh), воспользовавшись любым текстовым редактором:

Скрипт оболочки:
#!/bin/sh

## АБСОЛЮТНЫЙ путь к двоичному файлу spawn-fcgi
SPAWNFCGI="/usr/bin/spawn-fcgi" 

## АБСОЛЮТНЫЙ путь к двоичному файлу PHP
FCGIPROGRAM="/usr/bin/php-cgi" 

## Прослушивание порта TCP на localhost
FCGISOCKET="/var/www/fastcgi/fred/fred.socket" 

## Раскомментируйте строку PHPRC, если имеется дополнительный файл php.ini для этого пользователя
## Положите этот файл php.ini в /var/www/fastcgi/fred/php.ini
## С помощью этого файла php.ini можно увеличить безопасность системы
## Просто настройте параметр open_basedir на веб-каталоги пользователей
## Например: (добавьте эту строку в ваш настроенный файл php.ini)
## open_basedir = /var/www/vhosts/fred/html
#PHPRC="/var/www/fastcgi/fred/" 

## Количество детей PHP порождаемых дополнительно к основным. Минимум 2.
## Действительное количество детей = PHP_FCGI_CHILDREN + 1
PHP_FCGI_CHILDREN=5

## Количество запросов выполненных сервером к одному процессу php, прежде чем этот процесс будет перезапущен
PHP_FCGI_MAX_REQUESTS=1000

## IP-адреса, с которых PHP должен принимать соединения серверов
FCGI_WEB_SERVER_ADDRS="127.0.0.1" 

# Доступные переменные окружения, разделённые пробелами
ALLOWED_ENV="PATH USER" 

## Если этот скрипт запускается от имени пользователя root, то fastcgi переключится на следующего пользователя:
USERID=fred
GROUPID=fred

################## После этой строки настроек нет
if test x$PHP_FCGI_CHILDREN = x; then
  PHP_FCGI_CHILDREN=5
fi
export PHP_FCGI_MAX_REQUESTS
export FCGI_WEB_SERVER_ADDRS
export PHPRC
ALLOWED_ENV="$ALLOWED_ENV PHP_FCGI_MAX_REQUESTS FCGI_WEB_SERVER_ADDRS PHPRC"

# Скопируем доступные переменные окружения
E=
for i in $ALLOWED_ENV; do
  E="$E $i=$(eval echo "\$$i")" 
done

# Очистим переменные окружения и настроим новые
env - $E $SPAWNFCGI -s $FCGISOCKET -f $FCGIPROGRAM -u $USERID -g $GROUPID -C $PHP_FCGI_CHILDREN
chmod 770 $FCGISOCKET
Будьте аккуратны с путями, USERID и GROUPID.

Отметим, что в этом примере процессы php запускаются от имени пользователя, созданного ранее ("fred"). Это означает, что код php будет иметь права доступа к файлам html и php. Это может быть удобно, но может быть менее безопасно.

В качестве альтернативы можно задать USERID значение "nobody" (или любого другого пользователя без каких-либо особых разрешений), чтобы запретить процессу php запись.

Нужно повторить процесс и создать скрипт запуска для каждого пользователя из каталога "/var/www/fastcgi/startup". (Просто скопируйте фалй и замените FCGISOCKET, USERID и GROUPID на правильные значения).

Не забудьте установить разрешения на выполнение всех скриптов запуска:

Выполним следующие команды:
# cd /var/www/fastcgi/startup
# chmod 750 *
5. Проверим настройку PHP

Если вы не знаете точно, где находится файл php.ini, просто выполните следующие команды:
$ php-cgi -i | grep php.ini
Удостоверьтесь, что в файле php.ini имеется следующая строка:
cgi.fix_pathinfo=1
Если вы раскомментировали строку PHPRC в скрипте из раздела 4, проверьте владельца и права доступа к файлу php.ini. Чтобы он использовался, нужно выполнить команды:
# chmod 644 php.ini
# chown root:root php.ini
6. Запустим все скрипты запуска FastCGI

Теперь запустим все процессы-серверы FastCGI, выполнив следующие команды:
# /var/www/fastcgi/startup/fred-startup.sh
spawn-fcgi.c.170: child spawned successfully: PID: xxxxx
# /var/www/fastcgi/startup/george-startup.sh
spawn-fcgi.c.170: child spawned successfully: PID: xxxxx
# /var/www/fastcgi/startup/ron-startup.sh
spawn-fcgi.c.170: child spawned successfully: PID: xxxxx
Если будут какие-то сообщения об ошибках, проверьте скрипты запуска и права доступа к каталогу "/var/www/fastcgi", включая все подкаталоги.

7. Настроим виртуальные узлы на сервере lighttpd

Отредактируем файл "/etc/lighttpd.conf" в любом текстовом редакторе:
...[некоторое количество строк конфигурации]...
$HTTP["host"] =~ "(^|\.)fred-weasley.com$" {
  server.document-root = "/var/www/vhosts/fred-weasley.com/html" 
  accesslog.filename = "/var/www/vhosts/fred-weasley.com/logs/access_log" 
  fastcgi.server = (
    ".php" => (
      (
        "socket" => "/var/www/fastcgi/fred/fred.socket",
        "broken-scriptfilename" => "enable" 
      )
    )
  )
}

$HTTP["host"] =~ "(^|\.)george-weasley.com$" {
  server.document-root = "/var/www/vhosts/george-weasley.com/html" 
  accesslog.filename = "/var/www/vhosts/george-weasley.com/logs/access_log" 
  fastcgi.server = (
    ".php" => (
      (
        "socket" => "/var/www/fastcgi/george/george.socket",
        "broken-scriptfilename" => "enable" 
      )
    )
  )
}

$HTTP["host"] =~ "(^|\.)ron-weasley.com$" {
  server.document-root = "/var/www/vhosts/ron-weasley.com/html" 
  accesslog.filename = "/var/www/vhosts/ron-weasley.com/logs/access_log" 
  fastcgi.server = (
    ".php" => (
      (
        "socket" => "/var/www/fastcgi/ron/ron.socket",
        "broken-scriptfilename" => "enable" 
      )
    )
  )
}
Обратите внимание на пути к сокетам FastCGI каждого виртуального узла.

Условные блоки НЕ оказывают действия на server.errorlog, все сообщения об ошибках попадают в последний указанный файл журнала. Поэтому используется один глобальный журнал.

8. Перезапустим процесс демона lighttpd

Просто выполним следующую команду:
# /etc/init.d/lighttpd restart
Если будут какие-то сообщения об ошибках, проверьте файл конфигурации "/etc/lighttpd.conf".

9. Здравствуй мир!

Теперь, войдём под пользователем fred и создадим скрипт PHP в его виртуальном узле (например, "/var/www/vhosts/fred-weasley.com/html/index.php"):
<?php
  echo "<h1>Здравствуй мир!</h1>";
  echo "<p>Идентификатор текущего пользователя: ". posix_getuid();
  echo "<p>Идентификатор текущей группы: ". posix_getgid();
?>
Убедитесь, что вы задали разрешения на доступ к файлу:

Выполните следующие команды:
# chown fred:fred /var/www/vhosts/fred-weasley.com/html/index.php
# chmod 640 /var/www/vhosts/fred-weasley.com/html/index.php
# ls -l /var/www/vhosts/fred-weasley.com/html
-rw-r----- 1 fred fred 116 Jul 25 2004 index.php
Теперь, запустим веб-браузер и проверим вывод скрипта PHP. (Здесь: http://www.fred-weasley.com/index.php)

Если всё хорошо, вы увидите страницу, на которой будут отображены идентификаторы пользователя и группы fred. (Вы можете увидеть эти идентификаторы в файлах "/etc/passwd" и "/etc/group").

10. Автоматический вызов скриптов запуска FastCGI

При желании можно также создать запись в планировщике задач crontab для автоматического вызова скриптов запуска FastCGI при загрузке сервера.

Воспользуемся следующей командой для редактирования заданий планировщика crontab:
# crontab -e
Теперь добавим следующую строку:
@reboot for i in /var/www/fastcgi/startup/*.sh; do $i; done
А затем введём ":x" для сохранения и выхода.

Эта запись в планировщике задач crontab выполнит все файлы с расширением .sh, найденные в каталоге /var/www/fastcgi/startup, после загрузки сервера.

Поздравляю! Теперь у вас есть быстрый сервер, настроенный с отдельными правами для пользователей.

Ограничения

Таким образом мы создали отдельные группы процессов fastcgi для каждого пользователя. Это означает, что у этих процессов нет общей памяти. Поэтому, если этот способ используется на компьютере с большим количеством пользователей, потребуется значительное количество доступной оперативной памяти. Также, если используется какой-нибудь кэш транслированного кода PHP, например, xcache, apc или eaccelerator, этот способ приведёт к созданию собственного кэша у каждого из пользователей (что полезно для повышения безопасности, но приводит к увеличению использования памяти). Можно уменьшить использование памяти с помощью файлов php.ini, в которых настроить ускоритель с разными объёмами кэша, а также изменить значение переменной PHP_FCGI_CHILDREN в каждом из пользовательских скриптов startup.sh.

В FreeBSD (6.2) каждый пользователь может состоять максимум в 14 группах. Этот верхний предел экземпляров fastcgi для виртуальных узлов, поскольку пользователю lighttpd (www) необходим доступ к этим сокетам. Я настроил мой веб-сервер 1-2 года назад этим способом и столкнулся с проблемой несколько недель назад, когда добавил пользователя www в пятнадцатую группу. Не было никаких сообщений об ошибках, иди-свищи ответа у google. Но всё-таки, есть ли решение? ;) Да, в FreeBSD 8.0 этот предел был поднят до 1024.

Разрешения

У mod_fastcgi имеется опция check-local. Если она включена, Lighttpd использует своего пользователя для проверки существования файла в document-root. Если вы хотите, чтобы пользователь Lighttpd не имел доступа к document-root, нужно отключить эту опцию.

пятница, 14 октября 2011 г.

Postfix maildir umask

Захотел написать небольшое веб-приложение для управления почтовым сервером. Одна из функций этого приложения - удаление почтового ящика из БД. Стандартная задача, которая обычно возникает при удалении почтового ящика, - это создать пересылку с удалённого адреса на другой и перенести уже принятые письма в каталог преемника.

Пример: сотрудник раздавал клиентам визитки со своим электронным адресом. Сотрудник уволился, но его электронную почту нужно обрабатывать, чтобы не потерять клиентов. Для этого можно создать пересылку на другой почтовый ящик, уже полученные письма перенести в почтовый ящик преемника, а сам почтовый ящик уволившегося сотрудника удалить.

Переносом писем по задумке должно заниматься веб-приложение, работающее с правами веб-сервера. Чтобы веб-сервер мог перенести письма, ему нужно иметь соответствующие права доступа. Для этого я включил пользователя www-data в группу vmail, затем дал группе vmail права rwx на каталоги почтовых ящиков.

Каталоги почтовых ящиков создаёт программа virtual почтовой системы Postfix. Можно задать uid и gid, с которыми будет работать эта программа. Это делается с помощью параметров virtual_uid и virtual_gid. Я для пробы решил создать один почтовый ящик и отправить на него письмо. virtual создал каталоги почтового ящика, но выставил для группы vmail права доступа, которые не позволяют ей делать ничего с этим ящиком.

Я прочитал man virtual в надежде найти какой-нибудь параметр вроде virtual_umask, но не нашёл. Попробовал выставить umask в файле /etc/init.d/postfix, перезапустил его, удалил каталог почтового ящика и снова отправил тестовое письмо. Каталог создался с теми же правами. В недоумении я стал искать в интернете, не сталкивался ли кто с такой же проблемой.

Оказалось - сталкивались. А параметра virtual_umask нет и не будет. Вьетце Венема аргументирует свою позицию тем, что он сисадмин с 20-летним стажем и доступ к письмам со стороны левых программ может отрицательно отразиться на безопасности почтовой системы. Никаких других доводов он слышать не желает. В том числе он не желает слышать о том, что система прав в Unix задумана такой не для того, чтобы искусственно обходить её стороной. Патчи, если кто такие и напишет, судя по молчанию Вьетце, приняты в основную ветку не будут.

Единственное приемлемое решение моей задачи, по мнению Вьетце Венема, - это забрать почту по протоколу POP из этого ящика и отправить её на другой ящик по протоколу SMTP.

У меня отношение к этому простое - безопасность ради безопасности не нужна. Я лучше постараюсь заменить Courier на какую-нибудь другую программу, которая сама умеет складывать письма в почтовые ящики и имеет собственный модуль доставки для Postfix или умеет работать по протоколу LMTP. В качестве замены исправно работающего много лет Courier воспользуюсь Dovecot.

В общем, если что - не удивляйтесь невменяемости этого уважаемого всеми товарища.

P.S. Настроил Dovecot вместо Courier и... всё то же самое. Настройка umask у Dovecot в прошлом была, но потом была удалена. Вместо неё придумали плагины для работы с общими почтовыми ящиками. Не смешно, но для такой простой операции, видимо, придётся воспользоваться чем-то вроде fetchmail. Хотя, можно воспользоваться sudo, в конфиге которой прописать одну строго ограниченную команду, можно сделать скрипт, работающий по cron'у, можно пропатчить сам Dovecot, а вот использование LMTP из Dovecot тоже не поможет.

вторник, 4 октября 2011 г.

Remmina

Сегодня вновь посмотрел на программу Remmina и на этот раз она мне понравилась, т.к. я нашёл в ней функцию подключения по протоколу RDP через SSH-туннель, а также нашёл удобный апплет для XFCE.

Сама Remmina в Debian находится в пакете remmina и по умолчанию поддерживает только протоколы SSH и SFTP. Плагин для подключения по RDP находится в пакете remmina-rdp, а апплет находится в пакете remmina-xfce.

Для начала поставим всё это хозяйство:
# apt-get install remmina remmina-rdp remmina-xfce
Разобраться в настройках легко, я просто покажу как она выглядит.

Главное окно Remmina:

Окно настройки RDP:


Окно настройки SSH:

Окно настройки SFTP:

Кусочек экрана с апплетом для XFCE:

Удалённый рабочий стол, открытый по протоколу RDP с помощью Remmina:

Теперь подключаться к удалённым компьютерам стало значительно удобнее!

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

Программы, которыми я пользуюсь в Debian GNU/Linux

Решил выложить обновлённую заметку Программы, которыми я пользуюсь в Linux. С тех пор много воды утекло и теперь я пользуюсь другими программами.

Пользуюсь средой XFCE. До этого я пользовался KDE3, но эта ветка прекратила своё существование в пользу более новой - KDE4, которая мне не понравилась. Я последовательно перепробовал IceWM, затем LXDE, и остановился на XFCE, которым сейчас и пользуюсь. Смена графической среды повлекла за собой замену многих программ из лагеря KDE/Qt на аналогичные из лагеря Gnome/GTK.

Сеть:

1. Torrent-клиент - Transmission.
2. FTP-клиент

Iceweasel или Chromium - когда нужно просто скачать несколько файлов.

lftp или ncftp - когда я работаю в консоли или мне нужно работать с FTP-сервером из скрипта.

3. Web-браузер - Iceweasel или Chromium.
4. Почтовый клиент - пользуюсь GMail.
5. RDP-клиент - Remmina.
6. Эмулятор терминала - Terminal (пакет xfce4-terminal).
7. IM-клиент - Pidgin.

Раньше пользовался Psi. Сейчас стал пользоваться Pidgin по двум причинам:
1. America Online продала ICQ компании Mail.ru. Mail.ru поменяли политику - открыли протокол, перестали его менять, разрешили использовать альтернативные ICQ-клиенты. Поэтому я вновь стал пользоваться ICQ, в дополнение к Jabber.
2. KDE4 мне не понравился, поэтому с KDE3 я перешёл на XFCE. Для XFCE родным тулкитом является GTK, поэтому вместо логичного для KDE мультипротокольного клиента Kopete я выбрал Pidgin, который лучше подходит для XFCE.

Офисные программы:

1. Офисный пакет - Openoffice.org.

В дальнейшем, видимо, будет заменён на LibreOffice. Почему - я думаю понятно без объяснений.

2. Калькулятор - KCalc или bc.
3. Просмотр PDF, DjVu, PostScript - Evince.
4. Просмотр FB2 - fbreader.
5. Файловый менеджер - Thunar и bash.
6. Архиватор - Xarchiver или консольные tar, bzip2/bunzip2, gzip/gunzip, unzip, unrar.

Картинки:

1. Просмотр картинок - GPicView.
2. Редактор картинок - KolourPaint (альтернатив не искал, т.к. практически не пользуюсь).
3. Скриншоты - ScreenShooter из XFCE (пакет xfce4-screenshooter).

Мультимедиа:

1. CD-риппер - консольный риппер ripit.
2. Запись CD/DVD - K3b (увы, лучше него пока ничего не нашёл).
3. Аудио-плеер - DeadBeef.
4. Простановка тегов в музыкальных треках - ExFalso.
5. Видеоплеер - SMPlayer.

Разработка:

1. Редактор кода, в том числе C и HTML - Geany или vim-lite.
2. Текстовый редактор - LeafPad, MousePad.
3. Переводы страниц руководства - POEdit и po4a.

Разное:

1. Учёт личных финансов - GNUCash.

Ещё я пользуюсь рядом самописных и подсмотренных где-то скриптов. В частности это скрипты для конвертирования кодировок текстовых файлов (на основе iconv), конвертирования кодировок в тегах mp3-файлов (на основе mid3iconv из пакета python-mutagen), конвертирования из doc, rtf и html в текст (antidoc, unrtf и unhtml соответственно), скрипты переименования фотографий по EXIF-тегам (exiftool из пакета libimage-exiftool-perl), скрипты разбивки FLAC-файлов (shntool).

Я перестал пользоваться клиентами DC++, т.к. в уфанетовском хабе с некоторых пор наблюдается голяк. На первый план вышли torrent-трекеры.

Перестал пользоваться менеджером дисков Gnome Catalog, так как купил жёсткий диск на 1 Терабайт. Кроме того, запись дисков отнимает очень много времени, которого у меня теперь мало. Да и барахольщиком нынче быть не очень выгодно, т.к. тарифы на интернет стали очень дешёвыми - что угодно можно найти и быстро скачать из Интернета в любой момент.

Перестал вообще пользоваться двухпанельными менеджерами файлов. Это связано со предыдущими пунктами: дешёвые тарифы на интернет, распространение торрентов, объёмный жёсткий диск, нехватка времени - теперь реже нужно разгребать завалы файлов.

Перестал играть в компьютерные игры - нет времени. Стал читать вместо этого книги. Обычные, бумажные.

Изменения от 4 октября 2011:

Для просмотра PDF, PostScript и DjVu вместо программ KPDF, KGhostView и DjView4 теперь пользуюсь Evince.

Вместо FreeRDP теперь использую Remmina - менеджер подключений SSH, SFTP и RDP (и других, которыми не пользуюсь). Плагин RDP использует для подключения FreeRDP. Использую апплет Remmina для XFCE.

воскресенье, 31 июля 2011 г.

Перекодирование FLAC

Попались нестандартные FLAC-файлы с битрейтом 96 килогерц и с 24-битными сэмплами. Переделал в 44100-герцовые и 16-битные с помощью трёх команд:
$ flac -d infile.flac -o temp1.wav
$ sox temp1.wav -b 16 -r 44100 -t .wav temp2.wav
$ flac temp2.wav -o outfile.flac
Решил записать на память - может понадобится в будущем, а голову ломать второй раз не хочется.

четверг, 21 июля 2011 г.

Настройка DynDNS

Давно не приходилось пользоваться DynDNS, а потому не заметил, что у ddclient поменялся формат файла конфигурации. Теперь в файле конфигурации можно указывать несколько записей для обновления и мне теперь больше не нужны трюки, к которым я прибегал в заметке Настройка DynDNS на Debian.

Всё стало очень просто, как и должно быть. Файл конфигурации /etc/ddclient.conf:
pid=/var/run/ddclient.pid

protocol=dyndns2, \
  server=members.dyndns.org, \
  login=username, \
  password='mypassword', \
  use=if, \
  if=eth0, \
  ufadeb.homelinux.org

protocol=dyndns2, \
  server=members.dyndns.org, \
  login=username, \
  password='mypassword', \
  use=if, \
  if=ppp0, \
  stupin.homelinux.org
Файл настройки параметров демона /etc/default/ddclient:
run_ipup="false"
run_daemon="true"
daemon_interval="60"
Затем я запустил демона с помощью команды
/etc/init.d/ddclient start
и всё заработало.

среда, 13 июля 2011 г.

Xinerama: монитор и телевизор

Примерно год назад у меня дома случилась перестановка мебели, в результате которой телевизор стал стоять недалеко от компьютера. Тогда же мне пришла в голову мысль подключить телевизор к компьютеру для более удобного просмотра фильмов. Но, прошёл почти год, прежде чем у меня появилось достаточно свободного времени, чтобы этим заняться. Сейчас я в отпуске и решил этим заняться.

Хочу заранее сказать, что я не любитель отслеживать разного рода новинки в области компьютерной и видеотехники. Телевизор этот купила моя жена, когда ещё начала работать, с ней мы тогда не были знакомы. Компьютер с этой видеокартой (NVidia GeForce 6600) я купил где-то в начале 2006 года, когда мой старый компьютер стал намертво виснуть при повышенной нагрузке на процессор (архивирование, просмотр некоторых фильмов, просмотр флеша). Старый компьютер модернизации не подлежал и поэтому из старого компьютера в новый попал только привод DVD-RW, который позже сломался и был заменён на другой.

Есть люди, которым нравится покупать все новинки компьютерной и видеотехники. Им вряд ли будет интересно читать всё нижеследующее, потому что всё это уже давно устарело. Эти люди будут любят задавать вопросы "зачем тебе этот хлам" и раздавать ценные советы вида "купи себе то-то и то-то и не возись с этим барахлом". Заранее прошу таких людей не беспокоить меня.

Итак, перво-наперво, нужно было купить кабели для соединения телевизора и компьютера.

Я обследовал видеокарту и нашёл там разъём S-Video (собственно, я и так знал, что он там есть). Один друг мне до этого рассказывал, что он тоже подключал телевизор к компьютеру (правда под Windows) и сказал, что с этим кабелем он намучился, потому что их бывает несколько разных видов. Я это вспомнил, внимательно рассмотрел разъём и поискал его в интернете. Нашёл вот такую статью Разъёмы S-Video, применяемые в видеокартах и убедился в том, что у меня на видеокарте именно разъём S-Video, стандартный 4-контактный.

Этот разъём может работать в двух режимах:
  1. Композитный - по одному проводу передаются все три сигнала Y (яркость), Cr или U (разница между яркостью и синим), и Cb или V (разница между яркостью и красным). Сигналы мультиплексирются видеокартой и демультиплексируются телевизором. Обеспечивает менее качественную картинку, поскольку не может устранить взаимовлияние сигналов яркости и цвета.
  2. S-Video - по одному проводу передаётся сигнал яркости Y, а по другому - мультиплексированный сигнал цвета Cr или U (разница между яркостью и синим), и Cb или V (разница между яркостью и красным). Обеспечивает более качественную картинку, поскольку исключается взаимовлияние сигнала яркости и сигнала цветности. Более подробно об этом написано в статье Особенности преобразования сигналов VGA в TV.
Самым лучшим вариантом был бы компонентный сигнал, при котором каждый компонент передаётся по отдельному проводу. Но, к сожалению, мой разъём S-Video такого варианта обеспечить не может, его могут обеспечить 7-контактный или 9-контактный варианты разъёма S-Video. Подробнее об этом можно почитать, например, здесь: Подключение компьютера к телевизору.

Ещё можно было бы попробовать воспользоваться разъёмом DVI, имеющимся на видеокарте, но забегая вперёд скажу, что переходников DVI на 3 RCA я не нашёл ни в каком виде. Если найду - опробую этот вариант.

Затем я обследовал телевизор. На телевизоре оказалось огромное количество разъёмов типа "Тюльпан", которые правильно называются RCA.

Фото задней панели телевизора:

Разъёмы на задней панели выделены в 3 группы:
1 группа. 5 разъёмов для подключения DVD-плеера с развёрткой на 480 строк:
  1. Y,
  2. U или Cr,
  3. V или Cb,
  4. левый аудио,
  5. правый аудио.
2 группа. 3 разъёма для видеовхода:
  1. композитный,
  2. левый аудио,
  3. правый аудио.
3 группа. 3 разъёма для видеовыхода:
  1. композитный,
  2. левый аудио,
  3. правый аудио.
Фото передней панели телевизора:

Разъёмы на передней панели:
4 группа:
  1. композитный,
  2. левый аудио,
  3. правый аудио.
Соответственно, вариантов подключения у меня оказалось не много - либо к группе 2 на задней панели, либо к группе 4 на передней панели. При этом используется композитный видеосигнал и два аудиосигнала. Это вариант подключения, обеспечивающий самое низкое качество видеосигнала.

Расстояние между телевизором и компьютером - примерно 2 метра. Итак, с кабелями я определился - мне нужны кабель S-Video-RCA и MiniJack-2RCA. Первая же попытка найти такие кабели в магазинах бытовой электроники окончилась неудачей - именно таких кабелей нигде не было. Вторая попытка оказалась успешной - я купил их в магазине, специализирующемся на продаже электронных компонентов. Были кабели длиной 1,5 метра и 3 метра, я взял трёхметровые.

Теперь дело стало за настройкой. Для начала воспользовался вот этой заметкой Подключение двух мониторов: Xinerama или TwinView?. Настроил Xinerama, т.к. мне показался этот способ более естественным для X-сервера.

Получился вот такой файл конфигурации /etc/X11/xorg.conf:
Section "ServerLayout"
  Identifier     "X.org Configured"
  Screen         "Screen0" 0 0
  Screen         "Screen1" RightOf "Screen0"
  InputDevice    "Mouse0" "CorePointer"
  InputDevice    "Keyboard0" "CoreKeyboard"
  Option         "Xinerama" "On"
EndSection

Section "Files"
  ModulePath      "/usr/lib/xorg/modules"
  FontPath        "/usr/share/fonts/X11/misc"
  FontPath        "/var/lib/defoma/x-ttcidfont-conf.d/dirs/TrueType"
EndSection

Section "Module"
  Load           "glx"
  Load           "dbe"
  Load           "record"
  Load           "extmod"
EndSection

Section "ServerFlags"
  Option         "AutoAddDevices" "False"
  Option         "AllowEmptyInput" "False"
  Option         "DontZap" "True"
EndSection

Section "InputDevice"
  Identifier     "Keyboard0"
  Driver         "kbd"
  Option         "XkbRules" "xorg"
  Option         "XkbModel" "pc104"
  Option         "XkbLayout" "us,ru"
  Option         "XkbOptions" "grp:alt_shift_toggle"
  Option         "XkbVariant" ",winkeys"
  Option         "AutoRepeat" "250 30"
EndSection

Section "InputDevice"
  Identifier     "Mouse0"
  Driver         "mouse"
  Option         "Protocol" "auto"
  Option         "Device" "/dev/input/mice"
  Option         "ZAxisMapping" "4 5 6 7"
EndSection

Section "Monitor"
  Identifier     "Monitor0"
  VendorName     "LG"
  ModelName      "Flatron L1730S"
  DisplaySize     338    270
  HorizSync       30.0 - 80.2
  VertRefresh     56.0 - 75.0
  ModeLine       "1280x1024_75.00" 138.54 1280 1368 1504 1728 1024 1025 1028 1069 -hsync +vsync
  ModeLine       "1024x768_75.00" 81.80 1024 1080 1192 1360 768 769 772 802 -hsync +vsync
  ModeLine       "800x600_75.00" 48.91 800 840 920 1040 600 601 604 627 -hsync +vsync
  ModeLine       "640x480_75.00" 30.72 640 664 728 816 480 481 484 502 -hsync +vsync
  Option         "DPMS"
EndSection

Section "Monitor"
  Identifier     "Monitor1"
  VendorName     "LG"
  ModelName      "Flatron RT-21FA32X"
  DisplaySize    450 350
  HorizSync      15.625 - 15.625
  VertRefresh    50.0 - 50.0
  Option         "DPMS"
EndSection

Section "Device"
  Identifier     "Card0"
  Driver         "nvidia"
  VendorName     "nVidia Corporation"
  BoardName      "NV43 [GeForce 6600]"
  BusID          "5:0:0"
EndSection

Section "Device"
  Identifier     "Card1"
  Driver         "nvidia"
  VendorName     "nVidia Corporation"
  BoardName      "NV43 [GeForce 6600]"
  BusID          "5:0:0"
  Screen         1
EndSection

Section "Screen"
  Identifier     "Screen0"
  Device         "Card0"
  Monitor        "Monitor0"
  DefaultDepth    24
  SubSection     "Display"
    Viewport    0 0
    Depth       8
    Modes      "1280x1024_75.00" "1024x768_75.00" "800x600_75.00" "640x480_75.00"
  EndSubSection
  SubSection     "Display"
    Viewport    0 0
    Depth       24
    Modes      "1280x1024_75.00" "1024x768_75.00" "800x600_75.00" "640x480_75.00"
  EndSubSection
  SubSection     "Display"
    Viewport    0 0
    Depth       32
    Modes      "1280x1024_75.00" "1024x768_75.00" "800x600_75.00" "640x480_75.00"
  EndSubSection
EndSection

Section "Screen"
  Identifier      "Screen1"
  Device          "Card1"
  Monitor         "Monitor1"
  DefaultDepth    24
  SubSection      "Display"
    Depth           24
    #Modes           "768x576"
    Modes           "800x600"
  EndSubSection
EndSection
Возможно, что некоторые настройки здесь избыточны и не необходимы для нормальной работы. Действительное разрешение S-Video 768x576 точек, поэтому я указал наиболее похожее из доступных - 800x600. Частоты вертикальной и горизонтальной развёртки для режима S-Video - 15,625 КГц и 50 Гц. Геометрические размеры растровой сетки телевизионного экрана - 450 на 350 мм (замерял линейкой).

Настройки монитора перекочевали из предыдущей конфигурации, где они были заданы явно, поскольку видеокарта по протоколу EDID принимает от монитора несколько заниженные режимы.

Действительные настройки видеокарты я смотрел с помощью программы nvidia-settings. Там можно найти доступные видеорежимы, посмотреть частоту вертикальной развёртки (действительная частота оказалась равной 60,32 Гц), можно отцентрировать картинку, задать её размеры на экране, настроить насыщенность цвета.

пятница, 22 апреля 2011 г.

Базы данных postgrey

Сегодня я заинтересовался содержимым баз данных Postgrey. Как известно, база данных Postgrey находится в каталоге /var/lib/postgrey/ и имеет формат Berkeley DB.

Собственно вся база находится в двух основных файлах: postgrey.db и postgrey_clients.db.

Для их просмотра нам понадобится пакет db4.6-utils. Точную версию необходимого пакета можно выяснить, если изучить зависимости самого postgrey. У меня в дистрибутиве Debian Squeeze было три различных версии этого пакета, из которых подошла только версия 4.6.

В файле postgrey.db находятся триплеты тестируемых отправителей.

Просмотреть их можно следующей командой:
$ db4.6_dump -p postgrey.db | less
Нашему взору предстанет таблица с записями двух видов:
95.111.111.9/uzowu@sender.hu/ufa03@receiver.ru
1303233971,1303234277
и
95.138.211.0/vasiliy@sender.ru/sln@receiver.ru
1303295139,1303295139,90
Это два способа записи одной и той же информации. Первый вид расшифровывается следующим образом:
IP-адрес отправителя/почтовый адрес отправителя/почтовый адрес получателя
отметка времени первой попытки отправки,отметка времени второй попытки отправки
Второй вид, насколько я понял анализируя исходник postgrey, соответствует случаю если в PTR-записи IP-адреса отправителя найдено одно последнее число из IP-адреса или два последних числа IP-адреса. То есть соответствует случаю заведомо динамического IP-адреса отправителя. Очень редко в домен попадает последнее число IP-адреса или сразу два последних числа из IP-адреса - в основном это соответствует именно случаю динамического IP-адреса. В таком случае postgrey откусывает у IP-адреса последнее число, заменяя его на ноль. Само откушенное число добавляется в конец записи. Указанный выше случай соответствует IP-адресу 95.138.211.90. То есть во втором случае формат такой:
IP-адрес отправителя с последним числом заменённым на 0/почтовый адрес отправителя/почтовый адрес получателя
отметка времени первой попытки отправки,отметка времени второй попытки отправки, последнее число из IP-адреса
Не совсем понимаю зачем это сделано, я с этим не разбирался. Скорее всего - для ускорения поиска динамических клиентов-отправителей. Такому клиенту скорее всего каждый раз будет выдаваться не сильно отличающийся от предыдущего IP-адрес, поэтому чтобы не множить триплеты и не заставлять такого клиента каждый раз пробиваться через процедуру проверки, повторные проверки выполняются только в случае отличия одного из первых трёх чисел IP-адреса. Но это - всего лишь мои догадки. Если вам интересно - изучайте исходники внимательнее.

Второй файл postgrey_clients.db используется для автоматического помещения IP-адресов отправителей в белый список. Посмотреть его можно следующей командой:
$ db4.6_dump -p postgrey_clients.db | less
Видим много записей следующего вида:
1.122.11.90
1,1303296308
Что здесь что?
IP-адрес отправителя
количество удачных отправок,отметка времени последней отправки
Опция --auto-whitelist-clients=10, заданная в настройках демона, указывает, после какого количества успешных отправок IP-адрес отправителя будет помещён в белый список. Эта база используется как раз для отслеживания клиентов, претендующих на помещение в белый список.

Опция --max-age=30 действует на оба списка и говорит о том, что записи, время последней отправки которых старше 30 дней, будут удалены. Таким образом записей с последней попыткой отправки бывшей более 30 дней назад, в базе быть не должно.

Для того, чтобы загнать отредактированную информацию обратно в базу данных, можно воспользоваться командой db4.6_load:
$ db4.6_dump -p postgrey.db > base
$ vi base
$ db4.6_load postgrey.db < base
Возможно перед загрузкой информации в базе данных придётся остановить postgrey. И не забудьте при экспериментах по редактированию делать резервные копии. Лучше - всего каталога после остановки postgrey.

Как воспользоваться полученной информацией, я пока не придумал. Например, можно составить рейтинг отправителей по IP-адресам, а можно составить рейтинг пар отправитель/получатель. Можно добавлять записи вручную (только зачем?), а можно удалять записи. Если придумали что-нибудь интересное, отпишитесь.

четверг, 14 апреля 2011 г.

Настройка автодополнения адреса в Firefox

Меня уже пару лет подбешивает автодополнение адреса в Firefox. Когда я ввожу адрес в адресную строку вручную, то я ввожу известный мне адрес сайта. Кроме адресов сайтов я туда больше никогда и ничего не ввожу. Но услужливый Firefox при вводе первой же буквы вываливает на меня чуть ли не всё содержимое адресной книги, журнала посещённых страниц, скопированных и вставленных откуда-нибудь ссылок и введённых в прошлом сайтов. Из всего этого хлама мне пригодился бы только последний пункт. Но я, будучи обладателем ангельского терпения и чудовищной лени, постоянно забивал на это всю эту пару лет.

И вот, наконец-то, я решил уделить полчаса своего времени на поиск решения и на его описания на будущее, если оно мне вдруг снова потребуется.

Итак, интересующие нас настройки находятся, понятное дело, на странице с адресом about:config. За настройки адресной строки отвечают параметры с именами, начинающимися с browser.urlbar. Из всех этих настроек мне нужны только две: browser.urlbar.default.behavior и browser.urlbar.matchBehavior

Параметр browser.urlbar.default.behavior представляет собой шестибитное значение, каждый из битов которого указывает, по каким источникам осуществлять автодополнение. Значение этого параметра может быть представлено в виде суммы следующих чисел:

1 Ограничить поиск только историей
2 Ограничить поиск только закладками
4 Ограничить поиск только метками
8 Искать совпадения в названии страницы
16 Искать совпадение в адресе страницы
32 Искать совпадение только с ранее введёнными адресами

Итак, моему желанию соответствует сумма 16 и 32, поэтому я задаю значение этого параметра равным 48.

Параметр browser.urlbar.matchBehavior может принимать одно из следующих значений:

0 Искать где угодно в доступном тексте, не обращая внимания на границы слов.
1 Искать в пределах слов перед тем, как искать во всём доступном тексте, не обращая внимания на границы слов. (По умолчанию)
2 Искать только в пределах слов в автодополнении адресной строки.
3 Подходят только начала адресов и названий страниц.

Мне нравится значение 3.

После этих настроек в строке адреса выпадают только те ресурсы, адреса которых начинаются с указанных букв.

Всё описанное выше сработало для Firefox версии 3.6.16.

пятница, 25 марта 2011 г.

Настройка NetFlow сенсора на Cisco и коллектора на Debian

В прошлом году, в середине декабря, вышестоящее руководство по моему департаменту запросило суточную статистику в разрезе по IP-адресам по загрузке канала, соединяющего наш филиал с корпоративной сетью. Канал этот с нашей стороны заходит на один из портов маршуртизатора Cisco 2821. Недолго думая я решил прибегнуть к проверенному средству - NetFlow и пакету flow-tools. Может потом когда-нибудь пригодится мне или кому-нибудь ещё.

Для начала настроим NetFlow-сенсор на маршрутизаторе:
ip flow-export version 5
ip flow-export destination 192.168.0.1 9000
ip flow-export source GigabitEthernet 0/0
ip cef

interface GigabitEthernet 0/1
  ip flow ingress
  ip flow egress
  ip route-cache flow
  no ip mroute-cache
192.168.0.1 - это адрес компьютера, на котором настроен коллектор,
9000 - это UDP-порт на этом компьютере, куда будет сыпаться статистика,
GigabitEthernet 0/0 - это интерфейс, с которого будет исходить поток статистики,
GigabitEthernet 0/0 - это интерфейс, статистика трафика которого будет сниматься.

Теперь пришёл черёд NetFlow-коллектора. Поставим пакет flow-tools:
# apt-get install flow-tools
И зададим настройки коллектора в файле /etc/flow-tools/flow-capture.conf:
-w /var/flow/cisco2821 -n 24 -N 3 192.168.0.1/192.168.0.2/9000
/var/flow/cisco2821 - каталог с отловленными файлами потоков,
192.168.0.1 - адрес компьютера, а точнее - того интерфейса, на который льётся поток,
192.168.0.2 - адрес маршуртизатора Cisco 2821, с которого будет идти поток,
9000 - UDP-порт компьютера, на который будет сваливаться поток,
24 - количество ротаций журналов с потоком в сутки (по какой-то непонятной причине количество ротаций и момент их срабатывания всё-же не поддаются точному расчёту, поэтому это лишь приблизительная настройка),
3 - расфасовка файлов по подкаталогам вида YYYY/YYYY-MM/YYYY-MM-DD/

Обязательно нужно создать каталог для файлов /var/flow/cisco2821/:
# mkdir -p /var/flow/cisco2821/
И можно запускать коллектор:
# /etc/init.d/flow-capture start
С помощью следующей команды нужно убедиться, что коллектор запустился и приступил к работе:
# netstat -4nlp | grep 9000
Нужно также не забыть проковырять дырочку в пакетном фильтре, чтобы он не отбрасывал пакеты (это вы сделайте сами).

Пока статистика собирается, можно заняться фильтрами. Например, можно создать фильтр, отбирающий статистику только за рабочее время (хотя была запрошена в первую очередь суточная статистика). Например, в файл /etc/flow-tools/cfg/filter.cfg пропишем вот такие правила:
filter-primitive work-time-start
  type time
  permit gt 9:00

filter-primitive work-time-end
  type time
  permit lt 18:00

filter-definition work-time
  match start-time work-time-start
  match end-time work-time-end
Теперь этот фильтр можно использовать в команде flow-nfilter, которую можно включить в конвейер:
$ cd /var/flow/cisco2821/2010/2010-12/2010-12-16/
$ flow-cat ft-v05.2010-12-16.1* \
  | flow-nfilter -f /etc/flow-tools/cfg/filter.cfg -Fwork-time \
  | flow-stat -f10 > stat.txt
flow-cat объединяет отобранные файлы за сутки 2010-12-16,
flow-filter отбирает из объединённого потока ту информацию, которая соответствует правилу work-time,
flow-stat с опцией -f10 создаёт отчёт из пяти колонок: IP-адрес отправителя, IP-адрес получателя, количество соединений (уникальных триплетов протокол/порт-отправителя/порт-получателя), количество байт, количество пакетов.

Декодирование писем в формате TNEF в Postfix

Вчера столкнулся с интересной проблемой, корень которой в очередной раз нашёлся в Microsoft. Один из сотрудников пожаловался, что некоторые письма к нему приходят без вложений. Я попытался разобраться в ситуации и выяснил, что письма в почтовом клиенте имеют точно такой же размер, какой они имеют, когда их принимает Postfix. Стало быть почтовый сервер, почтовый клиент, антивирус на сервере и на компьютере почтового клиента никаких изменений в письма не вносят.

Потом я обратил внимание на размер письма (несколько сотен килобайт) и на отображаемый в клиенте текст. Письмо было явно слишком большим для такого небольшого объёма информации. Я заглянул в исходный текст письма и обнаружил, что в нём имеется вложение с именем файла "winmail.dat" и MIME-типом "application/ms-tnef".

Я заинтересовался, а что же это вообще такое и обнаружил, что это изобретённый Microsoft новый формат для писем, а понимают его только почтовые клиенты Outlook и те клиенты, разработчики которых специально озаботились этой проблемой. Письмо открывалось с помощью изделия той же фирмы Microsoft - Outlook Express, но изделие молча игнорировало попытки старшего брата донести до него информацию.

Первым делом я нашёл рецепт отключения этой фичи в Outlook отправителя
Файлы winmail.dat в письмах и отправил эту ссылку отправителю.

Предвидя возможные повторы этой проблемы и необходимость снова и снова отправлять эту ссылку разным людям, я поискал, а нельзя ли этот TNEF преобразовывать прямо на сервере? Нашёл следующую заметку Postfix + ytnef filter, которая, к слову, была написана всего полтора месяца назад. Так что если бы я столкнулся с проблемой раньше, возможно мне так и пришлось бы отправлять людям ссылку.

Там описывается настройка прокси-конвертера ytnef smtpd для FreeBSD. Поскольку у меня сервер работает под Debian Lenny, я решил выложить тут адаптированный вариант, а иначе просто ограничился бы ссылкой.

Итак, перво-наперво, ставим сам конвертер ytnef и python:
# aptitude install --with-recommends ytnef
# aptitude install python
Качаем архив со скриптом по ссылке и распаковываем его:
$ wget http://www.viraj.org/ytnef_smtpd/ytnef_smtpd-1.1.tar.gz
$ tar xzvf ytnef_smtpd-1.1.tar.gz
$ cd ytnef_smtpd-1.1
Копируем скрипт туда, где ему положено лежать:
# cp ytnef_smtpd.py /usr/local/bin/
# chmod +x /usr/local/bin/ytnef_smtpd.py
И меняем настройки скрипта, которые находятся в нём самом-же. У меня в Postfix уже есть два прокси, первый сканирует письма на предмет наличия вирусов, а второй проставляет оценки уровня спама. Наша задача - встроить новый прокси в начало цепочки, чтобы сначала письмо преобразовывалось, а затем уже проверялось и оценивалось.

Приведу лишь изменённые строки:
LISTEN_PORT = 10028
REMOTE_PORT = 10026
YTNEF_BIN = '/usr/bin/ytnef'
FILE_BIN = '/usr/bin/file'
LOG_FILE = '/var/log/ytnef_smtpd.log'
Скрипт будет ожидать подключений к порту 10028, а преобразованное письмо будет отправлять на порт 10026, где его будет ловить уже антивирус.

Теперь создадим скрипт автозапуска /etc/init.d/ytnef_smtpd.sh (он немного отличается от оригинала):
#!/bin/sh

case "$1" in
  start)
    if [ -f /var/run/ytnef_smtpd.pid ]
    then
      echo "Script already launched. PID: "`cat /var/run/ytnef_smtpd.pid`"
    else
      echo "Starting ytnef smtpd..."
      /usr/local/bin/ytnef_smtpd.py &
      echo $! > /var/run/ytnef_smtpd.pid
      echo "...Done!"
    fi
    ;;
  stop)
    if [ -f /var/run/ytnef_smtpd.pid ]
    then
      echo "Shutting down ytnef smtpd..."
      kill -TERM `cat /var/run/ytnef_smtpd.pid`
      rm -f /var/run/ytnef_smtpd.pid
      echo "...Done!"
    else
      echo "ytnef smtpd not launched."
    fi
    ;;
  *)
    echo "Use start script for: { start | stop }" >&2
    exit 1
    ;;
esac
Пропишем его автозапуск и запустим:
# chmod +x /etc/init.d/ytnef_smtpd.sh
# update-rc.d ytnef_smtpd.sh defaults
# /etc/init.d/ytnef_smtpd.sh start
Теперь скрипт должен прослушивать порт 10028, это можно проверить следующей командой:
# netstat -nlp4 | grep 10028
Если это так, значит пока что всё идёт нормально.

Теперь нужно перенастроить Postfix, так чтобы он перенаправлял только что полученные письма на обработку ytnef smtpd.

В файле /etc/postfix/main.cf прописываем порт первого прокси в цепочке (в нашем случае это порт ytnef smtpd - 10028):
content_filter = scan:127.0.0.1:10028
И если до этого у вас не было прокси, добавляем в файл /etc/postfix/master.cf следующие строчки (обратите внимание на пробелы в начале всех строк, кроме первой):
127.0.0.1:10025 inet n - n - 16 smtpd
  -o content_filter=
  -o receive_override_options=no_unknown_recipient_checks,no_header_body_checks
  -o smtpd_helo_restrictions=
  -o smtpd_client_restrictions=
  -o smtpd_sender_restrictions=
  -o smtpd_recipient_restrictions=permit_mynetworks,reject
  -o mynetworks_style=host
  -o smtpd_authorized_xforward_hosts=127.0.0.0/8
Эти строчки настроят ещё один smtp-сервер, который будет принимать письма на порту 10025 только от локальных программ, но при этом не будет отправлять письма на дальнейшую проверку. Именно этот порт необходимо указать в настройке "REMOTE_PORT", если у вас больше нет никаких прокси в цепочке.

Осталось перезапустить postfix и всё должно заработать:
# /etc/init.d/postfix restart
Я специально ради этого устанавливал себе на компьютер Outlook, отправил из него письмо в формате tnef и принял в Outlook Express. Письмо прочиталось вместе с вложениями.