Архив за месяц: Октябрь 2018

ZFS. Почему заканчивается место в пуле? Подводные камни ZVOL на raidz.

Файловая система ZFS — достаточно продвинутая и многофункциональная. Тут вам и дедупликация, и сжатие, и контрольные суммы, продвинутое кэширование и т.д. Одно из хороших применений ZFS — создание ZVOL на ее основе и дальнейшее расшаривание их по iSCSI для любых целей. Плюсы достаточно очевидны: надежность хранения как на любом RAID, отсутствие дорогих аппаратных RAID-контроллеров, быстрое восстановление массива в случае замены диска (ZFS не перестраивает весь массив, как классические RAID — перестраивается только реально необходимое место). Но потом всплывают малоизвестные минусы…

Итак, при создании ZVOL с параметрами по умолчанию (а именно volblocksize=8k) на raidz и заполнении всего раздела данными мы можем внезапно обнаружить очень немаленький оверхэд по реальному размеру, занимаемому этим разделом в массиве. Причем речь идет не о 10%, которые можно было бы простить «на служебные нужды». Речь легко может идти о 60-70% оверхэда. Да-да, при размере ZVOL в 1 ТБ, он вполне может занять 1.7 ТБ в вашем массиве. И произойдет это ровно в тот момент, когда вы этого ожидаете меньше всего — массив заполнен полезными данными, а найти такое количество места, чтобы быстро сбросить туда всё — нереально.

К сожалению, никаких «магических» способов исправить такую ситуацию, когда она уже случилась — нет. Более того, скорее всего вам придется уничтожить весь zpool для того, чтобы вернуть его к жизни — так как даже при удалении всех zvol в массиве вы не сможете создать такое же количество новых zvol с тем же размером. Т.е. только zfs destroy/zpool destroy/zpool create/zfs create.

А теперь немного цифр. Я провел тесты для определения потерь места на массиве raidz из 8 HDD с разными volblocksize. Ниже в таблице представлены результаты тестов. Методика такая: создаем ZVOL на 5 ГБ с размерами блоков 4k, 8k, 16k, 32k, 64k и 128k. После этого при помощи dd с параметром bs=8k записываем данные на раздел пока dd не скажет, что место закончилось. Далее при помощи команды zfs get all zpool/zvol1 смотрим на параметр used — он-то и расскажет о реально занятом месте.

Размер блока 4k 8k 16k 32k 64k 128k
Занятое место 8,52 ГБ 8,48 ГБ 6,34 ГБ 5,28 ГБ 5,27 ГБ 5,01 ГБ
% 170,4 169,6 126,8 105,6 105,4 100,2

Для моих целей прекрасно подошел размер блока 128к, т.к. мелкие файлы на нем не хранятся и потери в таком случае будут минимальны. Следует учитывать, что эти сведения актуальны для массива raidz из 8 дисков. Если у вас raidz2 или другое количество дисков — данные будут другими. Как вариант, вы можете использовать комбинации stripe и mirror — они лишены этой неприятной особенности.

Route-based IPSEC VPN между Ubuntu 18.04 (libreswan) и Cisco Router

В корпоративном секторе, особенно в больших компаниях с более, чем одним офисом зачастую возникает необходимо в site-to-site VPN-соединениях. Конечно, большинство провайдеров предлагает вам «прямую связь» через их оборудование. Но как-то так сложилось, что надежность этого решения зависит только от самого провайдера и из-за некорректных действий одного-единственного админа может зависеть целостность вашей сети. Такие объединения сетей частенько выполняются просто на уровне отдельного тегированного VLAN. И если кто-то внезапно (вполне может быть по неосторожности) скрестит вашу сеть с другими или просто снимет теги на портах — вы рискуете получить в свою сеть трафик от многих клиентов провайдера, а они, в свою очередь, получат беспрепятственный доступ в вашу сеть. Именно по этой причине доверять стоит только собственноручно поднятому IPSEC VPN. Если что-то пойдет не так — VPN просто развалится и сети будут изолированы друг от друга.

В каких случаях Route-based VPN удобнее, чем обычный site-to-site? Например, если вы хотите предоставить N хостам из одной сети доступ к ресурсам в другой сети, но создавать для этого клиентские соединения неудобно. Также, если у вас много подсетей с одной из сторон (или с обеих) и вы не хотите плодить IPSEC SA (как произойдет в случае обычного Policy-based IPSEC VPN). Или, например, вы хотите пробросить весь трафик нескольких клиентов через роутер в другой стране. Во всех этих случаях полезно и удобно будет использовать Route-based VPN.

