FastNetMon

Показаны сообщения с ярлыком Руководства. Показать все сообщения
Показаны сообщения с ярлыком Руководства. Показать все сообщения

понедельник, 20 июня 2016 г.

Руководство по уходу за дисковой подсистемой выделенного сервера

Дисковая подсистема - одно из самых частых мест возникновения сбоев в сервере (по причине механической организации систем хранения) и при этом одно из самых важных (в связи с тем, что там хранится самое важное - информация). Очевидно, что выход диска из строя на площадке хостинг-провайдера, расположенного в другой стране - ситуация фактически фатальная, так как для ремонта диска его нужно передать в соответствующую компанию (что уже само по себе крайне нетривиально) и даже в случае успешной передачи - это крайне дорогостоящая операция и нередко шанса на успех просто нету. Поэтому болезнь лучше предупреждать, чем лечить.

Профилактических мероприятий тут два: RAID массивы (с резервированием - raid - 1, 5, 6 10, raid-0 и его производные защиты от потери данные не дает) и самостоятельное слежение за здоровьем дисков посредством различных средств.

Защита данных посредством RAID

RAID массив является панацеей от подавляющего числа проблем с дисками, так как в случае его использования отказ 1 из дисков (я здесь о самом простейшем из RAID 1, зеркало) чреват лишь тем, что его надо будет заменить физически и пересобрать массив. Данные при этом потеряны не будут.

Но опять же, за массивом требуется следить. Так как он совершенно спокойно может перейти в состояние DEGRADED (то есть, один из его дисков отказал и массив работает в аварийном режиме), в котором сбой единственного оставшегося диска с данными чреват потерей всей информации. То есть, за массивом также нужно следить, а не просто "поставил и забыл".

Контроль состояния soft raid

Состояние soft-raid можно посмотреть командой:
cat /proc/mdstat
если все хорошо, то выдано там будет примерно следующее:
cat /proc/mdstat
Personalities : [raid0] [raid1] [raid6] [raid5] [raid4] [raid10]

md2 : active raid1 sda3[0] sdb3[1]
20972736 blocks [2/2] [UU]

md1 : active raid1 sda2[0] sdb2[1]
2104448 blocks [2/2] [UU]

md0 : active raid1 sda1[0] sdb1[1]
4200896 blocks [2/2] [UU]

Если же один из дисков откажет, то вместо [UU] будет [U_] либо [_U], это означает, что нужно написать в поддержку и указать на отказ одного из дисков и проблемы с RAID массивом. Вам должны будут заменить диск и, возможно, еще собрать массив.

Как же это автоматизировать? Не каждый же день дергать эту команду! Вообще, лучше каждый день. Потеря 1 секунды в сутки намного менее фатальна, чем отказ диска с информацией за годы. Конечно, есть способы автоматизации в виде mdadm monitor, но они упираются в электронную почту, которая никогда ни гарантией получения уведомления не отличалась. Так что если у Вас есть соответствующие знания, то пожалуйста, иначе - лучше руками.

Дает ли RAID гарантию от потери данных по механическим причинам?

Если же за RAID массивом следят и он всегда в состоянии ACTIVE, то я могу быть совершенно спокоен за данные? Да вот совершенно нет, кстати. Почему же? Во-первых, отказать могут сразу два диска (случай почти нереальный, но тем не менее согласно теории надежности имеющий место быть), может отказать электроника на одном из дисков, которая перестанет диагностировать ошибки чтения / записи (ввода-вывода) и на рабочий диск будет сдублирован мусор в итоге в лучшем случае немного повредится файловая система (обычно, лечится fsck), а в худшем будут потеряны данные. В своей практике я сталкивался с таким случаем и что-либо сделать в этом случае было нельзя.

Как защититься от форс-мажорных проблем c RAID

Для защиты от такого рода ошибок существует механизм само-тестирования массива. Когда система (по крону) раз в неделю запускает посекторное сравнение дисков массива и если находит отличия, сразу сообщает о них. Более подробно, об этом можно прочесть здесь: http://phpsuxx.blogspot.com/2010/04/warning-mismatchcnt-is-not-0-on-devmd2.html


Теперь немного о самих жестких дисках.

Мониторинг физического состояния жестких дисков
Проблемы с жестким диском можно определить двумя способами - напрямую (через систему самодиагностику жесткого диска именуемую SMART) и косвенно (ага, по потере данных, отказу сервера или же по ошибкам в dmesg).

S.M.A.R.T мониторинг жестких дисков

С мониторингом SMART посложнее, для его контроля используется пакет smartmontools (в CentOS его ставить: yum install -y smartmontools, в Debian: apt-get install -y smartmontools), в составе которого идет утилита smartctl, которая позволяет получить информацию от SMART подсистемы жестких дисков следующим образом:
smartctl --all /dev/sdX
Где sdX имя интересующего Вас жесткого диска (список имеющихся жестких дисков при использовании soft-raid можно посмотреть в команде cat /proc/mdstat). Тут в первую очередь стоит обращать внимание на параметр reallocated sectors, если он больше 20-30, то значит диск, скорее всего, скоро выйдет из строя и таже нужно написать в поддержку с просьбой его заменить.

Также в самом низу выдачи есть блоки "SMART Error Log Version: 1" - там могут быть большие записи (с кучей 16-ричных адресов), повествующие об отказе какой-либо из частей диска; если же диск в норме - там все должно быть пусто - "No Errors Logged". Кроме него, есть еще блок "SMART Self-test log structure revision number 1", в который пишутся результаты диагностических само-тестов диска. В нормальных условиях он выглядит так:
# 1  Short offline       Completed without error       00%     26274         -# 2  Short offline       Completed without error       00%     26248         -# 3  Short offline       Completed without error       00%     26226         -# 4  Short offline       Completed without error       00%     26200         -# 5  Short offline       Completed without error       00%     26178         -# 6  Short offline       Completed without error       00%     26151         -# 7  Short offline       Completed without error       00%     26127         -# 8  Extended offline    Completed without error       00%     26062         -

Но эти самые тесты нужно запускать либо вручную либо силами того же smartmontools'а (путем правки  /etc/smartd.conf).

Вручную запуск ускоренного теста осуществляется вот так:
smartctl -t short /dev/sdX
Запуск расширенного теста:
smartctl -t long /dev/sdX
Через некоторое время после запуска (несколько минут для короткого и до получаса-часа для длинного) поле "SMART Self-test log structure revision number 1" будет заполнено и будет добавлена информация о завершении теста.

Если какой-либо из тестов FAILED, то это повод идти к оператору Дата Центра и запрашивать замену сбойного диска.

Косвенный мониторинг состояния жесткого диска

Самый очевидный вариант - когда жесткий диск был выброшен из RAID массива по причине FAULTY (то есть возникла ошика ввода вывода и диск был отключен). Также косвенным показателем отказа дисков являются разнообразные ошибки (например I/O error) в выдаче команды dmesg.

Это также говорит о подтвержденном сбое с заданным жестким диском и должна быть осуществлена его замена.

Если с RAID и SMART все в порядке, могу ли я быть спокоен за данные?

И снова нет. Для полной защиты необходим последний штрих - бэкапы на внешнем носителе.

Бэкапы

Многие очень часто ошибаются, утверждая, что RAID дает гарантию от потери данных. От механических причин он, конечно же, спасет. А вот от деструктивных действий хакеров или ошибки администратора - навряд ли. Поэтому всегда крайне обязательно иметь на удаленном сервере полную актуальную копию всех важных данных.

четверг, 4 ноября 2010 г.

Почему могут не совпадать показания df и du -sh / ?

Имеем вот такую картину:

df -h
Filesystem Size Used Avail Use% Mounted on
/dev/simfs 16G 16G 115M 100% /
tmpfs 5.9G 0 5.9G 0% /lib/init/rw
tmpfs 5.9G 0 5.9G 0% /dev/shm

du -sh /
du: cannot access `/proc/23728/task/23728/fd/4': No such file or directory
du: cannot access `/proc/23728/fd/4': No such file or directory
5.2G /

Очевидно, куда-то пропало несколько гигабайт разницы между показаниями команд.

Вкратце объясню как так получилось - на сервере были крупные файлы (логи) и они были открыты в некоторых программах (например, nginx и apache). Эти файлы были удалены из системы посредством команды rm, но так как дескрипторы были открыты, данные, разумеется не были удалены (дабы не поломать программы) и хранились до того, пока программа их не "отпустит", но самих ссылок на файлы уже не существовало и du -sh их, разумеется, не видела и не учитывала в отличие от системы квот ядра, которая отлично понимала ситуацию. После перезаупска программ (в данном случае nginx и apache) файлы были отпущены и df -h начал показывать корректные значения.

Итого, после перезпуска демонов имеем корректные показания:
df -h
Filesystem Size Used Avail Use% Mounted on
/dev/simfs 16G 5.2G 11G 34% /
tmpfs 5.9G 0 5.9G 0% /lib/init/rw
tmpfs 5.9G 0 5.9G 0% /dev/shm

Дабы не искать, какой именно демон использует файл, можно просто перезапустить машину / VPS.

пятница, 7 мая 2010 г.

Что делать если в dmesg - reallocate failed? НЕ ПОВТОРЯТЬ ОПАСНО ДЛЯ ЖИЗНИ!

https://guust.tuxes.nl/~bas/wordpress/?p=12


Имеем: диск /dev/sda и раздел /dev/sda3, входящий в degraded RAID-1 массив /dev/md2. Проблема заключается в том, что на 49% сборки массива, вылетает ошибка ввода-вывода:


ata1.00: exception Emask 0x0 SAct 0x7fffffff SErr 0x0 action 0x0
ata1.00: irq_stat 0x40000008
ata1.00: cmd 60/80:58:d1:6a:08/00:00:2d:00:00/40 tag 11 ncq 65536 in
res 51/40:00:01:6b:08/bc:00:2d:00:00/40 Emask 0x409 (media error)
ata1.00: status: { DRDY ERR }
ata1.00: error: { UNC }
ata1.00: configured for UDMA/133
ata1: EH complete
ata1.00: exception Emask 0x0 SAct 0x7fffffff SErr 0x0 action 0x0
ata1.00: irq_stat 0x40000008
ata1.00: cmd 60/80:98:d1:6a:08/00:00:2d:00:00/40 tag 19 ncq 65536 in
res 41/40:00:01:6b:08/bc:00:2d:00:00/40 Emask 0x409 (media error)
ata1.00: status: { DRDY ERR }
ata1.00: error: { UNC }
ata1.00: configured for UDMA/133
ata1: EH complete
ata1.00: exception Emask 0x0 SAct 0x7fffffff SErr 0x0 action 0x0
ata1.00: irq_stat 0x40000008
ata1.00: cmd 60/80:58:d1:6a:08/00:00:2d:00:00/40 tag 11 ncq 65536 in
res 41/40:00:01:6b:08/bc:00:2d:00:00/40 Emask 0x409 (media error)
ata1.00: status: { DRDY ERR }
ata1.00: error: { UNC }
ata1.00: configured for UDMA/133
ata1: EH complete
ata1.00: exception Emask 0x0 SAct 0x7fffffff SErr 0x0 action 0x0
ata1.00: irq_stat 0x40000008
ata1.00: cmd 60/80:98:d1:6a:08/00:00:2d:00:00/40 tag 19 ncq 65536 in
res 41/40:00:01:6b:08/bc:00:2d:00:00/40 Emask 0x409 (media error)
ata1.00: status: { DRDY ERR }
ata1.00: error: { UNC }
ata1.00: configured for UDMA/133
ata1: EH complete
ata1.00: exception Emask 0x0 SAct 0x7fffffff SErr 0x0 action 0x0
ata1.00: irq_stat 0x40000008
ata1.00: cmd 60/80:58:d1:6a:08/00:00:2d:00:00/40 tag 11 ncq 65536 in
res 41/40:00:01:6b:08/bc:00:2d:00:00/40 Emask 0x409 (media error)
ata1.00: status: { DRDY ERR }
ata1.00: error: { UNC }
ata1.00: configured for UDMA/133
ata1: EH complete
ata1.00: exception Emask 0x0 SAct 0x7fffffff SErr 0x0 action 0x0
ata1.00: irq_stat 0x40000008
ata1.00: cmd 60/80:98:d1:6a:08/00:00:2d:00:00/40 tag 19 ncq 65536 in
res 41/40:00:01:6b:08/bc:00:2d:00:00/40 Emask 0x409 (media error)
ata1.00: status: { DRDY ERR }
ata1.00: error: { UNC }
ata1.00: configured for UDMA/133
sd 0:0:0:0: SCSI error: return code = 0x08000002
sda: Current [descriptor]: sense key: Medium Error
Add. Sense: Unrecovered read error - auto reallocate failed

Descriptor sense data with sense descriptors (in hex):
72 03 11 04 00 00 00 0c 00 0a 80 00 00 00 00 00
2d 08 6b 01
end_request: I/O error, dev sda, sector 755526401
ata1: EH complete
SCSI device sda: 1465149168 512-byte hdwr sectors (750156 MB)
sda: Write Protect is off
sda: Mode Sense: 00 3a 00 00
SCSI device sda: drive cache: write back
SCSI device sda: 1465149168 512-byte hdwr sectors (750156 MB)
sda: Write Protect is off
sda: Mode Sense: 00 3a 00 00
SCSI device sda: drive cache: write back
ata1.00: exception Emask 0x0 SAct 0x1 SErr 0x0 action 0x0
ata1.00: irq_stat 0x40000008
ata1.00: cmd 60/08:00:01:6b:08/00:00:2d:00:00/40 tag 0 ncq 4096 in
res 41/40:00:01:6b:08/bc:00:2d:00:00/40 Emask 0x409 (media error)
ata1.00: status: { DRDY ERR }
ata1.00: error: { UNC }
ata1.00: configured for UDMA/133
ata1: EH complete
SCSI device sda: 1465149168 512-byte hdwr sectors (750156 MB)
sda: Write Protect is off
sda: Mode Sense: 00 3a 00 00
SCSI device sda: drive cache: write back
ata1.00: exception Emask 0x0 SAct 0x1 SErr 0x0 action 0x0
ata1.00: irq_stat 0x40000008
ata1.00: cmd 60/08:00:01:6b:08/00:00:2d:00:00/40 tag 0 ncq 4096 in
res 41/40:00:01:6b:08/bc:00:2d:00:00/40 Emask 0x409 (media error)
ata1.00: status: { DRDY ERR }
ata1.00: error: { UNC }
ata1.00: configured for UDMA/133
ata1: EH complete
SCSI device sda: 1465149168 512-byte hdwr sectors (750156 MB)
sda: Write Protect is off
sda: Mode Sense: 00 3a 00 00
SCSI device sda: drive cache: write back
ata1.00: exception Emask 0x0 SAct 0x1 SErr 0x0 action 0x0
ata1.00: irq_stat 0x40000008
ata1.00: cmd 60/08:00:01:6b:08/00:00:2d:00:00/40 tag 0 ncq 4096 in
res 41/40:00:01:6b:08/bc:00:2d:00:00/40 Emask 0x409 (media error)
ata1.00: status: { DRDY ERR }
ata1.00: error: { UNC }
ata1.00: configured for UDMA/133
ata1: EH complete
SCSI device sda: 1465149168 512-byte hdwr sectors (750156 MB)
sda: Write Protect is off
sda: Mode Sense: 00 3a 00 00
SCSI device sda: drive cache: write back
ata1.00: exception Emask 0x0 SAct 0x1 SErr 0x0 action 0x0
ata1.00: irq_stat 0x40000008
ata1.00: cmd 60/08:00:01:6b:08/00:00:2d:00:00/40 tag 0 ncq 4096 in
res 41/40:00:01:6b:08/bc:00:2d:00:00/40 Emask 0x409 (media error)
ata1.00: status: { DRDY ERR }
ata1.00: error: { UNC }
ata1.00: configured for UDMA/133
ata1: EH complete
SCSI device sda: 1465149168 512-byte hdwr sectors (750156 MB)
sda: Write Protect is off
sda: Mode Sense: 00 3a 00 00
SCSI device sda: drive cache: write back
ata1.00: exception Emask 0x0 SAct 0x1 SErr 0x0 action 0x0
ata1.00: irq_stat 0x40000008
ata1.00: cmd 60/08:00:01:6b:08/00:00:2d:00:00/40 tag 0 ncq 4096 in
res 41/40:00:01:6b:08/bc:00:2d:00:00/40 Emask 0x409 (media error)
ata1.00: status: { DRDY ERR }
ata1.00: error: { UNC }
ata1.00: configured for UDMA/133
ata1: EH complete
SCSI device sda: 1465149168 512-byte hdwr sectors (750156 MB)
sda: Write Protect is off
sda: Mode Sense: 00 3a 00 00
SCSI device sda: drive cache: write back
ata1.00: exception Emask 0x0 SAct 0x1 SErr 0x0 action 0x0
ata1.00: irq_stat 0x40000008
ata1.00: cmd 60/08:00:01:6b:08/00:00:2d:00:00/40 tag 0 ncq 4096 in
res 41/40:00:01:6b:08/bc:00:2d:00:00/40 Emask 0x409 (media error)
ata1.00: status: { DRDY ERR }
ata1.00: error: { UNC }
ata1.00: configured for UDMA/133
sd 0:0:0:0: SCSI error: return code = 0x08000002
sda: Current [descriptor]: sense key: Medium Error
Add. Sense: Unrecovered read error - auto reallocate failed

Descriptor sense data with sense descriptors (in hex):
72 03 11 04 00 00 00 0c 00 0a 80 00 00 00 00 00
2d 08 6b 01
end_request: I/O error, dev sda, sector 755526401
ata1: EH complete
raid1: sda: unrecoverable I/O read error for block 742915328
SCSI device sda: 1465149168 512-byte hdwr sectors (750156 MB)
sda: Write Protect is off
sda: Mode Sense: 00 3a 00 00
SCSI device sda: drive cache: write back
md: md2: sync done.


В сжатом виде:
dmesg | egrep 'I/O.*sector'
end_request: I/O error, dev sda, sector 755526401
end_request: I/O error, dev sda, sector 755526401


То есть сектор не может быть считан.

Перезагружаемся в LiveCD или FastVPS Rescue и делаем следующее для проверки поднят ли mdraid:

ls -la /dev/md2
brw-rw---- 1 root disk 9, 2 2010-05-07 19:16 /dev/md2


Останавливаем RAID массив, чтобы освободить /dev/sda:
/etc/init.d/mdadm-raid stop


ls -la /dev/md2
ls: cannot access /dev/md2: No such file or directory


Смотрим состояние реаллокетед секторов ДО стирания сектора:
smartctl --all /dev/sda | grep reallo -i
5 Reallocated_Sector_Ct 0x0033 100 100 010 Pre-fail Always - 0
196 Reallocated_Event_Count 0x0032 100 100 000 Old_age Always - 0


ВНИМАНИЕ!! СЛЕДУЮЩЕЙ КОМАНДОЙ ВЫ МОЖЕТЕ УНИЧТОЖИТЬ ДИСК НАПРОЧЬ:
hdparm --write-sector 755526401 /dev/sda


После этого пробуем прочесть сектор:
hdparm --read-sector 755526401 /dev/sda


Должно выдать кучу нулей.

Теперь смотрим состояние SMART (у меня оно не изменилось, хотя я ожидал увеличения числа Reallocated_Sector_Ct):
smartctl --all /dev/sda | grep reallo -i
5 Reallocated_Sector_Ct 0x0033 100 100 010 Pre-fail Always - 0
196 Reallocated_Event_Count 0x0032 100 100 000 Old_age Always - 0


Запускаем массив:

/etc/init.d/mdadm-raid start
Assembling MD array md0...done (started [2/2]).
Assembling MD array md1...done (started [2/2]).
Assembling MD array md2...done (initialising [1/2)]).



И ждем, пока будет найден стертый напрочь нами сектор.

Собираем RAID повторно:
mdadm /dev/md2 -a /dev/sdb3


Если сборка снова обрывается на каком-то секторе и он отличается от того, что мы стерли на прошлом шаге, то повторяем операцию для него с нуля и продолжаем.

Тестируем результат fsck:
fsck.ext3 -f /dev/md2


У меня в итоге все успешно отзеркалилось и диск получилось заменить :)

Еще один вариант решения

Конечно, синхронизировать снова и снова 1.5 тб массивы для поиска очередного битого сектора крайне накладно (синхронизация в свою очередь сбивается от единственного битого сектора) и долго, поэтому более оптимален вариант найти все битые сектора за раз и перетереть их.

Для этого воспользуемся тулзой ddrescue:
apt-get install -y ddrescue screen
screen

После этого очищаем dmesg (чтобы потом из него извлечь номера битых секторов) и запускаем копирование с битого диска в /dev/null:
dmesg -c
ddrescue /dev/sda /dev/null

В ответ нам будет показано красивое окошко:
Press Ctrl-C to interrupt
rescued: 6056 MB, errsize: 0 B, current rate: 115 MB/s
ipos: 6056 MB, errors: 0, average rate: 114 MB/s
opos: 6056 MB
Copying data...

Теперь ждем, пока копирование будет закончено и потом выцепляем из dmesg номера битых секторов, как я показывал выше и перетираем их.

вторник, 6 апреля 2010 г.

Чем отличаются версии ПО на сайте производителя от версий ПО в составе дистрибутива?

Стабильное ПО в дистрибутиве и на сайте производителя - это две большие разницы. Все ПО в составе дистрибутива тщательно адаптируется к самому дистрибутиву (версиям библиотек, специфичным настройкам, путями к конфигурационным файлам, версиям ядер и проч.), также за всем ПО в составе дистрибутива следит security team, которая в кратчайшие сроки исправляет любые проблемы с безопасностью ПО и выпускает обновления.

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

Вот как-то так :)

вторник, 16 марта 2010 г.

Диагностика проблем с почтой на сервере / VPS

Добрый вечер!

Сегодня решил написать об одной из самых частых и часто сложных проблем при работе с выделенными серверами / VPS - это проблемы с почтой, причем как входящей, так и исходящей. Итак, поехали.

Решение проблем с исходящей почтой

Симптомы - отправляем почту из скриптов, а она не доходит до получателя.

1. Проверьте хостнейм своего сервера. Это делается командой hostname, он должен быть корректным (вида domain.ru либо subdomain.domain.ru). Очень многие сервера отклоняют почту от серверов с некорректнми хостнеймами (например, myserver или my-server).
2. Проверьте, что в DNS имеется А запись для Вашего хостнейма, которая в идеале должна резволвится в IP адрес Вашего сервера. Это правило соблюдать желательно, но не обязательно, хотя так или иначе есть сервера, которые делают такую проверку и требуют, чтобы хостнейм был отражен в DNS.
3. Проверьте наличие PTR записи для основного IP Вашего сервера (обычно, это IP адрес интерфейс eth0). Сделать это можно так: http://phpsuxx.blogspot.com/2009/10/ptr.html При этом, крайне рекомендую в качестве PTR указывать существующий домен, желательно привязанный к этому же серверу. Это правило из разряда "это делать обязательно", так как такие почтовые системы как hc.ru и mail.ru с высокой вероятностью просто отбросят Вашу почту, если не увидят для Вашего IP обратного резолва
4. Проверьте, запущен ли почтовик на Вашем сервере. Почтовик обычно называется Postfix/Exim/Qmail/Sendmail, проверьте его наличе в выдаче ps aux либо попробуйте подключиться к нему телнетом: telnet localhost 25 и в ответ Вы должны получить нечто вот такое (вместо Exim, разумеется, должно быть написано имя Вашего почтовика):

telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 sds.fastvps.ru ESMTP Exim 4.69 Tue, 16 Mar 2010 22:46:44 +0300


Если же в ответ Вы получаете "telnet: Unable to connect to remote host: Connection refused", то почтовик по всей видимости не установлен / не настроен / не запущен. За подробностями по этим пунктам, прошу в гугл.

Решение проблем с входящей почтой

1. Проверьте наличие MX для требуемого домена. Если не доходит почта на user@domain.ru, то проверьте, какой Mail Exchange (почтовый сервер) обслуживает требуемый домен:

nslookup -type=MX nic.ru
Server: 213.133.99.99
Address: 213.133.99.99#53

Non-authoritative answer:
nic.ru mail exchanger = 5 relay2.RIPN.net.
nic.ru mail exchanger = 5 relay3.RIPN.net.
nic.ru mail exchanger = 10 relay4.RIPN.net.

Authoritative answers can be found from:


Если же в ответ на запрос Вы получаете ошибку, то значит ошибка в настройках DNS.

2. Проверьте, функционирует ли почтовый сервер, обслуживающий домен. Из предыдущего примера мы узнали, что домен обсушивается тремя почтовыми серверами (но обычно это один сервер), который нужно поочередно првоерить командой telnet:

telnet relay2.RIPN.net 25
Trying 195.209.146.172...
Connected to relay2.RIPN.net.
Escape character is '^]'.
220 relay2.ripn.net ESMTP Sendmail (RIPN); Tue, 16 Mar 2010 22:52:54 +0300


Ответ Выше говорит о том, что почтовик функционирует и работает нормально. В противном случае при получении отказа в соединении, идем проверять настройки MTA.

3. Человеческий фактор - проверьте в Вашей панели управления, активирована ли почта для домена и созданы ли ящики и не стоит ли случайно правило для отброса почты.

Продолжение следует, дополнение / возражения принимаются.

понедельник, 25 января 2010 г.

Определение DoS/DDoS атак на сервер

Часто меня спрашивают, как узнать - идет ли DoS атака на сервер? С одной стороны это очевидно, но далеко не для всех и далеко не всегда. В этом посте постараюсь собирать все формальные признаки атак, по которым их можно легко определить.

Во-первых, посомтрим число процессов Апача:
ps aux | grep apache | wc -l


Либо в случае ОС CentOS5/RHEL:
ps aux | grep httpd | wc -l


Если их более 20-30, то это уже повод для беспокойства.

Далее обязательно просмотреть глобальные логи Апача на предмет наличия аномалий (например, запросов без указания вихоста):

/var/log/apache2/error.log
/var/log/apache2/access.log


И для CentOS:
/var/log/httpd/error.log
/var/log/httpd/access.log


Далее, стоит просмотреть логи всех сайтов (например, в случае использования панели ISPManager они лежат в папке /var/www/httpd-logs) и обратить особое внимание на самые большие из них.

Если "большой" лог найден, то его стоить проанализировать на предмет аномалий следующим образом:
cat log_type.log | awk '{print $1}' | sort | uniq -c


Эта команда укажет число запросов до сайта с уникальных айпи, вывод ее будет в виде:

14 95.67.xx.xx
21 95.68.xx.xx
25 95.68.xx.xx
15 95.68.xx.xx
15 95.68.xx.xx
1 95.69.xx.xx
15 95.70.xx.xx
1 95.70.xx.xx
21 95.70.xx.xx
24 95.70.xx.xx
22 95.70.xx.xx
15 95.70.xx.xx
17 95.70.xx.xx
1 95.70.xx.xx


Таким образом, если какой-то IP / блок айпи заваливает сайт запросами, это будет видно по резко уходящим в верх значениям запросов для IP злоумышленников.

Если же используется Nginx, то также обязательно просматривать логи:

/var/log/nginx/error.log
/var/log/nginx/access.log


Продолжение следует :)

воскресенье, 24 января 2010 г.

Защита от исходящего спама на Postfix / Debian

Чтобы запретить всем, кроме пользователя Postfix и рута соединяться с серверами на 25й порт необходимо внести в фаерволл следующие правила:

iptables -A OUTPUT -o lo -j ACCEPT # разрешаем соединения с loopback
iptables -A OUTPUT -p tcp -m tcp --dport 25 -m owner --gid-owner postfix -j ACCEPT
iptables -A OUTPUT -p tcp -m tcp --dport 25 -m owner --gid-owner root -j ACCEPT
iptables -A OUTPUT -p tcp -m tcp --dport 25 -j DROP


Теперь протестируем:

# id
uid=0(root) gid=0(root) groups=0(root)
# telnet smtp.mail.ru 25
Trying 94.100.177.1...
Connected to smtp.mail.ru.
Escape character is '^]'.
220 mail.ru ESMTP Sun, 24 Jan 2010 19:15:27 +0300



А все остальные пользователи получают облом:

$ id
uid=1000(nrg) gid=1000(nrg) groups=1000(nrg)
$ telnet smtp.mail.ru 25
Trying 94.100.177.1...


При этом почтовик также работает отлично:
echo test | mail -s test odintsov@test.ru

суббота, 16 января 2010 г.

Защита от DoS/DDoS атак посредством анализа логов (access.log) и фаерволла

cat access.log | awk '{print $1}' | sort | uniq -c | awk '{if($1>50){print $1 " " $2}}' | awk '{print $2}' > /tmp/ips


Также кроме безусловного анализа есть атаки, когда в логе появляются крайне странные записи примерно такого вида:
94.180.27.51 - - [17/Mar/2010:16:28:45 +0300] xxx.net 88.198.45.197 - 400 0 "-" "-" "-" 0.000--
94.180.27.51 - - [17/Mar/2010:16:28:46 +0300] xxx.net 88.198.45.197 - 400 0 "-" "-" "-" 0.000--
94.180.27.51 - - [17/Mar/2010:16:28:46 +0300] xxx.net 88.198.45.197 - 400 0 "-" "-" "-" 0.000--
94.180.27.51 - - [17/Mar/2010:16:28:46 +0300] xx.net 88.198.45.197 - 400 0 "-" "-" "-" 0.000--
94.180.27.51 - - [17/Mar/2010:16:28:46 +0300] xxx.net 88.198.45.197 - 400 0 "-" "-" "-" 0.000--
94.180.27.51 - - [17/Mar/2010:16:28:46 +0300] xxx.net 88.198.45.197 - 400 0 "-" "-" "-" 0.000--


Для них правило будет вот такое:

cat access.log | grep '400 0 "-" "-" "-" 0.000--' | awk '{print $1}' | sort | uniq > /tmp/ips


Теперь узнаем свой IP:

w | grep 'root' | awk '{print $3}'


IP сервера:

ifconfig -a | grep 'inet addr' | tr ':' ' ' | awk '{print $3}'


И удаляем их из списка.

И теперь достаточно одной команды, чтобы всех забанить:

for ip in `cat /tmp/ips`; do iptables -I INPUT -p tcp --dport 80 -s $ip -j DROP ; done



Только будьте аккуратны и себя не забаньте :)

Защита HTTP серверов от DoS / DDoS атак

Рекомендую для этого следующие правила:

http://phpsuxx.blogspot.com/2009/12/iptables_16.html и http://phpsuxx.blogspot.com/2010/01/http-get-dos.html

То есть, итого:
iptables -A INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 15 -j REJECT

iptables -A INPUT -p tcp --dport 80 -m state --state NEW -m recent --name http --set
iptables -A INPUT -p tcp --dport 80 -m state --state NEW -m recent --name http --update --seconds 60 --hitcount 20 -j DROP


А если хотите только записывать подозрительных товарищей, то -j LOG и dmesg Вам в помощь и вот примерчик:


iptables -A INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 15 -j LOG
iptables -A INPUT -p tcp --dport 80 -m state --state NEW -m recent --name http --set
iptables -A INPUT -p tcp --dport 80 -m state --state NEW -m recent --name http --update --seconds 60 --hitcount 20 -j LOG


Только не забываем отключить syslog, иначе будем смерть винтам :)

/etc/init.d/rsyslog stop


Ну и следом пускаем бан-скрипт:

while true; do sleep 1; dmesg -c; done | awk '{print $6}' | tr '=' ' ' | awk '{print $2}' | while read ip; do iptables -I INPUT -p tcp --dport 80 -s $ip -j DROP ; done

среда, 13 января 2010 г.

Как правильно переносить сайты с хостинга на хостинг не ломая кодировку?

1. Экспортируете базу данных на старом хостинге
2. Импортируете базу данных на новом хостинге
3. Блокиурете соединения с удаленными MySQL:
iptables -I OUTPUT -p tcp --dport 3306 -j DROP

4. Идете в phpmyadmin и смотрите, как выглядят русские буквы в таблицах ("Обзор")
5. Если на шаге 3 русских букв вы не увидели, то узнайте, в какой кодировке у Вас Дамп (сам файлик .sql) и добавьте в него в самый верх SET NAMES 'cp1251'; или SET NAMES 'UTF8'; и тогда mysql поймет, в какой кодировке у Вас база и правильно ее импортирует
6. Если все равно "какая-то фигня с кодирвокой на сайте", проверьте - нет ли в базе таблиц с разными CHARSET. Если есть, то приведите к одной и скорректируйте объявление схемы
7. Если все равно нифига не помогло, открывайте исходник кракозябленой страницы и ищите там латинские символы, которые можно отдать грепу и запускайте в своей домашней папке сайте grep -HiR 'latin_symbols' *, с немалой вероятностью, использовался кэш
8. Если все равно нифига не помогло, найдите все mysql_connect и под ними добавьте mysql_query("set names 'cp1251';")
9. Звоните в саппорт (с)

среда, 6 января 2010 г.

Защита от исходящего СПАМа на Debian Lenny 5 + Postfix

Для многих хостеров стоит очень актуальная проблема - проблема защиты от исходящих спам рассылок. Какой смысл от них защищаться? Пусть себе спамят. Но причин защищаться тут две - abus`ы в адрес Вашего сервера в Датацентр (которые при их игнорировании могут легко привести к блокировке) и высокая вероятность отказа исходящей почты для остальных клиентов на сервере, т.к. после спам рассылки Ваш IP с большой (если спам рассылка будет произведена автоматическим скриптом, то вероятность этого просто огромна) вероятностью попадет в какой-либо из популярных черных списков спам-серверов. Убедил, что защищаться стоит? Думаю, да :)

Сразу оговорюсь, что для моего случая задача облегчена, т.к. PHP подключен как FastCGI и работает от имени конкретного пользователя, что очень сильно упрощает задачу борьбы со СПАМ.

Итак, рассмотрим основные пути произведения спам рассылок - это sendmail, локальное не авторизированное соединение с localhost на 25й порт (при этом логин/пароль не требуются) и удаленное/локальное авторизированное соединение (т.е. клиент со своей машины подключается и начинает сваливать нам тонны СПАМА). Также есть очень экзотический вариант, когда спам-скрипт сам соединяется с удаленными серверами, выполняя роль MTA и рассылает СПАМ самостоятельно, но этот вариант уж очень сомнителен. Давайте рассмотрим все подробно и по пунктам.

Поставим необходимый диагностический софт:
apt-get install -y --force-yes strace


Создадим необходимых юзеров
useradd spammer


 Входим под предполагаемым спамером:
su spammer


Sendmail

Через /usr/sbin/sendmail почту отправляют такие популярные программы как PHP и /usr/bin/mail.

echo "some spam" | mail -s testspam testspammail@domain.ru


В итоге выливается в:

[pid 17520] execve("/usr/sbin/sendmail", ["send-mail", "-i", "--", "testspammail@domain.ru"], [/* 16 vars */]) = 0


И при получении в строке хидеров будет следующая строчка однозначно идентифицирующая спамера:

Received: by domain.ru (Postfix, from userid 1001)


Теперь попробуем послать спам от PHP.

php -r "mail('testspammail@domain.ru', 'spamsubj','spambody');"


И получаем аналогичную картину:

[pid 17553] execve("/bin/sh", ["sh", "-c", "/usr/sbin/sendmail -t -i"], [/* 16 vars */]


Это происходит по той причине, что Linux/UNIX версии PHP отправляют почту только через sendmail, windows же версия использует SMTP на локал хост. Следовательно, письмо также будет промаркировано UID пользователя, что позволит его найти и наказать :)

Кстати, обе выше указанные записи в логе /var/log/maillog выльются в следующее (так что можно легко посредством парсинга логов вычислять нарушителей лимитов):


Jan 6 14:12:08 vrt1 postfix/qmgr[13940]: 7B112D52001: removed
Jan 6 14:14:49 vrt1 postfix/pickup[17379]: 54CF3D52001: uid=1001 from=
Jan 6 14:14:49 vrt1 postfix/cleanup[17546]: 54CF3D52001: message-id=<20100106131449.54CF3D52001@vrt1.domain.ru>



Локальное не авторизированное соединение с localhost на 25й порт

Теперь давайте с самого сервера попробуем выполнить следующие команды:

telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 vrt1.domain.ru ESMTP Postfix (Debian/GNU)
HELO 11
250 vrt1.domain.ru
MAIL FROM:spammer@spammer.ru
250 2.1.0 Ok
RCPT TO:testspammer@domain.ru
250 2.1.5 Ok
DATA
354 End data with .
spam

.
250 2.0.0 Ok: queued as 009C768180



В итоге такое письмо приедет получателю только с хидером, который никаким образом не позволяет вычислить источник:

Received: from 11 (localhost [127.0.0.1])


Логи также молчат:

Jan 6 14:32:26 vrt1 postfix/smtpd[17703]: connect from localhost[127.0.0.1]
Jan 6 14:32:52 vrt1 postfix/smtpd[17703]: 009C768180: client=localhost[127.0.0.1]
Jan 6 14:33:02 vrt1 postfix/cleanup[17705]: 009C768180: message-id=<20100106133252.009C768180@vrt1.domain.ru>
Jan 6 14:33:02 vrt1 postfix/qmgr[13940]: 009C768180: from=, size=333, nrcpt=1 (queue


В итоге необходимо запретить неавторизованный прием почты с локалхоста. Есть у Постфикса такой параметр mynetworks, который в документации описывается так:

By default, Postfix will relay mail for clients in authorized networks.

Authorized client networks are defined by the mynetworks parameter. The default is to authorize all clients in the IP subnetworks that the local machine is attached to.


Так что открываем:
vi /etc/postfix/main.cf


Видим там на строке mynetworks следующее:
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128


Заменяем на:

mynetworks =


Перезапускаем постфикс:

/etc/init.d/postfix restart


Ну и все, теперь при попытке послать спам без авторизации будет следующее:

telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 vrt1.domain.ru ESMTP Postfix (Debian/GNU)
HELO 1
250 vrt1.domain.ru
MAIL FROM:spammer@domain.ru
250 2.1.0 Ok
RCPT TO:odintsov@domain.ru
554 5.7.1 : Relay access denied


Теперь попробуем авторизироваться и послать почту.

Для начала нам понадобятся преобразованные в base64 логин и пароль:

# echo "test@suxx.us" | base64
dGVzdEBzdXh4LnVzCg==
# echo "qwerty" | base64
cXdlcnR5Cg==


Теперь отсекаем "Cg==" у закодированных значений и используем.


telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 vrt1.domain.ru ESMTP Postfix (Debian/GNU)
HELO 1
250 vrt1.domain.ru
AUTH LOGIN
334 VXNlcm5hbWU6
dGVzdEBzdXh4LnVz
334 UGFzc3dvcmQ6
cXdlcnR5
235 2.7.0 Authentication successful
MAIL FROM:test@test.ru
250 2.1.0 Ok
RCPT TO:test@domain.ru
250 2.1.5 Ok
DATA
354 End data with .

spam

.
250 2.0.0 Ok: queued as 737C6680C6


А в логах в это время:

Jan 6 15:32:31 vrt1 postfix/smtpd[18540]: connect from localhost[127.0.0.1]
Jan 6 15:33:08 vrt1 postfix/smtpd[18540]: 737C6680C6: client=localhost[127.0.0.1], sasl_method=LOGIN, sasl_username=test@suxx.us
Jan 6 15:33:13 vrt1 postfix/cleanup[18544]: 737C6680C6: message-id=<20100106143308.737C6680C6@vrt1.domain.ru>
Jan 6 15:33:13 vrt1 postfix/qmgr[18428]: 737C6680C6: from=, size=326, nrcpt=1 (queue active)
Jan 6 15:33:13 vrt1 postfix/smtp[18545]: 737C6680C6: to=, relay=ASPMX.L.GOOGLE.COM[2


Удаленное/локальное авторизированное соединение

А тут нам помогут логи из предыдущего примера :) Но в письме опять же отправитель явно никак не идентифицирован. И фишка тут в том, что поле FROM никак не контролируется.

Спам скрипт-MTA

Тут нам поможет только правило фаерволла, запрещающее соединение до 25го порта удаленных серверов всем, кроме нашего родного MTA Postfix.

четверг, 31 декабря 2009 г.

Защищаемся от руткитов/спам скриптов и сканеров

Подавляющее большинство серверов взламываются через уязвимости в скриптах, позволяющие что-либо загрузить (обычно это perl скрипт) в /var/tmp либо /tmp и оттуда запустить (обычно PHP функцией exec).

Есть очень интересный вариант защиты - снятие exec флага с файловых систем /tmp и /var/tmp, это можно сделать следующим образом: http://www.debian-administration.org/articles/57

От второго можно защититься следующим образом, указав в /etc/php.ini либо /etc/php5/apache2/php.ini следующее (после внесения изменений необходимо перезапустить апача - /etc/init.d/httpd restart либо для Дебияна: /etc/init.d/apache2 restart):
disable_functions = dl, shell_exec, posix_mkfifo, exec, system,passthru, symlink, link, set_time_limit, max_execution_time


Это запретит ряд не безопасных функций предотвратит запуск бОльшей части вредоносных скриптов.

среда, 30 декабря 2009 г.

понедельник, 14 декабря 2009 г.

Руководство по поиску руткитов в Linux системах

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

Проверка временных директорий

1. Проверьте содержимое папки /var/tmp на предмет наличия исполняемых файло (они могут быть с очень неприметными именами, например, scan.txt и проч)
2. Проверьте содержимое папки /tmp
3. Проверьте содержимое папки /dev/shm, некоторые руткиты используют ее для хранения своего тела
4. Просканируете систему на факт наличия файлов с "подозрительными" именами (в примере ниже руткит шифруется под присутствующий в каждой папке псевдофайл ..):

find / | grep '\.\.\.'

5. Проверяем спиcки доверенных ключей SSH (владельцы приватной части этих ключей могут беспрепятственно войти в систему с любым паролем):
cat /root/.ssh/authorized_keys

6. Проверяем глобальный системный CRON:
cat /etc/crontab

7. Проверяем CRON рута:
crontab -l

8. Проверяем папки с CRON задачами на предмет наличия сомнительных файлов:
find /etc/ | grep cron

9. Проверяем конфиг файл sudo (может быть выдан доступ к системным командам какому-либо непривилегированному юзеру):
cat /etc/sudoers

10. Смотрим, с каких IP были входы по SSH.

Для Debian:
cat /var/log/auth.log | grep 'Accepted password'


Для CentOS (не забываем, что вход может быть по сертификату!):

cat /var/log/secure | grep 'Accepted password for'
cat /var/log/secure | grep 'Accepted publickey'


11. Также проверяем содержимое папки /etc/ssh:

find /etc/ssh


12. Проверяем файл /etc/rc.local, он также может использоваться для запуска руткитов:
cat /etc/rc.local


13. Общее замечание - лучше проверять руткито опасные папки не ls ом, а find ом, так как очень часто папки с руткитами имеют не отображаемые имена, например, из одного пробела :) Пример создания папки с пробельным именем ниже.

# mkdir ' '
# stat ' '
File: ` '
Size: 4096 Blocks: 8 IO Block: 4096 directory
Device: 902h/2306d Inode: 2107796 Links: 2
Access: (0755/drwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2010-03-19 18:36:46.000000000 +0300
Modify: 2010-03-19 18:36:46.000000000 +0300
Change: 2010-03-19 18:36:46.000000000 +0300



Если в указанных папках Вы нашли подозрительные файлы, то по всей видимости их владельцем будет какой-то из пользователей системы, поэтому очень полезно будет проверить и его. Чтобы узнать домашнюю папку пользвоателя, необходимо проверить файл /etc/passwd:

cat /etc/passwd | grep user_name


Проверка пользовательских файлов

1. Основным местом поиска следов руткитов является пользовательский крон файл, находящийся в файле:
/var/spool/cron/user_name


Так что обязательно проверьте все скрипты указанные в кроне очень внимательно.

2. Также в случае нестандартных конфигураций системы необходимо поискать все файлы пользователя в системе, это можно сделать так: http://phpsuxx.blogspot.com/2009/12/blog-post_7930.html

3. Если это веб-сервер, то найдите все папки cgi-bin и проверьте их на пустоту (если cgi не используется) или на наличие подозрительных файлов.

4. Проверьте все файлы, измененные несколько дней назад (если точно знаете дату взлома), вот пример поиска измененных за последние пять дней файлов:

find -mtime 5


Отфильтровать веб-лог файлы можно так:

find -mtime 5 | egrep -v 'access.log|error.log'


5. Проверяем файл .bash_history, который обычно проливает свет на то, как была взломана система (если взломщик его не удалил)

Ну вот пока и все :) Также рекомендую делать все вышеперечисленное на отключенной системе через chroot.