Списки IP адресов для iptables

Так как не все наши заказчики выполняют требование по защите наших серверов файрволлом (доступ по ssh только с доверенных IP), быстрым решением было ограничить подключения в /etc/ssh/sshd_config через AllowUsers. В целом задачу свою подобное решение выполняло, за исключением одного момента – подключение с неизвестного IP отвергается, а в логах записи, тем не менее, остаются. При активных bruteforce-атаках логи пухли как на дроджжах и в условиях ограниченного дискового пространства это вызывало определённые проблемы. В итоге, улучив минутку, сел переделывать по-человечески – настраивать iptables на подконтрольном сервере, раз заказчики не чешутся и не выполняют наши техтребования.
Как оказалось, сами iptables этого не умеют. Решение нашлось быстро – ipset. Конечно, в сравнении с pf, меня несколько удивляет, что для подобной элементарной задачи нужна отдельная утилита… Буду считать это ярчайшим проявлением unixway: одна задача – один инструмент.
Список для ipset готовится элементарно, потом экспотируется командой ipset save в понятный ipset формат и подгружается при помощи ipset restore.
В набор адресов для ipset я добавил внешние адреса офиса и внутренние подсети, определённые RFC. Вот что получилось:
create trusted hash:net family inet hashsize 1024 maxelem 65536
add trusted 192.168.0.0/16
add trusted 10.0.0.0/8
add trusted 172.16.0.0/12
add trusted xxx.xxx.xxx.0/24
add trusted yyy.yyy.yyy.yyy

Где trusted – это имя списка IP, точнее списка подсетей.
Правило для iptables трансформировалось из
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
в
-A INPUT -m state --state NEW -m set --set trusted src -m tcp -p tcp --dport 22 -j ACCEPT
т.е. добавил -m set --set trusted src, где -m set указание на использование списка ipset, --set trusted имя списка и параметр указывающий что это список источников – src.
А вот дальше началось самое интересное – как при загрузке ОС скормить эти списки iptables, т.к. если список не загружен, то правила iptables не применяются, ссылаясь на ошибку.
Т.е. комманда ipset restore должна выполняться ДО iptables rstore. Оказалось, что в Scientific Linux с этим проблема. В пакете ipset-6.11-1.el6.i686 службы ipset нет, а из /etc/rc.local комманды выполняются ПОСЛЕ iptables restore, что, как я писал выше, приводит к ошибке и правила не загружаются. Получается, что по умолчанию два варианта – писать свои скрипты инициализации (как вариант использовать найденные в интернете) или колхозить ещё более жутким образом, типа прописать ipset restore < /etc/ipset.rules в /etc/init.d/iptables. Оба этих варианта меня как-то не сильно радовали.
Выход таки нашёлся – в репозиториях CentOS есть пакет ipset-init, который содержит в себе необходимые для решения данной задачи скрипты init.d.
После установки пакета добавил вышеприведённый конфиг в /etc/sysconfig/ipset и все проблемы с подгрузкой списков разрешились.
К слову сказать, в Arch Linux пакет ipset идёт со скриптами для systemd и использование сторонних скриптов и пакетов не требуется.
UPDATE: В более позднем пакете ipset-6.11-3.el6.i686 из SL6.6 служба ipset всё-таки появилась и необходимость в стороннем пакете отпала.

Share

Munin SSH transport

This entry is part [part not set] of 1 in the series munin

Решил настроить munin сервер для опроса порядка 500 нод.
В штатном режиме сервер опрашивает ноду по дефолтному порту 4949. Это прекрасно и замечательно, когда этот порт доступен “напрямую”. В моём случае большинство серверов сидят за чужим NAT-ом и наружу проброшен только ssh, причём ещё на какой-нибудь высокий порт. Или есть второй распространённый вариант – проброшен порт от одного сервера, а остальные доступны только по внутренней сети.
Доступ по ssh открыт, так как это является нашим основным требованием к сети заказчика.
В официальной документации как-то не сильно рекламируют возможность работы через ssh, но, как оказалось, в munin 2.x она есть. О её существовании помог узнать большой брат, который вывел на ссылку http://munin-monitoring.org/wiki/Native_ssh.
В принципе всё понятно, за исключением конфигурации с нестандартным ssh портом, но об этом чуть позже.
Тестовый сервер у меня был поднят на OpenBSD и серверная часть munin запускалась с правами пользователя _munin, который по умолчанию вместо shell имеет /sbin/nologin. Продакшн настраивал на Scientific Linux, в котором munin запускается от пользователя munin. Соответственно для возможности подключения по ssh к нодам надо было в обоих случаях этому пользователю прописать рабочий шелл, например /bin/sh, создать домашнюю директорию, сгенерировать ключи при помощи ssh-keygen (ключ должен быть без passphrase) и переслать публичный ключ на ноду для той учётной записи, под которой планируется на неё заходить. Пусть учётка на ноде зовётся user. Соответственно в домашней директории пользователя user в .ssh/autorized_keys должен быть прописан публичный ключ пользователя munin с сервера.
На машине с munin-node должен быть установлен netcat (nc), который позволит обращаться к munin-node через:

nc localhost 4949
# munin node at ms13090624.domain
list
df mssversion uptime