Итак, начнем с оборудования. В моем случае это был Cisco Router серии ASR с одной стороны и сервер с Ubuntu 18.04 с другой. Цель — пустить трафик N клиентов в интернет через удаленный сервер. Начнем с Ubuntu:

  1.  Установим libreswan.
    apt-get install libreswan
  2. Разрешим форвардинг пакетов и отключим редиректы.
    echo "net.ipv4.ip_forward = 1" | tee -a /etc/sysctl.conf
    echo "net.ipv4.conf.all.accept_redirects = 0" | tee -a /etc/sysctl.conf
    echo "net.ipv4.conf.all.send_redirects = 0" | tee -a /etc/sysctl.conf
    for vpn in /proc/sys/net/ipv4/conf/*; do echo 0 > $vpn/accept_redirects; echo 0 > $vpn/send_redirects; done
  3. Применим настройки.
    sysctl -p
  4. Создадим в /etc/ipsec.d/ файл с конфигурацией нашего VPN и поместим в него следующий контент:
    nano /etc/ipsec.d/route-based-ipsec-vpn.conf
    
    config setup
        protostack=netkey
    conn vpn
        authby=secret
        pfs=no
        rekey=yes
        keyingtries=3
        type=tunnel
        auto=start
        ike=aes256-sha1;modp1536
        phase2alg=aes256-sha1;modp1536
        left=11.11.11.11
        right=22.22.22.22
        leftsubnet=0.0.0.0/0
        rightsubnet=0.0.0.0/0
        mark=5/0xffffffff
        vti-interface=vti01
        vti-routing=no

    Если один из ваших роутеров находится за NAT (например left), вам необходимо заменить в директиве left адрес на внутренний адрес интерфейса (left=10.0.0.1) и добавить директиву leftid с реальным адресом (leftid=11.11.11.11).  И, конечно, пробросить порты UDP 500, 1701 и 5000 на этот роутер. В противном случае туннель не поднимется.

    Краткие пояснения по конфигурационному файлу:
    authby=secret — авторизация по паролю, а не по сертификатам;
    vti-interface=vti01 — интерфейс, который будет создан автоматически при создании туннеля;
    vti-routing=no — не создавать маршруты на интерфейс туннеля автоматически.
  5. Далее необходимо придумать сгенерировать стойкий пароль на много символов (все равно вам его запоминать не надо) и внести его в файл.
    nano /etc/ipsec.d/route-based-ipsec-vpn.secrets
    
    11.11.11.11 22.22.22.22: PSK "%908A2R5vX9O694aoxh1"
  6. Делаем ipsec restart и ipsec verify. После ipsec verify у нас должно появиться что-то типа этого:
    Verifying installed system and configuration files
    
    Version check and ipsec on-path                         [OK]
    Libreswan 3.23 (netkey) on 4.15.0-1021-aws
    Checking for IPsec support in kernel                    [OK]
     NETKEY: Testing XFRM related proc values
             ICMP default/send_redirects                    [OK]
             ICMP default/accept_redirects                  [OK]
             XFRM larval drop                               [OK]
    Pluto ipsec.conf syntax                                 [OK]
    Two or more interfaces found, checking IP forwarding    [OK]
    Checking rp_filter                                      [ENABLED]
     /proc/sys/net/ipv4/conf/all/rp_filter                  [ENABLED]
     /proc/sys/net/ipv4/conf/default/rp_filter              [ENABLED]
     /proc/sys/net/ipv4/conf/eth0/rp_filter                 [ENABLED]
     /proc/sys/net/ipv4/conf/ip_vti0/rp_filter              [ENABLED]
      rp_filter is not fully aware of IPsec and should be disabled
    Checking that pluto is running                          [OK]
     Pluto listening for IKE on udp 500                     [OK]
     Pluto listening for IKE/NAT-T on udp 4500              [OK]
     Pluto ipsec.secret syntax                              [OK]
    Checking 'ip' command                                   [OK]
    Checking 'iptables' command                             [OK]
    Checking 'prelink' command does not interfere with FIPS [OK]
    Checking for obsolete ipsec.conf options                [OK]
    

    Если failed нигде не написано — можно жить.

  7. Заставляем трафик прятаться за айпишник нашего интерфейса при выходе наружу (в данном примере внешний интерфейс — eth0) при помощи iptables:
    iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
  8. Прописываем маршруты в нашу удаленную сеть (предположим, что на другом конце есть сети 192.168.0.0/24 и 192.168.10.0/24).
    ip route add 192.168.0.0/24 dev vti01
    ip route add 192.168.10.0/24 dev vti01
  9. На этом этапе настройка Ubuntu закончена и мы переходим к настройке Cisco ASR. Продолжение следует (линк на него будет в конце этой статьи).

При написании этого материала помог личный опыт, статья https://libreswan.org/wiki/Route-based_VPN_using_VTI и гугл.