Разворачивание syslog-сервера с веб-интерфейсом

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

Мне же от вебморды много не надо — мне надо чтобы она лог показывала,  фильтры имела, и было бы неплохо чтобы составляла с сервером полностью FOSS-решение. И сам я давно уже использую под это дело LogAnalyzer, который с поставленной задачей — презентовать лог сислог-сервера, собирающего в базу данных логи с различного оборудования — справляется весьма неплохо.

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

Итак, скрипт писался и проверялся на Debian 10 «Buster», его актуальная версия находится на гитхабе, а текущую я оставлю здесь:

loganalyzer_install.sh
 
  1. #!/bin/bash
  2. # Syslog server with web interface for Debian 10
  3. # LAMP + phpmyadmin + rsyslog + Log Analyzer
  4. PHPMYADMINUSER="pma"
  5. PHPMYADMINPASS="321"
  6. SYSLOGDBPASSWORD="Qwerty"
  7. PMAVER="4.9.2"
  8. LAVERSION="4.1.7"
  9. export LANG="en_US.UTF-8"
  10. function check_packages {
  11.     notinstalled=""
  12.     if [ $# -eq 0 ]; then echo "Package name(s) required"; fi
  13.     if [ $# -gt 0 ]; then
  14.         for packagename in $@; do
  15.             if [[ "" == $(dpkg-query  -W --showformat='${Status}\n' ${packagename}  2>&1 | grep "install ok") ]]; then
  16.                 notinstalled=${notinstalled}${packagename}" "
  17.             fi
  18.         done
  19.     fi
  20.     if [[ "" == ${notinstalled} ]]; then
  21.         echo "true"
  22.     else
  23.         echo "${notinstalled}"
  24.     fi
  25. }
  26. ######## MARIA DB
  27. function check_sql {
  28.     if [[ "true" != $( check_packages  mariadb-server ) && "true" != $( check_packages  mysql-server) ]]; then
  29.         echo "false"
  30.     fi
  31.     if  [[ "true" == $( check_packages  mariadb-server ) ]]; then echo "mariadb"; fi
  32.     if  [[ "true" == $( check_packages  mysql-server ) ]]; then echo "mysql"; fi
  33. }
  34. function install_sql {
  35.     apt -y install mariadb-server
  36. #    mysql -uroot -e "UPDATE mysql.user SET Password=PASSWORD('${MYSQLROOTPASS}') WHERE User='root';\
  37. #    DELETE FROM mysql.user WHERE User='';\
  38. #    DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1');\
  39. #    DROP DATABASE test;\
  40. #    DELETE FROM mysql.db WHERE Db='test' OR Db='test\_%';\
  41. #    FLUSH PRIVILEGES;"
  42. }
  43. ######### PHP
  44. function check_php {
  45.     phpnotinstalled=$( check_packages php libapache2-mod-php php-mysql php-common php-cli  php-json php-opcache php-readline php-mbstring )
  46.     if [[ "true" != ${phpnotinstalled} ]]; then
  47.         echo "${phpnotinstalled}"
  48.     else
  49.         echo "true"
  50.     fi
  51. }
  52. ######### PHPMYADMIN
  53. function check_phpmyadmin {
  54.     if [[ ! -d /usr/share/phpmyadmin/ ]]; then
  55.         echo "false"
  56.     fi
  57. }
  58. function install_phpmyadmin {
  59. IFS='' read -r -d '' SITECONFIG  <<"EOF"
  60. Alias /phpmyadmin /usr/share/phpmyadmin
  61. <Directory /usr/share/phpmyadmin>
  62.     Options SymLinksIfOwnerMatch
  63.     DirectoryIndex index.php
  64.     <IfModule mod_php5.c>
  65.         <IfModule mod_mime.c>
  66.             AddType application/x-httpd-php .php
  67.         </IfModule>
  68.         <FilesMatch ".+\.php$">
  69.             SetHandler application/x-httpd-php
  70.         </FilesMatch>
  71.         php_value include_path .
  72.         php_admin_value upload_tmp_dir /var/lib/phpmyadmin/tmp
  73.         php_admin_value open_basedir /usr/share/phpmyadmin/:/etc/phpmyadmin/:/var/lib/phpmyadmin/:/usr/share/php/php-gettext/:/usr/share/php/php-php-gettext/:/usr/share/javascript/:/usr/share/php/tcpdf/:/usr/share/doc/phpmyadmin/:/usr/share/php/phpseclib/
  74.         php_admin_value mbstring.func_overload 0
  75.     </IfModule>
  76.     <IfModule mod_php.c>
  77.         <IfModule mod_mime.c>
  78.             AddType application/x-httpd-php .php
  79.         </IfModule>
  80.         <FilesMatch ".+\.php$">
  81.             SetHandler application/x-httpd-php
  82.         </FilesMatch>
  83.         php_value include_path .
  84.         php_admin_value upload_tmp_dir /var/lib/phpmyadmin/tmp
  85.         php_admin_value open_basedir /usr/share/phpmyadmin/:/etc/phpmyadmin/:/var/lib/phpmyadmin/:/usr/share/php/php-gettext/:/usr/share/php/php-php-gettext/:/usr/share/javascript/:/usr/share/php/tcpdf/:/usr/share/doc/phpmyadmin/:/usr/share/php/phpseclib/
  86.         php_admin_value mbstring.func_overload 0
  87.     </IfModule>
  88. </Directory>
  89. # Authorize for setup
  90. <Directory /usr/share/phpmyadmin/setup>
  91.     <IfModule mod_authz_core.c>
  92.         <IfModule mod_authn_file.c>
  93.             AuthType Basic
  94.             AuthName "phpMyAdmin Setup"
  95.             AuthUserFile /etc/phpmyadmin/htpasswd.setup
  96.         </IfModule>
  97.         Require valid-user
  98.     </IfModule>
  99. </Directory>
  100. # Disallow web access to directories that don't need it
  101. <Directory /usr/share/phpmyadmin/templates>
  102.     Require all denied
  103. </Directory>
  104. <Directory /usr/share/phpmyadmin/libraries>
  105.     Require all denied
  106. </Directory>
  107. <Directory /usr/share/phpmyadmin/setup/lib>
  108.     Require all denied
  109. </Directory>
  110. EOF
  111. if [ ! -f phpMyAdmin-${PMAVER}-all-languages.tar.gz ]; then wget https://files.phpmyadmin.net/phpMyAdmin/${PMAVER}/phpMyAdmin-${PMAVER}-all-languages.tar.gz; fi
  112. tar -xf phpMyAdmin-${PMAVER}-all-languages.tar.gz
  113. mkdir /usr/share/phpmyadmin
  114. cp -r phpMyAdmin-${PMAVER}-all-languages/* /usr/share/phpmyadmin
  115. mkdir -p /var/lib/phpmyadmin/tmp
  116. chown -R www-data:www-data /var/lib/phpmyadmin
  117. mkdir /etc/phpmyadmin/
  118. cp /usr/share/phpmyadmin/config.sample.inc.php  /usr/share/phpmyadmin/config.inc.php
  119. ln -s /usr/share/phpmyadmin/config.inc.php /etc/phpmyadmin/
  120. echo "\$cfg['TempDir'] ='/var/lib/phpmyadmin/tmp';" >> /usr/share/phpmyadmin/config.inc.php
  121. r="\$cfg\['blowfish_secret'\] = '"
  122. sed -i  "s/${r}/${r}$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 32)/g" /usr/share/phpmyadmin/config.inc.php
  123. echo "$SITECONFIG" >  /etc/apache2/sites-available/phpmyadmin.conf
  124. ln -s /etc/apache2/sites-available/phpmyadmin.conf /etc/apache2/sites-enabled/
  125. service  apache2 restart
  126. mysql -uroot -e "use mysql; CREATE USER ${PHPMYADMINUSER}@localhost IDENTIFIED BY '${PHPMYADMINPASS}'; GRANT ALL ON *.* TO ${PHPMYADMINUSER}@localhost WITH GRANT OPTION;"
  127. service mysql restart
  128. }
  129. ######### SYSLOG
  130. function install_rsyslog_mysql {
  131. debconf-set-selections << END
  132. rsyslog-mysql      rsyslog-mysql/mysql/admin-pass      password
  133. # MySQL application password for rsyslog-mysql:
  134. rsyslog-mysql      rsyslog-mysql/mysql/app-pass      password ${SYSLOGDBPASSWORD}
  135. rsyslog-mysql      rsyslog-mysql/password-confirm      password ${SYSLOGDBPASSWORD}
  136. rsyslog-mysql      rsyslog-mysql/app-password-confirm      password ${SYSLOGDBPASSWORD}
  137. # MySQL username for rsyslog-mysql:
  138. rsyslog-mysql      rsyslog-mysql/db/app-user      string      rsyslog@localhost
  139. # Back up the database for rsyslog-mysql before upgrading?
  140. rsyslog-mysql      rsyslog-mysql/upgrade-backup      boolean      true
  141. # Host running the MySQL server for rsyslog-mysql:
  142. rsyslog-mysql      rsyslog-mysql/remote/newhost      string
  143. # MySQL database name for rsyslog-mysql:
  144. rsyslog-mysql      rsyslog-mysql/db/dbname      string      Syslog
  145. # Reinstall database for rsyslog-mysql?
  146. rsyslog-mysql      rsyslog-mysql/dbconfig-reinstall      boolean      false
  147. rsyslog-mysql      rsyslog-mysql/missing-db-package-error      select      abort
  148. rsyslog-mysql      rsyslog-mysql/remote/port      string
  149. # Perform upgrade on database for rsyslog-mysql with dbconfig-common?
  150. rsyslog-mysql      rsyslog-mysql/dbconfig-upgrade      boolean      true
  151. # Host name of the MySQL database server for rsyslog-mysql:
  152. rsyslog-mysql      rsyslog-mysql/remote/host      select      localhost
  153. # Deconfigure database for rsyslog-mysql with dbconfig-common?
  154. rsyslog-mysql      rsyslog-mysql/dbconfig-remove      boolean      true
  155. # Database type to be used by rsyslog-mysql:
  156. rsyslog-mysql      rsyslog-mysql/database-type      select      mysql
  157. rsyslog-mysql      rsyslog-mysql/upgrade-error      select      abort
  158. rsyslog-mysql      rsyslog-mysql/remove-error      select      abort
  159. rsyslog-mysql      rsyslog-mysql/install-error      select      abort
  160. rsyslog-mysql      rsyslog-mysql/passwords-do-not-match      error
  161. rsyslog-mysql      rsyslog-mysql/internal/skip-preseed      boolean      false
  162. # Delete the database for rsyslog-mysql?
  163. rsyslog-mysql      rsyslog-mysql/purge      boolean      false
  164. # Connection method for MySQL database of rsyslog-mysql:
  165. rsyslog-mysql      rsyslog-mysql/mysql/method      select      Unix socket
  166. rsyslog-mysql      rsyslog-mysql/mysql/admin-user      string      root
  167. rsyslog-mysql      rsyslog-mysql/internal/reconfiguring      boolean      false
  168. # Configure database for rsyslog-mysql with dbconfig-common?
  169. rsyslog-mysql      rsyslog-mysql/dbconfig-install      boolean      true
  170. END
  171. DEBIAN_FRONTEND=noninteractive apt-get install -y rsyslog-mysql
  172. echo "Creating /etc/rsyslog.d/enable-remote.conf"
  173. echo "module(load=\"imudp\")" > /etc/rsyslog.d/enable-remote.conf
  174. echo "input(type=\"imudp\" port=\"514\")" >> /etc/rsyslog.d/enable-remote.conf
  175. echo "module(load=\"imtcp\")" >> /etc/rsyslog.d/enable-remote.conf
  176. echo "input(type=\"imtcp\" port=\"514\")" >> /etc/rsyslog.d/enable-remote.conf
  177. service rsyslog restart
  178. echo "17 2     * * *     root mysql -uroot -e 'use Syslog; DELETE FROM SystemEvents WHERE ReceivedAt < DATE_SUB(CURRENT_TIMESTAMP, INTERVAL 365 DAY);'" > /etc/cron.d/rsyslog_mysql
  179. #mysql -uroot -e "CREATE DATABASE Syslog_template;"
  180. #mysqldump -uroot Syslog > /tmp/sql.sql
  181. #mysql -uroot Syslog_template < /tmp/sql.sql
  182. #mysql -uroot -e "TRUNCATE TABLE Syslog_template.SystemEvents"
  183. }
  184. ######### LOG ANALYZER
  185. function install_loganalyzer {
  186. if [ ! -f loganalyzer-${LAVERSION}.tar.gz ]; then wget http://download.adiscon.com/loganalyzer/loganalyzer-${LAVERSION}.tar.gz; fi
  187. tar -xf loganalyzer-${LAVERSION}.tar.gz
  188. cp -r loganalyzer-${LAVERSION}/src/* /var/www/html/
  189. rm -rf ./loganalyzer-${LAVERSION}/
  190. rm /var/www/html/index.html
  191. chown www-data:www-data -R /var/www/html/
  192. #create new db for loganalyzer user and settings with rsyslog user as admin
  193. mysql -uroot -e "create database loganalyzer; grant all privileges on loganalyzer.* to rsyslog@localhost"
  194. #disable new version check during logon into admin panel
  195. r="\$content\['UPDATEURL'\] = \"http://loganalyzer.adiscon.com/files/version.txt\";"
  196. sed -i  "s|${r}|\$content\['UPDATEURL'\] = \"\";|g"  /var/www/html/include/functions_common.php
  197. }
  198. ####
  199. ## MAIN
  200. ####
  201. instaldebconf="false"
  202. installmariadb="false"
  203. installapache="false"
  204. installphp="false"
  205. instalphpmyadmin="false"
  206. installrsyslog="false"
  207. printf "Checking debconf-utils..."
  208. check=$( check_packages debconf-utils )
  209. if [[ $check != "true" ]]; then
  210.     echo "......will be installed"
  211.     instaldebconf="true"
  212. else
  213.     echo "......found!"
  214. fi
  215. printf "Checking sql..."
  216. check=$( check_sql )
  217. case ${check} in
  218.     false)
  219.         echo "................will be installed: MariaDB"
  220.         installmariadb="true"
  221.         ;;
  222.     mysql)
  223.         echo "................MySQL found, it will be used during installation"
  224.         ;;
  225.     mariadb)
  226.         echo "................MariaDB found, it will be used during installation"
  227.         ;;
  228. esac
  229. printf "Checking apache..."
  230. check=$( check_packages apache2 )
  231. if [[ $check != "true" ]]; then
  232.     echo ".............will be installed"
  233.     installapache="true"
  234. else
  235.     echo ".............found!"
  236. fi
  237. printf "Checking php..."
  238. check=$( check_php )
  239. if [[ $check != "true" ]]; then
  240.     echo "................will be installed: ${check}"
  241.     installphp="true"
  242.     phptoinstall=${check}
  243. else
  244.     echo "................found!"
  245. fi
  246. printf "Checking rsyslog-mysql..."
  247. check=$( check_packages rsyslog-mysql )
  248. if [[ $check != "true" ]]; then
  249.     echo "......will be installed"
  250.     installrsyslog="true"
  251. else
  252.     echo "......found!"
  253. fi
  254. printf "Checking phpmyadmin..."
  255. check=$( check_phpmyadmin )
  256. if [[ $check == "false" ]]; then
  257.     echo ".........not found in /usr/share/phpmyadmin/"
  258.     echo
  259.     while true; do
  260.         read -p "Do you wish to install phpmyadmin? (y/n): " yn
  261.         case $yn in
  262.             [Yy] ) instalphpmyadmin="true"; break;;
  263.             [Nn] ) break;;
  264.             * ) echo "Please answer [y]es or [n]o.";;
  265.         esac
  266.     done
  267. else
  268.     echo ".........found!"
  269. fi
  270. echo
  271. echo "This file(s) should be downloaded:"
  272. if [[ ${instalphpmyadmin} != "false" ]]; then echo "https://files.phpmyadmin.net/phpMyAdmin/${PMAVER}/phpMyAdmin-${PMAVER}-all-languages.tar.gz" ; fi
  273. echo "http://download.adiscon.com/loganalyzer/loganalyzer-${LAVERSION}.tar.gz"
  274. echo "You can place this file(s) into current directory manually if you have not an Internet connection."
  275. echo "Debian repository must be accessible!"
  276. echo
  277. read -p "Ok, let's do it. Press ENTER to install, CTRL-C - to abort."
  278. # INSTALL
  279. apt update
  280. if [[ ${instaldebconf} != "false" ]]; then apt -y install debconf-utils ; fi
  281. if [[ ${installmariadb} != "false" ]]; then install_sql ; fi
  282. if [[ ${installapache} != "false" ]]; then apt -y install apache2 ; fi
  283. if [[ ${installphp} != "false" ]]; then  apt -y install ${phptoinstall} ; fi
  284. if [[ ${installrsyslog} != "false" ]]; then  install_rsyslog_mysql  ; fi
  285. installrsyslog
  286. if [[ ${instalphpmyadmin} != "false" ]]; then install_phpmyadmin ; fi
  287. install_loganalyzer
  288. serverip=$(ip addr show | grep -o "inet [0-9]*\.[0-9]*\.[0-9]*\.[0-9]*" | grep -o "[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*" | grep -v "^127.0.0.1" | head -n 1)
  289. echo
  290. echo
  291. echo Installation complete
  292. echo
  293. if [[ ${instalphpmyadmin} != "false" ]]; then
  294.     echo "phpmyadmin address: http://${serverip}/phpmyadmin"
  295.     echo "             login:${PHPMYADMINUSER}"
  296.     echo "          password:${PHPMYADMINPASS}"
  297.     echo
  298. fi
  299. echo "Open IP address of this server in web-browser (http://${serverip}/)"
  300. echo and use next settings for wizard:
  301. echo
  302. echo "User Database Options (optional)"
  303. echo "Enable User Database: Yes"
  304. echo "       Database User: rsyslog"
  305. echo "   Database Password: ${SYSLOGDBPASSWORD}"
  306. echo
  307. echo "First Syslog Source"
  308. echo "                        Source Type: MYSQL Native"
  309. echo "     Database Name (case-sensitive): Syslog"
  310. echo "Database Tablename (case-sensitive): SystemEvents"
  311. echo "                      Database User: rsyslog"
  312. echo "                  Database Password: ${SYSLOGDBPASSWORD}"
  313. echo "                Enable Row Counting: Yes"

 

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

  1. mariadb в качестве сервера баз данных,
  2. rsyslog с коннектором rsyslog-mysql в качестве сислог сервера, и создаст конфиг для приема логов по сети
  3. веб-сервер apache
  4. опционально phpmyadmin для управления базой данных
  5. LogAnalyzer.

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

Настройка сервера syslog с веб-интерфейсом и хранением логов в базе данных (на Debian 10 «buster»)

Установка debian

Для наших целей подойдет установленный в минимальной конфигурации дебиан. Идеально сразу при установке поставить LAMP-набор, отметив опцию web server

Но можно обойтись пунктом standard system utilities, а все остальное установить самостоятельно. Я буду исходить из этого варианта.

Установка базы данных MariaDB

 
 
  1. apt update && apt -y install mariadb-server

Установка веб-сервера apache

 
 
  1. apt -y install apache2

Установка необходимых модулей PHP

 
 
  1. apt -y install php libapache2-mod-php php-mysql php-common php-cli php-json php-opcache php-readline php-mbstring

Установка rsyslog

 
 
  1. apt -y rsyslog-mysql

В процессе установки соглашаемся сконфигурировать базу данных

Придумываем и подтверждаем пароль для пользователя «rsyslog» БД

После того как сислог будет установлен, его нужно сконфигурировать так, чтобы он мог принимать события с сетевого оборудования. Создаем файл /etc/rsyslog.d/enable-remote.conf с таким содержанием:

/etc/rsyslog.d/enable-remote.conf
 
  1. module(load="imudp")
  2. input(type="imudp" port="514")
  3. module(load="imtcp")
  4. input(type="imtcp" port="514")

И перезагружаем сервис

 
 
  1. service rsyslog restart

Установка веб-интерфейса (LogAnalyzer)

Скачиваем и распаковываем файлы в директорию веб-сервера:

 
 
  1. wget http://download.adiscon.com/loganalyzer/loganalyzer-4.1.7.tar.gz
  2. tar -xvf loganalyzer-4.1.7.tar.gz
  3. rm loganalyzer-4.1.7.tar.gz
  4. cp -r loganalyzer-4.1.7/src/* /var/www/html/
  5. rm /var/www/html/index.html
  6. chown www-data:www-data -R /var/www/html/

Перед тем как перейти мастеру настройки, создадим еще одну одну базу, в которой лог аналайзер будет хранить свои настройки, и дадим пользователю rsyslog полные права на нее

 
 
  1. mysql -uroot -e "create database loganalyzer; grant all privileges on loganalyzer.* to rsyslog@localhost"

Настройка LogAnalyzer

Теперь к мастеру. Перейдя в браузере по адресу сервера мы должны увидеть его приглашение создать конфиг

Первые два шага пропускаем, интересное  начинается с третьего. Здесь нужно выбрать Enable User Database и ввести имя пользователя (rsyslog)  и пароль с которыми будет производиться подключение к созданной нами базе «loganalyzer». Остальные настройки можно оставить по умолчанию.

На шестом шаге создаем внутреннего администратора лог аналайзера

На следующем шаге выбираем источник данных — базу rsyslog\’а. Важные пункты, которые будет нужно здесь изменить:

  1. Source Type — MYSQL Native
  2. Database Name — Syslog (была создана при установке rsyslog-mysql)
  3. Database Tablename — SystemEvents (именно так — с большими буквами, а не как по дефолту)
  4. Database User — rsyslog
  5. Database Password — пароль юзера rsyslog
  6. Enable Row Counting — Yes

Next, Finish и перед нами интерфейс лог аналайзера

Тюнинг

Теперь остается сделать две довольно важные вещи.

Во-первых, при попытке логина в админку, лог аналайзер пытается проверить свое собственное обновление, и это приводит к длительному ожиданию, если сервер не имеет выхода в интернет. Чтобы этого не происходило — нужно отредактировать файл /var/www/html/include/functions_common.php, изменив строку

 
 
  1. $content['UPDATEURL'] = "http://loganalyzer.adiscon.com/files/version.txt";

на

 
 
  1. $content['UPDATEURL'] = "";

Второе, и не менее важное. Со временем база сислога будет опухать, поэтому ее стоит периодически очищать от старых записей. Для этого нужно создать файлик /etc/cron.d/rsyslog_mysql с содержимым

 
 
  1. 23 2 * * * root mysql -uroot -e 'use Syslog; DELETE FROM SystemEvents WHERE ReceivedAt < DATE_SUB(CURRENT_TIMESTAMP, INTERVAL 365 DAY);'

С ним каждый день из базы будут удаляться записи старше 365 дней (разумеется это количество можно поправить на необходимое)

vSphere Launch Remote Console — сменить Workstation на Player в Linux

После переустановки VMware Workstation возникла проблема — ссылка «Launch Remote Console» в web-интерфейсе vSphere стала открываться при помощи основного Workstation вместо более легкого и не требующего аутентификации Player-приложения. Чинится в линуксе очень просто:

 
 
  1. xdg-mime default vmware-player.desktop  x-scheme-handler/vmrc

 

Не проверял, но по идее аналогично можно переключить на непосредственно VMware Remote Console, поставив название его ярлыка вместо «vmware-player.desktop» (ярлыки искать в /usr/local/share/applications/)

 

Скрипт для поднятия SOCKS-прокси посредством ssh с проверкой его работоспособности

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

ЗЫ: свой собственный прокси с шифрованием трафика средствами ssh — рекомендации лучших собаководов )

proxy.sh
 
  1. #!/bin/sh
  2. # establishes an SSH Socks proxy and reconnects if it fails.
  3. socksPort=8376
  4. server=example.com
  5. user=myproxyuser
  6. key=~/.ssh/id_rsa_myproxyuser
  7. while true
  8. do
  9.     timeout 20 curl --retry-max-time 1 --retry 5 --retry-delay 1 -x socks5://127.0.0.1:${socksPort} http://google.com/ > /dev/null 2>&1
  10.     if [ $? -ne 0 ]
  11.     then
  12.         echo $(date) reconnect...
  13.         while ps -eo pid,cmd | grep ssh | grep ${socksPort}
  14.         do
  15.             kill $(ps -eo pid,cmd | grep ssh | grep ${socksPort} | awk '{print $1}' | head -n 1)
  16.         done;
  17.         ssh -D ${socksPort} -f  -q -N -i "${key}" ${user}@${server}
  18.     else
  19.         sleep 10
  20.     fi
  21. done;

Вариант для cygwin

proxy_cygwin.sh
 
  1. #!/bin/sh
  2. # establishes an SSH Socks proxy and reconnects if it fails.
  3. socksPort=8376
  4. server=example.com
  5. user=myproxyuser
  6. key=~/.ssh/id_rsa_myproxyuser
  7. while true
  8. do
  9.     timeout 20  curl -x socks5://127.0.0.1:${socksPort} http://google.com/  > /dev/null 2>&1
  10.     if [ $? -ne 0 ]
  11.     then
  12.         while ps -e | grep ssh;
  13.         do
  14.             # /bin/kill - is important!
  15.             /bin/kill -f $(grep -a "ssh" /proc/*/cmdline  | grep -a  ${socksPort} | awk -F '/' '{print $3}' | head -n 1)
  16.         done;
  17.         echo $(date) reconnect
  18.         ssh -D ${socksPort} -fNq -i "${key}" ${user}@${server}
  19.     else
  20.         sleep 10
  21.     fi
  22. done;

Централизованное хранилище VMware Tools и тулзы для Windows 2003 на vSphere 6.7

Обновив сферу, столкнулся с ошибкой:

Unable to install VMware Tools. An error occurred while trying to access image file «/usr/lib/vmware/isoimages/winPreVista.iso» needed to install VMware Tools: 2 (No such file or directory). Please refer the product documentation or KB article 2129825 for details about how to get VMware Tools package for this guest operating system

Также ошибка может звучать более лаконично:

The required VMware Tools ISO image does not exist or is inaccessible.

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

Решение этой проблемы — скачать legacy-tools и добавить нужные исошники. Но так как это придется делать для каждого хоста, то проще на общедоступном сторадже выделить папку, свалить туда все исошники и поправить на каждом из серверов параметр, указывающий на папку с тулзами.

Собственно, тулзы качаются с сайта вмвари: легаси и текущие на данный момент.

Оба архива содержат папки «floppies» и «vmtools» — совмещаем их содержимое (для легаси и новых тулзов содержимое не пересекается) и аплоадим эти две папки в отдельную папку в хранилище. Допустим, в папку vmwaretools на сторадже myStorage (таким образом у нас две папки: «myStorage/vmwaretools/floppies» и «myStorage/vmwaretools/vmtools»)

Теперь заходим в «Advanced System Settings» одного из серверов:

Ищем в них параметр «UserVars.ProductLockerLocation«, по дефолту его значение — «/locker/packages/vmtoolsRepo/», меняем его на «/vmfs/volumes/myStorage/vmwaretools/«.

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

Технически можно повторить процедуру вручную на каждом из серверов, или включить этот параметр в host profile:

 

Защита wordpress с помощью fail2ban

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

Вообще говоря, защита учеток вордпресса — это совсем отдельная тема, в которую можно погружаться и погружаться. Ботнеты ищут инсталляции ВП и стараются атаковать, как правило, с двух сторон: разумеется это wp-login.php — страница аутентификации с логином и паролем; и xmlrpc.php — кусок механизма для удаленного подключения и управления сайтом. Причем большинство атак приходится на вторую сторону, и в интернете куча инфы (копия) о том, как эту лавочку прикрыть, отрубив весь механизм. На самом деле это вполне дельная мысль, так как велика вероятность что удаленный доступ к сайту вовсе не используется, но если есть желание, например, постить через мобильный клиент вордпресса — он понадобится.

Но вне зависимости от отключения  xmlrpc, придется защищать и основную форму логона. Опять же тут можно (и нужно) возвести многоступенчатую защиту. Негрешно воткнуть капчу при помощи  WordPress ReCaptcha Integration, хорошей мыслью будет вообще запретить или ограничить регистрацию с логином и паролем, включив авторизацию через социальные сети (с этим поможет Social Login). Однако все неплохо, пока на сайт пытаются ломиться люди, но вышеупомянутые ботнеты любят атаковать с пачек IP-адресов, посылая частые запросы на аутентификацию, и тут я подбираюсь к сабжу…

Хотя на самом деле скажу еще одно: для блокировки пользователей, активно брутящих пароли, можно с помощью неплохого плагина для самого вордпресса — Limit Login Attempts Reloaded. Он вполне шикарен — ведет список IP, банит на установленный срок при превышении лимита попыток, умеет писать об этом в почту админа. Но в какой-то момент мне захотелось, чтобы такие айпишники не просто банились на уровне ВП, а выпиливались на файрволле — это более концептуальное решение, которое ко всему прочему разгружает сервер от левых запросов. Ну и конечно для такого типа задач есть готовое решение — демон fail2ban.

Оказывается прикрутить его к вордпрессу — проще простого.

Для начала нужно в папку «wp-content/mu-plugins» (если ее нет — нужно ее создать) положить файлик:

return_403_on_failed_login.php
 
  1. <?php
  2. /**
  3.  *  * Plugin Name: Return 403 on Failed Login
  4.  *   */
  5. function my_login_failed_403() {
  6.     status_header( 403 );
  7. }
  8. add_action( 'wp_login_failed', 'my_login_failed_403' );

Этот файлик, положенный в эту папку, будет постоянно работающим плагином, который нельзя отключить (папка mu-plugins — именно для таких). Суть его работы в том, чтобы при неудачной попытке залогиниться, в лог вебсервера сообщение о доступе к файлам wp-login.php и xmlrpc.php падало с 403й ошибкой. Это нужно чтобы отличать такие фейлы от простого запроса страниц. Выглядеть это будет примерно так:

 
 
  1. 143.255.155.196 - - [30/Apr/2019:09:11:01 +0300] "POST /wp-login.php HTTP/1.1" 403 2947 "https://qiwichupa.net/wp-login.php" "Mozilla/5.0 (Windows NT 10.0; rv:48.0) Gecko/20100101 Firefox/48.0"

Теперь нужно пошаманить с fail2ban.

Добавляем фильтр таких сообщений:

/etc/fail2ban/filter.d/wp-login.conf
 
  1. [Definition]
  2. failregex = <HOST>.*POST.*(wp-login\.php|xmlrpc\.php).* 403

Простая регулярка, которая выхватит IP из строки с 403ей ошибкой и нужными именами файлов.

Теперь настроим тюрьму:

/etc/fail2ban/jail.d/wordpress.conf
 
  1. [wp-mysite]
  2. enabled = true
  3. port = http,https
  4. filter = wp-login
  5. logpath = /var/log/nginx/mysite_access.log
  6. findtime = 600
  7. maxretry = 2
  8. bantime = 86400

Тут нужно обратить внимание на параметр logpath — он должен вести к аксес-логу вебсервера (apache или nginx, если он стоит перед апачем). Параметры findtime и bantime принимают значение в секундах, первый отвечает за интервал в который с одного айпишника должны упасть фейлы для срабатывания блокировки, второй — время бана. Так данный пример конфига отправит айпишник в бан на сутки, если с него за 10 минут прилетит больше двух неудачных попыток аутентификации.

Собственно и всё. Рестартим fail2ban, смотрим в /var/log/fail2ban.log — в нем должно быть написано что тюрьма запустилась, а спустя какое-то время, если на сайт полезли боты, и сообщения о банах должны появиться:

 
 
  1. 2019-04-30 00:42:10,120 fail2ban.jail : INFO Jail 'wp-mysite' started
  2. 2019-04-30 00:42:37,452 fail2ban.actions: WARNING [wp-mysite] Ban 119.160.136.138
  3. 2019-04-30 00:42:37,483 fail2ban.actions: WARNING [wp-mysite] Ban 143.255.155.57

Написал поисковик для файлопомоек — pyFileSearcher

По работе нужно было внести ясность в постоянно убывающее место на файловых серверах, на которые пользователи любят сгружать всякий мусор, не относящийся к работе. Столкнувшись с такой необходимостью, полез искать софт и выяснил, что хотя индексаторов в целом довольно много, но они или перегружены функционалом и нацелены на домашнего пользователя — такие просто не справляются с большим объемом файлов; или являются какими-то безумными корпоративными системами, которые выглядят страшно шописец, ставятся как отдельный сервер с разворачиваемыми агентами и настраиваются так, что без поллитры не разобраться.

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

Получилось портабельное приложение, которое не обладает горой функционала, но во-первых умеет сожрать в себя 20 миллионов файлов, во-вторых — умеет искать по нужным в быту параметрам, таким как размер файла, тип, и — это важно — дате добавления в индекс. Строго говоря я не видел тулзов, которые бы сами запоминали время, когда файл был обнаружен. Да, у файла есть время создания и время модификации — и казалось бы их должно хватать для отфильтровывания новых файлов, когда мы хотим их найти. Но хрен там был, эти атрибуты ведут себя черт знает как — например файл притащенный с плеера может показать какой-нить 1700й год до нашей эры.

В общем ладно, это все лирика, вот что вышло:

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

При скролле результатов отсутствующие файлы подсвечиваются красным, список можно сохранить в csv чтобы предъявить владельцу каталога на сервере или его начальнику =) Фильтры поиска можно сохранять (обычно мне нужны медиафайлы размером не менее, список расширений прилагается, в индексе появились за неделю)

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

В общем получилось такое промежуточное решение — простенькое и на скорую руку, не требующее воскуривания мануалов перед использованием, но и не умирающее от большого файлсервера. Да, поиск внутри файлов не умеет, как и кучу других плюшек, так что для домашнего использования скорее всего не пригодится, но мою задачу решает лучше чем что-то похожее, что я использовал (Locate32 — от его интерфейса и возможностей я отталкивался, но он с некоторой периодичностью терял конфиг, жрал под гиг оперативки из-за использования локальных баз, и был виндуз-онли. Хотя в целом прога более чем годная). Так что вот он, первый релиз: https://github.com/qiwichupa/pyFileSearcher/releases также залил на сурсфордж.

Думаю еще пару фишек потом добавить, типа поиска по файлам которые были удалены, потому что оно бывает нужно. Но это как будет время и желание — базовые мои хотелки оно уже удовлетворяет, может кому пригодится тоже =)

 

Настройка хранилища с iSCSI для VMware

Не нашел нормальной статьи как из говна и палок собрать СХД для ESXI от вмвари, так что распишу сам как же это делается.

Для начала нужно СХД.

Подготовка iSCSI-хранилища

Назовем это сервер-хранилище, чтобы не путать с серверами вмвари.

Это может быть любой комп, желательно сервер, желательно с рейдом. Я поставил на него Debian, потому что я люблю дебиан.

Сразу хинт: в рабочей обстановке на сервере скорее всего не будет интернета, поэтому для установки софта лучше развернуть  отдельный дебиан на сервере (виртуалке) с доступом и в инет и в локалку, поставить на него apt-cacher-ng, а на нашей разворачиваемой хранилке создать файл «/etc/apt/apt.conf.d/66proxy» с содержимым

 
 
  1. Acquire::http { Proxy "http://IP:3142"; }

 Тогда конкретно apt будет качать все через этот «прокси» и не придется настраивать настоящую проксю, которая скорее всего не нужна а может и противоречить безопасности.

Однако про iSCSI. Ставим единственный необходимый пакет:

apt update && apt install tgt

После этого добавляем конфиг

/etc/tgt/conf.d/storage_target.conf:
 
  1. <target iqn.2019-10.server1.domain.local:lun1>
  2. scsi_id IET 00010001
  3. controller_tid 1
  4. lun 1
  5. backing-store /dev/mapper/server1-storage
  6. </target>

 