То есть для подобного режима работы ноде достаточно слушать только на 127.0.0.1 и отвечать на запросы тоже только с локалхоста. Одним сервисом “глядящим” наружу будет меньше.
Значимые строки в munin-node.conf для подключения к ней при помощи nc с localhost:

host_name ms13090624.domain
allow ^127\.0\.0\.1$
host 127.0.0.1

Вручную ноду можно проверить запустив с сервера через ssh nc на ноде:
sudo -u munin ssh user@xxx.xxx.xxx.xxx nc localhost 4949
В ответ должны получить приглашение munin-node, как и при локальном подключении.
Кусок конфига munin.conf для опроса ноды по 22 порту (описан в документации к munin):

[ms13090624.domain]
use_node_name no
address ssh://user@xxx.xxx.xxx.xxx/usr/bin/nc localhost 4949

Про использование альтернативного порта ssh я в документации не увидел ни слова, но просмотр кода и дальейшие тесты на стенде показали, что в конфиге сервера порт указывается вот в таком формате:

[ms13090622.domain]
use_node_name no
address ssh://user@xxx.xxx.xxx.xxx:2022/usr/bin/nc localhost 4949

то есть через двоеточие сразу после IP.

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

[ms13090625.domain]
use_node_name no
address ssh://user@zzz.zzz.zzz.zzz:2022/usr/bin/ssh user1@192.168.xxx.yyy /usr/bin/nc localhost 4949

ms13090625.domain – имя внутренней машины, прописанное в конфиге ноды
192.168.xxx.yyy – IP ноды, которая находится во внутренней сети
zzz.zzz.zzz.zzz:2022 ИП и порт машины к которой мы имеем доступ по ssh извне и с которй по ssh можно попасть на машину во внутренней сети, т.е. на ноду.

Итого для работы через туннель к “обычному” конфигу доступа по ssh вида
address ssh://user@zzz.zzz.zzz.zzz:2022/usr/bin/nc localhost 4949
добавилась команда для подключения с внешнего сервера на внутреннюю ноду: /usr/bin/ssh user1@192.168.xxx.yyy

Надеюсь это понятно сразу, что user на внешнем сервере должен быть обменян ssh ключом с user1 на внутреннем (ноде) для беспарольного доступа.

Share

Кривой стартер. Проблемы с разметкой дисков.

This entry is part [part not set] of 5 in the series kickstart

В процессе эксплуатации была выявлена одна проблема – порядок определения дисков имеет значение. Т.к. я привязывался к именам дисков, считая, что sda – установочная флешка, а sdb – целевой жёсткий диск, то всё благополучно ломается, если диски меняются местами. А они меняются местами. На абсолютно одинаковых неттопах, при условии, что “системная” флешка сидит всегда в одном и том же порту и установочная флешка подключается к другому порту (каждый раз расположенному там же на материнской плате), они, порой, меняются местами. Может от версии BIOS зависит, не знаю. Так глубоко копать не стал. Так же имена устройств меняются местами на одном и том же неттопе в зависимости от того, что является целевым диском – флешка или жёсткий диск.
Сбор информации по крупицам позволил сделать процесс универсальнее, о чём и поведаю.

В данном решении я отталкиваюь от метки установочной флешки. В моём случае – Scientific.
Начну с syslynux.cfg.
Нужно поменять в соответствующей строке append указание на загрузочный раздел. Вместо ks=hd:sda4 я использовал конструкцию hd:LABEL="Scientific"
В таком виде эта строка позволит найти ks.cfg вне зависимости от того, каким диском определилась установочная флешка (sda, sdb или sdc). Это уже должно упростить жизнь, особенно в случае установки на компьютер с несколькими дисками.

В самом ks.cfg меняем harddrive --partition=/dev/sda4 --dir=/ на
harddrive --partition=/dev/disk/by-label/Scientific --dir=/. Теперь и поиск установочного ISO образа будет завершаться непременным успехом.

Защитить установочную флешку от форматирования можно так же путём указания раздела не в формате sdXY, а указав метку:
part None --onpart=LABEL="Scientific" --noformat

Перейду к более сложному этапу – разметке диска. Часть вещей можно сделать штатными средствами anaconda, а часть придётся перевести в %pre скрипты.

Результатом работы будет сгенерированный файл /tmp/part-include, который надо будет подключить к ks.cfg через include.
Для начала нужно определить имя устройства установочной флешки и присвоить его значение переменной install_media:
install_media=blkid | grep Scientific | cut -c 6-8
Так как установка может проводиться на девственно чистый диск, то blkid уже не поможет, т.к. в выводе комманды присутствуют только диски, имеющие разделы. Исходя из того, что в системе два диска – установочный и целевой, причём на предыдущем этапе стало известно имя устройства установочного диска, воспользуемся для поиска имени устройства целевого диска содержимым директории /sys/block. Выведем список блочных устройств, исключим установочный диск и отфильтруем оставшиеся жёсткие диски и флешки:
dest_disk=ls -1 /sys/block | grep -v "$install_media" | egrep [hs]d
Получив таким образом имя устройства целевого диска, используем значение переменой в дальнейшем процессе. Все полученные строки надо записать в файл /tmp/part-include.
Укажем, куда ставить GRUB:
echo "bootloader --location=mbr --driveorder=$dest_disk --append="crashkernel=auto rhgb quiet reboot=bios"" >> /tmp/part-include
и удалим имеющиеся разделы на целевом диске:
echo "clearpart --all --initlabel --drives=$dest_disk" >> /tmp/part-include

