- PVSM.RU - https://www.pvsm.ru -
Про организацию прозрачного кэширования веб-трафика с использованием протокола WCCP написано много, в том числе есть хорошая статья на хабре [1]. Обычно в этих статьях рассматривается схема, подобная изображенной на рисунке слева.

На первый взгляд, решение обладает сплошными достоинствами: реализация несложна, кэширование выполняется абсолютно прозрачно для пользователей, при отказе прокси-сервера запросы автоматически будут перенаправлены напрямую.
Но всегда ли внедрение WCCP проходит гладко? И если нет, как бороться с возникающими проблемами?
Например, практически во всех статьях упоминается, что сервер кэширования должен находиться в том же сегменте, что и пользователи, но причины этого не уточняются. А как быть, если политика безопасности требует, чтобы все серверы находились в демилитаризованной зоне и были защищены межсетевым экраном (МЭ)?
Недавно пришлось столкнуться с подобным требованием при установке сервера кэширования в сети оператора связи, упрощенная схема которой изображена на заглавном рисунке справа.
Если читателям интересно, какие проблемы встречаются при реализации подобных схем, и как можно обойти ограничения — добро пожаловать.
Для начала немного теории. Протокол WCCP [2] предназначен для перенаправления трафика (не только веб) в реальном времени. Изначально протокол был разработан компанией Cisco, потом стал открытым стандартом, использующимся большинством вендоров.
На сегодняшний день актуальной является версия 2, находящаяся в статусе Internet-Draft и описываемая документом draft-mclaggan-wccp-v2rev1-00 [3].
Остановимся на нескольких важных моментах работы этого протокола (см. рисунок).

Все сообщения WCCP представляют собой пакеты UDP с номером порта назначения 2048. Порядок обмена сообщениями следующий:
Система готова к работе. Процесс обмена сообщениями WCCP2_HERE_I_AM и WCCP2_I_SEE_YOU повторяется периодически (по умолчанию — раз в 10 секунд), и если маршрутизатор не получает ответа от сервера кэширования, последний исключается из процесса.
В реальности протокол несколько сложнее, он предусматривает аутентификацию, разные алгоритмы перенаправления и т. п., но мы сознательно опустим подробности, неважные для дальнейшего понимания. Интересующиеся читатели могут найти их в соответствующем драфте, ссылка на который приведена выше.
Такая реализация способствует отказоустойчивости решения — если сервер кэширования откажет и перестанет отправлять сообщения WCCP2_HERE_I_AM, маршрутизатор перестанет пытаться перенаправлять пакеты и начнет отправлять их в Интернет напрямую. После восстановления сервиса процесс обмена сообщениями WCCP2_HERE_I_AM/WCCP2_I_SEE_YOU повторится, и схема кэширования снова начнет работать.
Для пользователей такой отказ либо совсем незаметен, либо это может выглядеть как однократное сообщение «Unable to connect», которое пропадет после повторной загрузки страницы в браузере.
В Wireshark процесс обмена сообщениями WCCP выглядит так, как изображено на следующем рисунке. Обратите внимание на столбец Time. Образ трафика взят с реально существующей системы, поэтому IP-адреса приведены в усеченном виде в целях безопасности.

Посмотрим, что происходит при попытке клиента получить данные от веб-сервера. Для наглядности присвоим хостам конкретные IP-адреса, воспользовавшись специальными диапазонами, выделенными для использования в примерах [4], а для простоты пока исключим из рассмотрения всю лишнюю функциональность (NAT, межсетевое экранирование и т. п.).

Описанный алгоритм схематически изображен на рисунке.

Обратите внимание на несколько важных моментов:
Такая реализация протокола значительно снижает загрузку маршрутизатора, т. к. ему приходится перенаправлять только трафик от веб-клиента к веб-серверу, объем которого обычно небольшой. Трафик от веб-сервера, объем которого обычно значительный, не подвергается никакой сложной обработке — он просто маршрутизируется.
Но такая реализация создает ассиметричный трафик, который, в свою очередь, порождает сложности, рассмотренные в следующем разделе.
Модифицируем предыдущую схему — поместим сервер кэширования за межсетевой экран:

Будем считать, что мы используем популярное оборудование — маршрутизатор Cisco с ПО Cisco IOS версии 12.3 и выше, межсетевой экран Cisco ASA с ПО версии 8.2 и выше, сервер кэширования на основе Linux (дистрибутив RHEL или CentOS), ПО кэширования Squid.
Как в этом случае все настроить? Предположим, что базовая функциональность уже настроена, т. е. веб-клиент и сервер кэширования в состоянии обращаться к ресурсам в Интернете. Начнем с настройки WCCP на Cisco.
Проведем подготовительную работу, для чего создадим два списка доступа:
ip access-list standard l_wccp_service
permit 203.0.113.100
ip access-list extended l_wccp_redirect
permit tcp host 198.51.100.150 any eq www
Первый определяет, от каких кэширующих серверов разрешено принимать сообщения WCCP2_HERE_I_AM.
Второй определяет, какой трафик необходимо заворачивать на сервер кэширования.
Настроим WCCP и включим его на интерфейсе, смотрящем в сторону внутренних пользователей, т. е. имеющем адрес 198.51.100.1. Для определенности пусть это будет FastEthernet0/0):
ip wccp web-cache redirect-list l_wccp_redirect group-list l_wccp_service
interface FastEthernet0/0
ip wccp web-cache redirect in
На межсетевом экране разрешим обмен пакетами WCCP и GRE между маршрутизатором и сервером кэширования.
access-list l_wccp extended permit gre host 198.51.100.1 host 203.0.113.100
access-list l_wccp extended permit udp host 198.51.100.1 host 203.0.113.100
access-group l_wccp in interface outside
Теперь настроим сервер кэширования. Для начала установим и настроим squid, для чего с помощью любимого текстового редактора откроем файл /etc/squid/squid.conf и убедимся, что он содержит следующие строки:
# /etc/squid/squid.conf
http_port 3128 transparent
wccp2_router 198.51.100.1
wccp2_forwarding_method 1
wccp2_return_method 1
wccp2_assignment_method hash
wccp2_service standard 0
Cоздадим туннельный интерфейс, для чего опять же в любимом редакторе создадим файл /etc/sysconfig/network-scripts/ifcfg-tun0 со следующим содержимым:
# /etc/sysconfig/network-scripts/ifcfg-tun0
DEVICE=tun0
BOOTPROTO=none
ONBOOT=yes
TYPE=GRE
PEER_OUTER_IPADDR=198.51.100.1
PEER_INNER_IPADDR=192.168.168.1
MY_INNER_IPADDR=192.168.168.2
IP-адреса PEER_INNER_IPADDR и MY_INNER_IPADDR могут быть абсолютно любыми — через этот туннель нормальным способом ничего маршрутизироваться не будет. Вместо этого весь приходящий в него TCP-трафик с DST port 80 будет заворачиваться на squid с использованием iptables. В предположении, что squid отвечает на порту 3128, поднимем туннельный интерфейс и завернем нужный трафик на squid:
/etc/sysconfig/network-scripts/ifup tun0
iptables -t nat -A PREROUTING -i tun0 -p tcp -m tcp --dport 80 -j DNAT --to-destination 203.0.113.100:3128
/etc/init.d/iptables save
Проверим, что сервер кэширования зарегистрировался на маршрутизаторе:
cisco# show ip wccp
Global WCCP information:
Router information:
Router Identifier: 198.51.100.1
Protocol Version: 2.0
Service Identifier: web-cache
Number of Service Group Clients: 1
Number of Service Group Routers: 1
Total Packets s/w Redirected: 175623
Process: 0
Fast: 0
CEF: 175623
Redirect access-list: l_wccp_redirect
Total Packets Denied Redirect: 113892411
Total Packets Unassigned: 20590
Group access-list: l_wccp_service
Total Messages Denied to Group: 26558
Total Authentication failures: 0
Total Bypassed Packets Received: 0
Здесь нас может ожидать неприятная засада: у маршрутизатора обычно бывает несколько интерфейсов с разными IP-адресами. И ничто не мешает ему отправлять пакеты WCCP2_I_SEE_YOU с SRC IP одного интерфейса, а пакеты GRE — с SRC IP другого интерфейса.
В некоторых, но далеко не во всех версиях встроенного программного обеспечения маршрутизаторов Cisco IOS предусмотрена команда “ ip wccp source-interface”, которая позволяет жестко задать интерфейс, IP-адрес которого будет использоваться в качестве SRC IP для всех пакетов, имеющих отношение к подсистеме WCCP.
Если ваш маршрутизатор поддерживает такую команду, вам повезло. Выполните ее:
ip wccp source-interface FastEthernet 0/0
Если же в ответ на такую команду маршрутизатор выдаст что-то вроде “Syntax error”, поступаем следующим образом — запускаем на МЭ диагностику, а на сервере кэширования какой-нибудь сетевой анализатор (хотя бы tcpdump) и выясняем, с каких IP-адресов приходят пакеты WCCP, и с каких — пакеты GRE.
Далее в настройках squid прописываем первый IP-адрес, в настройках туннельного интерфейса и iptables — второй. Модифицируем соответствующим образом списки доступа на МЭ.
Чтобы IP-адрес, с которого приходят пакеты WCCP, не ездил между интерфейсами при последующих перенастройках маршрутизатора, можно завести на последнем loopback-интерфейс. В этом случае протокол WCCP будет использовать для отправки своих пакетов наибольший IP-адрес среди всех loopback-интерфейсов.
interface lo0
ip address 198.51.100.20 255.255.255.255
Проверим, что перенаправление работает. Для начала убедимся, что счетчики пакетов в списках доступа, созданных ранее, растут:
cisco# show access-list l_wccp_redirect
Extended IP access list l_wccp_redirect
10 permit tcp host 198.51.100.150 any eq www (2399 matches)
Потом откроем произвольную веб-страницу в браузере клиентской машины. И наверняка ничего у нас не получится. При попытках разобраться мы наверняка найдем сообщения в логах межсетевого экрана примерно такого вида:
%ASA-4-313004: Denied ICMP type=0, from 192.0.2.20 on interface dmz to 198.51.100.150: no matching session
Если мы попробуем погуглить, первая же ссылка скажет нам что-нибудь про ассиметричный роутинг. Разберемся, что это означает.
Межсетевой экран Cisco ASA представляет собой устройство, работающее в режиме Stateful Inspection [5], т. е. для того чтобы пропустить через себя пакет с флагами TCP SYN/ACK от сервера кэширования к клиенту, необходимо, чтобы до этого соответствующий пакет с флагом TCP SYN от клиента к веб-сайту прошел в прямом направлении через тот же самый МЭ.
В этом случае МЭ поймет, что клиент инициировал TCP-сессию, создаст соответствующие внутренние структуры и начнет правильно отслеживать состояние этой TCP-сессии.
В нашей схеме инициирующий SYN-пакет проходит через МЭ а) внутри GRE-туннеля и б) «как бы не в том направлении».
Соответственно, МЭ не заводит TCP-сессию в своей таблице соединений и не может понять, что сессия началась, и ее пакеты надо пропускать.
Что в такой ситуации делать? Если подключить сервер кэширования в обход МЭ никак невозможно, остается только отключить для пакетов, приходящих со стороны DMZ, проверку на наличие открытой TCP-сессии.
В Cisco ASA функция отключения проверки называется TCP bypass [6]. Функция имеет ограничения:
Итак, включаем функцию TCP bypass:
access-list l_bypass extended permit tcp any eq www host 198.51.100.150
class-map c_bypass
match access-list l_bypass
policy-map p_bypass
class c_bypass
set connection advanced-options tcp-state-bypass
service-policy p_bypass interface dmz
В список доступа l_bypass надо поместить диапазон клиентских IP-адресов.
Вот теперь все должно работать. По крайней мере, у нас заработало.
Статья написана на основе опыта внедрения функции кэширования веб-трафика в сети небольшого оператора связи, и в очередной раз иллюстрирует два старых принципа в работе инженера-сетевика:
Удачного тестирования и внедрения! И пусть отныне и всегда ваши каналы транспортируют как можно меньше лишнего трафика.
Автор: mklochkov
Источник [7]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/cisco/43553
Ссылки в тексте:
[1] хабре: http://habrahabr.ru/post/150221/
[2] WCCP: http://en.wikipedia.org/wiki/Web_Cache_Communication_Protocol
[3] draft-mclaggan-wccp-v2rev1-00: http://tools.ietf.org/html/draft-mclaggan-wccp-v2rev1-00
[4] выделенными для использования в примерах: http://tools.ietf.org/html/rfc5737
[5] Stateful Inspection: http://en.wikipedia.org/wiki/Stateful_firewall
[6] TCP bypass: http://www.cisco.com/en/US/products/ps6120/products_configuration_example09186a0080b2d922.shtml
[7] Источник: http://habrahabr.ru/post/194054/
Нажмите здесь для печати.