И вот это долгооткладываемое время настало – пришлось апгрейдить сервер под управлением ОС Oracle Linux 6.5 до 7й версии (на данный момент последняя 7.9).
Сначала необходимо обновить систему до последней версии (репозиторий public yum latest должен быть активным):
yum upgrade -y
В моём случае я получал ошибку [Errno 14] problem making ssl connection при попытке что-либо обновить или установить с репозитория public-yum.oracle.com наподобии этой:
Это произошло из-за того, что пакет openssl в релизе 6.5, который был установлен на сервере, был старой версии и не поддерживает более усиленное шифрование, которое используется в репозитории. Проблему эту решил тем, что подмонтировал диск Oracle Linux 6.10 как репозиторий и обновил пакет opensssl с диска. После этого yum стал нормально заходить на интенет-репозиторий. Образ можно скачать тут: https://edelivery.oracle.com/osdc/faces/SoftwareDelivery
Чтобы сделать локальный диск репозиторием, нужно его примонтировать и добавить repo-файл в /etc/yum.repos.d/local.repo
mount /dev/cdrom /mnt/cdrom
[InstallMedia]
name=DVD for Red Hat Enterprise Linux 7.9 Server
metadata_expire=-1
gpgcheck=1
enabled=1
baseurl=file:///mnt/cdrom/
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release
Далее необходимо установить необходимые пакеты, для чего необходимо активировать репозиторий Addons в конфиг-файле по пути /etc/yum.repos.d/public-yum-ol6.repo (название файла может отличаться):
[public_ol6_addons]
name=Oracle Linux $releasever Add ons ($basearch)
baseurl=https://yum.oracle.com/repo/OracleLinux/OL6/addons/$basearch/
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-oracle
gpgcheck=1
enabled=1
Изменяем enabled на 1, сохраняем, делаем снова yum update. Если понадобиться, то и yum clean all, затем ставим пакеты:
Для проблемных пакетов можно применять опцию –skip-broken. После этого запускаем утилиту проверки совместимости обновления и ждём окончания её работы:
preupg
Результат её работы будет лежать в виде HTML-оформленного отчета в /root/preupgrade/result.html
Необходимо внимательно просмотреть этот отчёт, в нём будут указаны все проблемы, которые были найдены, рабитые по категориям. Рекомендуется обратить внимание и исправить все проблемы категории Error, Needs Action, Needs Inspection. Некоторые проблемы потребуют проверки после обновления, потому сохраните себе отчёт.
Можно перезапускать проверку сколько угодно раз после применения исправлений, результаты проверок будут лежать в папке /root/preupgrade-results
В моём случае ошибка была только одна – система была настроениа на загрузку EFI и обновление вроде как не поддерживается. Оно поддерживается на самом деле, но нужно быть готовым к тому, что система может не загрузиться сразу. Поэтому в случае, если система настроена на загрузку как UEFI/EFI, а не BIOS/Legacy, то обязательно убедитесь, что у вас есть загрузочный диск Oracle Linux 7 и вы можете с него загрузиться. Это также может быть образ, смонтированный как Vertual media в случае брендовых серверов Dell, IBM, HP.
Запускаем утилиту апгрейда релиза с ключем –force – чтобы обновиться несмотря на ошибку с UEFI, используя заранее скачанный на сервер образ:
Дожидаемся окончания обновления. В моём случае после второй перезагрузки сервер не загрузился. Как я выяснил, в Oracle Linux el6 используется загрузчик grub, а в el7 – grub2. Обновление происходит автоматически для типа загрузки BIOS/Legacy, а вот для UEFI скрипт обновления сломал старый загрузчик, но не установил корректно новый – и система осталась без bootloader’а. Совсем. Даже нет возможности зайти в консоль восстановления.
Вот здесь нам и пригодится скачанный образ/диск Oracle Linux 7.9. Загружаемся с диска и в стартовом меню выбираем Troubleshooting -> Rescue installed system. Ниже показан пример только в случае с CentOS:
Нажимаем Enter и входим в установленную систему с помощью chroot:
chroot /mnt/sysimage
Теперь монтируем установочный диск как репозиторий (если есть доступ в интернет – не нужно), как было описано выше, и удаляем загрузчик совсем чтобы избежать конфликта версий зависимостей (как было у меня):
К сожалению, в сети интернет множество мамкиных хакеров, пытающихся подобрать логин без пароля или иным способом брутфорсить сервера IP телефонии, имеющие доступ из интернет. Отсеять большинство из них помогает смена внешнего порта со стандартного 5060 на какой-либо другой. Но всё же брутфорс иногда возникает, что немного раздражает и представляет призрачную угрозу.
Оговорюсь, что здесь рассмотрен вариант конфигурации довольно старых версий Asterisk – 1.8 и ниже. Для настройки Asterisk начиная с версии 10 и новее с помощью отдельного файла логирования security, советую посмотреть ссылку [1].
Для блокировки подбора пользователей/паролей для различных сервисов существует демон fail2ban, который после указанного количества ошибочных попыток добавляет правило в iptables на блокировку доступа к серверу вообще для IP адреса нарушителя (на указанное время).
Перед началом настройки необходимо установить iptables и fail2ban, если их ещё нет. Также необходимо настроить iptables так, чтобы был доступ к серверу asterisk извне – отключить или добавить правило для порта asterisk. Если вы читаете эту статью, то у вас уже всё должно быть окей с этим.
Настройка ведения логов asterisk
В первую очередь имеет смысл настроить ведение логов asterisk, чтобы информация сразу же начала собираться в нужном нам формате и виде. Для этого в каталоге конфигурации asterisk (по умолчанию это /etc/asterisk) найдите файл logger.conf и раскомментируйте (уберите точку с запятой в начале строки):
dateformat=%F %T ; ISO 8601 date format
Это нужно для того, чтобы asterisk писал в логи дату в правильном формате: год-месяц-день часы:минуты:секунды
После этого перезапускаем сервис asterisk:
service asterisk restart
Настройка правил фильтрации
Теперь нам необходимо создать фильтр, который будет извлекать из общего потока сообщений астериска потенциально опасные события (неверный логин/пароль, попытка входа с неразрешенного IP адреса, и т.д. и т.п.). При этом нам необходимо не только обнаруживать такие потенциально опасные события, но и вычленять оттуда IP адрес, с которого было выполнено действие. То есть мы не просто ищем определенные строки в файлах событий астериска, а настраиваем правила фильтрации. Правила фильтрации можно прописать в файле /etc/fail2ban/filter.d/asterisk.conf
Вот образец содержимого этого файла:
# Fail2Ban configuration file
#
#
# $Revision: 250 $
#
[INCLUDES]
# Read common prefixes. If any customizations available -- read them from
# common.local
#before = common.conf
[Definition]
#_daemon = asterisk
# Option: failregex
# Notes.: regex to match the password failures messages in the logfile. The
# host must be matched by a group named "host". The tag "<HOST>" can
# be used for standard IP/hostname matching and is only an alias for
# (?:::f{4,6}:)?(?P<host>\S+)
# Values: TEXT
#
# Asterisk 1.8 uses Host:Port format which is reflected here
failregex = NOTICE.* .*: Registration from '.*' failed for '<HOST>:.*' - Wrong password
NOTICE.* .*: Registration from '.*' failed for '<HOST>:.*' - No matching peer found
NOTICE.* .*: Registration from '.*' failed for '<HOST>:.*' - Username/auth name mismatch
NOTICE.* .*: Registration from '.*' failed for '<HOST>:.*' - Device does not match ACL
NOTICE.* .*: Registration from '.*' failed for '<HOST>:.*' - Not a local domain
NOTICE.* .*: Registration from '.*' failed for '<HOST>:.*' - Peer is not supposed to register
NOTICE.* .*: Registration from '.*' failed for '<HOST>:.*' - ACL error (permit/deny)
NOTICE.* .*: Registration from '.*' failed for '<HOST>' - Wrong password
NOTICE.* .*: Registration from '.*' failed for '<HOST>' - No matching peer found
NOTICE.* .*: Registration from '.*' failed for '<HOST>' - Username/auth name mismatch
NOTICE.* .*: Registration from '.*' failed for '<HOST>' - Device does not match ACL
NOTICE.* .*: Registration from '.*' failed for '<HOST>' - Not a local domain
NOTICE.* .*: Registration from '.*' failed for '<HOST>' - Peer is not supposed to register
NOTICE.* .*: Registration from '.*' failed for '<HOST>' - ACL error (permit/deny)
NOTICE.* .*: Registration from '\".*\".*' failed for '<HOST>:.*' - No matching peer found
NOTICE.* .*: Registration from '\".*\".*' failed for '<HOST>:.*' - Wrong password
NOTICE.* .*: No registration for peer '.*' \(from <HOST>\)
NOTICE.* .*: Host <HOST> failed MD5 authentication for '.*' (.*)
NOTICE.* .*: Failed to authenticate user .*@<HOST>.*
NOTICE.* <HOST> failed to authenticate as '.*'$
NOTICE.* .*: Sending fake auth rejection for device .*\<sip:.*\@<HOST>\>;tag=.*
NOTICE.* .*: <HOST> tried to authenticate with nonexistent user '.*'
VERBOSE.*SIP/<HOST>-.*Received incoming SIP connection from unknown peer
# Option: ignoreregex
# Notes.: regex to ignore. If this regex matches, the line is ignored.
# Values: TEXT
#
ignoreregex =
В asterisk версии 1.4 и более ранних используются строки типа
“… failed for ” …”
а в asterisk 1.8 и выше – строки
“… failed for ‘:.*’ …”
поскольку начиная с версии asterisk 1.8 в логах появилась информация о номере порта, которой нет в asterisk 1.4. Приведенный выше вариант учитывает как старые, так и новые версии asterisk, так что нет необходимости в нем что-либо менять.
Настройка изоляторов (jails) для fail2ban
Теперь нам необходимо создать описания так называемых “изоляторов” (jails) для fail2ban, т.е. “привязать” наши фильтры к fail2ban: объяснить, в каких файлах эти строки искать, и что потом делать.
Для этого откройте файл /etc/fail2ban/jail.conf
Убедитесь, что нет (или не включено) других правил, связанных с asterisk! Для этого достаточно сделать поиск по файлу по имени “asterisk” (без кавычек) и убедиться, что если такие правила есть, для каждого из них свойство enabled установлено в false или закомментировать решетками все строчки с правилами:
enabled = false
В тексте правила нужно будет указать путь к логу asterisk. По умолчанию в астериске основной файл логов называется messages, но (например) в FreePBX это будет файл под названием full (как называется файл у Вас – см. настройки астериска в файле logger.conf).
Добавляем текст правила в конец файла:
[asterisk-iptables]
# Enable the rule:
enabled = true
# Name of filter used is asterisk in folder /etc/fail2ban/filter.d:
filter = asterisk
# Which asterisk file is used to search:
logpath = /var/log/asterisk/messages
# Max retries allowed:
maxretry = 5
# Action period of time in seconds:
bantime = 86400
# Period of time to search logpath for occurancies:
findtime = 3600
# What to do if there are more occurancies during findtime more than maxretry -
# Ban client's IP address using iptables and send report to admin's e-mail:
action = iptables-allports[name=ASTERISK, protocol=all]
sendmail-whois[name=ASTERISK, dest=admin@yourdomain.com, sender=asterisk@yourdomain.com]
# Whitelist:
#ignoreip = 192.168.1.0/24
Перезапускаем fail2ban:
service fail2ban restart
Для проверки, что fail2ban запущен успешно и правило загружено, выполните следующую команду, которая показывает статус нашего нового jail:
fail2ban-client status asterisk-iptables
В случае, если Вы только что установили fail2ban / iptables, не забудьте убедиться, что они настроены у Вас стартовать автоматически при загрузке системы!
Проверка работы fail2ban
Теперь важный этап – проверить, что всё работает так, как задумано и нигде нет ошибки. Для этого нужно использовать третий компьютер, кроме сервера asterisk и вашего, с которого вы заходите. Чтобы не забанить самого себя.
Последовательность действий для проверки работы связки fail2ban + iptables:
Убедитесь, что у Вас настроен запуск iptables и fail2ban при старте компьютера.
Запустите SIP-клиент (обязательно не с самого сервера asterisk или того, с которого вы на него зашли удалённо, а с другого компьютера!), и указав неверное имя пользователя для авторизации (IP адрес или доменное имя сервера asterisk должно быть верным), попробуйте авторизоваться более 5 раз (как указано в параметре maxretry.
В качестве тестового sip клиента можно использовать программу sipsak, которая работает из командной строки Linux:
Быстрая заметка. Иногда случается что дисковая I/O подсистема чем-то сильно нагружена и не понятно, каким именно процессом. В определении виновника может помочь следующая команда:
top -b -n 1 | awk '{if (NR <=7) print; else if ($8 == "D") {print; count++} } END {print "Total status D (I/O wait probably): "count}' > topsave.txt
Все команда нужно указывать по спецификации FTP протокола, например такой.
Осовные команды: RETR – получить файл с FTP в переменную или по хендлеру записать в локальный файл; LIST – показать список файлов/директорий в указанной или текущей по-умолчанию; NLST – то же, что и LIST, но возвращает только имена файлов/директорий; STOR – загрузить с презаписью файл на FTP-сервер; и другие
Для работы FTP_TLS нужен пайтон 2.7+, если у вас только 2.6, то придётся сделать одно из следующего: 1. Доустановить пайтон 2.7, например как описано здесь для Oracle Linux 6:
Редактируем /etc/yum.repos.d/public-yum-ol6.repo и убеждаемся, что enabled=1 в следующем параграфе:
[ol6_software_collections]
name=Software Collection Library release 3.0 packages for Oracle Linux 6 (x86_64)
baseurl=http://yum.oracle.com/repo/OracleLinux/OL6/SoftwareCollections/x86_64/
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-oracle
gpgcheck=1
enabled=1
Если при запуске скрипта по cron (а скорее всего так и будет) выбивает ошибку вида:
error while loading shared libraries: libpython2.7.so.1.0: cannot open shared object file: No such file or directory
То необходимо добавить путь к библиотеке в /etc/ld.so.conf и запустить команду ldconfig, которая сама всё пропишет.
или
2. Cкачать дистрибутив пайтона 2.7 отсюда и вытащить фал ftplib.py и положить его в папку со скриптом (если скрипт запускается по cron, то это может не сработать):
wget http://www.python.org/ftp/python/2.7.1/Python-2.7.1.tgz
tar -zxvf Python-2.7.1.tgz Python-2.7.1/Lib/ftplib.py
cp Python-2.7.1/Lib/ftplib.py /path_to_script/
или
3. Заходить на FTPS вызывая bash команды например lftp с помощью модуля subprocess.
Если вы несколько раз неправильно пытались подключиться к серверу Linux, где настроен fail2ban, то вы будете занесены в черный список и не сможете подключиться заданное на сервере количество времени или вообще навсегда.
Чтобы разбанить IP адрес, нужно на сервере выполнить следующие команды.
Вначале посмотреть цепочки правил (jail):
fail2ban-client status
Результат будет что-то вроде такого:
Status |- Number of jail: 3 `- Jail list: apache, ssh, apache-modsecurity
Затем в разбаниваем IP в нужной “клетке” (цепочке правил):
fail2ban-client set JAILNAMEHERE unbanip IPADDRESSHERE
В старых версиях Fail2ban может не существовать команды unbanip, тогда вы будете получать ошибку вида:
Invalid command (no set action or not yet implemented)
Здесь придётся перезагрузить “клетку”, что уберёт из неё все баны:
fail2ban-client reload JAILNAMEHERE
Также можно добавить IP в список исключений чтобы он не блокировался, если вы что-то тестируете:
fail2ban-client set sasl addignoreip 198.32.110.100
Посмотреть, какие IP забанены в “клетке” можно с помощью команды: