Stunnel: шифрование трафика под Linux

введение
Подавляющее большинство данных в Internet проходят в открытом виде. HTTP, FTP, TELNET, POP3, SMTP и многие другие часто используемые протоколы не имеют никакой криптографической защиты. Существует большое количество утилит для прослушивания сетевого трафика. Многие из них умеют сами анализировать проходящие данные и выделять из них наиболее важные. С помощью таких утилит можно получить пароли на различные службы (POP3, FTP, ICQ, SMB и т.д.), тексты писем, файлы, пересылаемые по NFS, SMB или FTP, сообщения, переданные по ICQ и т.д. (одной из таких программ является Dsniff) Всегда есть вероятность того, что найдется тот, кому захочется получить ваши пароли или почитать вашу же почту. Защитить себя от такого прослушивания можно с помощью шифрования трафика, проходящего между твоим хостом и хостом, к которому вы подключаетесь.
В свое время были разработаны несколько криптографических протоколов. Большую популярность получил протокол SSL, разработанный Netscape Communications. В основном он применяется для шифровки HTTP-протокола (HTTPS), но может применяться для создания защищенных соединений с SMTP, POP3, IMAP и т.д.. Существует серверные приложения под Linux, поддерживающие SSL-соединения для IMAP(IMAPS), POP3 (POP3S), HTTP (HTTPS), SMTP(SMTPS) и т.д. Некоторые клиентские приложения под Linux поддерживают SSL-соединения, например, Netscape Navigator поддерживает HTTPS.
Существует программа, создающая поддержку SSL почти для любых серверных и клиентских приложений под Linux и Windows — Stunnel. Фактически программа создает SSL-соединение между клиентом и сервером по любому протоколу, основанному на TCP. Исключение составляет FTP, так как он использует разные порты для соединения и передачи файлов. Таким образом, основное ее применение состоит в создании надежного шифрованного канала между двумя и более хостами в сетях, где возможна угроза прослушивания трафика. Может работать как в режиме клиента (шифрование исходящего трафика), так и в режиме сервера (расшифровка входящего трафика).

установка
Для работы необходим установленный OpenSSL. OpenSSL входит почти во все современные дистрибутивы Linux, так что возможно он у вас уже установлен.
Взять Stunnel можно на сайтеwww.stunnel.org  с странички Download/Stunnel Source Code. На момент написания статьи последней версией Stunnel была 3.14
После того, как скачаете, распакуйте полученный архив:

tar xfz stunnel-3.14.tar.gz

Для начала надо запустить скрипт configure для создания Makefile:

cd stunnel-3.14
./configure --with-pem-dir=/etc/ssl/certs --with-cert-dir=/etc/ssl/certs/trusted

Опция --with-pem-dir указывает каталог, где будет находиться секретный ключ и сертификат. Каталог зависит от опций компиляции OpenSSL. Это может быть /etc/ssl/certs,/usr/local/ssl/certs/var/ openssl/certs или какой-либо другой. Опция --with-cert-dir указывает каталог, где будут находиться проверенные сертификаты удаленных хостов. В принципе, можно указать любой каталог для хранения сертификатов и секретного ключа, это особого значения не имеет. Подробнее о секретных ключах и сертификатах можно почитать на http://www.openssl. org/docs
Если все прошло нормально, соберите пакет:

make

После сборки stunnel будут созданы секретный ключ и сертификат сервера, которые будут помещены в файл stunnel.pem. Для этого от вас потребуется ввести некоторые данные. Первые три — код страны, название штата (области) и город:

/usr/bin/openssl req -new -x509 -days 365 -nodes \
-config stunnel.cnf -out stunnel.pem -keyout stunnel.pem
Using configuration from stunnel.cnf
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) []:Moscow

Затем — название организации и отдела организации:

Organization Name (eg, company) [Stunnel Developers Ltd]:DH Developer
Organizational Unit Name (eg, section) []:

Затем имя сервера:

Common Name (FQDN of your server) []:dh.home.cxm
Common Name (default) []:localhost

Второе значение (localhost) проставляется без вашей помощи. От этого можно избавится, если удалить строку 1. commonName_value = localhost в файле stunnel.cnf, удалить файл stunnel.pem (если он есть) и запустить сборку заново, введя в этом месте имя хоста.
В конце будут выведены данные созданного сертификата:

/usr/bin/openssl x509 -subject -dates -fingerprint -noout \
-in stunnel.pem
subject= /C=RU/ST=Some-State/L=Moscow/O=DH Developer/CN=dh.home.cxm/CN=localhost
notBefore=Mar 11 22:53:11 2001 GMT
notAfter=Mar 11 22:53:11 2002 GMT
MD5 Fingerprint=FA:2A:D8:D7:4B:23:D5:6C:67:22:D9:EC:06:C4:26:6F

Осталось только установить пакет:

su -c "make install"

После установки должны появиться следующие файлы:

/usr/local/sbin/stunnel
/usr/local/lib/stunnel.so
/usr/local/man/man8/stunnel.8
/usr/local/var
/etc/ssl/certs/stunnel.pem

Последний файл будет в каталоге, который ты указал при конфигурации в опции --with-pem-dir. Не забудь также создать каталог, указанный тобой в опции --with-cert-dir, если он не существует.

туннелирование
Как я уже говорил, Stunnel может работать в двух режимах — сервера и клиента. В качестве сервера Stunnel открывает указанный порт, дешифрует все поступившие данные и передает их либо в указанную в параметрах запуска программу, либо на указанный порт на указанном хосте, обеспечивая таким образом поддержку SSL у различных серверных приложений, которые таковой не обладают. В качестве клиента Stunnel открывает указанный порт, шифрует все поступившие на него данные и передает их (как и в качестве сервера) в определенную программу или на определенный порт на заданном хосте. И в качестве сервера, и в качестве клиента есть возможность запуска как отдельного демона, так и посредством inetd.
Покажу все это на примере создания защищенного telnet-соединения между хостами A и B. Предположим, что telnet-соединение будет осуществляться с хоста A на хост B. При нормальных условиях достаточно набрать telnet B на хосте A, ввести имя пользователя и пароль и соединение осуществлено. Все данные, передаваемые по такому соединению (в том числе и имя пользователя и пароль), идут в открытом виде. Если это чревато последствиями (причем неприятными), то лучше организовать весь обмен данными по telnet между этими хостами в шифрованном виде.
Для начала надо на обоих хостах установить Stunnel (пригодится...:)). Затем на хосте B запустить Stunnel в режиме сервера:

stunnel -d 992 -r 23

Опция -d указывает Stunnel работать в режиме отдельного демона, ждущего соединения по порту 992. Все данные, полученные в шифрованном виде на порт 992, в открытом виде передаются на порт 23 на локальной машине (опция -r).
Затем на хосте A запустить Stunnel в режиме клиента:

stunnel -c -d 1123 -r B:992

Опция -c указывает на работу в режиме клиента (по умолчанию Stunnel запускается в режиме сервера), как и в предыдущем случае, работа в режиме отдельного демона, все данные, полученные в открытом виде на порт 1123, передаются в шифрованном виде на порт 992 на хосте B. Таким образом, получается следующая цепочка:

данные_в_открытом_виде ->порт_1123_на_хосте_A ->шифрование ->
данные_в_зашифрованном_виде ->порт_992_на_хосте_B ->дешифровка ->
данные_в_открытом_виде ->порт_23_на_хосте_B

