Игорь Олемской — практические заметки по системному администрированию Linux CentOS

Архив тега ‘howto’

MacOS X (iATKOS v7) на Proxmox (KVM) (перепечатка)

Комментариев нет

Встала задача поставить сабж на KVM. Ни один установочный образ хакинтошей не хотел даже загружаться с isoшника, не смотря на успешные отчеты на хабре и прочих злачных местах.

После двух дней долбления башкой об клаву поднялся образ iATKOS v7. И на обычном KVM (intel) и на Proxmox KVM (AMD).

Из особенностей подъема:

  • Видеокарта Standard VGA
  • Опции при загрузке (нажать F8 перед загрузкой): -cpus=1 -v -x -f platform=acpi idlehalt=0

По поводу последнего, я хрен знает что это значит, нашел на какой то буржуйской борде. С этими опциями поднялось, а это главное.

Отбиваем DDOS mod_evasive + firewall на CentOS (перепечатка)

Комментариев нет

Анализ DDoS можно производить конечно своими скриптами, парсить логи. Но лучше предоставить это апачевскому mod_evasive.

Ставим mod_evasive, в конфигурации пишем

DOSHashTableSize    3097
DOSPageCount        15
DOSSiteCount        15
DOSPageInterval     3
DOSSiteInterval     3
DOSBlockingPeriod   300
DOSSystemCommand    "/usr/bin/sudo /usr/bin/fwban %s"
  • DOSPageInterval – интервал для хитов определенной страницы
  • DOSSiteInterval – интервал для хитов определенного vhost
  • DOSPageCount – после этого количества хитов по определенному URI в течении интервала DOSPageInterval, айпи будет забанен
  • DOSSiteCount – после этого количества хитов по определенному vhost в течении интервала DOSSiteInterval, айпи будет забанен

Нам понадобиться скрипт для бана на уровне файрвола «/usr/bin/fwban» (вариант для Linux):

#!/bin/bash
if [ "x$1" = "x" ] ; then
    echo "USAGE: $0 IPADDR"
    exit
fi
/sbin/iptables -A BAN -s $1 -j DROP

Ему надо поставить права 755.

Так же нам понадобиться утилита sudo. Она стоит практически везде. В «visudo» закомментируем опцию:

#Defaults    requiretty

И добавим строку

apache  ALL = NOPASSWD: /usr/bin/fwban

где apache – юзер от которого работает апач.

Так же нам понадобиться цепочка BAN в iptables:

iptables -N BAN
iptables -I INPUT -j BAN

Сохраним правила файрвола

/etc/init.d/iptables save

Рестартанем апач. Теперь попробуйте уложить ваш сайт (только не со своего айпи!!!):

ab -n 1000  -c 20 http://yoursite.info/

В логах «жертвы» можно увидеть:

May  6 15:18:25 Server1 mod_evasive[26514]: Blacklisting address 1.2.3.4: possible DoS attack.

А в файрволе:

# iptables-save
---многа букав---
-A BAN -s 1.2.3.4 -j DROP
---многа букав---

Ура! No pasaran.

Да. И конечно, апач лучше бы прикрыть извне nginx’ом.

Да. И данный метод банит айпишнеги перманентно, пока не рестартанет сервер, или не будет сброшена цепочка BAN. Вот такой брутальный метод )

Предотвращение двойного запуска cron задач (перепечатка)

Комментариев нет

Администрируя высоконагруженный проект, то и дело натыкаюсь на проблему повторного запуска cron задач в то время как предыдущая задача еще не отработала.

Таким образом получается, что одни и те же cron скрипты выполняют одни и те же задачи одновременно, удваивая тем самым нагрузку. При этом они начинают выполняться медленнее, и возможна лавинообразная ситуация, когда к этим двум добавится еще и третья такая же задача. Потом четвертая, а потом все упадет вообще.

Как с этим бороться?

Вариант 1. Сложный.

Использовать в скрипте, который запускается по cron, проверку pid:

  1. Проверяем наличие pid файла с идентификатором процесса
  2. Проверяем, есть ли такой pid в памяти командой «ps -p PID»
  3. Если pid запущен, прерываем работу
  4. Иначе, пишем в pid файл свой pid и продолжаем

Однако это требует модификации скрипта.

Вариант 2. Простой.

Есть замечательная утилитка в Linux, называется flock (1). В качестве параметра, утилита принимает имя файла лока и команду для исполнения. flock ставит эксклюзивный лок на указанный файл и, при успехе, запускает указанную команду. Функционал flock не ограничивается только этой возможностью – на эту тему можно покурить соответствующий man.

Итак, у нас есть cron задача:

* * * * *   user  /usr/bin/php /some/heavy/script.php

С помощью небольшой модификации этой строки мы сможем предотвратить повторный запуск задачи во время выполнения предыдущей задачи:

* * * * *   user  /usr/bin/flock -xn /var/lock/script.lock -c '/usr/bin/php /some/heavy/script.php'

Ну собсно все.

Лечение микрофона для Skype в Linux (перепечатка)

Комментариев нет

Который раз уже натыкаюсь на пропадающий в skype микрофон под Linux. При чем все остальные приложения работают с микрофоном нормально. Вероятно это как то связано с этим глючным pulseaudio.

В общем проблема решается установкой пакета alsa-utils (Fedora). Запускаем alsamixer в терминале, выбираем Capture, жмем F6, выбираем свою звуковую карту. Включаем Mic Boost, на канале микрофона делаем левый канал на полную, а правый чуть меньше. Чуть меньше означает что левый и правый канал не должны находиться на одном уровне.

Левый канал регулируется кнопками QZ, правый CE.

Вуаля. Я не знаю почему это работает, но почему то работает. Еще помогает поиграться с галочкой «Позволить Skype автоматически подстраивать громкость» в настройках устройств Skype.

Уведомления Nagios посредством SMS (перепечатка)

Комментариев нет

Здесь пойдет речь о том как просто настроить отсылку уведомлений Nagios на SMS. Для отсылки я использовал сервис smsc.ru. Подойдет и любой другой, поддерживающий почтовый шлюз для отправки SMS.

Дальше пошли исходники и конфиги.

1. Настраиваем контакт для уведомления по SMS (contacts.cfg). График уведомлений и тип уведомлений по вкусу. В поле pager указываем мобильный номер.

define contact{
        contact_name                    admin_sms
        alias                           Admin SMS
        service_notification_period     24x7
        host_notification_period        24x7
        service_notification_options    w,u,c,r
        host_notification_options       d,r
        service_notification_commands   notify-by-custom-sms
        host_notification_commands      notify-by-custom-sms
        email                           admin@foobar.com
        pager                           +79991112233
        }

Добавляем этот контакт в соответствующую группу контактов.

2. Пишем скрипт отправки. Написано на пых-пых. Надо проверить правильность пути к интерпретатору (/usr/local/bin/php).

#!/usr/local/bin/php
<?
 
if (!eregi('^\+[0-9]{5,}$',$argv[1])) {
    echo "USAGE: echo 'message' | $argv[0] PHONENUMBER\n";
    exit;
}
 
$fp=fopen('php://stdin','r');
$mess='';
 
while ($buff=fread($fp,256)) {
    $mess.=$buff;
}
 
$mess=trim($mess);
fclose($fp);
 
$body=sprintf('username:password:::0,0,Nagios:%s:%s',$argv[1],$mess);
mail('send@send.smsc.ru','sms',$body);
 
?>

На скрипт ставим права 755, таким образом его можно юзать из командной строки. Назовем его notify_via_sms.php и положим, скажем, в /usr/local/bin/.

username и password – заменить на ваш логин и пароль в сервис рассылки SMS.

Проверить работу скрипта можно примерно так

echo "Test message" | /usr/local/bin/notify_via_sms.php ВАШ_НОМЕР

Номер разумеется в международном формате.

3. Теперь Nagios’у надо рассказать как пользоваться этим скриптом. В commands.cfg пишем:

define command
        command_name    notify-by-custom-sms
        command_line    /usr/bin/printf "%b" "$NOTIFICATIONTYPE$ ON $HOSTALIAS$\n$SERVICEDESC$ IS $SERVICESTATE$\n$SERVICEOUTPUT$" | /usr/local/bin/notify_via_sms.php $CONTACTPAGER$
        }

Все. Теперь все уведомления с сервисов, которым присвоена группа, к которой принадлежит этот контакт будут получать уведомления по SMS.

Small Office Linux OpenVPN Server (перепечатка)

Комментариев нет

I recently set up a CentOS Linux OpenVPN server for a small office, and this is a complete howto writeup of the process. These instructions contain everything you need for configuring the server (including firewall rules!). Also included are complete instructions for setting up both mac and windows client machines.

Original news source

Nagios Plugin: check_ftp_login (перепечатка)

Комментариев нет

В общем нужно было проверять Nagios’ом не только порт фтп на удаленном хосте, но и работоспособность определенного аккаунтa FTP. Т.е. чтобы check_ftp заходил на FTP сервер и логинился под определенным юзером.

Существующая утилитка check_ftp из набора Nagios Plugins на момент написания статьи не умела делать логин. Точнее утилитки как таковой там и нет, там просто стоит симлинк check_ftp -> check_tcp.

По сему утилитка была написана на Perl с использованием Nagios::Plugin и Net::FTP.

Может так же использоваться как пример написания Nagios Plugins на Perl в виду простоты кода.

Сырец: http://www.pentarh.com/files/check_ftp_login

Пользоваться так.

1. Скопировать в диру с плагинами Nagios

2. Поставить чмод 755

3. Убедиться что стоят перловые модули Net::FTP и Nagios::Plugin (т.е. запустить утилитку и если все ок, она выдаст USAGE)

4. Прописать команду в commands.cfg:

define command{
   command_name    check_ftp_login
   command_line    $USER1$/check_ftp -H '$ARG1$' -u '$ARG2$' -p '$ARG3$'
}
5. Юзать, например так
define service{
   use             remote-service
   host_name ВАШХОСТ
   service_description FTP LOGIN
   check_command   check_ftp_login!ftp.foobar.com!FTP_LOGIN!FTP_PASSWORD
   normal_check_interval       10
}

Удаленный шифрованный бэкап MySQL при помощи LVM snapshot (перепечатка)

Комментариев нет

Имеем: высоконагруженый MySQL сервер с таблицами объёмом более 20 Гб.

Требуется: ежедневное резервное копирование на удавленный хост с шифрованием данных

Условия: процедура бекапа не должна ни коим образом сказаться на производительности MySQL во время проведения оной.

Итак, mysqldump отпадает автоматически, ибо локи таблиц там испортят нам весь аптайм. Выбор пал на технологию LVM снэпшотов, доступную в любом линуксе, утилитку шифрования gpg, а так же IO scheduler CFQ.

Итак, подготовка.

1. Подготовка LVM.

Нам нужна LVM группа с необходимым свободным местом для:

  • Баз MySQL
  • LVM снэпшота

Т.е. объема свободного пространства в группе LVM должно быть под базы + где-то 10-20% (в зависимости от тяжести IO записи работы с базами).

Создаем LVM Physical Volume на девайсе /dev/sda2 (у меня /dev/sda это RAID5 из 6 SAS дисков, sda2 можете заменить на свой девайс):

pvcreate /dev/sda2

Создаем Volume Group с именем vg0 на /dev/sda2:

vgcreate vg0 /dev/sda2

Теперь надо создать в группе vg0 логический том (Logical Volume) под партицию MySQL таблиц с именем mysql.  У меня эта партиция занимает 500 Гб. При этом важно оставить в группе vg0 10-20% свободного места, не занятого логическими томами, дабы было возможно делать снэпшоты.

lvcreate -L 500G -n mysql vg0

Теперь наш девайс будет виден в:

/dev/mapper/vg0-mysql
/dev/vg0/mysql (symlink)

2. Подготовка ФС

Это, думаю, умеют делать все. Но на всякий напишу.

Делаем FS:

mke2fs -j -L lmysql /dev/mapper/vg0-mysql
mkdir /mysql

Прописываем в fstab:

LABEL=lmysql            /mysql                  ext3    defaults,noatime 0 0

Монтируем, подготавливаем:

mount /mysql
mkdir /mysql/myisam
chown mysql:mysql /mysql/myisam

Прописываем в /etc/my.cnf:

datadir=/mysql/myisam

Стартуем MySQL:

/etc/init.d/mysqld start

Дальше любимым путем переносим на этот раздел (/mysql/myisam) свои базы.

3. Подготовка MySQL

Надо пропатчить RC-скрипт MySQL для выделения высокого приоритета IO, дабы наша мышца не сдулась в ходе интенсивного бекапа.

Так же следует заметить, что я использую IO scheduler CFQ. Если у вас не CFQ, то можно забыть про приоритеты IO. Узнать/Выставить IO scheduler на девайсе можно в файле:

/sys/block/sda/queue/scheduler
(sda заменить на ваш девайс)

Смысл патча в том, чтобы после старта MySQL отдавать ему высокий приоритет IO в CFQ. Патч на CentOS 5 RC скрипт /etc/init.d/mysqld выглядит так. Думаю, народ разберется.

4. Подготовка авторизации

Я буду делать бекап через кучу пайпов. Причин две:

  • Так проще
  • tar накидывается на дисковое IO с меньшим энтузиазмом когда пишет в пайп | gpg | ssh, чем когда пишет на диск.

Конечно, это увеличивает продолжительность бекапа. Но и уменьшает вероятность затыка MySQL на время бекапа.

А по сему, мы создаем Беспарольную авторизацию по публичному ключу с хоста MySQL (юзер root) на ваш некий бекап-хост  user@backup.remotehost.com.

5. Скрипт бэкапа

Собственно скрипт состоит из двух частей. Я их сложил оба в /root/scripts/. И в скрипте backup.sh используется этот путь.

1. backup.php

Этот скрипт делает сброс таблиц MySQL на диск с READ LOCK. После лока он создает снэпшот тома /dev/vg0/mysql и после этого отпускает лок MySQL.

Скриптик это служебный, используется он из скрипта backup.sh.

В нем нужно поменять в строке коннекта к MySQL данные для коннекта рутового юзера к локальному серверу:

$link=@mysql_connect('localhost','root','');

Так же стоит обратить внимание на строку

exec("/usr/sbin/lvcreate --size 30G --snapshot --name $lv /dev/{$vg}/$part",$out,$ret);

А именно на 30G – это размер LVM снапшота. Нам он нужен на время бекапа, и размер снапшота должен превышать тот максимальный объем данных, которые MySQL сможет записать за это время на диск. Ну и конечно, в группе LVM vg0 должно быть именно столько или больше свободного места. 30G в общем за глаза.

2. backup.sh

А это именно тот скрипт, который будет запускаться из крона.

Он запускает backup.php для снятия снапшота, монтирует снапшот в указанную директорию, тарит раздел с таблицами, кидает это все в пайп к gpg для шифрования по алгоритму AES256 с симметричным ключом и кидает дальше в пайп ssh, который уже на удаленной стороне складывает с помощью dd все это хозяйство в файл бекапа с временной меткой. Фух.

Далее он размонтирует снапшот и удаляет его.

Если кто успел заметить, используется утилита gpg для шифрования симметричным ключом, который расположен в файле $keyfile. Данный файл должен содержать около 20 случайных ASCII символов одной строкой. Стоит заметить что нужно создать этот файл раз и навсегда и сохранить где то у себя его копию, поскольку расшифровать бекап можно будет только с его помощью. А сделать это можно будет сделать командой:

gpg --passphrase-file $keyfile --cipher-algo AES256 -d file.tgz.gpg > file.tgz

Прочие переменные:

gpgpath – путь к gpg, с завершающим слешем
vgname – имя группы LVM, содержащей том с таблицами MySQL
lvname – имя тома создаваемого снапшота
partitionlvname – имя тома с таблицами MySQL в группе $vgname
mntpoint – директория для монтирования снапшота
remotehost – юзер и хост для удаленного бекапа (см. пункт 4)
f — имя файла, в который на удаленной стороне будет складываться шифрованный бекап

Собственно, все. Удачного дебага всего этого хаоса что выше ))

 

Еще один способ отбиться от небольшого DDOS (перепечатка)

Комментариев нет

Все нижеописанное относится к GNU/Linux 2.6.x. ДДОС совершенно тупой, разномастный: syn/tcp/udp/icmp flood тупо на все открытые порты, мегабит на 60. UDP срали вообще куда попало. Но основная атака конечно на HTTP. По этому, тушим сервисы и пишем….

Немного sysctl…

vm.min_free_kbytes=70000
net.core.somaxconn=65536
net.ipv4.tcp_tw_reuse=1
net.ipv4.tcp_tw_recycle=1
net.ipv4.ip_local_port_range = 2000 61000
net.ipv4.tcp_fin_timeout = 25
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_window_scaling = 0
net.ipv4.tcp_timestamps = 0
net.core.rmem_max=16777216
net.core.wmem_max=32777216
net.ipv4.tcp_no_metrics_save=0
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 187380 32777216
net.core.netdev_max_backlog=16384
net.ipv4.tcp_max_syn_backlog=4096
net.ipv4.ip_conntrack_max=600000
net.ipv4.icmp_echo_ignore_all=1
net.ipv4.netfilter.ip_conntrack_max=500000
net.netfilter.nf_conntrack_max=500000
Не забываем перезапустить Network.

Немного iptables….

# Форвард нам нэ нада
iptables -P FORWARD DROP
# BAN – цепочка для помещения туда айпи хостов, ведущих себя не правильно ) Ну типа
# iptables – I BAN -s 123.123.123.123 -j DROP
iptables -N BAN
# TRUSTED – цепочка для помещения туда правильных хостов и хостов откуда мы сидим в шелле. Типа
# iptables -I TRUSTED -s 111.111.111.111 -j ACCEPT
iptables -N TRUSTED
# Стандартный заголовок, eth1 – наш интерфейс внешний
# если есть еще интерфейсы, надо их тоже запрячь правилами разрешения как у lo
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -i eth1 -m state –state ESTABLISHED -j ACCEPT
iptables -A INPUT -i eth1 -m state –state RELATED -j ACCEPT
# Проход по белым и черным цепочкам
iptables -A INPUT -i eth1 -j TRUSTED
iptables -A INPUT -i eth1 -j BAN
# У меня висит только сервис http, по этому здесь такая себе мини защита по данному порту
# Насчет –seconds 10 –hitcount 10, курим маны, экспериментируем, ставим то, что подойдет.
# Режем всех TCP на порту 80, которые за последние 10 секунд сделали 10 попыток открыть соединение
# (кому то может не подойти!)
iptables -A INPUT -p tcp -m tcp –dport 80 -m state –state NEW -m recent –update –seconds 10 –hitcount 10 –name httpd –rsource -j DROP
# А остальных разрешаем
iptables -A INPUT -i eth1 -p tcp -m tcp –dport 80 -j ACCEPT
# Вот по этой теме ддосеры тоже затрахали, по этому был категоричен
iptables -A OUTPUT -p udp -j DROP
iptables -A OUTPUT -p icmp -j DROP
# Здесь добавить разрешения на прочие порты, у меня прочих не было
# …
# Здесь добавить (!!!) свои айпи, с которых сидишь в шелле
iptables -A TRUSTED -s 111.111.111.111 -j ACCEPT
# Хорошо подумаем, покурим, затаим дыхание и напишем….
iptables -P INPUT DROP
# Что означает зарезать все, что не разрешили на INPUT’е
А теперь запускаем nginx/httpd и прочую лабуду. Надеюсь заработает. У меня заработало, как будто ничего и не происходило :)

vim: внешние фильтры (перепечатка)

Комментариев нет

Помимо сортировки, внешние команды можно использовать для любых манипуляций над всем документом или его фрагментом.

Выполнение внешней команды на диапазоне:

:{диапазон} ! {команда}

При этом на STDIN команды подается содержимое диапазона, а затем диапазон заменяется выводом STDOUT команды.

Несколько примеров.

Форматирование всего исходного текста на perl с помощью perltidy:

:% ! perltidy -es=4 -t -st

Отфильтровать с помощью команды grep все строки, содержащие символ «#» из строк 14-24:

:14,24 ! grep -v "\#"