DNSTap және BGP көмегімен ILV блоктауын айналып өтіңіз

DNSTap және BGP көмегімен ILV блоктауын айналып өтіңіз

Тақырып өте күрделі, мен білемін. Мысалы, керемет бар мақала, бірақ ол жерде блоктау тізімінің IP бөлігі ғана қарастырылады. Біз сондай-ақ домендерді қосамыз.

Соттар мен РКН бәрін оңды-солды бұғаттайтындықтан, ал провайдерлер Revizorro шығарған айыппұлдарға түспеуге тырысады, бұғаттаудан болатын шығындар айтарлықтай үлкен. Ал «заңды» бұғатталған сайттардың арасында пайдалылары көп (сәлем, рутреккер)

Мен ҚРҚК құзырынан тыс жерде тұрамын, бірақ үйде ата-анам, туыстарым және достарым қалды. Сондықтан IT-тен алыс адамдар үшін бұғаттауды айналып өтудің оңай әдісін ойлап табу туралы шешім қабылданды, жақсырақ олардың қатысуынсыз.

Бұл жазбада мен негізгі желілік нәрселерді қадамдармен сипаттамаймын, бірақ бұл схеманы қалай жүзеге асыруға болатынының жалпы принциптерін сипаттаймын. Сондықтан желінің жалпы және атап айтқанда Linux жүйесінде қалай жұмыс істейтінін білу міндетті болып табылады.

Құлыптардың түрлері

Алдымен, блокталған нәрсе туралы жадымызды жаңартайық.

РКН-дан түсірілген XML-де құлыптардың бірнеше түрі бар:

  • IP
  • Домен атауы
  • URL

Қарапайымдылық үшін біз оларды екіге азайтамыз: IP және домен, және біз жай ғана URL мекенжайы бойынша доменді блоктаудан шығарамыз (дәлірек айтқанда, олар мұны біз үшін жасады).

жақсы адамдардан Роскомсвобода тамаша түсінді API, ол арқылы біз қажет нәрсені ала аламыз:

Блокталған сайттарға кіру

Мұны істеу үшін бізге шағын шетелдік VPS қажет, жақсырақ трафикті шектеусіз - 3-5 долларға олардың көпшілігі бар. Пинг өте үлкен болмауы үшін оны жақын шетелде қабылдау керек, бірақ Интернет пен география әрдайым сәйкес келмейтінін ескеріңіз. 5 долларға SLA жоқ болғандықтан, ақауларға төзімділік үшін әртүрлі провайдерлерден 2+ дана алған дұрыс.

Әрі қарай, клиенттік маршрутизатордан VPS-ке шифрланған туннель орнатуымыз керек. Мен Wireguard құралын орнату үшін ең жылдам және оңай пайдаланамын. Менде Linux негізіндегі клиенттік маршрутизаторлар да бар (APU2 немесе OpenWRT ішіндегі бір нәрсе). Кейбір Mikrotik / Cisco жағдайында сіз OpenVPN және GRE-over-IPSEC сияқты оларда қол жетімді протоколдарды пайдалана аласыз.

Қызықтыратын трафикті анықтау және қайта бағыттау

Сіз, әрине, шет елдер арқылы барлық интернет-трафикті өшіре аласыз. Бірақ, сірә, жергілікті мазмұнмен жұмыс істеу жылдамдығы осыдан қатты зардап шегеді. Сонымен қатар, VPS өткізу қабілетіне қойылатын талаптар әлдеқайда жоғары болады.

Сондықтан біз қандай да бір жолмен блокталған сайттарға трафикті бөліп, оны туннельге таңдап бағыттауымыз керек. Тіпті «қосымша» трафиктің бір бөлігі сол жерге жетсе де, бәрібір туннель арқылы өтуден әлдеқайда жақсы.

Трафикті басқару үшін біз BGP протоколын қолданамыз және VPS-тен клиенттерге қажетті желілерге маршруттарды жариялаймыз. BIRD-ді ең функционалды және ыңғайлы BGP демондарының бірі ретінде алайық.

IP

IP арқылы бұғаттау арқылы бәрі түсінікті: біз VPS арқылы барлық блокталған IP-терді жай ғана жариялаймыз. Мәселе мынада, API қайтаратын тізімде шамамен 600 мың ішкі желі бар және олардың басым көпшілігі /32 хост болып табылады. Бұл бағыттар саны әлсіз клиенттік маршрутизаторларды шатастыруы мүмкін.

