пятница, 1 июля 2016 г.

Как переименовать сетевой интерфейс в CentOS 7

Во FreeBSD, когда настраиваешь сетевые параметры, есть очень удобный механизм переименовывания названий сетевых интерфейсов. Можно, к примеру, интерфейс em0 назвать lan0, а xl0 - wan0. Во-первых, это придаёт настройкам всевозможных конфигурационных файлов осмысленности: сразу понятно, какой интерфейс за что отвечает, а во-вторых, в различных конфигурационных файлах можно использовать эти псевдонимы и, в случае замены сетевой карты, нужно всего-лишь поменять одну строчку в rc.conf. Причём, делается такое переименование элементарно - одной строкой в конфиге rc.conf:

ifconfig_em0_name="lan0"
ifconfig_xl0_name="wan0"

И всё! Дальше везде используем только имена lan0 и wan0.


Когда я начал настраивать очередной Linux сервер, был сильно удивлён, что этот, вроде бы, тривиальный механизм в линуксе устроен, мягко говоря, несколько сложнее. Казалось бы, чего проще - добавь в конфигурационный файл сетевого интерфейса параметр NAME и интерфейс сам переименуется. Но нет. Там нужно задействовать какие-то сложные и не до конца понятные механизмы udev. 99% советов сводится к необходимости добавить в конфигурационный файл /etc/udev/rules.d/70-persistent-ipoib.rules строк типа:

SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="90:2b:34:87:d1:7d", ATTR{dev_id}=="0x0", ATTR{type}=="1", NAME="lan0"

Тут с ходу понятно только, что сетевому интерфейсу с соответствующим mac-адресом присваивается имя lan0. Объяснения, зачем нужны остальные параметры, и что они означают, найти весьма непросто.
Но и это ещё не всё. После описанных действий нужно переименовать в каталоге /etc/sysconfig/network-scripts/ файл с именем ifcfg-старое_имя в файл ifcfg-новое_имя и изменить в самом файле все названия интерфейсов со старого на новый. (Написанное выше справедливо для CentOS, в Ubuntu немного по-другому).

В последних дистрибутивах (RHEL7, CentOS 7, Ubuntu 16.04) всё ещё больше запуталось. Там отказались от традиционного для линуксов именования сетевых интерфейсов, типа eth0, eth1 и т.д., и внедрили именование более сложное, основанное на аппаратном расположении интерфейса. Как это теперь работает, можно почитать, к примеру, здесь:
http://val-khmyrov.blogspot.ru/2015/11/blog-post_22.html
Всё понятно? Мне не совсем.
Я же, когда начал копать в сторону решения проблемы наткнулся на следующий мануал:
https://www.freedesktop.org/software/systemd/man/systemd.link.html
Т.е., по идее, с помощью этого механизма можно легко переименовать любой сетевой инерфейс, используя штатное средство systemd.link. Для этого всего-лишь нужно для каждого интерфейса в каталоге /etc/systemd/network/ создать файл, например с именем 10-lan0.link примерно следующего содержания:

[Match]
MACAddress=00:a0:de:63:7a:e6
[Link]
Name=lan0

после чего интерфейс с соответствующим mac-адресом, по идее, должен переименоваться. Но не тут то было! Сделал, как написано - не работает. Начал гуглить и обнаружил, что про это почти нигде ничего не сказано, кроме вышеприведённого мануала.
Хотел уже плюнуть на всё и воспользоваться методом редактирования 70-persistent-ipoib.rules (благо, он в CentOS 7 тоже работает), но случайно попал на основополагающий сайт документации RHEL. Там, вот на этой странице:
https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/Networking_Guide/sec-Disabling_Consistent_Network_Device_Naming.html
увидел совет, как отключить существующую схему именования. А именно нужно сделать симлинк:

ln -s /dev/null /etc/udev/rules.d/80-net-name-slot.rules

Таким образом отключается именование интерфейсов по слотам и включается именование по линкам.
И вот только после этого начинает работать механизм systemd.link. Победа!

В итоге имеем следующее.
Чтобы переименовать, к примеру, сетевой интерфейс ens160 в lan0 в CentOS 7, нужно сначала создать символическую ссылку:

ln -s /dev/null /etc/udev/rules.d/80-net-name-slot.rules

В каталоге /etc/systemd/network/ создаём файл 10-lan0.link следующего содержания:

[Match]
MACAddress=00:a0:de:63:7a:e6
[Link]
Name=lan0

указав реальный mac-адрес интерфейса, который пытаемся переименовать.

После чего, в каталоге /etc/sysconfig/network-scripts/ переименовываем файл ifcfg-ens160 в файл ifcfg-lan0 и в самом файле изменяем параметры NAME и DEVICE на новые. Перегружаемся, наслаждаемся новым именем.

И всё это вместо одной строчки:
ifconfig_ens16_name="lan0"
во FreeBSD.
Архитекторы Linux тут явно перемудрили.

понедельник, 23 мая 2016 г.

Ротация логов сервера OpenVPN под FreeBSD


Задача эта, как ни странно, весьма нетривиальная.
Во-первых, если расположение log-файлов задать в конфиге OpenVPN через дерективу:

log /var/log/openvpn/openvpn.log

то никакой ротации настроить не получится. Дело тут в том, что демон OpenVPN держит этот файл до своего перезапуска и пытается писать именно в него не по имени, а по дескриптору. Т.е., когда программа newsyslog осуществляет ротацию логов, она старый файл копирует, удаляет и создаёт вместо него новый, а OpenVPN продолжает пытаться писать логи в файл со старым дескриптором, которого уже не существует. В результате, после ротации лога таким способом, запись в него прекращается.
В сети описаны способы, как настроить это через утилиту logrotate с использованием параметра copytruncate, но, во-первых, logrotate штатно во FreeBSD не входит, а во-вторых, у меня это тоже не заработало. Идея тут в том, что параметр copytruncate позволяет не удалять старый log-файл, копируя его в другой, а старый просто обнулять. После этого, по идее, OpenVPN должен продолжить писать в старый файл нулевого размера с тем же дескриптором, а предыдущий лог уже подвергается упаковке и ротации. Однако у меня ротация лога таким способом, конечно, произошла, но OpenVPN продолжил писать в старый файл с той же позиции, на которой он остановился. Т.е. размер текущего log-файла не уменьшился.

Второй способ более правильный, и описан в документации OpenVPN, хотя и не совсем явно. Состоит он в том, что дерективу "log" из файла конфигурации OpenVPN нужно убрать. После этого все логи OpenVPN начнут попадать в общий файл /var/log/messages, а уже оттуда их нужно перенаправить в другой файл через настройки syslogd и ротировать посредством newsyslog. Во многих руководствах, найденных мной в сети, написано, что для этого нужно всего-лишь добавить в конец стандартного файла /etc/syslog.conf следующие строки:

!openvpn
*.*                                             /var/log/openvpn/openvpn.log

Добавил, логи OpenVPN действительно начали писаться куда надо, НО они продолжали попадать и в /var/log/messages, т.е. дублировались.
После долгих экспериментов и консультаций с умными людьми выяснилось, что вышеуказанные строки нужно добавлять не в конец файла syslog.conf, а в его начало, добавив туда ещё одну строку, в результате чего выглядеть это должно так:

!openvpn
*.*                                             /var/log/openvpn/openvpn.log
!-openvpn

Первые две строки указывают демону syslogd перенаправлять все сообщения от программы openvpn в файл /var/log/openvpn/openvpn.log, а третья сточка отключает какое-либо другое сохранение сообщений от программы openvpn.
Далее добавляем в newsyslog.conf то, что нам нужно, например такую строку:

/var/log/openvpn/openvpn.log    644     7       *       @T04    ZC


и процесс пошёл. Всё работает.

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

В начале /etc/syslog.conf:
!openvpn1
*.*                                             /var/log/openvpn/openvpn1.log
!openvpn2
*.*                                             /var/log/openvpn/openvpn2.log
!openvpn3
*.*                                             /var/log/openvpn/openvpn3.log
!-openvpn1,openvpn2,openvpn3
...

В конце /etc/newsyslog.conf:
...
/var/log/openvpn/openvpn1.log    644     7       *       @T04    ZC
/var/log/openvpn/openvpn2.log    644     7       *       @T04    ZC
/var/log/openvpn/openvpn3.log    644     7       *       @T04    ZC

Теперь всё.