Апдейты и фиксы на домашнем сервере

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

Поднятые темы – VPN, munin, Apache (прокси и редиректы), Xen pygrub и апдейты Debian’a.

Прежде всего – VPN. Да, у меня так и крутится все вокруг PPTP, работает – и ладно. То, что должно шифроваться – шифруется и так, а мне надо просто порт куда-нибудь прокинуть. Но давно пора освоить какой-нибудь Wireguard.

Если быть точным – работало. Нет, я давно обратил внимание на то, что dom0 у меня не подключается к VPN, что сломало, как минимум, просмотр видеонаблюдения удаленно (но ок, необходимость в этом стала редкой – чаще я находился прямо возле сервера, так что смотрел локально). Но, как выяснилось, на сейчас у меня вообще ничего не подключалось – постоянно шли запросы, но ни одного установившегося подключения.

На малом сервере у меня так и крутится автобалансировка между двумя каналами через route с метрикой. Думал, какая-то проблема возникла из-за этого – в частности, раньше сталкивался с тем, что контрольное подключение могло идти по одному каналу, GRE по другому и так далее. Плюс всякие разрешения, дополнительные модули ядра для PPTP – в общем, морока. Полную схему в голове толком никогда не держал.

Полез разбираться; проверял наличие нужных модулей и тому подобного. Пробовал подгружать те модули, что искались по gre и pptp. Часть модулей уже была неактуальна – так и осталась в скрипте, просто ошибка загрузки отправлялась в /dev/null. Часть покомментировал – все равно на VPS’ке нет нужды в форварде IRC и FTP, а скрипт делался по образцу. По ходу дела вспомнилось, что были и требовались какие-то helper’ы. Полез искать – нужных файлов нет. Модули не ищутся. В итоге в сети нашел отсылку к тому, что сейчас helper добавляется прямо в правила iptables’а. Открыл свой скрипт iptables’а – а ведь правило вида

"${ipt}" -A PREROUTING -t raw -p tcp -m tcp --dport 1723 -j CT --helper pptp

у меня уже было. Правда, закомментированное. Почему – уже не помню. Похоже, в рантайме добавил, но после перезагрузки оно сбросилось, поэтому подключение через PPTP перестало работать. Добавил заново, раскомментировал – все отлично.

Но dom0 на сейчас так и не подключается, ругается “LCP: timeout sending Config-Requests” и “Input/output error” для GRE.

Однако решил пока отложить поиски решения по dom0, а двигаться в сторону большей самостоятельности отдельных хостов – развернуть pptp-client на нужных машинах – тем более, их не так уж и много: восстановить наблюдение, статистику. В идеале – добавить Home Assistant. Составил список бывших форвардов, исключил лишние.

NAS запустил быстро, там свежий софт. Сложнее было с статистикой и поисковиком – там сразу несколько проблем: после перехода на pygrub, в системе у меня осталось только одно самосборное ядро (Update: как выяснилось, на малом сервере остались все собранные ранее ядра. Ну да поздно) и там не было возможности работы с PPP. В свою очередь, хосты были очень старые (Debian 7) и просто так поставить все нужное сходу было сложно. Старость хостов цеплялась за 2 вещи:

  • Mnogosearch на поисковике, который был давно неактуален – даже сайт перестал существовать – собирался еще на старой системе и так с тех пор и работал. Обновлять систему – риск все разломать. Более кардинальный подход – развернуть какой-нибудь Sphinx, но на это требовалось больше времени.
  • На сервере статистики был нормально работающий Munin, строящий графики по запросу. Почему-то Munin на NAS’е (обслуживающий только NAS) не выводил ничего вообще. Часть пакетов начал обновлять, часть осталась старой, так и оставил, лишь бы работало – разломать сервер статистики не хотелось.

В итоге для начала на поисковике добавил живые репозитории с http://archive.debian.org, чтобы можно было хоть как-то ставить пакеты. Самосборное ядро было версии 4.9.161, в репозиториях доступно только 3-е как для Debian 7, так и для 8. 4-е появлялось только в бэкпортах для Debian 8. Поставил в итоге это ядро, но загрузиться так и не смог – думаю, из-за сопутствующих проблем, которые потом всплывали и для ядра с Debian 9. Так или иначе, оптимальным вариантом оказалось последовательное обновление сначала до Debian 8 – функции хостов при этом остались плюс-минус рабочими (поплыли некритичные опции в Апаче, отвалился мониторинг Апача в monit – такое). Далее подключался репозиторий Debian 9 и ставилось 4-е ядро оттуда. Все делалось не за один раз; бэкапил диск целиком перед большими изменениями, несколько раз разворачивал.

Попутно отказался от reiserfs, когда при загрузке была ругань на отсутствие утилиты для проверки (при том, что в системе она была). Хорошая была ФС – особенно для медленного HDD, но сейчас все уже на NVMe, а для унификации лучше использовать везде ext4.

А еще была ругань на отсутствие драйверов блочных и сетевых устройств, а также в других случаях – проблемы с зависающим до бесконечности каким-то скриптом, работающим с блочным устройством. Как выяснилось (как я это на сейчас понимаю), проблема была в том числе в недостаточно строгой проверке версии udev, он оставался старее (от Debian 7), чем надо. Попутно один раз наступил на еще одни грабли – initrd сгенерировался с modules=dep в конфиге при том, что работало самосборное ядро (без модулей). В итоге старался следить, чтобы было modules=most до конца всех процедур.

В итоге системы привел к виду “Debian 8 + ядро от Debian 9”. Но если с поисковиком все было плюс-минус нормально, то сервер статистики я все же немного разломал. Одним из моментов было то, что более новый Апач хотел видеть конфиги в виде файлов *.conf. Munin же держал симлинк в каталоге /etc/apache2/conf-enabled/ (или /etc/apache2/sites-enabled/ – уже не помню) в виде просто “munin“. Далее, для /usr/share в /etc/apache2/apache2.conf стояла опция Require all granted, что позволяло работать редиректу на Nagios, но не давало работать Munin, который был в /var/cache/munin/, несмотря на всякие “Options FollowSymLinks” – опции просто не работали, а в логах Апача были сообщения про “client denied by server configuration“. В общем, добавление опции прямо в конфиг /etc/munin/apache.conf (симлинк на который подкладывался Апачу) решило проблему. А параллельно возникла мысль о том, что проблема с неработающим Munin на NAS имеет тот же корень. И таки да, таким же образом решил проблему и там, с той лишь поправкой, что немного отличались каталоги. Теперь вполне можно развернуть новый сервер статистики на базе более свежего Debian’а – как исправить проблему с отсутствием графиков уже знаю.

PPTP клиенты были успешно развернуты на всех нужных хостах. Что интересно, на свежих системах интерфейс получал в том числе IPv6 link local адрес – при том же конфиге у PPTP.

Конфиг Апача для проксирования запросов поправил под актуальные адреса. В том числе сделал вывод “наружу” домашний Home Assistant. Но тут уже захотелось иметь HTTPS-соединение – т.е., надо задействовать Апач как для проксирования любых запросов к домену на адрес в VPN’e, так и для получения сертификата и использования их локально для самого Апача. В итоге для начала нашел вариант с добавлением опции

ProxyPass /.well-known/ !

перед остальными ProxyPass / ProxyPassReverse (плюс создал DocumentRoot и добавил его в конфиг), что позволяло обрабатывать запросы от  Let’s Encrypt локально, а все остальное форвардить на VPN. А уже после успешного получения сертификатов добавил Апачу секцию с SSL, а проксирование через HTTP решил отключил совсем. Теперь HTTP будет служить только для получения сертификатов, а весь трафик до сервера будет ходить через HTTPS. Правило исключения для /.well-known у HTTPS на всякий случай оставил.

Со стороны Home Assistant тоже потребовалась настройка – на внешние запросы он упорно отдавал ошибку 400 до тех пор, пока в конфиг (в моем случае это /home/homeassistant/.homeassistant/configuration.yaml) не добавил найденный в сети рецепт:

http:
  use_x_forwarded_for: true
  trusted_proxies:
    - 192.168.223.253

Где, соответственно, IP – адрес VPN-сервера.

Update: Иии… Fail. Недостаточно просто лишь проксировать запросы Апачем, нужна дополнительная акробатика. Выяснилось, когда пытался подключиться приложением на телефоне с внешней сети. Решение тут. Дублирую: надо доставить модуль proxy_wstunnel для Апача, а в конфиге прокси сделать так:

<VirtualHost *:443>
 ServerName home.example.org
 ProxyPreserveHost On
 ProxyRequests off
 ProxyPass /api/websocket ws://localhost:8123/api/websocket
 ProxyPassReverse /api/websocket ws://localhost:8123/api/websocket
 ProxyPass / http://localhost:8123/
 ProxyPassReverse / http://localhost:8123/

 RewriteEngine on
 RewriteCond %{HTTP:Upgrade} =websocket [NC]
 RewriteRule /(.*) ws://localhost:8123/$1 [P,L]
 RewriteCond %{HTTP:Upgrade} !=websocket [NC]
 RewriteRule /(.*) http://localhost:8123/$1 [P,L]
</VirtualHost>

Соответственно, IP меняем на адрес хоста в VPN’e. После этого заработало.

Добавить комментарий