ДМИТРИЙ НЕСТЕРКИН, инженер, системный администратор ООО «Телисет-С», имеет сертификат Microsoft MCDST. Сфера интересов: сетевые технологии, программное обеспечение с открытым исходным кодом
Настройка интернет-шлюза
с авторизацией через AD по протоколу Kerberos
Едва ли есть организация, компьютерная сеть которой не имела бы собственного шлюза для доступа в Интернет. Различных решений здесь масса, я опишу то, которое было выбрано в нашей организации.
Были поставлены следующие задачи:
- обеспечение безопасности сети посредством файeрвола;
- прокси-сервер для организации доступа пользователей в Интернет с возможностью контроля и учета доступа, запрета посещения сайтов согласно политике компании;
- интеграция с Active Directory;
- надежное и безопасное решение, не подверженное большинству угроз.
В результате мы пришли к следующей конфигурации ПО:
- Debian Lenny 5.0;
- Squid 2.7 STABLE3, аутентификация через Kerberos;
- Apache2 (для вывода страниц с сообщениями о запрете доступа);
- Rejik 3 для ограничения доступа к запрещенным сайтам.
Преимущества данного решения:
- как любая Linux-система, Debian мало подвержена вирусным атакам;
- гибко настраиваемый прокси-сервер, для которого доступны различные анализаторы логов и сторонние модули;
- Kerberos-аутентификация абсолютно прозрачна для пользователя и является одной из самых безопасных схем аутентификации.
Немного устаревшая версия Squid выбрана из-за того, что она, по нашему опыту, максимально корректно работает с протоколом Kerberos. В Squid версии 3 модуль авторизации squid_kerb_auth на момент написания статьи отсутствовал.
Настройка
После этапа непосредственной установки операционной системы, описанного уже много раз, приступаем к конфигурированию.
Для упрощения настройки файервола был составлен следующий скрипт, автозапуск которого потом был прописан через rc-update:
#!/bin/sh# Конфигурация внешнего интерфейсаINET_IP="11.22.33.44"INET_IFACE="eth0"INET_BROADCAST="255.255.255.0"## Конфигурация внутреннего интерфейсаLAN_IP="192.168.100.253"LAN_IP_RANGE="192.168.100.0/24"LAN_IFACE="eth1"# Конфигурация localhostLO_IFACE="lo"LO_IP="127.0.0.1"# Конфигурация IPTablesIPT="/sbin/iptables"# Номера непривилегированных портовNONPRIPORTS="1024:65535"# Модули IPTables/sbin/modprobe ip_tables/sbin/modprobe ip_conntrack/sbin/modprobe iptable_filter/sbin/modprobe iptable_mangle/sbin/modprobe iptable_nat/sbin/modprobe ipt_LOG/sbin/modprobe ipt_limit/sbin/modprobe ipt_state/sbin/modprobe ipt_REJECT# Включаем форвардингecho "1" > /proc/sys/net/ipv4/ip_forward/sbin/sysctl -w net.ipv4.ip_forward=1# Сбрасываем правила и удаляем цепочки$IPT -F$IPT -X# Политика по умолчанию$IPT -P INPUT DROP$IPT -P OUTPUT DROP$IPT -P FORWARD ACCEPT# Разрешаем прохождение любого трафика по loopback-интерфейсу$IPT -A INPUT -i $LO_IFACE -j ACCEPT$IPT -A OUTPUT -o $LO_IFACE -j ACCEPT# Если интерфейс не loopback, то запрещаем входить в список# его адресов$IPT -A INPUT -s 127.0.0.1/255.0.0.0 ! -i $LO_IFACE -j DROP# Отбрасываем все некорректно сформированные пакеты$IPT -A INPUT -m state --state INVALID -j DROP$IPT -A FORWARD -m state --state INVALID -j DROP# Принимаем все пакеты, принадлежащие уже установленным# (ESTABLISHED) соединениям$IPT -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT$IPT -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT# Правила для внутренней сети$IPT -A INPUT -p ALL -i $LAN_IFACE -s $LAN_IP_RANGE -j ACCEPT$IPT -A OUTPUT -p ALL -o $LAN_IFACE -d $LAN_IP_RANGE -j ACCEPT$IPT -A INPUT -p tcp -i $LAN_IFACE --dport 3128 -j ACCEPT# Правила защиты от некоторых распространенных атак снаружи и изнутри сети# (Внимание! Данные правила могут нарушить работу части прграмм и сервисов)#SYN Flood$IPT -A INPUT -p tcp ! --syn -m state --state NEW -j DROP$IPT -A OUTPUT -p tcp ! --syn -m state --state NEW -j DROP#UDP Flood$IPT -A INPUT -p UDP -i $INET_IFACE --dport 138 -j DROP$IPT -A INPUT -p UDP -i INET_IFACE --dport 113 -j REJECT$IPT -A INPUT -p UDP -i INET_IFACE --sport 67 --dport 68 -j REJECT$IPT -A INPUT -p UDP -j RETURN$IPT -A OUTPUT -p UDP -o $INET_IFACE -j ACCEPT#ICMP-перенаправление$IPT -A INPUT --fragment -p ICMP -j DROP$IPT -A OUTPUT --fragment -p ICMP -j DROP# Разрешаем ICMP-соединение$IPT -A INPUT -p icmp -m icmp -i $INET_IFACE --icmp-type source-quench -j ACCEPT$IPT -A OUTPUT -p icmp -m icmp -o $INET_IFACE --icmp-type source-quench -j ACCEPT# Разрешаем ping и весь ICMP-трафик внутри нашей сети$IPT -A INPUT -p icmp -m icmp -i $INET_IFACE --icmp-type echo-reply -j ACCEPT$IPT -A INPUT -p icmp -m icmp -i $LAN_IFACE -j ACCEPT$IPT -A OUTPUT -p icmp -m icmp -o $INET_IFACE --icmp-type echo-request -j ACCEPT$IPT -A OUTPUT -p icmp -m icmp -o $LAN_IFACE -j ACCEPT$IPT -A INPUT -p icmp -m icmp -i $INET_IFACE --icmp-type echo-request -j ACCEPT$IPT -A OUTPUT -p icmp -m icmp -o $INET_IFACE --icmp-type echo-reply -j ACCEPT# Разрешаем передачу пакета «некорректный параметр» – используется, если в заголовке пакета# содержится недопустимая запись или CRC пакета не совпадает с указанной$IPT -A INPUT -p icmp -m icmp -i $INET_IFACE --icmp-type parameter-problem -j ACCEPT$IPT -A OUTPUT -p icmp -m icmp -o $INET_IFACE --icmp-type parameter-problem -j ACCEPT# Разрешаем запросы к DNS$IPT -A OUTPUT -p udp -m udp -o $INET_IFACE --dport 53 --sport $NONPRIPORTS -j ACCEPT$IPT -A OUTPUT -p tcp -m tcp -o $INET_IFACE --dport 53 --sport $NONPRIPORTS -j ACCEPT$IPT -A INPUT -p udp -m udp -i $INET_IFACE --dport $NONPRIPORTS --sport 53 -j ACCEPT$IPT -A INPUT -p tcp -m tcp -i $INET_IFACE --dport 1024:65353 --sport 53 -j ACCEPT # Разрешаем AUTH-запросы на удаленные сервера, на свой – запрещаем$IPT -A OUTPUT -p tcp -m tcp -o $INET_IFACE --dport 113 --sport $NONPRIPORTS -j ACCEPT$IPT -A INPUT -p tcp -m tcp -i $INET_IFACE --dport $NONPRIPORTS --sport 113 -j ACCEPT ! --syn$IPT -A INPUT -p tcp -m tcp -i $INET_IFACE --dport 113 -j DROP# Открываем необходимые нам порты# FTP (21)$IPT -A OUTPUT -p tcp -m tcp -o $INET_IFACE --dport 21 --sport $NONPRIPORTS -j ACCEPT# SMTP (25)$IPT -A OUTPUT -p tcp -m tcp -o $INET_IFACE --dport 25 --sport $NONPRIPORTS -j ACCEPT# POP3 (110)$IPT -A OUTPUT -p tcp -m tcp -o $INET_IFACE --dport 110 --sport $NONPRIPORTS -j ACCEPT# HTTP/HTTPS клиент (80, 443)$IPT -A OUTPUT -p tcp -m tcp -m multiport -o $INET_IFACE --sport $NONPRIPORTS -j ACCEPT --dports 80,443# PROXY (3128)$IPT -A OUTPUT -p tcp -m tcp -o $LAN_IFACE --dport 3128 -j ACCEPT$IPT -A INPUT -p tcp -m tcp -i $LAN_IFACE --dport 3128 -j ACCEPT#ICQ (5190)$IPT -A OUTPUT -p tcp -m tcp -o $INET_IFACE --dport 5190 --sport $NONPRIPORTS -j ACCEPT#QIP-аккаунт (5222)$IPT -A OUTPUT -p tcp -m tcp -o $INET_IFACE --dport 5222 --sport $NONPRIPORTS -j ACCEPT# Включаем NAT$IPT -t nat -A POSTROUTING -o $INET_IFACE -j SNAT --to-source $INET_IP
Таким образом, мы контролируем трафик по различным протоколам и организовываем трансляцию адресов для нашей сети.
Конечно, данный скрипт не может претендовать на абсолютную универсальность, он приведен здесь скорее в качестве примера, а не руководства к действию.
Установливаем Squid
Стандартная установка пакета через менеджер пакетов компилируется не совсем так, как нам нужно. Поэтому нам необходимо скачать пакет с исходными текстами командой dpkg‑source и отредактировать файл debian/rules так, чтобы там были прописаны следующие параметры:
--enable-auth="basic,negotiate"
--enable-negotiate-auth-helpers="squid_kerb_auth"
--enable-external-acl-helpers="ldap_group"
После этого Squid собирается командами:
debian/rules build
debian/rules binary
Вы получите 3 бинарных пакета, однако установить достаточно только два: squid и squid-common.
Однако и это еще не все. Необходимый нам хелпер squid_kerb_auth поддерживает как реализацию MIT Kerberos, так и Heimdal Kerberos, и поэтому в итоге скомпилированный хелпер не работает корректно. Для решения данной проблемы в исходниках ищем файл ./helpers/negotiate_auth/squid_kerb_auth/readme.txt и копируем оттуда кусок кода, отвечающий за реализацию MIT kerberos, в файл и запускаем получившийся скрипт.
Вот что нужно скопировать:
#!/bin/shDEFINE_SPNEGO=-DHAVE_SPNEGO#HEIMDAL# DEFINE="-DHEIMDAL $DEFINE_SPNEGO -d__LITTLE_ENDIAN__"# INCLUDE=-I/usr/include/heimdale -Ispnegohelp#LIBS="-Lgssapi -lkrb5 -lcom_err -lasn1 -lroken"#MIT DEFINE="$DEFINE_SPNEGO -D__LITTLE_ENDIAN__" INCLUDE=-Ispnegohelp LIBS="-lgssapi_krb5 -lkrb5 -lcom_err"#SPNEGO="spnegohelp/derparse.c spnegoelp/spnego.c spnegohelp/spnegohelp.c spnegohelp/spnegoparse.c"SOURCE="squid_kerb_auth.c base64.c"qcc -o squid_kerb_auth $DEFINE $INCLUDE $SOURCE $SPNEGO $LIBS
Скомпилированный хелпер копируем в /usr/lib/squid с заменой исходного файла.
Устанавливаем Rejik
В принципе установка сводится к простым командам:
make
make install
За исключением пары тонкостей:
- Необходима библиотека pcre.
- В makefile нужно прописать переменные SQUID_USER и SQUID_GROUP, значения которых должны совпадать со значением переменных cache_effective_user и cache_effective_group файла squid.conf.
После установки редактируем конфигурационный файл /usr/local/rejik3/redirector.conf – там необходимо прописать правила блокировки сайтов и пути к HTML-страницам с сообщениями о запрете доступа.
Теперь на контроллере домена необходимо создать билет для учетной записи, под которой будут проверяться учетные данные пользователя при доступе в Интернет. Учетная запись должна иметь неограниченный срок действия пароля и не должна блокироваться. Например:
домен – mydomain.local;
имя пользователя – proxyuser;
пароль – password.
сервер – squidproxy.mydomain.local.
Наша команда:
C:\Program Files\Support Tools>ktpass -princ HTTP/squidproxy.mydomain.local@MYDOMAIN.LOCAL \
-mapuser proxyuser -crypto des-cbc-md5 -pass "password" -ptype KRB5_NT_SRV_HST -out squid.keytab
Поскольку мы не вводим прокси-сервер в домен, то в DNS должны быть внесены данные о нашем сервере (A- и PTR-записи). Создаем группу пользователей, которым разрешен доступ в Интернет (например, группа INET_ALLOW в OU Internet). Копируем .keytab-файл в папку /etc/squid. Меняем права доступа:
chmod 400 /etc/squid/squid.keytab
chown proxy /etc/squid/squid.keytab
В файл /etc/init.d/squid вносим строки для подключения ключа:
KRB5_KTNAME=/etc/squid/squid.keytab
export KRB5_KTNAME
Если у вас много пользователей и Squid тратит много ресурсов на их аутентификацию, то можно отключить проверку кэша использованных тикетов, добавив в /etc/init.d/squid следующие строки:
KRB5RCACHETYPE=none
export KRB5RCACHETYPE
Настраиваем Kerberos
Несмотря на то что пакет krb5-user (клиент Kerberos) в стабильной версии Lenny должен быть совместим с Kerberos V5, у нас он работал некорректно, и потребовалось установить данный пакет (со всеми зависимостями) из ветки testing.
Основным файлом настроек является /etc/krb5.conf. Необходимо отредактировать его следующим образом:
[libdefaults]default_realm = MYDOMAIN.LOCALdns_lookup_realm = nodns_lookup_kdc = nodefault_keytab_name = /etc/squid/squid.keytabdefault_tgs_enctypes = des-cbc-crc rc4-hmac des-cbc-md5default_tkt_enctypes = des-cbc-crc rc4-hmac des-cbc-md5permitted_enctypes = des-cbc-crc rc4-hmac des-cbc-md5ticket_lifetieme = 24000clock_skew = 300# The following krb5.conf variables are only for MIT Kerberoskrb4_config = /etc/krb.confkrb4_realms = /etc/krb.realmskdc_timesync = 1ccache_type = 4forwardable = trueproxiable = true# The following libdefaults parameters are only for Heimdal# Kerberosv4_instance_resolve = falsev4_name_convert = {host = {rcmd = hostftp = ftp}plain = {something = something-else}}fcc-mit-ticketflags = true#[realms]MYDOMAIN.LOCAL = {kdc = dc.mydomain.localadmin_server = dc.mydomain.localdefault_domain = mydomain.local}#[domain_realm].linux.local = MYDOMAIN.LOCAL.mydonain.local = MYDOMAIN.LOCALmydomain.local = MYDOMAIN.LOCAL#[logging]default = FILE:/var/log/krb5lib.logkdc = FILE:/var/log/kdc.logkdc = SYSLOG:INFO AEMONadmin_server = FILE:/var/log/kadmin.log
Проверяем ключ:
$ kinit -V -k -t /etc/squid/squid.keytab HTTP/squidproxy.mydomain.local
Вы должны получить в ответ:
Authenticated to Kerberos V5 |
Настраиваем Squid
Редактируем файл /etc/squid/squid.conf так:
auth_param negotiate program /usr/lib/squid/squid_kerb_auth -d -s HTTP/squidproxy.mydomain.local@MYDOMAIN.LOCALauth_param negotiate children 10auth_param negotiate keep_alive onacl all src all#Recommended minimum configuration:acl manager proto cache_objectacl localhost src 127.0.0.1/32acl to_localhost dst 127.0.0.0/8#acl SSL_ports port 443acl Safe_ports port 80 # httpacl Safe_ports port 21 # ftpacl Safe_ports port 443 # httpsacl Safe_ports port 70 # gopheracl Safe_ports port 210 # waisacl Safe_ports port 1025-65535 # unregistered portsacl Safe_ports port 280 # http-mgmtacl Safe_ports port 488 # gss-httpacl Safe_ports port 591 # filemakeracl Safe_ports port 777 # multiling httpacl CONNECT method GET# Тут проверяем группу, к которой принадлежит пользователь# (вся конструкция пишется в одну строку, хотя и разбита при печати)external_acl_type ldap_ad_check ttl=1200 %LOGIN /usr/lib/squid/squid_ldap_group -R -b "dc=mydomain,dc=local" \ -f "(&(objectclass=user)(sAMAccountName=%v (memberof=cn=%a,ou=internet,dc=mydomain,dc=local))" \ -D "proxyuser@mydomain.local" -w "password" -K -d 192.168.100.#192.168.100.2 – адрес DCacl inet_access external ldap_ad_check @INET_ALLOWacl AUTHENTIC proxy_auth REQUIRED#http_access allow inet_accesshttp_access deny !AUTHENTIChttp_access allow AUTHENTIChttp_access deny all#http_port 3128#redirect_program /usr/local/rejik3/redirector /usr/local/rejik3/redirector.conf
На клиентских машинах необходимо прописать прокси-сервер в виде FQDN: squidproxy.mydomain.local, порт 3128. Использование IP-адреса или сокращенного имени компьютера недопустимо. Также был выявлен необычный баг, связанный с длиной имени хоста прокси-сервера. В случае слишком короткого имени (у нас вначале было 5 букв) Kerberos-авторизация не работает.
Просмотр статистики доступа к интернет-ресурсам можно организовать с помощью различных утилит, генерирующих отчеты на основе журналов Squid. Мы используем для этой цели lightsquid. Это очень удобное решение, генерирующее подробные html-отчеты, которые доступны через веб-интерфейс. Для установки достаточно скачать архив с официального сайта http:// lightsquid.sourceforge.net, распаковать его в каталог /var/www/<каталог lightsquid> и изменить права доступа ко всем файлам так, чтобы они стали исполняемыми, а их владельцем стал пользователь Apache.
В файле httpd.conf необходимо добавить строки:
<Directory "/var/www/<каталог lightsquid>"> AddHandler cgi-script .cgi AllowOverride All</Directory>
Настройка осуществляется через файл lightsquid.cfg. Соответствие учетных записей пользователей, групп и их реальных имен – через файлы group.cfg и realname.cfg.
***
Итак, мы получили интернет-шлюз, работающий абсолютно прозрачно для пользователей (учетные данные берутся из Windows-сессии) и соответствующий всем поставленным в начале статьи требованиям. При этом нам не потребовались дополнительные сервисы вроде Samba, что экономит ресурсы сервера. Однако у данного решения есть один минус: Kerberos-аутентификация поддерживается не всеми браузерами. Поэтому их использование в компании должно быть регламентировано.
В настоящий момент совместимость браузеров такова:
Internet Explorer 6 и более ранние – Kerberos не поддерживается;
Internet Explorer 7 – поддержка заявлена, однако из-за имеющейся ошибки аутентификация пропадает через полчаса, и требуется перезапуск браузера;
Internet Explorer 8 – полная поддержка;
Mozilla Firefox 3.5 – полная поддержка;
Opera – не поддерживается ни в одной версии, включая 10 (представители Opera Software заявляют, что данный тип авторизации редко востребован, а внесение его поддержки требует серьезных изменений в коде браузера);
Apple Safari – поддержка заявлена, но я не проверял;
Google Chrome – не поддерживается ни в одной версии, включая 3.0 (на момент написания статьи актуальной была версия 3.0.195.21).