Введение


Моё первое знакомство с контейнерной виртуализацией было с jail в FreeBSD, данный подход позволяет изолировать различные службы в безопасном окружении. Недостаток jail в том, что в нём нет возможности создать собственную сетевую подсистему, в отличии от Zones Solaris. В данной публикации будет рассмотрено создание зоны с собственной сетевой подсистемой, а также без неё.

Firewall


В качестве «фаервола» будет использоваться packet filter из OpenBSD. С помощью packet filter будет осуществляться nat из зоны с собственной сетевой подсистемы, а также ограничения сети глобальной зоны. Для установки packet filter и запуска, выполните команды:

pkg install firewall
svcadm enable firewall

Далее откройте файл с будущими правилами:

nano /etc/firewall/pf.conf

в редактор nano добавьте следующие строки:

table <good> {192.168.1.105,192.168.1.106}
table <nat> {192.168.0.0/24}

pass quick on lo0 from any to any no state

pass quick on vnic0 from any to any

pass out quick on net0 from <nat> to any nat-to (net0)
pass in quick on net0 proto tcp from any to 192.168.1.105 port 80 rdr-to 192.168.0.2

pass in quick on net0 proto tcp from any to <good> port=22 flags S/SA modulate state

pass out quick on net0 proto tcp from <good> to any port {80,443,21,53} flags S/SA modulate state

pass out quick on net0 proto udp from <good> to any port=53 keep state
pass out quick on net0 proto icmp from <good> to any

block from any to any fragment
block from any to any
block all

Укажите какой файл необходимо использовать в packet filter:

pfctl -f /etc/firewall/pf.conf

В данном файле правил присутствую две таблицы с списком ip адресов:

table <good> {192.168.1.105,192.168.1.106}
table <nat> {192.168.0.0/24}

В таблице good перечислены ip адреса глобальной зоны и зоны которая не имеет собственной сетевой подсистемы, если планируете использовать несколько таких зон, то через запятую укажите список ip адресов. Данным ip адресам будет разрешён исходящий трафик, а также будет возможность производить подключение через ssh. Если планируете организовать, например, вэб сервер в глобальной зоне, или в зоне без сетевой подсистемы, в этом случае необходимо добавить следующею строку:

pass in quick on net0 proto tcp from any to 192.168.1.106 port=80 flags S/SA modulate state

Или группу портов:

pass in quick on net0 proto tcp from any to 192.168.1.106 port {80, 443, 21,22} flags S/SA modulate state

В таком случаи производить подключение возможно через http,https, ftp, ssh.

В таблице nat указана подсеть зоны с собственной сетевой подсистемой, если планируете несколько таких сетей, то укажите их через запятую. В приведённой ниже строке производиться «натирование» через net0 всех подсетей из таблицы nat.

pass out quick on net0 from <nat> to any nat-to (net0)

Зону с собственной сетевой подсистемой можно использовать как DMZ, но для этого необходимо пробросить необходимые порты, следующая строка пробрасывает в зону 80 порт вэб сервера, тоесть все обращения на ip 192.168.1.105(глобальной зоны) будут перенаправлены на ip 192.168.0.2:

pass in quick on net0 proto tcp from any to 192.168.1.105 port 80 rdr-to 192.168.0.2

Также необходимо обратить внимание на строку:

pass quick on vnic0 from any to any

Данная строка разрешает любой трафик на виртуальном интерфейсе vnic0, данный интерфейс будет выступать в качестве шлюза. ip адрес данного интерфейса 192.168.0.1, этот интерфейс будет активен в глобальной зоне, поэтому его нужно указать в файле правил. Если планируется несколько шлюзов для разных подсетей, то в этом случаи необходимо добавить аналогичную строку с именем виртуально интерфейса. Например если планируете ещё одну подсеть 192.168.2.0/24 и присвоили адаптеру vnic5 ip(как это сделать будет написано в следующей главе) адрес 192.168.2.1, то строка будет выглядеть так:

pass quick on vnic5 from any to any

Виртуальные интерфейсы которые создаются для не глобальной зоны указывать не нужно.

Создание зоны


Данную главу можно начать с создания виртуальных интерфейсов, а также необходимо позволить ходить пакетам между интерфейсами net0 и vnic0:

dladm create-vnic -l net0 vnic0
dladm create-vnic -l net0 vnic1
ipadm set-ifprop -p forwarding=on net0
ipadm set-ifprop -p forwarding=on vnic0

После создания необходимо для vnic0 создать ip адрес:

ipadm create-ip vnic0
ipadm create-addr -T static -a 192.168.0.1/24 vnic0/v4

На этом с виртуальными интерфейсами закончено, если у Вас конечно нет необходимости создать ещё несколько подсетей.

Следующим шагом будет создание zfs пула для хранения зон, пул создадим из файла образа:

mkfile 10g /disk

Данная команда создаст файл размером 10 гигабайт(размер укажите который необходим Вам), создадим пул командой:

zpool create zones /disk

Создадим два раздела под будущие зоны и назначим каждому квоту в 5 гигабайт:

zfs create zones/zone1
zfs create zones/zone2
zfs set quota=5g zones/zone1
zfs set quota=5g zones/zone2

На момент написания данной публикации версия Solaris 11.4 являлась бета версией, в данной версии добавлена возможность ограничить(не применимо к версии 11.3) чтение и запись на раздел zfs:

zfs set writelimit=50mb zones/zone1
zfs set readlimit=50mb zones/zone2

Перейдём непосредственно к созданию зоны, первоначально создадим зону без собственной сетевой подсистемы, введите команду:

zonecfg -z zone1

После создайте основные параметры командой create, следующим шагом будет удаление параметра anet(содержит название сети, mac адрес, mtu и так далее):

remove anet

Далее укажем путь для будущей зоны, установим автозапуск зоны и тип ip адреса:

set zonepath=/zones/zone1
set autoboot=true
set ip-type=shared

Далее необходимо создать сеть для зоны:

add net

Следующим шагом необходимо указать физический интерфейс и ip адрес для зоны, и выйти из настроек сети(end):

set physical=net0
set address=192.168.1.106/24
end

Сохраните изменения и выйдете из zonecfg командами:

commit
exit

Установка зоны происходит после выполнения команды:

 zoneadm -z zone1 install

Если скорость доступа в сеть интернет достаточно большая, то весь процесс займёт не более 5-ти минут. После того как зона будет установлена, необходимо её запустить и произвести первичную настройку(hostname, dns, domen search, пароль для root, создать учётную запись), настройка происходит таким же образом как и при установке системы. Выполните последовательно команды(для запуска зоны и первичной настройки):

zoneadm -z zone1 boot
zlogin -C zone1

Дождитесь пока появиться «мастер настройки». В будущем возможно производить подключение к зоне командой:

zlogin zone1

На этом настройка и установка зоны закончена. Настройка зоны с собственной сетевой подсистемой мало чем отличается от создания обычной зоны, необходимо лишь указать тип ip адреса, в качестве физического интерфейса указать виртуальный адаптер vnic1(для которого не создавался ip адрес), а также не создавать ip адрес для сети зоны, ip адрес будет создан при первом подключении к зоне(zlogin -C zone2). Для того что-бы всё корректно заработало, согласно данной публикации, необходимо указать ip адрес 192.168.0.2.

zonecfg -z zone2
create
remove anet
set zonepath=/zones/zone2
set autoboot=true
set ip-type=exclusive
add net
set physical=vnic1
end
commit
exit
zoneadm -z zone2 install
zoneadm -z zone2 boot
zlogin -C zone2

После того как первичная настройка закончена, установите apache, nano и packet filter, а также запустите apache и packet filter

pkg install apache-24
pkg install firewall
pkg install nano
svcadm enable apache24
svcadm enable firewall

Отредактируйте pf.conf:

nano /etc/firewall/pf.conf

В nano добавьте строки:

ip=192.168.0.2

pass in quick on vnic1 proto tcp from any to $ip port 80 flags S/SA modulate state

pass out quick on vnic1 proto tcp from $ip to any port {80,443,21,53} flags S/SA modulate state

pass out quick on vnic1 proto udp from $ip to any port=53 keep state
pass out quick on vnic1 proto icmp from $ip to any

block from any to any fragment
block from any to any
block all

Укажите какой файл необходимо использовать в packet filter:

pfctl -f /etc/firewall/pf.conf

В данном примере используется переменная $ip, если Вы указали другой ip адрес, то достаточно изменить первую строчку на корректный адрес.

Дополнительно


