Сергей Яремчук
Настраиваем эффективную систему сетевой защиты Zorp
ModSecurity – Open Source firewall седьмого уровня – позволяет защититься от угроз, типичных для веб-сервера. Но в обычной сети можно встретить и другие сервисы, также нуждающиеся в защите.
Фильтры пакетов вроде ipchains во время работы используют самые простые критерии, и для фильтрации основываются на информации, содержащейся в заголовках IPпакетов: IP-адреса источника и назначения, протокол и номера портов источника и назначения, взятые с TCP/UDP-протоколов следующего уровня.
По сегодняшним меркам такой подход может обеспечить только самую минимальную защиту. Система защиты, использующая этот принцип, не владеет более подробной информацией о соединении. И приняв пакет, не может определить – устанавливается новое соединение либо пришедший пакет является частью уже установленного соединения, а может, это вообще случайный или враждебный пакет. Так работал ipchains, используемый совместно с Linux-ядром серии 2.2.
В Netfilter/iptables ядра 2.4/2.6 эта проблема решается за счет контроля состояния (stateful) флагов и порядковых номеров ТСР. Такой фильтр работает аналогично предыдущему и дополнительно просматривает флаги TCP и UDP-пакетов, а поэтому может определить, является ли этот пакет попыткой установления нового соединения. Если да, то в таблице состояний делается новая запись и действие разрешается, если нет, то проверяется принадлежность существующим соединениям и при положительном результате пакет пропускается. Кроме явного отсеивания приходящего мусора, такие фильтры упрощают написание правил фильтрации. Например, если ранее требовалось явно разрешить в правиле оба направления, т.е. от клиента к серверу и от сервера к клиенту, то теперь достаточно просто разрешить соединение с сервером, забота же о доставке информации клиенту полностью ляжет на плечи фильтра пакетов.
Кроме того, при использовании stateful-фильтров можно смело запрещать все соединения на номера портов выше 1024. Но опять же при всех положительных качествах контроль состояний не сможет защитить сервер от атак, направленных на конкретное приложение. Например, никто не помешает злоумышленнику послать запрос большой длины или попробовать реализовать сross-site scripting атаку. Без посредника здесь точно не обойтись.
Подход Zorp
Создатель Syslog-NG венгр Балазс Шайдлер (Balazs Scheidler) разработал еще одно полезное приложение – Zorp. На заглавной странице сайта проекта [2] он дословно именуется как Modular Application Level Gateway (хотя в некоторых документах его название несколько другое – new generation proxy firewall).
Но как бы ни звучало его название, назначение остается неизменным – защита приложений от направленных атак. Принцип действия похож на рассматриваемый ранее ModSecurity [1]. Zorp представляет собой прозрачный (transparent) прокси, который выступает посредником при работе клиента и сервера. В этом случае для клиента, который хочет установить новое соединение, Zorp выступает как сервер, а реальный сервер видит Zorp как клиента. Находясь посередине, такой прокси знает особенности своего протокола и на основании имеющейся информации и настроек может принять решение о необходимости продолжения текущего соединения.
Но в отличие от ModSecurity, который является отдельным приложением и в идеальных условиях требует установки на отдельный компьютер, Zorp фактически представляет собой расширение к Netfilter/iptables. Таким образом, вся обработка происходит на одном-единственном компьютере, который находится на входе сети, что освобождает её от пакетов, которые все равно будут отброшены. Кроме того, функции устройств защиты не будут дублироваться, что повысит надежность за счет суммарного уменьшения их количества, а с другой стороны, приведет к меньшим задержкам, так как весь анализ будет произведен только один раз и в одном месте.
Взаимодействие сервера и клиента в случае использования Zorp показано на рис. 1. Клиент, желая установить соединение, посылает TCP SYN-пакет, который поступает на маршрутизатор с установленным iptables (ipchais), использующим Zorp. Полученный пакет проверяется на соответствие правил iptables. Если он должен быть обработан Zorp, то в записи следует указать цель TPROXY (iptables) или REDIRECT (ipchains). В качестве одного из параметров указывается порт, где Zorp будет ждать подключения. Zorp получает пакет, проверяет его на соответствие со своими правилами и запускает соответствующий прокси, который инициализирует соединение с сервером и дальше действует уже от имени клиента, а в процессе работы проверяет проходящий поток данных. Естественно, и остальные цепочки также должны пропускать обработанные Zorp пакеты.
Рисунок 1. Принцип работы Zorp
Теперь аномалии более низкого уровня будут отсеиваться сразу. Такой принцип работы позволяет делать то, что недоступно многим IDS, а именно проверять защищенные HTTPS, POP3S, IMAPS или SSH-соединения. То есть когда пользователь подключается к веб-серверу, последний отсылает ему сертификат, прокси может перехватить этот сертификат и отправить пользователю свой. Теперь, находясь посередине, можно беспрепятственно контролировать любой трафик. Таким же образом можно автоматически проверять сертификаты и разрешать доступ только к определенным ресурсам.
Недостатков у такого способа, как минимум, два: повышенное требование к производительности системы по сравнению с использованием обычного пакетного фильтра и большая сложность в настройке по сравнению со специализированными прокси вроде ModSecurity или DansGuardian.
Версии Zorp
В настоящее время доступны три версии Zorp: Zorp Pro, Zorp GPL и Zorp Unofficial.
Zorp Unofficial ранее играл роль тестовой бета-версии, но последние два года фактически не развивается, его можно свободно получить на сайте [3].
Самой продвинутой является коммерческий Zorp Pro, представляющий собой доработанный Debian, который можно установить за 10 минут (без настройки). В его составе имеются:
- 16 модулей, контролирующих свои протоколы;
- сервер управления (Zorp Management Server – ZMS), с помощью которого удобно создавать и настраивать правила работы системы фильтрации, клиенты, при помощи которых и производится удаленная настройка, доступны для нескольких систем;
- возможно подключение модуля антивирусной проверки;
- строгая аутентификация по любому протоколу, генерирование ключей на лету на основании информации клиента;
- возможность горячей перезагрузки без разрыва существующих связей;
- техническая поддержка.
GPL-версия, распространяемая свободно, не имеет таких богатых возможностей, в ней есть модули, позволяющие контролировать только 6 типов протоколов (HTTP, FTP, PSSL, TELNET, WHOIS, FINGER) и Plug. Последний работает без проверки протокола и поддерживает протоколы, использующие только один порт (SSH, MySQL, VNC, Microsoft Terminal Service, GOPHER, SMB/CIFS, TALK, SYSLOG, RSYNC). Также в GPL-версии для SSL возможна работа только с заранее сгенерированными ключевыми парами. И готовьтесь к тому, что собирать и настраивать все это придется самостоятельно и вручную. Используя версию Pro, относительно просто организовать однократную аутентификацию (SSO – Single-sign-on authentication), с Zorp GPL сделать это невозможно. Осталось добавить, что использование Netfilter налагает ограничение по операционной системе, здесь только GNU/Linux. Cам прокси в Zorp написан на языке С, а модули контроля – с применением языка высокого уровня Python.
Установка Zorp GPL
Балазс Шайдлер по совместительству является одним из майтайнеров Debian, поэтому самым простым способом установки является использование этого дистрибутива, который затем обновляется его до ZorpOS. Для этого достаточно установить базовые пакеты Debian, затем в файл /etc/apt/sources.list занести (для версии 3.0 woody) следующие строки:
deb http://apt.balabit.hu/zorp-gpl-os/zorp-os-3.0/3.0 security zorp-os common-gpl zorp-gpl
deb http://apt.balabit.hu/zorp-gpl-os/zorp-os-3.0/3.0 zorp-os common-gpl zorp-gpl
И дать команду на обновление и установку:
# apt-get -u upgrade
В случае использования других дистрибутивов придется немного потрудиться, пересобрав все компоненты с исходных текстов, найти готовые прекомпилированные пакеты, отличные от deb, мне не удалось. Так как межсетевой экран должен иметь минимум компонентов и тем более не иметь компилятора, то устанавливаем базовую систему, а собираем все остальное на отдельном компьютере. В первую очередь необходимо пересобрать ядро, оставив только необходимые опции, а также утилиты iptables.
Версии ядра 2.2 уже имеют встроенный прозрачный прокси, и для его активации требуется только включить в меню «Networking options IP: firewalling», и активируем «Transparent proxy support». В следующих версиях 2.4/2.6, когда был введен iptables, такая возможность была убрана, поэтому перед компиляцией необходимо будет наложить патч tproxy [4]. Имя патча имеет вид cttproxy-2.6.15-2.0.4.tar.gz, где 2.6.15 означает версию ядра, для которого он предназначен, а 2.0.4 – версию tproxy. Также следует помнить о двух совместимостях. Версии TProxy 1.2.x совместимы со всеми версиями Zorp, но не подходят к ядрам серии 2.6, а версия TProxy 2.0 будет работать с ядрами 2.4 и 2.6, но совместима только с Zorp, начиная с 2.1.9.
Для примера используем ядро 2.6.15:
# tar xzvf cttproxy-2.6.15-2.0.4.tar.gz
# tar xjvf linux-2.6.15.tar.bz2
# cd linux-2.6.15
Патчи для ядра находятся в каталоге patch_tree, не все являются обязательными, достаточно установить только 03-tproxy.diff.
# for i in ../cttproxy-2.6.15-2.0.4/patch_tree/0{1,2,3}*.diff; do cat $i | patch -p1; done
При конфигурировании в «Networking options IP: Netfilter Configuration ...» включаем «Connection tracking», «IP tables support», «Full NAT» и «Transparent proxying» (см. рис. 2) с дополнительными опциями.
Рисунок 2. Для использования Zorp необходимо пересобрать ядро
В .config-файле это выглядит так:
CONFIG_NETFILTER=m
CONFIG_IP_NF_TPROXY=m
CONFIG_IP_NF_MATCH_TPROXY=m
CONFIG_IP_NF_TARGET_TPROXY=m
CONFIG_IP_NF_IPTABLES=m
CONFIG_IP_NF_NAT=m
Кроме того, для прозрачного прокси необходим виртуальный dummy-интерфейс. Проследите, чтобы во вкладке «Network device support» был активирован пункт «Dummy net driver support». Если в процессе работы Zorp возникнут проблемы, то следует добавить отладочной информации. Заглянув в net/ipv4/netfilter/iptable_tproxy.c, найдете строку:
#ifdef CONFIG_NETFILTER_DEBUG
#define DEBUGP printk
То есть отладочный режим можно активировать глобально, поставив «CONFIG_ NETFILTER_DEBUG=y» либо заменив первую строку на:
#if 1
В последних версиях модуль iptable_tproxy.o загружается автоматически при запуске по мере необходимости, если используете ядро версии 2.4 или более ранние 2.6, то загрузите его вручную при помощи modprobe.
# modprobe iptable_tproxy.o
# lsmod | grep -i tproxy
iptable_tproxy 14340 0
ip_nat 17600 1 iptable_tproxy
ip_conntrack 45516 2 iptable_tproxy,ip_nat
ip_tables 9624 1 iptable_tproxy
|
Если с ядром все в порядке, то следующим шагом модифицируем и пересобираем утилиты iptables, чтобы они могли работать с новой таблицей tproxy и новой целью TPROXY. В подкаталоге iptables лежат два патча. Один – для версии iptables 1.2.7a, второй – для 1.3
# tar xzvf iptables-1.3.3.tar.gz
# cd iptables-1.3.X
# cat ../cttproxy-2.6.15-2.0.4/iptables/iptables-1.3-cttproxy.diff | patch -p1
# chmod +x extensions/.tproxy-test
# make KERNELDIR=/usr/src/linux-2.6.15
Zorp состоит из библиотеки libzorpll и собственно zorp. Последними версиями на момент написания статьи были libzorpll_3.1.2.2 и zorp_3.0.9.tar.gz. Каких-либо особенностей по их установке нет, делаем это обычным образом.
Настраиваем Dummy-интерфейс
Во избежание недоразумений dummy-адрес не должен принадлежать реально существующему сетевому адресу. В Debian добавляем следующие строки в файл /etc/networking/interfaces:
auto dummy0
iface dummy0 inet static
address 10.2.3.4
netmask 255.255.255.255
В RedHat и клонах, а также SuSE это будет файл ifcfg-dummy0, лежащий в /etc/sysconfig/network:
BOOTPROTO='static'
IPADDR='10.2.3.4'
NETMASK='255.255.255.255'
STARTMODE='onboot'
И затем:
# ifup dummy0
В Slackware /etc/rc.d/ создаем файл /etc/rc.d/rc.inet4 такого содержания:
#!/bin/sh
DEVICE='dummy0'
DHCP='no'
IPADDR='10.2.3.4'
NETMASK='255.255.255.255'
PROBE='no'
. /etc/rc.d/functions-network "$@"
И запускаем:
# /etc/rc.d/rc.inet4 start
Starting network dummy0 as 10.2.3.4/255.255.255.255… |
Настраиваем Zorp
Для настройки Zorp используются три файла, которые по умолчанию должны лежать в /etc/zorp/. Файл instances.conf содержит список примеров Zorp, с которыми нужно работать, и запускаемые сценарием zorpctl. Другой файл, zorpctl.conf, содержит глобальные настройки, связанные с работой самого zorpctl (разрешение автоматического рестарта, pid файл, дополнительные аргументы командной строки). И третий файл, policy.py, хранит правила и политики, связанные с примерами.
В файле zorpctl.conf можно пока ничего не трогать, параметры по умолчанию пригодны для работы. Рекомендую снять знак комментария лишь со следующих строк:
CHECK_PERMS="1"
CONFIG_DIR=/etc/zorp
CONFIG_DIR_OWNER=root
CONFIG_DIR_GROUP=zorp
CONFIG_DIR_MODE=0750
Тогда при запуске утилиты zorpctl будут проверяться соответствующие разрешения.
# zorpctl start
Config directory has invalid permissions, expected:
dir="/etc/zorp", owner="root", group="zorp", perm="0750"
|
# groupadd zorp
# chown root:zorp /etc/zorp
# chmod 0750 /etc/zorp/
# zorpctl start
Starting Zorp Firewall Suite |
Для удобства предположим, что на межсетевом экране имеются три сетевых интерфейса:
- eth0 – интранет-интерфейс с IP 192.168.0.1/24 – local;
- eth1 – DMZ с IP 10.0.0.1/24 – dmz;
- eth2 – Интернет с IP 111.222.333.444 – internet.
Дописываем в instances.conf. следующие строки:
local -v3 -p /etc/zorp/policy.py --autobind-ip 10.2.3.4
dmz -v3 -p /etc/zorp/policy.py --autobind-ip 10.2.3.4
internet --verbose=5 --policy /etc/zorp/policy.py --autobind-ip 10.2.3.4
Первое поле – это имя примера, выбранное произвольно. Для каждого имени можно использовать отдельный файл, но можно сконфигурировать многочисленные зоны в пределах единственного файла. Опции -v или --verbose показывают уровень оповещения, а -р или --policy – на файл политик. Возможны и другие параметры, либо можно просто привязать Zorp к определенному сервису. Вроде такого:
zorp_ftp -v4 -p /etc/zorp/policy.py --threads 500 -- --no-auto-restart --fd-limit 1024 --process-limit 512
Теперь файл политик policy.py. Он состоит из двух секций. Первая является глобальной и описывает зоны, основываясь на адресах и сервисах. Во второй описываются сервисы, которые будут пропущены через прокси. Помните, мы имеем дело с Python, разделение на блоки у которого производится табуляцией и пробелами, поэтому рекомендую здесь быть очень аккуратными:
Zorp.firewall_name = 'zorp.domain.com'
Подключаем модули для работы c протоколами http, ftp, ssl и plug:
from Zorp.Core import *
from Zorp.Plug import *
from Zorp.Http import *
from Zorp.Ftp import *
from Zorp.Pssl import *
Ниже определяются зоны с соответствующими адресами и сервисами, которые они обеспечивают. Обратите внимание, что значения исходящих (outbound) и входящих (inbound) сервисов выбираются относительно самой зоны, а не межсетевого экрана. Поэтому, например, если из Интернета будут обращаться с запросом к веб-серверу, расположенному в DMZ, то это будет указано как outbound. В качестве названий допущенных сервисов можно выбрать любые, но при большом их количестве очень легко запутаться, поэтому лучше выбрать такое описание, чтобы оно показывало его суть. Также если, например, для локальных пользователей разрешен доступ (outbound) к веб-серверу в DMZ (назовем параметр local_http), то он должен быть обязательно прописан и в inbound в записи dmz. Пустое значение означает отсутствие параметров, т.е. фактически запрет сервисов, а звездочка «*» означает разрешение всех сервисов, которые описаны в файле, а не все, которые вообще возможны. Но здесь необходимо помнить, что Zorp обрабатывает только те пакеты, которые передают ему Netfilter и TPROXY.
Для примера разрешим доступ к серверу, находящемуся в DMZ, из локальной сети по протоколам http и для удаленного управления ssh, а из внешней сети – по http.
InetZone('local', '192.168.0.0/24' "
## здесь через запятую можно указать несколько адресов
outbound_services=["local_http", "local_ssh"]],
inbound_services=[])
InetZone('dmz', '10.0.0.0/24',
inbound_services=["local_http", "local_ssh", "internet_http"] )
InetZone('internet', '0.0.0.0/0',
outbound_services=["internet_http"],
inbound_services=["*"])
InetZone("localzone", "127.0.0.0/8",
inbound_services=["*"])
И теперь сервисы. Описание сервиса состоит из исходной зоны, протокола и зоны назначения. Если услуга прозрачна и зона назначения не определяется, то ее описание опускается. После адреса указывается порт, на который iptables будет направлять пакеты, предназначенные для этого сервиса.
def local():
Service("local_http", HttpProxy,
router=TransparentRouter())
Service("local_ssh", PlugProxy,
router=TransparentRouter())
# вместо PlugProxy можно использовать PsslProxy
Listener(SockAddrInet('192.168.0.1', 50080),
"local_http")
Listener(SockAddrInet('192.168.0.1', 50022),
"local_ssh")
def dmz():
pass
В отличие от других сервисов веб-сервис имеет конкретное расположение, поэтому направляем трафик internet_http при помощи DirectedRouter, а не TransparentRouter, как было в остальных случаях. Возможен вариант InbandRouter(), который соответствует непрозрачному прокси.
def internet():
Service("internet_http", HttpProxy,
router=DirectedRouter(SockAddrInet('10.0.0.2',80), forge_addr=TRUE))
Listener(SockAddrInet('111.222.333.444 ', 50080),
"internet_http")
На первый взгляд, составлять правила очень непросто, но если заранее распланировать ресурсы, к которым требуется организовать доступ, указать адреса и порты, то правила напишутся относительно быстро. Для того чтобы не запутаться в номерах портов, лучше выбирать их примерно так: 22 50022 или 80 50080. Кроме того, на сайте [3] и в документации проекта, можно найти ряд примеров позволяющих организовать: HTTPS-прокси, в том числе и без шифрования трафика к серверу, включить адрес клиента в http-заголовок, избежать подбора пароля в ssh, поддерживать виртуальный узел, ограничить полосу и некоторые другие.
Вот так можно организовать фильтрацию содержимого URL http-запроса, для этого добавляем сервис local_internet_http и даем ему такое описание.
from Zorp.Matcher import *
class IDHttp(HttpProxyURIFilter):
matcher=RegexpFileMatcher('/etc/zorp/http.black', '/etc/zorp/http.white')
def config(self):
HttpProxyURIFilter.config(self)
self.transparent_mode = 1
def regexp():
Service("local_internet_http", IDHttp)
Listener(SockAddrInet("192.168.0.1", 50090), " local_internet_http ")
Как видите, вначале на основе стандартного класса HttpProxyURIFilter, который определен в модуле Addon.py (по умолчанию в нем используются файлы blacklist-http и blacklist-http.ignore), был создан новый класс IDHttp, и затем применен при описания сервиса. Файлы http.black и http.white содержат список регулярных выражений, здесь можно указать URL, к которым необходимо запретить доступ, слова, при нахождении в запросе которых он будет прерываться. Например, добавив строку .*exe, можно запретить скачивать файлы с указанным расширением. Чтобы по ошибке не запретить доступ к ценным ресурсам, их стоит занести в http.white.
Используя следующую конструкцию, можно организовать NAT средствами самого Zorp.
NATPolicy("local-internet",
cacheable=TRUE,
nat=GeneralNAT([(InetDomain(111.222.333.444/24'),
InetDomain('192.168.0.0/24'))]))
NATPolicy("internet-local",
cacheable=TRUE,
nat=GeneralNAT([(InetDomain('192.168.0.0/24'),
InetDomain('111.222.333.444/24'))]))
Если заглянуть в модули, то можно обнаружить, что контролю поддаются практически все основные параметры поддерживаемых протоколов, по которым можно организовать фильтрацию либо другую их обработку. Например, использовав следующую конструкцию, можно обработать код ответа 404, заменив его своим сообщением.
class DmzHTTP(HttpProxy):
def config(self):
HttpProxy.config(self)
self.response["GET", "404"] = (HTTP_RSP_POLICY, self.filter404)
def filter404(self, method, url, version, response):
self.error_status = 404
self.error_info = "Requested page was not accessible."
return HTTP_RSP_REJECT
Построение правил iptables
Таблица tproxy содержит все встроенные цепочки, наиболее естественно использовать PREROUTING. Самое простое правило, которое направит нужный пакет в Zorp, выглядит так:
# iptables -t tproxy -A PREROUTING -j TPROXY --on-port 50080
Но чтобы не засорять Zorp мусором, отсеивая пакеты, которые не должны проходить через фильтр, средствами самого Netfilter, лучше указать интерфейс, с которого ожидается пакет, поэтому для каждого создадим свои цепочки. Остальные пакеты будут проходить в соответствии с политикой по умолчанию (-Р):
# iptables -t tproxy -P PREROUTING ACCEPT
# iptables -t tproxy -P OUTPUT ACCEPT
Создаем цепочки для каждого интерфейса:
# iptables -t tproxy -N PRlocal
# iptables -t tproxy -N PRdmz
# iptables -t tproxy -N PRinternet
И привязываем их к своему интерфейсу:
# iptables -t tproxy -A PREROUTING -i eth0 -j PRinternet
# iptables -t tproxy -A PREROUTING -i eth1 -j PRlocal
# iptables -t tproxy -A PREROUTING -i eth2 -j PRdmz
Заполняем:
# iptables -t tproxy -A PRlocal -p tcp --dport 80 -j TPROXY --on-port 50080
# iptables -t tproxy -A PRlocal -p tcp --dport 22 ! -d zorp.domain.com -j TPROXY --on-port 50022
# iptables -t tproxy -A PRintenet -p tcp --dport 80 -j TPROXY --on-port 50080
И разрешаем прохождение по цепочке INPUT:
# iptables -P INPUT DROP
# iptables -A INPUT -m tproxy -j ACCEPT
# iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# iptables -A INPUT -i lo -j ACCEPT
# iptables -N LOlocal
# iptables -A INPUT -i eth1 -j LOlocal
# iptables -A LOlocal -p tcp --dport 22 --syn -j ACCEPT
# iptables -A LOlocal -p udp --dport 53 -j ACCEPT
# iptables -A LOlocal -p tcp --dport 25 --syn -j ACCEPT
# iptables -A LOlocal -j LOG --log-prefix "LOblue DROP: "
# iptables -A LOlocal -j DROP
# iptables -N LOdmz
# iptables -A INPUT -i eth2 -j LOdmz
# iptables -A LOdmz -p udp --dport 53 -j ACCEPT
# iptables -A LOdmz -j DROP
# iptables -N LOinternet
# iptables -A INPUT -i eth0 -j LOinternet
# iptables -A LOinternet -p udp -sport 53 -j ACCEPT
# iptables -A LOinternet -p tcp --dport 25 --syn -j ACCEPT
# iptables -A LOinternet -j DROP
Теперь можно запускать Zorp: «zorpctl start» и проверить результат.
Вывод
Zorp позволяет на порядок лучше защитить компьютерные системы по сравнению с обычным межсетевым экраном хотя бы потому, что сам прокси даже без контроля приложений изолирует системы от нападений, направленных на более низкий уровень, которые, возможно, не видит Netfilter. Но, к сожалению, настраивать GPL-вариант все-таки непросто. Хотя, впрочем, вовсе не обязательно делать это сразу и за один день, можно постепенно наращивать его возможности.
Ссылки:
- Яремчук С. Как повысить безопасность веб-приложений. – Журнал «Системный администратор», №2, 2006 г. – 60-64 с. (http://www.samag.ru/cgi-bin/go.pl?q=articles;n=02.2006;a=10).
- Сайт проекта Zorp – http://www.balabit.com.
- Неофицальный сайт Zorp – http://zorp-unoff.sourceforge.net.
- Патч tproxy – http://www.balabit.com/products/oss/tproxy.
- Статья в «Linux Journal» – «Application Proxying with Zorp, Part I и Part II»– http://www.linuxjournal.com.
- Статья в немецком «Linux magazin», № 12/04 – «Ampel-Schaltung» – http://www.linux-magazin.de.