Сондықтан, тізімді өңдеу кезінде, егер оның 24 немесе одан да көп хосттары болса, желіге / 2-ке дейін қорытындылау туралы шешім қабылданды. Осылайша, маршруттар саны ~100 мыңға дейін қысқарды. Бұл үшін сценарий орындалады.

Домендер

Бұл күрделірек және бірнеше жолы бар. Мысалы, әрбір клиенттік маршрутизаторға мөлдір Squid орнатып, сол жерде HTTP ұстап алуды орындауға және бірінші жағдайда сұралған URL мекенжайын, екіншісінде SNI доменін алу үшін TLS қол алысуын қарауға болады.

Бірақ жаңа TLS1.3 + eSNI барлық түрлеріне байланысты HTTPS талдауы күн сайын азайып барады. Иә, және клиенттік жағындағы инфрақұрылым күрделене түсуде - сіз кем дегенде OpenWRT пайдалануыңыз керек.

Сондықтан мен DNS сұрауларына жауаптарды ұстау жолын таңдауды шештім. Мұнда да кез келген DNS-over-TLS/HTTPS сіздің басыңызда жүре бастайды, бірақ біз (әзірше) клиенттің бұл бөлігін басқара аламыз - оны өшіріңіз немесе DoT/DoH үшін өз серверіңізді пайдаланыңыз.

DNS-ті қалай ұстауға болады?

Мұнда да бірнеше тәсілдер болуы мүмкін.

  • PCAP немесе NFLOG арқылы DNS трафигін ұстау
    Ұстаудың осы екі әдісі де утилитада жүзеге асырылады сидмат. Бірақ оған ұзақ уақыт бойы қолдау көрсетілмеді және функционалдылық өте қарабайыр, сондықтан сіз әлі де ол үшін белдік жазуыңыз керек.
  • DNS серверінің журналдарын талдау
    Өкінішке орай, маған белгілі рекурсорлар жауаптарды тіркеуге қабілетті емес, тек сұраулар. Негізінде, бұл қисынды, өйткені сұраулардан айырмашылығы, жауаптар күрделі құрылымға ие және оларды мәтін түрінде жазу қиын.
  • DNSTap
    Бақытымызға орай, олардың көпшілігі осы мақсат үшін DNSTap-ті қолдайды.

DNSTap дегеніміз не?

DNSTap және BGP көмегімен ILV блоктауын айналып өтіңіз

Бұл DNS серверінен құрылымдық DNS сұраулары мен жауаптарының коллекторына тасымалдауға арналған протокол буферлері мен кадр ағындарына негізделген клиент-сервер протоколы. Негізінде, DNS сервері сұрау және жауап метадеректерін (хабарлама түрі, клиент/сервер IP, т.б.) және толық DNS хабарламаларын желі арқылы олармен жұмыс істейтін (екілік) пішінде жібереді.

DNSTap парадигмасында DNS сервері клиент, ал коллектор сервер ретінде әрекет ететінін түсіну маңызды. Яғни, DNS сервері коллекторға қосылады, керісінше емес.

Бүгінгі күні DNSTap барлық танымал DNS серверлерінде қолдау көрсетеді. Бірақ, мысалы, көптеген дистрибутивтердегі BIND (мысалы, Ubuntu LTS) қандай да бір себептермен оның қолдауынсыз жасалады. Ендеше, қайта жинаумен алаңдамай, жеңілірек және жылдамырақ рекурсорды алайық - Unbound.

DNSTap файлын қалай ұстауға болады?

бар кейбір количество DNSTap оқиғаларының ағынымен жұмыс істеуге арналған CLI утилиталары, бірақ олар біздің мәселемізді шешуге жарамайды. Сондықтан мен өзімнің велосипедімді ойлап табуды шештім, ол барлық қажетті нәрсені жасай алады: dnstap-bgp

Жұмыс алгоритмі:

  • Іске қосылған кезде ол мәтіндік файлдан домендер тізімін жүктейді, оларды кері түрлендіреді (habr.com -> com.habr), үзілген жолдарды, көшірмелерді және ішкі домендерді қоспайды (яғни тізімде habr.com және www.habr.com болса, ол біріншісі ғана жүктеледі) және осы тізім арқылы жылдам іздеу үшін префикс ағашын құрады
  • DNSTap сервері ретінде әрекет ете отырып, ол DNS серверінен қосылымды күтеді. Негізінде ол UNIX және TCP ұяшықтарын қолдайды, бірақ мен білетін DNS серверлері тек UNIX ұяшықтарын пайдалана алады.
  • Кіріс DNSTap пакеттері алдымен Protobuf құрылымына сериясыздандырылады, содан кейін Protobuf өрістерінің бірінде орналасқан екілік DNS хабарламасының өзі 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 жұмыс істеу керек. олардың ешқандай тәуелділігі жоқ.

Схема

Сонымен, барлық компоненттерді біріктіруді бастайық. Нәтижесінде біз осы желі топологиясына ұқсас нәрсені алуымыз керек:
DNSTap және BGP көмегімен ILV блоктауын айналып өтіңіз

Жұмыстың логикасы, менің ойымша, диаграммадан анық:

  • Клиентте DNS ретінде конфигурацияланған серверіміз бар және DNS сұраулары да VPN арқылы өтуі керек. Бұл провайдер блоктау үшін DNS кедергісін пайдалана алмау үшін қажет.
  • Сайтты ашқан кезде клиент «xxx.org IP мекенжайлары қандай» сияқты DNS сұрауын жібереді.
  • байланыспаған xxx.org сайтын шешеді (немесе оны кэштен алады) және клиентке «xxx.org-да осындай және осындай IP бар» жауабын жібереді, оны DNSTap арқылы параллельді көшіреді.
  • dnstap-bgp осы мекенжайларды хабарлайды BIRD домен бұғатталған тізімде болса, BGP арқылы
  • BIRD көмегімен осы IP мекенжайларына бағытты жарнамалайды next-hop self клиенттік маршрутизатор
  • Клиенттен осы IP-ге келесі пакеттер туннель арқылы өтеді

Серверде бұғатталған сайттарға маршруттар үшін мен BIRD ішіндегі бөлек кестені қолданамын және ол ОЖ-мен ешбір жолмен қиылыспайды.

Бұл схеманың кемшілігі бар: клиенттің бірінші SYN пакеті, ең алдымен, отандық провайдер арқылы кетуге үлгереді. маршрут бірден жарияланбайды. Мұнда провайдер блоктауды қалай жасайтынына байланысты опциялар мүмкін. Егер ол жай ғана трафикті төмендетсе, онда ешқандай проблема жоқ. Ал егер ол оны қандай да бір DPI-ге қайта бағыттаса, онда (теориялық) арнайы әсерлер мүмкін.

Сондай-ақ, клиенттер DNS TTL кереметтерін құрметтемеуі мүмкін, бұл клиентке Unbound сұраудың орнына өзінің шіріген кэшіндегі кейбір ескірген жазбаларды пайдалануға әкелуі мүмкін.

Іс жүзінде біріншісі де, екіншісі де маған қиындық тудырмады, бірақ жүгірісіңіз әртүрлі болуы мүмкін.

Серверді баптау

Жылжытуға ыңғайлы болу үшін мен жаздым Ansible рөлі. Ол Linux негізіндегі серверлерді де, клиенттерді де теңшей алады (дебек негізіндегі таратулар үшін жасалған). Барлық параметрлер анық және орнатылған inventory.yml. Бұл рөл менің үлкен ойын кітабымнан кесілген, сондықтан ол қателерді қамтуы мүмкін - тарту сұраулары қош келдіңіз 🙂

Негізгі компоненттерді қарастырайық.

BGP

Бір хостта екі BGP демонын іске қосудың негізгі проблемасы бар: BIRD жергілікті хостпен (немесе кез келген жергілікті интерфейспен) BGP пирингін орнатқысы келмейді. Сөзден мүлде. Гуглинг пен пошталық тізімдерді оқу көмектеспеді, олар бұл дизайн бойынша деп мәлімдейді. Мүмкін бір жолы бар шығар, бірақ мен оны таппадым.

Сіз басқа BGP демонын қолданып көруге болады, бірақ маған BIRD ұнайды және оны мен барлық жерде қолданамын, мен нысандарды шығарғым келмейді.

Сондықтан мен dnstap-bgp файлын veth интерфейсі арқылы түбірге қосылған желінің аттар кеңістігінің ішіне жасырдым: ол түтік тәрізді, оның ұштары әртүрлі аттар кеңістігінде шығып тұрады. Осы ұштардың әрқайсысында біз хост шеңберінен шықпайтын жеке p2p IP мекенжайларын іліп қоямыз, сондықтан олар кез келген нәрсе бола алады. Бұл ішкі процестерге қол жеткізу үшін қолданылатын механизм барлығы жақсы көреді Docker және басқа контейнерлер.

Бұл үшін жазылған сценарий және өзіңізді басқа аттар кеңістігіне шашыңызбен сүйреп апаруға арналған жоғарыда сипатталған функция dnstap-bgp файлына қосылды. Осыған байланысты ол түбір ретінде іске қосылуы немесе setcap пәрмені арқылы CAP_SYS_ADMIN екілік файлына шығарылуы керек.

Атау кеңістігін құруға арналған мысал сценарийі

#!/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

dnstap-bgp.conf

namespace = "dtap"
domains = "/var/cache/rkn_domains.txt"
ttl = "168h"

[dnstap]
listen = "/tmp/dnstap.sock"
perm = "0666"

[bgp]
as = 65000
routerid = "192.168.149.2"

peers = [
    "192.168.149.1",
]

bird.conf

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 ұяларының барлық түрлеріне қосылуға тыйым салады. Бұл профильді жоюға немесе оны өшіруге болады:

# cd /etc/apparmor.d/disable && ln -s ../usr.sbin.unbound .
# apparmor_parser -R /etc/apparmor.d/usr.sbin.unbound

Мұны ойын кітабына қосу керек шығар. Әрине, профильді түзету және қажетті құқықтарды беру өте жақсы, бірақ мен тым жалқау болдым.

unbound.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. The қоспаңыз и қорытындыламау IP мекенжайлары мен желілерге өткізіп жіберуді немесе қорытындыламауды айта аласыз. Маған керек еді. менің VPS ішкі желісі блоктар тізімінде болды 🙂

Бір қызығы, RosKomSvoboda API әдепкі Python пайдаланушы агентімен сұрауларды блоктайды. Оны сценарийші бала түсінген сияқты. Сондықтан біз оны Ognelis деп өзгертеміз.

Әзірге ол тек IPv4 арқылы жұмыс істейді. IPv6 үлесі аз, бірақ оны түзету оңай болады. Сондай-ақ bird6 пайдалану қажет болмаса.

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_routes.list) BIRD үшін
  • 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 орнатамыз:

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

Барлығы, сервердің туннель IP мекенжайын DNS ретінде тарату үшін маршрутизаторда DHCP конфигурациялау қалады және схема дайын.

кемшіліктер

Домендер тізімін жасау және өңдеудің ағымдағы алгоритмімен ол басқа нәрселермен қатар: youtube.com және оның CDN-лері.

Бұл барлық бейнелер VPN арқылы өтетініне әкеледі, бұл бүкіл арнаны бітеп тастауы мүмкін. Бәлкім, РКН-ны әзірше бұғаттайтын танымал домендердің тізімін жасау керек шығар, ішектері жұқа. Және талдау кезінде оларды өткізіп жіберіңіз.

қорытынды

Сипатталған әдіс қазіргі уақытта провайдерлер жүзеге асыратын кез келген дерлік блоктауды айналып өтуге мүмкіндік береді.

Негізі, dnstap-bgp домендік атау негізінде трафикті басқарудың қандай да бір деңгейі қажет болатын кез келген басқа мақсат үшін пайдаланылуы мүмкін. Есіңізде болсын, біздің уақытта мыңдаған сайттар бір IP мекенжайында ілінуі мүмкін (мысалы, кейбір Cloudflare артында), сондықтан бұл әдіс өте төмен дәлдікке ие.

Бірақ құлыптарды айналып өту қажеттіліктері үшін бұл жеткілікті.

Толықтырулар, өңдеулер, тарту сұраулары - қош келдіңіз!

Ақпарат көзі: www.habr.com

пікір қалдыру