Проксирование c помощью nginx

или как создать зеркало интернет-сайта в сети Yggdrasil

Здесь будет описан способ создания зеркала сайта в сети Yggdrasil с использованием возможности web-сервера nginx работать в качестве прокси-сервера.

Всё описанное доступно для реализации как под управлением ОС Linux, так и Windows.
Мы рассмотрим конфигурирование nginx, установленного в OC linux (на базе Debian).

Для создания корректно функционирующего зеркала сайта необходимы базовые знания языка гипертекстовой разметки (HTML), а так же, Java Script, CSS, и понимание принципов взаимодействия браузера и web-сервера.

Если ранее вы не занимались конфигурированием web-сервера nginx, настоятельно рекомендую ознакомиться со структурой конфигурационного файла, базовыми настройками, встроенными переменными и с примерами простейших конфигураций.
Документация nginx доступна на официальном сайте проекта:
https://nginx.org/ru/docs/
Руководство для начинающих:
https://nginx.org/ru/docs/beginners_guide.html

В процессе исследования проксируемого сайта, скорее всего, вам понадобятся инструменты отладки, встроенные в популярные браузеры. С ними так же желательно предварительно ознакомиться.
Краткое описание инструментов разработчика в браузере Firefox: https://developer.mozilla.org/ru/docs/Tools

Если nginx еще не установлен, необходимо его установить:

sudo apt-get install nginx

Базовой установки (с поставляемыми по-умолчанию модулями) в большинстве случаев будет достаточно.

Конфигурационные файлы nginx находятся в директории /etc/nginx/.
Общие настройки сервера (nginx.conf) мы рассматривать не будем, перейдем непосредственно к конфигурированию проксирования конкретного сайта. Тем, кто впервые установил nginx рекомендую, как минимум, просмотреть файл /etc/nginx/nginx.conf и, желательно, прочитать о директивах, которые там содержатся.

В качестве примера возьмем новостной сайт https://www.interfax.ru/

Небольшое отступление
Конфигурационные файлы конкретных сайтов обычно размещаются в директории /etc/nginx/sites-available/.
А в директории /etc/nginx/sites-enabled/, как правило, помещают символические ссылки на конфигурации из /etc/nginx/sites-available/.
Всё, что находится в /etc/nginx/sites-enabled/ nginx считывает при запуске.
Таким образом можно легко включать и отключать какой-то сайт на сервере.
Например, если в /etc/nginx/sites-available/ есть файл homesite.conf, можно создать на него ссылку в /etc/nginx/sites-enabled/

$ sudo ln -s /etc/nginx/sites-available/homesite.conf /etc/nginx/sites-enabled/homesite.conf

Перезапустив nginx, мы сможем зайти на сайт, настроенный в этом конфигурационном файле.

$ sudo systemctl restart nginx

Если мы захотим сделать сайт недоступным, мы просто удаляем ссылку из /etc/nginx/sites-enabled/ и перезапускаем nginx.

$ sudo rm -f /etc/nginx/sites-enabled/homesite.conf && sudo systemctl restart nginx

Cайт более не работает, а его конфигурация осталась в /etc/nginx/sites-available/.

Для экспериментов временно добавим IP-адрес на интерфейс tun0.

sudo ip address add 300:529f:150c:eafe::7/64 dev tun0:1

Подробнее о том, как добавить несколько адресов на один интерфейс можно прочесть статье Короткий адрес из подсети 300::/64.

Создадим файл /etc/nginx/sites-available/interfax.ru.conf
И внесем в него такое содержимое:

/etc/nginx/sites-available/interfax.ru.conf
server {
    #установка заголовков, которые позволят понять серверу, что запросы пришли через прокси-сервер
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Real-IP $remote_addr;
 
    listen [300:529f:150c:eafe::7]:80;
	location / {
		proxy_pass https://www.interfax.ru/;
	}
}

Таким образом мы сообщаем серверу, на каком интерфейсе (адресе) и порту должен работать сайт, и что при обращении к корневой директории необходимо сделать запрос на https://www.interfax.ru/ и выдать нам результат.

Создаем ссылку в /etc/nginx/sites-enabled/ и перезапускаем nginx.

sudo ln -s /etc/nginx/sites-available/interfax.ru.conf /etc/nginx/sites-enabled/interfax.ru.conf && sudo systemctl restart nginx

Если сейчас мы откроем браузер и перейдем по адресу http://[300:529f:150c:eafe::7]/, мы уже увидим страницу с новостями.
Но это еще не всё. Откроем панель инструментов разработчика, перейдем на закладку Сеть и обновим страничку.
Видно, что часть скриптов запрашивается браузером с других адресов (static.smi2.net др.)…
Пользователи, не имеющие доступа в интернет (подключенные к Yggdrasil посредством технологии mesh-сетей), не смогут загрузить эти скрипты.
Исправим это, а заодно заблокируем лишнее (баннеры, счетчики и т.п.).

/etc/nginx/sites-available/interfax.ru.conf
server {
    listen [300:529f:150c:eafe::7]:80;
 
    #установка заголовков, которые позволят понять серверу, что запросы пришли через прокси-сервер
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Real-IP $remote_addr;
 
    sub_filter_once off; #нужно заменять все совпадения, не только первое
    sub_filter_last_modified on; #сохранение поля Last-Modified в исходном ответе
 
    location / {
 
        proxy_set_header Accept-Encoding ""; # сообщаем серверу, что данные не нужно сжимать, иначе не будут работать фильтры sub_filter
 
        sub_filter "https://static.smi2.net/" "$scheme://$host/staticsmi2net/";
        sub_filter "//smi2.ru/" "//$host/smi2ru/";
        sub_filter "https://www.interfax.ru/" "$scheme://$host/";
        sub_filter "https://fonts.googleapis.com/" "$scheme://$host/ftsgapis/";
        sub_filter "https://cdn.onthe.io/" "$scheme://$host/cdnontheio/";
 
        #обрезаем лишнее
        sub_filter "https://yastatic.net" "$scheme://$host/_empty";
        sub_filter "//www.googletagmanager.com/" "//$host/_empty";
        sub_filter "/js/prebid.min.js" "/_empty";
        sub_filter "https://static.videonow.ru/" "$scheme://$host/_empty";
        sub_filter "https://stats2.videonow.ru/" "$scheme://$host/_empty";
        sub_filter "https://cdn.videonow.ru/" "$scheme://$host/_empty";
        sub_filter "http://imasdk.googleapis.com/" "$scheme://$host/_empty";
        sub_filter "https://s0.2mdn.net/" "$scheme://$host/_empty";
 
        sub_filter "<!-- tns-counter.ru -->" "<!-- tns-counter.ru";
        sub_filter "<!--/ tns-counter.ru -->" "/ tns-counter.ru -->";
        sub_filter "<!-- Yandex.Metrika counter -->" "<!-- Yandex.Metrika counter";
        sub_filter "<!-- /Yandex.Metrika counter -->" "/Yandex.Metrika counter -->";
        sub_filter "<!-- Global site tag (gtag.js) - Google Analytics -->" "<!-- Global site tag (gtag.js) - Google Analytics";
        sub_filter "<!-- /Global site tag (gtag.js) - Google Analytics -->" " /Global site tag (gtag.js) - Google Analytics -->";
        sub_filter "<!--noindex-->" "<!--noindex";
        sub_filter "<!--/noindex-->" "/noindex-->";
 
        sub_filter "containerId: '" "containerId: '-";
        sub_filter "/css/ads.css" "/_empty";
        sub_filter "cntimg.src = \"/cnt/\" + cntParseReferer()" "cntimg.src = \"/_empty\"";
 
        #скроем ненужные элементы
        sub_filter "class=\"toplinks\"" "style=\"visibility: hidden;\"";
        sub_filter "class=\"header__soc\"" "style=\"visibility: hidden;\"";
        sub_filter "class=\"but__enter\"" "style=\"visibility: hidden;\"";
        sub_filter "<footer " "<footer style=\"visibility: hidden;\"";
        sub_filter "class=\"bss__wrap\"" "style=\"visibility: hidden;\"";
        sub_filter "class=\"faqSend faqSendOpen\"" "style=\"visibility: hidden;\"";
 
        proxy_pass https://www.interfax.ru/; # проксируем
    }
 
    location ~* /cdnontheio {
        rewrite ^/cdnontheio/(.*) /$1 break; # заменяем строку cdnontheio в адресе на параметры в исходном запросе и...
        proxy_pass https://cdn.onthe.io; # делаем запрос к нужному серверу
    }
 
    location ~* /taticsmi2net { # ~* - без учета регистра (~ - с учетом)
        rewrite ^/staticsmi2net/(.*) /$1 break;
        proxy_pass https://static.smi2.net;
    }
 
    location ~* /smi2ru {
        rewrite ^/smi2ru/(.*) /$1 break;
        proxy_pass http://smi2.ru;
    }
 
    location ~* /ftsgapis {
        rewrite ^/ftsgapis/(.*) /$1 break;
        proxy_pass https://fonts.googleapis.com;
    }
 
    location /_empty { # здесь просто выдается пустой ответ
        expires max;
        add_header Content-Type text/plain;
        add_header Content-Length 0;
        return 204;
    }
}

Обновим страницу. Теперь всё выглядит лучше. Запросы напрямую в интернет браузером не отправляются. Перейдем по ссылкам на подробности новостей, убедимся, что там тоже всё хорошо.

Примечание
На популярных и активно поддерживаемых сайтах довольно часто происходят изменения, затрагивающие структуру HTML, CSS, JavaScript и пр. - например, когда администраторы или разработчики решат сменить тему оформления сайта или добавить новые рекламные баннеры. Поэтому на момент прочтения вами этой статьи, если вы будете использовать приведенные конфигурационные файлы, скорее всего, вам потребуется внести какие-то изменения, чтобы достич желаемого результата. По этой же причине администраторам проксируемых таким образом сайтов (зеркал) периодически придется отслеживать изменения на сайтах и вносить корректировки в конфигурационные файлы.

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

Например, ссылка //smi2.ru/data/js/93374.js после обработки директивой

sub_filter "//smi2.ru/" "//$host/smi2ru/";

будет выглядеть так: //[300:529f:150c:eafe::7]/smi2ru/data/js/93374.js

Таким образом, запрос будет сделан к нашему ресурсу.
Но как обработать такой запрос?
Вот так обрабатываем эту локацию:

location ~* /smi2ru {
    rewrite ^/smi2ru/(.*) /$1 break; # заменяем /smi2ru/ на исходный запрос (/data/js/93374.js)
    proxy_pass http://smi2.ru; # и отправляем этот запрос на нужный сервер
 
    #если в ответе этого сервера тоже потребуется что-то изменить, добавим сюда proxy_set_header Accept-Encoding "" и sub_filter...
}

Директива rewrite позволяет изменять URI запроса с помощью регулярных выражений.

Совет
Для исследования каких-то конкретных элементов на странице удобно использовать щелчок ПКМ по нему и выбор из контекстного меню пункта «Исследовать элемент» - попадём в ту же панель инструментов разработчика, но на другую закладку, где курсор спозиционируется на код выбранного элемента..

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

Стоит заменить, что это не предел. Этот конфигурационный файл можно оптимизировать, отключив логи там, где это не нужно, добавив кэширование, можно ограничить количество соединений и кое-что другое…

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

Ссылки

Только авторизованные участники могут оставлять комментарии.
yggdrasil/nginx_proxying.txt · Последние изменения: 2022/02/04 12:34 — Thunar
 
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki