Темата е прилично претепана, знам. На пример, постои голема Член, но таму се разгледува само IP делот од блок листата. Ќе додадеме и домени.
Поради фактот што судовите и РКН блокираат сè десно и лево, а давателите на услуги напорно се трудат да не потпаднат под казните издадени од Revizorro, придружните загуби од блокирањето се прилично големи. И меѓу „законски“ блокираните страници има многу корисни (здраво, rutracker)
Живеам надвор од надлежноста на РКН, но моите родители, роднини и пријатели останаа дома. Така, беше одлучено да се најде лесен начин за луѓето далеку од ИТ да го заобиколат блокирањето, по можност без нивно учество воопшто.
Во оваа белешка, нема да ги опишам основните мрежни работи во чекори, туку ќе ги опишам општите принципи за тоа како оваа шема може да се имплементира. Значи мора да се има знаење за тоа како функционира мрежата воопшто и особено во Linux.
Видови брави
Прво, да ја освежиме меморијата за блокирањето.
Постојат неколку типови на брави во истоварениот XML од RKN:
IP
Име на домен
URL
За едноставност, ќе ги намалиме на два: IP и домен, и едноставно ќе го повлечеме доменот од блокирање по URL (поточно, тие веќе ни го направија ова).
добри луѓе од Роскомсвобода реализира прекрасно API, преку кој можеме да го добиеме она што ни треба:
За да го направите ова, потребни ни се некои мали странски VPS, по можност со неограничен сообраќај - има многу такви за 3-5 долари. Треба да го земете во блиска странство, така што пингот не е многу голем, но повторно, земете во предвид дека Интернетот и географијата не секогаш се совпаѓаат. И бидејќи нема SLA за 5 долари, подобро е да земете 2+ парчиња од различни провајдери за толеранција на грешки.
Следно, треба да поставиме шифриран тунел од клиентскиот рутер до VPS. Јас го користам Wireguard како најбрз и најлесен за поставување. Имам и клиентски рутери базирани на Linux (APU2 или нешто во OpenWRT). Во случај на некои Mikrotik / Cisco, можете да ги користите протоколите достапни на нив како OpenVPN и GRE-over-IPSEC.
Идентификација и пренасочување на сообраќајот од интерес
Се разбира, можете да го исклучите целиот интернет сообраќај преку странски земји. Но, најверојатно, брзината на работа со локална содржина ќе страда многу од ова. Плус, барањата за пропусниот опсег на VPS ќе бидат многу повисоки.
Затоа, ќе треба некако да го распределиме сообраќајот на блокираните локации и селективно да го насочиме кон тунелот. Дури и ако дел од „дополнителниот“ сообраќај стигне таму, сепак е многу подобро отколку да возите сè низ тунелот.
За да управуваме со сообраќајот, ќе го користиме протоколот BGP и ќе објавиме маршрути до потребните мрежи од нашите VPS до клиентите. Да го земеме BIRD како еден од најфункционалните и најзгодните BGP демони.
IP
Со блокирање преку IP, сè е јасно: едноставно ги објавуваме сите блокирани IP-адреси со VPS. Проблемот е што има околу 600 илјади подмрежи во списокот што API ги враќа, а огромното мнозинство од нив се /32 хостови. Овој број на рути може да ги збуни слабите рутери на клиентите.
Затоа, при обработката на списокот, беше одлучено да се сумира до мрежата / 24 ако има 2 или повеќе хостови. Така, бројот на рути се намали на ~ 100 илјади. Ќе следи сценариото за ова.
домени
Покомплицирано е и има неколку начини. На пример, можете да инсталирате транспарентен Squid на секој клиентски рутер и таму да извршите пресретнување на HTTP и да ѕирнете во ракувањето со TLS за да ја добиете бараната URL во првиот случај и доменот од SNI во вториот.
Но, поради сите видови новоформирани TLS1.3 + eSNI, HTTPS анализата станува се помалку реална секој ден. Да, и инфраструктурата на клиентската страна станува посложена - ќе мора да користите барем OpenWRT.
Затоа, решив да тргнам по патот на пресретнување одговори на барањата за DNS. Овде, исто така, секој DNS-over-TLS / HTTPS почнува да лебди над вашата глава, но ние можеме (засега) да го контролираме овој дел на клиентот - или да го оневозможиме или да користиме сопствен сервер за DoT / DoH.
Како да пресретнете DNS?
Тука, исто така, може да има неколку пристапи.
Пресретнување на DNS сообраќај преку PCAP или NFLOG
И двата од овие методи на пресретнување се имплементирани во алатката сидмат. Но, тој не е поддржан долго време и функционалноста е многу примитивна, па сепак треба да напишете темперамент за него.
Анализа на дневници на серверот DNS
За жал, рекурзорите што ми се познати не можат да ги евидентираат одговорите, туку само барањата. Во принцип, ова е логично, бидејќи, за разлика од барањата, одговорите имаат сложена структура и тешко е да се напишат во текстуална форма.
DNSTap
За среќа, многу од нив веќе поддржуваат DNSTap за оваа намена.
Што е DNSTap?
Тоа е протокол клиент-сервер базиран на протокол бафери и стримови на рамки за пренос од DNS сервер до собирач на структурирани DNS прашања и одговори. Во суштина, DNS серверот пренесува метаподатоци за барање и одговор (тип на порака, IP на клиент/сервер, итн.) плус комплетни DNS пораки во (бинарна) форма во која работи со нив преку мрежата.
Важно е да се разбере дека во парадигмата DNSTap, серверот DNS делува како клиент, а колекторот како сервер. Тоа е, серверот DNS се поврзува со колекторот, а не обратно.
Денес DNSTap е поддржан во сите популарни DNS сервери. Но, на пример, BIND во многу дистрибуции (како Ubuntu LTS) често се гради поради некоја причина без негова поддршка. Затоа, да не се замараме со повторно склопување, туку да земеме полесен и побрз рекурсор - Неврзано.
Како да фатите DNSTap?
Постои некоиброј CLI комунални услуги за работа со проток на настани DNSTap, но тие не се погодни за решавање на нашиот проблем. Затоа, решив да измислам свој велосипед кој ќе направи се што е потребно: dnstap-bgp
Работен алгоритам:
Кога ќе се стартува, вчитува список со домени од текстуална датотека, ги превртува (habr.com -> com.habr), исклучува скршени линии, дупликати и поддомени (т.е. ако списокот содржи habr.com и www.habr.com, ќе се вчита само првиот) и гради префиксно дрво за брзо пребарување низ оваа листа
Дејствувајќи како сервер DNSTap, тој чека врска од DNS сервер. Во принцип, поддржува и UNIX и TCP приклучоци, но DNS серверите што ги знам можат да користат само UNIX приклучоци
Дојдовните DNSTap пакети најпрво се десеријализираат во структура Protobuf, а потоа самата бинарна DNS порака, сместена во едно од полињата Protobuf, се анализира на ниво на записи DNS RR
Се проверува дали бараниот хост (или неговиот родителски домен) е во вчитаната листа, ако не, одговорот се игнорира
Само A/AAAA/CNAME RR се избираат од одговорот и од нив се извлекуваат соодветните IPv4/IPv6 адреси
IP-адресите се кеширани со TTL што може да се конфигурира и се рекламираат на сите конфигурирани BGP врсници
Кога примате одговор кој укажува на веќе кеширана IP адреса, нејзиниот TTL се ажурира
Откако ќе истече TTL, записот се отстранува од кешот и од објавите BGP
Дополнителна функционалност:
Препрочитување на листата на домени од SIGHUP
Одржување на кешот во синхронизација со други примероци dnstap-bgp преку HTTP/JSON
Умножете го кешот на дискот (во базата на податоци BoltDB) за да ја вратите неговата содржина по рестартирање
Поддршка за префрлување на друг мрежен именски простор (зошто е тоа потребно ќе биде опишано подолу)
Поддршка за IPv6
Ограничувања:
IDN домените сè уште не се поддржани
Неколку поставки за BGP
Собрав RPM и DEB пакети за лесна инсталација. Треба да работи на сите релативно неодамнешни ОС со systemd. тие немаат никакви зависности.
Шемата
Значи, да почнеме да ги собираме сите компоненти заедно. Како резултат на тоа, треба да добиеме нешто како оваа мрежна топологија:
Логиката на работа, мислам, е јасна од дијаграмот:
Клиентот го има нашиот сервер конфигуриран како DNS, а барањата за DNS исто така мора да одат преку VPN. Ова е неопходно за да може провајдерот да користи DNS пресретнување за блокирање.
Кога ја отворате страницата, клиентот испраќа барање за DNS како „кои се IP-адресите на xxx.org“
Неврзани го решава xxx.org (или го зема од кешот) и испраќа одговор до клиентот „xxx.org има таква и таква IP адреса“, дуплирајќи ја паралелно преку DNSTap
dnstap-bgp ги објавува овие адреси во BIRD преку BGP ако доменот е на блокираната листа
BIRD рекламира рута до овие IP-адреси со next-hop self клиент рутер
Следните пакети од клиентот до овие IP-адреси одат низ тунелот
На серверот, за маршрути до блокирани сајтови, користам посебна табела во BIRD и таа не се вкрстува со ОС на кој било начин.
Оваа шема има недостаток: првиот SYN пакет од клиентот, најверојатно, ќе има време да замине преку домашниот провајдер. рутата не се објавува веднаш. И тука се можни опции во зависност од тоа како давателот го прави блокирањето. Ако само го испушти сообраќајот, тогаш нема проблем. А ако го пренасочи на некој DPI, тогаш (теоретски) се можни специјални ефекти.
Исто така, можно е клиентите да не ги почитуваат чудата на DNS TTL, што може да предизвика клиентот да користи некои застарени записи од својата скапана кеш меморија наместо да прашува Unbound.
Во пракса, ниту првото ниту второто не ми правеа проблеми, но вашата километража може да варира.
Подесување на серверот
За полесно тркалање, напишав улога за Ансибл. Може да ги конфигурира и серверите и клиентите базирани на Linux (дизајниран за дистрибуции базирани на deb). Сите поставки се сосема очигледни и се поставени инвентар.yml. Оваа улога е отсечена од мојата голема игротека, па може да содржи грешки - повлече барања добредојде 🙂
Ајде да поминеме низ главните компоненти.
БГП
Кога се извршуваат два BGP демони на истиот домаќин, се јавува фундаментален проблем: BIRD не сака да започне BGP peering со локалниот хост (или со кој било локален интерфејс). Од зборот воопшто. Гуглирањето и читањето мејлинг-листи не помогна, тие тврдат дека тоа е по дизајн. Можеби има некој начин, но не го најдов.
Можете да пробате друг BGP демон, но ми се допаѓа BIRD и се користи насекаде од мене, не сакам да произведувам ентитети.
Затоа, го скрив dnstap-bgp во мрежниот именски простор, кој е поврзан со коренот преку интерфејсот veth: тоа е како цевка, чии краеви се држат во различни именски простори. На секој од овие краеви, закачуваме приватни p2p IP адреси кои не одат подалеку од домаќинот, за да можат да бидат што било. Ова е истиот механизам што се користи за пристап до процесите внатре сакан од сите Докер и други контејнери.
За ова беше напишано скрипта и функционалноста веќе опишана погоре за влечење за коса во друг именски простор беше додадена во dnstap-bgp. Поради ова, мора да се изврши како root или да се издаде на бинарната CAP_SYS_ADMIN преку командата setcap.
Пример скрипта за создавање именски простор
#!/bin/bash
NS="dtap"
IP="/sbin/ip"
IPNS="$IP netns exec $NS $IP"
IF_R="veth-$NS-r"
IF_NS="veth-$NS-ns"
IP_R="192.168.149.1"
IP_NS="192.168.149.2"
/bin/systemctl stop dnstap-bgp || true
$IP netns del $NS > /dev/null 2>&1
$IP netns add $NS
$IP link add $IF_R type veth peer name $IF_NS
$IP link set $IF_NS netns $NS
$IP addr add $IP_R remote $IP_NS dev $IF_R
$IP link set $IF_R up
$IPNS addr add $IP_NS remote $IP_R dev $IF_NS
$IPNS link set $IF_NS up
/bin/systemctl start dnstap-bgp
router id 192.168.1.1;
table rkn;
# Clients
protocol bgp bgp_client1 {
table rkn;
local as 65000;
neighbor 192.168.1.2 as 65000;
direct;
bfd on;
next hop self;
graceful restart;
graceful restart time 60;
export all;
import none;
}
# DNSTap-BGP
protocol bgp bgp_dnstap {
table rkn;
local as 65000;
neighbor 192.168.149.2 as 65000;
direct;
passive on;
rr client;
import all;
export none;
}
# Static routes list
protocol static static_rkn {
table rkn;
include "rkn_routes.list";
import all;
export none;
}
rkn_routes.list
route 3.226.79.85/32 via "ens3";
route 18.236.189.0/24 via "ens3";
route 3.224.21.0/24 via "ens3";
...
DNS
Стандардно, во Ubuntu, бинарниот Unbound е прицврстен од профилот AppArmor, што му забранува да се поврзе со сите видови DNSTap приклучоци. Можете или да го избришете овој профил или да го оневозможите:
Ова веројатно треба да се додаде во книгата за игри. Идеално е, се разбира, да се поправи профилот и да се издадат потребните права, но бев премногу мрзлив.
неврзан.conf
server:
chroot: ""
port: 53
interface: 0.0.0.0
root-hints: "/var/lib/unbound/named.root"
auto-trust-anchor-file: "/var/lib/unbound/root.key"
access-control: 192.168.0.0/16 allow
remote-control:
control-enable: yes
control-use-cert: no
dnstap:
dnstap-enable: yes
dnstap-socket-path: "/tmp/dnstap.sock"
dnstap-send-identity: no
dnstap-send-version: no
dnstap-log-client-response-messages: yes
Преземање и обработка на листи
Скрипта за преземање и обработка на список со IP адреси
Ја презема листата, сумира до префиксот pfx. Во не_додавај и не_сумирај можете да им кажете на IP-адресите и мрежите да прескокнуваат или да не резимираат. ми требаше. подмрежата на мојот VPS беше во блок листата 🙂
Смешното е што RosKomSvoboda API блокира барања со стандардниот кориснички агент на Python. Изгледа дека сценариото го сфатило. Затоа, го менуваме во Огнелис.
Засега работи само со IPv4. уделот на IPv6 е мал, но ќе биде лесно да се поправи. Освен ако не мора да користите и птица6.
rkn.py
#!/usr/bin/python3
import json, urllib.request, ipaddress as ipa
url = 'https://api.reserve-rbl.ru/api/v2/ips/json'
pfx = '24'
dont_summarize = {
# ipa.IPv4Network('1.1.1.0/24'),
}
dont_add = {
# ipa.IPv4Address('1.1.1.1'),
}
req = urllib.request.Request(
url,
data=None,
headers={
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Safari/537.36'
}
)
f = urllib.request.urlopen(req)
ips = json.loads(f.read().decode('utf-8'))
prefix32 = ipa.IPv4Address('255.255.255.255')
r = {}
for i in ips:
ip = ipa.ip_network(i)
if not isinstance(ip, ipa.IPv4Network):
continue
addr = ip.network_address
if addr in dont_add:
continue
m = ip.netmask
if m != prefix32:
r[m] = [addr, 1]
continue
sn = ipa.IPv4Network(str(addr) + '/' + pfx, strict=False)
if sn in dont_summarize:
tgt = addr
else:
tgt = sn
if not sn in r:
r[tgt] = [addr, 1]
else:
r[tgt][1] += 1
o = []
for n, v in r.items():
if v[1] == 1:
o.append(str(v[0]) + '/32')
else:
o.append(n)
for k in o:
print(k)
Скрипта за ажурирање
Го пуштам на круната еднаш дневно, можеби вреди да се влече на секои 4 часа. ова, според мое мислење, е периодот на обновување што RKN го бара од давателите на услуги. Плус, тие имаат некое друго суперитно блокирање, кое може да стигне побрзо.
Го прави следново:
Ја извршува првата скрипта и ја ажурира листата на правци (rkn_routes.list) за ПТИЦА
Вчитај повторно BIRD
Ја ажурира и чисти листата на домени за dnstap-bgp
Вчитај повторно dnstap-bgp
rkn_update.sh
#!/bin/bash
ROUTES="/etc/bird/rkn_routes.list"
DOMAINS="/var/cache/rkn_domains.txt"
# Get & summarize routes
/opt/rkn.py | sed 's/(.*)/route 1 via "ens3";/' > $ROUTES.new
if [ $? -ne 0 ]; then
rm -f $ROUTES.new
echo "Unable to download RKN routes"
exit 1
fi
if [ -e $ROUTES ]; then
mv $ROUTES $ROUTES.old
fi
mv $ROUTES.new $ROUTES
/bin/systemctl try-reload-or-restart bird
# Get domains
curl -s https://api.reserve-rbl.ru/api/v2/domains/json -o - | jq -r '.[]' | sed 's/^*.//' | sort | uniq > $DOMAINS.new
if [ $? -ne 0 ]; then
rm -f $DOMAINS.new
echo "Unable to download RKN domains"
exit 1
fi
if [ -e $DOMAINS ]; then
mv $DOMAINS $DOMAINS.old
fi
mv $DOMAINS.new $DOMAINS
/bin/systemctl try-reload-or-restart dnstap-bgp
Тие се напишани без многу размислување, па ако видите нешто што може да се подобри - повелете.
Поставување на клиентот
Еве ќе дадам примери за Linux рутери, но во случајот со Mikrotik / Cisco би требало да биде уште полесно.
Прво, поставивме BIRD:
птица.conf
router id 192.168.1.2;
table rkn;
protocol device {
scan time 10;
};
# Servers
protocol bgp bgp_server1 {
table rkn;
local as 65000;
neighbor 192.168.1.1 as 65000;
direct;
bfd on;
next hop self;
graceful restart;
graceful restart time 60;
rr client;
export none;
import all;
}
protocol kernel {
table rkn;
kernel table 222;
scan time 10;
export all;
import none;
}
Така, ќе ги синхронизираме маршрутите добиени од BGP со рутирачката табела на кернелот број 222.
После тоа, доволно е да побарате од јадрото да ја погледне оваа плоча пред да ја погледне стандардната:
# ip rule add from all pref 256 lookup 222
# ip rule
0: from all lookup local
256: from all lookup 222
32766: from all lookup main
32767: from all lookup default
Сè, останува да се конфигурира DHCP на рутерот за да се дистрибуира IP адресата на тунелот на серверот како DNS, а шемата е подготвена.
Ограничувања
Со сегашниот алгоритам за генерирање и обработка на листата на домени, меѓу другото вклучува и youtube.com и неговите ЦДН.
И ова води до фактот дека сите видеа ќе поминат преку VPN, што може да го заглави целиот канал. Можеби вреди да се состави список на популарни домени-исклучувања кои засега го блокираат RKN, храброста е тенка. И прескокнете ги при парсирање.
Заклучок
Опишаниот метод ви овозможува да го заобиколите речиси секое блокирање што моментално го спроведуваат провајдерите.
Во принцип, dnstap-bgp може да се користи за која било друга цел каде што е потребно одредено ниво на контрола на сообраќајот врз основа на името на доменот. Само имајте на ум дека во наше време, илјада страници можат да висат на иста IP адреса (зад некои Cloudflare, на пример), така што овој метод има прилично мала точност.
Но, за потребите на заобиколување на бравите, ова е сосема доволно.
Дополнувања, уредувања, барања за повлекување - добредојде!