![]() ![]() |
![]() |
![]() |
Ссылка на пост #1 |
W&P Team
![]() ![]() ![]() ![]() ![]() Живой человек
Сообщений: 1,948 На форуме с: 11.03.02
Провел: 1нед. 5д. 11ч. 51мин. |
Ролезные решения на платформе FreeBSD
Я конечно обещал статьи пока не писать :), но все равно пишу инструкцию, так что.
Архивирование unix по простому. Итак, забудем пока про всякие ArcServe и прочие умные (дорогие) вещи с умением бакапить unix на ленты. Поговорим про родные, встроенные и бесплатные средства резервного копирования данных. Ессессенно, они поскромнее в возможностях, чем ArcServe, но порой дают вполне сопоставимые результаты. Что на потребуется: 1. Знать пароли рута на бакапируемых машинах. 2. Машина, на которую будем сливать копии (у меня как правило стоит "лишний" unix, который способен быстро подменить любой из работающих. то есть на нем установлены все продукты, используемые на прочих unix, остается подложить настройки, данные и подменить ip). На этой машине должен быть ftp-сервер. Как правило, одной из функций unix и является ftp-сервер, так что на "лишней" машине он у меня установлен. 3. Стандартные утилиты unix - tar, gzip (или compress, по вкусу), ftp. Ну, поехали. Создаем каталог со скриптами копирования. Я предпочитаю использовать каталог типа /root/backup или /root/save. Пишем в него следующий скрипт (назовем его backup.sh): Код:
#!/usr/local/bin/bash # Определим имя машины NAME=`uname -n`; export NAME #Упакуем нужные нам каталоги # /etc tar cvf /root/save/etc.tar /etc >/dev/null # /chroot tar cvf /root/save/chroot.tar /chroot >/dev/null # Для BSD систем - /usr/local/etc tar cvf /root/save/usr-local-etc.tar /usr/local/etc >/dev/null # /var/log tar cvf /root/save/var-log.tar /var/log >/dev/null # настройки пользователей как правило лежат в файлах, начинающихся на точку tar cvf /root/save/home.tar /home/*/.* >/dev/null # ну и всякие специальные данные, типа данных ftp-сервера. Oracle так конечно не # забакапишь, но мы же делаем простую дешевую систему :) tar cvf /root/save/ftp.tar /data/ftp >/dev/null # Сжимаем полученные архивы gzip -f *.tar # Собираем их в один файл с именем машины tar cvf $NAME.tar *.tar.gz # Освобождаем место :) rm *.tar.gz # Засылаем данные ftp -i backup </root/save/cmd # Чистим место rm $NAME.tar Сразу оговорки :). Необходимо достаточное количество места в том каталоге, куда будем бакапить. Минимум двойной запас по сравнению с объемом бакапа. Идеально использовать для этого отдельную файловую систему (у меня /root всегда отдельная FS), переполнение которой не повредит работе ОС. Если вы используете compress, то расширение файлов будем .Z. И zgip, и compress заменяют сжимаемый файл сжатым - то есть беспокоиться об удалении первых файлов .tar не надо. Теперь про ftp. На целевой машине создаем пользователя с правами доступа только по ftp, именем и паролем. Даем ему права записи в какой-то каталог, куда мы собираемся бакапиться. Лучше сделать этот каталог его домашним и указать этого пользователя в /etc/ftpchroot. На машине, копию которой будем делать, добавляем следующие настройки: В /etc/hosts прописываем название машины backup и ее ip. Это для того, чтобы бакап не зависел от работы dns-сервера. А для того, чтобы ftp работал без вопросов и участия пользователя, в домашнем каталоге пользователя root создаем файлик .netrc с правами доступа к нему 600 или 400 (00 обязательно!) и примерно следующего содержания: Код:
machine backup login логин password пароль Код:
lcd /root/save bin mput *.tar quit И добавляем в crontab (системный или рутовый) запуск /root/save/backup.sh. Периодичность этого запуска зависит от частоты изменения данных и от их важности. Например, dns сервер я сливаю каждые 20 минут, логи почты, cisco и web-сервера - каждый час, а всякие почтовые релеиб ftp-сервера и пр. - раз в сутки. Все! Поскольку результирующих .tar содержит имя машины, то у нас в целевом каталоге на целевой машине лежит N .tar файлов, относящихся к разным машинам. Теперь мы можем сливать их на стриммер, подключенный к этой машине, или забирать в общий бакап arcserve, или просто там хранить - это же дополнительная, резервная машина! Теперь ответ на вопрос "а нахрена?!". Рассказываю - во-первых, дешево и сердито. Во-вторых, если у Вас по каким-то причинам завалиться система (RAID развалиться, motherboard сгорит, ...) , то и установленный в нее стриммер будем вам совсем без радости. Все равно нужна будет машина, на котрой можно временно, но быстро поднять функции умершей. А так все настроечки на ней уже лежат. А ежели на ней есть стриммер (или место позволяет и мы cron`ом переименовываем старые файлы), то лежат настроечки за неделю :)). Ну вот так. Дополнения принимаются. Редактировалось Smithson 04-03-2008 11:41. |
![]() ![]() |
![]() ![]() |
![]() |
Ссылка на пост #2 |
Гость
|
Smithson: спасибо :) А мне больше по душе конструкция вида:
Код:
tar cvfz /patch/to/arc/archive.tar.gz * |
![]() |
![]() |
![]() |
Ссылка на пост #3 |
W&P Team
![]() ![]() ![]() ![]() ![]() Имею пределы
Сообщений: 3,424 На форуме с: 29.10.02
Провел: 1мес. 2нед. 4д. 18ч. 46мин. |
Smithson:Не, все нормально и имхо правильно, это МАСТЕР-бой перегибает уже -)) Вернее недогибает имхо :о))
[offtopic] К ЛюдЯм надо относится лутше! А на вопросы смотреть ширше! -(с) [offtopic] А Ораклы ты как бекапишь? __________________ |
![]() ![]() |
![]() |
![]() |
Ссылка на пост #4 |
Гость
|
* тщательно выцеливает гадкого Triiler'aQ из rail'a...
|
![]() |
![]() |
![]() |
Ссылка на пост #5 |
W&P Team
![]() ![]() ![]() ![]() ![]() Живой человек
Сообщений: 1,948 На форуме с: 11.03.02
Провел: 1нед. 5д. 11ч. 51мин. |
Macmep: Вообщем-то ты прав, просто та система, на которой я это рожал в первый раз, ключ z еще не поддерживала :))
KillerLoo: А ораклы я бакаплю либо стандбаем, либо арксервом :). |
![]() ![]() |
![]() ![]() |
![]() |
Ссылка на пост #6 |
Гость
|
* всегда прав :)
(шютка) Smithson: предлагаю нещадно тереть мой флуд и грохать флеймы! =) |
![]() |
![]() |
![]() |
Ссылка на пост #7 |
W&P Team
![]() ![]() ![]() ![]() ![]() Имею пределы
Сообщений: 3,424 На форуме с: 29.10.02
Провел: 1мес. 2нед. 4д. 18ч. 46мин. |
Ну тут дискутировать и обсуждать? Или маны и методы?
* KillerLoo непрерывно качает маятник и фиг в него Мастер попадет! |
![]() ![]() |
![]() |
![]() |
Ссылка на пост #8 |
Гость
|
KillerLoo:
Цитата: > Ну тут дискутировать и обсуждать? Или маны и методы? А по-моему одно другому только на пользу? Я вот закончу ваять тут кой-чего и засяду статейки кропать :) А пока Mr. Smithson тут сам чудесно справляется, за что ему респект. :) |
![]() |
![]() |
![]() |
Ссылка на пост #9 |
Серфер
На форуме с: 17.07.04
Провел: 4ч. 50мин. |
По сети гонять tar овые архивы неоптимально. гораздо удобнее использовать rsync и прочие программы использующие его алгоритм синхронизации. Например unison или duplicity.
Мне по душе связка duplicity + patch для MC. Хотя я пока как раз пока пользуюсь таром. но как только придет новый сервер буду исправляться. патч |
![]() ![]() |
![]() |
![]() |
Ссылка на пост #10 |
Серфер
На форуме с: 17.07.04
Провел: 4ч. 50мин. |
Бакапим на usb
Продолжене темы:
А ежели у вас вмето ленты USB винты - наиболее практичное устройство. то при смене этих устройств вам нужно их монтировать размонтировать. чтобы не делать это руками добавим: [CODE] MOUNTPOINT=/mnt/usb DEVLABEL=/sbin/devlabel DEVLABELCONFIG=/etc/sysconfig/devlabel IAM=$0 function allAttachedScsiUsb { find /proc/scsi/ -path '/proc/scsi/usb-storage*' -type f | xargs grep -l 'Attached: Yes' } function scsiDevFromScsiUsb { echo $1 | awk -F"[-/]" '{ n=$(NF-1); print "/dev/sd"substr("abcdefghijklmnopqrstuvwxyz", n+1, 1) }' } for procEntry in $(allAttachedScsiUsb); do scsiDev=$(scsiDevFromScsiUsb $procEntry) # Some bug with usb-storage? # partitions are not in /proc/partitions until they are accessed # somehow. /sbin/fdisk -l $scsiDev >/dev/null ## # Most devices have partitioning info, so the data would be on # /dev/sd?1. However, some stupider ones don't have any partitioning # and use the entire device for data storage. This tries to # guess semi-intelligently if we have a /dev/sd?1 and if not, then # it uses the entire device and hopes for the better. # if grep -q 'basename $scsiDev'1 /proc/partitions; then part=$scsiDev else part="$scsiDev""1" fi echo $part done #check if we already mount it if grep -q "$MOUNTPOINT" /etc/mtab; then echo "usb already mounted" else mount -o noatime $part /mnt/usb/ >>/dev/null fi #------------shutdown-------------# if grep -q "$MOUNTPOINT" /etc/mtab; then # unmount cleanly echo "umount " umount -l $MOUNTPOINT fi #------------end_of_shutdown--------# |
![]() ![]() |
![]() |
![]() |
Ссылка на пост #11 |
W&P Team
![]() ![]() ![]() ![]() ![]() Живой человек
Сообщений: 1,948 На форуме с: 11.03.02
Провел: 1нед. 5д. 11ч. 51мин. |
Keeping FreeBSD Up-to-Date: A Security Odyssey
Статья про постоянный update FreeBSD. В общем-то, релизы FreeBSD достаточно стабильны, так что можно и рискнуть.
Читать Скачать в виде pdf |
![]() ![]() |
![]() ![]() |
![]() |
Ссылка на пост #12 |
Гость
|
Полезные решения на платформе FreeBSD.
Ну что еще делать человеку накануне НГ? :) Наверное задуматься о подведении итогов прошедшего года или, как вариант, задуматься о заделе на следующий. :) Я, собственно, давно собирался разродиться циклом статей по *nix'ам, но хронически не хватало времени. Может быть и опять не хватит, так как планов на праздники громадьё, как говориться, но однако попробую. Итак, лирическое отступление, оно же вступление, закончено и перехожу непосредственно к изложению материала. :)
Сперва задумки ака содержание или, как учили в славной советской средней школе, напишем план сочинения. У кого со словом план возникают другие ассоциации, тот может дальше не читать, а смело отправляться курить бамбук. :) 1. Почему именно FreeBSD? 2. Chroot vs jail достоинства и недостатки. 3. Stunnel, как оружие пролетариата. 4. 3proxy - джентльменский набор сервисов. 5. Итоги, дополнения, исправления, пожелания и планы на будущее. Ну и приступим, пожалуй. :) Глава 1. Почему именно FreeBSD? Я уже как то высказывал свои соображения на эту тему но не побоюсь повториться. Группа разработчиков системы чрезвычайно внимательно следит за появлением новых уязвимостей в сервисах и старается максимально быстро выпускать к ним патчи. Коллекция портов содержит практически все необходимые утилиты, составляется специально с учетом особенностей системы, регулярно обновляется, при этом изменения вносятся в Makefile, как при появлении новых версий программ, так и при добавлении патчей к старым. Мощная утилита portaudit (/usr/port/security/portaudit) при установке добавляется в скрипты periodic daily и регулярно апдейтит базы уязвимостей с серверов проекта. В случае обнаружения уязвимого сервиса в системе сообщение об этом выдается в отчетах periodic daily, которые совсем не вредно регулярно просматривать. Установка portaudit абсолютно тривиальна. Сперва устанавливаем самое свежее дерево портов, что полезно производить перед каждой установкой утилит. Делается это с помощью CVSup, и этот процесс подробно описан во многих местах в рунете. Выглядит это, например, так: Код:
vi /etc/cvsupfile *default host=cvsup.FreeBSD.org *default base=/usr *default prefix=/usr *default release=cvs *default tag=RELENG_4_10 *default delete use-rel-suffix *default compress *default tag=. ports-all /usr/local/bin/cvsup -g -L 2 -P - /etc/cvsupfile Подразумевается, что пакет CVSup уже установлен в системе, так как после установки фри на комп - он наш верный и надежный друг на весь период существования сервера под управлением FreeBSD. :) Тепер ставим собственно portaudit. Код:
cd /usr/ports/security/portaudit make install clean После успешной установки утилиты читаем добрый совет: Код:
===> To check your installed ports for known vulnerabilities now, do: /usr/local/sbin/portaudit -Fda И делаем это незамедлительно с, например такими результатами: Код:
/usr/local/sbin/portaudit -Fda auditfile.tbz 100% of 16 kB 41 kBps New database installed. Database created: Fri Dec 31 21:40:17 MSK 2004 Affected package: wget-1.8.2_6 Type of problem: wget -- multiple vulnerabilities. Reference: <http://www.FreeBSD.org/ports/portaudit/06f142ff-4df3-11d9-a9e7-0001020eed82.html> Affected package: FreeBSD-491000 Type of problem: multiple vulnerabilities in the cvs server code. Reference: <http://www.FreeBSD.org/ports/portaudit/d2102505-f03d-11d8-81b0-000347a4fa7d.html> Note: To disable this check add the uuid to `portaudit_fixed' in /usr/local/etc/portaudit.conf 1 problem(s) in your installed packages found. You are advised to update or deinstall the affected package(s) immediately. Это уже информация к размышлению. :) Быстро бежим в каталог с wget Код:
cd /usr/ports/ftp/wget www-/usr/ports/ftp/wget# ls -lt total 10 drwxr-xr-x 2 root wheel 512 Jul 5 09:02 files -rw-r--r-- 1 root wheel 194 Mar 18 2004 distinfo -rw-r--r-- 1 root wheel 1470 Feb 4 2004 Makefile -rw-r--r-- 1 root wheel 1144 Oct 16 2003 pkg-plist -rw-r--r-- 1 root wheel 510 Jan 15 2001 pkg-descr Результат весьма грустный - свежих патчей не наблюдается. На всякий случай просматриваем distinfo Код:
www-/usr/ports/ftp/wget# vi distinfo MD5 (wget-1.8.2.tar.gz) = a2473d7a53ebaf0a1bdb06f17059e8f1 SIZE (wget-1.8.2.tar.gz) = 1154648 MD5 (wget_1.8.2-12.diff.gz) = 6017ad7231afb85ac37a2b975203fc40 SIZE (wget_1.8.2-12.diff.gz) = 34921 Ну и вариантов два. Первый - оставить утилиту и использовать ее на свой страх и риск до момента выхода патча. Второй - снести ее к едрене Фене, подыскав недырявую альтернативу в тех же портах, например. http://freebsd.org/ports + search помогут нам в этом вопросе. :) Редактировалось Macmep 12-01-2005 10:57. |
![]() |
![]() |
![]() |
Ссылка на пост #13 |
Гость
|
Глава 2. Chroot vs jail достоинства и недостатки.
Оговорюсь сразу, что данные статьи отнюдь не отменяют необходимость RTFM, как залога успеха. Внимательное прочтение man – это 90% успешного решения задачи. Я постараюсь максимально доступно изложить все на конкретных примерах, но сразу скажу, что эти решения возникли после длительного копания мануалов и гугля. Еще одно немаловажное замечание – все сказанное в этих статьях применено и работает на платформах 4 линейки FreeBSD. На пятой ветке у меня возникли с этим определенные затруднения и я подробно расскажу о них позже, после того, как найду решения задач. Приступим наконец. :) Указанные в названии главы системные утилиты являются весьма мощным инструментом повышения уровня безопасности всей системы в целом. Смысл их работы заключается в том, что потенциально опасные процессы и сервисы можно запускать в отдельном от всей системы окружении со своими бинарниками, библиотеками и переменными окружения. В каком случае это решение оправдано? Во-первых, если необходимый сервис достаточно часто встречается в списках уязвимых, но при этом реальной альтернативы ему найти не представляется возможным. Так, например, сами разработчики фри рекомендуют запускать bind (пожалуй самый популярный на сегодняшний день сервер DNS) в chroot окружении и предоставляют, кстати, детальное описание настроек. Во-вторых, такая необходимость может возникнуть в случае предоставления хостинга с большим количеством сервисов и при этом разработчики скриптов сайта по вашему мнению не являются надежными или их скрипты просто вам не по душе :) И в этом случае весь проект, включая вьёб-сервер, базы данных и ftp-сервер, обеспечивающий доступ в докрут апача, можно изолировать от самой системы. Теперь скажу несколько слов о jail. На платформе FreeBSD, в отличие от Linux это две абсолютно разные утилиты. Установка и запуск jail достаточно просты и подробно описаны в манах (man jail). Jail считается более защищенным и функциональным, чем chroot, но при этом предъявляет более высокие требования к системе. В частности, jail – машина требует выделения отдельного IP – адреса, что не всегда возможно. Правда в случае нехватки реальных адресов можно попробовать использовать фейковые (192.168.0.0/24 etc.) и задействовать портмапперы – решение всегда зависит от конкретной задачи. Кроме этого, jail – машина, установленная по дефолту, как это описано в манах, достаточно громоздка и содержит в себе массу файлов, которые скорее всего не потребуются при дальнейшей работе. Избавиться от них можно путем длительной подгонки напильником файла Make.conf, но для этого уже потребуются экспертные знания. Еще одной удобной функцией jail являются весьма широкие возможности предоставления сервисов “на сторону”, фактически – это полноценная виртуальная машина, позволяющая заводить своего суперюзера root, имеющая свои собственные файлы групп и паролей и системные утилиты для управления ими. Как реальный пример – вы можете поднять ssh на jail – машине, создать запись root и юзерские аккаунты, разместить свое дерево портов и отдать в таком виде сторонним разработчикам. Проблемы возникающие при эксплуатации jail, в случаях запуска нескольких машин на одной системе – это проблема квотирования дискового пространства (решения существуют, но я не планирую на них останавливаться в этой статье) и запреты определенных системных вызовов к ядру, налагаемые разработчиками исходя из соображений безопасности и структуры самой утилиты (альтернативные решения также существуют и те, кто заинтересуется этим вопросом смогут найти их, попробовать использовать и поделиться опытом). Еще одно весьма важное замечание – любой апгрейд системы, влекущий за собой последующую ее пересборку, включая ядро, требует обновления файлов как в jail (путем новой сборки), так и в chroot (путем ручной замены файлов, претерпевших изменения). Об этом нельзя забывать никогда! И последнее, прежде, чем я перейду к детальному объяснению процесса создания chroot – окружения. В jail, chroot и chrootuid периодически обнаруживаются собственные уязвимости! Смысл их заключается в появлении у злоумышленника возможности подняться выше уровня “ракушки”, в которую мы утолкли сервис, и получить доступ к бинарникам и библиотекам основной системы со всеми вытекающими из этого последствиями! Поэтому нужно отдавать себе отчет в том, что настоящий системный инженер никогда не может спать спокойно, а если и спит, то ему снятся багтраки. :)) Единственное, чем можно себя тешить – это тем, что свежие ксплойты никогда не являются достоянием широкой ламерской общественности, поэтому “сломать” вас можно будет только в случае серьезного “заказа” со стороны доброжелателей с привлечением экспертов. Так что никогда не тешьте себя иллюзиями относительно крутизны и неуязвимости собственной системы. Описываемые решения только значительно повышают уровень ее безопасности, но достигнуть 100% уровня защищенности не позволяет ничего, включая самые супер-пупер дорогие решения на базе цисок и другого тяжеловесного оборудования. Теперь перейдем к детальному рассмотрению решения задачи запуска процесса в chroot –окружении. Делать это будем на примере утилиты stunnel. Зачем она нам нужна, будет рассказано в следующей главе, согласно утвержденному плану работы (см. выше) :) Тем же, кому на самом деле интересно то, что я излагаю :) могу предложить посетить сайт разработчика утилиты и попытаться самостоятельно разобраться в вопросе, как она функционирует и где её можно применить. ![]() Для начала определим в каком месте файловой системы мы разместим дерево создаваемого chroot’a. В конкретном примере это будет раздел /var. Руководствоваться при выборе нужно только размером свободного дискового пространства в разделе и возможным объемом файлов, возникающих в процессе работы конкретного сервиса, например log-файлов. Утилита df - наш главный помощник при решении этого вопроса. Код:
www-/var# df -h Filesystem Size Used Avail Capacity Mounted on /dev/ar0s1a 1008M 45M 882M 5% / /dev/ar0s1f 40G 14G 22G 39% /usr /dev/ar0s1e 15G 5.1G 8.5G 38% /var procfs 4.0K 4.0K 0B 100% /proc Создадим корневой каталог в котором в последующем мы сможем размещать и другие сервисы, помещенные в chroot. Код:
www-/# cd /var/ www-/var# mkdir chroot www-/var# chown -R root:sys chroot Группу sys я использую исключительно для удобства дальнейшей работы. Идем дальше – создаем собственно корневой каталог для сервиса и структуру его системных каталогов. Код:
www-/var# mkdir -p chroot/stunnel/dev www-/var# mkdir -p chroot/stunnel/etc www-/var# mkdir -p chroot/stunnel/tmp www-/var# mkdir -p chroot/stunnel/usr/lib www-/var# mkdir -p chroot/stunnel/usr/libexec www-/var# mkdir -p chroot/stunnel/usr/local/etc www-/var# mkdir -p chroot/stunnel/var/run www-/var# mkdir -p chroot/stunnel/var/log При установке утилиты из портов это безошибочное решение, после установки останется добавить всего несколько каталогов и окончательное их количество выяснится только в процессе отладки. Следующие далее действия также необходимы для работы любого chroot – окружения. Код:
www-/var# cd chroot/stunnel/dev/ www-/var/chroot/stunnel/dev# mknod null c 2 2 www-/var/chroot/stunnel/dev# chmod 0666 null Создается нода для дивайса null, без которого, как известно, в никсах жизни нет :) Следующий шаг не менее важен. Код:
www-/var/chroot/stunnel/dev# cp /usr/libexec/ld-elf.so.1 /var/chroot/stunnel/usr/libexec/ www-/var/chroot/stunnel/dev# cp /var/run/ld-elf.so.hints /var/chroot/stunnel/var/run/ Без них ни один процесс не запустится в chroot – окружении. Почему? Вот первый абзац мана: Код:
www-/var/chroot/stunnel/dev# man ld-elf.so.1 Formatting page, please wait...Done. RTLD(1) FreeBSD General Commands Manual RTLD(1) NAME ld-elf.so.1, rtld -- run-time link-editor DESCRIPTION ld-elf.so.1 is a self-contained shared object providing run-time support for loading and link-editing shared objects into a process' address space. It is also commonly known as the dynamic linker. It uses the data structures contained within dynamically linked programs to determine which shared libraries are needed and loads them using the mmap(2) system call. Теперь переходим непосредственно к установке порта. Код:
www-/var/chroot/stunnel/dev# cd /usr/ports/security/stunnel/ www-/usr/ports/security/stunnel# ls -l total 18 -rw-r--r-- 1 root wheel 4275 Dec 31 21:32 Makefile -rw-r--r-- 1 root wheel 97 Dec 31 21:32 distinfo drwxr-xr-x 2 root wheel 512 Dec 31 21:32 files -rw-r--r-- 1 root wheel 1192 Sep 20 2002 pkg-deinstall -rw-r--r-- 1 root wheel 491 Sep 20 2002 pkg-descr -rw-r--r-- 1 root wheel 894 Sep 20 2002 pkg-install -rw-r--r-- 1 root wheel 1186 Dec 31 21:32 pkg-plist www-/usr/ports/security/stunnel# cd files/ www-/usr/ports/security/stunnel/files# ls -l total 28 -rw-r--r-- 1 root wheel 18788 Apr 24 2004 connect-proxy.mwald.patch -rw-r--r-- 1 root wheel 593 Dec 31 21:32 patch-Makefile.in -rw-r--r-- 1 root wheel 1581 Dec 30 17:22 patch-src::network.c -rw-r--r-- 1 root wheel 584 Dec 31 21:32 ssl-noengine.patch -rw-r--r-- 1 root wheel 1058 Dec 31 21:32 stunnel.sh Здесь я немного позволил себе пробежать впереди паровоза. =) В каталоге files любого порта FreeBSD находятся патчи, которые посчитали необходимым добавить разработчики системы. В следующей главе для нас ключевой интерес будет представлять connect-proxy.mwald.patch. Но это уже совсем другая история. :) Едем дальше. Стандартный набор команд устанавливает порт и очищает каталог порта от продуктов работы компилятора, иными словами удаляет каталог work. Это make install clean и я его приводил в предыдущей главе. Здесь мы воспользуемся несколько иной конструкцией: Код:
www-/usr/ports/security/stunnel# make && make install Почему так? Потому, что нам на данном этапе понадобится скрипт для генерации SSL – сертификата, без которого работа программы невозможна. Я не буду приводить громоздкий листинг работы компилятора и инсталлятора, но рекомендую их просматривать, так как там содержится много полезной информации. В частности, нам будет интересно следующее: Код:
Libraries have been installed in: /usr/local/lib Added group "stunnel". Added user "stunnel". Первое – библиотеки программы помещены в /usr/local/lib, второе – разработчиками предусмотрен запуск программы от отдельных user/group, что есть очень хорошо с точки зрения безопасности всей системы. Создадим SSL – сертификат. Код:
www-/usr/local/share# cd /usr/ports/security/stunnel/work/stunnel-4.06/ www-/usr/ports/security/stunnel/work/stunnel-4.06# make cert (cd tools; rm -f stunnel.pem; make stunnel.pem) if test -r "/dev/urandom"; then dd if="/dev/urandom" of=stunnel.rnd bs=256 count=1; RND="-rand stunnel.rnd"; else RND=""; fi; /usr/bin/openssl req -new -x509 -days 365 -nodes $RND -config ./stunnel.cnf -out stunnel.pem -keyout stunnel.pem; test 0 -eq 0 || /usr/bin/openssl gendh $RND 512 >> stunnel.pem 1+0 records in 1+0 records out 256 bytes transferred in 0.000215 secs (1191722 bytes/sec) Generating a 1024 bit RSA private key .........................++++++ .........................................++++++ writing new private key to 'stunnel.pem' ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [PL]:RU State or Province Name (full name) [Some-State]:. Locality Name (eg, city) []:. Organization Name (eg, company) [Stunnel Developers Ltd]:. Organizational Unit Name (eg, section) []:. Common Name (FQDN of your server) [localhost]:myhost.ru /usr/bin/openssl x509 -subject -dates -fingerprint -noout -in stunnel.pem subject= /C=RU/CN=myhost.ru notBefore=Jan 1 18:01:48 2005 GMT notAfter=Jan 1 18:01:48 2006 GMT MD5 Fingerprint=F6:4D:C8:28:64:BF:FA:14:84:0A:02:6A:D7:BE:45:C3 Таким способом мы просто облегчили себе жизнь, так как воспользовались готовым скриптом от разработчиков утилиты для генерации сертификата используя пакет openssl. В следующей главе будет подробно описан процесс генерации сертификатов самостоятельно. На что следует обратить внимание в приведенном выше листинге. 1. Сгенеренный сертификат будет лежать в каталоге tools. 2. При генерации использовано устройство "/dev/urandom 3. Срок действия сертификата – 1 год (-days 365) 4. Приватный ключ создан с использованием алгоритма шифрования RSA 5. Длина ключа 1024 бита 6. При заполнении формы проставлены только страна и доменное имя – строки, заполненные мной точками проигнорировались. Минимально необходимо указать только Common Name 7. Common Name (FQDN of your server) в этом поле обязательно именно FQDN, в противном случае при коннекте по имени хоста вы получите отлуп от программы. Продолжим работу. Скопируем сертификат в наше chroot –окружение. Код:
www-/usr/ports/security/stunnel/work/stunnel-4.06# mkdir -p /var/chroot/stunnel/usr/local/etc/stunnel www-/usr/ports/security/stunnel/work/stunnel-4.06# cp tools/stunnel.pem /var/chroot/stunnel/usr/local/etc/stunnel/ www-/usr/ports/security/stunnel/work/stunnel-4.06# chmod 0600 /var/chroot/stunnel/usr/local/etc/stunnel/stunnel.pem О необходимости создать каталог stunnel в /usr/local/etc я узнал просмотрев пути установки программы. Следующий шаг – перейти в /usr/local и сделав Код:
www-/usr/local# ls -lt total 38 drwxr-xr-x 5 root wheel 2048 Jan 1 20:40 lib drwxr-xr-x 10 root wheel 512 Jan 1 20:40 etc drwxr-xr-x 2 root wheel 1536 Jan 1 20:40 sbin drwxr-xr-x 22 root wheel 512 Jan 1 20:28 share drwxr-xr-x 2 root wheel 512 Jan 1 20:28 info drwxr-xr-x 4 root wheel 512 Jan 1 20:28 libexec выяснить в каких каталогах произошли изменения после установки порта – эта информация чуть позже нам весьма пригодится. Теперь, внимание, очень важный шаг – выясним список библиотек, необходимых для работы программы! Здесь наш лучший друг - это системная утилита ldd. Смотрим Код:
www-/usr/local# ldd sbin/stunnel sbin/stunnel: libutil.so.3 => /usr/lib/libutil.so.3 (0x28076000) libssl.so.3 => /usr/lib/libssl.so.3 (0x2807f000) libcrypto.so.3 => /usr/lib/libcrypto.so.3 (0x280ae000) libwrap.so.3 => /usr/lib/libwrap.so.3 (0x281a5000) libc_r.so.4 => /usr/lib/libc_r.so.4 (0x281ad000) По результатам ее работы производим следующие очевидные манипуляции Код:
www-/usr/local# cp /usr/lib/libutil.so.3 /var/chroot/stunnel/usr/lib/ www-/usr/local# cp /usr/lib/libssl.so.3 /var/chroot/stunnel/usr/lib/ www-/usr/local# cp /usr/lib/libcrypto.so.3 /var/chroot/stunnel/usr/lib/ www-/usr/local# cp /usr/lib/libwrap.so.3 /var/chroot/stunnel/usr/lib/ www-/usr/local# cp /usr/lib/libc_r.so.4 /var/chroot/stunnel/usr/lib/ www-/usr/local# mkdir -p /var/chroot/stunnel/usr/sbin www-/usr/local# cp sbin/stunnel /var/chroot/stunnel/usr/sbin/ www-/usr/local# cp /usr/local/etc/stunnel/stunnel.conf-sample /var/chroot/stunnel/usr/local/etc/stunnel/stunnel.conf Как видим, я скопировал все определенные через ldd библиотеки в chroot – окружение, ну и по ходу пьесы отправил туда собственно бинарник stunnel, создав для него каталог sbin, о котором я не знал еще в тот момент, когда строил структуру для chroot – окружения. Ну и отправил в chroot – окружение конфиг-файл, который, после внимательного изучения мануалов будем редактировать. Следующие действия направлены на заполнение каталога /etc в chroot – окружении Код:
www-/var/chroot/stunnel/etc# cp /etc/hosts /var/chroot/stunnel/etc/ www-/var/chroot/stunnel/etc# cp /etc/host.conf /var/chroot/stunnel/etc/ www-/var/chroot/stunnel/etc# cp /etc/localtime /var/chroot/stunnel/etc/ www-/var/chroot/stunnel/etc# cp /etc/resolv.conf /var/chroot/stunnel/etc/ www-/var/chroot/stunnel/etc# cp /etc/services /var/chroot/stunnel/etc/ www-/var/chroot/stunnel/etc# cp /etc/protocols /var/chroot/stunnel/etc/ www-/var/chroot/stunnel/etc# cp /etc/master.passwd /var/chroot/stunnel/etc/PASSZ Это тот малый джентльменский набор, без которого ну просто никуда. =) Теперь процесс будет знать конфигурацию хоста, откуда ресолвить имена хостов, корректно писать в логи локальное время, знать соответствие протоколов и сервисов и получит своего пользователя и группу, от которых и будет работать в системе. Редактируем файлы групп и паролей Код:
www-/var/chroot/stunnel/etc# vi group stunnel:*:7780: www-/var/chroot/stunnel/etc# vi PASSZ stunnel:*:7998:7780::0:0:stunnel Daemon:/dev/null:/dev/null www-/var/chroot/stunnel/etc# pwd_mkdb -d /var/chroot/stunnel/etc PASSZ www-/var/chroot/stunnel/etc# rm -rf master.passwd www-/var/chroot/stunnel/etc# ls -lt total 168 -rw------- 1 root sys 40960 Jan 1 21:54 spwd.db -rw-r--r-- 1 root sys 40960 Jan 1 21:54 pwd.db -rw-r--r-- 1 root sys 16 Jan 1 21:50 group -rw-r--r-- 1 root sys 5752 Jan 1 21:45 protocols -rw-r--r-- 1 root sys 73544 Jan 1 21:45 services -rw-r--r-- 1 root sys 39 Jan 1 21:45 resolv.conf -r--r--r-- 1 root sys 815 Jan 1 21:44 localtime -rw-r--r-- 1 root sys 205 Jan 1 21:44 host.conf -rw-r--r-- 1 root sys 150 Jan 1 21:44 hosts Готово. Этого вполне достаточно, чтобы программа запустилась. В файлах групп и паролей оставлены только stunnel:stunnel, создана база и удалён сам файл master.password, содержащий хэши паролей. Теперь пора приниматься за конфиг. В данном примере сделаем его упрощенным, чтобы сервис стартовал – пока это наша конечная цель в данной главе. Код:
cd www-/var/chroot/stunnel/usr/local/etc/stunnel vi stunnel.conf setuid = stunnel setgid = stunnel pid = /var/run/stunnel.pid socket = l:TCP_NODELAY=1 socket = r:TCP_NODELAY=1 debug = 7 output = /var/log/stunnel.log [https] accept = 10.0.0.1:443 connect = 127.0.0.1:1080 TIMEOUTclose = 0 Подготовим место для лога и pid- файла Код:
www-/var/chroot/stunnel/usr/local/etc/stunnel# cd /var/chroot/stunnel/var/ www-/var/chroot/stunnel/var# chown stunnel:stunnel * www-/var/chroot/stunnel/var# ls -l total 4 drwxr-xr-x 2 stunnel stunnel 512 Jan 1 20:00 log drwxr-xr-x 2 stunnel stunnel 512 Jan 1 20:08 run Теперь у процесса заведомо есть права записи в эти каталоги. =) Ну и пришло время пробного пуска двигателя. Здесь я остановлюсь еще на одном моменте. В портах присутствует утилита chrootuid позволяющая запускать процесс от имени конкретного пользователя. Однако использовать ее имеет смысл только в том случае, если процесс биндится на непривелегированный порт tcp (=>1024). Поехали. Работаем с системной утилитой truss которая поможет нам убрать камни с тернистого пути, ведущего к победе коммунизма :o)) Код:
www-/var/chroot/stunnel/var# truss chroot /var/chroot/stunnel /usr/local/sbin/stunnel mmap(0x0,2048,0x3,0x1000,-1,0x0) = 671477760 (0x2805f000) munmap(0x2805f000,0x800) = 0 (0x0) __sysctl(0xbfbffa40,0x2,0x2805df88,0xbfbffa3c,0x0,0x0) = 0 (0x0) mmap(0x0,32768,0x3,0x1002,-1,0x0) = 671477760 (0x2805f000) geteuid() = 0 (0x0) getuid() = 0 (0x0) getegid() = 0 (0x0) getgid() = 0 (0x0) open("/etc/libmap.conf",0x0,0666) ERR#2 'No such file or directory' open("/var/run/ld-elf.so.hints",0x0,00) = 3 (0x3) read(0x3,0xbfbffa20,0x80) = 128 (0x80) lseek(3,0x80,0) = 128 (0x80) read(0x3,0x28063000,0x37) = 55 (0x37) close(3) = 0 (0x0) access("/usr/lib/libc.so.4",0) = 0 (0x0) open("/usr/lib/libc.so.4",0x0,05001172053) = 3 (0x3) fstat(3,0xbfbffa68) = 0 (0x0) read(0x3,0xbfbfea38,0x1000) = 4096 (0x1000) mmap(0x0,626688,0x5,0x20002,3,0x0) = 671510528 (0x28067000) mprotect(0x280e8000,0x1000,0x7) = 0 (0x0) mprotect(0x280e8000,0x1000,0x5) = 0 (0x0) mmap(0x280e9000,20480,0x3,0x12,3,0x81000) = 672043008 (0x280e9000) mmap(0x280ee000,73728,0x3,0x1012,-1,0x0) = 672063488 (0x280ee000) close(3) = 0 (0x0) mmap(0x0,280,0x3,0x1000,-1,0x0) = 672137216 (0x28100000) munmap(0x28100000,0x118) = 0 (0x0) mmap(0x0,13360,0x3,0x1000,-1,0x0) = 672137216 (0x28100000) munmap(0x28100000,0x3430) = 0 (0x0) sigaction(SIGILL,0xbfbffac0,0xbfbffaa8) = 0 (0x0) sigprocmask(0x1,0x0,0x2805debc) = 0 (0x0) sigaction(SIGILL,0xbfbffaa8,0x0) = 0 (0x0) sigprocmask(0x1,0x2805de80,0xbfbffae8) = 0 (0x0) sigprocmask(0x3,0x2805de90,0x0) = 0 (0x0) chdir(0xbfbffc7b) = 0 (0x0) chroot(0x8048cf9) = 0 (0x0) execve(<missing argument>,<missing argument>,<missing argument>)execve(0xbfbffc8f,0xbfbffba0,0xbfbffba8) ERR#2 'No such file or directory' chroot: write(2,0xbfbff358,8) = 8 (0x8) /usr/local/sbin/stunnelwrite(2,0xbfbff388,23) = 23 (0x17) : write(2,0xbfbff348,2) = 2 (0x2) No such file or directory write(2,0xbfbff348,26) = 26 (0x1a) exit(0x1) process exit, rval = 256 Ай-ай-ай, какая глупая ошибка – по указанному пути chroot не нашел бинарник stunnel! :) Не расстраиваемся, а бежим исправляться. Код:
www-/var/chroot/stunnel# cd usr/local/ www-/var/chroot/stunnel/usr/local# ls -l total 2 drwxr-xr-x 3 root sys 512 Jan 1 22:05 etc www-/var/chroot/stunnel/usr/local# cd .. www-/var/chroot/stunnel/usr# ls -l total 8 drwxr-xr-x 2 root sys 512 Jan 1 21:37 lib drwxr-xr-x 2 root sys 512 Jan 1 20:08 libexec drwxr-xr-x 3 root sys 512 Jan 1 19:59 local drwxr-xr-x 2 root sys 512 Jan 1 21:37 sbin www-/var/chroot/stunnel/usr# mv sbin local/ Да. Да и еще раз да. Ваш покорный слуга создал каталог /sbin выше, чем local. :o)) Починили? Ключ на старт. Код:
www-/var/chroot/stunnel/usr# truss chroot /var/chroot/stunnel /usr/local/sbin/stunnel mmap(0x0,2048,0x3,0x1000,-1,0x0) = 671477760 (0x2805f000) munmap(0x2805f000,0x800) = 0 (0x0) __sysctl(0xbfbffa4c,0x2,0x2805df88,0xbfbffa48,0x0,0x0) = 0 (0x0) mmap(0x0,32768,0x3,0x1002,-1,0x0) = 671477760 (0x2805f000) geteuid() = 0 (0x0) getuid() = 0 (0x0) getegid() = 0 (0x0) getgid() = 0 (0x0) open("/etc/libmap.conf",0x0,0666) ERR#2 'No such file or directory' open("/var/run/ld-elf.so.hints",0x0,00) = 3 (0x3) read(0x3,0xbfbffa2c,0x80) = 128 (0x80) lseek(3,0x80,0) = 128 (0x80) read(0x3,0x28063000,0x37) = 55 (0x37) close(3) = 0 (0x0) access("/usr/lib/libc.so.4",0) = 0 (0x0) open("/usr/lib/libc.so.4",0x0,05001172053) = 3 (0x3) fstat(3,0xbfbffa74) = 0 (0x0) read(0x3,0xbfbfea44,0x1000) = 4096 (0x1000) mmap(0x0,626688,0x5,0x20002,3,0x0) = 671510528 (0x28067000) mprotect(0x280e8000,0x1000,0x7) = 0 (0x0) mprotect(0x280e8000,0x1000,0x5) = 0 (0x0) mmap(0x280e9000,20480,0x3,0x12,3,0x81000) = 672043008 (0x280e9000) mmap(0x280ee000,73728,0x3,0x1012,-1,0x0) = 672063488 (0x280ee000) close(3) = 0 (0x0) mmap(0x0,280,0x3,0x1000,-1,0x0) = 672137216 (0x28100000) munmap(0x28100000,0x118) = 0 (0x0) mmap(0x0,13360,0x3,0x1000,-1,0x0) = 672137216 (0x28100000) munmap(0x28100000,0x3430) = 0 (0x0) sigaction(SIGILL,0xbfbffacc,0xbfbffab4) = 0 (0x0) sigprocmask(0x1,0x0,0x2805debc) = 0 (0x0) sigaction(SIGILL,0xbfbffab4,0x0) = 0 (0x0) sigprocmask(0x1,0x2805de80,0xbfbffaf4) = 0 (0x0) sigprocmask(0x3,0x2805de90,0x0) = 0 (0x0) chdir(0xbfbffc87) = 0 (0x0) chroot(0x8048cf9) = 0 (0x0) execve(<missing argument>,<missing argument>,<missing argument>)mmap(0x0,2048,0x3,0x1000,-1,0x0) = 671539200 (0x2806e000) munmap(0x2806e000,0x800) = 0 (0x0) __sysctl(0xbfbffa70,0x2,0x2806cf88,0xbfbffa6c,0x0,0x0) = 0 (0x0) mmap(0x0,32768,0x3,0x1002,-1,0x0) = 671539200 (0x2806e000) geteuid() = 0 (0x0) getuid() = 0 (0x0) getegid() = 0 (0x0) getgid() = 0 (0x0) open("/etc/libmap.conf",0x0,0666) ERR#2 'No such file or directory' access("/usr/lib/libutil.so.3",0) = 0 (0x0) open("/usr/lib/libutil.so.3",0x0,05001362053) = 3 (0x3) fstat(3,0xbfbffa98) = 0 (0x0) read(0x3,0xbfbfea68,0x1000) = 4096 (0x1000) mmap(0x0,36864,0x5,0x20002,3,0x0) = 671571968 (0x28076000) mprotect(0x2807d000,0x1000,0x7) = 0 (0x0) mprotect(0x2807d000,0x1000,0x5) = 0 (0x0) mmap(0x2807e000,4096,0x3,0x12,3,0x7000) = 671604736 (0x2807e000) close(3) = 0 (0x0) access("/usr/lib/libssl.so.3",0) = 0 (0x0) open("/usr/lib/libssl.so.3",0x0,05001362053) = 3 (0x3) fstat(3,0xbfbffa98) = 0 (0x0) read(0x3,0xbfbfea68,0x1000) = 4096 (0x1000) mmap(0x0,192512,0x5,0x20002,3,0x0) = 671608832 (0x2807f000) mprotect(0x280a9000,0x1000,0x7) = 0 (0x0) mprotect(0x280a9000,0x1000,0x5) = 0 (0x0) mmap(0x280aa000,12288,0x3,0x12,3,0x2a000) = 671784960 (0x280aa000) mmap(0x280ad000,4096,0x3,0x1012,-1,0x0) = 671797248 (0x280ad000) close(3) = 0 (0x0) access("/usr/lib/libcrypto.so.3",0) = 0 (0x0) open("/usr/lib/libcrypto.so.3",0x0,05001362053) = 3 (0x3) fstat(3,0xbfbffa98) = 0 (0x0) read(0x3,0xbfbfea68,0x1000) = 4096 (0x1000) mmap(0x0,1011712,0x5,0x20002,3,0x0) = 671801344 (0x280ae000) mprotect(0x2818f000,0x1000,0x7) = 0 (0x0) mprotect(0x2818f000,0x1000,0x5) = 0 (0x0) mmap(0x28190000,77824,0x3,0x12,3,0xe1000) = 672727040 (0x28190000) mmap(0x281a3000,8192,0x3,0x1012,-1,0x0) = 672804864 (0x281a3000) close(3) = 0 (0x0) access("/usr/lib/libwrap.so.3",0) = 0 (0x0) open("/usr/lib/libwrap.so.3",0x0,05001362053) = 3 (0x3) fstat(3,0xbfbffa98) = 0 (0x0) read(0x3,0xbfbfea68,0x1000) = 4096 (0x1000) mmap(0x0,32768,0x5,0x20002,3,0x0) = 672813056 (0x281a5000) mprotect(0x281aa000,0x1000,0x7) = 0 (0x0) mprotect(0x281aa000,0x1000,0x5) = 0 (0x0) mmap(0x281ab000,4096,0x3,0x12,3,0x5000) = 672837632 (0x281ab000) mmap(0x281ac000,4096,0x3,0x1012,-1,0x0) = 672841728 (0x281ac000) close(3) = 0 (0x0) access("/usr/lib/libc_r.so.4",0) = 0 (0x0) open("/usr/lib/libc_r.so.4",0x0,05001362053) = 3 (0x3) fstat(3,0xbfbffa98) = 0 (0x0) read(0x3,0xbfbfea68,0x1000) = 4096 (0x1000) mmap(0x0,745472,0x5,0x20002,3,0x0) = 672845824 (0x281ad000) mprotect(0x28244000,0x1000,0x7) = 0 (0x0) mprotect(0x28244000,0x1000,0x5) = 0 (0x0) mmap(0x28245000,20480,0x3,0x12,3,0x97000) = 673468416 (0x28245000) mmap(0x2824a000,102400,0x3,0x1012,-1,0x0) = 673488896 (0x2824a000) close(3) = 0 (0x0) mmap(0x0,1696,0x3,0x1000,-1,0x0) = 673591296 (0x28263000) munmap(0x28263000,0x6a0) = 0 (0x0) mmap(0x0,1400,0x3,0x1000,-1,0x0) = 673591296 (0x28263000) munmap(0x28263000,0x578) = 0 (0x0) mmap(0x0,4448,0x3,0x1000,-1,0x0) = 673591296 (0x28263000) munmap(0x28263000,0x1160) = 0 (0x0) mmap(0x0,21864,0x3,0x1000,-1,0x0) = 673591296 (0x28263000) munmap(0x28263000,0x5568) = 0 (0x0) mmap(0x0,1136,0x3,0x1000,-1,0x0) = 673591296 (0x28263000) munmap(0x28263000,0x470) = 0 (0x0) mmap(0x0,16256,0x3,0x1000,-1,0x0) = 673591296 (0x28263000) munmap(0x28263000,0x3f80) = 0 (0x0) sigaction(SIGILL,0xbfbffaf0,0xbfbffad8) = 0 (0x0) sigprocmask(0x1,0x0,0x2806cebc) = 0 (0x0) sigaction(SIGILL,0xbfbffad8,0x0) = 0 (0x0) getpid() = 25391 (0x632f) fcntl(0x0,0x3,0x0) = 2 (0x2) fcntl(0x1,0x3,0x0) = 2 (0x2) fcntl(0x2,0x3,0x0) = 2 (0x2) pipe() = 3 (0x3) fcntl(0x3,0x3,0x0) = 2 (0x2) fcntl(0x3,0x4,0x6) = 0 (0x0) fcntl(0x4,0x3,0x0) = 2 (0x2) fcntl(0x4,0x4,0x6) = 0 (0x0) readlink("/etc/malloc.conf",0xbfbff944,63) ERR#2 'No such file or directory' mmap(0x0,4096,0x3,0x1002,-1,0x0) = 673591296 (0x28263000) break(0x805f000) = 0 (0x0) break(0x8060000) = 0 (0x0) break(0x8061000) = 0 (0x0) break(0x8062000) = 0 (0x0) __sysctl(0xbfbffa20,0x2,0x28246760,0xbfbffa1c,0x0,0x0) = 0 (0x0) mmap(0xbfaff000,4096,0x0,0x1000,-1,0x0) = -1078988800 (0xbfaff000) break(0x8063000) = 0 (0x0) gettimeofday(0x28246788,0x0) = 0 (0x0) sigaction(SIGHUP,0x0,0x2825d920) = 0 (0x0) sigaction(SIGINT,0x0,0x2825d938) = 0 (0x0) sigaction(SIGQUIT,0x0,0x2825d950) = 0 (0x0) sigaction(SIGILL,0x0,0x2825d968) = 0 (0x0) sigaction(SIGTRAP,0x0,0x2825d980) = 0 (0x0) sigaction(SIGABRT,0x0,0x2825d998) = 0 (0x0) sigaction(SIGEMT,0x0,0x2825d9b0) = 0 (0x0) sigaction(SIGFPE,0x0,0x2825d9c8) = 0 (0x0) sigaction(SIGBUS,0x0,0x2825d9f8) = 0 (0x0) sigaction(SIGSEGV,0x0,0x2825da10) = 0 (0x0) sigaction(SIGSYS,0x0,0x2825da28) = 0 (0x0) sigaction(SIGPIPE,0x0,0x2825da40) = 0 (0x0) sigaction(SIGALRM,0x0,0x2825da58) = 0 (0x0) sigaction(SIGTERM,0x0,0x2825da70) = 0 (0x0) sigaction(SIGURG,0x0,0x2825da88) = 0 (0x0) sigaction(SIGTSTP,0x0,0x2825dab8) = 0 (0x0) sigaction(SIGCONT,0x0,0x2825dad0) = 0 (0x0) sigaction(SIGCHLD,0x0,0x2825dae8) = 0 (0x0) sigaction(SIGTTIN,0x0,0x2825db00) = 0 (0x0) sigaction(SIGTTOU,0x0,0x2825db18) = 0 (0x0) sigaction(SIGIO,0x0,0x2825db30) = 0 (0x0) sigaction(SIGXCPU,0x0,0x2825db48) = 0 (0x0) sigaction(SIGXFSZ,0x0,0x2825db60) = 0 (0x0) sigaction(SIGVTALRM,0x0,0x2825db78) = 0 (0x0) sigaction(SIGPROF,0x0,0x2825db90) = 0 (0x0) sigaction(SIGWINCH,0x0,0x2825dba8) = 0 (0x0) sigaction(SIGINFO,0x0,0x2825dbc0) = 0 (0x0) sigaction(SIGUSR1,0x0,0x2825dbd8) = 0 (0x0) sigaction(SIGUSR2,0x0,0x2825dbf0) = 0 (0x0) sigaction(SIGPROF,0xbfbffa28,0x0) = 0 (0x0) sigaction(SIGINFO,0xbfbffa28,0x0) = 0 (0x0) sigaction(SIGCHLD,0xbfbffa28,0x0) = 0 (0x0) sigprocmask(0x3,0x0,0x282467f8) = 0 (0x0) __sysctl(0xbfbffa20,0x2,0xbfbffa40,0xbfbffa1c,0x0,0x0) = 0 (0x0) getdtablesize() = 14781 (0x39bd) break(0x8072000) = 0 (0x0) break(0x808f000) = 0 (0x0) break(0x8090000) = 0 (0x0) fcntl(0x0,0x4,0x6) = 0 (0x0) fcntl(0x1,0x4,0x6) = 0 (0x0) fcntl(0x2,0x4,0x6) = 0 (0x0) break(0x8091000) = 0 (0x0) sigprocmask(0x1,0x2806ce80,0xbfbffb18) = 0 (0x0) sigprocmask(0x3,0x2806ce90,0x0) = 0 (0x0) open("/usr/local/etc/stunnel/stunnel.conf",0x0,00) = 5 (0x5) fcntl(0x5,0x3,0x0) = 0 (0x0) fcntl(0x5,0x4,0x4) = 0 (0x0) fstat(5,0xbfbff880) = 0 (0x0) break(0x8095000) = 0 (0x0) read(0x5,0x8091000,0x4000) = 229 (0xe5) read(0x5,0x8091000,0x4000) = 0 (0x0) fstat(5,0xbfbff8c0) = 0 (0x0) fcntl(0x5,0x3,0x0) = 4 (0x4) fcntl(0x5,0x4,0x0) = 0 (0x0) close(5) = 0 (0x0) open("/var/log/stunnel.log",0x209,0640) = 5 (0x5) fcntl(0x5,0x3,0x0) = 9 (0x9) fcntl(0x5,0x4,0xd) = 0 (0x0) fcntl(0x5,0x2,0x1) = 0 (0x0) getdtablesize() = 14781 (0x39bd) gettimeofday(0xbfbff848,0x0) = 0 (0x0) access("/etc/localtime",4) = 0 (0x0) open("/etc/localtime",0x0,00) = 6 (0x6) fcntl(0x6,0x3,0x0) = 0 (0x0) fcntl(0x6,0x4,0x4) = 0 (0x0) fstat(6,0xbfbff700) = 0 (0x0) read(0x6,0xbfbfd3f4,0x1f08) = 815 (0x32f) fstat(6,0xbfbfd340) = 0 (0x0) fcntl(0x6,0x3,0x0) = 4 (0x4) fcntl(0x6,0x4,0x0) = 0 (0x0) close(6) = 0 (0x0) getpid() = 25391 (0x632f) fstat(5,0xbfbff4e0) = 0 (0x0) write(5,0x8091000,137) = 137 (0x89) stat("/usr/local/etc/stunnel/stunnel.pem",0xbfbffaf0) = 0 (0x0) sigaction(SIGPIPE,0xbfbffac8,0x0) = 0 (0x0) sigaction(SIGTERM,0xbfbffad8,0x0) = 0 (0x0) sigaction(SIGQUIT,0xbfbffac8,0x0) = 0 (0x0) sigaction(SIGINT,0xbfbffad8,0x0) = 0 (0x0) sigaction(SIGHUP,0xbfbffac8,0x0) = 0 (0x0) break(0x8096000) = 0 (0x0) break(0x8097000) = 0 (0x0) break(0x8098000) = 0 (0x0) break(0x8099000) = 0 (0x0) break(0x809a000) = 0 (0x0) break(0x809b000) = 0 (0x0) break(0x809c000) = 0 (0x0) issetugid() = 0 (0x0) issetugid() = 0 (0x0) stat("/root/.rnd",0xbfbff9b0) ERR#2 'No such file or directory' getpid() = 25391 (0x632f) open("/dev/urandom",0x8104,00) ERR#2 'No such file or directory' open("/dev/random",0x8104,00) ERR#2 'No such file or directory' open("/dev/srandom",0x8104,00) ERR#2 'No such file or directory' socket(0x1,0x1,0x0) = 6 (0x6) fcntl(0x6,0x3,0x0) = 2 (0x2) fcntl(0x6,0x4,0x6) = 0 (0x0) connect(0x6,{ AF_UNIX "/var/run/egd-pool" },19) ERR#2 'No such file or directory' fstat(6,0xbfbff670) = 0 (0x0) close(6) = 0 (0x0) socket(0x1,0x1,0x0) = 6 (0x6) fcntl(0x6,0x3,0x0) = 2 (0x2) fcntl(0x6,0x4,0x6) = 0 (0x0) connect(0x6,{ AF_UNIX "/dev/egd-pool" },15) ERR#2 'No such file or directory' fstat(6,0xbfbff670) = 0 (0x0) close(6) = 0 (0x0) socket(0x1,0x1,0x0) = 6 (0x6) fcntl(0x6,0x3,0x0) = 2 (0x2) fcntl(0x6,0x4,0x6) = 0 (0x0) connect(0x6,{ AF_UNIX "/etc/egd-pool" },15) ERR#2 'No such file or directory' fstat(6,0xbfbff670) = 0 (0x0) close(6) = 0 (0x0) socket(0x1,0x1,0x0) = 6 (0x6) fcntl(0x6,0x3,0x0) = 2 (0x2) fcntl(0x6,0x4,0x6) = 0 (0x0) connect(0x6,{ AF_UNIX "/etc/entropy" },14) ERR#2 'No such file or directory' fstat(6,0xbfbff670) = 0 (0x0) close(6) = 0 (0x0) getuid() = 0 (0x0) gettimeofday(0xbfbff8a8,0x0) = 0 (0x0) stat("/dev/urandom",0xbfbff9b0) ERR#2 'No such file or directory' stat("/dev/urandom",0xbfbff9b0) ERR#2 'No such file or directory' gettimeofday(0xbfbff7a8,0x0) = 0 (0x0) getpid() = 25391 (0x632f) write(5,0x8091000,74) = 74 (0x4a) gettimeofday(0xbfbff798,0x0) = 0 (0x0) getpid() = 25391 (0x632f) write(5,0x8091000,98) = 98 (0x62) break(0x809d000) = 0 (0x0) break(0x809e000) = 0 (0x0) break(0x809f000) = 0 (0x0) open("/usr/local/etc/stunnel/stunnel.pem",0x0,00) = 6 (0x6) fcntl(0x6,0x3,0x0) = 0 (0x0) fcntl(0x6,0x4,0x4) = 0 (0x0) fstat(6,0xbfbff6d0) = 0 (0x0) break(0x80a3000) = 0 (0x0) read(0x6,0x809f000,0x4000) = 1571 (0x623) read(0x6,0x809f000,0x4000) = 0 (0x0) fstat(6,0xbfbff9c0) = 0 (0x0) fcntl(0x6,0x3,0x0) = 4 (0x4) fcntl(0x6,0x4,0x0) = 0 (0x0) close(6) = 0 (0x0) gettimeofday(0xbfbff8b8,0x0) = 0 (0x0) getpid() = 25391 (0x632f) write(5,0x8091000,91) = 91 (0x5b) gettimeofday(0xbfbff8a8,0x0) = 0 (0x0) getpid() = 25391 (0x632f) write(5,0x8091000,88) = 88 (0x58) open("/usr/local/etc/stunnel/stunnel.pem",0x0,00) = 6 (0x6) fcntl(0x6,0x3,0x0) = 0 (0x0) fcntl(0x6,0x4,0x4) = 0 (0x0) fstat(6,0xbfbff2e0) = 0 (0x0) read(0x6,0x809e000,0x4000) = 1571 (0x623) fstat(6,0xbfbff9c0) = 0 (0x0) fcntl(0x6,0x3,0x0) = 4 (0x4) fcntl(0x6,0x4,0x0) = 0 (0x0) close(6) = 0 (0x0) getrlimit(0x8,0xbfbff8f0) = 0 (0x0) gettimeofday(0xbfbff698,0x0) = 0 (0x0) getpid() = 25391 (0x632f) write(5,0x8091000,97) = 97 (0x61) gettimeofday(0xbfbff688,0x0) = 0 (0x0) getpid() = 25391 (0x632f) write(5,0x8091000,98) = 98 (0x62) gettimeofday(0xbfbff698,0x0) = 0 (0x0) getpid() = 25391 (0x632f) write(5,0x8091000,64) = 64 (0x40) pipe() = 6 (0x6) fcntl(0x6,0x3,0x0) = 2 (0x2) fcntl(0x6,0x4,0x6) = 0 (0x0) fcntl(0x7,0x3,0x0) = 2 (0x2) fcntl(0x7,0x4,0x6) = 0 (0x0) fcntl(0x6,0x4,0x6) = 0 (0x0) fcntl(0x6,0x3,0x0) = 6 (0x6) gettimeofday(0xbfbff620,0x0) = 0 (0x0) getpid() = 25391 (0x632f) write(5,0x8091000,69) = 69 (0x45) fcntl(0x7,0x4,0x6) = 0 (0x0) fcntl(0x7,0x3,0x0) = 6 (0x6) gettimeofday(0xbfbff610,0x0) = 0 (0x0) getpid() = 25391 (0x632f) write(5,0x8091000,69) = 69 (0x45) fcntl(0x6,0x2,0x1) = 0 (0x0) fcntl(0x7,0x2,0x1) = 0 (0x0) socket(0x2,0x1,0x0) = 8 (0x8) fcntl(0x8,0x3,0x0) = 2 (0x2) fcntl(0x8,0x4,0x6) = 0 (0x0) fcntl(0x8,0x4,0x6) = 0 (0x0) fcntl(0x8,0x3,0x0) = 6 (0x6) gettimeofday(0xbfbff648,0x0) = 0 (0x0) getpid() = 25391 (0x632f) write(5,0x8091000,69) = 69 (0x45) setsockopt(0x8,0xffff,0x4,0x8058528,0x4) = 0 (0x0) gettimeofday(0xbfbff678,0x0) = 0 (0x0) getpid() = 25391 (0x632f) write(5,0x8091000,84) = 84 (0x54) bind(0x8,{ AF_INET 10.0.0.1:443 },16) = 0 (0x0) gettimeofday(0xbfbff6a8,0x0) = 0 (0x0) getpid() = 25391 (0x632f) write(5,0x8091000,76) = 76 (0x4c) listen(0x8,0x5) = 0 (0x0) fcntl(0x8,0x2,0x1) = 0 (0x0) fork() = 25392 (0x6330) setitimer(0x2,0xbfbff8c0,0x0) = 0 (0x0) close(3) = 0 (0x0) close(4) = 0 (0x0) fcntl(0x0,0x3,0x0) = 6 (0x6) fcntl(0x0,0x4,0x2) = 0 (0x0) fcntl(0x1,0x3,0x0) = 2 (0x2) fcntl(0x1,0x4,0x2) = 0 (0x0) fcntl(0x2,0x3,0x0) = 2 (0x2) fcntl(0x2,0x4,0x2) = 0 (0x0) fcntl(0x5,0x3,0x0) = 13 (0xd) fcntl(0x5,0x4,0x9) = 0 (0x0) exit(0x0) process exit, rval = 0 Страшно? Мне тоже. =) Но в конце листинга видим заветную фразу fork() = 25392 (0x6330) ! Неужто форкнулись?!! Проверяем, что счастье так близко Код:
www-/var/chroot/stunnel/usr# netstat -na | grep LISTEN tcp4 0 0 10.0.0.1.443 *.* LISTEN Согласно нашему конфигу – стартовали и прибиндились к 443 tcp. Адрес только нужно ставить в конфиге реальный. В моем примере он заменен на “левый” 10.0.0.1. Глянем в лог для порядка. Код:
www-/var/chroot/stunnel/var/log# vi stunnel.log 2005.01.01 22:17:07 LOG5[25391:134610944]: stunnel 4.06 on i386-unknown-freebsd4.10 PTHREAD+POLL+LIBWRAP with OpenSSL 0.9.7d 17 Mar 2004 2005.01.01 22:17:07 LOG6[25391:134610944]: PRNG seeded with 0 bytes total 2005.01.01 22:17:07 LOG4[25391:134610944]: PRNG may not have been seeded with enough random bytes 2005.01.01 22:17:07 LOG7[25391:134610944]: Certificate: /usr/local/etc/stunnel/stunnel.pem 2005.01.01 22:17:07 LOG7[25391:134610944]: Key file: /usr/local/etc/stunnel/stunnel.pem 2005.01.01 22:17:07 LOG6[25391:134610944]: file ulimit = 14781 (can be changed with 'ulimit -n') 2005.01.01 22:17:07 LOG6[25391:134610944]: poll() used - no FD_SETSIZE limit for file descriptors 2005.01.01 22:17:07 LOG5[25391:134610944]: 7217 clients allowed 2005.01.01 22:17:07 LOG7[25391:134610944]: FD 6 in non-blocking mode 2005.01.01 22:17:07 LOG7[25391:134610944]: FD 7 in non-blocking mode 2005.01.01 22:17:07 LOG7[25391:134610944]: FD 8 in non-blocking mode 2005.01.01 22:17:07 LOG7[25391:134610944]: SO_REUSEADDR option set on accept socket 2005.01.01 22:17:07 LOG7[25391:134610944]: https bound to 10.0.0.1:443 2005.01.01 22:17:07 LOG7[25392:134610944]: Created pid file /var/run/stunnel.pid И правда работает! :)) Вопрос – а насколько корректно? Вникаем неспешно в результаты работы трейсера. Смотрим, какие были ошибки при запуске. Код:
open("/etc/libmap.conf",0x0,0666) ERR#2 'No such file or directory' readlink("/etc/malloc.conf",0xbfbff944,63) ERR#2 'No such file or directory' Это не критично. Убедиться в этом можно, сделав трэйс программы вне chroot’a. Они и там будут – программа замечательно работает и без этих файлов. Код:
stat("/root/.rnd",0xbfbff9b0) ERR#2 'No such file or directory' getpid() = 25391 (0x632f) open("/dev/urandom",0x8104,00) ERR#2 'No such file or directory'[code] А вот это не есть хорошо. Похоже, что мы лишили движок openssl пользоваться генератором случайных чисел. Засучив рукава принимаемся за исправление ошибок. [code] www-/var/chroot/stunnel/var/log# cd .. www-/var/chroot/stunnel/var# cd run/ www-/var/chroot/stunnel/var/run# kill `cat stunnel.pid` www-/var/chroot/stunnel/var/run# ls -l total 2 -r--r--r-- 1 root sys 183 Jan 1 20:08 ld-elf.so.hints Грохнули процесс. Теперь добавляем недостающее. Код:
www-/var/chroot/stunnel/var/log# cd .. www-/var/chroot/stunnel/var# cd run/ www-/var/chroot/stunnel/var/run# kill `cat stunnel.pid` www-/var/chroot/stunnel/var/run# ls -l total 2 -r--r--r-- 1 root sys 183 Jan 1 20:08 ld-elf.so.hints www-/var/chroot/stunnel/var/run# cd /root/ www-~# ls -l total 50 -rw------- 1 root wheel 2232 Feb 26 2002 .bash_history drwxr-xr-x 2 root wheel 512 Oct 22 11:48 .ccache -rw-r--r-- 2 root wheel 802 Jan 28 2002 .cshrc -rw------- 1 root wheel 388 Feb 12 2002 .history -rw-r--r-- 1 root wheel 142 Jan 28 2002 .klogin drwx------ 2 root wheel 512 Aug 2 10:10 .links -rw-r--r-- 1 root wheel 297 Jan 28 2002 .login drwxr-xr-x 3 root wheel 512 Sep 21 11:13 .mc -rw------- 1 root wheel 25255 Dec 25 16:24 .mysql_history -rw-r--r-- 2 root wheel 251 Jan 28 2002 .profile -rw------- 1 root wheel 1024 Oct 28 20:34 .rnd drwx------ 2 root wheel 512 Sep 9 2002 .ssh www-~# mkdir -p /var/chroot/stunnel/root www-~# cp .rnd /var/chroot/stunnel/root www-~# ls -l /var/chroot/stunnel/root total 2 -rw------- 1 root sys 1024 Jan 1 22:43 .rnd www-~# ls -l /dev/urandom crw-r--r-- 1 root wheel 2, 4 May 29 2004 /dev/urandom www-~# cd /var/chroot/stunnel/dev/ www-/var/chroot/stunnel/dev# mknod urandom c 2 4 www-/var/chroot/stunnel/dev# ls -l total 0 crw-rw-rw- 1 root sys 2, 2 Jan 1 20:05 null crw-r--r-- 1 root sys 2, 4 Jan 1 22:45 urandom Опять ключ на старт. И да поможет нам всевидящий truss! :)) Не буду снова приводить здесь листинг работы truss. Скажу только, что теперь ошибки исчезли. Заглянем для очистки совести в лог Код:
2005.01.01 22:41:52 LOG5[25392:134610944]: Received signal 15; terminating 2005.01.01 22:41:52 LOG7[25392:134610944]: removing pid file /var/run/stunnel.pid 2005.01.01 22:46:54 LOG5[25425:134610944]: stunnel 4.06 on i386-unknown-freebsd4.10 PTHREAD+POLL+LIBWRAP with OpenSSL 0.9.7d 17 Mar 2004 2005.01.01 22:46:54 LOG7[25425:134610944]: Snagged 64 random bytes from /root/.rnd 2005.01.01 22:46:54 LOG7[25425:134610944]: Wrote 1024 new random bytes to /root/.rnd 2005.01.01 22:46:54 LOG7[25425:134610944]: RAND_status claims sufficient entropy for the PRNG 2005.01.01 22:46:54 LOG6[25425:134610944]: PRNG seeded successfully 2005.01.01 22:46:54 LOG7[25425:134610944]: Certificate: /usr/local/etc/stunnel/stunnel.pem 2005.01.01 22:46:54 LOG7[25425:134610944]: Key file: /usr/local/etc/stunnel/stunnel.pem 2005.01.01 22:46:54 LOG6[25425:134610944]: file ulimit = 14781 (can be changed with 'ulimit -n') 2005.01.01 22:46:54 LOG6[25425:134610944]: poll() used - no FD_SETSIZE limit for file descriptors 2005.01.01 22:46:54 LOG5[25425:134610944]: 7217 clients allowed 2005.01.01 22:46:54 LOG7[25425:134610944]: FD 6 in non-blocking mode 2005.01.01 22:46:54 LOG7[25425:134610944]: FD 7 in non-blocking mode 2005.01.01 22:46:54 LOG7[25425:134610944]: FD 8 in non-blocking mode 2005.01.01 22:46:54 LOG7[25425:134610944]: SO_REUSEADDR option set on accept socket 2005.01.01 22:46:54 LOG7[25425:134610944]: https bound to 10.0.0.1:443 2005.01.01 22:46:54 LOG7[25426:134610944]: Created pid file /var/run/stunnel.pid На сей раз похоже, что всё – нирвана. Некорректностей не наблюдается. Немножко еще проверим себя, чтоб убедиться в окончательной победе =) Код:
www-/var/chroot/stunnel/var/log# netstat -na | grep LISTEN tcp4 0 0 10.0.0.1.443 *.* LISTEN telnet 10.0.0.1 443 Trying 10.0.0.1... Connected to myhost.ru. Escape character is '^]'. ^] telnet> q Connection closed. vi stunnel.log 2005.01.01 22:52:14 LOG7[25426:134610944]: https accepted FD=9 from 10.0.0.1:3216 2005.01.01 22:52:14 LOG7[25426:134610944]: FD 9 in non-blocking mode 2005.01.01 22:52:14 LOG7[25426:134614016]: https started 2005.01.01 22:52:14 LOG7[25426:134614016]: TCP_NODELAY option set on local socket 10.0.0.1:3216 2005.01.01 22:52:14 LOG7[25426:134614016]: SSL state (accept): before/accept initialization 2005.01.01 22:52:32 LOG3[25426:134614016]: SSL_accept: Peer suddenly disconnected 2005.01.01 22:52:32 LOG7[25426:134614016]: https finished (0 left) www-/var/chroot/stunnel/var/log# ps axfu | grep stunnel stunnel 25426 0.0 0.4 2776 1988 ?? Ss 10:46PM 0:00.01 /usr/local/sbin/stunnel Ну чтож, можете обнять себя и расцеловать или даже перепрыгнуть на радостях через самого себя с разбегу! :)) Задача решена и конечная цель достигнута. Проанализируйте сделанное и определитесь – все ли понятно. Зачем нам это было нужно станет ясно в следующей главе (почему именно stunnel). В данном конкретном примере мной ставилась цель – детально и максимально подробно рассказать и показать, как создается chroot- окружение и как в нем запускаются сервисы. И еще вот пожалуй что – вопросы, пожелания и предложения можно пока постить в этом треде. Потом, когда цикл статей будет мной закончен, я разделю треды на собственно статьи и возникшее в процессе работы FAQ (если конечно это кого-нибудь заинтересует) ![]() Редактировалось Macmep 02-01-2005 13:42. |
![]() |
![]() |
![]() |
Ссылка на пост #14 |
Гость
|
Прежде чем перейти к изложению следующей части материала, хочу высказать еще несколько соображений относительно применения технологий chroot и jail. Очевидно, что использование их имеет смысл только в том случае, если изолированный процесс не может использовать файловую систему выше уровня своей “скорлупы”. Любые линки наружу категорически запрещены. Какие же существуют способы взаимодействия процессов, каждый из которых заключен в своё chroot – окружение? Первый и самый очевидный – это по TCP. Разместив, например, внутри корневого каталога /chroot два chroot – окружения, первый – apache, содержащий известный всем и горячо любимый народом веб-сервер, второй – mysql с не менее популярной БД, мы биндим мускул к локалхосту (ключ --bind-address=127.0.0.1 в строке запуска mysqld) и считаем вопрос решенным. Более красивое решение с точки зрения производительности связки апач+сиквель – это работа через unix-socket файл. При нагруженных сервисах работа через сокет-файл добавляет до 10% производительности этой конструкции. Решение вопроса не представляется мне сложным. Будем использовать хардлинк между двумя chroot-системами, который, как уже очевидно, создается на уровне каталога /chroot
Код:
cd /var/chroot ln mysql/tmp/mysql.sock apache/tmp/mysql.sock Код:
cd /usr/local/etc/rc.d ls –l 001.mysql.sh 002.apache.sh Ну и последний, испробованный мной метод, это применить NFS. В четвертой линейке FreeBSD начиная кажется с 4.5 (могу ошибиться – поправьте) nfs абсолютно корректно работает на том хосте, где запущен nfs – сервер. Таким способом можно отдавать кусок файловой системы для совместного использования нескольким jail – машинам. В варианте chroot можно создавать nfs – шару на одном уровне со всеми chroot – окружениями. В заключение этого лирического отступления, хочу сказать, что технология chroot является весьма гибкой и при наличии упорства и желания можно исполнять весьма оригинальные вещи. =) В частности, в процессе экспериментов, мне удалось собрать систему из трех postfix и трех courier-imap, которые обслуживали три разных почтовых домена, каждый со своим SSL –сертификатом, выдававшими корректные RFC-822 заголовки, использовавшие общий каталог для хранения сообщений, доступный как раз по NFS и проверяемый на вирусы drwebd. Однако задача написать тутор на эту тему у меня не стоит даже в самых отдаленных планах, так как способов разрулить мультидоменную почту существует масса, хотя в первом приближении, если на всех доменах должна быть корректная работа с SSL, то это поддерживается уже коммерческими продуктами типа Communigate Pro. Хотя, врать не буду, я никогда не пробовал в качестве MTA, скажем кумыл или экзим, возможно, что они это делают еще красивей, но, к сожалению в сутках всего лишь 24 часа из которых хочется хотя бы 5 отдавать сну. ![]() |
![]() |
![]() |
![]() |
Ссылка на пост #15 |
Гость
|
Глава 3. Stunnel, как оружие пролетариата.
Для начала небольшая предыстория проливающая свет на вопрос, по какой же все-таки причине я решил так плотно заняться юзаньем stunnel и во что это в конечном итоге вылилось. :o)) Однажды один очень хороший человек обратился ко мне с просьбой помочь другому очень хорошему человеку. Суть проблемы состояла в том, что злобный и гадкий админ (а другие в природе разве бывают, а?) заткнул на своей проксе ресурсы, чрезвычайно человеку нужные. Первое предложение звучала примерно так: “ Можешь у себя быстренько повесить socks и отдать его в работу?” А в чем проблема то? Конечно можно… Только вот неожиданно выяснилось, что в той сетке, откуда нужно попасть на socks, у юзеров (а может и во всей подсети) отрублен NAT. Значит путь наружу один – через проксю, а над ней то админ и колдует, рисуя злобные запреты на ресурсы. Стало ясно, что выход один – туннелирование трафика через прокси. Изучив достаточно много документации по этому вопросу, в том числе и весьма неплохой обзор Битая ссылка я пришел к выводу, что решения есть, но они меня не устраивают. Понятно, что коммерческая тулзень настоящему индейцу не помеха, но весь этот софт желал иметь серверную часть на виндовозе, что меня уже ну никак не устраивало. Для меня всегда был и остается одним из наиболее значимых, девиз – “выставить виндовый сервис в инет – это равносильно тому, что сесть голой жопой на раскаленную сковороду”. Почему? Да потому, что уровень моих знаний виндовоза не позволяет мне осуществлять такие решения. При этом мне известны люди, более того, мои хорошие друзья, которые работают с виндовыми серверами, но уровень их знаний в этом вопросе соответствует экспертному. =) Итак, я искал сервер, который будет работать на фре и вспомнил, как довольно давно наткнулся на stunnel, когда решал вопрос с pop3-ssl, но потом, перебравшись на courier-imap, его благополучно забросил. Посетив www.stunnel.org я выяснил, что существует патч, позволяющий пробрасывать ssl-туннель через прокси с включенной поддержкой CONNECT. Остановлюсь немного на этой функции proxy-сервера на примере популярного squid. Если заглянуть в конфиг сквида в его раздел # ACCESS CONTROLS, то можно подчерпнуть следующую полезную информацию Код:
#Recommended minimum configuration: acl all src 0.0.0.0/0.0.0.0 acl manager proto cache_object acl localhost src 127.0.0.1/255.255.255.255 acl to_localhost dst 127.0.0.0/8 acl SSL_ports port 443 563 acl Safe_ports port 80 # http acl Safe_ports port 21 # ftp acl Safe_ports port 443 563 # https, snews acl Safe_ports port 70 # gopher acl Safe_ports port 210 # wais acl Safe_ports port 1025-65535 # unregistered ports acl Safe_ports port 280 # http-mgmt acl Safe_ports port 488 # gss-http acl Safe_ports port 591 # filemaker acl Safe_ports port 777 # multiling http acl CONNECT method CONNECT # TAG: http_access # Deny requests to unknown ports http_access deny !Safe_ports # Deny CONNECT to other than SSL ports http_access deny CONNECT !SSL_ports Короче, лично мне еще не попадался до такой степени отмороженный админ, который закрывал на проксе CONNECT при соединении на внешний порт по https :)) В нашей ситуации все оказалось хорошо – соединения по https проходили без вопросов. Осталось решить последнюю задачу, которая оказалась для меня весьма нетривиальной. Все на том же www.stunnel.org доступна версия бинарника, скомпиленная под винду вместе dll – ками. Фактически – готовый клиент, но не умеющий ходить через прокс :( Итак, имеем сорцы плюс патч connect-proxy.mwald.patch и очень хочется собрать виндового клиента. Под фрей и для нее – минутное дело, а вот под виндовоз… Короче, после установки на фре mingw32 , который самими разработчиками stunnel позиционируется, как единственный компилятор, выдающий рабочие продукты и пары часов безуспешной битвы с сорцами, отчаяшись подоткнуть все необходимые инклуды, я обратился за помощью к Ноп’у aka 0x90, автору известного опуса Битая ссылка, который со свойственным ему упорством, вооружившись напильником, пропатчил, выправил сорцы и собрал живую и рабочую версию! В-принципе, мои планы таковы, что я собираюсь предоставить здесь Нопу отдельную главу для написания тутора по созданию живой проги. =)) В этом он мне не откажет, но вот открытым остается вопрос свободного времени. Подождем автора и в любом случае, несколько позже, а дам линк для скачивания пропатченной версии, которой пользуется уже немалое количество народа. :) Итак, что мы получаем в сухом остатке: 1. Готовое решение для создания туннеля через прокси с поддержкой CONNECT. 2. Соединение с достаточной степенью надежности защищено от сниффинга в локальной сети, читай от того же гадского админа. =) 3. Пароль на приватный ключ клиентского SSL – сертификата является дополнительным средством защиты от несанкционированного доступа к сервису. 4. Вход в туннель осуществляется по TCP на локалхосте со стороны клиентской машины, а выход на локалхосте сервера. Таким образом, прибиндив на серверной стороне на локалхосте требуемый клиенту сервис (proxy, socks) мы предоставляем клиенту широкие возможности для действий. 5. stunnel весьма удобное средство, если клиентская программа по каким-либо причинам не поддерживает SSL сервис, или работает с ним некорректно а на сервере эти функции реализованы ( например старые версии почтового клиента The Bat!) 6. При определенном полёте фантазии можно использовать stunnel, как достойную замену вечнодырявому модулю апача mod_ssl. Проверено – работает корректно. 7. Авторизация доверенных клиентских сертификатов – вполне надежное средство ограничения доступа к сервисам. Если при этом сам сервис имеет собственные средства авторизации, то можно рассматривать эту функцию, как дополнительный рубеж защиты. Как грамотно поднять сервер stunnel на FreeBSD мы рассмотрели в предыдущей главе. Теперь я хочу подробно остановиться на вопросе использования механизма авторизации SSL с использованием списка доверенных клиентских сертификатов. 1. Создадим серверные сертификаты с использованием стандартного скрипта CA.sh из комплекта openssl. Можно конечно сделать все ручками, и диры для сертов и ключей создать и свой конфиг написать, но лениво. :o)) Код:
www-/var/chroot/stunnel/usr/local/etc/stunnel# cd /var/chroot/ www-/var/chroot# mkdir certs www-/var/chroot# locate CA.sh /usr/src/crypto/openssl/apps/CA.sh www-/var/chroot# cp /usr/src/crypto/openssl/apps/CA.sh /var/chroot/certs/ www-/var/chroot# cd /var/chroot/certs www-/var/chroot/certs# chmod 0700 CA.sh Готово? Теперь слегка поправим скрипт CA.sh Дело в том, что по умолчанию собственный доверенный сертификат (Certificate Authority – он же CA), которым мы будем подписывать сертификат нашего сервера stunnel, равно как и серверный серт, будут созданы с зашифрованными закрытыми ключами. Это конечно супер - правильно с точки зрения безопасности, но вот сервис stunnel будет стартовать только при вводе пароля на закрытый ключ сертификата, таким образом мы лишимся автоматического запуска сервиса в случае перезагрузки сервера. Я предпочитаю, как это делалось выше, поставить на серт сервера права 0600, а не шифровать закрытый ключ. При этом вероятность компрометации сертификата возрастает, так что решать вам самим. Итак, находим в скрипте CA.sh строки: 1. В секции -newca) в строке Код:
$REQ -new [color=red]-nodes[/color] -x509 -keyout ${CATOP}/private/$CAKEY \ 2. В секции -newcert) в строке Код:
$REQ -new [color=red]-nodes[/color] -keyout newreq.pem -out newreq.pem $DAYS Опция -nodes - не шифровать закрытый ключ. Теперь генерим сертификат CA. Код:
./CA.sh -newca CA certificate filename (or enter to create) Making CA certificate ... Generating a 1024 bit RSA private key .................................++++++ ...++++++ writing new private key to './demoCA/private/./cakey.pem' ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:RU State or Province Name (full name) [Some-State]:. Locality Name (eg, city) []:. Organization Name (eg, company) [Internet Widgits Pty Ltd]:. Organizational Unit Name (eg, section) []:. Common Name (eg, YOUR name) []:Master Email Address []:. Особо любопытные личности могут исследовать результат работы скрипта =) Код:
www-/var/chroot/certs# openssl rsa -noout -text -in demoCA/private/cakey.pem Private-Key: (1024 bit) modulus: 00:ab:95:01:cb:c2:1e:3f:7a:68:7b:93:72:21:e6: 2a:43:6f:a0:f7:d8:6a:11:3e:9f:3f:91:3d:c4:6f: ce:ea:08:36:48:25:fa:4c:2e:7f:f6:03:c3:6f:8d: 56:a4:12:f0:0c:49:79:ca:75:01:f3:77:67:0a:f9: 28:1b:8d:4c:00:ca:c1:3f:6d:74:e4:07:21:dd:8c: a4:36:bc:e3:90:3e:76:a4:68:22:35:ad:bb:c1:61: bf:82:13:6b:e6:d0:97:8b:eb:f6:90:c6:ff:8f:f3: 51:47:a8:80:1a:05:b5:78:b1:ec:cb:47:6c:7e:e0: 5a:22:e8:58:04:ee:ad:6c:dd publicExponent: 65537 (0x10001) privateExponent: 56:7b:c7:a8:f5:52:1b:ba:ce:39:23:6b:8e:ac:9d: b6:d9:e8:2f:a4:94:69:d6:bf:9b:e1:d0:59:57:e5: da:4e:83:55:c0:56:b5:d9:66:44:11:47:8b:cd:98: d3:20:7c:80:24:f4:cf:58:44:c0:7b:f9:a3:2d:4c: ca:fe:60:44:de:a0:93:af:b2:e8:d6:8c:52:de:40: 62:6c:13:c8:8c:ac:15:24:de:8d:b9:54:c8:be:67: 80:14:8a:04:e4:7d:8e:05:85:71:87:8d:7e:bc:d4: c6:d5:ff:1d:73:1c:fd:1a:8a:61:ec:58:78:6e:59: c8:b9:90:ec:3f:3f:86:7d prime1: 00:d4:b5:65:a5:5a:82:33:e2:36:32:c4:70:58:a2: 3c:5e:7d:e4:6a:62:62:ef:b3:24:8a:22:cc:82:ef: 56:1d:70:1b:84:59:59:a3:53:ba:ac:80:e9:3f:57: 17:6b:64:55:d5:64:8f:29:95:68:e7:25:d7:c5:7c: 7e:a8:70:2c:17 prime2: 00:ce:80:d2:fb:a0:85:0b:6b:0a:b1:0e:c5:be:ab: ba:56:ed:36:3f:05:4b:b9:ca:61:88:06:fc:91:68: 75:76:86:11:78:02:57:ac:52:de:e0:49:9a:16:11: 23:22:82:4c:a4:f8:4b:31:2c:46:0e:04:c5:5f:17: 86:6d:94:43:2b exponent1: 00:b8:cf:26:92:85:51:ed:1c:55:34:c4:c2:4b:f0: 21:7d:83:ea:2a:98:73:17:8a:51:6c:07:92:23:0d: 29:88:08:38:90:44:45:82:87:a4:00:6f:3c:b9:00: c5:63:54:58:d3:40:3c:b6:c7:8e:ce:8e:6d:ab:b3: 60:24:9e:d9:5f exponent2: 4a:d8:24:1f:f1:20:e7:6f:87:73:7e:e0:2a:e8:40: e4:4a:9b:73:a1:ee:bd:4a:dd:a8:98:a7:a7:e8:0d: 52:c4:ea:c5:ed:4b:6b:78:a9:b0:ee:dc:3b:0d:41: 07:bb:e4:1d:92:a4:66:11:1e:de:eb:d9:c1:4a:5c: 7d:90:d3:fb coefficient: 02:78:d2:15:55:ed:b1:24:67:16:38:a4:32:24:31: f4:e4:1a:61:d0:26:bc:56:5e:77:b4:8a:7f:1e:14: 32:21:bb:df:bd:1f:cd:48:5c:8a:58:6e:78:4b:3d: 41:5a:e7:29:5c:1a:97:6b:88:1c:bb:6b:7c:02:19: e5:25:cf:b7 www-/var/chroot/certs# openssl x509 -noout -text -in demoCA/cacert.pem Certificate: Data: Version: 3 (0x2) Serial Number: 0 (0x0) Signature Algorithm: md5WithRSAEncryption Issuer: C=RU, CN=Master Validity Not Before: Jan 3 18:23:16 2005 GMT Not After : Jan 3 18:23:16 2006 GMT Subject: C=RU, CN=Master Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public Key: (1024 bit) Modulus (1024 bit): 00:ab:95:01:cb:c2:1e:3f:7a:68:7b:93:72:21:e6: 2a:43:6f:a0:f7:d8:6a:11:3e:9f:3f:91:3d:c4:6f: ce:ea:08:36:48:25:fa:4c:2e:7f:f6:03:c3:6f:8d: 56:a4:12:f0:0c:49:79:ca:75:01:f3:77:67:0a:f9: 28:1b:8d:4c:00:ca:c1:3f:6d:74:e4:07:21:dd:8c: a4:36:bc:e3:90:3e:76:a4:68:22:35:ad:bb:c1:61: bf:82:13:6b:e6:d0:97:8b:eb:f6:90:c6:ff:8f:f3: 51:47:a8:80:1a:05:b5:78:b1:ec:cb:47:6c:7e:e0: 5a:22:e8:58:04:ee:ad:6c:dd Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Subject Key Identifier: 8B:C0:8D:5B:7C:79:9F:DC:59:50:19:A8:BA:50:1B:03:B5:C3:4F:E5 X509v3 Authority Key Identifier: keyid:8B:C0:8D:5B:7C:79:9F:DC:59:50:19:A8:BA:50:1B:03:B5:C3:4F:E5 DirName:/C=RU/CN=Master serial:00 X509v3 Basic Constraints: CA:TRUE Signature Algorithm: md5WithRSAEncryption 99:d3:11:35:23:69:bb:ee:99:3d:9a:a1:40:a1:2c:44:08:43: b2:29:3d:2e:76:a5:f3:06:0f:90:39:16:30:07:e8:85:9f:c2: dd:9c:76:61:44:d2:13:18:2e:79:77:4b:f5:9f:a1:0b:e5:ba: 5b:89:a0:0f:9a:d9:24:ed:36:61:8d:a8:7e:b0:b8:bf:63:cb: 0d:52:86:40:bc:3d:c9:96:5c:bc:e2:df:e3:88:45:77:51:07: 73:2a:17:3d:ac:e7:70:71:23:44:c2:ad:18:df:c7:1f:ed:9e: e4:77:b9:79:fd:08:a6:e3:6d:eb:b8:03:68:44:94:67:e0:40: 25:d2 Готово? Теперь сгенерим сертификат нашего сервера stunnel. Первый этап – это создание запроса на сертификат (Certificate Signing Request): Код:
www-/var/chroot/certs# ./CA.sh -newreq Generating a 1024 bit RSA private key ..++++++ .++++++ writing new private key to 'newreq.pem' ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:RU State or Province Name (full name) [Some-State]:. Locality Name (eg, city) []:. Organization Name (eg, company) [Internet Widgits Pty Ltd]:. Organizational Unit Name (eg, section) []:. Common Name (eg, YOUR name) []:myhost.ru Email Address []:. Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []:qwerty An optional company name []: Request (and private key) is in newreq.pem Посмотреть содержание запроса в удобоваримой форме можно следующим образом: Код:
www-/var/chroot/certs# openssl req -noout -text -in newreq.pem Certificate Request: Data: Version: 0 (0x0) Subject: C=RU, CN=myhost.ru Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public Key: (1024 bit) Modulus (1024 bit): 00:a0:16:34:18:7f:5e:b1:e5:11:2b:96:67:b3:ab: 62:58:30:0a:7b:98:fd:f8:34:5a:24:28:96:63:59: 1e:68:87:0d:5a:a6:6c:f5:60:5c:bf:22:d5:7f:3c: ce:2a:fe:85:69:a2:bb:1d:82:f8:70:93:3b:93:9e: e9:0c:53:47:e0:fa:83:32:af:44:57:f9:5d:36:09: 50:e7:4f:ce:6d:b5:7e:11:13:1b:e2:c0:f6:72:78: 41:1a:5d:8f:f1:42:cf:3a:b6:85:20:08:00:d8:f5: 9e:cf:5c:09:78:33:6d:8d:a4:ea:fe:f4:5c:4c:fd: 1c:d6:20:65:d6:78:19:61:31 Exponent: 65537 (0x10001) Attributes: challengePassword :qwerty Signature Algorithm: md5WithRSAEncryption 06:a1:aa:73:68:f5:f4:63:84:4f:f0:a4:3a:60:b9:25:8e:11: 6c:bc:86:07:41:da:d4:95:63:3b:d6:a0:ed:a0:6f:69:6c:36: ad:cc:d0:20:67:09:38:a8:e6:a8:35:7b:45:42:fb:9b:46:a3: 92:f7:26:b3:81:46:2a:ef:6f:fe:94:04:92:3c:e8:57:dd:43: 3b:da:4f:80:71:93:62:00:ab:9d:12:29:a9:e0:1f:f8:e7:9f: 49:29:9a:42:d7:ab:c7:26:da:86:73:d1:cf:34:55:6b:cc:6d: 8b:af:f9:d0:9e:4e:33:26:17:39:ff:af:b5:a0:25:fa:a1:51: f8:7a Теперь подписываем запрос нашим CA сертификатом: Код:
www-/var/chroot/certs# ./CA.sh -sign Using configuration from /etc/ssl/openssl.cnf Check that the request matches the signature Signature ok Certificate Details: Serial Number: 1 (0x1) Validity Not Before: Jan 3 18:34:38 2005 GMT Not After : Jan 3 18:34:38 2006 GMT Subject: countryName = RU commonName = myhost.ru X509v3 extensions: X509v3 Basic Constraints: CA:FALSE Netscape Comment: OpenSSL Generated Certificate X509v3 Subject Key Identifier: 7F:38:6A:58:3B:84:60:55:57:84:4E:03:7F:E9:79:D6:A5:46:80:36 X509v3 Authority Key Identifier: keyid:8B:C0:8D:5B:7C:79:9F:DC:59:50:19:A8:BA:50:1B:03:B5:C3:4F:E5 DirName:/C=RU/CN=Master serial:00 Certificate is to be certified until Jan 3 18:34:38 2006 GMT (365 days) Sign the certificate? [y/n]:y 1 out of 1 certificate requests certified, commit? [y/n]y Write out database with 1 new entries Data Base Updated Certificate: Data: Version: 3 (0x2) Serial Number: 1 (0x1) Signature Algorithm: md5WithRSAEncryption Issuer: C=RU, CN=Master Validity Not Before: Jan 3 18:34:38 2005 GMT Not After : Jan 3 18:34:38 2006 GMT Subject: C=RU, CN=myhost.ru Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public Key: (1024 bit) Modulus (1024 bit): 00:a0:16:34:18:7f:5e:b1:e5:11:2b:96:67:b3:ab: 62:58:30:0a:7b:98:fd:f8:34:5a:24:28:96:63:59: 1e:68:87:0d:5a:a6:6c:f5:60:5c:bf:22:d5:7f:3c: ce:2a:fe:85:69:a2:bb:1d:82:f8:70:93:3b:93:9e: e9:0c:53:47:e0:fa:83:32:af:44:57:f9:5d:36:09: 50:e7:4f:ce:6d:b5:7e:11:13:1b:e2:c0:f6:72:78: 41:1a:5d:8f:f1:42:cf:3a:b6:85:20:08:00:d8:f5: 9e:cf:5c:09:78:33:6d:8d:a4:ea:fe:f4:5c:4c:fd: 1c:d6:20:65:d6:78:19:61:31 Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: CA:FALSE Netscape Comment: OpenSSL Generated Certificate X509v3 Subject Key Identifier: 7F:38:6A:58:3B:84:60:55:57:84:4E:03:7F:E9:79:D6:A5:46:80:36 X509v3 Authority Key Identifier: keyid:8B:C0:8D:5B:7C:79:9F:DC:59:50:19:A8:BA:50:1B:03:B5:C3:4F:E5 DirName:/C=RU/CN=Master serial:00 Signature Algorithm: md5WithRSAEncryption 34:20:71:8c:9b:8b:20:ca:93:cb:95:34:f0:70:ba:35:d1:1a: 60:22:60:ee:16:5e:93:30:d6:22:a5:60:7e:fe:85:a4:fe:77: bc:ab:a3:fa:a7:ad:b5:84:6a:29:eb:b5:30:ea:37:15:6b:39: f1:db:d3:22:68:ca:0c:e1:02:3a:5e:af:a7:06:1a:53:6e:35: 99:6a:f0:ce:be:f8:d2:6f:22:35:1b:c0:1d:d1:b1:a8:b3:f7: fc:10:6d:2e:b7:90:54:bf:e5:62:c2:e6:a6:6f:e7:a6:74:40: a2:39:c3:bb:ca:38:73:f5:79:71:17:9a:79:f7:a2:2d:97:e7: bc:c0 -----BEGIN CERTIFICATE----- MIICWTCCAcKgAwIBAgIBATANBgkqhkiG9w0BAQQFADAeMQswCQYDVQQGEwJSVTEP MA0GA1UEAxMGTWFzdGVyMB4XDTA1MDEwMzE4MzQzOFoXDTA2MDEwMzE4MzQzOFow ITELMAkGA1UEBhMCUlUxEjAQBgNVBAMTCW15aG9zdC5ydTCBnzANBgkqhkiG9w0B AQEFAAOBjQAwgYkCgYEAoBY0GH9eseURK5Zns6tiWDAKe5j9+DRaJCiWY1keaIcN WqZs9WBcvyLVfzzOKv6FaaK7HYL4cJM7k57pDFNH4PqDMq9EV/ldNglQ50/ObbV+ ERMb4sD2cnhBGl2P8ULPOraFIAgA2PWez1wJeDNtjaTq/vRcTP0c1iBl1ngZYTEC AwEAAaOBozCBoDAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdl bmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUfzhqWDuEYFVXhE4Df+l51qVG gDYwRgYDVR0jBD8wPYAUi8CNW3x5n9xZUBmoulAbA7XDT+WhIqQgMB4xCzAJBgNV BAYTAlJVMQ8wDQYDVQQDEwZNYXN0ZXKCAQAwDQYJKoZIhvcNAQEEBQADgYEANCBx jJuLIMqTy5U08HC6NdEaYCJg7hZekzDWIqVgfv6FpP53vKuj+qettYRqKeu1MOo3 FWs58dvTImjKDOECOl6vpwYaU241mWrwzr740m8iNRvAHdGxqLP3/BBtLreQVL/l YsLmpm/npnRAojnDu8o4c/V5cReaefeiLZfnvMA= -----END CERTIFICATE----- Signed certificate is in newcert.pem Объединяя файлы приватного ключа и сертификата получаем заветный сертификат для работы сервера stunnel. Затем складываем его и cacert.pem в chroot-окружение stunnel следующим образом: Код:
www-/var/chroot/certs# cat newreq.pem newcert.pem > stunnel.pem www-/var/chroot/certs# chmod 0600 stunnel.pem www-/var/chroot/certs# cp stunnel.pem /var/chroot/stunnel/usr/local/etc/stunnel/ www-/var/chroot/certs# cp demoCA/cacert.pem /var/chroot/stunnel/usr/local/etc/stunnel/ Изменяем конфиг сервера следующим образом: Код:
www-/var/chroot/certs# cd /var/chroot/stunnel/usr/local/etc/stunnel/ www-/var/chroot/stunnel/usr/local/etc/stunnel# mkdir -p /var/chroot/stunnel/cert/trusted www-/var/chroot/stunnel/usr/local/etc/stunnel# vi stunnel.conf setuid = stunnel setgid = stunnel verify = 3 CApath = /cert/trusted pid = /var/run/stunnel.pid socket = l:TCP_NODELAY=1 socket = r:TCP_NODELAY=1 debug = 7 output = /var/log/stunnel.log [https] accept = 10.0.0.1:443 connect = 127.0.0.1:80 TIMEOUTclose = 0 Теперь поясню что есть что. Всё детально описано с документации по stunnel, кстати =)) verify = 3 – проверка клиентского сертификата на наличие его в списке доверенных. CApath = /cert/trusted – путь, где программа ищет доверенные сертификаты, точней, если удосужитесь прочесть маны, слинкованные хэши клиентских серификатов. debug = 7 – максимально подробные логи отладчика, после того, как все заработает эту опцию следует убрать из конфига, иначе лог будет гигантских размеров. [https] – собственно секция сервера, указывается на каком внешнем порту и адресе stunnel принимает соединения и к какому порту на локалхосте биндится выход из туннеля (в моем примере это эмуляция работы https). Теперь мы вплотную приблизились к вопросу создания клиентского сертификата. Оговорюсь сразу, что самый грамотный вариант – это когда клиент генерит приватный ключ, зашифрованный паролем, самостоятельно, а вам для авторизации присылает только сертификат. На виндовозе для этого придется установить пакет OpenSSL для Win (без труда ищется в гугле). Я же свой пример приведу на никсах, так как процесс абсолютно одинаков. Код:
www-/var/chroot/stunnel/usr/local/etc/stunnel# openssl req -x509 -newkey rsa -keyout masterkey.pem -out mastercert.pem -days 365 Generating a 1024 bit RSA private key ........++++++ .........++++++ writing new private key to 'masterkey.pem' Enter PEM pass phrase: Verifying - Enter PEM pass phrase: ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:RU State or Province Name (full name) [Some-State]:. Locality Name (eg, city) []:. Organization Name (eg, company) [Internet Widgits Pty Ltd]:. Organizational Unit Name (eg, section) []:. Common Name (eg, YOUR name) []:-=Macmep=- Email Address []:. www-/var/chroot/stunnel/usr/local/etc/stunnel# cat masterkey.pem mastercert.pem > master.pem www-/var/chroot/stunnel/usr/local/etc/stunnel# vi master.pem -----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: DES-EDE3-CBC,92B6CCC97ACC6BF6 eQHq1DEauWS4flv6M3Xlm0k90WlRCCZwysX9OlkJMHvQE2zjNrbG+4zm2P9wTb03 K6gkF3BmZbpWbS91CoJ/04wDysgqS9rldNQR104YhVf/oNZxsrWNqJzNyffmYtpH WoeR2qmI2wFmHTbmepEVKTYYMU4a6foYh5/vhfgYyc7k1hZ0dLCVqLlY0XFZrkKe HPwysx6EvXWmzy/DMW1M37wM3VWcgRwKzwATvUPWc4+Olo3qOG6t9pQgEl09hstR lOXOiPAS5KAKeg8mvJ0cDgIllhOJmLyHD9IUHaIg0WJvPIe81bIsMafsL+z3yEMm 3BHcwsT1LSFOX3Xc+oldO8PDPnbpLbBsqWOnE232M2vETTXfW3RHiDf5TeLoyLh7 hDrNZgBI0why3zke85PzKikgAU8e1JlOtc5bvPI3+3hFLOkev2iVmLFNLP2TkHUY YNSv59zpE6N5tTai0042DtRGq1lyd9ECjm5WYnE/PBv6q07hbsYWNVO1woYNSuhU XY94N1k6+piyZtXxYB7BLO7E3OEx/DJMPtuNMoFLqYdkAh6XH+1xgH9ThXflr2bJ xRCdTN9iSwfElfn1z0bhTJr9reWaGyGwdQZMm7bnSUKj+sgfEG5C8oUW5WIpzMrC 9q/fx2iHS9wp/FXyhYOlAwTmZmq0qy3hVLPzb0SREFn+yPIII9Kg/JtqzwY5+8Hu d7xtdV1RjmjY5gQqSc6bGSazft3bknhg9EN9g/WhfEVVSDNr4G54mVVdGXlYs7I5 x7jp46BA0VLx1WM4xAcAnJ5BugKmsQRQIGbEFzv0N4TAQEELLiq9rQ== -----END RSA PRIVATE KEY----- -----BEGIN CERTIFICATE----- MIICNTCCAZ6gAwIBAgIBADANBgkqhkiG9w0BAQQFADAiMQswCQYDVQQGEwJSVTET MBEGA1UEAxMKLT1NYWNtZXA9LTAeFw0wNTAxMDMxOTAyMDNaFw0wNjAxMDMxOTAy MDNaMCIxCzAJBgNVBAYTAlJVMRMwEQYDVQQDEwotPU1hY21lcD0tMIGfMA0GCSqG SIb3DQEBAQUAA4GNADCBiQKBgQC+4tQ6mcC5vafFGJ3TOr32rhzE4fuh0D4BlJYG TgovVI0EBa/yU9yAsnCJqoGoyRyyxQ04inHOjsGzq5rhCxsklFQ8T3YoQg4341K3 L/uQ9OApJEN4HhK3gg1pzziotDVjsV0qeHZjDX2B+MntP9AMwoINnWpmioXwBv2R uczGHQIDAQABo3sweTAdBgNVHQ4EFgQUQCkCxs/YyHU3KT3U8/WMzzM1cWgwSgYD VR0jBEMwQYAUQCkCxs/YyHU3KT3U8/WMzzM1cWihJqQkMCIxCzAJBgNVBAYTAlJV MRMwEQYDVQQDEwotPU1hY21lcD0tggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcN AQEEBQADgYEAIZjXZNNeRlNkCd4d4jJPHpmrSvbUqjXV6RfDS6iukxfH1PSBcYOY FefPVZGsKQtoyCcw8xjW1PSXfmEWURwpQWv0dKhEMYJAk2dVh3c1b2bcwExMOTwC 8Yp0GkgE0jMZNcrWr01nUeKxzqYahdA+4XBTOgFDK54kUICYoRaR//k= -----END CERTIFICATE----- Теперь расскажу, что должно быть на стороне виндового клиента. Во-первых это набор скомпиленных под Win бинарника и dll-лек: 1. stunnel-4.06.exe 2. libssl32.dll 3. libeay32.dll Для тестирования работы системы можно взять эти, не патченные, если конечно вы не заперты наглухо проксом =)) 4. cacert.pem – берется с сервера (см. выше) и отдается клиенту. 5. master.pem – клиентские ключ + сертификат (см. выше) 6. stunnel.conf – собственно конфиг клиента Все эти файлы должны лежать в одном каталоге. Рассмотрим содержимое конфигурационного файла клиента: CAfile=cacert.pem cert=master.pem client=yes debug=7 verify=2 [https] accept=127.0.0.1:443 connect=10.0.0.1:443 Здесь добавились следующие параметры: client=yes – режим клиента verify=2 – предоставлять серверу клиентский сертификат Всё. Можно приступать к испытаниям. Сперва не авторизуя клиентский сертификат. Запускаем сервер stunnel на фре. Код:
www-/var/chroot/stunnel# chroot /var/chroot/stunnel /usr/local/sbin/stunnel www-/var/chroot/stunnel# tail -f var/log/stunnel.log 2005.01.03 22:24:26 LOG5[36999:134610944]: Peer certificate location /cert/trusted 2005.01.03 22:24:26 LOG6[36999:134610944]: file ulimit = 14781 (can be changed with 'ulimit -n') 2005.01.03 22:24:26 LOG6[36999:134610944]: poll() used - no FD_SETSIZE limit for file descriptors 2005.01.03 22:24:26 LOG5[36999:134610944]: 7217 clients allowed 2005.01.03 22:24:26 LOG7[36999:134610944]: FD 6 in non-blocking mode 2005.01.03 22:24:26 LOG7[36999:134610944]: FD 7 in non-blocking mode 2005.01.03 22:24:26 LOG7[36999:134610944]: FD 8 in non-blocking mode 2005.01.03 22:24:26 LOG7[36999:134610944]: SO_REUSEADDR option set on accept socket 2005.01.03 22:24:26 LOG7[36999:134610944]: https bound to 10.0.0.1:443 2005.01.03 22:24:26 LOG7[37000:134610944]: Created pid file /var/run/stunnel.pid Всё замечательно. Теперь стартуем клиента на винде. Если все сделано без ошибок, то он запросит пасс к ключу и упадет после запуска в трей. Пнув значок в трее можно читать логи клиента. Вернемся к серверу и посмотрим, как он отреагирует на попытку к нему подключиться. Набираем в браузере клиента https://localhost/ и смотрим логи на сервере (можно и на клиенте глянуть – тоже очень информативно). Код:
2005.01.03 22:28:59 LOG7[37000:134610944]: https accepted FD=9 from 192.168.0.1:1487 2005.01.03 22:28:59 LOG7[37000:134610944]: FD 9 in non-blocking mode 2005.01.03 22:28:59 LOG7[37000:134614016]: https started 2005.01.03 22:28:59 LOG7[37000:134614016]: TCP_NODELAY option set on local socket 2005.01.03 22:28:59 LOG5[37000:134614016]: https connected from 192.168.0.1:1487 2005.01.03 22:28:59 LOG7[37000:134614016]: SSL state (accept): before/accept initialization 2005.01.03 22:28:59 LOG7[37000:134614016]: SSL state (accept): SSLv3 read client hello A 2005.01.03 22:28:59 LOG7[37000:134614016]: SSL state (accept): SSLv3 write server hello A 2005.01.03 22:28:59 LOG7[37000:134614016]: SSL state (accept): SSLv3 write certificate A 2005.01.03 22:28:59 LOG7[37000:134614016]: SSL state (accept): SSLv3 write certificate request A 2005.01.03 22:28:59 LOG7[37000:134614016]: SSL state (accept): SSLv3 flush data 2005.01.03 22:29:01 LOG4[37000:134614016]: VERIFY ERROR: depth=0, error=self signed certificate: /C=RU/CN=-=Macmep=- 2005.01.03 22:29:01 LOG7[37000:134614016]: SSL alert (write): fatal: bad certificate 2005.01.03 22:29:01 LOG3[37000:134614016]: SSL_accept: 140890B2: error:140890B2:SSL routines:SSL3_GET_CLIENT_CERTIFICATE:no certificate returned 2005.01.03 22:29:01 LOG7[37000:134614016]: https finished (0 left) Все прекрасно – клиентский серт не авторизован и клиент отправлен к маме. :o))) Последний шаг – авторизация клиентского сертификата. Код:
www-/var/chroot/certs# locate c_hash /usr/ports/games/zoom/files/patch-src_hash.c /usr/src/crypto/openssl/tools/c_hash www-/var/chroot/certs# cp /usr/src/crypto/openssl/tools/c_hash /var/chroot/certs/ www-/var/chroot/certs# chmod 0700 c_hash www-/var/chroot/certs# ./c_hash /var/chroot/stunnel/usr/local/etc/stunnel/mastercert.pem 358e4942.0 => /var/chroot/stunnel/usr/local/etc/stunnel/mastercert.pem www-/var/chroot/certs# cd /var/chroot/stunnel/usr/local/etc/stunnel/ www-/var/chroot/stunnel/usr/local/etc/stunnel# mv mastercert.pem /var/chroot/stunnel/cert/trusted/master.pem www-/var/chroot/stunnel/usr/local/etc/stunnel# rm -rf master* www-/var/chroot/stunnel/usr/local/etc/stunnel# cd /var/chroot/stunnel/cert/trusted/ www-/var/chroot/stunnel/cert/trusted# ls -l total 2 -rw-r--r-- 1 root sys 826 Jan 3 22:02 master.pem www-/var/chroot/stunnel/cert/trusted# ln -s master.pem 358e4942.0 www-/var/chroot/stunnel/cert/trusted# ls -l total 2 lrwxr-xr-x 1 root sys 10 Jan 3 22:37 358e4942.0 -> master.pem И бегом опять смотреть в stunnel.log Код:
2005.01.03 22:39:47 LOG7[37000:134610944]: https accepted FD=9 from 192.168.0.1:1492 2005.01.03 22:39:47 LOG7[37000:134610944]: FD 9 in non-blocking mode 2005.01.03 22:39:47 LOG7[37000:134614016]: https started 2005.01.03 22:39:47 LOG7[37000:134614016]: TCP_NODELAY option set on local socket 2005.01.03 22:39:47 LOG5[37000:134614016]: https connected from 192.168.0.1:1492 2005.01.03 22:39:47 LOG7[37000:134614016]: SSL state (accept): before/accept initialization 2005.01.03 22:39:47 LOG7[37000:134614016]: SSL state (accept): SSLv3 read client hello A 2005.01.03 22:39:47 LOG7[37000:134614016]: SSL state (accept): SSLv3 write server hello A 2005.01.03 22:39:47 LOG7[37000:134614016]: SSL state (accept): SSLv3 write certificate A 2005.01.03 22:39:47 LOG7[37000:134614016]: SSL state (accept): SSLv3 write certificate request A 2005.01.03 22:39:47 LOG7[37000:134614016]: SSL state (accept): SSLv3 flush data 2005.01.03 22:39:49 LOG5[37000:134614016]: VERIFY OK: depth=0, /C=RU/CN=-=Macmep=- 2005.01.03 22:39:49 LOG7[37000:134614016]: SSL state (accept): SSLv3 read client certificate A 2005.01.03 22:39:49 LOG7[37000:134614016]: SSL state (accept): SSLv3 read client key exchange A 2005.01.03 22:39:49 LOG7[37000:134614016]: SSL state (accept): SSLv3 read certificate verify A 2005.01.03 22:39:49 LOG7[37000:134614016]: SSL state (accept): SSLv3 read finished A 2005.01.03 22:39:49 LOG7[37000:134614016]: SSL state (accept): SSLv3 write change cipher spec A 2005.01.03 22:39:49 LOG7[37000:134614016]: SSL state (accept): SSLv3 write finished A 2005.01.03 22:39:49 LOG7[37000:134614016]: SSL state (accept): SSLv3 flush data 2005.01.03 22:39:49 LOG7[37000:134614016]: 1 items in the session cache 2005.01.03 22:39:49 LOG7[37000:134614016]: 0 client connects (SSL_connect()) 2005.01.03 22:39:49 LOG7[37000:134614016]: 0 client connects that finished 2005.01.03 22:39:49 LOG7[37000:134614016]: 0 client renegotiatations requested 2005.01.03 22:39:49 LOG7[37000:134614016]: 3 server connects (SSL_accept()) 2005.01.03 22:39:49 LOG7[37000:134614016]: 1 server connects that finished 2005.01.03 22:39:49 LOG7[37000:134614016]: 0 server renegotiatiations requested 2005.01.03 22:39:49 LOG7[37000:134614016]: 0 session cache hits 2005.01.03 22:39:49 LOG7[37000:134614016]: 0 session cache misses 2005.01.03 22:39:49 LOG7[37000:134614016]: 0 session cache timeouts 2005.01.03 22:39:49 LOG6[37000:134614016]: SSL accepted: new session negotiated 2005.01.03 22:39:49 LOG6[37000:134614016]: Negotiated ciphers: AES256-SHA SSLv3 Kx=RSA Au=RSA Enc=AES(256) Mac=SHA1 2005.01.03 22:39:49 LOG7[37000:134614016]: FD 10 in non-blocking mode 2005.01.03 22:39:49 LOG7[37000:134614016]: https connecting 127.0.0.1:80 2005.01.03 22:39:49 LOG7[37000:134614016]: Remote FD=10 initialized 2005.01.03 22:39:49 LOG7[37000:134614016]: TCP_NODELAY option set on remote socket 2005.01.03 22:39:49 LOG7[37000:134614016]: Socket closed on read 2005.01.03 22:39:49 LOG7[37000:134614016]: SSL write shutdown (output buffer empty) 2005.01.03 22:39:49 LOG7[37000:134614016]: SSL alert (write): warning: close notify 2005.01.03 22:39:49 LOG7[37000:134614016]: SSL_shutdown retrying 2005.01.03 22:39:49 LOG7[37000:134614016]: s_poll_wait timeout waiting for SSL close_notify 2005.01.03 22:39:49 LOG5[37000:134614016]: Connection closed: 267 bytes sent to SSL, 78 bytes sent to socket 2005.01.03 22:39:49 LOG7[37000:134614016]: https finished (0 left) Всё! Проверено – мин нет. :o)) Итак на этой стадии мы научились: 1. Запускать процессы в chroot – окружение. 2. Кофигурировать клиентскую и серверную части stunnel 3. Получили представление и освоили некоторые аспекты работы с пакетом openssl. N.B. В процессе подготовки материала я выяснил, что вышел релиз stunnel-4.07. Попрошу 0x90 собрать его из патченных сорцев с последней версией openssl и подробно осветить этот нелегкий труд в рамках данной статьи. Ну и в завершение опуса постараюсь завтра доделать последнюю главу, которая, по логике, должна получиться совсем небольшой. :)) |
![]() |
![]() |