Категории

четверг, 27 декабря 2012 г.

Linux Ubuntu создаем файл подкачки Swap

Обычно swap создают размером в 2 раза превышающим размер доступной оперативной памяти.
Шаг первый: Создадим файл с помощью команды низкоуровневого копирования dd Файл забьём нулями из /dev/zero и разметим на 256 блоков по 1 Мб каждый:
Ubuntu$ sudo dd if=/dev/zero of=/swap256.swap bs=1M count=256
Шаг второй: отформатируем получившийся файл как swap устройство:
Ubuntu$ sudo mkswap /swap256.swap
Шаг третий: подключаем отформатированный файл (после второго шага это уже полноценный swap) с помощью команды swapon которая как раз для этого и предназначена.
Ubuntu$ sudo swapon /swap256.swap
Четвёртый шаг: делаем так чтобы swap файл подключался каждый раз при загрузке системы. Для этого в /etc/fstab добавляем одну строчку:
/swap256.swap none swap sw 0 0
Контролировать использование swap можно как обычно через опцию sysctl vm.swappiness
У меня в /etc/sysctl.conf прописано:
vm.swappiness=10
Это значит, что система будет использовать swap, если останется 10% от объема оперативной памяти.

Ссылки по теме:
1. Ubuntu. Как создать swap файл подкачки
2. Swappiness

среда, 26 декабря 2012 г.

Asterisk 1.8 и статистика по SNMP в zabbix

Прежде чем начинать собирать статистику с Asterisk по протоколу snmp, нужно чтобы в нем был модуль res_snmp.so:
FreeBSD# asterisk -rvvvv
...
pbx*CLI> module show like snmp                                                                                                                   Module                         Description                              Use Count 
res_snmp.so                    SNMP [Sub]Agent for Asterisk             0         
1 modules loaded
Как видим, все на месте. Для тех, у кого это нет этого модуля, нужно пересобрать порт с нужной опцией:
FreeBSD# make config
[*] SNMP      SNMP protocol
Когда разобрались с наличием модуля, идем в конфиг /usr/local/etc/asterisk/res_snmp.conf и включаем SNMP:
[general]
; We run as a subagent per default -- to run as a full agent
; we must run as root (to be able to bind to port 161)
subagent = yes
; SNMP must be explicitly enabled to be active
enabled = yes
Как видим, Asterisk не может открыть 161 порт (по нему работает протокол snmp), если он запущен не от пользователя root. Но не беда, по умолчанию asterisk работает как суб-агент snmp это значит, что он может отдавать данные в демон snmpd через сокет и ему не надо будет открывать 161 порт.
Готовим конфиг для snmp, вот мой конфиг /usr/local/etc/snmp/snmpd.conf:
syslocation  "Univers Server Room"
syscontact  admin@my_organization_dom
rocommunity  public ТУТ_IP_сервера_zabbix

master agentx
agentXPerms  0660 0550 asterisk asterisk
agentXSocket /var/agentx/master
Если с запуском Asterisk 1.8 в jail не возникло проблем, то с запуском snmpd было 2 проблемы:
1. Не запускался демон snmpd:
FreeBSD# service snmpd restart
snmpd not running? (check /var/run/net_snmpd.pid).
Starting snmpd.
/usr/local/etc/rc.d/snmpd: WARNING: failed to start snmpd
Сообщение об ошибке как-то не особо помогло в решении проблемы, но все-же рискнем заглянуть в логи:
FreeBSD# cat /var/log/snmpd.log 
init_kmem: kvm_openfiles failed: /dev/mem: No such file or directory
Agent initialization failed
Решение оказалось простым man snmpd:
FreeBSD# man snmpd
....
-r      Do not require root access to run the daemon.  Specifically, do
               not exit if files only accessible to root  (such  as  /dev/kmem
               etc.) cannot be opened.
.....
Как сказано в мане, говорим демону snmpd запускаться с опцией -r, добавляем в /etc/rc.conf строку:
#----------------------------- SNMP ---------------------------------------#
snmpd_enable="YES"
snmpd_flags="-r"
#--------------------------------------------------------------------------#
И пробуем еще раз, теперь должно все запуститься:
FreeBSD# service snmpd restart
Stopping snmpd.
Waiting for PIDS: 27711.
Starting snmpd.
Error 2 (No such file or directory) could not get the assoclist
Опять какая-то ошибка, немного погуглив яндексом в рамблере нашел страничку с описанием бага #2311, там говорится про ядро FreeBSD и отсутствие в нем SCTP (У меня в ядре как раз небыло этого SCTP) и эту ошибку можно спокойно проигнорировать. Ну чтож, если говорят, что все должно работать, то проверяем:
FreeBSD# sockstat | grep snmpd
root     snmpd      27758 6  udp4   *:161                 *:*
root     snmpd      27758 7  stream /var/agentx/master
root     snmpd      27758 8  tcp4   *:199                 *:*
root     snmpd      27758 9  stream /var/agentx/master
Как видим, snmpd слушает 161 порт (по нему работает протокол snmp) и сокет /var/agentx/master. Значит мы все сделали правильно, и теперь двигаемся дальше к настройке zabbix.
...... Тут должна быть часть о настройке Zabbix :) Позже допишу. ......

Ссылки по теме:
1. FreeBSD jails and net-snmp
2. SourceForge SNMPd bug: #2311 5.7.1 errors at startup on FreeBSD systems without SCTP
3. Asterisk MIB Definitions
4. asterisk-users mailing list - ASTERISK and SNMP
5. Мониторим Asterisk при помощи snmp и Zabbix

пятница, 21 декабря 2012 г.

Установка git + gitweb + nginx + fcgiwrap на FreeBSD.

Понадобился репозиторий для хранения конфигов серверов и активного сетевого оборудования. Почитав про системы контроля версий и немного поразмыслив выбрал git.
У меня уже имелся готовый веб хостинг на nginx под FreeBSD - решил использовать его. Итак смотрим что есть в составе порта git:
FreeBSD# cd /usr/ports/devel/git/
FreeBSD# make config
[*] CONTRIB    Install contributed scripts
[*] CURL       Data transfer via cURL
[*] CVS        Enable CVS support
[ ] ETCSHELLS  Modify /etc/shells
[*] GITWEB     Install gitweb
[ ] GUI        GUI (Graphical User Interface)
[ ] HTMLDOCS   Install additional documentation
[*] ICONV      Encoding conversion via iconv
[*] NLS        Native Language Support
[*] P4         Enable Perforce support
[*] PERL       Perl scripting language
[ ] SVN        Subversion support
Меня интересовали 2 вещи, какая-нибудь простенькая веб морда интерфейс и собственно сам git. Видим, что в составе порта есть GITWEB, как говорит wikipedia "gitweb - написан на Perl (Kay Sievers). Большинство приведённых ниже крупных публичных git-репозиториев его и применяет."
Настраиваем по вкусу и ставим:
FreeBSD# make config-recursive
FreeBSD# make install clean
Затем идем в /etc/rc.conf и приводим блок с веб сервером примерно к такому виду:
#----------------------------- nginx --------------------------------------#
nginx_enable="YES"  # (bool) Set to "NO" by default. Set it to "YES" to enable nginx
nginx_profiles=""  # (str) Set to "" by default. Define your profiles here.
nginxlimits_enable="NO"  # (bool) Set to "NO" by default. Set it to yes to run `limits $limits_args` just before nginx starts.
nginx_flags=""   # (str) Set to "" by default. Extra flags passed to start command.
nginxlimits_args="-e -U www" # (str) Default to "-e -U www" Arguments of pre-start limits run.

php_fpm_enable="YES"  # 

fcgiwrap_enable="YES"  # 
fcgiwrap_user="www"  # (str) run fcgiwrap as user
#fcgiwrap_socket="unix:/var/run/fcgiwrap/fcgiwrap.sock" #this could also be: tcp:[ipv4_addr]:port (for ipv4) | tcp6:[ipv6_addr]:port (for ipv6)
#fcgiwrap_flags="-c 4"
fcgiwrap_profiles="gitweb"
fcgiwrap_gitweb_socket="unix:/var/run/fcgiwrap/gitweb.socket"
#--------------------------------------------------------------------------#
Я специально запускаю отдельный экземпляр fcgiwrap для каждого "сайта". Если не дай бог упадет, то упадет только один сайт, а не все сразу. :)
Теперь настройки nginx:
server {
#-------------------------- Options --------------------------#
 listen 192.168.4.27:443;
 server_name git.local git;

 open_file_cache max=100000 inactive=40s;
 open_file_cache_valid 60s;
 open_file_cache_min_uses 2;
 open_file_cache_errors on;

#ssl
# ssl on;
# ssl_certificate  ssl/git/git.local.crt;
# ssl_certificate_key ssl/git/git.local.key;

#logs
 access_log /var/log/nginx/git.local_https_access.log;
 error_log /var/log/nginx/git.local_https_error.log;


#-------------------------- Configs --------------------------#
 # Default config
 include confs/main.conf;
 gzip off;

#-------------------------- Locations ------------------------#

# Main location
 location / {
  root /usr/local/www/gitweb;
  index gitweb.cgi;

  location ~ ^/(.*\.cgi)$ {
   include  fastcgi_params;
   fastcgi_pass unix:/var/run/fcgiwrap/gitweb.socket;
   fastcgi_index gitweb.cgi;
   fastcgi_param SCRIPT_FILENAME /usr/local/www/gitweb/gitweb.cgi;
   fastcgi_param DOCUMENT_ROOT /usr/local/www/gitweb;
  }

 }

}
Теперь самое интересное, после установки порта devel/git в каталоге веб сервера /usr/local/www ничего не появилось, хотя опция GITWEB была отмечена, беглый анализ логов установки и поиск по винту навел на папочку:
FreeBSD# find /usr -name gitweb
/usr/local/share/examples/git/gitweb
FreeBSD# # ls /usr/local/share/examples/git/gitweb
gitweb.cgi static
Вот оно! Копируем всю найденную папку gitweb в каталог веб сервера:
FreeBSD# cp /usr/local/share/examples/git/gitweb /usr/local/www
Запускаем сервисы:
FreeBSD# service nginx reload
Performing sanity check on nginx configuration:
nginx: the configuration file /usr/local/etc/nginx/nginx.conf syntax is ok
nginx: configuration file /usr/local/etc/nginx/nginx.conf test is successful
FreeBSD# service fcgiwrap start
===> fcgiwrap profile: gitweb
Starting fcgiwrap.
Переходим по ссылке http://git.local - все работает, ура! :)
P.S. Памятка работы с git репозиторием:
  1. Создаю на сервере новую папку (например /git/www/test).
    $ mkdir -p /git/www/test
  2. Делаю в ней инициализацию пустого репозитория git init:
    $ cd /git/www/test
    $ git init
  3. На локальной машине скачиваю созданный репозиторий:
    $ git clone projects@example.ru:/git/www/test/.git
    Это создаст локальную копию удалённого репозитория (пока пустого).
  4. Накидываю кучу файлов в локальную папку, которую мы создали на предыдущем шаге. Делаю, так сказать, каркас проекта. Если нужно — добавляю исключения в файл (.gitignore).
  5. Выполняю:
    $ cd /git/www/test
    $ git add .
    $ git commit
    $ git push
    Обязательно ввожу комментарий к своим изменениям - желательно писать всегда что-то адекватное, чтобы потом можно было понять что именно было изменено.
    $ git add . - добавляет новые файлы в репозиторий от текущего каталога.
    $ git commit - Фиксирует новую ревизию кода - тут-то и спросит ввести комментарий.
    $ git push - Отправляет изменения на сервер.
  6. Всё. Локальный и удалённый репозиарии обновлены и синхронизированы.
  7. Работаю над проектом. После каких-либо осмысленных изменений делаю вновь шаг 5. Не забывайте предварительно зайти в ту папку, с которой работали.

Если вы веб-разрабочик и вам нужно довольно часто показывать текущий результат работы — очень полезно будет положить файл post-receive в папку .git/hooks какого-либо проекта с таким содержимым:
#!/bin/sh
cd ..
env -i git checkout -f
echo "Удалённый репозиторий успешно обновлён!"
И дайте ему права на исполнение. Теперь после каждого обновления (шаг 5) будет также обновляться рабочее дерево проекта и реальные файлы всегда будут последней, актуальной версии (а этого почти все и ожидают, когда обновили удалённый репозиторий, но так по умолчанию не происходит).
UPD: 21.06.2014
Если после настройки появляется ошибка:
404 - No projects found.
Возможно причина в правах на репазитории, необходимо, чтобы владельцем файлов в репазиториях был тот же пользователь, что и у fcgiwrap. Если репазитории храятся в /git-repos, то решением будет:
cd /git-repos
chown -R www:www .


Ссылки по теме:
1. Wikipedia - Git
2. HOWTO: GIT hosting = nginx + cgit + gitosis + ssh
3. Устанавливаем и настраиваем cGit на Ubuntu
4. Собственный сервер Git на базе Ubuntu или Debian/GNU Linux
5. Tip по использованию Git под Windows
6. Installing Git and Gitweb on FreeBSD
7. Simple CGI support for Nginx (fcgiwrap)
8. 4.1 Git на сервере - Протоколы
9. Configuring GitWeb - 404 - No projects found

вторник, 18 декабря 2012 г.

VirtualBox и FreeBSD, не запускаются виртуальные машины при загрузке системы.

Столкнулся с проблемой на FreeBSD - не запускаются виртуальные машины при загрузке системы. Все оказалось довольно просто - нужные модули ядра не подгружались при загрузке системы, выход оказался очень прост - при запуске скрипта /usr/local/etc/rc.d/vboxheadless подгружать эти модули, если они вдруг не загружены.
Открываем стартовый скрипт /usr/local/etc/rc.d/vboxheadless, находим там строки:
vboxheadless_start()
{
 local machine mpidfile pid vmname vmuser vmflags vmdelay
И добавляем заветные строки, которые будут проверять и загружать необходимые модули ядра, если потребуется:
vboxheadless_start()
{
 local machine mpidfile pid vmname vmuser vmflags vmdelay

( ! kldstat | grep vboxnetflt >/dev/null ) && kldload vboxnetflt
( ! kldstat | grep vboxnetadp >/dev/null ) && kldload vboxnetadp
Ну и не забываем в /etc/rc.conf указать нужные настройки:
#---------------------- VirtualBox ----------------------------------------#
vboxnet_enable="YES"
vboxheadless_enable="YES"  # (bool): Set to "NO" by default. Set it to "YES" to enable vboxheadless.
vboxheadless_user="root"  # (str): Default user account to run with. (default: vboxusers)
vboxheadless_stop="poweroff"  # (str): Default stop cmd for VBoxManage controlvm. (default: savestate)
vboxheadless_delay="0"   # (int): Default startup/shutdown delay in seconds. (default: 0)
vboxheadless_machines="Win7"  # (str): Space separated list of machines.
#--------------------------------------------------------------------------#
А так же в файле /boot/loader.conf добавляем строку:
vboxdrv_load="YES"
Теперь все будет само запускаться, при загрузке системы!

среда, 12 декабря 2012 г.

Настраиваем запись логов в isc-dhcp-server под FreeBSD

После установки и настройки порта isc-dhcpd-server очень захотелось, чтобы логи от этого демона складировались в отдельный файлик, например /var/log/dhcpd.log, а не в общий системный лог /var/log/messages. Как этого достичь описано ниже.
Первым делом добавляем строку в конфиг демона dhcpd /usr/local/etc/dhcpd.conf:
log-facility local7; # куда в syslog шлем логи
Теперь в syslog принимаем от демона dhcpd логи - добавляем строки в файл /etc/syslog.conf:
!dhcpd
local7.*  /var/log/dhcpd.log

#если встретили эту сроку (я имею ввиду это -> !*), то закоментируйте, а то не заработает :)
#!*
А так же рассказываем syslog'у, что у нас есть dhcpd демон, для этого добавляем опцию в /etc/rc.conf:
syslogd_flags="-l /var/db/dhcpd/var/run/log -ss"
И не забываем про ротацию логов в /etc/newsyslog.conf добавляем строки:
#dhcp
/var/log/dhcpd.log  644  15    300 *     XC

Ссылки по теме:
1. FreeBSD: DHCP-сервер для локальной сети на базе ISC DHCP Server
2. Cisco DHCP Snooping with ISC DHCPd
3. Reagent Team - dhcp opt 82

воскресенье, 14 октября 2012 г.

Перенос Windows на RAID контроллер.

1. уменьшить размер раздела через Gparted в Ubuntu Live CD.
2. загрузиться и проверить, что все ОК,
    Скорей всего запустится chkdsk и будет испрвлять ошибки.
3. сделать образ РАЗДЕЛОВ в clonezilla.
4. собрать рейд и установить винду на рейд, используя драйвера.
5. отключить рейд контроллер и подключить винты в материнскую плату.
6. восстановить из образа clonezilla содержимое разделов, не трогая MBR!
    Возможно 100Мб раздел не нужно восстанавливать, т.к. туда были
    установлены драйвера для рейда, а в сохраненном образе их НЕТ!
    Следовательно средство восстановления запуска не получится запустить
    в дальнейшем... Чтобы избежать этой проблемы лучше не восстаналивать
    100Мб раздел... Хотя не уверен! проверю.
7. подключить обратно рейд контроллер и винты.
8. загрузиться и проверить, что все работает :).
    Скорей всего запустится chkdsk и будет испрвлять ошибки.
P.S. это сырая статья.

четверг, 27 сентября 2012 г.

Ubuntu 12.04 установка VNC сервера не зависимого от пользователей.

Выкладываю функцию добавления VNC сервиса. Данная функция используется в моем скрипте lentayka_14.04.sh. Функция была проверена на Ubuntu 12.04 LTS
install_vnc_service() {
 apt-get purge vino
 apt-get install x11vnc

 mkdir /etc/x11vnc
 chmod 755 /etc/x11vnc

 sudo x11vnc -storepasswd YouPasswordHere /etc/x11vnc/passwd
 chmod 644 /etc/x11vnc/passwd

 cat > /etc/init/x11vnc.conf <<_EOF
start on login-session-start
script
x11vnc -xkb -bg \
 -noxrecord \
 -noxfixes \
 -noxdamage \
 -display :0 \
 -auth /var/run/lightdm/root/:0 \
 -rfbauth /etc/x11vnc/passwd \
 -forever \
 -o /var/log/x11vnc.log
end script
_EOF
}

Ссылки по теме:
1. How to setup VNC server for remote desktop in Ubuntu 11.10 Oneiric
2. Remote VNC login to Ubuntu 11.10
3. Запуск VNC-сервера в Ubuntu 11.10 (LightDM)
4. Быстрая настройка x11vnc

пятница, 31 августа 2012 г.

RDP Windows, перенаправленные принтеры, Easy Print Driver.

Для работы перенаправленных принтеров через RDP сессию в Windows 2008 нужно, чтобы у клиента были установлены:
1. Microsoft .NET Framework 3.5.
2. Клиент служб терминалов версии 6.1, для Windows XP (KB952155).

В этом случае принтеры имеющиеся у клиента, будут автоматически перенаправлены через RDP сессию на сервер терминалов.
ВАЖНО! Чтобы не расшаривать каждый принтер у клиента, нужно включить Брандмауэр и выбрать тип сети - "Сеть Предприятия".

P.S. Что самое замечательное, у клиентов видны только их принтеры, и они не смогут распечатать случайно на чужом принтере!
И еще больше всего мне понравилось то, надобность установки драйверов отпадает для многих принтеров - практически все заводятся через Easy Print драйвер.
Ссылки по теме:
1. Подключение к удаленному рабочему столу (клиент служб терминалов версии 6.1) для Windows XP (KB952155)
2. Microsoft .NET Framework 3.5

среда, 29 августа 2012 г.

Запуск КИАСУО 1252 на Windows Server x64, corflags.exe, NetFramework 3.5

Дело в том, что программа КИАСУО ниже версии 1280 откомпилирована с опцией "для всех архитектур", и при запуске на 64 разрядных ОС не запускается. Лечится это довольно просто, ниже описана методика.
Смотрим статус:
C:\Users\Администратор>cd "C:\Program Files (x86)\КИАСУО3\OuServer\bin\Release"
C:\Program Files (x86)\КИАСУО3\OuServer\bin\Release>CorFlags.exe OuServer.exe
Microsoft (R) .NET Framework CorFlags Conversion Tool.  Version  2.0.50727.42
Copyright (c) Microsoft Corporation.  All rights reserved.

Version   : v2.0.50727
CLR Header: 2.5
PE        : PE32
CorFlags  : 9
ILONLY    : 1
32BIT     : 0
Signed    : 1
Видим, что флаг "32BIT : 0" не установлен.
Для запуска КИАСУО на Windows Server 2008 X64 нужно найти утилитку CorFlags.exe — 73.7 КБ, скопировать ее в папку с файлом OuServer.exe и проделать следующее:
C:\Users\Администратор>cd "C:\Program Files (x86)\КИАСУО3\OuServer\bin\Release"
C:\Program Files (x86)\КИАСУО3\OuServer\bin\Release>CorFlags.exe OuServer.exe /3
2BIT+ /Force
Microsoft (R) .NET Framework CorFlags Conversion Tool.  Version  2.0.50727.42
Copyright (c) Microsoft Corporation.  All rights reserved.

corflags : warning CF011 : The specified file is strong name signed.  Using /For
ce will invalidate the signature of this image and will require the assembly to
be resigned.
Проверяем результат:
C:\Program Files (x86)\КИАСУО3\OuServer\bin\Release>CorFlags.exe OuServer.exe
Microsoft (R) .NET Framework CorFlags Conversion Tool.  Version  2.0.50727.42
Copyright (c) Microsoft Corporation.  All rights reserved.

Version   : v2.0.50727
CLR Header: 2.5
PE        : PE32
CorFlags  : 11
ILONLY    : 1
32BIT     : 1
Signed    : 1
Видим флаг 32BIT : 1 установлен, приятной работы!
После этого сервер запускается нормально. У меня заработал как в ручном режиме запуска, так и в режиме сервиса.
Ссылки по теме:
1. CorFlags.exe (CorFlags Conversion Tool)
2. Flipping bits on managed images to make them load with the right bitness...

понедельник, 27 августа 2012 г.

Ubuntu и DNS-Суффикс, /etc/nsswitch.conf, NetworkManager

Столкнулся с проблемой, когда Ubuntu при работе по DHCP неправильно работала с DNS-суффиксом, а именно работала только с суффиксами, а полные доменные имена не понимала, как следствие некорректно работали некоторые локальные сайты в браузерах, да и банальные пинги работали как-то не совсем правильно:
Ubuntu$ ping server
PING server.local (192.168.0.2) 56(84) bytes of data.
64 bytes from server.local (192.168.0.2): icmp_req=1 ttl=64 time=0.131 ms
^C
Ubuntu$ ping server.local
ping: unknown host server.local
При этом DNS сервер отлично обрабатывает запросы:
Ubuntu$ nslookup server
Server:  192.168.0.254
Address: 192.168.0.254#53

Name: server.local
Address: 192.168.0.2
И для доменного имени полностью:
Ubuntu$ nslookup server.local
Server:  192.168.0.254
Address: 192.168.0.254#53

Name: server.local
Address: 192.168.0.2
Погуглив немного, решил, что проблема в NetworkManager'е, на старых версиях Ubuntu он неправильно генерировал /etc/resolv.conf, проверил свой:
Ubuntu$ cat /etc/resolv.conf 
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
nameserver 192.168.0.254
search local
Как оказалось, в моем случае NetworkManager вовсе не виноват! Но в чем же тогда проблема? Еще раз погуглил яндексом в рамблере и пришел к выводу, что виноват конфиг /etc/nsswitch.conf, сравнил его с FreeBSD'шным, где все работает как надо и пришел к выводу, что нужно строку hosts: привести к такому виду:
#НЕ работает!
#hosts:          files mdns4_minimal [NOTFOUND=return] dns mdns4

#работает!
hosts:          files dns
Что такое mdns4 разбираться не стал, без него все работает так, как надо и это главное.

Ссылки по теме:
1. Debian/Ubuntu - [решено] Не распознаёт имя контроллера домена

четверг, 9 августа 2012 г.

Борьба с DDoS SYN-Flood штатными средствами и nginx в Linux

Однажды мой знакомый написал мне, что его сайт перестал открываться сказал, что на сайт обрушилась DDoS атака. Полез я разбираться, в чем дело и в итоге суть проблемы была найдена - куча ip адресов с различными User Agent'ами приходили на сайт и делали очень много различных запросов...
В общем нужно было этих ботов отлавливать и блокировать им доступ к сайту, сперва подумал об iptables и ConfigServer Firewall (csf), но хостинг был внутри OpenVZ, а это означало невозможность использования более 120 правил, а так же невозможность установки модулей ядра и вообще каких либо изменений опций ядра. Потому стандартные подходы для решения проблемы сразу отпадали.
А время шло, и переписываться с тех поддежкой хостинга небыло времени, а платить огромные суммы за защиту от такой примитивной атаки небыло никакого желания.
Решение пришло в голову неожиданно, при перечитывании man ip, вспомнить зачем я его читал затрудняюсь, но решение было на редкость извращенским, но вполне рабочим :)
Решением было добавление маршрута проблемного IP в blackhole. В следствие чего пакеты от этих адресов будут молча отбрасываться (the rule prescribes to silently drop the packet.).
Сперва конфигурируем nginx:
...
worker_rlimit_nofile 200000;
events {
        worker_connections 1024;
        use epoll;
}

....

http {
        # Документ по умолчанию
        index  index.html index.htm index.php;

        ##
        # Basic Settings
        ##
        sendfile on;
        send_timeout 5;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 30 15;
        types_hash_max_size 2048;
        server_tokens off;

        client_header_timeout 15;
        client_body_timeout 15;

        #  лимитируем для зоны one 10 конектов в 1 сек.
        limit_req_zone $binary_remote_addr zone=one:16m rate=10r/s;

        #В ситуации когда сервер записал в сокет данные, но клиент не хочет
        #       их забирать, после таймаута по закрытию соединения в ядре
        #       данные будут держаться еще несколько минут. В nginx если директи                                                                             ва
        #       для принудительного сброса всех данных после закрытия по таймаут                                                                             у.
        reset_timedout_connection  on;

        include /etc/nginx/mime.types;
        default_type application/octet-stream;

        ##
        # Logging Settings
        ##
        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;

        gzip on;
        gzip_disable "msie6";
...
server {
        listen ip.ip.ip.ip:80;
        server_name my.site;

        open_file_cache max=100000 inactive=40s;
        open_file_cache_valid 60s;
        open_file_cache_min_uses 2;
        open_file_cache_errors on;

        #это значит что законектится с лимитом в 3 подключения за 1 сек можно 3 раза, а дальше 503 ошибка. Что и пишется в лог access.
        limit_req zone=one burst=10;

        # Default locations config.
        include conf.std;
...
}
...
}
Файлик /etc/nginx/conf.std:
####### STANDART
# redirect server error pages to the static page /50x.html
error_page   500 502 503 504  /50x.html;
        location = /50x.html {
        root   /var/www/nginx-dist;
}

# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
location ~ /\.ht {
        deny  all;
}

location ~ /\< {
        deny  all;
}
С конфигурацией nginx все, теперь скрипты.
Добавляем в файл /etc/crontab строки:
# parse nginx logs and ban bad ip via nullroute
* * * * * root /root/ddos/parse_nginx.log.sh >/root/ddos/parse_nginx.log.log 2>&1
Содержимое скрипта /root/ddos/parse_nginx.log.sh:
#!/bin/sh

ADMINS_IP='ip.ip.ip.ip'

echo $(date)
echo '--- запускаем систему парсинга nginx лога---'

echo ' ищем ботов'
cat /var/log/nginx/access.log \
        | grep -E -e 'HTTP/1.(0|1)" (400|403|405|499|503)' -e '] "-" 400 0 "-" "-"' \
        | awk '{print $1}' \
        | sort -nr | uniq -c \
        | awk '{if($1>10)print $1" "$2}' \
    > /root/ddos/banlist.txt

cat /var/log/nginx/error.log \
        | grep -E '(limiting requests|limiting connections)' \
        | awk -F"client: " '{print $2}' \
        | awk -F"," '{print $1}' \
        | sort -nr | uniq -c \
        | awk '{if($1>10)print $1" "$2}' \
    >> /root/ddos/banlist.txt

# get unique ip
cat /root/ddos/banlist.txt \
        | grep -v $ADMINS_IP \
        | uniq | sort -nr \
    > /root/ddos/banlist_uniq.txt

echo '------  очищаем tmp file бана-'
cat /dev/null > /root/ddos/banlist.txt

echo ' создаем DROP правила для 50 самых агрессивных ботов'
awk '{print $2}' /root/ddos/banlist_uniq.txt \
        | uniq | head -n 150 > /root/ddos/banlist.txt

#т.к. iptables полнейшее УГ, особенно внутри OpenVZ, баним ip вот таким извращенским методом... через nullroute
#ip route flush type blackhole
for ip in $(cat /root/ddos/banlist.txt); do
        ip route add blackhole ${ip}/32
done

#echo 'записываем злобных ботов в csf.deny'
#cat /etc/csf/csf.deny >> /root/ddos/banlist.txt
#cat /root/ddos/banlist.txt \
#       | uniq | sort -nr \
#    > /etc/csf/csf.deny

#echo 'csf релоад, внесение в iptables ботов'
#/usr/sbin/csf -r
sleep 5

echo '--  делаем ротацию лога--------'
test -x /usr/sbin/logrotate || exit 0
/usr/sbin/logrotate /etc/logrotate.conf

echo '=====злобные боты в списке бана====='

sleep 1
Для мониторинга состояния сервера используем такой скрипт:
#!/bin/sh

while :; do
netstat_str=$(netstat -an)
        echo -n 'SYN_RECV: '
        echo "$netstat_str" | grep 80 | grep SYN_RECV | wc -l
        echo -n 'TIME_WAIT: '
        echo "$netstat_str" | grep 80 | grep TIME_WAIT | wc -l
        echo -n 'FIN_WAIT: '
        echo "$netstat_str" | grep 80 | grep FIN_WAI1 | wc -l
        echo -n 'ESTABLISHED: '
        echo "$netstat_str" | grep 80 | grep ESTABLISHED | wc -l

        echo -n 'BLOCKED_IP to Black-route: '
        ip route list | grep blackhole | sort | wc -l

        sleep 2
        echo '------------------------- for stop this script Press Ctrl+C'
done
Еще понадобится настроить ротацию логов, приводим файл /etc/logrotate.d/nginx к такому виду:
/var/log/nginx/*.log {
        size 1M
        missingok
        rotate 52
        compress
        delaycompress
        notifempty
        create 0640 www-data adm
        sharedscripts
        prerotate
                if [ -d /etc/logrotate.d/httpd-prerotate ]; then \
                        run-parts /etc/logrotate.d/httpd-prerotate; \
                fi; \
        endscript
        postrotate
                [ ! -f /var/run/nginx.pid ] || kill -USR1 `cat /var/run/nginx.pid`
        endscript
}
Еще я использовал встроенные средства iptables для борьбы с DDoS:
#!/bin/sh

iptables -F
iptables -N syn_flood
iptables -A INPUT -p tcp --syn -j syn_flood
iptables -A syn_flood -m limit --limit 100/s --limit-burst 150 -j RETURN
iptables -A syn_flood -j DROP

Данный скрипт спокойно блокировал DDoS примерно в 10 000 ботов, при этом сайт был полностью доступен и атака вообще не чувствовалась.
Прошу обратить внимание на то, что скрипт запускается раз в минуту, и блокирует ip адреса по заданным критериям в скрипте /root/ddos/parse_nginx.log.sh. В моем случае атака была "вялой" и одной минуты вполне хватало для сбора ip адресов ботов. В первые минуты сайт "туго" работал, но спустя минут 10, когда список заблокированных вырос сайт начал свою штатную работу, а список блокированных с течением времени увеличивался все медленнее и в итоге совсем перестал расти - у атакующего закончились боты.

понедельник, 6 августа 2012 г.

Перенос FreeBSD 4 на VirtualBox

Заходим по ssh на машину, которую будем переносить, останавливаем все процессы, которые могут использовать hdd и писать туда важную информацию (например MySQL и т.п.) и делаем дампы всех важных разделов:
# dump -0uan -f - /usr | ssh -c blowfish user@ip.ip.ip.ip dd of=/home/user/oldsrv/var.dd
# dump -0uan -f - /var | ssh -c blowfish user@ip.ip.ip.ip dd of=/home/user/oldsrv/var.dd
Грузимся с LiveCD FreeBSD у меня уже была загрузка по сети FreeBSD 9.0 (но думаю подойдет и любой другой дистрибутив, Frenzy например). Восстанавливаем корневой раздел:
# mkdir /tmp/oldsrv
# cd /tmp/oldsrv
# scp user@ip.ip.ip.ip:/home/user/oldsrv/*.dd
# dd if=from_real_srv/rootfs.dd | restore -rf -
...
убедиться, что все необходимые каталоги, куда будем восстанавливать остальные разделы имеются:
# ls usr
# ls var
...
И начинаем восстанавливать остальные разделы:
# dd if=from_real_srv/usr.dd | (cd usr; restore -rf -)
# dd if=from_real_srv/var.dd | (cd var; restore -rf -)
...

Ссылки по теме:
1. 17.12. Основы технологии резервного копирования.
2. Перенос FreeBSD с одного жёсткого диска на другой.

четверг, 2 августа 2012 г.

Перенос Windows 7 с одного HDD на другой HDD меньшего объема. (dd + Gparted)

На работе часто бывает необходимо перенести или скопировать Windows 7 с одного HDD на другой по разным причинам, умирает HDD или нужно установить HDD с меньшим или наоборот с бОльшим объемом, в общем проблема решается довольно просто, при помощи 2 утилит dd и Gparted.
Загружаемся в Ubuntu LiveCD, у меня была загрузка по сети образа Ubuntu 12.04 LTS Desktop.
И первым делом копируем главную загрузочную запись (MBR):
dd if=/dev/sda of=/dev/sdb bs=512 count=1
После чего запускаем Ggparted и копируем разделы (она имеется в обычном ISO).
Не забываем проверить флаг boot на 100Мбайтном разделе.




P.S. Немного об утилите dd:
if=/dev/sda -- input file (входной файл, в данном случае диск с Windows 7)
of=/dev/sdb -- output file (выходной файл, в данном случае диск куда копируем)
bs=512 -- block size (Внимание! Операнд count имеет дело с блоками, а не с байтами! 512 блоков)
count=1 -- count (количество раз проведения операции копирования буфером)

MBR находится в 0 секторе первого раздела жесткого диска и занимает вместе с таблицей разделов ровно 512 байт. Поэтому и размер блока выбираем 512, а количество count единица - получаем 512 байт.
А если нам нужно не весь MBR, а только загрузочный код, который занимает первые 446 байт 0 сектора, то придется изменить размер блока:
# dd if=/dev/sda of=boot-code.mbr bs=446 count=1
Обратите внимание, на то, что сохраняем в файл, т.к. в устройство записать такой объем не получится, как уже говорилось выше, запись на устройства производится блоками по 512 байт.
Чтобы теперь записать сохраненный загрузчик, нужно получить блок размером в 512 байт, для этого сохраняем в другой файл таблицу разделов - это оставшиеся 66 байт после загрузочного кода - 446 байт.
# dd if=/dev/sdb of=part-table.mbr bs=1 count=66 skip=446
skip=n(блоков) Этот операнд пропускает n блоков от начала входного (if) файла(устройства), а затем копирует указанное количество блоков. Внимание! Операнд skip (как и count) имеет дело с блоками, а не с байтами! Поэтому размер блока следует выбирать вдумчиво.
И еще обратите внимание на то, что сейчас мы выбрали устройство /dev/sdb, т.к. нам нужна таблица разделов именно этого устройства, ведь мы туда собираемся копировать загрузчик с устройства /dev/sda :)
Теперь нужно "собрать" MBR из имеющихся кусочков:
# cat boot-code.mbr > mbr
# cat part-table.mbr >> mbr
Теперь наконец-то мы можем записать загрузочный код на устройство!
# dd if=mbr of=/dev/sdb bs=512 count=1

Ссылки по теме:
1. Команда dd и её использование.
2. Как мне скопировать загрузочную запись линуха на дискету?

вторник, 5 июня 2012 г.

Отключение ipv6 в Ubuntu

Для начала открываем, а если его еще нет, то создаем файл /etc/modprobe.d/aliases и добавляем такие строки:
alias net-pf-10 ipv6 off
alias net-pf-10 off
alias ipv6 off
Далее правим /etc/modprobe.d/blacklist.conf:
echo "blacklist ipv6" >> /etc/modprobe.d/blacklist.conf
И наконец редактируем файл /etc/default/grub, добавляя в конец опции GRUB_CMDLINE_LINUX_DEFAULT строку ipv6.disable=1, в итоге получаем:
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash ipv6.disable=1"
После чего даем команду sudo update-grub и перезагружаем систему.
На этом все, ipv6 будет отключен в системе. Для проверки отключен ли ipv6 выполняем:
$ sudo netstat -npl | grep -E "tcp6|udp6" | wc -l
Если видим 0, значит все сделано правильно.

Ссылки по теме:
1. Отключение ipv6 в Ubuntu / Debian

понедельник, 4 июня 2012 г.

JavaScript вывод даты модификации html документа в форматированном виде

<script language="JavaScript">
 <!--
 var month=new Array(12);
 month[0]="Января";
 month[1]="Февраля";
 month[2]="Марта";
 month[3]="Апреля";
 month[4]="Мая";
 month[5]="Июня";
 month[6]="Июля";
 month[7]="Августа";
 month[8]="Сентября";
 month[9]="Октября";
 month[10]="Ноября";
 month[11]="Декабря";
 var lastmoddate=Date.parse(document.lastModified); // Получает строку даты последней модификации
 var d=new Date(); d.setTime(lastmoddate);          // lastmoddate приводим к типу данных Date
 if(lastmoddate == 0) {                             // неизвестная дата (или 1 июля, 1970 GMT)
  var datestr="Неизвестна";
 } else {
  var datestr=d.getDate() + ' ' + month[d.getMonth()] + ' ' + d.getFullYear();
 }
  document.write ("Дата последнего изменения: " + datestr);
 //-->
<script>

Ссылки по теме:
1. Отображаем точное время и дату с помощью JavaScript.
2. Date.parse Синтаксис, Описание, примеры.

среда, 30 мая 2012 г.

Ubuntu 11.04, 11.10, 12.04, Midnight Commander, mc и Unity 3D исправляем проблему с F10 в терминале

Вот такой нехитрый скрипт установит и избавит от проблем с F10 при работе в терминале с mc в Ubuntu 11.04, 11.10 и 12.04.
#!/bin/sh

sudo apt-get install mc
gconftool-2 --set --type string "/apps/compiz-1/plugins/unityshell/screen0/options/panel_first_menu" "Disabled" # Unity Panel 3D

gconftool-2 --set --type bool "/apps/gnome-terminal/global/use_menu_accelerators" "false" # Gnome-Terminal

# И последний штрих для Ubuntu 12.04-LTS
[ ! -d ~/.config/gtk-3.0/ ] && mkdir -p ~/.config/gtk-3.0/
cat >~/.config/gtk-3.0/gtk.css <<_EOF
@binding-set NoKeyboardNavigation {
 unbind "F10"
}

* {
 gtk-key-bindings: NoKeyboardNavigation
}
_EOF
После чего придется закрыть все открытые окна терминала, чтобы изменения вступили в силу.

среда, 2 мая 2012 г.

Проблема с grub и русской локализацией в Ubuntu

В некоторых версиях Ubuntu почему-то отсутствует файл локализации ru.mo в Grub:
Ubuntu$ ls /boot/grub/locale/
en_AU.mo  en_CA.mo  en_GB.mo
В результате мы видим меню граба на английском языке, хотя при этом язык установлен правильно:
Ubuntu$ cat /boot/grub/grub.cfg | grep lang
  set lang=ru_RU

ВНИМАНИЕ, перед дальнейшими действиями сделайте резервные копии всех модифицированных вами файлов от Grub'а, например /etc/default/grub или /etc/grub.d/00_header, если вы счастливый обладатель нетбука с чипсетом i915 Ubuntu 11.10 на EeePC разрешение экрана 1024x600 в меню GRUB2.
Чтобы меню граба снова стало на русском, нужно сперва удалить пакет grub-pc:
Ubuntu$ sudo apt-get purge grub-pc
Затем снова установить:
Ubuntu$ sudo apt-get install grub-pc

Теперь проверяем появился ли ru.mo:
Ubuntu$ ls /boot/grub/locale/
en_AU.mo  en_CA.mo  en_GB.mo  ru.mo
Теперь можно перезагрузиться и проверить, что все нормально.
P.S. думаю и обычное копирование этого файла с "рабочей" системы так же исправит ситуацию, но я такой метод не проверял.

среда, 4 апреля 2012 г.

FreeBSD 9.0 GPT + gmirror

Столкнулся с проблемой реализации подобной связки GPT и gmirror на FreeBSD 9.0. Методом проб и ошибок получилась вот такая пошаговая инструкция:
0. Загружаемся с диска FreeBSD 9.0 amd64 в режиме LiveCD, система спросит логин, вводим root, а вместо пароля просто жмем Enter.
1. Удаляем все GPT данные с дисков:
FreeBSD# gpart destroy -F ada0
FreeBSD# gpart destroy -F ada1
2. Создаем GPT на 1 диске:
FreeBSD# gpart create -s gpt ada0
3. Создаем GPT разметку на 1 диске:
3.1 Загрузочный раздел
FreeBSD# gpart add -b 34 -s 94 -t freebsd-boot ada0
3.2 Раздел подкачки
FreeBSD# gpart add -s 5G -t freebsd-swap ada0
3.3 Файловую систему UFS
FreeBSD# gpart add -t freebsd-ufs ada0
3.4 Проверяем все ли так, как мы задумали
FreeBSD# gpart show
=>        34  2930277101  ada0  GPT  (1.4T)
          34          94     1  freebsd-boot  (47k)
         128     2097152     2  freebsd-swap  (1.0G)
     2097280  2928179855     3  freebsd-ufs  (1.4T)
3.5 Записываем загрузчик
FreeBSD# gpart bootcode -b /boot/pmbr -p /boot/gptboot -i 1 ada0
3.6 Копируем разметку GTP с 1 диска на 2 диск
FreeBSD# gpart backup ada0 | gpart restore -F ada1
3.7. Проверяем что теперь получилось:
FreeBSD# gpart show
=>        34  2930277101  ada0  GPT  (1.4T)
          34          94     1  freebsd-boot  (47k)
         128     2097152     2  freebsd-swap  (1.0G)
     2097280  2928179855     3  freebsd-ufs  (1.4T)

=>        34  2930277101  ada1  GPT  (1.4T)
          34          94     1  freebsd-boot  (47k)
         128     2097152     2  freebsd-swap  (1.0G)
     2097280  2928179855     3  freebsd-ufs  (1.4T)
4. загружаем gmirror:
FreeBSD# gmirror load
4.1 Создаем RAID1 для SWAP раздела
FreeBSD# gmirror label -v -b round-robin swap /dev/ada0p2
4.2 Добавляем 2-ой диск в зеркало:
FreeBSD# gmirror insert swap /dev/ada1p2
4.3 Создаем RAID1 для UFS раздела:
FreeBSD# gmirror label -v -b round-robin rootfs ada0p3
4.4 Добавляем 2-ой диск в зеркало:
FreeBSD# gmirror insert rootfs /dev/ada1p3
4.5 Удалить случайно созданные RAID1 разделы(если вдруг чего-то напутали выше)
FreeBSD# gmirror remove swap ada0p2 ada1p2
5. Создаем файловые системы на RAID1 разделах
FreeBSD# newfs -m 1 -U /dev/mirror/rootfs
6. УСТАНОВКА FreeBSD:
6.1 Монтируем созданную файловую систему в /mnt
FreeBSD# mount /dev/mirror/rootfs /mnt
6.2 Устанавливаем FreeBSD 9.0
FreeBSD# cd /usr/freebsd-dist
FreeBSD# sh
FreeBSD# export DESTDIR=/mnt
FreeBSD# for file in base.txz kernel.txz lib32.txz;
>do (cat $file | tar --unlink -xpJf - -C ${DESTDIR:-/}); done
6.3 Создаем /etc/fstab для установленной системы:
FreeBSD# cat >/mnt/etc/fstab << __EOF__
> #dev   #mount #fs #opts #dump #pass
> /dev/mirror/rootfs / ufs rw 1 1
> /dev/mirror/swap none swap sw 0 0
> __EOF__
6.4 Создаем /boot/loader.conf
FreeBSD# cat > /mnt/boot/loader.conf << __EOF__
> geom_mirror_load="YES"
> __EOF__
7. Отмонтируем зеркало
FreeBSD# umount /mnt
10. все готово, теперь можно перезагружаться и смотреть на результат

Ссылки по теме:
  1. HOWTO: Install FreeBSD 9.0 RELEASE (Root on UFS + ZFS, RAID1)
  2. Варианты загрузки FreeBSD: gmirror + GPT + UFS
  3. Использование gmirror для создания программного зеркалирования дисков
  4. [Solved] No gmirror in 9.0, now what?
  5. gmirror With Disk Partitions
  6. mirroring FreeBSD-9 disks with GPT

воскресенье, 26 февраля 2012 г.

Аналоги на sed для dos2unix и unix2dos

Команда dos2unix служит для преобразования форматов текстовых файлов MSDOS к UNIX формату, а команда unix2dos служит для преобразования форматов текстовых файлов UNIX к формату MSDOS и Windows. Известно, что форматы текстовых файлов в DOS и в UNIX немного отличаются: в DOS все строки заканчиваются парой символов CR и LF (возврат каретки /r и перевод строки /n), а UNIX использует только символ LF перевод строки /n, справедливо полагая, что второй символ совершенно излишен. Чтобы не устанавливать эти консольные утилиты dos2unix и unix2dos можно воспользоваться вот такими несложными функциями написанными с использованием sed в sh:
#!/bin/sh
dos2unix() {
 sed -i '' -e 's/'"$(printf '\015')"'$//' "$1"
}

unix2dos() {
 sed -i '' -e 's|$|'"$(printf '\015')"'|' "$1"
}

# Сделать окончания строк LF (Unix)
dos2unix file.test

# Сделать окончания строк CR/LF (Win or Dos)
unix2dos file.test
Запустить аналог на sed для dos2unix прямо в консоли можно командой:
FreeBSD$ sed -i '' -e 's/'"`printf '\015'`"'$//' file.name
А аналог на sed для unix2dos прямо в консоли выглядит так:
FreeBSD$ sed -i '' -e 's|$|'"`printf '\015'`"'|' file.name
Обработать рекурсивно все php файлы в текущем каталоге:
FreeBSD$ find . -name "*.php" -type f -exec sed -i '' -e 's/'"`printf '\015'`"'$//' {} \;
Причины НЕ устанавливать данные консольные утилиты могут быть разными, например невозможность их установить (случай с VPS или web хостингом), спортивный интерес ну или просто лень :)

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

Уменьшение количества соединений в состоянии TCP TIME_WAIT

TCP TIME_WAIT состояние характерно для завершающей стадии соединения.
Рассмотрим пример:
FIN 1 => 2
ACK 1 <=2
FIN  1 <= 2
ACK 1 => 2
В первой строке хост 1 инициирует завершение соединение отправкой пакета с флагом FIN. Хост 2, получив такой пакет подтверждает его флагом ACK, после чего в свою очередь отправляет хосту 1 свой пакет с флагом FIN и закрывает соединение. С момента получения этого пакета хостом 1, соединение переходит в состояние TIME_WAIT. Это время дается на случай, если последний ACK не дойдет до хоста 2, тогда он снова отправит FIN, на который хост 1 еще раз отошлет ACK.

Соединение может еще долгое время находится в состоянии TIME_WAIT, согласно RFC 1323 это время должно равнятся 2 минутам, двум msl (Maximum Segment Lifetime). MSL - это время, в течение которого сегмент может путешествовать по сети (RFC рекомендует 60 секунд). На загруженном сервере при таком значении msl число соединений time_wait расчет очень быстро, к тому же упомянутый rfc составлялся достаточно давно и пропускная способность каналов с тех пор возросла многократно, поэтому многие уменьшают это значение.
Во FreeBSD есть переменная sysctl net.inet.tcp.msl, по умолчанию равная 30 секундам. Можно уменьшить его до 20 или даже 15 секунд.
FreeBSD# echo "net.inet.tcp.msl=15000" >> /etc/sysctl.conf
FreeBSD# /etc/rc.d/sysctl start
В Linux немного сложнее, там msl спрятано в ядре в файле /net/tcp.h
#define TCP_TIMEWAIT_LEN (60*HZ)