
Преамбула… Даная статья была написана ещё летом но, по независящим от автора причинам, немножко подзадержалась…
Однажды, жарким летним вечером, после очередной введённой в консоли браузера команды вида :set content.proxy socks://localhost:9050, автор сего опуса понял, что дальше так жить нельзя и пора приводить выход во всякие скрытосети, а заодно и обход блокировок имени известной организации к какому-то единому, для любого софта вообще и браузера в частности, «общему знаменателю». А как приводить? Разумеется так, чтобы прокси сервер сам «понимал», через какой вышестоящий прокси отправлять и принимать трафик в зависимости от введённого адреса. Вторая цель, вытекающая из первой, вышестоящие прокси могут работать либо как http, либо как socks и оба протокола должны поддерживаться входным прокси. Ну и сам софт должен быть более менее актуальным, что б в случае ошибок или «хотения фич», не приходилось грустно смотреть на одинокую репу на гитхабе, а то и вообще на каком-нибудь сорсфорже.
Итак цели поставлены!
Муки выбора
На самом деле особых мук не было. Ибо, по большому счёту, из имеющихся известных прокси серверов поставленным требованиям удовлетворяли два. Это privoxy и tinyproxy. Но tinyproxy оказался более живым, более легковесным и более простым, поэтому и был выбран и немедленно установлен (в качестве примера используется текущая версия Manjaro Linux).
sudo pacman -Syu tinyproxy
Само собой, до этого, уже были установлены настроены пакеты tor и i2pd. (sudo pacman -Syu tor i2pd).
Базовая настройка tinyproxy
Итак, настроим базовые перенаправления, чтобы в обычный web ходило напрямую, а в *.i2p и *.onion через соответствующие вышестоящие (parent) proxy.
/etc/tinyproxy/tinyproxy.conf:
User tinyproxy Group tinyproxy PidFile "/var/run/tinyproxy/tinyproxy.pid" Port 8888 Listen 127.0.0.1 Timeout 600 DefaultErrorFile "/usr/share/tinyproxy/default.html" StatFile "/usr/share/tinyproxy/stats.html" Syslog On # Set the logging level. Allowed settings are: # Critical, Error, Warning, Notice, Connect, Info LogLevel Info MaxClients 100 MinSpareServers 5 MaxSpareServers 20 StartServers 10 MaxRequestsPerChild 0 Allow 127.0.0.1 ViaProxyName "tinyproxy" ## Parent proxy for TOR hosts upstream socks5 127.0.0.1:9050 ".onion" ## Parent proxy for I2P hosts upstream socks5 127.0.0.1:4447 ".i2p" ##### End of static configuration #####
Для начала практически все параметры в конфиге остаются по умолчанию.
- Сохраняем
- Запускаем:
sudo systemctl enable --now tinyproxy - Проверяем:
journalctl -f -u tinyproxy, параллельно пытаемся зайти на i2p и onion ресурсы (настроив браузер на использование http proxyhttp://localhost:8888) и видим в лог файле сообщения о перенаправлениях на parent proxy’s:
июл 20 01:36:16 dell-lnx tinyproxy[198356]: Request (file descriptor 6): GET http://flibusta.i2p/ HTTP/1.1 июл 20 01:36:17 dell-lnx tinyproxy[198356]: Found upstream proxy socks5 127.0.0.1:4447 for flibusta.i2p июл 20 01:36:17 dell-lnx tinyproxy[198356]: opensock: opening connection to 127.0.0.1:4447 июл 20 01:36:17 dell-lnx tinyproxy[198356]: opensock: getaddrinfo returned for 127.0.0.1:4447 июл 20 01:36:17 dell-lnx tinyproxy[198356]: Established connection to socks5 proxy "127.0.0.1" using file descriptor 7. июл 20 01:36:40 dell-lnx tinyproxy[198356]: Closed connection between local client (fd:6) and remote client (fd:7) ... июл 20 01:39:36 dell-lnx tinyproxy[214495]: Found upstream proxy socks5 127.0.0.1:9050 for ilitafrzzgxymv6umx2ux7kbz3imyeko6cnqkvy4nisjjj4qpqkrptid.onion июл 20 01:39:36 dell-lnx tinyproxy[214495]: opensock: opening connection to 127.0.0.1:9050 июл 20 01:39:36 dell-lnx tinyproxy[214495]: opensock: getaddrinfo returned for 127.0.0.1:9050 июл 20 01:39:36 dell-lnx tinyproxy[214495]: Established connection to socks5 proxy "127.0.0.1" using file descriptor 7.
Список «zapret.info»
Ну что ж, связка прокси базово работает, теперь начинается самое интересное — обход блокировок роскомнадзора. К сожалению, tinyproxy не поддерживает внешние файлы со списком parent proxy, но это не должно быть препятствием. Ведь мы можем сгенерировать монолитный конфиг «on the fly».
-
Копируем имеющийся конфиг tinyproxy под новым именем:
cp /etc/tinyproxy/tinyproxy.conf /etc/tinyproxy/tinyproxy.conf.static -
Слегка правим новый
/etc/tinyproxy/tinyproxy.conf.static:LogLevel Info→LogLevel Error -
Создаём юнит который будет клонировать репозиторий проекта zapret.info —
sudo systemctl edit --full --force z-i-prepare.service:# /etc/systemd/system/z-i-prepare.service [Unit] Description=Zapret Info repository cloner ConditionPathExists=|!/usr/local/lib/z-i/ ConditionFileNotEmpty=|!/usr/local/lib/z-i/dump.csv Wants=local-fs.target After=local-fs.target Wants=network.target After=network.target # [Service] Type=oneshot User=tinyproxy Group=tinyproxy ExecStartPre=+/usr/bin/mkdir -p /usr/local/lib/z-i ExecStartPre=+/usr/bin/chown tinyproxy:tinyproxy /usr/local/lib/z-i ExecStartPre=+/usr/bin/chmod 0750 /usr/local/lib/z-i ExecStart=git clone --depth 1 https://github.com/zapret-info/z-i.git /usr/local/lib/z-i -
Создаём юнит который будет генерировать конфиг tinyproxy, в рантайме —
sudo systemctl edit --full --force tinyproxy-cfg-generator.service:# /etc/systemd/system/tinyproxy-cfg-generator.service [Unit] After=z-i-prepare.service Wants=z-i-prepare.service # [Service] Type=oneshot User=tinyproxy Group=tinyproxy Environment="PATH=/usr/local/bin:/usr/sbin:/usr/bin" ExecStart=tinyproxy-cfg-gen.sh StandardOutput=file:/run/tinyproxy/tinyproxy.conf… и собственно скрипт
/usr/local/bin/tinyproxy-cfg-gen.shк нему:#!/usr/bin/env sh # tinyproxy-cfg-gen.sh -- tinyproxy dynamic config generator to stdout. awk -F';' '{print "upstream socks5 127.0.0.1:9050 \"" $2"\""}' /usr/local/lib/z-i/dump.csv|tr -d '*'|sort|uniq|grep -v '\s\"\"'>/tmp/tinyproxy.conf.dynamic cat /etc/tinyproxy/tinyproxy.conf.static /tmp/tinyproxy.conf.dynamic -
Таймер и сервис, который раз в сутки будет выкачивать обновления списка и рестартовать основной сервис:
sudo systemctl edit --full --force z-i-update-daily.timer:# /etc/systemd/system/z-i-update-daily.timer [Unit] Description=Zapret Info daily update After=network.target Wants=network.target # [Timer] OnCalendar=daily AccuracySec=1h Persistent=true # [Install] WantedBy=timers.targetИ сервис к нему
sudo systemctl edit --full --force z-i-update-daily.service:# /etc/systemd/system/z-i-update-daily.service [Unit] Description=Zapret Info daily update service After=network.target Wants=network.target # [Service] Type=oneshot User=tinyproxy Group=tinyproxy ExecStartPre=/usr/bin/git -C /usr/local/lib/z-i pull ExecStart=+/usr/bin/systemctl try-restart tinyproxy.service -
Наконец вишенка на торте, редактируем tinyproxy.service под наши нужды —
sudo systemctl edit tinyproxy.service:# /etc/systemd/system/tinyproxy.service.d/override.conf [Unit] Wants=network.target Wants=z-i-prepare.service After=z-i-prepare.service Wants=tinyproxy-cfg-generator.service After=tinyproxy-cfg-generator.service # [Service] User=tinyproxy Group=tinyproxy ExecStart= ExecStart=/usr/bin/tinyproxy -c /run/tinyproxy/tinyproxy.conf ExecStopPost=+/usr/bin/rm -rf /run/tinyproxy/tinyproxy.conf -
А теперь, со всем этим безобразием мы попытаемся взлететь ©
sudo systemctl enable --now tinyproxy sudo systemctl enable --now z-i-update-daily.timerHow it works?
Вдумчивый читатель безусловно поинтересуется, Для чего такие танцы с бубном? Что ж, в заключении не мешает прояснить некоторые моменты. Пойдём прямо по пунктам предыдущего раздела.
- Тут всё просто. Мы сохраняем в отдельный файл ту часть конфигурации, которая не должна меняться автоматически.
- Очень важный параметр, сокращающий время загрузки основного сервиса с часа(SIC!) до, примерно, полутора минут (нетбучный AMD проц года 2009-го и HDD на 5400 об./мин.). Разумеется это не единственный способ повышения производительности.
- «bootstrap» юнит, который запускается всегда, но отрабатывает только в том случае если отсутствует директория
/usr/local/lib/z-i/либо пуст файл/usr/local/lib/z-i/dump.csv(ДирективыCondition*). Ключик--depth 1позволяет склонировать только последний коммит, а не все 8 Гб. - Основная генерация конфига и ещё один лайвхак для повышения производительности. Из csv
awk-ом вырезается поле с доменом, очищается от лишних символов. Удаляются строки с пустым доменом, далееcatотправляет результат наstdout. а уже юнит, благодаря директивеStandardOutput=записывает весь вывод в конфиг файл в/runнаtmpfs! По зависимостям запускается после того как отработает «bootstrap» юнит из предыдущего пункта. - Раз в сутки, начиная с нуля часов, с джиттером в час, обновляем репозиторий и перегенерим конфиг, с рестартом сервиса. Точнее рестартуем сервис с перегенерацией конфига.
- (и 7.) Ну тут всё понятно, запуск вспомогательных юнитов и основного.
Данная связка работает уже неделю 2,5 месяца. Глюкобагов, пока, вроде бы не замечено. готовые конфиги и скрипты живут на гитхабе, PR приветствуются!
ссылка на оригинал статьи https://habr.com/ru/articles/582906/
Добавить комментарий