Ваш
Системный Администратор

Качественная IT инфраструктура - залог успеха компании.

Mikrotik и лицензия третьего уровня

schedule folder_open Any, Hardware label_outline Hell, MikroTik

Сегодня мне напомнили о такой проблеме как впустую потраченые людьми, несколько десятков долларов, на лицензию 4-го уровня - ради режима “ap bridge”.

Лиценцзия 3-го уровня допускает подключение одного клиента, что более чем достаточно для работы в режиме “Точка-Точка”. Для реализации, необходимо создать “бридж” и добавить беспроводный интерфейс в него, в настройках беспроводного интерфейса выбрать режим “bridge”. Остальные настройки беспроводной сети стандартные.

1
2
3
4
5
6
7
8
9
10
11
12
13
# Переводим беспроводный интерфейс в режим "bridge"
/interface wireless
set [ find default-name=wlan1 ] mode=bridge

# Добавляем бридж интерфейс и добавляем в него наш беспроводный интерфейс
/interface bridge
add name=wireless
/interface bridge port
add bridge=wireless interface=wlan1

# Назначаем локальный адрес бридж интерфейсу
/ip address
add address=192.168.88.1/24 interface=wireless network=192.168.88.0

С этого момента, ваша ТД, начнёт вещание и готова к подключению одного клиента.

Rsync поверх SSH с авторизацией отдельных пользователей на стороне Rsync

schedule folder_open Security, Unix label_outline Backup, CentOS, SSH, Ubuntu


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

Rsync клиент соединяется с rsync сервером поверх SSH подключения (key auth), проходит авторизацию самого rsync и синхронизирует данные c каталогом указанным в конфигурации rsync.

По большей части, эта заметка посвящена именно авторизации “windows rsync” клиентов поверх ssh.

Резервирование канала на Mikrotik с 3G модемом

schedule folder_open Any, Hardware, Monitoring label_outline Backup, MikroTik

Дано
1. Mikrotik 951Ui-2nD
2. RouterOS 6.40.3
3. 3G модем Huawei E3372
4. Основной канал, настройки по DHCP

Производит переключение на резервный канал путём смены Destation у роута по умолчанию, перед переключением производится сброс модема для устранения “подвисания” (зависит от модема, сброс может производиться как переподключением PPTP инерфейса так и сбросом питания по USB порту - параметр reconnectMobMethod в скрипте).

Работа скрипта
Скрипт проверяет доступность двух адресов путём “пинга” указанных адресов, один из адресов задаётся автоматически и является адресов шлюза основно канал, второй адрес задаётся вами в самом скрипте, в параметре extPingAddr (при проверке добавляется роут на этот адрес через основной канал).
В случае недостуаности хоть одного из адресов или большие потери пакетов (процент задаётся в параметре pingStatusOK), производится переключение на резервный канал.
Переодически производится проверка доступности основного канала, интервал задаётся в Schedulder (/system scheduler), в случае восстановления связи, прозводится обратное переключение на основной канал.

Недостатки
В лог постоянно сыпится запись об удалении/добавлении роута до второго адреса проверки доступности канала.

Скрипт

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# Скрипт резервирования канала на 3G модем
# При DHCP WAN
# 09.09.2017 Samolyk Alexey [root[dog]sysalex.com]

# -- Настройки --
# Имя WAN интерфейса (основной канал)
:local wanIfaceName "ether1";
# Имя WAN интерфейса (модем)
:local mobIfaceName "pptp-out1";
# Адрес которые будем "пиговать для проверки наличия основного канала"
:local extPingAddr    "8.8.8.8";

# Метод реконекта модема
# 0 - сброс питания по USB
# 1 - Отключение/включение интерфейса
:local reconnectMobMethod 1;

# Процент допустимых потерь на основном интерфейсе
# при значении не неже, будет производиться переключение
# на основной канал
:local pingStatusOK 70;


# -- Функции --
# Определение шлюза на основном интерфейсе
:local getGeteway do={
    :return [/ip dhcp-client get [ /ip dhcp-client find status=bound interface=$wanIfaceName ] gateway];
}
# Очистка ARP таблицы (далеко не всегда нужно но лишним не будет)
:local clearARP do={
    :local dumplist [/ip arp find]
    :foreach i in=$dumplist do={
        /ip arp remove $i
    }
}

# Переподключение мобильного соединения
# Иногда сессия виснет если нет трафика
:local reconnectMobConnection do={
    :if ($method = 0) do={
        # Сбрасываем питание USB порта
        :log warning ("Reset mobile modem (USB power)")
        /system routerboard usb power-reset;
        # 10 секунд не инициализацию модема
        :delay 10s;
    } else={
        # Перезапускаем PPtP интерфейс
        :log warning ("Reconect mobile interface before using");
        /interface ppp-client set $mobIface disable=yes;
        :delay 1s;
        /interface ppp-client set $mobIface disable=no;
    }
}

# Проверка и при отсуствии создание маршрутов по умолчанию
# для основного и мобильного соединения.
:local checkRoutes do={
    # Проверяем наличие роута на основной канал
    :if ([/ip route find dst-address="0.0.0.0/0" gateway=$currentWanGateway] = "") do={
        /ip route add gateway=$currentWanGateway distance=1 disabled=no
        :log warning ("Default route to WAN interface create");
    }
    # Проверяем наличие роута на резервный канал
    :if ([/ip route find dst-address="0.0.0.0/0" gateway=$currentMobGateway] = "") do={
        /ip route add gateway=$currentMobGateway distance=2 disabled=no
        :log warning ("Default route to Modem interface create");
    }
}

# Пинг адресов для проверки доступности подключения на основном канале
:local pingStatus do={
        # Добавляем роут через шлюз
        /ip route add dst-address=$pingAddr1 gateway=$currentGateway;
        # пингуем
        :local status ((( [/ping $pingAddr0 interface=$wanIface count=4] + \
        [/ping $pingAddr1 interface=$wanIface count=4] ) / 8) * 100);
        # Удаляем роут
        /ip route remove [find dst-address=$pingAddr1."/32"];
        :return $status;
}


# Поехали :)
# Получаем текущий шлюз на основном канале
:local curGateway [$getGeteway wanIfaceName=$wanIfaceName];
# Ищем интерфейсы, пригодяться для операций с ними
:local mainIface [/ip route find dst-address="0.0.0.0/0" gateway=$curGateway];
:local mobIface  [/ip route find dst-address="0.0.0.0/0" gateway=$mobIfaceName];

# Проверяем наличие основных маршрутов и если отсуствуют то добавляем
$checkRoutes currentWanGateway=$curGateway currentMobGateway=$mobIfaceName;

# На всякий случай проверяем правильность выставленный "distance"
# у марштутов. Конечно маловероятно что с ними что-то не то но вдруг руками поменяли.
:if ( [/ip route get $mainIface distance] != 2 ) do={
    /ip route set $mainIface distance=2;
}
:if ( [/ip route get $mobIface distance] != 1 && [/ip route get $mobIface distance] != 3) do={
    /ip route set $mobIface distance=3;
}

# Выясняем статус основного канала
:local wanChanelStatus [$pingStatus pingAddr0=$curGateway pingAddr1=$extPingAddr wanIface=$wanIfaceName currentGateway=$curGateway];

:if ($wanChanelStatus < $pingStatusOK) do={

        # Если нет коннекта на основном канале то переключаемся на резервный
        # путём смены "distance" на 1 - у резервного роута
        :if ( [/ip route get $mobIface distance] != 1 ) do={
              $reconnectMobConnection mobIface=$mobIfaceName;
            /ip route set $mobIface distance=1;
            :log warning ("Reconnect to reserve chanel");
            $clearArp;
        }

    } else={
        # Если коннект на основном канале появился, то переключаемся на основной
        # путём смены "distance" на 3 - у резервного роута
        :if ( [/ip route get $mobIface distance] != 3 ) do={
            /ip route set $mobIface distance=3;
            :log warning ("Reconnect to Main chanel");
            $clearArp;
        }
    }

Установка

1
2
3
4
/system scheduler
add interval=30s name=rezerv_check on-event=NAME_SCRIPT policy=\
    ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \
    start-time=startup

NAME_SCRIPT - заменить на имя которое указали при добавлении скрипта.

P.S. Никоим случаем не претендую на оригинальность и полное авторство на скрипт, использовались разные источники.

Me.Doc откат на 188-ю версию

schedule folder_open Any, Security label_outline Backup, MeDoc

UPD: Выпустили обновление 10.01.190.
Так, что откатываемся и обновляемся.

В связи с недавними событиями, 189-я версия Me.Doc является небезопасной и не рекомендуется к использованию.
Сама компания заявляет что у неё уже есть обновление ПО, гарантированно (Ха-Ха), не содержащее бэкдоров, но КиберПолиция не даёт им добра на его развёртывания.
В данный момент единственным, способом хоть как-то обезопасить себя, является откат на 188-ю версию.

1. Загружаем с офф. сайта 188-ю версию
2. Загружаем скрипт, правящий версию в БД
3. Останавливаем службы Firebird server - ZvitGrp и ZvitGrp
4. Копируем каталог C:\ProgramData\Medoc_ (оттуда нам понадобится БД, да и вообще пусть будет)
5. Производим деинсталляцию 189-й версии с компьютера/сервера (убедитесь что не забыли про п.4.)
6. Инсталлируем 188-ю версию
7. Проверяем что в службах не запущены службы из п.3.
8. Копируем каталог db из копии сделаной в п.4. в ново установленную 188-ю версию, с заменой файлов (
C:\ProgramData\Medoc\MedocSRV_ если сетевая)
9. Запускаем ScriptRun.exe из каталога с установленным Me.Doc и в открывшемся окне выбираем скрипт загруженный в п.2. (слева в меню кнопка “створити”) и после выбора “виконаты”
10. После отработки скрипта запускаем службы из п.3.
11. Проверяем работоспособность.

Что конкретно делает скрипт - не известно, по теории он должен просто править версию ПО указанную в БД с 189-й на 188-ю ибо без этого 188-я версия не будет работать с БД.
Не удаляйте резервную копию до тех пор пока не выяснится как жить дальше :)

Установка 32-х битного Wine в CentOS7

schedule folder_open Unix label_outline CentOS, Fix
1
2
sudo rpm -Uvh http://rpm.playonlinux.com/playonlinux-yum-4-1.noarch.rpm
sudo yum install playonlinux glibc.i686 alsa-lib.i686 libXv.i686 libXScrnSaver.i686 libSM.i686 libXi.i686 libXrender.i686 libXrandr.i686 freetype.i686 fontconfig.i686 zlib.i686 glib2.i686 libstdc++.i686

Дальше заходим в PlayOnLinux, устанавливаем x86 версию Wine и радуемся жизни.

Q: Почему PlayOnLinux?
A: Просто удобная обёртка над Wine и не засирает систему.

Не работает TouchPad в CentOS7 [Dell Vostro 15]

schedule folder_open Any, Hardware, Unix label_outline CentOS, Fix, Notebook

Возникла проблема при установке CentOS7 на мой Dell Vostro 15, после установки (и во время) не работал TouchPad.
Проблема в общем решалась доволи просто, больше ушло времени на Google-инг.

Добавляем опцию i8042.nopnp в конфиг grub /etc/default/grub:

1
GRUB_CMDLINE_LINUX_DEFAULT="... quiet splash i8042.nopnp"

Обновляем grub:

UEFI

1
sudo grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg

Legacy

1
sudo grub2-mkconfig -o /boot/grub2/grub.cfg

Добавляем модуль i2c_hid в бдэклист (от root-а):

1
2
sudo su
echo "blacklist i2c_hid" > /etc/modprobe.d/i2c-hid.conf

Перегенерируем initramfs (от root-а):

1
2
cp -v /boot/initramfs-$(uname -r).img /boot/initramfs-$(uname -r).img.bak
dracut -f

Дальше перезагрузка и радость :)

Gitlab-CI deploy OctoPress blog

schedule folder_open Any, Development, Unix label_outline Docker, Fix, Git, Project, Ruby, SSH

А зачем? Веяние моды?
Нет. Просто я замучался бороться в глюками Ruby под Win10 :)

Для работы используются две ветки master и development.
development ветка используется для деплоя на тестовый сервер и проверки что всё собралось верно, после “мержа” в master ветку, уже из неё деплоится на основной сервер.

Так как OctoPress генерирует чистую статику то в качестве development сервера можно использовать просто подкаталог на основном.

1
2
/var/www/blog
/var/www/blog/dev

При деплое master ветки, rsync удалит этот каталог. Также, никто не мешает заместь rsync, деплоить в тот-же github-page и вообще куда душе угодно.

$SSH_DEPLOY_KEY - “Secret Variables” из настроек проекта в Gitlab (Проект -> Settings -> CI/CD Pipelines -> Secret Variables).
Необходимо создать новую переменную и в качестве value вставить SSH Private Key, public ключ, соответственно, должен быть прописан на сервере - у пользователя из-под которого будем осуществлять деплой и иметься права на запись в соответствующие каталоги.
my_theme - заменить на имя используемой вами темы.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
image: ruby:2.1
# Подготовка окружения
before_script:
  # Ставим Node.JS, есть зависимость
  - curl -sL https://deb.nodesource.com/setup_4.x | bash -
  - apt-get install nodejs rsync -y
  - mkdir "${HOME}/.ssh"
  - echo "${SSH_DEPLOY_KEY}" > id_rsa # копируем SSH private key
  - chmod 600 id_rsa
  - ssh-keyscan -H sysalex.com >> "${HOME}/.ssh/known_hosts" # Добавляем наш хост в известные
  - bundle install # ставим гемы

# Master ветка
PROD generate and deploy:
  script:
    - cp -rf .themes/my_theme/* ./ # Копируем тему (указать свою)
    - rake generate # производим сборку
    # синхронизируем каталог public с каталогом на сервере
    - rsync -hrvz --delete  -e 'ssh -i id_rsa' public/ user@example.com:/path/to/dir/
  only:
    - master

# Development ветка  
DEV generate and deploy:
  script:
    - cp -rf .themes/my_theme/* ./
    - rake generate
    - rsync -hrvz --delete  -e 'ssh -i id_rsa' public/ user@example.com:/path/to/dir/dev/
  only:
    - develop

Среднее время сборки, составляет 3 мин. из них 90% это установка необходимых Gem, можно значительно сократить это время - если использовать, заранее, подготовленный образ с уже установленными, необходимыми Gem (может, когда-нибудь, заморочусь этим повросом).

VirtualBox USB device connect

schedule folder_open Hardware, Unix label_outline Fix, Ubuntu

При установке VirtualBox (например в Ubuntu) локальный пользователь не добавляется в группу vboxusers,при установке плагина Oracle VM VirtualBox Extension Pack необходимого для работы с USB, пользователь так-же не добавляется в группу.

К счастью это легко исправить всего одной командой, до тех пор VB просто не будет “видеть” USB устройств
(как вариант можно запустить VB из под root но это сильно не рекомендуется делать)

1
sudo usermod -a -G vboxusers YOUR_USER

Chef, auto registration node on server

schedule folder_open Development, Unix label_outline Chef, Chef-client, Chef-server

Скрипт для установки Chef-Client и автоматической регистрации ноды на Chef-Server - без Knife и лишних телодвижений.

node_name соответсвует текущему имени хоста указанному в /etc/hostname ($HOSTNAME переменная окружения), в run_list="" необходимо указать рецепт(ы)/роль(и) или оставить пустым.
Другие параметры Chef-Client смотрите в офф. документации client.rb , chef-client

Если используются подготовленные инсталяционные образы (у меня так) то Chef-Client лучше интергрировать сразу в образ вместе с postinstall скриптом.

В случае если заданное имя хоста не резолвиться через DNS то на Chef-Server параметр FQDN останется незаполненным для этой ноды, в большинстве случаев это не мешает работе но при возможности необходимо обеспечить резолвинг имени через DNS сервер или /etc/hosts и при следующей синхронизации FQDN будет заполнена.

Имя ноды необязательно должно соответсвовать имени хоста но в этом случае необходимо явно указать node_name в конфигурационном файле /etc/chef/client.rb до первого запуска Chef-Client, также это необходимо сделать если по какой либо причине пришлось изменить имя хоста (необходимо в node_name прописать старое имя) иначе клиент не сможет пройти авторизацию на сервере.
Для задания имени ноды можно использовать переменную окружения $NODE_NAME

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#!/bin/bash

# settings
chef_package="chef_12.9.41-1_amd64.deb" # Set Chef package version
chef_package_url="https://packages.chef.io/stable/ubuntu/14.04/${chef_package}" # Download URL
org_name="ORG_NAME" # set organizations name  
validation_name="validator" # Validator username
chef_url="https://chef.server/organizations/${org_name}"

config_dir="/etc/chef" # config directory
log="/var/log/chef-client.log" # log file

#####################################
# Roles and Recipes, assigned for Node
# "role[ROLE_NAME], recipe[RECIPE_NAME], ..."
run_list=""

wget ${chef_url}
dpkg -i ${chef_package}

# Create client config file
# See other parameters in the officiall documentation
# https://docs.chef.io/config_rb_client.html
cat <<EOF > ${config_dir}/client.rb
log_level        :info
log_location     '${log}'
chef_server_url  '${chef_url}'
validation_client_name '${validation_name}'
ssl_verify_mode  :none
node_name ENV[NODE_NAME] || ENV[HOSTNAME]
EOF

# Create "validation" key file
# Insert content your validate private key
cat <<EOF > ${config_dir}/validation.pem
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBA
......
dPQ7sje3GKXqsGfT58hBCCPc=
-----END RSA PRIVATE KEY-----
EOF

# Run client
chef-client -r "${run_list}"

Ubuntu: восстановление системных файлов

schedule folder_open Unix label_outline Fix, Ubuntu

Сегодня человек попросил переустановить Ubuntu только потому что зачем-то удалил каталог /usr/share/icons, но данная проблема решается намного проще и главное быстрее чем переустановка и настройка новой системы.

1. Загружаем ISO образ Ubuntu с офф. сайта. (в моём случае это Ubuntu 14.04.4 x64)

2. Монтируем ISO образ

1
2
mkdir /tmp/iso
sudo mount -t iso9660 -o loop /path_to_iso/ubuntu-14.04.4-desktop-amd64.iso /tmp/iso

3. Монтируем filesystem.squashfs - образ файловой системы со всеми необходимыми нам файлами

1
2
mkdir /tmp/squashfs
sudo mount -t squashfs -o loop /tmp/iso/casper/filesystem.squashfs /tmp/squashfs

если в наличии есть “флэшка” с Ubuntu то п.1-2 можно пропустить и взять filesystem.squashfs оттуда, он расположен в каталоге /casper/filesystem.squashfs относительно корня накопителя.

к примеру у меня есть “флэшка” с Ubuntu и тогда команда из п.3 примет такой вид

1
2
mkdir /tmp/squashfs
sudo mount -t squashfs -o loop /media/sysalex/casper/filesystem.squashfs /tmp/squashfs

где sysalex это LABEL флэш накопителя (Ubuntu как правило так именует).
После того как смонтировали filesystem.squashfs можно непосредственно занятся копирыванием недостающих файлов.

4. Копируем недостающие файлы

1
sudo cp -rf /tmp/squashfs/usr/share/icons/* /usr/share/icons/

5. Размонтируем смонитрованные файловые системы

1
sudo umount /tmp/iso /tmp/squashfs

На этом можно закончить и с чувством выполненного долга выпить чаю :)