Немного о безопасности Asterisk
Хотелось бы затронуть тему безопасности в Asterisk.
Частенько в логах можно встретить такие строки:
[2012-04-16 16:24:02] NOTICE[24403] chan_sip.c: Registration from ‘41.223.65.93<sip:300@89.189.1.178>’ failed for ‘37.75.213.83’ — Wrong password
[2012-04-16 16:24:09] NOTICE[24403] chan_sip.c: Registration from ‘41.223.65.93<sip:500@89.189.1.178>’ failed for ‘37.75.213.83’ — Wrong password
[2012-03-03 00:04:04] NOTICE[30578] chan_sip.c: Registration from ‘»password»<sip:password@89.189.1.178>’ failed for ‘46.165.193.26’ — No matching peer found
[2012-03-03 00:04:10] NOTICE[30578] chan_sip.c: Registration from ‘»nopassword»<sip:nopassword@89.189.1.178>’ failed for ‘46.165.193.26’ — No matching peer found
Ниже приведу небольшой список мероприятий которые можно сделать, чтобы избежать попадания на «бабло».
Но 100% гарантий они не дадут.
- Не разрешайте SIP аутентификацию со ВСЕХ ИП адресов. Используйте опции “permit=” и “deny=” в sip.conf как в глобальной секции, так и в параметрах пиров. Разрешайте только ожидаемые диапазоны ИП адресов. Даже если принимаете входящие «отовсюду» (через контекст [default]) не забывайте об аутентификации!
- Укажите “alwaysauthreject=yes” в глобальной секции файла sip.conf. Эта опция доступна давно (уже с версии 1.2?) но по дефолту она в “no”, что позволяет получить информацию о внутренних номерах даже при неудавшейся регистрации. Устанавливая этот паратметр в “yes” мы отправляем такой же «reject» для существующего внутреннего номера, как и в случае несуществующего. Это уменьшает возможности удалённых хакеров получить список номеров, по которым уже начинается атака по подбору паролей методом brute force.
- Используйте СЛОЖНЫЕ пароли для всех SIP пиров и юзеров. Это возможно наиболее важный шаг, который вы можете предпринять. Не используйте последовательно два одинаковых слова,разделите их хоть «1». Если бы вы видели инструменты по подбору паролей вы бы поняли смысл этой казалось бы простой рекомендации, так как такое задваивание является ничтожной помехой для современных процессоров. Используйте символы, цифры и буквы обеих регистров длиной не менее 12 знаков.
- Блокируйте доступ к порту AMI. Используйте “permit=” и “deny=” параметры в manager.conf чтобы сократить число возможных подключений только с доверенных хостов. Используйте сложные пароли минимум из 12-ти знаков в различных сочетаниях символов, цифр и букв разного регистра.
- Разрешайте только один или два одновременных вызова с каждого внутреннего SIP абонента, если возможно. В любом случае любые ограничения против мошенников являются мудрым шагом. Не допускайте разрешённым пользователям, которые имеют доступ к настройкам, хранить пароли в обозреваемом месте (например записаные снизу на телефоне).
- Делайте SIP usernames отличными от внутренних номеров. Обычно внутренний номер “1234″ соответствует SIP пиру “1234″, который имеет аналогично SIP user “1234″, это лёгкая цель для хакеров в попытке угадать аутентифицированые SIP names. Используйте МАС адреса устройств или другие комбинации известных фраз + MD5 хэширование внутреннего номера (например исполните команду “md5 -s ThePassword5000″)
- Убедитесь, что контекст [default] достаточно рационален. Не допускайте неаутентифицированным входящим соединениям попадать в любые контексты, откуда исполняются платные вызовы. Ограничивайте количество активных звонков в дефолтном контексте (используя функцию “GROUP” в качестве счётчика). Запретите неаутентифицированные звонки (если вы действительно их не хотите) установкой параметра “allowguest=no” в секции [general] файла sip.conf.
- От «засерания» логов можно использовать fail2ban. Настройку этого чуда я вынес в отдельную статью.
- Сохраняйте IP адреса для каждого SIP звонка внутри CDR
Стандартные CDR Asterisk-а не содержат IP адреса, с которого был совершён звонок. Это легко исправить. Если Вы используете cdr_addon_mysql для хранения CDR в базе данных, добавьте поле в таблицу cdr:
alter table cdr add column remote_signal_ip varchar(16) not null default ''
Теперь измените свой диалплан так, что бы cdr переменная remote_signal_ip инициализировалась перед исходящим звонком. Например, вот так:
context dialout { _X. => { Noop(); Set(CDR(remote_signal_ip)=${SIPCHANINFO(recvip)}); Dial(SIP/myprovider/${EXTEN}); } }
Вот и всё! Функция SIPCHANINFO(recvip) вернёт IP адрес, с которого клиент производит вызов, а по окончании вызова модуль cdr_addon_mysql сохранит все переменные, имена которых совпадают с названиями колонок в таблице cdr.
Сохранение IP адреса для каждого звонка открывает большой потенциал для изучения миграции клиентов по IP сетям, выявления приоритетных партнёров для пиринга IP трафиком, решения проблем с утечками паролей и много чего ещё.
Подходите к вопросу творчески: комбинируйте, изобретайте!
Не стоит сидеть, сложа руки и ждать, пока появятся проблемы. Лучше потратить немного усилий на превентивные меры, что бы обезопасить себя от форс-мажора. В вопросе безопасности, надо всегда быть на шаг впереди. Анализируйте свой трафик — каждый всплеск мг/мн трафика должен быть тщательно расследован. Не работайте по шаблонам — комбинируйте и изобретайте. Например, можно написать скрипт, который раз в месяц анализирует IP адреса из вашей таблицы cdr, и автоматически генерирует списки доступа (acess-list) для тех аккаунтов, чьи IP не менялись за прошедший месяц. Будьте креативными!