A single point of exit to the web, I2P, TOR and blocking bypass
Єдина точка виходу в web, I2P, TOR та обхід блокувань
Преамбула ... Ця стаття була написана ще влітку але, з незалежних від автора причин, трохи підзатрималася...
Одного разу, спекотного літнього вечора, після чергової введеної в консолі браузера команди виду: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.timer
Як це працює?
Для чого такі танці з бубном? Що ж, у висновку не заважає прояснити деякі моменти. Підемо прямо по пунктах попереднього розділу.
- Тут все просто. Ми зберігаємо в окремому файлі ту частину конфігурації, яка не повинна змінюватись автоматично.
- Дуже важливий параметр, що скорочує час завантаження основного сервісу з години (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 вітаються!
Comments
Post a Comment