Практическое применение Cisco FPM или как заблокировать TeamViewer и прочее зло из песочницы

Немного теории

Теории на эту тему хватает, но все же еще раз, ну на всякий случай. Для тех кому лень читать, и нужно тупо заблокировать TeamViewer – готовый конфиг в конце статьи.

FPM (Flexible Packet Matching) — реализованная в IOS технология, позволяющая идентифицировать трафик по содержанию полей в заголовках и payload пакетов. По сути своей – аналогична ACL, но не имеет ограничений по тому, какую часть пакета можно матчить. В случае с ACL — это три поля в заголовке IP: Source IP Address, Destination IP address, Protocol + 2 поля в заголовке TCP/UDP: Source Port, Destination Port (ну или type/code для ICMP). В случае с FPM матчить можно по любому биту пакета.

Нужно обратить внимание, что FPM ну совсем никак не statefull, не анализирует всю сессию, не анализирует фрагменты, не анализирует пакеты с IP Options. Излишние детали по ограничениям опущу, они все описаны на cisco.com.

FPM для анализа нужен один пакет со всеми заголовками, поскольку, опираясь на эти заголовки и смещения относительно них, и строятся правила. ИМХО – аналогично Atomic IP engine в Cisco IPS, но с большими возможностями.

Что нужно сделать, чтобы это использовать

1. Инициализировать PDHF для интересующих протоколов (лучше для всех).

Поскольку не все — дикие эксперты (хотя и не без оных) в знании всех полей заголовков L3/L4 протоколов, их смещений относительно друг друга, неплохо было бы иметь возможность при написании правил использовать имена полей заголовков, так как они определены в стандартах, а не тупо смещение относительно начала заголовка. И такая возможность есть. Для этого используются т.н. PHDF (Protocol Header Description File) файлы. Например, так выглядит PDHF для заголовка IP:

R1#sh protocols phdf IP

< Protocol ID: 1

Constant length. Length: 4

Field id: 2, tos, IP-Type-of-Service

Fixed offset. offset 8

Constant length. Length: 8

Field id: 3, length, IP-Total-Length

Fixed offset. offset 16

Constant length. Length: 16

Field id: 4, identification, IP-Identification

Fixed offset. offset 32

Constant length. Length: 16

Field id: 5, flags, IP-Fragmentation-Flags

Fixed offset. offset 48

Constant length. Length: 3

Field id: 6, fragment-offset, IP-Fragmentation-Offset

Fixed offset. offset 51

Constant length. Length: 13

Field id: 7, ttl, Definition-for-the-IP-TTL

Fixed offset. offset 64

Constant length. Length: 8

Field id: 8, protocol, IP-Protocol

Fixed offset. offset 72

Constant length. Length: 8

Field id: 9, checksum, IP-Header-Checksum

Fixed offset. offset 80

Constant length. Length: 16

Field id: 10, source-addr, IP-Source-Address

Fixed offset. offset 96

Constant length. Length: 32

Field id: 11, dest-addr, IP-Destination-Address

Fixed offset. offset 128

Constant length. Length: 32

Field id: 12, payload-start, IP-Payload-Start

Fixed offset. offset 160

Constant length. Length: 0

Т.е. мы четко видим, из каких 12-ти полей состоит заголовок IP (имя, длина, офсет) и можем использовать эту информацию при написании правил.

PHDF файлы, как правило, уже есть на флеше роутера, и чтобы их загрузить в пямять/инициализировать (без этого их нельзя будет использовать), нужно выполнить команду:

R1(config)#load protocol system:fpm/phdf/[ip.phdf|tcp.phdf|udp.phdf|icmp.phdf|ether.phdf]

2. Определить стек протоколов, подлежащий анализу.

Это, по сути своей, фильтр в крупную клетку. Здесь мы должны определить, что нам для дальнейшего, более детального анализа будет, например, интересен стек, в котором в качестве L3 протокола задействован IP, а в качестве L4 протокола –TCP. Пакеты же, в которых протокол транспортного уровня – UDP или ICMP анализироваться не будут. Следствие – меньший ущерб производительности.

Для написания правил используется стандартный MQC CLI (class-map, policy-map, service-policy). При определении стека, class-map должен быть типа stack. По дефолту стек начинается с заголовка L3 (как правило – IP). Выглядит так:

R1(config) class-map type stack match-all IP_TCP_STACK

R1(config-cmap) match field IP protocol eq 6 next TCP

Строка с match читается: «нам будут интересны пакеты, в IP заголовке которых поле protocol (слово protocol взято из PHDF, загруженного ранее) эквивалентно 6. Следующий протокол в стеке — TCP». Шесть – номер протокола TCP (номера можно посмотреть здесь www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml ).

Если бы мы хотели матчить пакеты с какой-нибудь хитрой инкапсуляцией, например UDP over IP over IP, стек выглядел бы так:

3. Определить непосредственно правило фильтрации трафика.

Тут мы говорим, что для пакетов, структура заголовков которых соответствует ранее определенному стеку протоколов, мы будем искать что-то конкретное. Например, будем искать строку «danger» в первых 20 байтах payload TCP. Если находим – дропаем такой пакет. Используется тот же MQC CLI, но class-map и policy-map уже будут типа access-control. Выглядит так:

4. Связать воедино ранее созданный стек и правило фильтрации.

Для этого потребуется еще одна policy-map типа access-control. В итоге получим такую конструкцию:

Читается так:

class:«Будем наблюдать за пакетами со стеком IP->TCP».

service-policy:«как только видим такой пакет, изучаем содержание 20-ти байт, начиная с начала payload TCP (с того места, где заголовок TCP заканчивается и начинаются данные). Как только в этих 20-байтах видим строку danger – дропаем такой пакет».

5. Повесить политику на интерфейс.

Например, вешаем политику на внешний интерфейс в исходящем направлении:

На этом по теории все. Че-то длинновато вышло…

Более подробно и детально есть вот в этой замечательной статье (хотя и не все уже актуально): blog.ine.com/2009/06/14/understanding-flexible-packet-matching/

Теперь по делу

С помощью FPM

можно заблокировать все что угодно (skype, teamviewer, ammyy admin, etc). Достаточно просто выделить специфичную для конкретного приложения последовательность байт и отбрасывать пакеты, такую последовательность содержащие. Нжуно не дать клиенту приложения подключиться к серверу, какие бы хитроумные приемы тот не предпринимал.

Пример с TeamViewer (TV).

Ну вот возникла у меня задача остановить хождение этого зла в нашу сеть. Пользователи в организации достаточно хитросделанные умные и думают так: «А нафига я буду получать доступ к VPN, писать служебную записку, читать регламент, если есть TV и он меня радует, аж так, что прям не могу?». Поэтому, приходится насильно с этим бороться.

Можно пытаться блокировать TV через закрытие доступа к определенным серверам (по DNS, IP), но, на практике, этот зверь без труда пробирается через подобные механизмы.

Тут то и приходит на помощь FPM.

Первым делом нужно увидеть, что делает TV, как выглядит сессия подключения клиента к серверу. Для этого, проще всего взять всем известный Wireshark, установить его на хост, на котором установлен TV и посмотреть, что будет происходить при старте TV. В идеале нужно чтобы другой трафик не забивал интерфейс и не мешал анализировать нужный трафик. Т.е. такой хост нужно как-то изолировать от LAN, но обеспечить ему интернет-доступ (можно использовать GNS3, или подключить хост к интернету через 3G/4G модем).

Итак, wireshark слушает интерфейс. Запускаем TV. Видим следующее:

После установление TCP-сессии с неким сервером (первые 3 пакета – TCP-3WAY-Handshake), в четвертом пакете TV в поле данных передает некую последовательность байт, выглядящую так: 0x17241004. Для чего TV передает эту последовательность? Понятия не имею, но, вероятно, блокирование ее передачи может помешать установлению соединения клиента с сервером. И тут следует оговориться и заметить, что прежде чем блокировать нечто подобное, нужно как следует убедиться, что это что-то действительно является признаком блокируемого приложения, дабы не навредить легитимному трафику. Для этого можно проанализировать работу нескольких версий блокируемого приложения и удостовериться, что искомая последовательность есть во всех версиях, можно посмотреть остальной трафик и убедиться, что там искомой последовательности нет и т.д. Кроме того, для избежания т.н. false-positives, нужно выбрать уникальную последовательность максимальной длины (понятно, что, чем длиннее уникальная последовательность, т.е. содержится в большем количестве байт, тем меньше вероятность ее повторения другим приложением), а также максимально точно указать, в какой части пакета мы предполагаем ее встретить (offset) и какова ее длина.

Итак, есть последовательность байт 0x17241004, которая (как было мной установлено) принадлежит TV. Пробуем ее заблокировать и смотрим, что получится.

TV работает по TCP, поэтому определим соответствующий стек:

Теперь определим class-map, который будет матчить ту самую последовательность:

Определим правило фильтрации для класса MATCH_TCP_PAYLOAD_17241004:

Дальше, создадим политику и повесим ее на один из интерфейсов:

Запустим TV повторно, и посмотрим, что изменилось:

Видим, что передача блокированной FPM последовательности не удалась, TV попытался передать ее еще несколько раз (TCP Retransmission), поморгал, подергался, сказал что не может подключиться, но, после нажатия кнопки «Повтор», он все-таки выбрался наружу.

Передать эту последовательность TV пытался на порт 443. Т.е. видимо, это ему было нужно для успешного установления SSL-сессии.

Посмотрим на счетчики (some unrelated output omitted):

Видном, что правило работает, и даже, что TV теперь не так уверенно подключается, но тем не менее, пока ему это удается.

Снова запускаем TV, Wireshark и анализируем трафик дальше.

А дальше видим следующее:

Поняв, что установитьSSL сессию сервером у него не получится, TV пытается подключиться к нему по http. После успешного подключения он запрашывает URL, содержащую последовательность «DynGate».

Теперь имеет смысл попытаться заблокировать забросы, содержащие подобную последовательность. Технически, более правильно это сделать с помощью CBAC (http deep packet inspection), поскольку тут уже речь идет о чистом http и никакой проблемы чтобы это зарубить с помощью application inspection я не вижу. Но, т.к. в этой статье говорим о FPM, продолжим в том же ключе, в котором начали.

Итак, нужно заблокировать TCP/http пакет, который содержит в поле payload строку DynGate. Если покликать по полям в Vireshark, видно, что GET занимает три байта, далее несколько байт занимают какие-то каракули, потом идет то самое DynGate. Поэтому, будем инспектировать payload начиная, скажем, с 10-го байта и заканчивая 60-м (диапазон выбран примерно, что называется, на глаз). Конечно, можно (и даже нужно) точно выяснить сколько байт занимает DynGate и сколько у него offset (так будет лучше с точки зрения производительности, поскольку роутеру потребуется анализировать меньшую часть пакета), но лень, лень и еще раз лень.

Создадим еще один class map, в котором будем матчить искомую строку. На всякий случай учтем любой вариант регистра символов:

Прицепим вновь созданный class-map к уже имеющейся policy map. В итоге BLOCK_TEAMVIEWER_POLICY будет выглядеть так:

Попробуем еще раз запустить TV.

И все… TV предпринял несколько отчаянных попыток проскочить, но в итоге сдался, лишь иногда подергиваясь, с мыслью: «а вдруг что-то изменилось?».

Смотрим счетчики еще раз (some unrelated output omitted):

Таким образом, так выглядит вся необходимая конфигурация, позволяющая заблокировать TeamViewer (по крайней мере на июль 2013 г):

Вместо заключения

Таким образом, FPM – достаточно мощный инструмент, позволяющий заблокировать все что угодно, до того момента пока это «что-угодно» не установило защищенную сессию. Главное, правильно идентифицировать нужное приложение и не заблокировать что-то лишнее.

Конечно, в идеале, для этого нужно использовать решения, реализующие сигнатурный анализ, которые уже научены идентифицировать подобного рода приложения (например, ASA CX), но как временная мера — FPM — вполне приемлемый вариант.

Следует обратить внимание, что фичей нужно пользоваться с осторожностью и без фанатизма. Не нужно инспектировать всю payload на наличие буквы «x». Лучше узнать, где эта буква «x» может встретиться, и инспектировать именно эту часть пакета, иначе роутер может просто умереть от чрезмерной загрузки, вызванной необходимостью инспектировать весь трафик.

Источник: habrahabr.ru

Категория: Безопасность

Похожие статьи: