Настраиваем Zorp

Настраиваем 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 используются три файла, которые по умолчанию должны лежать в /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


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: