Archive for the ‘ BSD ’ Category

Proftpd Bruteforce — Достойный ответ для подбирателей паролей

Бредовое вступление.
Давно я чтото не делился с вами своими простенькими поделиями на bash. Не от того что перестал их писать, просто лень описывать 🙂 Но вот чтото захотелось …. Ловите!

Последнее время розвелось много ботов-подбирателей паролей ко всему чему угодно. Рано или поздно это надоедает! Да и ничего хорошего от ботов ждать не приходится, только создают никому ненужную сетевую активность, засоряют логи и грузят сервис непотребными действиями. Решил дать достойный отпор, ибо задолбало!
Потихоньку-неспеша накропал такой вот скриптец, который брутфорсеров отправляет в некую таблицу фаервола, где им имитируется 99% потерь в канале 🙂

1. Скрипт, bash, FreeBSD … что это? Куда я попал и где мои вещи?
Ну, обо всем по порядку! Вот сам скрипт, он на bash:

root@black:~# cat /root/scripts/ftp_bots.sh
#!/usr/local/bin/bash

ban_log="/var/log/ftp_ban.log"

[ -f ${ban_log} ] || touch ${ban_log}

ftp_log="/var/log/proftpd.log"
ftp_bots=`grep -E -e 'no such user' ${ftp_log} |egrep -v '77.99.175.111|111.222.200.100' |sed -e 's/^.*from //' -e 's/\ .*//'| sort -nr | uniq -c | awk '{if($1>7)print $2}'`

for bot in $ftp_bots
 do
  TIME_NOW=`date "+%F %T"`

    pfctl -q -t bots -T test $bot

    if [ $? -eq 0 ]
        then
          continue
        else
         pfctl -q -t bruteforce -T test $bot
          if [ $? -eq 0 ]
            then
                continue
            else
                pfctl -q -t bruteforce -T add $bot
                pfctl -q -K $bot
                pfctl -q -k $bot
                echo "${TIME_NOW} --- Banned IP --- $bot" >> ${ban_log}
          fi
    fi
done

2. И это работает? Да ладно!!! Какието букавки непонятные … и что же этот скрипт делает?
Чуток опишу логику работы скрипта:
/var/log/ftp_ban.log — лог файл скрипта. Туда будут писаться дата-время-ip заблокированных ботов
ftp_log=»/var/log/proftpd.log» — лог FTP сервера
77.99.175.111|111.222.200.100 — некие IP адреса которые я хочу исключить из лога, заведомо считаем что это «белый список». Рекомендую вписать сюда свои IP, а также самых активных пользователей сервера. Заведомо даем им возможность делать ошибки в регистрации, мало ли что 🙂 Как обычно — разраб. сайта пароль на FTP забудет 🙂
ftp_bots — это переменная-список в которую попадут все кроме «белого списка», которые получили от proftpd ошибку — ‘no such user’ более 7 раз!
for bot in $ftp_bots — Ну дальше берем список $ftp_bots и смотрим есть ли IP из списка в таблице bots, если есть — следующий по списку ip, если нету, проверяем есть ли IP из списка в таблице bruteforce, если есть — следующий по списку ip, если нету, добавляем ip в таблицу bruteforce и делаем об этом запись в ${ban_log} и следующая итерация … до тех пор пока список $ftp_bots не закончится.

3. Таблицы, фаерволы … что это и как оно работает?
Теперь про таблицы и фаервол. В качестве фаервола — PF. Обожаю его, простой как двери и достаточно функциональный. В нем есть 2 таблицы — bots и bruteforce. В таблицу bots я закидываю «особо отличившихся» красавчиков. Эта таблица блочится для мира начисто:

block in log quick on $INET_IF from <bots> to any

Для тех же кто просто балуется брутфорсиком — есть табличка bruteforce для ip которой фаерволом имитируются потери в канале 99%

block in log quick on $INET_IF from <bruteforce> to any probability 99%

4. А если этих самых ботов тыщи???
Ну и чтобы не копить себе IP злоумышленников до бесконечности (они всетаки захламляют RAM) — по cron периодически очищаем табличку bruteforce от старых записей. Я настроил на очистку записей старше 86400 секунд, тоесть даю боту сутки на то чтоб подумал надо своим поведением. Также по крону запускаю скрипт ftp_bots.sh каждые 5 минут.

root@black:~# crontab -l
MAILTO=""
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
#### <- For clean entries from table SSH BRUTEFORCE older than 1 day ! -> ####
52      *       *       *       *       /sbin/pfctl -t bruteforce -T expire 86400
#### <= FTP bots => ####
*/5     *       *       *       *       /root/scripts/ftp_bots.sh

root@black:~#

5. А зачем нам лог в скрипте? С ним что делать?
Ну и на последок, так выглядит log файл. Его можно глянуть в случай если вам ктото позвонил и грозно заявил что «сервер перестал видеться в сети …». Там можно найти кого в последнее время банили чтобы оперативно розбанить:

root@black:~# cat /var/log/ftp_ban.log
2014-06-03 11:15:20 --- Banned IP --- 109.186.76.161
2014-06-03 19:45:00 --- Banned IP --- 199.193.71.123
2014-06-03 19:00:00 --- Banned IP --- 186.205.53.223
2014-06-03 19:00:00 --- Banned IP --- 91.121.195.189
2014-06-03 19:05:00 --- Banned IP --- 59.58.139.120
2014-06-04 12:25:00 --- Banned IP --- 109.186.76.161
2014-06-04 20:00:00 --- Banned IP --- 199.193.71.123
2014-06-04 20:55:00 --- Banned IP --- 186.205.53.223
2014-06-04 20:55:01 --- Banned IP --- 91.121.195.189
2014-06-04 20:55:01 --- Banned IP --- 59.58.139.120
root@black:~#

Пробуйте … пишите комменты, замечания и т.д.
P.S. Некоторые в таких случаях еще заявляют — а как же клиенты за NAT, многопользовательские сети/сервера и прочее. IP залочен одним нехорошим клиентом — остальная масса пользователей за NAT тоже получается залочены. Мой ответ прост — да мне пофигу! Мой сервер, мой ресурс и мое решение. Если какойто Вася поймал вирь и от этого 200 клиентов рядом с ним перестали видеть мой сервер — мне жаль их 🙂 Пусть почитают с соседнего сервера статью про маленьких пушистых котиков …

Хай щастить!

Настройка nginx + GeoIP на FreeBSD

Зачем это надо? Да много чего можно наворотить! Например разным странам выдавать разный контент, проксировать трафик на разные сервера и тд. Мне, например, для ограничения нежелательного трафика на некий тестовый web-сервер. Хочу дать туда доступ только из Украины, остальных — в баню!
У меня уже был установлен и настроен nginx, поэтому тут упомяну только о включении в его сборку необходимого модуля.
Для начала я установил GeoIP из портов:

root@gw:~# cd /usr/ports/net/GeoIP
root@gw:/usr/ports/net/GeoIP# make install clean

После этого проверил стоит ли в собранном ранее nginx необходимый флаг HTTP_GEOIP:

root@gw:/usr/ports/net/GeoIP# cd /usr/ports/www/nginx
root@gw:/usr/ports/www/nginx# make config

Читать полностью

FreeBSD — настройка bacula с SSL шифрованием трафика

Сначала чуть данных из wiki
Bacula — кроссплатформенное клиент-серверное программное обеспечение, позволяющее управлять резервным копированием, восстановлением, и проверкой данных по сети для компьютеров и операционных систем различных типов.
Итак, это то что мне нужно! Более подробно рассмотрим из чего состоит bacula, это даст больше понимания о том как она работает.
Director (DIR) — осуществляет централизованный контроль и администрирование всего комплекса задач. Планирование и управление заданиями на резервное копирование (Job). Обслуживание Каталога (Catalog) — центральной БД для хранения метаданных.
File Daemon (FD) — сервис, выполняющий непосредственное копирование, восстановление и проверку данных по запросу Director. File Daemon должен быть установлен на каждой клиентской машине. File Daemon обменивается информацией с Director и Storage Daemon.
Storage Daemon (SD) — читает и пишет данные на физический носитель: диск, ленту, DVD, USB.
Console — управляющая консоль оператора или администратора. Поддерживаются ACL для разных пользователей консоли. Типы консолей: TTY, wxWidgets (GUI) для Linux, Unix, Win32, GNOME (GUI), несколько веб-интерфейсов, Qt4.
Catalog database — база данных SQL : MySQL, PostgreSQL, или SQLite для хранения метаданных.
Tray Monitor — апплет GNOME/KDE/Win32 GUI для показа активности Director, File daemons, Storage daemon в реальном времени.

Вот как выглядит работа настроенной системы:
Bacula applications

Что такого уникального я опишу в данной статье? Зачем она вообще нужна? Такие вопросы лезли мне в голову когда я брался это писать.
Хочу написать, в первую очередь для себя! Дело в том что данную систему я настраивал уже 3 раза и каждый раз рассчитывал на то что «нагуглю» рецепт и спокойненько настрою, тем более что в голове уже есть понимание что к чему. Но каждый раз было одно и тоже — все рецепты в сети оказывались для меня непригодны по разным причинам.
Сразу скажу, эта заметка не подходит для тех кто будет настраивать систему первый раз не имея понимания «что это и как его едят». Делаю для себя чтоб в следующий раз заюзать по принципу «Ctrl + C, Ctrl + V» потом минимально подправил и «поехали». Тут нету разжеванных опций и подробных описаний, за этим либо в google либо на официальный сайт в документацию.

Чего мы хотим?
Я хочу не так много — бекапить сервера через сеть Интернет с шифрованием трафика. Просто звучит, но чтоб настроить придется поработать 🙂

Что нужно подготовить перед тем как взяться за настройку? Многое … пойдем по порядку.
1. Определим кто есть кто! Сразу оговорюсь что все сервера у меня под FreeBSD. Но для Linux статья вполне сойдет, только обратите внимание на пути к директориям/файлам. Также отмечу, что у меня 2 физических сервера, поэтому на одном будет DIR + SD, а второй будет FD (его будем бэкапить). В дальнейшем данное решение абсолютно просто масштабируется. Я опишу это в конце заметки.

dir1.domain.ua — директор, тут же будет расположен каталог (БД mysql)
sd1.domain.ua — сторадж, тут будут храниться бэкапы в виде файлов (pools) на HDD
fd1.domain.ua — клиент, это та машина которую мы будем бэкапить

Эти имена должны правильно резолвиться на любой из данных ПК. Это можно реализовать либо создав соответствующие записи в DNS в виде host A либо просто прописать в /etc/hosts

Например на каждой машине прописать в /etc/hosts

111.111.111.111 dir1.domain.ua sd1.domain.ua
111.111.222.222 fd1.domain.ua

Проверить с помощью ping связь между собой для каждого хоста.

2. Определиться какие части системы на каких хостах (серверах) будут установлены. У меня будет так:
111.111.111.111 — директор (DIR) + БД MySQL (Catalog) + сторадж демон (SD) + консоль управления (Console)
111.111.222.222 — клиент (FD)

3. Настроить фаервол. Если он есть то необходимо открыть порты на вход/выход для хостов:
Console -> DIR:9101
DIR -> SD:9103
DIR -> FD:9102
FD -> SD:9103

4. На директоре установить и настроить MySQL. Я писал об этом ранее, вполне подойдет и для этой задачи.

5. Сгенерить необходимые SSL сертификаты. Этот процесс я также описывал ранее.
Важно! В процессе генерации не забываем прописывать корректно параметр Common Name (eg, YOUR name) Прописывать туда нужно FQDN сервера для которого данный сертификат генерится. Например в процессе генерации запроса на сертификат для сервера fd1.domain.ua параметр Common Name будет fd1.domain.ua Это очень важно!

6. Скопировать сертификаты на хосты. Создаем директорию /usr/local/etc/bacula-ssl и копируем (rsync, scp) туда сертификаты таким образом:
DIR, SD — ca.crt, dir1.crt, dir1.key, sd1.crt, sd1.key
FD — ca.crt, fd1.crt, fd1.key

7. Установить порты (напомню что я настраиваю на FreeBSD):
dir1.domain.ua (он же sd1.domain.ua) — bacula-server с опциями MYSQL, NLS, OPENSSL
fd1.domain.ua — bacula-client с опциями NLS, OPENSSL
И добавить в rc.conf опции для автозагрузки
На сервере dir1.domain.ua

# <= Bacula => #
bacula_dir_enable="YES"
bacula_sd_enable="YES"

На сервере fd1.domain.ua

# <= Bacula => #
bacula_fd_enable="YES"

8. На сервере dir1.domain.ua настроить в MySQL базу данных для bacula. Для этого есть готовые скрипты, которые нужно выполнить от рута:

root@dir1# /usr/local/share/bacula/grant_mysql_privileges
root@dir1# /usr/local/share/bacula/create_mysql_database
Creation of bacula database succeeded.
root@dir1# /usr/local/share/bacula/make_mysql_tables
Creation of Bacula MySQL tables succeeded.
root@dir1#

9. Создать на сервере хранения директорию для бэкапов и дать права :

root@dir1# mkdir -p /home/bacula/pools

И дать права бакуле туда писать/читать:

root@dir1# chown bacula:bacula /home/bacula

10. Ну и собственно сами конфиги, начнем с простого — файл-сервер (FD), это у нас хост fd1.domain.ua
Ранее мы на этом серваке установили bacula-client и настроили его автозапуск.
Также напомню что на сервере уже должны быть сертификаты, у меня они расположены в /usr/local/etc/bacula-ssl:

root@fd1:~# ls -l /usr/local/etc/bacula-ssl/
total 16
-rw-r--r--  1 root  bacula  1655 23 окт 15:38 ca.crt
-rw-r--r--  1 root  bacula  4632 23 окт 15:43 fd1.crt
-rw-r--r--  1 root  bacula  1679 23 окт 15:42 fd1.key
root@fd1:~#

Теперь настроим конфиг:

root@fd1:~# cat /usr/local/etc/bacula/bacula-fd.conf |egrep -v '^#|^$'
Director {
  Name = dir1
  Password = "fd1_5XLGGiNNxLfjMxCcfgLM"
  TLS Enable = yes
  TLS Require = yes
  TLS Certificate = /usr/local/etc/bacula-ssl/fd1.crt
  TLS Key = /usr/local/etc/bacula-ssl/fd1.key
  TLS CA Certificate File = /usr/local/etc/bacula-ssl/ca.crt
  TLS Verify Peer = yes
  TLS Allowed CN = "fd1.domain.ua"
  TLS Allowed CN = "sd1.domain.ua"
  TLS Allowed CN = "dir1.domain.ua"
}
FileDaemon {
  Name = fd1
  FDport = 9102
  WorkingDirectory = /var/db/bacula
  Pid Directory = /var/run
  Maximum Concurrent Jobs = 20
  FDAddress = fd1.domain.ua
  Heartbeat Interval = 30 sec
  TLS Enable = yes
  TLS Require = yes
  TLS Certificate = /usr/local/etc/bacula-ssl/fd1.crt
  TLS Key = /usr/local/etc/bacula-ssl/fd1.key
  TLS CA Certificate File = /usr/local/etc/bacula-ssl/ca.crt
}
Messages {
  Name = Standard
  director = dir1 = all, !skipped, !restored
}
root@fd1:~#

Ну вот, первая ласточка пошла 🙂 УРА! Перегрузите сервис (или запустите) стандартными средствами:

root@fd1:~# service bacula-fd restart

Настройку FD можно считать завершенной! Идем дальше …

11. Дальше чуть сложнее но тоже осилим! Настройка сервера хранения бэкапов (SD) — это у нас хост sd1.domain.ua Напомню что у меня DIR и SD на одном сервере, если у вас на разных, предварительно нужно на SD-сервер скопировать необходимые сертификаты ca.crt, sd1.crt и ключ sd1.key

root@dir1:~# cat /usr/local/etc/bacula/bacula-sd.conf |egrep -v '^#|^$'
Storage {
  Name = sd1
  SDPort = 9103
  WorkingDirectory = "/var/db/bacula"
  Pid Directory = "/var/run"
  Maximum Concurrent Jobs = 20
  SDAddress = sd1.domain.ua
  Heartbeat Interval = 30 sec
  TLS Enable = yes
  TLS Require = yes
  TLS Verify Peer = no
  TLS CA Certificate File = /usr/local/etc/bacula-ssl/ca.crt
  TLS Key = /usr/local/etc/bacula-ssl/sd1.key
  TLS Certificate = /usr/local/etc/bacula-ssl/sd1.crt
}
Director {
  Name = dir1
  Password = "sd1_ho6a&teSuA@CC2HnEEgu"
  TLS Enable = yes
  TLS Require = yes
  TLS Verify Peer = yes
  TLS Allowed CN = "fd1.domain.ua"
  TLS Allowed CN = "dir1.domain.ua"
  TLS CA Certificate File = /usr/local/etc/bacula-ssl/ca.crt
  TLS Key = /usr/local/etc/bacula-ssl/sd1.key
  TLS Certificate = /usr/local/etc/bacula-ssl/sd1.crt
}
Device {
  Name = FileStorage
  Media Type = File
  Archive Device = /home/bacula/pools
  LabelMedia = yes;
  Random Access = Yes;
  AutomaticMount = yes;
  RemovableMedia = no;
  AlwaysOpen = no;
}
Messages {
  Name = Standard
  director = dir1 = all
}
root@dir1:~#

Перегрузите сервис (или запустите) стандартными средствами:

root@dir1:~# service bacula-sd restart

Настройку SD можно считать завершенной! Идем дальше …

12. Настроим директор (DIR) — это основная часть системы. Тут будет много всяких параметров, углубляться не буду, для этого есть официальные доки. Вот что у меня:

root@dir1:~# cat /usr/local/etc/bacula/bacula-dir.conf |egrep -v '^#|^$'
Director {
  Name = dir1
  DIRport = 9101
  QueryFile = "/usr/local/share/bacula/query.sql"
  WorkingDirectory = "/var/db/bacula"
  PidDirectory = "/var/run"
  Maximum Concurrent Jobs = 1
  Password = "dir1_Ag@6Uzp8tHUW6PuRumc"
  Messages = Daemon
  DirAddress = dir1.domain.ua
  Heartbeat Interval = 30 sec
  TLS Enable = yes
  TLS Require = yes
  TLS Certificate = /usr/local/etc/bacula-ssl/dir1.crt
  TLS Key = /usr/local/etc/bacula-ssl/dir1.key
  TLS CA Certificate File = /usr/local/etc/bacula-ssl/ca.crt
  TLS Verify Peer = yes
  TLS Allowed CN = "fd1.domain.ua"
  TLS Allowed CN = "sd1.domain.ua"
  TLS Allowed CN = "dir1.domain.ua"
}
Job {
  Name = "RestoreFiles"
  Type = Restore
  Client=fd1                
  FileSet="Full Set"                  
  Storage = sd1                      
  Pool = Default
  Messages = Standard
  Where = /tmp/bacula-restores
}
FileSet {
  Name = "Full Set"
  Include {
    Options {
      signature = MD5
    }
    File = /usr/local/sbin
  }
  Exclude {
    File = /var/db/bacula
    File = /tmp
    File = /proc
    File = /tmp
    File = /.journal
    File = /.fsck
  }
}
Schedule {
  Name = "WeeklyCycle"
  Run = Full 1st sun at 23:05
  Run = Differential 2nd-5th sun at 23:05
  Run = Incremental mon-sat at 23:05
}
Schedule {
  Name = "WeeklyCycleAfterBackup"
  Run = Full sun-sat at 23:10
}
FileSet {
  Name = "Catalog"
  Include {
    Options {
      signature = MD5
    }
    File = "/var/db/bacula/bacula.sql"
  }
}
Storage {
  Name = sd1
  Address = sd1.domain.ua                # Use ONLY a FQDN here
  SDPort = 9103
  Password = "sd1_ho6a&teSuA@CC2HnEEgu"
  Device = FileStorage
  Media Type = File
  TLS Enable = yes
  TLS Require = yes
  TLS Certificate = /usr/local/etc/bacula-ssl/fd1.crt
  TLS Key = /usr/local/etc/bacula-ssl/fd1.key
  TLS CA Certificate File = /usr/local/etc/bacula-ssl/ca.crt
}
Catalog {
  Name = MyCatalog
  dbname = "BACULA_DB"; DB Address = "127.0.0.1"; dbuser = "BACULA_USER"; dbpassword = "bacula_db_password"
}
Messages {
  Name = Standard
  mailcommand = "/usr/local/sbin/bsmtp -h localhost -f "\(Bacula\) \<%r\>" -s "Bacula: %t %e of %c %l" %r"
  operatorcommand = "/usr/local/sbin/bsmtp -h localhost -f "\(Bacula\) \<%r\>" -s "Bacula: Intervention needed for %j" %r"
  mail = admin@domain.ua = all, !skipped            
  operator = admin@domain.ua = mount
  console = all, !skipped, !saved
  append = "/var/log/bacula.log" = all, !skipped
  catalog = all
}
Messages {
  Name = Daemon
  mailcommand = "/usr/local/sbin/bsmtp -h localhost -f "\(Bacula\) \<%r\>" -s "Bacula daemon message" %r"
  mail = admin@domain.ua = all, !skipped            
  console = all, !skipped, !saved
  append = "/var/log/bacula.log" = all, !skipped
}
Pool {
  Name = Default
  Pool Type = Backup
  Recycle = yes                       # Bacula can automatically recycle Volumes
  AutoPrune = yes                     # Prune expired volumes
  Volume Retention = 365 days         # one year
}
Pool {
  Name = File
  Pool Type = Backup
  Recycle = yes                       # Bacula can automatically recycle Volumes
  AutoPrune = yes                     # Prune expired volumes
  Volume Retention = 90 days          # 90 days
  Maximum Volume Bytes = 50G          # Limit Volume size to something reasonable
  Maximum Volumes = 100               # Limit number of Volumes in Pool
}
Pool {
  Name = Scratch
  Pool Type = Backup
}
Console {
  Name = mon
  Password = "console_"
  CommandACL = status, .status
}
@/usr/local/etc/bacula-fd1.conf
root@dir1:~#

Что такого необычного мы видим в этом конфиге? Да ничего особенного, все просто «как двери». В конце данного конфига включен дополнительный файл настроек, в котором прописаны уникальные настройки для fd1.

13. И наконец конфиг бэкапа для fd1, тот что /usr/local/etc/bacula-fd1.conf

root@dir1:~# cat /usr/local/etc/bacula-fd1.conf |egrep -v '^#|^$'
Job {
    Name = "www-backup"
    Type = Backup
    Level = Full
    Client = fd1
    FileSet = "www Set"
    Schedule = "WeeklyCycle_www"
    Messages = Standard
    Pool = www-pool
    Full Backup Pool = www-pool-FULL
    Differential Backup Pool = www-pool-DIFF
    Incremental Backup Pool = www-pool-INCR
    Write Bootstrap = "/var/db/bacula/www-fd1.bsr"
    Priority = 3
}
FileSet {
  Name = "www Set"
  Include {
    Options {
      signature = MD5
      compression = GZIP
      recurse = yes
      xattrsupport = yes
    }
    File = /etc
    File = /usr/local/etc
    File = /home/backup
    File = /root
    File = /usr/local/www
    File = /usr/home/user1/htdocs
    File = /usr/home/user2/htdocs
    File = /usr/home/user3/htdocs
  }
  Exclude {
    File = /usr/local/www/apache22/data/somedomain.org.ua/drupal/sites/default/files
  }
}
Schedule {
  Name = "WeeklyCycle_www"
  Run = Level=Full 1st sun at 4:05
  Run = Level=Differential 2nd-5th sun at 4:02
  Run = Level=Incremental mon-sat at 4:07
}
Client {
  Name = fd1
  Address = fd1.domain.ua
  FDPort = 9102
  Catalog = MyCatalog
  Password = "fd1_5XLGGiNNxLfjMxCcfgLM"
  File Retention = 45 days
  Job Retention = 6 months
  AutoPrune = yes
  TLS Enable = yes
  TLS Require = yes
  TLS Certificate = /usr/local/etc/bacula-ssl/fd1.crt
  TLS Key = /usr/local/etc/bacula-ssl/fd1.key
  TLS CA Certificate File = /usr/local/etc/bacula-ssl/ca.crt
}
Pool {
  Name = www-pool
  Pool Type = Backup
  Recycle = yes                     # Bacula can automatically recycle Volumes
  AutoPrune = yes                   # Prune expired volumes
  Volume Retention = 65 days        # 65 days
  Recycle Oldest Volume = yes
  Maximum Volume Bytes = 4400m      # Limit Volume size to something reasonable
  Maximum Volumes = 7               # Limit number of Volumes in Pool
  Label Format = "www_pool-vol"
  Storage = sd1
}
Pool {
  Name = www-pool-FULL
  Pool Type = Backup
  Recycle = yes                     # Bacula can automatically recycle Volumes
  AutoPrune = yes                   # Prune expired volumes
  Volume Retention = 60 days        # 60 days
  Recycle Oldest Volume = yes
  Maximum Volume Bytes = 4400m      # Limit Volume size to something reasonable
  Maximum Volumes = 7               # Limit number of Volumes in Pool
  Label Format = "www_pool-FULL-vol"
  Storage = sd1
}
Pool {
  Name = www-pool-DIFF
  Pool Type = Backup
  Recycle = yes                     # Bacula can automatically recycle Volumes
  AutoPrune = yes                   # Prune expired volumes
  Volume Retention = 60 days        # 60 days
  Recycle Oldest Volume = yes
  Maximum Volume Bytes = 4400m      # Limit Volume size to something reasonable
  Maximum Volumes = 7               # Limit number of Volumes in Pool
  Label Format = "www_pool-DIFF-vol"
  Storage = sd1
}
Pool {
  Name = www-pool-INCR
  Pool Type = Backup
  Recycle = yes                     # Bacula can automatically recycle Volumes
  AutoPrune = yes                   # Prune expired volumes
  Volume Retention = 60 days        # 60 days
  Recycle Oldest Volume = yes
  Maximum Volume Bytes = 4400m      # Limit Volume size to something reasonable
  Maximum Volumes = 7               # Limit number of Volumes in Pool
  Label Format = "www_pool-INCR-vol"
  Storage = sd1
}
root@dir1:~#

Как видим, тут описано само задание на бэкап (Job), также описан FileSet — собственно те файлы/папки которые хотим бэкапить, время/день недели когда делаются бэкапы Shedule, а также пулы. Все относительно просто, для детального описания каждой опции смотрите официальную документацию.

Перегрузите сервис (или запустите) стандартными средствами:

root@dir1:~# service bacula-dir restart

Настройку DIR можно считать завершенной! Идем дальше …

14. Настроим консоль. Консоль я буду пользовать на сервере там же где и директор (dir1). Для настройки рихтуем конфиг:

root@dir1:~# cat /usr/local/etc/bacula/bconsole.conf
#
# Bacula User Agent (or Console) Configuration File
#

Director {
  Name = dir1
  DIRport = 9101
  address = dir1.domain.ua
  Password = "dir1_Ag@6Uzp8tHUW6PuRumc"

  TLS Enable = yes
  TLS Require = yes
  TLS Certificate = /usr/local/etc/bacula-ssl/dir1.crt
  TLS Key = /usr/local/etc/bacula-ssl/dir1.key
  TLS CA Certificate File = /usr/local/etc/bacula-ssl/ca.crt
}
root@dir1:~#

Настройку консоли можно считать завершенной.

15. Тестируем! Для этого на сервере dir1.domain.ua запускаем в root-овой консоли bconsole:

root@dir1:~# bconsole
Connecting to Director dir1.domain.ua:9101
1000 OK: dir1 Version: 5.2.12 (12 September 2012)
Enter a period to cancel a command.
*

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

*status all
dir1 Version: 5.2.12 (12 September 2012) i386-portbld-freebsd9.0 freebsd 9.0-RELEASE-p3
Daemon started 23-Mar-14 20:36. Jobs: run=4, running=0 mode=0,0
 Heap: heap=0 smbytes=80,026 max_bytes=113,890 bufs=296 max_bufs=327

Scheduled Jobs:
Level          Type     Pri  Scheduled          Name               Volume
===================================================================================
Incremental    Backup     3  28-Mar-14 04:07    www-backup         Vol_1
====

Running Jobs:
Console connected at 27-Mar-14 11:16
No Jobs running.
====

Terminated Jobs:
 JobId  Level    Files      Bytes   Status   Finished        Name
====================================================================
   379  Incr        101    6.737 M  OK       18-Mar-14 04:07 www-backup
   380  Incr         27    6.536 M  OK       19-Mar-14 04:07 www-backup
   381  Incr      1,634    18.16 M  OK       20-Mar-14 04:07 www-backup
   382  Incr         18    6.401 M  OK       21-Mar-14 04:07 www-backup
   383  Incr         17    6.402 M  OK       22-Mar-14 04:07 www-backup
   384  Diff         42    18.34 M  Error    23-Mar-14 04:02 www-backup
   385  Incr         27    12.79 M  OK       24-Mar-14 04:07 www-backup
   386  Incr      1,413    15.02 M  OK       25-Mar-14 04:07 www-backup
   387  Incr         22    6.412 M  OK       26-Mar-14 04:07 www-backup
   388  Incr         29    6.863 M  OK       27-Mar-14 04:07 www-backup

====
Connecting to Storage daemon sd1 at sd1.domain.ua:9103

sd1 Version: 5.2.12 (12 September 2012) i386-portbld-freebsd9.0 freebsd 9.0-RELEASE-p3
Daemon started 23-Mar-14 20:36. Jobs: run=4, running=0.
 Heap: heap=0 smbytes=90,823 max_bytes=224,190 bufs=93 max_bufs=113
 Sizes: boffset_t=8 size_t=4 int32_t=4 int64_t=8 mode=0,0

Running Jobs:
No Jobs running.
====

Jobs waiting to reserve a drive:
====

Terminated Jobs:
 JobId  Level    Files      Bytes   Status   Finished        Name
===================================================================
   379  Incr        101    6.755 M  OK       18-Mar-14 04:07 www-backup
   380  Incr         27    6.540 M  OK       19-Mar-14 04:07 www-backup
   381  Incr      1,634    18.39 M  OK       20-Mar-14 04:07 www-backup
   382  Incr         18    6.403 M  OK       21-Mar-14 04:07 www-backup
   383  Incr         17    6.405 M  OK       22-Mar-14 04:07 www-backup
   384  Diff         42    18.14 M  Error    23-Mar-14 04:02 www-backup
   385  Incr         27    12.80 M  OK       24-Mar-14 04:07 www-backup
   386  Incr      1,413    15.22 M  OK       25-Mar-14 04:07 www-backup
   387  Incr         22    6.416 M  OK       26-Mar-14 04:07 www-backup
   388  Incr         29    6.867 M  OK       27-Mar-14 04:07 www-backup
====

Device status:
Device "FileStorage" (/home/bacula/pools) is not open.
====

Used Volume status:
====

====

Connecting to Client fd1 at fd1.domain.ua:9102

fd1 Version: 5.2.12 (12 September 2012)  amd64-portbld-freebsd9.0 freebsd 9.0-RELEASE-p3
Daemon started 20-Mar-14 12:11. Jobs: run=7 running=0.
 Heap: heap=0 smbytes=23,861 max_bytes=372,763 bufs=73 max_bufs=215
 Sizeof: boffset_t=8 size_t=8 debug=0 trace=0
Running Jobs:
Director connected at: 27-Mar-14 11:16
No Jobs running.
====

Terminated Jobs:
 JobId  Level    Files      Bytes   Status   Finished        Name
======================================================================
   379  Incr        101    6.737 M  OK       18-Mar-14 04:07 www-backup
   380  Incr         27    6.536 M  OK       19-Mar-14 04:07 www-backup
   381  Incr      1,634    18.16 M  OK       20-Mar-14 04:07 www-backup
   382  Incr         18    6.401 M  OK       21-Mar-14 04:07 www-backup
   383  Incr         17    6.402 M  OK       22-Mar-14 04:07 www-backup
   384  Diff         42    18.34 M  Error    23-Mar-14 04:02 www-backup
   385  Incr         27    12.79 M  OK       24-Mar-14 04:07 www-backup
   386  Incr      1,413    15.02 M  OK       25-Mar-14 04:07 www-backup
   387  Incr         22    6.412 M  OK       26-Mar-14 04:07 www-backup
   388  Incr         29    6.863 M  OK       27-Mar-14 04:07 www-backup
====

*

Можно ради интереса запустить бэкап прямо сейчас, не дожидаясь ночного автозапуска (учтите нагрузку на сервер! Если у вас боевой сервер — лучше это делать в момент наименьшей нагрузки … вечером/ночью/рано утром):

*run job=www-backup

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

16. И пара слов про восстановление. В случай необходимости восстановить файлы идем в консоль и делаем следующее:

*restore

После чего выбрать те Job в которых находится необходимый вам файл. В случае как у меня, когда делается full бэкап раз в месяц, а каждый день либо diff либо incremental — нужно выбирать все Job-ы от full и до последнего Incremental-а. Дальше все просто, следуйте указаниям мастера восстановления.

Что делать если хотим добавить еще один FD в эту систему?
Да все проще простого:
— на новом сервере fd2 установить bacula-client и настроить также как описано выше для fd1
— на сервере dir1 копируем файлик настроек FD /usr/local/etc/bacula-fd1.conf в какойнить /usr/local/etc/bacula-fd2.conf
— генерим для fd2.domain.ua сертификат и ключ
— прописываем FileSet в новом конфиге и меняем пароль/сертификаты. По желанию можно по-другому назвать пулы или перестроить время бэкапа
Вот собственно, и все. 5 минут работы и сервак добавлен в систему. Просто? Ато!
Так же просто «перенести» SD на другую железку. Или подключить второй SD, для того чтобы разные FD бэкапить на разные SD. Система очень гибко настраивается — это дополнительный плюс.

P.S. Получилось не очень стройно, както сумбурно и не особо детально. Но статья рассчитана скорее на человека который уже имеет понимание и просто хочет «по быстрому подкинуть конфиги» и с минимальными правками стартонуть систему, а не на тех кто совсем с нуля осваивается. Можно конечно и с нуля разобраться, но придется изрядно поглядеть в официальные доки.

Mysql server на FreeBSD

Очень часто в различных проэктах используется БД mysql. Я хочу показать как я инсталлирую ее на примере своего домашнего сервера под FreeBSD 9.2
Установку я делал из портов:

root@gw:~# cd /usr/ports/databases/mysql56-server
root@gw:~# make install clean

Автозапуск при старте системы нужно прописать в rc.conf

root@gw:~# echo 'mysql_enable="YES"' >> /etc/rc.conf

Основной конфигурационный файл mysql-server в FreeBSD находится тут /var/db/mysql/my.cnf
Я сгенерил свой конфиг с помощью online конфигуратора от percona (ссылка есть в шапке конфига). В конфигураторе вводил что у меня 2GB RAM и честный сервер (не виртуалка). А также указал что это будет Slave-сервер, поэтому ID = 11. Вот что получилось в итоге:

# Generated by Percona Wizard (http://tools.percona.com/)
# Configuration name home generated for admin@somedomain.net.ua

[mysql]

# CLIENT #
port                           = 3306
socket                         = /tmp/mysql.sock

[mysqld]

# GENERAL #
user                           = mysql
default-storage-engine         = InnoDB
socket                         = /tmp/mysql.sock
pid-file                       = /var/db/mysql/mysql.pid

# MyISAM #
key-buffer-size                = 32M
myisam-recover                 = FORCE,BACKUP

# SAFETY #
max-allowed-packet             = 16M
max-connect-errors             = 1000000

# DATA STORAGE #
datadir                        = /var/db/mysql/

# BINARY LOGGING #
log-bin                        = /var/db/mysql/mysql-bin
binlog_format                  = mixed
expire-logs-days               = 7
sync-binlog                    = 1

# REPLICATION #
server-id                      = 11
log-slave-updates              = 1
relay-log                      = /var/db/mysql/relay-bin
slave-net-timeout              = 60
sync-master-info               = 1
sync-relay-log                 = 1
sync-relay-log-info            = 1

# CACHES AND LIMITS #
tmp-table-size                 = 32M
max-heap-table-size            = 32M
query-cache-type               = 0
query-cache-size               = 0
max-connections                = 500
thread-cache-size              = 50
open-files-limit               = 65535
table-definition-cache         = 1024
table-open-cache               = 2048

# INNODB #
innodb-flush-method            = O_DIRECT
innodb-log-files-in-group      = 2
innodb-log-file-size           = 128M
innodb-flush-log-at-trx-commit = 1
innodb-file-per-table          = 1
innodb-buffer-pool-size        = 1024M

# LOGGING #
log-error                      = /var/db/mysql/mysql-error.log
log-queries-not-using-indexes  = 1
slow-query-log                 = 1
slow-query-log-file            = /var/db/mysql/mysql-slow.log

Итак, конфиг есть — запускаем mysql-server так:

root@gw:~# service mysql-server start

Убедиться что он работает можно по логам — /var/db/mysql/mysql-error.log или командой:

root@gw:~# sockstat |grep mysql
mysql    mysqld     74112 16 tcp4 6 *:3306                *:*
mysql    mysqld     74112 18 stream /tmp/mysql.sock
root@gw:~#

FreeBSD 9.x — обновление perl5.12 или perl5.14 до 5.16 … 5.18

Увидел при очередном обновлении портов что версия Perl5.14 уже считается старой и рекомендацию обновиться.
Как любой порядочный фряшник, полез читать что пишут по этому поводу в /usr/ports/UPDATING и вот что нашел:

20131120:
  AFFECTS: users of lang/perl5.12 lang/perl5.14 lang/perl5.16 and lang/perl5.18
  AUTHOR: mat@FreeBSD.org

  The THREADS option has been enabled by default in all Perl. If you're using
  binary packages you need to do :

    # pkg install -Rf perl5

  If you'
re not using binary packages, and want to switch from non threaded
  Perl to threaded Perl, you need to recompile and reinstall most ports
  depending on Perl. Supposing you have Perl 5.16, you would do:

  Portupgrade users:
    0) Fix pkgdb.db (for safety):
        pkgdb -Ff

    1) Change the option in lang/perl5.16:
        make -C /usr/ports/lang/perl5.16 config

    2) Reinstall everything that depends on Perl:
        portupgrade -fr lang/perl5.16

  Portmaster users:
    1) Change the option in lang/perl5.16:
        make -C /usr/ports/lang/perl5.16 config

    2) Reinstall everything that depends on Perl:
        portmaster -r perl5-

  Note: The installed Perl package was named perl and is now named perl5, if
        you have not updated your installation in a long time, you may need to
        use "perl-" here.

Но проделав все пункты для portupgrade ничего в результате не обновилось, вообще ничего толкового не произошло. Версия Perl осталась прежней — 5.14. Читать полностью

apache-itk-mpm и виртуальный хостинг

Итак, рано или поздно возникает задача в духе: «А как бы нам организовать хостинг нескольких клиентов с их сайтами так чтобы они не имели друг к другу доступа и не было проблем с доступом к файлам через web/ftp/ssh?». Тут уже обычный стандартный apache не справляется и нужно городить некую более сложную конфигурацию. К счастью, задача эта не уникальна и поэтому давным давно есть готовые решения. Одним из них есть модификация apache2 под названием apache-itk-mpm. Он позволяет запускать от имени определенного в конфигах системного пользователя некий виртуалхост апача. Тоесть получаем чтото в духе некоего изолированного контейнера для нужного пользователя или ряда оных. Туманно объяснил, но по конфигам это более понятно. Итак, поехали! Читать полностью

Ejabberd на FreeBSD с авторизацией в Active Directory

Установка ничем особенным не отличается, как обычно, собрал из портов.
А вот конфигурация весьма интересная и отличается крайней невменяемостью, которую ejabberd унаследовал от языка программирования, на котором он написан — erlang. Многие админы сломали голову в попытках настроить данный софт, и часто совсем отказываются от его использования в пользу jabberd2 или openfire. Я считаю что напрасно, но это только мое ИМХО.
Итак, для настройки достаточно создать пару конфигурационных файлов и прописать автостарт в rc.conf. Также необходимо создать учетку в AD которая имеет права на чтение LDAP базы домена my.domain.local, в моем случае это — CN=for_jabber,OU=it,DC=my,DC=domain,DC=local
Также нужен pem файл который содержит сертификат и ключ для шифрования сетевой деятельности между клиентами и сервером. Ничего особенного в нем нету, стандартное содержимое формата:

-----BEGIN CERTIFICATE-----
....cert here....
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
....key here....
-----END RSA PRIVATE KEY-----

Листинг конфига /usr/local/etc/ejabberd/inetrc

{lookup,["file","native"]}.
{host,{127,0,0,1}, ["localhost","hostalias"]}.
{file, resolv, "/etc/resolv.conf"}.

Листинг главного конфига ejabberd — /usr/local/etc/ejabberd/ejabberd.cfg

override_global.
override_local.
override_acls.

{loglevel, 2}.

% Ports and services
{listen, [

        % Client to server
        {5222, ejabberd_c2s, [
                starttls_required, {certfile, "/usr/local/etc/ejabberd/jabber.pem"},
                zlib
        ]},

        % HTTP service
        {5280, ejabberd_http, [
                web_admin
        ]}

]}.

% Webadmin access
{acl, admins, {user, "my_ad_login", "my.domain.local"}}.
{access, configure, [{allow, admins}]}.

% Host config
{hosts, ["my.domain.local"]}.

%
% HOST: my.domain.local
%

{host_config, "my.domain.local", [

        {auth_method, ldap},
        {ldap_servers, ["my.domain.local"]},
        {ldap_rootdn, "CN=for_jabber,OU=it,DC=my,DC=domain,DC=local"},
        {ldap_password, "12345609876"},
        {ldap_base, "DC=my,DC=domain,DC=local"},
        {ldap_uids, [{"sAMAccountName", "%u"}]},
        {ldap_filter, "(&(objectCategory=person)(objectClass=user))"}

]}.

{language, "ru"}.

{access, muc_admin,  [{allow, admins}]}.
{access, muc_access, [{allow, all}]}.
{access, muc_create, [{allow, admins}]}.
{access, muc_log,    [{allow, admins}]}.

%%%.   =======
%%%'   MODULES

%%
%% Modules enabled in all ejabberd virtual hosts.
%%
{modules,
 [
  {mod_adhoc,    []},
  {mod_announce, [{access, announce}]}, % recommends mod_adhoc
  {mod_blocking,[]}, % requires mod_privacy
  {mod_caps,     []},
  {mod_configure,[]}, % requires mod_adhoc
  {mod_disco,    []},
  %%{mod_echo,   [{host, "echo.localhost"}]},
  {mod_irc,      []},
  {mod_http_bind, []},
  %%{mod_http_fileserver, [
  %%                       {docroot, "/var/www"},
  %%                       {accesslog, "/var/log/ejabberd/access.log"}
  %%                      ]},
  {mod_last,     []},
  {mod_muc,      [
                  {host, "conference.@HOST@"},
                  {access, muc_access},
                  {access_create, muc_create},
                  {access_persistent, muc_create},
                  {access_admin, muc_admin},
                  {default_room_options,
                        [
                         {logging, true}
                        ]}
                 ]},
  {mod_muc_log,  [{access_log, muc_log}, {cssfile, false}, {dirname, room_jid}, {outdir, "/usr/local/www/ejabberd/logs_muc"}]},
  {mod_log_chat, [{path, "/usr/local/www/ejabberd/logs_chat"}, {format, html}]},
  {mod_offline,  [{access_max_user_messages, max_user_offline_messages}]},
  {mod_ping,     []},
  %%{mod_pres_counter,[{count, 5}, {interval, 60}]},
  {mod_privacy,  []},
  {mod_private,  []},
%% Proxy Server for file transfer over NAT %%  
  {mod_proxy65,  [
                {host, "proxy.my.domain.local"}, %% defines the Jabber ID of service.
                {ip, {0,0,0,0}}, %% 127.0.0.1 by default, make it 0.0.0.0 to listen on all interfaces, or the ip of specific interface
                {hostname, "my.domain.local"}, % useful service run behind a NAT. default is ip option. Ex: "proxy.mydomain.org", "200.150.100.50"
                {port, 7777}, %% Default, we don't need to add
                {access, all} %% Default, we don't need to add
                 ]},
  {mod_pubsub,   [
                  {access_createnode, pubsub_createnode},
                  {ignore_pep_from_offline, true}, % reduces resource comsumption, but XEP incompliant
                  %%{ignore_pep_from_offline, false},  % XEP compliant, but increases resource comsumption
                  {last_item_cache, false},
                  {plugins, ["flat", "hometree", "pep"]}  % pep requires mod_caps
                 ]},
  {mod_register, [
                  %%
                  %% Protect In-Band account registrations with CAPTCHA.
                  %%
                  %%{captcha_protected, true},

                  %%
                  %% Set the minimum informational entropy for passwords.
                  %%
                  %%{password_strength, 32},

                  %%
                  %% After successful registration, the user receives
                  %% a message with this subject and body.
                  %%
                  {welcome_message, {"Welcome!",
                                     "Hi.\nWelcome to this XMPP server."}},

                  %%
                  %% When a user registers, send a notification to
                  %% these XMPP accounts.
                  %%
                  %%{registration_watchers, ["admin1@example.org"]},

                  %%
                  %% Only clients in the server machine can register accounts
                  %%
                  {ip_access, [{allow, "127.0.0.0/8"},
                               {deny, "0.0.0.0/0"}]},

                  %%
                  %% Local c2s or remote s2s users cannot register accounts
                  %%
                  %%{access_from, deny},

                  {access, register}
                 ]},
  %%{mod_register_web, [
                  %%
                  %% When a user registers, send a notification to
                  %% these XMPP accounts.
                  %%
                  %%{registration_watchers, ["admin1@example.org"]}
  %%             ]},
  {mod_roster,   []},
  %%{mod_shared_roster,[]},
  {mod_shared_roster_ldap, [
          {ldap_filter, "(&(objectCategory=person)(objectClass=user))"},
          {ldap_base, "OU=Organisation,DC=my,DC=domain,DC=local"},
   %%     {ldap_rfilter, "(&(sAMAccountType=805306368)(!(memberOf=CN=Some_not_real_users,OU=Users_All,OU=Organisation,DC=my,DC=domain,DC=local)))"},
          {ldap_rfilter, "(&(objectClass=person)(objectClass=user))"},
          {ldap_groupattr, "department"},
          {ldap_groupdesc, "department"},
          {ldap_memberattr, "sAMAccountName"},
          {ldap_userdesc, "cn"}
        ]},
  %%{mod_service_log,[]},
  {mod_shared_roster,[]},
  {mod_stats,    []},
  {mod_time,     []},
  %%{mod_vcard,    []},

{mod_vcard_ldap,
   [
    %% We use the same server and port, but want to bind anonymously because
    %% our LDAP server accepts anonymous requests to
    %% "ou=AddressBook,dc=example,dc=org" subtree.
    {ldap_rootdn, "CN=for_jabber,OU=it,DC=my,DC=domain,DC=local"},
    {ldap_password, "12345609876"},
    %% define the addressbook's base
    {ldap_base, "OU=Organisation,DC=my,DC=domain,DC=local"},
    %% uidattr: user's part of JID is located in the "mail" attribute
    %% uidattr_format: common format for our emails
    %%%%%%{ldap_uids, [{"mail","%u@myco.ua"}]},
    %% We have to define empty filter here, because entries in addressbook does not
    %% belong to shadowAccount object class
    %%{ldap_filter, "(&(sAMAccountType=805306368)(!(memberOf=CN=Some_not_real_users,OU=Users_All,OU=Organisation,DC=my,DC=domain,DC=local)))"},
    {ldap_filter, "(&(objectClass=person)(objectClass=user))"},
    %% Now we want to define vCard pattern
    {ldap_vcard_map,
      [{"NICKNAME", "%u", []},
       {"GIVEN", "%s", ["givenName"]},
       {"MIDDLE", "%s", ["initials"]},
       {"FAMILY", "%s", ["sn"]},
       {"FN", "%s", ["displayName"]},
       {"EMAIL", "%s", ["mail"]},
       {"ORGNAME", "%s", ["company"]},
       {"ORGUNIT", "%s", ["department"]},
       {"CTRY", "%s", ["c"]},
       {"LOCALITY", "%s", ["l"]},
       {"STREET", "%s", ["streetaaadress"]},
       {"REGION", "%s", ["st"]},
       {"PCODE", "%s", ["postalCode"]},
       {"TITLE", "%s", ["title"]},
       {"URL", "%s", ["wWWHomePage"]},
       {"DESC", "%s", ["description"]},
       {"TEL", "%s, office: %s", ["mobile", "telephoneNumber"]}]},
    {ldap_search_fields,
      [{"User", "%u"},
       {"Name", "givenName"},
       {"Family Name", "sn"},
       {"Email", "mail"},
       {"Company", "company"},
       {"Department", "department"},
       {"Role", "title"},
       {"Description", "description"},
       {"Phone", "mobile"}]},
    {ldap_search_reported,
      [{"Full Name", "FN"},
       {"Nickname", "NICKNAME"},
       {"Email", "EMAIL"}]}
  ]},

  {mod_version,  [
        {show_os, true}
  ]}
 ]}.

Со стороны клиента настройки должны быть такие:

    server — server FQDN
    domain — my.domain.local
    username — AD sAMAccountName
    password — AD password
    Шифрование — обязательно!

Также в данном конфиге используется модуль которого нету в стандартной поставке сервера — mod_log_chat, его необходимо собирать самому и подключать отдельно. Как это делается я писал ранее.
Не побрезгуйте ознакомиться с официальной документацией, она, на удивление, очень подробная с множеством примеров и разъяснений.
Enjoy!

FreeBSD — exim + rspamd

Идея о том чтобы выкинуть нафик непомерно прожорливый spamassassin из почтовой связки exim + dovecot давно мучила мне мозг. В особенности если учесть что поток почты единицы писем в сутки 🙂 Но вот случайно набрел на просторах инета инфо про замечательную альтернативу SA — rspamd. Заинтриговала невероятная легковесность решения при сохранении функциональности. Ну чтож … гоним метлой из системы жирного spammassassina и пробуем настроить rspamd. Вроде бы все должно быть просто, вот и документация есть — дел на пару минут, ан нет — установить с полпинка не получилось 🙂
Итак, как я говорил выше, на сервере установлен и работает exim + sa, для начала нужно отучить exim проверять письма spamassasin-ом, для этого уберите из конфига exim-а все что вяжет его с SA. Это просто, справится любой.
Дальше тоже просто — установить из портов rspamd. Тут и писать нечего, идем в порты и устанавливаем привычным способом.
А вот следующий шаг оказался для меня тяжеловат — нужно пересобрать exim с поддержкой rspamd, для этого есть patch patch-exim-src_spam.c.diff который можно скачать вот тут. Читать полностью

MySQL — Could not execute Write_rows_v1 event on table my_wp.wp_options; Duplicate entry

На мастере была проблема с одной из БД, в результате slave тоже ругается ошибкой

Last_SQL_Error: Could not execute Write_rows_v1 event on table my_wp.wp_options; Duplicate entry '_transient_doing_cron' for key 'option_name', Error_code: 1062; handler error
HA_ERR_FOUND_DUPP_KEY; the event's master log mysql-bin.000014, end_log_pos 337

Решить удалось довольно просто, сбойную команду нужно просто пропустить, для этого подколючаемся в mysql под рутом и выполняем:

mysql> stop slave;
mysql> SET GLOBAL sql_slave_skip_counter = 2;
mysql> start slave;

Enjoy!

MySQL — ‘wp_options’ is marked as crashed and should be repaired

Както раз у меня завалился mysql, после перезапуска в логах увидел такую срань. Причем блог на wordpress при этом нормально работал,

131112  9:37:52 [Note] /usr/local/libexec/mysqld: ready for connections.
Version: '5.5.34-log'  socket: '/tmp/mysql.sock'  port: 3306  Source distribution
131112 09:37:53 mysqld_safe A mysqld process already exists
131112  9:40:44 [ERROR] /usr/local/libexec/mysqld: Table './diff_wp/wp_options' is marked as crashed and should be repaired
131112  9:40:44 [Warning] Checking table:   './my_wp/wp_options'
131112  9:40:45 [ERROR] /usr/local/libexec/mysqld: Table './diff_wp/wp_usermeta' is marked as crashed and should be repaired
131112  9:40:45 [Warning] Checking table:   './my_wp/wp_usermeta'
131112  9:40:46 [ERROR] /usr/local/libexec/mysqld: Table './diff_wp/wp_posts' is marked as crashed and should be repaired
131112  9:40:46 [Warning] Checking table:   './my_wp/wp_posts'
131112  9:40:47 [ERROR] /usr/local/libexec/mysqld: Table './diff_wp/wp_postmeta' is marked as crashed and should be repaired
131112  9:40:47 [Warning] Checking table:   './my_wp/wp_postmeta'
131112  9:40:47 [ERROR] /usr/local/libexec/mysqld: Table './diff_wp/wp_comments' is marked as crashed and should be repaired
131112  9:40:47 [Warning] Checking table:   './my_wp/wp_comments'

На официальном сайте mysql рекомендуют в таком случае восстановить таблицы специальной утилитой — myisamchk Читать полностью