Теперь можно набрать telnet localhost 1123 на хосте A для подключения к порту 23 на хосте B. Сложно, зато безопасно...:) Естественно, во втором случае вместо B:992 должно быть указано реальное_имя_хоста_в_Internet:992. Порты, открытые на хосте A и хосте B (1123 и 992), могут быть любые — главное, чтоб они не использовались другими программами.
Случай, описанный выше, довольно-таки тривиальный. Усложним задачу.:)
Предположим, что есть хосты A1, B1, C1 в одной подсетке со шлюзом G1, но без прямого доступа в Internet, и хост A2 в другой подсети, также без прямого доступа в и из Internet, со шлюзом G2. Единственное соединение между двумя подсетками — через Internet. Также предположим, что хостам A1,B1 и C1 нужен доступ к различным почтовым аккаунтам на хосте A2. При этом, весь трафик, проходящий по незащищенным сетям между хостами A1, B1, C1 и хостом A2 должен быть шифрованным. (Нестандартная ситуация, не так ли?:))
Таким образом, прямое соединение хостов A1,B1,C1 возможно только с хостом G1, хост G1 может соединяться через Internet с хостом G2, а с хоста G2 напрямую доступен хост A2. В данном случае, незащищенное соединение — между хостами G1 и G2.
Решение:
Устанавливаем Stunnel на хосты G1 и G2. На хосте G2 запустим серверную часть:

stunnel -d 1110 -r A2:110
stunnel -d 1125 -r A2:25

Первый демон перенаправляет весь входящий трафик, предварительно расшифровав его, на порт 110 (pop3), а второй — на порт 25 (smtp) на хосте A2. Предполагается, что программы ipop3d (или подобная) и sendmail (или подобная) уже запущены на хосте A2.
На хосте G1 запускаем клиентскую часть:

stunnel -с -d 1110 -r G2:1110
stunnel -с -d 1125 -r G2:1125

На хостах A1,B1,C1 настраиваем почтовые клиенты, указывая в качестве pop3-сервера — G1, порт 1110, а в качестве smtp-сервера — G1, порт 1125, имена пользователей и пароли те, что прописаны на хосте A2.
Таким же образом можно создавать соединения по любым портам и практически по любым протоколам, основанным на TCP.
Единственная проблема в том, что надо запускать отдельный демон для каждого соединения, и каждый запущенный Stunnel должен использовать свой уникальный порт. Покажу это еще на одном примере:
Предположим, что есть хост A, который должен иметь защищенные telnet-соединения с хостами B,C и D. Соответственно, на всех указанных хостах должен быть установлен Stunnel.
Запустим Stunnel на хостах B,C и D в режиме сервера, выполнив на каждом из них следующую команду:

stunnel -d 992 -l /usr/sbin/in.telnetd — in.telnetd

Опция -l указывает Stunnel при подключении к открытому порту запустить указанную программу с указанными аргументами (после "--") и передать ей весь входящий трафик. Имя программы и аргументы передаются в том же виде, что и в /etc/inetd.conf.
На хосте A запустим три Stunnel-клиента, каждый на своем порту:

stunnel -c -d 1123 -r B:992
stunnel -c -d 1124 -r C:992
stunnel -c -d 1125 -r D:992

Запустив на хосте A команду telnet localhost 1123, вы подключитесь к хосту B, запустив telnet localhost 1124 — к хосту C, а telnet localhost 1125 отправит вас на хост D.

SSL-порты и Inetd
Может возникнуть ситуация, когда используемое вами с одной стороны (клиента или сервера) приложение поддерживает SSL. Тогда Stunnel можно запускать только со другой стороны (сервера или клиента). 
Например, если вы хотите забирать почту Netscape Messenger'ом через imaps (ssl-imap), а установленный на сервере imapd не поддерживает SSL, то на хосте-сервере можно запустить Stunnel, а на хосте-клиенте можно не запускать, т.к. Netscape Messanger и так поддерживает соединение по SSL. И, наоборот, если на сервере у вас установлен ipop3d, поддерживающий SSL, а ваш почтовый клиент не поддерживает pop3s(ssl-pop3), то Stunnel запускать нужно только на хосте-клиенте.
Возьмем первую ситуацию (когда клиентское приложение поддерживает SSL, а серверное — нет). Необходимо не просто запустить на сервере Stunnel, но и выбрать такой порт для подключения, который будет поддерживаться клиентским приложением. Благо данную проблему давно решили за нас — существует официальный список SSL-портов, т.е. надо просто выбирать для каждого сервиса такие порты, которые используют все...:) Вот этот список:

https443/tcp# http protocol over TLS/SSL
smtps465/tcp# smtp protocol over TLS/SSL (was ssmtp)
nntps563/tcp# nntp protocol over TLS/SSL (was snntp)
imap4-ssl585/tcp# IMAP4+SSL (use 993 instead)
sshell614/tcp# SSLshell
ldaps636/tcp# ldap protocol over TLS/SSL (was sldap)
ftps-data989/tcp# ftp protocol, data, over TLS/SSL
ftps990/tcp# ftp protocol, control, over TLS/SSL
telnets992/tcp# telnet protocol over TLS/SSL
imaps993/tcp# imap4 protocol over TLS/SSL
ircs994/tcp# irc protocol over TLS/SSL
pop3s995/tcp# pop3 protocol over TLS/SSL (was spop3)

Добавьте эти данные в файл /etc/services, предварительно убедившись, что там их до этого не было;) 
После этого можно настроить вызов Stunnel из inetd.
Вызов из inetd имеет свои преимущества. У Stunnel нет встроенной возможности ограничений на подключение, у inetd есть. При помощи файлов /ets/hosts.allow и /etc/hosts.deny можно запретить или разрешить доступ к определенным сервисам, в том числе и поддерживаемым Stunnel, с определенных хостов.
Предположим, вам необходимо добавить поддержку SSL для imapd, ipop3d и sendmail.
В файле /etc/inetd.conf есть примерно такие строки:

pop-3stream tcpnowait root/usr/sbin/tcpdipop3d
imapstream tcpnowait root/usr/sbin/tcpdimapd

Они описывают вызов imapd и ipop3d из inetd (строки в вашем inetd.conf могут отличаться от вышеуказанных). Добавьте следующие строки для поддержки SSL для pop3,imap и smtp:

pop3sstream tcpnowait root/usr/local/sbin/stunnelstunnel -l /usr/sbin/ipop3d
imapsstream tcpnowait root/usr/local/sbin/stunnelstunnel -l /usr/sbin/imapd
smtpsstream tcpnowait root/usr/local/sbin/stunnelstunnel -r 25

Выполните /etc/rc.d/init.d/inet restart или killall -HUP inetd. Теперь можете проверить работу, подключившись к указанным портам при помощи своего почтового клиента с поддержкой SSL.
Аналогичным образом можно настроить и вызов Stunnel для остальных портов.

сертификаты
В Stunnel есть встроенная возможность проверки подлинности сертификатов тех хостов, к которым или с которых идет подключение. Для этого предназначена опция -v. После -v при вызове Stunnel указывается уровень проверки сертификата. Он может иметь следующие значения:
0
Никакой проверки наличия и подлинности сертификата не производится (значение по умолчанию).
1
Сертификат проверяется на подлинность, если присутствует. Если сертификат не является подлинным — соединение не устанавливается.
2
Проверяется присутствие сертификата и его подлинность. Если сертификат отсутствует или не является подлинным — соединение не устанавливается.
3
Проверяется присутствие сертификата и его наличие в списке проверенных сертификатов. Если сертификат отсутствует или его нет в списке проверенных сертификатов — соединение не устанавливается.
Сертификат создается при сборке пакета и помещается вместе с секретным ключом, используемым при расшифровке входящего трафика, в файл stunnel.pem. Подлинность сертификата означает его подтверждения какой-нибудь официальной службой проверки сертификатов. Для того, чтобы ваш сертификат был подтвержден (подписан), необходимо отправить заявку, заплатить и получить официальный подлинный сертификат.
В этом нет необходимости, если вы собираетесь пользоваться Stunnel для своих целей. Для этого достаточно использовать неподтвержденный сертификат, не проверяя его на подлинность. Т.е. исключить использование -v 1 и -v 2. Однако остается возможность использовать -v 3.
Файл stunnel.pem после установки помещается в указанный вами при сборке в опции --with-pem-dir каталог. В моем примере это /etc/ssl/certs. Содержимое его примерно такое:

-----BEGIN RSA PRIVATE KEY-----
#данные
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
#данные
-----END CERTIFICATE-----

Строки, начиная с "-----BEGIN CERTIFICATE-----" и заканчивая "-----END CERTIFICATE-----", и являются сертификатом. Его необходимо скопировать в отдельный файл и добавить в список проверенных сертификатов на хосте, с которым будет производится соединение. Список проверенных сертификатов может хранится в двух видах — каталог с файлами сертификатов или файл, содержащие данные сертификатов, примерно такого формата:

-----BEGIN CERTIFICATE-----
#данные 1-го сертификата
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
#данные 2-го сертификата
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
#данные 3-го сертификата
-----END CERTIFICATE-----
.....
-----BEGIN CERTIFICATE-----
#данные N-го сертификата
-----END CERTIFICATE-----

В первом случае, файл с сертификатом удаленного хоста копируется в каталог, указанный в опции --with-cert-dir при сборке (в моем примере /etc/ssl/certs/trusted). Затем выполняется команда c_rehash, входящая в поставку OpenSSL.

c_rehash /etc/ssl/certs/trusted

Она создает ссылку на скопированный файл, имеющую имя, состоящее из набора букв и цифр, и расширение.0 ("ноль", а не заглавное "о"). Этот так называемый hash-файл используется OpenSSL для создание индекса сертификатов. Поподробнее можно почитать, набрав man x509. Если в вашей системе нет команды c_rehash, то можно выполнить команду:

mv файл_сертификата.pem `openssl x509 -hash -noout -in файл_сертификата.pem`.0

Естественно, вместо файл_сертификата.pem должно быть указано имя вашего файла:)
Можно использовать каталог, отличный от указанного по умолчанию. Это удобно в случае, когда к каждому порту доступ должен быть с разного списка хостов. Указывается каталог при помощи опции -a. Например, для проверки сертификатов, содержащихся в каталоге /etc/ssl/certs/trusted2 необходимо запустить следующую команду:

stunnel [различные_опции] -a /etc/ssl/certs/trusted2 -v 3

Использование файла с проверенными сертификатами проще, чем использование каталога. Достаточно создать файл, записать в него содержимое нескольких сертификатов и указать его при запуске при помощи опции -A. Например, для указания файла /etc/certs/trusted_certs.pem в качестве файла проверенных сертификатов необходимо запустить stunnel таким образом:

stunnel [различные_параметры] -A /etc/certs/trusted_ certs.pem -v 3

Проверка сертификатов может производится как на стороне сервера (проверять подключенных клиентов), так и на стороне клиента (чтоб быть уверенным, что подключаешься к нужному хосту). Если Stunnel на стороне сервера настроен на проверку сертификата, то Stunnel на стороне клиента должен запускаться с опцией -p, после которой указан путь к файлу stunnel.pem. При запуске на стороне сервера использование -p не обязательно. Например:

stunnel -c -p /etc/ssl/certs/stunnel.pem -d 1123 -r some_host:992

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

заключение
• Везде, где это возможно, используйте шифрованные протоколы — это не сложно организовать и избавляет от многих головных болей.
• Используйте проверку сертификатов удаленных хостов на наличие их в списке проверенных — это поможет вам избежать атаки типа man-in-the-middle.
• Не проблема, если хост-клиент или хост-сервер работает под управлением системы семейства M$ Windows — есть Stunnel, работающий под МД.
• Stunnel не поддерживает FTP, поэтому в качестве защищенного FTP-сервера можно использовать OpenSSH, а в качестве FTP-клиента — Secure FTP.
• Stunnel имеет еще много различных опций запуска. Почитать о них можно, выполнив man stunnel. Также на сайте проекта можете почитать раздел FAQ — там много полезной информации.

Ерижоков А.А
DH's Linux Site
обсуждение статьи


Сетевые решения. Статья была опубликована в номере 04 за 2001 год в рубрике software

©1999-2024 Сетевые решения