Перенос PostgreSQL базы вместе с пользователями на сервер с другой архитектурой

Встала задача перенести PostgreSQL базу из под самописной CRM со старого физического сервера, на новый виртуальный и как всегда, вылезли проблемы..

Проблема номер раз — простым копированием файлы данных не перенести из за разницы в архитектуре, нет, это можно сделать, но с ОЧЕНЬ большим геморроем.

Проблема номер два — все 200 пользователей которые работают в CRM не записаны внутри базы, а созданы как пользователи PostgreSQL, т.е. простым бэкапом базу перенести конечно можно, но вот пользователей нет. Поэтому единственным разумным решением оказался бэкап через pg_dumpall всего сервера, потом удаление ненужного, расчесывание и полировка.

Ну а раз я взялся за это редкое для меня дело, решил описать подробную процедуру начиная с установки PostgreSQL на Debian 7.5 и заканчивая переносом базы и подключением к ней с другой машины через pgAdmin III.

1. Подготовка чистого сервера, установка необходимого минимума.

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

Начнем установку.

aptitude install postgresql mc ssh screen

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

su - postgres

Во втором окне, которое под root останавливаем сервер:

service postgresql stop

идем сюда /var/lib/postgresql/9.1/main и переносим куда нибудь содержимое (обратите внимание, в разных дистрибутивах путь может различаться).

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

/usr/lib/postgresql/9.1/bin/initdb --locale=ru_RU.utf8 /var/lib/postgresql/9.1/main

Далее в другом окне screen не запуская сервер копируем симлинки server.crt и server.key из нашего бэкапа. После этого можно попробовать запустить сервер, ошибок быть не должно.

2. Теперь настраиваем доступ к базе по сети.   Меняем в конфиге postgresql.conf слушаемый интерфейс, я всегда ставлю «*» и не понимаю тех, кто заморачивается указанием ip внутри сети:

nano /var/lib/postgres/data/postgresql.conf
listen_addresses = '*'

А в конфиге pg_hba.conf определяем по какому подключению, кто, к какой базе, с какого адреса и с каким методом авторизации может подключиться. У меня разрешено подключение с любого ipv4 адреса. Подробнее о настройке pg_hba.conf можно почитать тут разжевано все и очень доступно.

nano /var/lib/postgres/data/pg_hba.conf

host all all 0.0.0.0/0 trust

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

pg_dumpall > backup

И так же под системным пользователем залить бэкап в новый сервер (назначением для заливки указываем системную базу postgres):

psql -f backup postgres

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

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

P.S. Что бы не забыть, решил сохранить настройку беспарольного входа в psql.

Для автологина создаем на сервере с базой в корне домашней директории пользователя файлик:

touch /root/.pgpass

nano /root/.pgpass

И пишем внутрь:

127.0.0.1:5432:*:postgres:pass

Т.е.  разрешен автологин с локалхоста на стандартный порт postgresql 5432 ко всем базам на сервере для пользователя postgres, и последним указан пароль.

Далее, нужно выставить права на файлик:

chmod 600 /root/.pgpass
chown postgres:postgres /root/.pgpass

И можно наслаждаться конструкциями вида (с ключом -w):

/usr/bin/psql --dbname baza --host 127.0.0.1 --port 5432 --username pip -w --command "vacuum full analyze;"

Настройка ip-ip тоннеля с IPsec шифрованием в Debian

Данная статья написана на основе моих мучений с тоннелем между нашими основными офисами. Исторически сложилось, что тоннель этот, был построен на базе ip-ip + IPsec и изначально он был между двумя FreeBSD шлюзами.

Шло время и шлюзы начали помирать. Вначале, умер один шлюз и нужно было его оперативно заменить, что и было сделано. Вместо него встал шлюза на моем любимом Debian.

В процессе настройки, выяснилось ужасное!! IPsec в этой связке не работал, причем не работал уже очень давно.

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

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

Забил ровно до момента смерти второго BSD шлюза. Вместо умершего шлюза, был так же поставлен Debian и началось шаманство. Дабы учесть ошибки прошлого, и сделать все хорошо, я решил употребить иную схему применения связки ip-ip + IPsec — поднять ip-ip тоннель, а уже его содержимое, обернуть в IPsec.

Зачем я вообще решил оставить ip-ip тоннель?

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

Вот официальная wiki в ней обошлись без сетевух. Тут повторили конфиг из wiki, но с применением виртуальных интерфейсов eth0:1.

Я не стал делать так, про нескольким причинам:

1. При шифрование трафика между внешними ip неминуемого появляется дырка в безопасности, в виде spoofing, т.е. на внешнем интересе, где должны быть сети класса А, появится сеть класса С и их придется разрешить.

2. Трафик между шлюзами, очень тяжело считать. Гораздо проще считать трафик на интерфейсе, чем трафик между сетями. Виртуальный eth0:1 тут тоже не спасает, ибо считается устаревшим и убогим и не поддерживается iptables.

3. Не наглядность конфигурации. Это конечно спорный момент, но для меня это так.

4. Усложнение, точнее нагромождение маршрутизации. Я люблю, когда все маршруты, идут через свои устройства. Это наглядно, это понятно.

Может быть описанные выше причины кому то покажутся и не причинами вовсе. Но у меня так.

При таком подходе я получаю полноценный интерфейс tun0, на котором можно легко и просто считать трафик, на основе которого получаются внятные маршруты, и который полностью поддерживается iptables. Конфигурация IPsec перестает зависеть от внешних ip и от маршрутизируемых сетей, что упрощает перенастройку, в случае чего.

В общем, к делу.

Ставим:  apt-get install racoon ipsec-tools

Вводные данные:

Внутренняя сеть на объекте А — 192.168.16.0/21

IP в тоннеля на стороне А — 192.168.77.1

Внешний IP на объекте А — 10.0.0.65

Внутренняя сеть на объекте В — 192.168.0.0/24

IP в тоннеля на стороне В — 192.168.77.2

Внешний IP на объекте В — 195.0.0.65

И настраиваем на первом шлюзе А в /etc/network/interfaces:

auto tun0
 iface tun0 inet static
 address 192.168.77.1
 network 255.255.255.255
 pointopoint 192.168.77.2
 mtu 1350
 pre-up /sbin/ip tunnel add tun0 mode ipip remote <strong>195.0.0.65</strong> local <strong>10.0.0.65</strong> dev eth0
 pre-up /sbin/ip link set tun0 up
 post-up /sbin/ip route add 192.168.0.0/24 dev tun0 src 192.168.77.1
 pre-down /sbin/ip route del 192.168.0.0/24 dev tun0 src 192.168.77.1
 post-down /sbin/ip link set tun0 down
 post-down /sbin/ip tunnel del tun0

И настраиваем на первом шлюзе В в /etc/network/interfaces:

auto tun0
 iface tun0 inet static
 address 192.168.77.2
 network 255.255.255.255
 pointopoint 192.168.77.1
 mtu 1350
 pre-up /sbin/ip tunnel add tun0 mode ipip remote <strong>10.0.0.65</strong> local <strong>195.0.0.65</strong> dev eth0
 pre-up /sbin/ip link set tun0 up
 post-up /sbin/ip route add 192.168.16.0/21 dev tun0 src 192.168.77.2
 pre-down /sbin/ip route del 192.168.16.0/21 dev tun0 src 192.168.77.2
 post-down /sbin/ip link set tun0 down
 post-down /sbin/ip tunnel del tun0

Так мы создали ip-ip тоннель между объектами и прописали маршруты через тоннель, до внутренних сетей. После перезагрузки или ifup tun0 пинги из сити А в сеть В и обратно должны ходить.

Теперь настраиваем IPsec:

В /etc/racoon/psk.txt  на объекте А пишем придуманную фразу и ip объекта В:

192.168.77.2  tryamromashka888

В /etc/racoon/psk.txt  на объекте В пишем придуманную фразу и ip объекта А:

192.168.77.1  tryamromashka888

В psk.txt на обоих объектах, вместо ip можно поставить звездочку, дабы не заморачиваться.

Конфиг /etc/racoon/racoon.conf на объекте А приводим к такому виду:

path pre_shared_key "/etc/racoon/psk.txt";
remote anonymous {
 exchange_mode main,aggressive;
 proposal {
 encryption_algorithm 3des;
 hash_algorithm sha1;
 authentication_method pre_shared_key;
 dh_group 2;
 }
 }
sainfo address 192.168.16.0/21 any address 192.168.0.0/24 any {
 pfs_group 2;
 lifetime time 1 hour;
 encryption_algorithm 3des, blowfish 448, rijndael;
 authentication_algorithm hmac_sha1, hmac_md5;
 compression_algorithm deflate;
 }

Конфиг /etc/racoon/racoon.conf на объекте В приводим к такому виду:

path pre_shared_key "/etc/racoon/psk.txt";
remote anonymous {
 exchange_mode main,aggressive;
 proposal {
 encryption_algorithm 3des;
 hash_algorithm sha1;
 authentication_method pre_shared_key;
 dh_group 2;
 }
 }
sainfo address 192.168.0.0/24 any address 192.168.16.0/21 any {
 pfs_group 2;
 lifetime time 1 hour;
 encryption_algorithm 3des, blowfish 448, rijndael;
 authentication_algorithm hmac_sha1, hmac_md5;
 compression_algorithm deflate;
 }

Конфиг /etc/ipsec-tools.conf на объекте А приводим к такому виду:

#!/usr/sbin/setkey -f
# NOTE: Do not use this file if you use racoon with racoon-tool
 # utility. racoon-tool will setup SAs and SPDs automatically using
 # /etc/racoon/racoon-tool.conf configuration.
 #
## Flush the SAD and SPD
 #
 flush;
 spdflush;
## Some sample SPDs for use racoon
 
spdadd 192.168.16.0/21 192.168.0.0/24 any -P out ipsec
 esp/tunnel/192.168.77.1-192.168.77.2/require;
spdadd 192.168.0.0/24 192.168.16.0/21 any -P in ipsec
 esp/tunnel/192.168.77.2-192.168.77.1/require;

Конфиг /etc/ipsec-tools.conf на объекте В приводим к такому виду:

#!/usr/sbin/setkey -f
# NOTE: Do not use this file if you use racoon with racoon-tool
 # utility. racoon-tool will setup SAs and SPDs automatically using
 # /etc/racoon/racoon-tool.conf configuration.
 #
## Flush the SAD and SPD
 #
 flush;
 spdflush;
## Some sample SPDs for use racoon
spdadd 192.168.0.0/24 192.168.16.0/21 any -P out ipsec
 esp/tunnel/192.168.77.2-192.168.77.1/require;
spdadd 192.168.16.0/21 192.168.0.0/24 any -P in ipsec
 esp/tunnel/192.168.77.1-192.168.77.2/require;

После этого на обоих шлюзах делаем /etc/init.d/setkey restart && /etc/init.d/racoon restart

и смотрим setkey -D

На обоих машинах должны сформироваться ключевые пары:

192.168.77.2 192.168.77.1
 esp mode=tunnel spi=248989780(0x0ed74854) reqid=0(0x00000000)
 E: 3des-cbc b976192f e8c17ff6 8fc64e5f 1efda225 c9333c6c 15b03656
 A: hmac-sha1 ae7e03ba d760a471 ef22f01e 0baca744 ef0371c6
 seq=0x00000000 replay=4 flags=0x00000000 state=mature
 created: Sep 9 16:32:56 2015 current: Sep 9 17:02:31 2015
 diff: 1775(s) hard: 3600(s) soft: 2880(s)
 last: Sep 9 16:35:13 2015 hard: 0(s) soft: 0(s)
 current: 260919(bytes) hard: 0(bytes) soft: 0(bytes)
 allocated: 3249 hard: 0 soft: 0
 sadb_seq=1 pid=30197 refcnt=0
 192.168.77.1 192.168.77.2
 esp mode=tunnel spi=52619622(0x0322e966) reqid=0(0x00000000)
 E: 3des-cbc a52242b8 0f0f7042 d92c8011 25242258 34385bc2 4f618b95
 A: hmac-sha1 1e98b340 1db1c65c d7368c5d ffc78cc7 3e9b3a33
 seq=0x00000000 replay=4 flags=0x00000000 state=mature
 created: Sep 9 16:32:56 2015 current: Sep 9 17:02:31 2015
 diff: 1775(s) hard: 3600(s) soft: 2880(s)
 last: Sep 9 16:33:05 2015 hard: 0(s) soft: 0(s)
 current: 2077093(bytes) hard: 0(bytes) soft: 0(bytes)
 allocated: 3832 hard: 0 soft: 0
 sadb_seq=0 pid=30197 refcnt=0

Проверяем пинг. Если он есть, и значение

diff: 2225(s)

в выводе setkey -D выше меняется, значит данные пошли внутри IPsec.

Если пинг идет, а ключевых пар нет, или если пинг не идет значит где то в конфигах IPsec ошибка. Смотрим правильность своих подсетей, пропускаем демонов и пингуем еще раз, до нужного результата.

Работа в Красноярске

Приветствую всех.

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

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

Отсюда вопрос к читателям. Это мне кажется, или кол-во вакансий и их качество снизились?

Контроль свободного места на сервере с помощью скрипта

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

 

#!/bin/bash

# Ящики на которые шлем отчет
mails="admin1@itroad.ru admin2@itroad.ru"

# Создаем массив из рейтинга, наполняя одну переменную разделами, а другую процентом заполнения (убирая с конца символ процента).
F=(echo `df -h | awk '{print $6}' | grep /`)
S=(echo `df -h | awk '{print $5}' | grep % | rev | cut -c 2,3,4 | rev`)

# Считаем кол-во строк с разделами, и наполняем этим числом переменную счетчика.
N=`df -h | awk '{print $5}' | grep -c %`

# Чистим\создаем файл отправки перед циклом.
cat /dev/null &gt;/tmp/df_tmp

# Начинаем перебор массива с 1 элемента до N элемента.
i=1
while [ $i -lt $N ]
do
          # Внутри цикла проверяем первую переменную с процентами, не превысило ли значение 96%
          if [ ${S[$i]} -ge 96 ] <code class="shell plain">&gt;</code><code class="shell plain">/dev/null</code> <code class="shell plain">2&gt;&amp;1</code>; then
                  
                  # Если заполнение раздела 96% или больше, пишем об этом на почту.
                  echo "На разделе ${F[$i]} заканчивается место, занято уже ${S[$i]}%" &gt;&gt;/tmp/df_tmp
          
          # Если процент заполнения всех разделов меньше 96% - выходим.
          fi

# Добавляем к счетчику единицу.
i=$[$i+1]
done

# Если файл не пустой, шлем его на почту, если пустой, выходим.
test -s /tmp/df_tmp &amp;&amp; mutt -s "На разделах сервера `hostname` заканчивается свободное место" $mails &lt;/tmp/df_tmp

exit 0

Вообще, такие вот задачи, и задачи подобные, должны решаться с помощью систем мониторинга — но мне неимоверно лень заниматься.

Для меня система мониторинга, это такой здоровенный монстр — кальмар, половина щупалец которого нафиг не нужны, кроме как ингредиент салата. Вот и клепаю свои поделки, которые потом распространяю через Ansible.

Хотя я конечно же не прав — системы мониторинга, наше все!

Вечный бан fail2ban версия 2.0

fail2ban

Какое то время назад, я написал пост — «Защита от перебора паролей SSH. Автоматический вечный бан на основе списков fail2ban» в котором запилил скрипт по вечной блокировке наиболее активных перебирателей паролей к ssh.

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

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

#!/bin/bash

# Ящики на которые шлем отчет
mails="admin1@itroad.ru.ru admin2@itroad.ru"

# Генерируем список IP которые попадали в бан.
rm -rf /tmp/fail2banlog && mkdir /tmp/fail2banlog && cp `ls /var/log/fail2ban*` /tmp/fail2banlog && cd /tmp/fail2banlog && ls *.gz >/dev/null 2>&1 | while read i; do gzip -d $i >/dev/null 2>&1; done; cat fail2ban.log* | grep Ban | awk '{print $7}' >/tmp/fail2banlog/send_0

# Наполняем переменную из этого списка
fil="`cat /tmp/fail2banlog/send_0`"

# Проверяем все IP на наличие из в блоке
for w in $fil
do
      vuurmuur_script --list-blocked | grep $w >/dev/null 2>&1
   
      # Если такого ip нет в бан листе, то передаем его дальше на проверку, если есть, просто пропускаем.
      if [ $? -ne 0 ]; then
      echo $w >>/tmp/fail2banlog/send_1
      fi
done
# Составляем топ 10 адресов
cat /tmp/fail2banlog/send_1 | sort -nr | uniq -c | sort -nr | head -n10 >/tmp/fail2banlog/send
echo >>/tmp/fail2banlog/send

# Создаем массив из рейтинга, наполняя одну переменную кол-вом совпадений, а другую ip который совпал
F=(echo `cat /tmp/fail2banlog/send |awk '{print $1}'`)
S=(echo `cat /tmp/fail2banlog/send |awk '{print $2}'`)

# Начинаем перебор массива с 1 элемента до 10 элемента (в рейтинге ведь у нас всего 10 элементов).
i=1
while [ $i -lt 10 ]
do

    # Внутри цикла проверяем первую переменную с кол-вом попыток перебора, не превысило ли шест кол-во попыток.
    if [ ${F[$i]} -ge 6 ] >/dev/null 2>&1; then
    
    # Если попыток подбора 6 или больше смотрим бан лист и проверяем, нет ли в нем уже этого ip.
    # Если нет, то баним
    vuurmuur_script --block ${S[$i]} >/dev/null 2>&1
    echo "Ip ${S[$i]} добавлен в вечный бан." >>/tmp/fail2banlog/send
    
    # Если попыток меньше 6, ничего не делаем и выходим.
    else echo >/dev/null 2>&1
    fi

# Добавляем к счетчику единицу.
i=$[$i+1]
done

# Обновляем правила файрвола
vuurmuur_script --reload >/dev/null 2>&1

# Отсылаемый на почту рейтинг ip пытающихся подобрать пароль к SSH.
mutt -s "fail2ban" $mails </tmp/fail2banlog/send

В качестве файрвола, я использую vuurmuur, но переписать скрипт на использование чистого iptables или hosts.deny нет никакой проблемы.

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

К тому же, в процессе изменения, скрипт был существенно упрощен.

По видимому следующим изменением скрипта будет указание сервиса, из за которого ip попал в бан. Я вообще стараюсь не делать на одном сервере более одного сервиса, но в последнее время таких серверов становится все больше и больше. Уже появляется asterisk + apache и прочие связки, в которых fail2ban работает на несколько сервисов.