Я уже писал про домашний сервер не один раз и эта статья должна стать завершающей в данном цикле. В этот раз мне требуется организовать доступ к своему «домашнему железу«, чтобы можно было работать из любой точки города, региона или страны. Есть 2 варианта организации такого доступа: купить внешний IP-адрес у провайдера на постоянку (белый IP) или арендовать внешний VPS, который будет являться шлюзом в интернете. Лично я для себя решил выбрать VPS. Ну что же… Release it!

Выбор VPS
Тут я мог бы провести анализ рынка облаков, стоимости, качества, стабильности. Но я этого делать не буду. На рынке услуг просто масса и можно выбирать все что угодно согласно Вашему бюджету, предпочтению, желанию и требованиям. Вторая причина по которой я этого делать не буду — это реклама. Ну вот не хочу и все!
Чтобы подобрать для себя VPS нужно определиться с техническими характеристиками. В моем случае у меня будет установлено всего 3 основных приложения: openvpn, nginx и certbot. Для чего они нужны я буду говорить далее. На весь этот ворох приложений на текущий момент у меня уходит 260МБ ОЗУ, загрузка CPU (на одно ядро) не более 30% и HDD занято 5.5ГБ. Так что выбираем под себя (или даже один из самых дешевых на сколько это возможно). На счет скорости сети смотрим и оцениваем сами. Может вы будете гонять терабайты данных на высоких скоростях, а может и 100 мегабайт превышать не будет. Так что прикидываем и определяемся.
Что на счет операционной системы, то выбираем то, что умеем настраивать лучше всего. Просто потому что так проще. Лично я для себя выбрал CentOS из тех дистрибутивов, что были доступны.
Настройка хостера
Для начала нужно немного подготовить настройки хостинга. Первым делом идем в настройки самого хостера и настраиваем сеть. Первое это нужно убедиться, что нам дали внешний IP, по которому мы будем подключаться. После заходим в настройки безопасности сети и проверяем какие порты открыты. Понадобятся следующие порты:
- 80 (http)
- 443 (https)
- 22 (ssh)
- 1194 (openvpn)
Все остальные можно закрыть (они не понадобятся). Как это сделать я не буду рассказывать, так как у каждого хостера свой интерфейс с настройками. По факту ничего сложного нету. Что касается портов, то 22-й множно перенести на другой, например 2222 с перенаправлением порта на 22 самой виртуальной машины (VM), а 1194 можно просто использовать другой, например, 11194й, ну или какой-то еще по желанию. 80й и 443й должны остаться такими, чтобы web-браузеры могли спокойной работать.
Если же хостинг не предоставляет таких настроек и Вам открыты все порты, то хорошим тоном будет настройка межсетевого экрана на самой VPS, иначе получится проходной двор. В общем «не секурно» как-то…
Подготовка ОС
Чтобы не мешал SELinux — выключим его. Для этого в консоли переходим в root и выполняем:
setenforce 0
И в файле /etc/sysconfig/selinux устанавливаем параметр SELINUX=disabled. Кстати, в CentOS по умолчанию редактор vim, но те кто хочет nano ставим так:
dnf install nano
Теперь подключаем epel (а вдруг пригодится):
yum install epel-release
Далее устанавливаем nginx по мануалу. Я не буду описывать, потому что все предельно просто.
Теперь устанавливаем некоторые пакеты:
dnf install openvpn certbot openvpn easy-rsa
Здесь мы устанавливаем CertBot для Let’s Encrypt, OpenVPN для соединения с нашим домашним сервером и easy-rsa для генерирования сертификатов и настройки тоннеля.
OpenVPN
Не хочу расписывать целые талмуты настройки тоннеля, так как этого материала полно. Все же есть некоторый моменты на которые я наткнулся и о них я немного расскажу.
Первым делом действуем по инструкции и генерируем сертификаты. Здесь все выполняется пошагово. Различия начинаются (как у меня сделано) в конфигурационных файлах самого OpenVPN.
На сервере файлы распологаются по пути /etc/openvpn/server и в моем случае конфигурационный файл называется gateway.conf:
port 1194
proto tcp
dev tun
server 10.26.0.0 255.255.255.0
keepalive 10 120
dh dh.pem
ca ca.crt
cert gateway.crt
key gateway.key
tls-auth ta.key 0
verb 3
status /var/log/openvpn/openvpn-status.log 1
status-version 3
log-append /var/log/openvpn/openvpn-client.log
client-config-dir /etc/openvpn/clients
comp-lzo
Вот тут появляются моменты, с которыми я столкнулся.
server 10.26.0.0 255.255.255.0
Здесь я устанавливаю водсеть самого vpn. У меня это будет 10.26.0.0/24. Соответственно выставляйте свою, которая Вам нравится. Просто это класс корпоративной сети. За подробностями стоит обратиться к соответствующей технической литературе.
keepalive 10 120
Вот этот параметр говорит, что каждые 10 секунд и, если в течении 120 секунд не будет ответа, то попытаться перезапустить туннель. Без этого у меня туннель зависал и отваливался. Обидно даже.
comp-lzo
Тут все просто! Включаем сжатие трафика в туннеле алгоритмом lzo. Бинарные сжатые данные конечно же не сожмутся (может даже чуть увеличится объем), а вот на текстовых данные это будет видно. Порой спорный параметр, нужно смотреть, но в общем и целом, думаю, использовать можно.
client-config-dir /etc/openvpn/clients
В этой директории будут лежать некоторые настройки для клиентов. Здесь все просто. У меня лежит один файл apps с таким содержимым:
ifconfig-push 10.26.0.253 10.26.0.1
Тут говорится, что подключенномe клиенту apps (так называется сертификат клиента и так его показывает openvpn) присвоить адрес 10.26.0.253 и сказать ему, что шлюз будет 10.26.0.1.
Перезапускаем сервер:
systemctl start openvpn-server@gateway && systemctl enable openvpn-server@gateway

OpenVPN-клиент
Теперь на домашнем сервере необходимо установить как раз соединение со шлюзом. Устанавливаем (напоминаю, у меня armbian):
apt install openvpn
Сразу идем в /etc/openvpn и наполняем файл client.conf настройками:
dev tun
proto tcp
remote <внешний IP-адрес сервера> 1194
client
resolv-retry infinite
ca /etc/openvpn/client/ca.crt
cert /etc/openvpn/client/apps.crt
key /etc/openvpn/client/apps.key
persist-key
persist-tun
comp-lzo
verb 3
status /var/log/openvpn/openvpn-status.log 1
status-version 3
log-append /var/log/openvpn/openvpn-client.log
tls-auth client/ta.key 1
keepalive 10 120
Файл клиента очень похож на файл сервера, просто в нем отличается пара строк. Так же не забываем скопировать с сервера сертификаты для клиента.
Теперь запускаем:
systemctl start openvpn@client && systemctl enable op[envpn@client
Обязательно проверяем, что туннель поднялся как на сервере, так и на клиенте с помощью команды ip a. В выводе должен появиться сетевой интерфейс tun и отобразиться IP-адреса, которые мы установили.

DNS
cloudПеред настройкой web-сервера хочется чтобы это было «красиво«. Так что бежим за покупкой доменного имени второго уровня! Проверяем желаемый и, если он свободен, покупаем и радуемся! Сказать тут больше нечего…
После покупки прописываем внешний IP-адрес нашего шлюза и ждем… Ждем… Ждем… Можем и сутки ждать, пока все заработает. Это нормально, так как DNS-запись должна распространиться по всем DNS-серверам.
Если нужен домен 3-го уровня на Вашем же домене 2-го уровня, то добавляем его там же и вешаем на этот же IP-адрес. В этом ничего страшного нет, так как web-сервер сам разрулит какой запрос к какому серверу перенаправить.
Nginx и CertBot
Вот тут, по сути, нужно их настраивать в паре. Чтобы настроить получение сертификатов я использовал вот эту статью. Работает и на CentOS (а чего бы ему не работать?).
Теперь когда все готово прописываем конфигурацию для нашего сайта:
server {
listen 80;
server_name <домен 2го уровня> www.<домен 2го уровня>;
access_log /var/log/nginx/site.access.log main;
include acme;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl http2;
server_name <домен 2го уровня> www.<домен 2го уровня>;
gzip on;
access_log /var/log/nginx/site.access.log;
ssl_certificate /etc/letsencrypt/live/<директория с сертификатами>/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/<директория с сертификатами>/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/<директория с сертификатами>/chain.pem;
ssl_stapling on;
ssl_stapling_verify on;
ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS";
#ssl_ciphers "RC4:HIGH:!aNULL:!MD5:!kEDH";
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:100m;
ssl_session_timeout 5m;
add_header Strict-Transport-Security 'max-age=604800';
add_header Content-Security-Policy "img-src https: data:; upgrade-insecure-requests";
resolver 8.8.8.8;
client_max_body_size 1024m;
set_real_ip_from 10.26.0.1;
real_ip_header X-Forwarded-For;
location / {
proxy_pass http://10.26.0.253:8080;
proxy_set_header Host $host;
proxy_redirect off;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 120s;
proxy_read_timeout 180s;
}
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
}
Вот тут нужно немного пояснить.
Тот сервер, что слушает 80й порт нужен чтобы ответить на acme для certbot, а остальные запросы перенаправить на 443й порт. Второй сервер, который слушает 443й порт перенаправляет запросы по vpn-каналу на наш домашний сервер. Вот собственно и все.
Теперь проверим правильно ли написана конфигурация (нет ли ошибок):
nginx -t
И, если все хорошо, скажем nginx чтобы применил конфигурацию:
nginx -s reload
Результат
Вот и все. Теперь можно спокойно отключать мобильник от домашнего Wi-Fi и пробовать ломиться по нашему адресу.