Стив Гибсон борется в одиночку

6 март, 2002 - 00:00Виктор Вейтман
Имя президента Gibson Research Стива Гибсона уже известно нашим читателям. В мае 2001 г. сеть компании подверглась DDoS-атаке, анализируя особенности которой, Гибсон пришел к выводу, что средства raw sockets системы Windows XP существенно расширят возможности хакеров, позволяя им легко подменять адрес в исходящих пакетах ("Компьютерное Обозрение", # 29, 2001 и # 33, 2001).
Поскольку руководство Microsoft отказалось принять предложения по ограничению доступа к raw sockets, Гибсон стал самостоятельно разрабатывать средства противодействия атакам злоумышленников и получил первые положительные результаты.

Недавно Стив Гибсон объявил о найденном им способе, позволяющем бороться с SYN-наводнением -- одним из самых эффективных типов атак, предпринимаемых с целью вывода из строя сетевых служб.


SYN-наводнение: что это такое?

Стив Гибсон борется в одиночку
Чтобы разобраться в том, что же такое SYN-наводнение, и по достоинству оценить решение Гибсона, обратимся к RFC-793. В этом "классическом" документе, детально описывающем все особенности TCP-обмена, определены одиннадцать состояний, в которых могут находиться узлы, взаимодействующие по TCP-протоколу. Для понимания сути SYN-наводнения можно ограничиться тремя из них: LISTEN, SYN-RECEIVED и ESTABLISHED. Типичная процедура организации соединения состоит из трех этапов (см. рисунок).
  • Первоначально сервер находится в режиме LISTEN, т. е. готов принимать обращения клиентов. В этот момент клиент посылает пакет с установленным флагом SYN, который содержит в поле SEQ начальный номер последовательности, указанный клиентом (ISN_C): <SEQ=ISN_C><CTRL=SYN>.
  • В ответ сервер передает клиенту пакет с установленными флагами SYN и ACK. В поле SEQ этого пакета сервер помещает свой начальный номер последовательности ISN_S, а в поле ACKN (согласно RFC-793 -- ACK, здесь же название изменено для того, чтобы отличать его от флага ACK) -- значение, на единицу большее, чем номер последовательности, полученный от клиента: <SEQ=ISN_S><ACKN= ISN_C+1> <CTRL=SYN, ACK>.

    Передав пакет, сервер переходит в режим SYN-RECEIVED. Именно это состояние и является "лакомым куском" для организаторов атаки, поскольку сервер находится в нем до получения от клиента очередного пакета или до истечения времени тайм-аута.
  • От клиента приходит пакет с установленным флагом ACK и с заполненными полями SEQ и ACKN: <SEQ=ISN_С+1><ACKN= ISN_S+1> <CTRL=ACK>.

    После получения этого пакета сервер переходит в состояние ESTABLISHED, и соединение считается установленным.

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

SYN-наводнение начинается с того, что атакующий клиент передает серверу, выбранному в качестве жертвы, SYN-пакет. Сервер, как и следует из описания в RFC-793, отвечает передачей пакета SYN/ACK, записывает данные в очередь, переходит в состояние SYN_RECEIVED, называемое "полуоткрытым" соединением, и ожидает получения ACK-пакета. На этом нормальный ход процедуры установления соединения прекращается, и сервер остается в состоянии SYN_RECEIVED. "Страдает" ли от этого сервер? Конечно же, да. Во-первых, сведения о "полуоткрытом" соединении хранятся в буфере, имеющем ограниченные размеры, а во-вторых, при переходе в состояние SYN_RECEIVED в память записывается управляющий блок. Одним словом, для поддержания "полуоткрытого" соединения выделяются ресурсы, а их объем в системе отнюдь не бесконечен. Более того, в некоторых операционных системах, например в ранних версиях SunOS, размер буфера для хранения сведений о "полуоткрытых" соединениях был смехотворно мал (это неудивительно, ведь когда разрабатывались такие системы, о SYN-наводнении еще ничего не было известно). Впоследствии выделенные ресурсы освобождаются по тайм-ауту, но за это время атакующий клиент успевает прислать новые SYN-пакеты. Передавая SYN-пакеты быстрее, чем закрываются "полуоткрытые" соединения, атакующий компьютер может исчерпать ресурсы сервера, в результате чего последний потеряет способность устанавливать TCP-соединения с реальными клиентами.

Интересно, что внешне SYN-наводнение никак не проявляется, и системный администратор поначалу его и не заметит. Ведь исходящие соединения исправно устанавливаются, а пользователи локальной сети по-прежнему имеют возможность посылать и получать данные из Internet. Факт длительного отсутствия свежей почты также не сразу бросается в глаза. Через какое-то время кто-то все же обратит внимание на недоступность "родного" сервера, в то время как обмен данными со всей Глобальной Сетью происходит без проблем. Тут-то и выяснится, что сервер атакован и надо срочно предпринимать необходимые меры защиты.

Конечно же, злоумышленник совсем не заинтересован в том, чтобы системный администратор выявил источник атаки, поэтому в передаваемых SYN-пакетах он подменяет исходный IP-адрес (это как раз и обеспечивается реализацией raw sockets).

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


Доверяй, но проверяй

Занимаясь поисками средств, способных противодействовать атаке, Гибсон заметил, что все сведения, необходимые для установления TCP-соединения, находятся в составе ACK-пакета, передаваемого клиентом. Действительно, в нем содержатся исходный порт и порт назначения, а также начальные номера последовательности для клиента и для сервера (ISN_C и ISN_S). Следовательно, сервер может не выделять ресурсы и не помещать информацию о запросе в очередь. Единственное, что ему надо сделать при получении SYN-пакета -- отправить пакет SYN/ACK и "забыть" о том, что кто-то попытался установить соединение.

Однако такой подход еще не решает проблемы, ведь вместо SYN-наводнения злоумышленнику ничего не стоит организовать ACK-наводнение и заставить сервер выделять ресурсы на поддержание уже не "полуоткрытых", а открытых соединений. Поэтому Гибсон пошел дальше и разработал изящный способ идентификации клиента, который он назвал методом зашифрованного маркера (encrypted token).

Как было сказано выше, в составе пакета SYN/ACK передается начальный номер последовательности (ISN_S). Поскольку этот номер устанавливается сервером, то в нем, по предложению Гибсона, должен быть зашифрован IP-адрес клиента. Если процедура соединения проходит корректно, то, получив пакет SYN/ACK, клиент передает ACK-пакет, записав в поле ACKN значение ISN_S+1. Расшифровав начальный номер последовательности, сервер сравнивает его с адресом, указанным в IP-заголовке, и, если адреса совпадают, устанавливает соединение. Если же адрес, зашифрованный в ISN_S, отличается от IP-адреса, значит, имеет место фальсификация и, следовательно, предпринимается попытка атаки.

Разрабатывая методику защиты, Гибсон уделил большое внимание шифрованию IP-адреса клиента и использовал для этого систему кодирования RC5. Имеет ли значение выбор того или иного алгоритма? Вряд ли. По-видимому, простейший код даст не менее надежные результаты, чем "сверхмощный" шифр, ведь злоумышленнику неоткуда взять информацию для декодирования. Зашифрованные данные придут не ему, а клиенту, расположенному по фальшивому адресу, указанному в пакете. Даже если хакер предпримет специальные меры для сбора информации, затратит время и ресурсы для подбора ключа, он сможет воспользоваться полученными результатами лишь до первой перезагрузки сервера. При перезагрузке будет выбран новый ключ, который придется взламывать заново.


ISN_S -- не роскошь...

Описание решения, предложенного Гибсоном, будет неполным, если не упомянуть об одной детали. Дело в том, что непосредственная замена ISN_S зашифрованным IP-адресом противоречит одному из требований RFC-793. Начальный номер последовательности не случайно включается в состав пакетов SYN и ACK. Он необходим для того, чтобы "заблудившийся" пакет не нарушил нормального обмена данными.

При работе в Internet нередки случаи, когда клиент разрывает соединение с сервером, а затем снова устанавливает его. В рамках нового соединения начинается обмен данными, который может быть нарушен пакетом, отправленным в течение предыдущего соединения, но "заблудившимся" в сети. Как выявить такой пакет? Ведь IP-адреса компьютеров постоянны, а номера портов также могут остаться неизменными.

Для защиты от "заблудившихся" пакетов используются возрастающие начальные номера последовательности. ISN_S и ISN_C должны выбираться так, чтобы содержимое полей SEQ и ACKN гарантированно отличалось бы от соответствующих значений для пакетов, которыми компьютеры обмениваются в рамках текущего соединения. Для этого в каждой системе, предназначенной для поддержки TCP, содержится генератор начального номера последовательности, каждые 4 микросекунды увеличивающий начальный номер на единицу.

С проблемой выбора ISN_S удалось справиться очень просто. Получив SYN-пакет, система Гибсона кодирует IP-адрес клиента и складывает его с начальным номером последовательности, переданным клиентом. Полученное значение используется в качестве ISN_S. Приняв ACK-пакет, система вычитает ISN_C из ISN_S, в результате чего получает данные для расшифровки IP-адреса.

Следует признать, что, для того чтобы реализовать такую схему, придется затратить определенные усилия, в частности необходимо существенно модифицировать средства поддержки TCP. Однако изменения, предложенные Гибсоном, не затрагивают клиентов, а вносятся только в состав серверных программ, поэтому провести требуемую модернизацию вполне реально.


Новое -- хорошо забытое старое?

Оценив по достоинству решение Гибсона, обратимся к документу TCP SYN Flooding and IP Spoofing Attacks. Среди рекомендаций, призванных снизить негативные воздействия SYN-наводнения, пользователям Linux предлагается некое дополнение к системе. В описании читаем следующее: "...поддержка TCP/IP-взаимодействия осуществляется обычным образом до тех пор, пока очередь ["полуоткрытых" соединений] не будет близка к заполнению. После этого вместо отправки пакетов SYN/ACK сервер посылает SYN-cookie и ожидает ответа на него. При этом сервер удаляет запись о принятом SYN-пакете из очереди...".

Указанный здесь механизм был разработан Дэном Бернстейном (Dan Bernstein) и Эриком Шенком (Eric Schenk). На Web-странице cr.yp.to/syncookies.html один из авторов данного подхода кратко описал принцип действия SYN-cookie. От обычного SYN/ACK-пакета SYN-cookie отличается принципом формирования ISN_S.

  • 5 старших бит ISN_S представляют циклический таймер, значение которого увеличивается каждые 64 секунды.
  • Следующие 3 бита содержат максимальный размер сегмента (MSS), представленный в закодированном виде.
  • И наконец, младшие 24 бита являются значением специальной функции от адреса клиента, номера порта клиента, адреса сервера, номера порта сервера и текущего содержимого таймера.
Как видите, SYN-сооkie действуют примерно по тому же принципу, который предложил Гибсон, отличие состоит лишь в алгоритме вычисления ISN_S. То, что сходные мысли приходят в голову разным людям, -- явление нередкое, а поскольку решения все же отличаются в деталях, имеет смысл проанализировать их оба.


Защита в ущерб надежности

Какими бы изящными ни казались методика Гибсона и SYN-cookie Бернстейна и Шенка, противодействуя SYN-наводнению, они снижают надежность TCP-соединений. Дело в том, что при любом из этих подходов трехэтапная процедура установления TCP-соединения, по сути, превращается в одноэтапную. Если сервер не хранит в очереди запись о "полуоткрытом" соединении, он не имеет сведений о начальных значениях ISN_S и ISN_C и должен полагаться на ISN_S+1 и ISN_C+1, полученные в составе ACK-пакета. Если же окажется, что одна из этих величин принята некорректно, сбой гарантирован. Конечно, вероятность такого события чрезвычайно мала, но и количество соединений, поддерживаемых сервером, довольно велико, а когда вступает в действие закон больших чисел, любая, самая незначительная вероятность рано или поздно будет реализована.

Другая опасность, подстерегающая разработчиков, вычисляющих ISN_S по собственному алгоритму, связана с "заблудившимися" TCP-пакетами. Как было сказано выше, Гибсон блестяще справился с этой проблемой, в то время как Бернстейн и Шенк, создавая SYN-cookie, похоже, немного "перемудрили". Значение младших 24 бит ISN_S в SYN-cookie зависит не только от адреса удаленного компьютера, но и от номера порта, который может изменяться в довольно широких пределах. При этом затруднительно обеспечить непрерывное возрастание ISN_S с течением времени. Однако, выбрав алгоритм, гарантирующий постоянное увеличение значения, легко впасть в другую крайность. Если функция будет возрастать слишком быстро, она может исчерпать четыре миллиарда (232) допустимых значений за время, меньшее, чем время жизни пакета (MSL). При этом проблема "заблудившихся" пакетов снова напомнит о себе.

Таким образом, следует признать, Гибсон смог найти лучшее решение, чем Бернстейн и Шенк. Его принцип защиты от SYN-наводнения оказывает минимальное воздействие на надежность системы в целом.


Практика -- критерий истины

Приблизительно полгода назад сотрудник консалтинговой компании Tech Mavens Росс Оливер (Ross Oliver) провел тестирование четырех продуктов, предназначенных для противодействия SYN-атаке. Для имитации SYN-наводнения использовался специальный программный генератор. Брандмауэр Cisco PIX перестал справляться с SYN-наводнением при интенсивности атаки, равной 100 пакетам в секунду, а Firewall-1 -- при интенсивности 500 пакетов. Netscreen-100 смог выдержать 14000 SYN-пакетов в секунду, а возможности AppSafe превысили 22000 пакетов.

С какими же из этих продуктов сможет конкурировать технология, предложенная Гибсоном? Пока что сообщений о подобном тестировании нет. Теоретически возможности такой системы должны ограничиваться лишь пропускной способностью линий связи и быстродействием вычислительных средств. Применительно к конкретным условиям корпорации Gibson Research, сеть которой подключена к Internet через две линии T1, на сервер может поступать не более 10000 (скорее всего -- существенно меньше) SYN-пакетов в секунду, после чего SYN-наводнение уже не будет отличаться от обычного наводнения ICMP-пакетами.


Решена ли проблема?

Итак, Гибсону удалось справиться с SYN-наводнением и предоставить возможность всем желающим защитить свои серверы. Что же, DDoS-атаки побеждены? Увы, сделан только первый незначительный шаг в этом направлении. Ведь, по правде говоря, SYN-наводнение не является DDoS-атакой в чистом виде; это, скорее, DoS-атака. Для того чтобы обеспечить плотность SYN-пакетов, необходимую для вывода из строя "среднего" сервера, не оснащенного специальными средствами защиты, вполне достаточно одного компьютера, подключенного к Internet. "Настоящие" DDoS-атаки, в которых принимают участие программы-"зомби" на чужих компьютерах, по-прежнему остаются грозой системных администраторов. Поэтому успокаиваться еще очень рано.