Немного о пингвиноидах-параноиках

В этой статье мы поговорим про некоторые простенькие приемы безопасности для Linux. Есть много людей, которые считают: Линукс - это круто и надежно! Недаром ведь есть такая поговорка: "Это неправда, что под Линукс не существует вирусов, просто нужно самостоятельно скачать исходники с сайта производителя, скомпилировать их и запустить под рутом". Но, как показывает практика, уязвимостей и эксплоитов под никсы хватает. Если у вас все еще нет мании преследования, то это отнюдь не означает, что за вами не следят. Лучше быть параноиком, чем объектом издевательств. Защита пингвина сводится, в основном, к двум пунктам:


- защитить файрволом все, что не должно быть видно снаружи, и оставить только нужные амбразуры портов :)


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


Итак, начнем с файрвола. В Линуксе огненная стена поставляется с дистрибутивом, и чтобы выключить ее, надо сильно постараться. Сами по себе настройки по умолчанию уже достаточно неплохи. Есть два файервола под Линукс: ipchains (айпицепочки) и iptables (айпитаблицы). Хотя первый еще довольно часто встречается и используется, но дальнейшая разработка его прекращена. По-моему, в ветке ядра 2.6 ipchains уже вроде умерло (что там, например, у нас в Мандраке 10-м?). Все, что можно сделать в ipchains, можно сделать и в iptables. И даже намного больше.


Есть три встроенные цепочки: INPUT, OUTPUT и FORWARD, которые вы не можете удалить. Первые две отвечают за входящие и исходящие пакеты соответственно. Третья отвечает за пересылку (например с одного сетевого интерфейса на другой). А теперь берем командную строку, делаем su, топчем рутовый пассворд и начинаем набирать команду iptables. Находится она у нас в /sbin. Какие же опции можно скармливать данной команде? Сначала научимся обращаться с цепочками:


- Создать новую цепочку (-N)


- Удалить пустую цепочку (-X)


- Изменить policy для встроенной цепочки (-P)


- Просмотреть правила в цепочке (-L)


- Очистить все правила в цепочке (-F)


- Обнулить счетчики пакетов и байтов во всех правилах в цепочке (-Z)



Для управления правилами внутри цепочки:


- Добавить новое правило к цепочке (-A)


- Вставить новое правило в цепочку (-I)


- Заменить правило в цепочке (-R)


- Удалить правило в цепочке (-D)


- Удалить первое правило в цепочке соответствующее указанному (-D)


Однако работать в командной строке и писать все эти цепочки с головы как-то некошерно. Мне всегда нравилось написание с помощью Midnight Commander’а файла с командами, а потом его выполнение. Так наглядно видно, что же мы наваяли, и всегда легко можно все подправить. У каждого правила в цепочке должна быть цель. Здесь мы имеем ACCEPT (кому-то что-то разрешить) и DROP (кого-то на что-то опустить). Каждый пакет, проходящий через огненную стену, имеет множество параметров. Вот некоторые из них:


- Адрес отправителя. Задается с помощью ключей:
-s --source --src
Например:
-s 192.168.0.1 --src fuck.da.shit.ru --source 0/0
Это для любого айпишника. Также можно указывать в формате "ip/netmask" и адрес получателя. Задается с помощью ключей:
-d --destination --dst
Формат указания целей аналогичен с предыдущим ключом.



- Протокол. Ключ:
-p
Аргументы tcp или udp как раз для этого ключа.



- Порт назначения:
--dport
Можно писать как цифровое значение, так и его эквивалент. Например:
--dport 21
или
--dport ftp



- Порт отправителя:
--sport
Формат аналогичен предыдущему.


При указании портов можно делать логическое отрицание. Делается это выставлением знака "!" сразу перед айпишником. Пониматься это будет так: пакет который пришел (ушел) НЕ с заданного порта.



- Интерфейс, на который принимается пакет:
-i



- Интерфейс, через который отправляется пакет:
-o


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



А теперь несколько примеров с пояснениями, чтобы не заниматься голой теорией:


iptables -A INPUT -p udp --dport 139 -j DROP
Данное правило будет резать ВХОДЯЩИЕ на 139-й порт УДП пакеты.


iptables -A OUTPUT -p icmp -j DROP
Данное правило будет резать все ИСХОДЯЩИЕ ICMP пакеты (пинги).


iptables -A INPUT -s !101.102.103.104 --sport 53 -j DROP
Это правило будет резать ВХОДЯЩИЕ пакеты, которые ОТПРАВЛЕНЫ с 53-го порта, которые пришли НЕ с адреса 101.102.103.104. Это будет иметь смысл, когда на айпишнике 101.102.103.104 сидит ваш DNS сервер. То есть, вы будете слать ему на 53-й порт доменное имя типа www.fucking.site.ru, а он вам будет оттуда отдавать айпишник, по которому вы и будете связываться с нужным сервером.



Чтобы узнать текущий набор правил, можно глянуть, что нам покажет команда
iptables -L



При построении политики безопасности имеет смысл по умолчанию закрыть ВСЕ порты, а потом вручную открыть только те, которые нужны.



Теперь немного о NAT - о трансляции сетевых адресов или Network Address Translation. Вы никогда не задавались вопросом: а как работает любой прокси-сервер? Он на входе получает пакет, меняет в этом пакете адрес отправителя, перекидывает на другой интерфейс и отправляет дальше по назначению. Потом он получает пакет в ответ, смотрит кому же нужен этот пакет-ответ, и отправляет его машине, которая прислала запрос. Этот механизм и называется трансляцией сетевых адресов. Для реализации данной технологии используются две цепочки: PREROUTING и POSTROUTING. Первая предназначена для трансляции сетевого адреса при получении пакета на сетевой интерфейс, вторая занимается трансляцией адреса при отправлении пакетов с интерфейса. Для функционирования этого нужно включить пересылку пакетов с одного интерфейса на другой:
echo 1 > /proc/sys/net/ipv4/ip_forward



А теперь пару примеров:


Задачка #1.


Есть сеть из n+1 компов. На одном компе есть доступ в инет, а на остальных нет. При этом есть только один реальный внешний айпишник. Нужно выпускать все остальные n компов в инет. Как вы уже сами догадались, на этом самом компе есть два интерфейса (один - eth0 - смотрит в интернет, а другой - eth1 - смотрит во внутреннюю сеть) и стоит пингвин :)


Решение.


Топчем:
iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source eth0ip
где eth0ip - айпишник интерфейса, смотрящего в инет. Если же получается так, что у внешнего интерфейса нет постоянного айпишника (крутится на DHCP), такое бывает когда n+1 компов ходят в инет не по выделенке, а, например, через диалап, то используется такая вещь как MASQUERADE. Делаем так:
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
Все это даст совершенно одинаковый результат - n компьютеров получат доступ в инет. Данный метод называется "маскарадингом" и является классическим для использования.



Задачка #2.


Есть сеть из задачки один. Компьютер, подключенный к инету, назовем А. Нужно, чтобы компьютер А стал веб-сервером, но поднимать на нем Апач не хочется (например, потому что машина старая и медленная), и можно поднять апач на машине в замаскарадженной сети, назовем эту машину В.


Решение.


Поднимаем на машине В Апача (или любой другой веб-демон), топчем:
iptables -t nat -A PREROUTING -p tcp -d eth0IP --dport 80 -j DNAT --to-destination B_IP
где В_IP - IP-адрес машины В. И теперь получается так, что все http запросы перенаправляются на машину B, но самой машины В из внешней сети не видно. Вся прелесть в том, что в обоих случаях из инета видно только машину А, и все атаки будут идти на нее :) Все остальные машины смогут себе спокойно сидеть без всяких заплаток и файрволов и могут быть уверены, что их не зацепит всякая зараза типа MSblast.



Вот мы наконец подобрали правила для своей машины, все работает как часы, и нам хочется сохранить результаты своего труда и оставить это все в наследство внукам. Хранить это все в скриптах и запускать каждый раз - метод людей, проживающих недалеко от города Кишинеу. Лезем в /etc/sysconfig. Там мы находим чудесный файлик iptables. Как, у вас его нет????!!! Вы, наверное, счастливый обладатель дистрибутива от французов. Но ничего, Мандрэйк тоже хороший дистрибутив, и поможет вам команда
iptables-save


В том чудесном файлике хранятся все наши наборы правил, которые мы сделали для нашей системы. После недолгого рассмотрения видим, что внешний вид их не сильно изменился, и здесь их тоже можно свободно редактировать. Чтобы сохранить результаты наших команд, нужно набрать
iptables-save>/etc/sysconfig/iptables


После этой стадии все изменения и правила для вашего файрвола будут храниться там и инициализироваться при загрузке.


Рассмотрим, что же у нас получилось на нашем (моем) примере. Сначала минимальные пояснения: у меня два интерфейса. eth1 имеет 10.108.3.19 и смотрит в сеть, eth0 имеет 192.168.0.1 и смотрит на замаскарадженную тачку (она имеет 192.168.0.2)


Выдержка из файлика iptables:
# Generated by iptables-save v1.2.7a on Mon Apr 5 11:55:09 2004
*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [10537:617753]
# эти три строчки разрешили цепочки прероутинга (тут обрабатывается пересылка получаемых пакетов), построутинга (обработка пересылки отправляемых пакетов) и цепочки отправления
-A PREROUTING -d 10.108.3.19 -i eth1 -p tcp --dport 1023 -j DNAT --to-destination 192.168.0.2
# Здесь мы ловим поступающие запросы на 1023 порт и пересылаем эти запросы на замаскарадженую тачку с мастдаем. На этом порту в нашей сети обычно висит болталка, которой мы звоним друг другу. А поднимать виндовый софт вайном под рутом некошерно. Поэтому, если мне кто-то звонит, то попадает соответственно на другой комп (о существовании которого даже и не подозревает).
-A POSTROUTING -o eth1 -j SNAT --to-source 10.108.3.19
# здесь мы ловим пакеты которые уходят с интерфейса eth1 и меняем в них айпишник отправителя на 10.108.3.19. С помощью SNAT адреса потом транслируются назад при получении пакетов, и, если их отправляла машина, на которую смотрит интерфейс, eth0, то она получит их назад.
COMMIT
# Completed on Mon Apr 5 11:55:09 2004
# Generated by iptables-save v1.2.7a on Mon Apr 5 11:55:09 2004
*filter
:INPUT DROP [53878:5226995]
:FORWARD ACCEPT [2:96]
:OUTPUT ACCEPT [11788103:16967571263]
# рубим входящие пакеты и разрешаем отправку и пересылку между интерфейсами
:okay - [0:0]
# Заводим новую цепочку где заведем правила для разрешения некоторых входящих пакетов
-A INPUT -s 192.168.0.0/255.255.255.0 -i eth0 -j ACCEPT
# разрешаем все пакеты из доверенной внутренней подсети
-A INPUT -s 127.0.0.1 -i lo -j ACCEPT
-A INPUT -s 192.168.0.1 -i lo -j ACCEPT
-A INPUT -s 10.108.3.19 -i lo -j ACCEPT
# разрешаем пакеты для интерфейса внутренней петли
-A INPUT -d 10.108.3.19 -p tcp -m state --state RELATED,ESTABLISHED -j ACCEPT
# разрешаем входящие пакеты с состоянием RELATED и ESTABLISHED
-A INPUT -s 10.108.3.254/255.255.255.0 -p udp -m udp --sport 53 -j ACCEPT
# На 10.108.3.254 находится нэймсервер. Разрешаем вход пакетов с его 53 порта. Там живет BIND-DNS-сервер
-A INPUT -i eth1 -p tcp -m tcp --dport 21 -j okay
# открываем 21 порт для ФТП
-A INPUT -i eth1 -p tcp -m tcp --dport 22 -j okay
# открываем 22 порт для SSH
-A INPUT -i eth1 -p udp -m udp --dport 21 -j okay
# открываем 21 порт для ФТП
-A INPUT -i eth1 -p udp -m udp --dport 22 -j okay
# открываем 22 порт для SSH
-A INPUT -i eth1 -p icmp -m icmp --icmp-type 8 -j DROP -A INPUT -i eth1 -p icmp -m icmp --icmp-type 11 -j DROP
# режем эхо-реквесты (пинги)
-A FORWARD -i eth0 -j ACCEPT
# Разрешаем форвардинг пакетов, которые попадают к нам с внутреннего интерфейса
-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
# разрешаем форфардинг пакетов с состоянием RELATED и ESTABLISHED
-A okay -p tcp -m tcp --tcp-flags SYN,RST,ACK SYN -j ACCEPT
-A okay -p tcp -m state --state RELATED,ESTABLISHED -j ACCEPT
# Читайте доки по сетевым протоколам :)
-A okay -p tcp -j DROP
# Все остальные пакеты зарезаем
COMMIT
# Completed on Mon Apr 5 11:55:09 2004



Продолжим с набором нашего софта, а конкретнее - демонов, которые сидят и слушают порты. После окапывания с помощью iptables у нас остались извне открыты две амбразуры: ssh и ftp. Придирчиво выбираем демона, которого мы посадим в данную амбразуру. При этом усиленно гуглим по интернету и читаем всяческие обзоры по этому демону, читаем, какие там есть уязвимости, если есть - сразу качаем патчи. Устанавливаем демона, ставим (если надо, конечно) заплатки. Потом конфигуряем его, правя соответствующий конфиг, при этом учитываем все те правила безопасности что мы вычитали в инете. Дальше
/etc/rc.d/init.d/нашдемон start
или
/usr/local/sbin/./нашдемон
(в зависимости от того, как он был поставлен). И демон теперь усердно трудится в отведенном ему месте. Для фтп для собственных нужд я выбрал proftpd 1.2.9. Все работает, все отлично, но вот горе! Если сделать вот так:
telnet my_ip 21
Получаем в ответ:
Proftpd server v1.2.9 ready


И так при коннекте этот демон отвечает всем, выдавая потенциальным злоумышленникам, кто он и что он. А где гарантия, что завтра не найдут новую уязвимость и не опубликуют ее в инете? А маленький Вася не скачает себе эксплоит и не атакует мою машину? Как же с этим бороться? Берем машину, где стоит старенький и дырявый фтп-сервер на винде и делаем так:
telnet win_tachka_ip 21
Получаем:
Serv-U FTP Server v2.7 for WinSock ready...


Заходим в /etc/proftpd.conf, и там пишем строку:
ServerIdent "on" "Serv-U FTP Server v2.7 for WinSock ready..."


Перезапускаем наш демон, топчем в командной строке:
telnet my_ip 21
Получаем:
Serv-U FTP Server v2.7 for WinSock ready...


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


Вуаля!! Теперь маленький Вася (или большой Петя) просканирует нас и будет до посинения пробовать на нас эксплоиты для дырявого виндового СервУ :) И что самое главное, совершенно безрезультатно. А мы в это время будем спокойно сидеть, пить пиво или гулять с девушкой.


Если возникнут вопросы, пишите на _cherep_@list.ru

Автор: Cherep , @