Реверс-прокси на службе человечества

Реверс-прокси на службе человечества Инструкция, Linux, Https, Длиннопост, Информационная безопасность

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

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

Примечание 1: это статья рассчитана на нулевой или начальный уровень читающего. Очень подробно и просто, без занудства.

Примечание 2: Всё описанное в этой статье приведено только в обучающих целях и не должно быть использовано для противоправных действий. Администрация сайта не несёт ответственность за действия третьих лиц, использующих инструкции из данной статьи. Все скриншоты и адреса сайтов в этой статье являются художественным вымыслом, совпадения с реальными адресами и сайтами случайно.

Примечание 3: статья может и будет дорабатываться. Наиболее актуальный вариант как всегда в первоисточнике. Да и конфиги там выглядят как надо.

Nginx это не только web-сервер, но и кое что получше. Его можно использовать в качестве обратного прокси или реверс-прокси. Что это значит? Реверс-прокси это посредник между пользователем и реальным web-сервером. Это значит, мы можем скрыть от пользователя (или от того, сто фильтрует наш трафик ) настоящий адрес web-сервера, обеспечить доступ по https к серверу, который умеет только http, можем подменить домен web-сервера, можем фильтровать содержимое трафика как с целью подмены содержимого сайта, так и для защиты web-сервера от атак злодеев, можем кэшировать сайт для ускорения, можем балансировать нагрузку, можем… Да очень много можем! Например, сделать своё собственное зеркало RuTracker или любого другого сайта, к которому нет доступа обычным способом.


Лучше всего показывать на реальных примерах. Нам понадобится VPS с минимальными характеристиками. Nginx не требователен к ресурсам. Главное, чтобы хватило лимитов трафика под Вашу задачу. В данной статье для скриншотов будет использоваться VPS с операционной системой CentOS 7. Для других операционных систем конфиги абсолютно аналогичны. Старайтесь использовать минимальную конфигурацию операционной системы без дополнительных пакетов.

Реверс-прокси на службе человечества Инструкция, Linux, Https, Длиннопост, Информационная безопасность

Также нам понадобится домен. Можете использовать домен третьего уровня у какого-то своего домена, но лучше для таких дел арендовать отдельный новый платный домен, или арендовать бесплатный домен где-нибудь на freenom.com. Вы должны быть готовы к тому, что ваш домен добавят в реестр запрещенных сайтов. Это не должно затронуть какие-либо другие Ваши сервисы, кроме реверс-прокси. Для этого домена нужно добавить A запись с IP адресом нашего VPS. Как арендовать домен и настраивать DNS записи можно почитать здесь. Для примера в статье будет использоваться домен mydomain.com


Как арендовать и первично настроить VPS описано здесь, здесь и здесь. Должен быть разрешён доступ к серверу по портам tcp/22, tcp/80 и tcp/443. Если вы используете эту статью для настройки файрволла, то конфиг ipt-set будет выглядеть так:


#!/bin/sh

IF_EXT="venet0"

IPT="/sbin/iptables"

IPT6="/sbin/ip6tables"

# flush

$IPT --flush

$IPT -t nat --flush

$IPT -t mangle --flush

$IPT -X

$IPT6 --flush

# loopback

$IPT -A INPUT -i lo -j ACCEPT

$IPT -A OUTPUT -o lo -j ACCEPT

# default

$IPT -P INPUT DROP

$IPT -P OUTPUT DROP

$IPT -P FORWARD DROP

$IPT6 -P INPUT DROP

$IPT6 -P OUTPUT DROP

$IPT6 -P FORWARD DROP

# allow forwarding

echo 1 > /proc/sys/net/ipv4/ip_forward

# NAT

# #########################################

# SNAT - local users to out internet

$IPT -t nat -A POSTROUTING -o $IF_EXT -j MASQUERADE

# INPUT chain

# #########################################

$IPT -A INPUT -p tcp ! --syn -m state --state NEW -j DROP

$IPT -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# ssh

$IPT -A INPUT -i $IF_EXT -p tcp --dport 22 -j ACCEPT

# WEB

$IPT -A INPUT -i $IF_EXT -p tcp --dport 80 -j ACCEPT

$IPT -A INPUT -i $IF_EXT -p tcp --dport 443 -j ACCEPT

# OUTPUT chain

# #########################################

$IPT -A OUTPUT -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT

Обновим сервер:

yum -y update

yum -y install epel-release

Ставим собственно Nginx

yum -y install nginx

Пробуем запустить

systemctl start nginx

Теперь, если мы попробуем в браузере перейти по адресу нашего домена http://mydomain.com (вы, соответсвенно вводите своё имя домена), то должны увидеть страницу-заглушку. Типа такой:

Реверс-прокси на службе человечества Инструкция, Linux, Https, Длиннопост, Информационная безопасность

Также можно проверить работоспособность службы командой:

systemctl status -l nginx

Вывод команды должен выглядеть так:

Реверс-прокси на службе человечества Инструкция, Linux, Https, Длиннопост, Информационная безопасность

Если возникли проблемы и служба не запускается, то скорее всего вы используете не минимальный дистрибутив операционной системы и в системе уже установлен какой-то web-сервер, который занимает порт. Чтобы проверить это, установим сетевые утилиты

yum install net-tools -y

И проверим, кто занимает порт

netstat -tulnp | grep 80

В выводе команды вы можете увидеть, например:

tcp 0 0 :::80 :::* LISTEN 104/httpd

Это значит, что установлен Apache и запущен его демон httpd. Убираем это командами:

systemctl stop httpd

systemctl disable httpd

А потом пробуем запустить службу Nginx как описано выше. Если всё хорошо, добавляем её в автозагрузку:

systemctl enable nginx

Переходим к конфигу Nginx. Откройте файл /etc/nginx/nginx.conf

Напомню, все манипуляции с фалами я делаю с помощью программ WinSCP, как это описано в этой статье. В качестве редактора рекомендую использовать программу Notepad++. Установите её на свой компьютер и укажите в настройках WinSCP путь к редактору в меню Options->Preferences->Editors. Он должен быть первым в списке для использования по умолчанию.

Реверс-прокси на службе человечества Инструкция, Linux, Https, Длиннопост, Информационная безопасность

В конфиге уже есть секция

server {

listen 80 default_server;

listen [::]:80 default_server;

server_name _;

root /usr/share/nginx/html;


# Load configuration files for the default server block.

include /etc/nginx/default.d/*.conf;


location / {

}


error_page 404 /404.html;

location = /40x.html {

}


error_page 500 502 503 504 /50x.html;

location = /50x.html {

}

}

Именно эта секция выводит страницу-заглушку. А вот ниже есть закоментированный пример секции https (порт 443) страницы-заглушки. Крайне желательно эту секцию сделать работающей. Нам понадобятся сертификаты. Установим certbot и получим сертификат командами:

yum -y install certbot python2-certbot-nginx

certbot certonly

На запрос:

Реверс-прокси на службе человечества Инструкция, Linux, Https, Длиннопост, Информационная безопасность

Вводим 1


На запрос:

Реверс-прокси на службе человечества Инструкция, Linux, Https, Длиннопост, Информационная безопасность

Вводим свой действующий e-mail. На него будут приходить в уведомления. Например, если срок сертификата истекает и его необходимо продлить.


Напомню: Let’s Encrypt выдаёт сертифакты со сроком действия три месяца.

Далее принимаем соглашение и отказываемся от рассылок, вводим, соответственно, A и N

Реверс-прокси на службе человечества Инструкция, Linux, Https, Длиннопост, Информационная безопасность
Реверс-прокси на службе человечества Инструкция, Linux, Https, Длиннопост, Информационная безопасность

Дальше нужно ввести имя Вашего домена. В моём случае это mydomain.com. И нажать Enter. Если у Вас настроена A запись, как указано в начале статьи, и прошло достаточно времени (запись должна прореплицироваться на все DNS-сервера, это можета занимать до 24-х часов, дожен пинговаться адрес домена), то будет получен сертификат и мы получим вывод в консоли:

IMPORTANT NOTES:

- Congratulations! Your certificate and chain have been saved at:

/etc/letsencrypt/live/mydomain.com/fullchain.pem

Your key file has been saved at:

/etc/letsencrypt/live/mydomain.com/privkey.pem

Your cert will expire on 2020-02-26. To obtain a new or tweaked

version of this certificate in the future, simply run certbot

again. To non-interactively renew *all* of your certificates, run

"certbot renew"

Заметьте, тут сразу есть пути к файлам сертификата и их можно очень удобно скопировать в конфиг. Возвращаемся к файлу /etc/nginx/nginx.conf, раскоментируем секцию для https и исправим пути на сертификат. Получится так:

# Settings for a TLS enabled server.


server {

listen 443 ssl http2 default_server;

listen [::]:443 ssl http2 default_server;

server_name _;

root /usr/share/nginx/html;


ssl_certificate "/etc/letsencrypt/live/mydomain.com/fullchain.pem";

ssl_certificate_key "/etc/letsencrypt/live/mydomain.com/privkey.pem";

ssl_session_cache shared:SSL:1m;

ssl_session_timeout 10m;

ssl_ciphers HIGH:!aNULL:!MD5;

ssl_prefer_server_ciphers on;


# Load configuration files for the default server block.

include /etc/nginx/default.d/*.conf;


location / {

}


error_page 404 /404.html;

location = /40x.html {

}


error_page 500 502 503 504 /50x.html;

location = /50x.html {

}

}

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

systemctl restart nginx

И проверяем, что старница-заглушка доступна в браузере по адресу https://mydomain.com (вы вводите своё имя домена).


В конфиге /etc/nginx/nginx.conf обратите внимание на строчку

include /etc/nginx/conf.d/*.conf;

Это значит, что если мы в папке /etc/nginx/conf.d/ разместим файл с расширением .conf, то он будет включен в основной конфиг и выполнен вместе с ним. Так и будем делать. Файл /etc/nginx/nginx.conf закрываем и больше не трогаем.


Теперь определим, к чему мы будем проксировать трафик. Например, я хочу чтоб при переходе по адресу test.mydomain.com, во-первых, происходила переадресация на адрес https://test.mydomain.com (мы за безопасность и шифрование), а во-вторых, открывался сайт eng.rkn.gov.ru.


Сначала создадим домен третьего уровня вида test.mydomain.com


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

Т.е. создадим на DNS-сервере А запись test (вы подставляете своё имя) с тем же IP-адресом, что и основной домен mydomain.com (вы подставляете своё имя). Дождитесь, чтобы запись прореплицировалась по DNS-серверам. Можно проверить, что домен пингуется командой на VPS:

ping test.mydomain.com -c 3

Должны корректно пройти три пинга

PING test.mydomain.com (185.nnn.nnn.nnn) 56(84) bytes of data.

64 bytes from vpsNNNN.hostsailor.com (185.nnn.nnn.nnn): icmp_seq=1 ttl=64 time=0.031 ms

64 bytes from vpsNNNN.hostsailor.com (185.nnn.nnn.nnn): icmp_seq=2 ttl=64 time=0.019 ms

64 bytes from vpsNNNN.hostsailor.com (185.nnn.nnn.nnn): icmp_seq=3 ttl=64 time=0.019 ms


--- test.secfall.com ping statistics ---

3 packets transmitted, 3 received, 0% packet loss, time 2000ms

rtt min/avg/max/mdev = 0.019/0.023/0.031/0.005 ms

В папке /etc/nginx/conf.d/ создаём файл с именем вида test.mydomain.com.conf следующего содержания:

server {

listen 80;

server_name test.mydomain.com;

location /.well-known/acme-challenge {

alias /usr/share/nginx/html/.well-known/acme-challenge;

}

location / {

return 301 https://$server_name$request_uri;

}

}

Перезапускаем службу Nginx и, с помощью команды certbot certonly, делаем сертификат для нашего домена третьего уровня test.mydomain.com (подставляете свои имена).


Если сертификат получен, дописываем (т.е. добавляем с новой строчки в конце) в файл /etc/nginx/conf.d/test.mydomain.com.conf секцию для https:

server {

listen 443 ssl;

server_name test.mydomain.com;


access_log /var/log/nginx/test.mydomain.com.access.log;

error_log /var/log/nginx/test.mydomain.com.error.log;


client_max_body_size 0;

underscores_in_headers on;


ssl_certificate /etc/letsencrypt/live/test.mydomain.com/fullchain.pem;

ssl_certificate_key /etc/letsencrypt/live/test.mydomain.com/privkey.pem;


ssl_stapling on;

ssl_stapling_verify on;

location /.well-known/acme-challenge {

alias /usr/share/nginx/html/.well-known/acme-challenge;

}


location / {

proxy_set_header Host eng.rkn.gov.ru;

add_header Front-End-Https on;

add_header Referer-Policy no-referrer;

proxy_pass http://eng.rkn.gov.ru;

}

}

Рассмотрите внимательно конфиг. В нём test.mydomain.com вы заменяете на своё имя домена, а eng.rkn.gov.ru на имя того сервера, который будете проксировать. И обратите внимание, что в данном конфиге к eng.rkn.gov.ru сервер обращается по http, а нам отдаёт по https. Такое полезно, когда web-сервер расположен где-то во внутренней инфраструктуре и нет необходимости или возможности прикрутить к нему https.


Например, есть некий сервис который вообще не умеет в https. Мы устанавливаем его на сервер, привязываем к адресу localhost и к порту, например, 8080. Теперь к сервису нельзя обратится извне, а только «изнутри» сервера по адресу http://localhost:8080. На этот же сервер ставим реверс-прокси, как написано выше, и указываем


proxy_pass http://localhost:8080;


Т.е. Nginx будет обращаться к этому же серверу на localhost к нашему сервису по порту 8080. А нам будет отдавать нормальный https. Да ещё всякой фильтрации для безопасности можно навесить, чтобы помешать злодеям ломать наш сервис. Но об этом ниже.

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

systemctl status -l nginx

смотрим, в чём ошибка. Обычно Nginx достаточно внятно пишет, что ему не нравиться, и даже укавает номер строки конфига, где есть ошибка.


Если служба запустилась без ошибок, то в браузере открываем адрес test.mydomain.com Получится как-то так:

Реверс-прокси на службе человечества Инструкция, Linux, Https, Длиннопост, Информационная безопасность

Обратите внимание, что хотя мы не писали в адресе https, сервер сам перевёл нас на зашифрованный трафик. Всё, мы сделали зеркало сайта! Дальше можно дорабатывать конфиг. Например добавить строчку


proxy_cookie_domain rkn.gov.ru $host;

proxy_pass_header Set-Cookie;

Это позволит обеспечить корректную работу куков и нормальную авторизацию на проксируемом сайте. Получится так (показан кусок конфига, только с параметрами проксирования):

location / {

proxy_cookie_domain eng.rkn.gov.ru $host;

proxy_pass_header Set-Cookie;


proxy_set_header Host eng.rkn.gov.ru;

add_header Front-End-Https on;

add_header Referer-Policy no-referrer;

proxy_pass http://eng.rkn.gov.ru;

}

Можно включить фильтрацию текста. Например заменять слово «Roskomnadzor» на «Roskompozor». Нужно дописать пару строчек (показан кусок конфига, только с параметрами проксирования):

location / {

proxy_cookie_domain rkn.gov.ru $host;

proxy_pass_header Set-Cookie;

proxy_set_header Host eng.rkn.gov.ru;

add_header Front-End-Https on;

add_header Referer-Policy no-referrer;

proxy_pass http://eng.rkn.gov.ru;

sub_filter "Roskomnadzor" "Roskompozor";

sub_filter_once off;

}

Директива

sub_filter «Roskomnadzor» «Roskompozor»;

показывает что на что менять.

Директива

sub_filter_once off;

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

Сохряняем конфиг, перезапускаем службу Nginx и с помощью комбинации Ctrl+F5 (чтобы игнорировать кэш браузера) обновляем страницу в браузере. Получится как-то так :)

Реверс-прокси на службе человечества Инструкция, Linux, Https, Длиннопост, Информационная безопасность

Теперь про фильтрацию заголовков. Это нужно делать, если проксируете трафик к какому-то своему сервису и нужно его дополнительно защитить. Я покажу часть конфига с проксированием со всеми основными примочками безопасности (кусок с ними выделен линиями). Я не буду расписывать — для чего они. Это тема отдельной статьи. Если интересно — легко сможете нагуглить.

location / {

proxy_cookie_domain rkn.gov.ru $host;

proxy_pass_header Set-Cookie;

proxy_set_header Host eng.rkn.gov.ru;

#------------------------------------------------------------------------------------------------------------------------------------------

proxy_headers_hash_max_size 512;

proxy_headers_hash_bucket_size 64;

proxy_set_header Accept-Encoding "";

proxy_set_header X-Forwarded-Proto $scheme;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

add_header X-Content-Type-Options nosniff;

add_header X-XSS-Protection "1; mode=block";

add_header Content-Security-Policy "default-src 'self';

frame-ancestors https://framer.mozilla.org;

form-action 'self';

base-uri 'self';

script-src 'self' https://mc.yandex.ru https://ssl.google-analytics.com;

img-src 'self' https://mc.yandex.ru https://ssl.google-analytics.com;

style-src 'self' 'unsafe-inline' https://mc.yandex.ru https://fonts.googleapis.com;

font-src 'self' https://mc.yandex.ru https://themes.googleusercontent.com;

frame-src https://mc.yandex.ru;

object-src 'none'

";

add_header X-Frame-Options "DENY";

proxy_cookie_path / "/; HTTPOnly; Secure";

#------------------------------------------------------------------------------------------------------------------------------------------

add_header Front-End-Https on;

add_header Referer-Policy no-referrer;

proxy_pass http://eng.rkn.gov.ru;

}

Если Вам нужно добавить ещё одно зеркало, то порядок действий такой:


1. Добавляет новую A запись с доменом третьего уровня на DNS-сервере. Ждем, пока не начнёт пинговаться с нашего VPS.

2. Создаем ещё один файл конфига в папке /etc/nginx/conf.d/ с секцией для 80 порта (для http) и перезапускаем Nginx.

3. Делаем сертификаты с помощью certbot.

Дописываем секцию для https в конфиг. Указывем пути на сертификаты. Перезапускаем Nginx.


Еще можно добавить ключ для алгоритма Диффи-Хелмана. Настроить автообновлене сертификатов. Как сделать, описано в этой статье.


P.S. Всё, что описано в статье - может сделать каждый! Это не сложно. Повышая свою грамотность в современных технологиях вы делаете мир лучше.

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