Что тут почем:

iqn.2019-10.server1.domain.local:lun1 — тут iqn.2019-10 — это стандартное начало с указанием даты создания луна  например; storage1.server1.local — адрес нашего сервера; lun1 — первый (и единственный) лун. Фактически во всей этой строке можно писать значения от балды, они несут скорее идентификационное значение для нас.

«scsi_id IET 00010001» , «controller_tid 1» и «lun 1» —  айдишник луна,  айдишник контроллера луна и номер луна, все идут в связке и имеют важное значение, если в планах подключение нескольких импровизированных серверов-хранилищ к серверу с вмварью. Чтобы вмварь не подумала что ваши два (три, пять, двадцать два) сервера-хранилища содержат один и тот же лун,  все эти номера должны быть уникальны. Если у вас по одному луну на хранилище — просто нумеруйте их последовательно: 00010001, 1, 1 — для первого сервера-хранилища; 00020001, 2, 2 — для второго; 00030001, 3, 3 — для третьего и т.д.

backing-store — неотформатированное  блочное устройство, в моем случае том LVM. Имя должно быть уникально, разумеется, в пределах сервера-хранилища.

В моем случае я настраиваю два хранилища, так что вот конфиг второго

/etc/tgt/conf.d/storage_target.conf:
 
  1. <target iqn.2019-10.server2.domain.local:lun1>
  2. scsi_id IET 00020001
  3. controller_tid 2
  4. lun 2
  5. backing-store /dev/mapper/server2-storage
  6. </target>

 

Собственно, всё. Стоит только уточнить — сервер-хранилище и esxi-сервер должны быть в одной подсети, по крайней мере если у вас ESXI не одной из последних версий, которые научились в машрутизируемый iSCSI. Я буду использовать старенький уже ESXI 5, так что для моего случая это замечание справедливо.

Настройка сервера ESXI

Итак, у меня отдельно стоящий сервер ESXI без — это важно — железного iSCSI-адаптера. Если у вас они есть и вмварь их видит (как на картинке ниже) — стоит использовать их, если нет — нажимайте синюю ссылку Add над списком:

После нажатия, вам должны предложить добавить софтварный iSCSI-адаптер

Окей, добавили

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

Дальше переходим на вкладку Dynamic Discovery и добавляем айпишники серверов-хранилищ (порт по умолчанию)

Закрываем окна, соглашаемся обновить список лунов и вуаля — видим по два имени на одно однолунное хранилище (имя луна имя контроллера). Обратите внимание — айдишники луна и контроллера входят в имя (к id контроллера дописывается «0000»), а номер луна — показывается в графе LUN.

 

Теперь остается через Storage — Add storage превратить луны в хранилища VMware

Debian Installer: Detect network hardware, missing firmware BNX2

При установке дебиана на сервера подобные IBM x3650 можно столкнуться с ошибкой определения сетевых драйверов: «Some of your hardware needs non-free firmware files to operate», что означает необходимость подсунуть инсталлятору несвободные драйвера, указанные ниже.

В данном случае это «bnx2/bnx2-mips-09-6.2.1b.fw», но может быть и другой в зависимости от железа. Необходимые драйвера можно скачать вот тут: https://github.com/cernekee/linux-firmware/tree/master/bnx2. Их нужно положить на съемный носитель как предписывает инсталлятор (то есть, в данном случае, в папку bnx2 в корне флешки) и нажать YES. Вполне возможно, что операцию придется провести несколько раз, если в сервере несколько сетевых карт, требующих разных драйверов — в таком случае можно скачать их все сразу, или подсовывать по мере необходимости. Отмонтировать или монтировать флешку не нужно — можно смело втыкать и вытыкать из порта сколько понадобится.

Из моих наблюдений: драйвера не подцеплялись со съемного диска Zalman VE200, эмулирующего CD-привод с ISO-образом инсталлятора. Может особенность конкретного устройства, но скорее потому что сам диск был отформатирован в NTFS, так что флешку под дрова лучше сразу форматнуть в FAT32.

CyrTranscoder — свой велосипед для борьбы с кракозябрами

В качестве лишней практики написал перекодировщик кракозябр, наподобие старой-доброй утилки «Штирлиц».

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

Скачать можно на гитхабе: https://github.com/qiwichupa/cyrtranscode/releases

LVM: изменение размера, снапшоты, миграция

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

Перво-наперво

У нас должно быть свободное место в Volume Group.  Нет смысла без особой необходимости забивать все свободное место логическими томами, когда их свободное место будет использовано не до конца. Если у нас один хард на 500 гиг, мы делаем группу на весь этот объем, а дальше, например, делаем один том в 1G под swap, другой — в 9G под /, и, например, третий — на 50G под /home. У нас остается  440G свободного места, которое мы в любой момент можем докинуть в любой раздел, а также использовать под снапшоты. Соу…

Как добавить места на Logical Volume

Увеличение можно проделывать на смонтированной файловой системе.

Допустим, у нас есть LVM-том с линуксовым корнем /dev/mypc/root, содержащий на себе линуксовый корень. Докинуть 100 мегабайт можно командой:

 
 
  1. lvextend -L +100m /dev/mypc/root
  2. resize2fs /dev/mypc/root

 

Первая команда увеличит том, вторая — распространит на него файловую систему.

 

 

 

Как сделать и откатить снапшот

Допустим, у нас все еще есть LVM-том /dev/mypc/root, содержащий на себе линуксовый корень. Если нам нужно, например, накатить новые дрова для видюхи и мы боимся все сломать, делаем снапшот:

 
 
  1. lvcreate -L2G -s -n rootsnapshot /dev/mypc/root

 