В секции %pre, когда монтируется установочная флешка для доступа к устанавливаемым конфигам и скриптам, можно монтировать раздел, отталкиваясь от его метки:
mkdir /tmp/flash
mount /dev/disk/by-label/Scientific /tmp/flash

Share

Кривой стартер. post-install

This entry is part [part not set] of 5 in the series kickstart

Эта секция позволяет заскриптовать практически любые действия, которые будут проведены по окончании инсталяции. В моём случае все скрипты идут отдельным инклудом post.cfg, кторый начинается со строчки %post --interpreter /bin/sh --nochroot --log /tmp/postinstall.log.
Большая часть моего post.cfg не представляет интереса, т.к. выполняет узкоспециализированные задачи, но часть может быть полезна.
Т.к. в kickstart’е я не нашёл способа, не возвращаясь в интерактивный режим, задать пароль для шифрованного раздела, то эту операцию я выполняю уже в post секции:
# Setup crypted partition.
umount /dev/sdb4
dmsetup remove mcrypt
cryptsetup -q luksFormat /dev/sdb4 --key-file /mnt/sysimage/etc/mss.key
cryptsetup luksOpen /dev/sdb4 mcrypt --key-file /mnt/sysimage/etc/mss.key
mkfs.ext4 -O dir_index /dev/mapper/mcrypt
# Installer adds a line to mount sdb4 as uncrypted partition to fstab. Remove it!
sed -i '/mss/d' /mnt/sysimage/etc/fstab
# And add correct data to fstab and crypttab.
echo "/dev/mapper/mcrypt /var/lib/mss ext4 defaults 1 3" >> /mnt/sysimage/etc/fstab
echo "mcrypt /dev/sda4 /etc/mss.key" > /mnt/sysimage/etc/crypttab

Ключ mss.key генерируется в %pre секции.

Затем я копирую различные конфиги. Общий принцип:
cp /mnt/isodir/configs/* /mnt/sysimage//

Как вариант – донастройка munin-node:
# Unhook unused munin plugins.
for i in df_inode diskstats entropy forks fw_packets if_err_eth0 \
if_eth0 interrupts threads irqstats netstat open_files users swap \
open_inodes selinux_avcstat sendmail* proc_pri vmstat processes
do
rm -r /mnt/sysimage/etc/munin/plugins/$i
done

# Enable usable munin plugins.
ln -s /usr/share/munin/plugins/sensors_ /mnt/sysimage/etc/munin/plugins/sensors_temp
ln -s /usr/share/munin/plugins/sensors_ /mnt/sysimage/etc/munin/plugins/sensors_fan
ln -s /usr/share/munin/plugins/proc /mnt/sysimage/etc/munin/plugins/proc

# Accept connections from our munin-server.
echo "cidr_allow ???.???.??.??/32" >> /mnt/sysimage/etc/munin/munin-node.conf

# Install munin-node configuretion.
cp /mnt/isodir/configs/munin-node-mss /mnt/sysimage/etc/munin/plugin-conf.d/

При помощи sed разрешаю пользователям из группы wheel повышать привилегии без ввода пароля:
# Let wheel users sudo without typing password every time.
sed -Ei 's/^#( %wheel.*NOPASSWD.*)/\1/' /mnt/sysimage/etc/sudoers

Т.к. процесс настройки сети был пропущен, то некоторые манипуляции с именем машины производим тут же:
# Setup hostname.
sed -i '/^HOSTNAME/d' /mnt/sysimage/etc/sysconfig/network
echo "HOSTNAME=cat /tmp/hostname.txt" >> /mnt/sysimage/etc/sysconfig/network

# Add hostname to /etc/hosts to prevent resolve timeouts.
#awk ‘{$(NF+1)=”cat /tmp/hostname.txt“;}1′ /mnt/sysimage/etc/hosts > /tmp/hosts.tmp && mv /tmp/hosts.tmp /mnt/sysimage/etc/hosts
awk ‘{getline HOST /tmp/hosts.tmp && mv /tmp/hosts.tmp /mnt/sysimage/etc/hosts

Т.к. наши сервера потом попадают в чужие руки, я удаляю улики, т.е. логи:
# Remove clues.
#rm /mnt/sysimage/root/anaconda-ks.cfg
rm /mnt/sysimage/tmp/ks-script-*

Обычная часть закончена. Теперь предстоит выполнить некоторые операции в свежеустановленной системе, для чего надо сделать chroot в /:
# Chrooted postinstall scripts to make local changes in fresh system.
%post --interpreter /bin/sh

Например можно добавить в загрузку службу, которая была установлена не из пакетов:
# Add mss player init.d script to runlevels.
/sbin/chkconfig --add mss

Или создать пользователя с заданным паролем:
adduser mss -m -U -u 1000 -G wheel -p sa************

Завершает процесс %end.

Share

Отключение console blanking в Linux

Долго и неспешно искал адекватное решение, позволяющее отключить энергосберегающие фишки, связанные с консолью. Мне не очень удобно, когда на сервере надо нажимать что-нибудь на клавиатуре, чтобы увидеть происходящее в консоли, если она успела погаснуть. Лучший способ энергосбережения – выключить монитор, если ничего не собираешься смотреть.
setterm -blank 0 отключает blanking консоли и решает проблему. Но только в текущей консоли. Чтобы эти настройки применились ко всем консолям, да ещё цеплялись при загрузке машины, самое элегантное решение из всех найденных следующее – добавить вывод этой комманды в файл /etc/issue. В этом файле, по умолчанию, содержится приветствие, которое отображается на незалогиненной консоли. Надо просто добавить вывот setterm в конец файла: echo setterm -blank 0 >> /etc/issue. Проверено в Scientific Linux 6.4.

Share

Кривой стартер. Пакеты.

This entry is part [part not set] of 5 in the series kickstart

Самая простая и не интересная часть – выбор пакетов. Всегда “любил” Linux за то, что при установке он выносит мозг необходимостью выбора пакетов. Благо, благодаря kickstart’у, можно от этого избавиться. Но только для повторных установок, ха-ха.
Первоначальный спискок пакетов и групп пришлось выбирать вручную через UI anaconda. Всё выбранное потом будет отражено в /root/anaconda-ks.cfg, откуда его и следует скопировать в свой kickstart.cfg.
То что было выбрано группами (с префиксом @) и отдельные полезные пакеты из дистрибутива:

# List of packages to be installed.
%packages
@Base
@Core
@base
@client-mgmt-tools
@core
@dial-up
@hardware-monitoring
@misc-sl
@network-tools
@russian-support
@system-admin-tools
@system-management
SL_password_for_singleuser
autofs
device-mapper-persistent-data
dos2unix
lm_sensors
mc
nmap
pptp
rp-pppoe
screen
telnet
unix2dos

Как видно из комментария, я удаляю пакеты, которые мне никак не пригодятся:

# Remove packages that were installed with @groups.
-at
-dmraid
-lvm2
-lvm2-libs
-fprintd-pam
-mdadm
-pcmciautils
-rng-tools
-sl-release-notes
-words
-libselinux
-libselinux-utils
-selinux-policy
-selinux-policy-targeted
-postfix
-mysql-libs
-procmail

Часть из них, например postfix, всё равно поставится, т.к. являются чьими-то зависимостями.
В общем пока всё стандартно.

А вот тут есть нюанс. В дистрибутиве уже есть пакеты gstreamer. Да-да, протухшие и с утечками памяти. Я собрал собственные пакеты с более свежим gsreamer’ом, скопировал их на флешку в директорию gst и при помощи creatrepo элегантно превратил директорию в репу с пакетами. Чтобы ставились более свежие версии, чем в самом дистрибе, надо отразить это:

# Install gstreamer python bindings and plugins needed for mss.
# Using versions in names forces installation of rpms with specified versions.
gstreamer-0.10.35-SS.2
gstreamer-python-0.10.22-SS.2
# plugins-good for reading id3tags
gstreamer-plugins-good-0.10.30-SS.2
# plugins-ugly for playing mp3.
gstreamer-plugins-ugly-0.10.18-SS.2

Ну и всякие опциональные полезности, которые ставятся из дополнительно созданного репозитория:

# Install munin-node for monitoring.
munin-node
# Install ntfs utils. They're quite usable in our windoze world.
ntfs-3g
# Install lshw. It would be helpful for inventory datatbase automatization.
lshw
%end

Всё, с пакетами закончили. Теперь установка переходит в завершающую стадию – %post секцию. О ней в следующей части.

Share

Кривой стартер. Интерактивность.

This entry is part [part not set] of 5 in the series kickstart

Мне была нужна возможность ввода дополнительной информации при установке. Долго бился и искал решение, но всё же нашёл. Довольно удобное и элегантное. Для решения подобных задач можно использовать секцию %pre. Скрипты из этой секции выполняются ДО запуска установки Linux на жёсткий диск.

%pre
mkdir /tmp/flash
mount /dev/sda4 /tmp/flash

Монтирую флешку в /tmp, так как на момент запуска %pre к ней ещё нет доступа. Манёвр нужен для разделения kickstart на файлы. В дополнительных файлах отдельно прописаны секции %packages и %post, чтобы не делать один большой километровый конфиг.


chvt 6
exec /dev/tty6 2>/dev/tty6

А вот это тот код, который позволяет добавить кастомной интерактивности в процесс установки. Я переключаюсь на шестой виртуальный терминал и перенаправляю на него stdin, stdout и stderr.
# Read MAC address and hostname from stdin.
echo "-- MAC configuration --"
mac=ifconfig eth0 | awk '/HWaddr/{print $5}'
echo -n "Current MAC address is $mac ( enter alternative MAC or press return ): "
read _altmac
# Convert MAC to uppercase as in ifconfig output.
altmac=echo $_altmac | awk '{print toupper($0)}'

[ -n “$altmac” ] && mac=$altmac
echo “MAC was set to $mac”
# Store variable in temporary file. It will be used in %post section.
echo “$mac” > /tmp/mac.txt
Запрашиваю MAC-адрес, который будет использоваться в роли ключа шифрования. Да, я знаю, это абсольютно не безопасно, но такой ключ шифрования – банальная защита от дурака.
Так как в выводе ifconfig MAC-адрес идёт в верхнем регистре, то я автоматом конвертирую введённую информацию в верхний регистр. Если не вводить MAC, то будет использоваться текущий MAC интерфейса eth0. Значение сохраняю в /tmp для дальнейшего использования.

echo "-- Hostanme configuration --"
echo -n "Enter hostname: "
read _host
# Store hostname in lower case. Upper case breaks at least munin-node.
host=echo $_host | awk '{print tolower($0)}'

# Store variable in temporary file. It will be used later in %post section.
echo “Hostname was set to $host”
echo “$host” > /tmp/hostname.txt
Дабы долго не тыркаться в сетевых настройках инсталлятора, я имя машины буду задавать так же скриптом. Плюс проверка чтобы имя было в нижнем регистре. Напирмер munin не опрашивает свои ноды, у которых имена содержат символы в верхнем регистре.

sleep 5
Даю возможность в течение пяти секунд созерцать содеянное и….
chvt 1
exec /dev/tty1 2> /dev/tty1
%end

… переключаюсь обратно на первую консоль, в которй запущенная anaconda приступает к дальнейшей работе.

%include /tmp/flash/ks/packages.cfg
%include /tmp/flash/ks/post.cfg

Вот для этого момента я монтировал флешку в /tmp/flash. Про %include с локального носителя в документации, ессно, ничего толком не написано.

Предварительный этап закончен, больше никаких вопросов установщик не задаст (если только на жёстком диске не было до этого RAID, или если жёсткий диск только из упаковки извлечён).
Можно идти кури^Wпить чай, пока создаются разделы, устанавливаются пакеты и шуршат скрипты из секции %post. Про пакеты писать особо нечего, хотя один нюанс есть. Наибольший интерес представляет секция %post, о которой речь пойдёт через главу.

Share

Кривой стартер. Начало.

This entry is part [part not set] of 5 in the series kickstart

В связи с новой работой возникла необходимость автоматизировать установку Linux на x86 железо. Из всего зоопарка пингвинов выбрал Scientific Linux, как наиболее мне привычный (уже имел с ним дело). Плюс SL является основным инструментом моего друга при решении большинства задач, так что будет к кому обратиться с вопросом, если что.
Плюсы, они же и минусы SL да и вообще всех RHEL – их стабильнось. Они не прикручивают всякие новомодные финтифлюшки тоннами и развиваются довольно планомерно, так что SL не сильно отличается от ASP Linux десятилетней давности :). Хотя эта стабильность оборачивается, как я написал, и минусами – в RHEL-based дистрибутивах большинство софта настолько протухшее… Сразу оговорюсь, что я не гонюсь слепо за версией программ. Но в ходе создания установочной флешки выяснил, что в SL (и RHEL) сидит довольно древняя версия gstreamer, у которой серьёзные проблемы с утечками памяти. Убил кучу времени на “отлов” причины. В итоге решил эту проблему сборкой собственных пакетов с более свежей версией gstreamer’a.
Ладно, буду последователен.
В красношапочных дистрибутивах есть такая вещь как kickstart, которая позволяет подготовить файл с ответами на вопросы инсталлятора и автоматизировать установку частично или полностью.
Моей задачей было сделать автономную и максимально автоматизированную установку. Под автономностью я подразумеваю отсутствие доступа к сети, только установочная флешка и минимальное количество вопросов, задаваемое установщиком.
Для моих задач хватает флешки на 8GiB. Чтобы её создать не заморачиваясь с dd и прочими юниксовыми утилитами, я, по совету друга, возпользовался UltraISO и её возможностью писать ISO образы на флешки. Причём она не просто пишет, но ещё и подсовывает корректный вайл syslinux.cfg Для этого надо в UltraISO открыть образ SL-64-i386-2013-03-18-boot.iso (т.е. минимальный загрузочный образ) и через меню выбрать запись образа диска. В роли destination выбираем флешку. Через энсколько минут получается флешка, с которой уже можно загрузиться и попасть в инсталлятор anaconda.
Теперь можно переходить к самому кикстарту. Шаблон этого файла можно получить сделав пробную установку. По окончании установки в домашней директории пользователя root появится файл anaconda-ks.cfg, который можно будет дорабатывать напильником. Я приведу выдержки из уже готового файла. Краткие комментарии мною уже сделаны в самом файле, так что более подробно буду комментировать только отдельные моменты.

install

# Force using textmode install. Why anyone will need GUI when smoking?
# But even in this case one may need more than 384M of RAM to run install.
text

# Tell installer where ISO image is.
harddrive --partition=sda4 --dir=/

Последней строчкой я указываю инсталлятору место нахождения DVD образа SL-64-i386-2013-03-18-Install-DVD.iso. Этот образ отличается от boot.iso тем, что содержит репозитории с пакетами. В моём случае этот путь указывает инсталлатору на то, что установочный образ находится в корне раздела sda4. sda4 – это сама флешка. Т.е. установочный образ надо скопировать в корень флешки.


# No russian in console!!! Learn to read, write and understand documentation in English.
lang en_US.UTF-8
keyboard us

# Configure interface to use DHCP by default.
network --onboot=yes --bootproto=dhcp --noipv6

# Do you want to know how it looks like in palintext? ;)
rootpw --iscrypted BLAH_BLAH_BLAH

В шифрованном виде пароль, естественно, выглядит иначе ;)

# Open SSH and munin-node by default.
firewall --service=ssh --port=4949

Перечисляю порты, которые по умолчанию будут открыты в iptables. Можно указывать именами сервисов или номером порта.

# Disable SElinux. It's evil in most cases.
selinux --disabled

SELinux я готовить не умею и воевать с ним не хочу, отключаю.

# Add reboot=bios fix for Acer netbooks.
bootloader --location=mbr --driveorder=sdb,sda --append="crashkernel=auto rhgb quiet reboot=bios"

На Acer Apire One вылезла проблема – при перезагрузке они висли. Помогало только нажатие на кнопку питания. Т.к. наше оборудование должно быть максимально автономным, то эту проблему надо было решить. Покопавшись на форумах узнал, что для решения проблемы надо указать загрузчику дополнительный параметр reboot=bios.

# Clear all existing partitions on destiation disk.
clearpart --all --drives=sdb

При загрузке с флешки ядро определяет флешку как диск sda, а жёсткий диск – как sdb. Соответственно жёсткий диск я предварительно очищаю от существующих разделов.

# Don't touch our installation usb stick.
part None --fstype=efi --label="Scientific" --onpart=sda4 --noformat

Anaconda автоматом создала строчку, предотвращающую изменеия на флешке при установке. Я, естественно, решил её оставить.

# Create partitions. Set --asprimary to prevent creating extended partition.
part /boot --asprimary --fstype=ext4 --size=100
part swap --asprimary --size=256
part / --asprimary --fstype=ext4 --size=2000
# We should create this partition for further use as crypto partition.
# I can't find a way to create it without formatting.
part /var/lib/mss --asprimary --fstype=ext4 --grow --size=1024

В моём случае нужны четыре раздела – /boot, swap, / и раздел с данными /var/lib/mss. Чтобы при установке не плодились ненужные мне extended разделы, я для каждого раздела указал параметр --asprimary. Раздел /var/lib/mss в пост-инсталляционном скрипте будет сделан шифрованым. Создаю я его штаными средствами чтобы потом не развлекаться со скриптованием для fdisk. Не делаю его шифрованым штаными средствами, т.к. ключом шифрования будет являться файл с MAC-адресом и автоматизацию этого процесса так же удобнее делать в %post секции.

# Configure list of services.
services --disabled pppoe-server,mdmonitor,ip6tables,kdump
# Enable autofs for automounting flash drives with updates.
# Enable ntpd so machine can obtain correct time from NTP server if Internet connection is available.
# Enable munin-node for monitoring machines with Internet access.
services --enabled autofs,ntpd,munin-node

Тут всё понятно. Отключаю лишнее, добавляю нужное. Через services --enabled добавить можно только сервисы из базового дистрибутива или из дополнительных репозиториев. Я писал init.d скрипт для собственной программы и его добавлял уже в %post скрипте.

# Add local repos for extra packages (i.e. munin-node and gstreamer-plugins-ugly).
repo --name=SSextras --baseurl=file:///mnt/isodir/extras
repo --name=SSgst --baseurl=file:///mnt/isodir/gst

Методом тыка выяснил, как же нативно добраться до флешки во время установки. Оказалось, что инсталлятор её монтирует в /mnt/isodir. Тут я добавил два репозитория с дополнительными пакетами, которых нет в базовом дистрибутиве.
Чтобы директорию с пакетами сделать репозиторием, надо натравить на неё программу createrepo – она создаст всю необходимую структуру, понятную пакетному менеджеру. Прога есть в родном репозитории SL.

Дальше начинается более интересная часть, на которую я потратил существенное количество сил и времени. Данная информация, по большей части, была почерпнута из форумов. В официальном руководстве по kickstart’у ничего полезного про предустановочные скрипты не пишут. Результаты изысканий в следующей части.

Share

Linux во всей красе

Как же меня всё-таки умиляют подобные развлечения в линуксе :) При перезагрузке сетёвки меняются местами, гыгы. Я ещё могу понять, когда при обновлении RHEL с 5 на 6 он в обратном порядке просканировал шину PCI и, следовательно, в обратном порядке пронумеровал интерфейсы… Но при перезагрузке :)))

Share

apcupsd и несколько UPS

Иногда возникает необходимость управлять несколькими UPS на одном сервере даже когда есть несколько серверов и все они запитаны от тех же бесперебойников. Когда-то давно на сервере под RHEL5 я уже настраивал мониторнг нескольких UPS через apcupsd. Так как времена RHEL5 давно минули, то аналогичную конфигурацию я настроил на более современном RHEL6 в виде Scientific Linux 6.4 и apcupsd-3.14.10, последней достуной версии из сторонних пакетов на текущий момент.
Имеем три бесперебойника: Smart-UPS 3000 RM XL, Smart-UPS SC1500 и Smart-UPS SMC1500I-2U.
3000 и SMC подключены через “стандартный” USB кабель, а к SC1500 в комплекте шли кабели RS232-RS232 и RS232-USB, который при проверке оказался обычным Prolific 2303 usb2serial. SC1500 была подключена через usb2serial кабель.
Основной фокус при использовании нескольких бесперебойников заключается в указании apcupsd конфига под конкретную железку. Чтобы было нагляднее, я стандартный apcupsd.conf скопировал в три конфига соответственно: apcupsd-rm3000.conf, apcupsd-cs1500.conf и apcupsd-smc1500.conf.
Из очевидных вещей в каждом каждом конфиге указываем соответствующие UPSNAME исходя из имени бесперебойника. А вот с UPSCABLE, UPSTYPE и DEVICE предстоит заняться более внимательно. С SC1500 всё просто – надо прописать обычные для подключения по последовательному порту параметры UPSCABLE smart и UPSTYPE apcsmart и DEVICE /dev/ttyUSB0. С USB подключением одного ИБП тоже всё просто – параметр DEVICE нужно закоментировать или значение оставить пустым и apcupsd сама найдёт бесперебойник. В случае с двумя ИБП параметр DEVICE надо будет использовать, чтобы “объяснить” apcupsd где какой ИБП.
dmesg в Linux всегда для меня выглядел хаосом (в сравнении с *BSD), так что “поиск” нужного устройства делался распространённым “научным” методом.
Вот что пишет ядро:
# dmesg|grep generic-usb
generic-usb 0003:0557:2221.0001: input,hidraw0: USB HID v1.00 Mouse [Winbond Electronics Corp Hermon USB hidmouse Device] on usb-0000:00:1a.0-1.2/input0
generic-usb 0003:0557:2221.0002: input,hidraw1: USB HID v1.00 Keyboard [Winbond Electronics Corp Hermon USB hidmouse Device] on usb-0000:00:1a.0-1.2/input1
generic-usb 0003:051D:0002.0003: hiddev96,hidraw2: USB HID v1.10 Device [American Power Conversion Smart-UPS 3000 RM XL FW:691.19.I USB FW:7.4] on usb-0000:00:1d.0-1.5/input0
generic-usb 0003:051D:0003.0004: hiddev97,hidraw3: USB HID v1.00 Device [American Power Conversion Smart-UPS C 1500 FW:UPS 09.7 / ID=1005] on usb-0000:00:1d.0-1.4/input0

Итого на сервере 4 generic-usb устройства – мышь, клавиатура и два бесперебойника. Про оба бесперебойника ядро пишет hiddev9?,hidraw?.
Устройство /dev/hiddevXX можно не искать – его нет. Зато есть /dev/usb/hiddev?. Найти взаимосвязь между /dev/usb/hiddev? и hiddev??,hidraw? я так и не смог. Продолжая использовать “научный” метод тыка, в конфигурационные файлы для ИБП, подключенных по USB добавил DEVICE /dev/usb/hiddev?.
Помимо этого все три конфигурационных файла отличаются портом, NISPORT на котором висит демон, чтобы можно было получать статус с определённой UPS. Дефолтовый NISIP 0.0.0.0 (привет безопасности по умолчанию) поменял на 127.0.0.1, так как мониторинг apcupsd будет вестись локально. Подправил пути на файлы сообщений и статуса (EVENTSFILE и STATFILE), чтобы у каждого запущенного демона был свой собственный набор файлов.
Окинем взором различие в конфигурационных файлах:
diff3 apcupsd-smc1500.conf apcupsd-cs1500.conf apcupsd-rm3000.conf
====
1:15c
UPSNAME CS1500
2:15c
UPSNAME SMC1500I-2U
3:15c
UPSNAME RM3000
====
1:29c
UPSCABLE smart
2:29c
UPSCABLE usb
3:29c
UPSCABLE usb
====
1:79,80c
UPSTYPE apcsmart
DEVICE /dev/ttyUSB0
2:79,80c
UPSTYPE usb
DEVICE /dev/usb/hiddev1
3:79,80c
UPSTYPE usb
DEVICE /dev/usb/hiddev0
====
1:202c
NISPORT 3552
2:202c
NISPORT 3553
3:202c
NISPORT 3551
====
1:206c
EVENTSFILE /var/log/apcupsd-cs1500.events
2:206c
EVENTSFILE /var/log/apcupsd-smc1500.events
3:206c
EVENTSFILE /var/log/apcupsd-rm3000.events
====
1:241c
STATFILE /var/log/apcupsd-cs1500.status
2:241c
STATFILE /var/log/apcupsd-smc1500.status
3:241c
STATFILE /var/log/apcupsd-rm3000.status

Для мониторинга вручную всё готово. Достаточно запустить /sbin/apcupsd -f /etc/apcupsd/config_name.conf. Для проверки работоспособности запустил apcaccess:
[root@mail apcupsd]# apcaccess
APC : 001,043,1074
DATE : 2014-02-04 14:20:12 +0400
HOSTNAME : **********
VERSION : 3.14.10 (13 September 2011) redhat
UPSNAME : RM3000
CABLE : USB Cable
DRIVER : USB UPS Driver
UPSMODE : Stand Alone
STARTTIME: 2014-02-03 17:25:12 +0400
MODEL : Smart-UPS 3000 RM XL
STATUS : ONLINE
LINEV : 233.2 Volts
LOADPCT : 0.0 Percent Load Capacity
BCHARGE : 100.0 Percent
TIMELEFT : 137.0 Minutes
MBATTCHG : 5 Percent
MINTIMEL : 3 Minutes
MAXTIME : 0 Seconds
OUTPUTV : 233.2 Volts
SENSE : High
DWAKE : -01 Seconds
DSHUTD : 090 Seconds
LOTRANS : 208.0 Volts
HITRANS : 253.0 Volts
RETPCT : 000.0 Percent
ITEMP : 24.7 C Internal
ALARMDEL : 30 seconds
BATTV : 55.1 Volts
LINEFREQ : 50.0 Hz
LASTXFER : Automatic or explicit self test
NUMXFERS : 0
TONBATT : 0 seconds
CUMONBATT: 0 seconds
XOFFBATT : N/A
SELFTEST : NO
STESTI : 14 days
STATFLAG : 0x07000008 Status Flag
MANDATE : 2010-12-17
SERIALNO : XXXXXXXXXXX
BATTDATE : 2010-12-17
NOMOUTV : 230 Volts
NOMBATTV : 48.0 Volts
FIRMWARE : 691.19.I USB FW:7.4
END APC : 2014-02-04 14:20:56 +0400

В данном случае apcaccess выводит информацию, которую по умолчанию берёт на 127.0.0.1 и стандартном порту 3551. Для получения информации о двух других бесперебойниках надо указать соответствующие порты (3552 и 3553):
[root@mail apcupsd]# apcaccess status 127.0.0.1:3552
APC : 001,048,1181
DATE : 2014-02-04 14:23:51 +0400
HOSTNAME : **********
VERSION : 3.14.10 (13 September 2011) redhat
UPSNAME : CS1500
CABLE : Custom Cable Smart
DRIVER : APC Smart UPS (any)
UPSMODE : Stand Alone
STARTTIME: 2014-02-03 12:36:35 +0400
MODEL : Smart-UPS SC1500
STATUS : ONLINE
LINEV : 230.0 Volts
LOADPCT : 9.1 Percent Load Capacity
BCHARGE : 100.0 Percent
TIMELEFT : 121.0 Minutes
MBATTCHG : 5 Percent
MINTIMEL : 3 Minutes
MAXTIME : 0 Seconds
MAXLINEV : 230.0 Volts
MINLINEV : 230.0 Volts
OUTPUTV : 230.0 Volts
SENSE : High
DWAKE : 000 Seconds
DSHUTD : 060 Seconds
DLOWBATT : 02 Minutes
LOTRANS : 208.0 Volts
HITRANS : 253.0 Volts
RETPCT : 000.0 Percent
ALARMDEL : 5 seconds
BATTV : 26.9 Volts
LINEFREQ : 50.0 Hz
LASTXFER : Line voltage notch or spike
NUMXFERS : 0
TONBATT : 0 seconds
CUMONBATT: 0 seconds
XOFFBATT : N/A
SELFTEST : NO
STESTI : 336
STATFLAG : 0x07000008 Status Flag
REG1 : 0x00 Register 1
REG2 : 0x00 Register 2
REG3 : 0x00 Register 3
MANDATE : 05/31/12
SERIALNO : XXXXXXXXXXX
BATTDATE : 05/31/12
NOMOUTV : 230 Volts
NOMBATTV : 24.0 Volts
FIRMWARE : 738.3.I
END APC : 2014-02-04 14:24:07 +0400

Осталось самое весёлое – подправить rc.d скрипты чтобы все три демона стартовали автоматически при запуске системы. Идём в /etc/rc.d/init.d/, где объектом изменений будет скрипт apcupsd. Его так же копирую, в соответствии с вышеописанными именами файлов конфигурации: apcupsd-rm3000, apcupsd-smc1500 и apcupsd-cs1500, а затем редактирую новые стартовые скрипты с учётом имён файлов конфигурации и параметров в них указанных. В скриптах интересуют значения APCPID, указание корректных флагов запуска apcupsd, изменение поведения killproc, чтобы он не убивал одним махом все запущенные процессы apcupsd и имена lock-файлов. Это что касается запуска демона. Для проверки статуса необходимо указать соответствующий демону NISPORT в параметрах запуска apcaccess.
После всех необходимых изменений в стартовых скриптах, эти стартовые скрипты надо “зарегистрировать”, а стандартный скрипт apcupsd наоборот – отключить. Для этого имена новых скриптов передаём в качестве параметра chkconfig:
chkconfig --add apcupsd-rm3000
и отключаем стандартный скрипт:
chkconfig --del apcupsd
Теперь в ntsysv доступны новые скрипты и нет стандартного. Ставим на них * и радуемся результатам содеянного:
[root@mail apcupsd]# service apcupsd-rm3000 start
Starting UPS monitoring: [ OK ]

[root@mail apcupsd]# ps ax|grep apc
5750 ? Ssl 0:00 /sbin/apcupsd -f /etc/apcupsd/apcupsd-rm3000.conf -P /var/run/apcupsd-rm3000.pid
5781 ? Ssl 0:00 /sbin/apcupsd -f /etc/apcupsd/apcupsd-smc1500.conf -P /var/run/apcupsd-cs1500a.pid
5810 ? Ssl 0:00 /sbin/apcupsd -f /etc/apcupsd/apcupsd-cs1500.conf -P /var/run/apcupsd-cs1500b.pid
5851 pts/5 S+ 0:00 grep apc

Целиком файлы конфигов я выкладывать не буду ни в этот раз, ни в последующие, дабы предотвратить бездумный copy-paste. Для всех файлов максимум будут diff относительно оригинального файла.

Share