В заключительной главе речь пойдёт о ограничениях зоны, монтирование папок, а также расширенных полномочиях зоны. Предположим Вам необходимо смонтировать некий каталог из глобальной зоны, для этого выберете необходимую зону:

zonecfg -z zone1

Далее добавьте файловую системы:

add fs

Укажите каталог в глобальной зоне(например каталог /test):

set special=/test

Укажите куда необходимо его смонтировать:

set dir=/usr/test

Тип файловой системы укажем loopback:

set type=lofs

Выставим права на каталог только для чтения(если необходимо и для записи укажите rw, или вообще не добавляйте данный параметр):

add options [ro,nodevices]

Выйдете из настроек файловой системы и сохраните изменения:

end
commit
exit

Также можно смонтировать раздел zfs:

add dataset
set name=rpool/export/home
end
commit

Перезапустите зону:

zoneadm -z zone1 reboot

Теперь давайте ограничим оперативную память, swap и использование процессора, выберете необходимую зону:

zonecfg -z zone1

Добавьте ограничения для памяти:

add capped-memory

Ограничим оперативную память в 1 гигабайт, а swap в 500 мегабайт:

set physical=1024m
set swap=500m
end
commit

Ограничим использования каждого ядра процессора на 30 процентов:

add capped-cpu
set ncpus=.30
end
commit

Последний штрих, добавим зоне привилегии по умолчанию, список всех привилегий можно посмотреть выполнив команду:

ppriv -l -v

Ознакомиться с привилегиями которые используются по умолчанию(а также которые можно добавить при необходимости) можно в этом руководстве. Добавить привилегии можно следующей командой(из zonecfg):

set limitpriv="default,sys_time"

Как указано в данном руководстве, данная строка установит привилегии по умолчанию, а также позволит изменять системное время из не глобальной зоны. На мой взгляд для зоны лучше не добавлять дополнительных привилегий, так как зона с маленьким количеством привилегий более ограниченна в функционале, а значит более защищена.

Заключение


Как видно из данной публикации зоны довольно просты в настройке, но в тоже время предоставляют высокий уровень защиты(особенно зоны с собственной сетевой подсистемой) в связке с packet filter настроенный на политику «запрещено всё, что не разрешено». Настройка и развёртывание занимает минимум усилий в времени.

Список источников, которые помогли мне написать данную публикацию.

Zones

Packet Filter

Комментарии (5)


  1. skeletor
    15.02.2018 13:21

    В целом для новичка достаточно неплохо, но есть несколько нюансов:

    Перезапустите зону:

    zoneadm -z zone1 reboot

    Начиная с 11.3 можно этого не делать, а использовать команду zoneadm -z ZONE apply, после того, как в работающую зону внесли изменения через zonecfg. Но тут так же следует добавить, то apply не сработает, если вы:
    — поменяли тип сети (shared/exclusive)
    — добавили/удалили датасет (add dataset)

    В 11.4 добавлять/удалять датасет можно уже без ребута зоны (через zoneadm -z ZONE apply)

    dladm create-vnic -l net0 vnic0
    dladm create-vnic -l net0 vnic1

    Для настройки зон по вашим условиям можно обойтись и без этого: если ip-type=shared, то этого уж точно не нужно, а если ip-type=exclusive, то ОС сама это сделает на этапе загрузки зоны.


  1. 7rusyk9
    15.02.2018 13:21

    pass quick on vnic0 from any to any

    skip on (vnic)


    1. skeletor
      15.02.2018 13:24

      Это совсем разные вещи. Из документации по PF:

      set skip on interface
      Skip all PF processing on interface. This can be useful on loopback interfaces where filtering, normalization, queueing, etc, are not required. This option can be used multiple times. By default, this option is not set.


    1. Nemets85 Автор
      15.02.2018 13:30

      Изначально такое правило у меня и было прописано, но не чего не заработало, до тех пор пока не прописал pass quick on vnic0 from any to any


  1. kernelconf
    15.02.2018 14:15

    Почему в клетках FreeBSD нельзя создать сетевую подсистему? vnet работает в jail. Припоминаю, что на 8.x люди ловили паники, но с тех пор много воды утекло.

    Кроме того, даже не имея сетевой подсистемы в клетке, можно использовать pf чтобы управлять трафиком клеток (на хосте).