Эта команда сделает снапшот /dev/mypc/rootsnapshot, который будет содержать состояние на момент создания снапшота. При этом есть ограничение в 2 гига на изменения в нашем корне, если превысим — снапшот перестанет быть валидным и его можно будет только удалить:

 
 
  1. lvremove /dev/mypc/rootsnapshot

 

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

 

Автоматическое увеличение размера снапшота LVM

Тут все просто, но не так просто, как часто пишут в интернетах. Нужно:

  1. Изменить файлик /etc/lvm/lvm.conf:
    snapshot_autoextend_threshold = 80
    snapshot_autoextend_percent = 20
    monitoring = 1Эти опции включают мониторинг, а так же увеличивают размер снапшота на 20% (от текущего размера) каждый раз, когда он оказывается занят изменениями на 80%.
  2. Установить dmeventd, который может не стоять, но который нужен чтобы все работало!

Теперь, когда наш снапшот умеет расти в размере и ему почти ничего не страшно, можно поиздеваться над корнем и откатить все изменения командой:

 
 
  1. lvconvert --merge  /dev/mypc/rootsnapshot

 

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

 

Как смигрировать на другой физический диск

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

Допустим у нас есть диск /dev/sda. На его разделе /dev/sda1 у нас покоится Volume Group «mypc» с нашими логическими томами:

  1. root — с корнем линукса (/),
  2. home — с домашними  каталогами (/home),
  3. swap — с разделом подкачки.

И нам нужно все это добро перенести на новый хард — /dev/sdb, который гол как сокол и ничего ж там нет.

Готовим новый диск

 
 
  1. # Создаем раздел на новом диске:
  2. parted -a opt /dev/sdb mkpart primary 0% 100%
  3. # Создаем физический том LVM:
  4. pvcreate /dev/sdb1
  5. # Расширяем Volume Group на новый физический том:
  6. vgextend mypc /dev/sdb1

 

Сдвигаем наши три логических тома со старого физического тома на новый:

 
 
  1. pvmove -n /dev/mypc/root /dev/sda1 /dev/sdb1
  2. pvmove -n /dev/mypc/home /dev/sda1 /dev/sdb1
  3. pvmove -n /dev/mypc/swap /dev/sda1 /dev/sdb1

 

Избавляемся от старого харда

 
 
  1. # Удаляем физический том LVM из группы "mypc":
  2. vgreduce mypc /dev/sda1
  3. # Удаляем физический том LVM:
  4. pvremove /dev/sda1

 

Устанавливаем загрузчик на новый диск и обновляем его конфиг:

 
 
  1. grub-install /dev/sdb
  2. update-grub

 

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