Bypassa u bloccu ILV cù DNSTap è BGP

Bypassa u bloccu ILV cù DNSTap è BGP

U tema hè abbastanza battutu, a so. Per esempiu, ci hè una grande un articulu, ma solu a parte IP di u blocklist hè cunsideratu quì. Avemu ancu aghjunghje domini.

A causa di u fattu chì i tribunali è u RKN bluccanu tuttu u dirittu è a manca, è i fornituri sò attenti à ùn cascà micca sottu à l'amende emesse da Revizorro, i perditi assuciati da u bloccu sò abbastanza grande. È trà i siti "legalmente" bluccati ci sò parechji utili (ciao, rutracker)

Vivu fora di a ghjuridizione di u RKN, ma i mo genitori, parenti è amichi sò stati in casa. Allora hè statu decisu di vene cun un modu faciule per e persone luntanu da l'IT per bypassà u bluccatu, preferibile senza a so participazione.

In questa nota, ùn descriveraghju micca e cose basi di a rete in passi, ma descriverà i principii generali di cumu si pò implementà stu schema. Allora a cunniscenza di cumu funziona a reta in generale è in Linux in particulare hè un must have.

Tipi di serratura

Prima, rinfrescemu a nostra memoria di ciò chì hè bluccatu.

Ci sò parechji tipi di chjusi in u XML scaricatu da u RKN:

  • IP
  • Domain Name
  • URL

Per a simplicità, i riducemu à dui: IP è duminiu, è simpricimenti tirà u duminiu da u bluccatu per URL (più precisamente, anu digià fattu questu per noi).

bona ghjente da Roskomsvoboda realizatu un maravigliu API, attraversu quale pudemu avè ciò chì avemu bisognu:

Accessu à i siti bluccati

Per fà questu, avemu bisognu di qualchì VPS straneru chjucu, preferibile cù un trafficu illimitatu - ci sò assai di questi per 3-5 bucks. Avete bisognu à piglià in u vicinu à l'esteru per chì u ping ùn hè micca assai grande, ma dinò, pigliate in contu chì l'Internet è a geografia ùn sò micca sempre coincide. E postu chì ùn ci hè micca SLA per 5 bucks, hè megliu piglià 2+ pezzi da diversi fornituri per a tolleranza di difetti.

In seguitu, avemu bisognu di stallà un tunnel criptatu da u router client à u VPS. Aghju utilizatu Wireguard cum'è u più veloce è faciule da stallà. Aghju ancu client router basati in Linux (APU2 o qualcosa in OpenWRT). In u casu di qualchi Mikrotik / Cisco, pudete aduprà i protokolli dispunibili nantu à elli cum'è OpenVPN è GRE-over-IPSEC.

Identificazione è redirezzione di u trafficu d'interessu

Pudete, sicuru, disattivà tuttu u trafficu Internet attraversu paesi stranieri. Ma, assai prubabile, a rapidità di travaglià cù u cuntenutu lucale soffre assai da questu. Inoltre, i requisiti di larghezza di banda in VPS seranu assai più alti.

Per quessa, avemu bisognu di qualcuna manera d'assignà u trafficu à i siti bluccati è selettivu dirigenu à u tunnel. Ancu s'ellu ci hè un pocu di u trafficu "extra", hè sempre assai megliu cà guidà tuttu per u tunnel.

Per gestisce u trafficu, useremu u protocolu BGP è annunziate rotte à e rete necessarie da u nostru VPS à i clienti. Pigliamu BIRD cum'è unu di i demoni BGP più funziunali è convenienti.

IP

Cù u bluccatu da IP, tuttu hè chjaru: annunziemu solu tutti l'IP bluccati cù VPS. U prublema hè chì ci sò circa 600 mila subnets in a lista chì l'API torna, è a maiò parte di elli sò / 32 hosts. Stu nùmeru di rotte pò cunfundà i routers client debuli.

Dunque, quandu si tratta di a lista, hè statu decisu di riassume à a reta / 24 s'ellu hà 2 o più ospiti. Cusì, u numeru di rotte hè stata ridutta à ~ 100 mila. U script per questu seguitarà.

Domini

Hè più cumplicatu è ci sò parechje manere. Per esempiu, pudete installà un Squid trasparente in ogni router di u cliente è fà l'intercepzione HTTP quì è peep in u TLS handshake per ottene l'URL dumandatu in u primu casu è u duminiu da SNI in u sicondu.

Ma per via di ogni tipu di TLS1.3 + eSNI newfangled, l'analisi HTTPS hè diventata menu è menu reale ogni ghjornu. Iè, è l'infrastruttura in u latu di u cliente hè diventata più cumplicata - avete da aduprà almenu OpenWRT.

Dunque, aghju decisu di piglià a strada di intercepting risposti à e dumande DNS. Ancu quì, qualsiasi DNS-over-TLS / HTTPS cumencia à sopra à a vostra testa, ma pudemu (per avà) cuntrullà sta parte nantu à u cliente - sia disattivàla o utilizate u vostru propiu servitore per DoT / DoH.

Cumu intercepte DNS?

Quì, ancu, ci ponu esse parechji approcci.

  • Interceptazione di u trafficu DNS via PCAP o NFLOG
    I dui metudi di intercepzioni sò implementati in l'utilità sidmat. Ma ùn hè statu supportatu per un bellu pezzu è a funziunalità hè assai primitiva, cusì avete sempre bisognu di scrive un arnesi per questu.
  • Analisi di i logs di u servitore DNS
    Sfortunatamente, i risorsi cunnisciuti da mè ùn sò micca capaci di logà risposte, ma solu richieste. In principiu, questu hè logicu, postu chì, à u cuntrariu di e dumande, e risposte anu una struttura cumplessa è hè difficiule di scrive in forma di testu.
  • DNSTap
    Fortunatamente, assai di elli supportanu digià DNSTap per questu scopu.

Cosa hè DNSTap?

Bypassa u bloccu ILV cù DNSTap è BGP

Hè un protokollu cliente-servitore basatu in Protocol Buffers è Frame Streams per u trasferimentu da un servitore DNS à un cullettore di dumande è risposte DNS strutturate. Essenzialmente, u servitore DNS trasmette metadati di quistione è risposta (tipu di missaghju, IP cliente / servitore, etc.) più missaghji DNS cumpleti in a forma (binaria) in quale travaglia cun elli nantu à a reta.

Hè impurtante di capiscenu chì in u paradigma DNSTap, u servitore DNS agisce cum'è un cliente è u cullettore cum'è un servitore. Questu hè, u servitore DNS cunnetta à u cullettore, è micca vice versa.

Oghje DNSTap hè supportatu in tutti i servitori DNS populari. Ma, per esempiu, BIND in parechje distribuzioni (cum'è Ubuntu LTS) hè spessu custruitu per qualchì mutivu senza u so supportu. Allora ùn ci preoccupa micca di rimonta, ma pigliate un recursor più liggeru è più veloce - Unbound.

Cumu catturà DNSTap?

Ci sò certi количество Utilità CLI per travaglià cù un flussu di avvenimenti DNSTap, ma ùn sò micca adattati per risolve u nostru prublema. Dunque, aghju decisu di inventà a mo propria bicicletta chì farà tuttu ciò chì hè necessariu: dnstap-bgp

Algoritmu di travagliu:

  • Quandu hè lanciatu, carica una lista di domini da un schedariu di testu, li inverte (habr.com -> com.habr), esclude linee rotte, duplicati è sottodominii (vale à dì se a lista cuntene habr.com è www.habr.com, serà caricatu solu u primu) è custruisce un arbulu di prefissu per a ricerca rapida attraversu sta lista
  • Agendu cum'è un servitore DNSTap, aspetta una cunnessione da un servitore DNS. In principiu, supporta i sockets UNIX è TCP, ma i servitori DNS chì cunnoscu ponu aduprà solu socket UNIX.
  • I pacchetti DNSTap entranti sò prima deserializzati in una struttura Protobuf, è dopu u missaghju DNS binariu stessu, situatu in unu di i campi Protobuf, hè analizatu à u livellu di i registri DNS RR.
  • Hè verificatu se l'ospite dumandatu (o u so duminiu parentale) hè in a lista caricata, se no, a risposta hè ignorata.
  • Solu A / AAAA / CNAME RR sò scelti da a risposta è l'indirizzi IPv4 / IPv6 currispondenti sò estratti da elli.
  • L'indirizzi IP sò in cache cù TTL configurable è annunziati à tutti i pari BGP cunfigurati
  • Quandu riceve una risposta chì punta à una IP digià in cache, u so TTL hè aghjurnatu
  • Dopu chì u TTL scade, l'entrata hè eliminata da a cache è da l'annunzii BGP

Funzionalità supplementu:

  • Rileghje a lista di domini da SIGHUP
  • Mantene a cache in sincronia cù altri casi dnstap-bgp via HTTP/JSON
  • Duplicate a cache nantu à u discu (in a basa di dati BoltDB) per restaurà u so cuntenutu dopu un reiniciu
  • Supportu per cambià à un spaziu di nomi di rete differente (perchè questu hè necessariu serà descrittu quì sottu)
  • Supportu IPv6

Limitazioni:

  • I domini IDN ùn sò ancu supportati
  • Pochi paràmetri BGP

Aghju cullatu RPM è DEB pacchetti per una facilità d'installazione. Deve travaglià in tutti i OS relativamente recenti cù systemd. ùn anu micca dipendenze.

U schema

Allora, cuminciamu à assemble tutti i cumpunenti. In u risultatu, duvemu ottene qualcosa cum'è questa topologia di a rete:
Bypassa u bloccu ILV cù DNSTap è BGP

A logica di u travagliu, pensu, hè chjaru da u diagramma:

  • U cliente hà u nostru servitore cunfiguratu cum'è DNS, è e dumande DNS devenu ancu passà nantu à a VPN. Questu hè necessariu per chì u fornitore ùn pò micca aduprà intercepzioni DNS per bluccà.
  • Quandu apre u situ, u cliente manda una dumanda DNS cum'è "chì sò l'IP di xxx.org"
  • Unbound risolve xxx.org (o piglia da a cache) è manda una risposta à u cliente "xxx.org hà tali è tali IP", duplicà in parallelu via DNSTap
  • dnstap-bgp annuncia sti indirizzi in BIRDU via BGP se u duminiu hè nantu à a lista bluccata
  • BIRDU annuncia una strada à questi IP cun next-hop self router client
  • I pacchetti successivi da u cliente à queste IP passanu per u tunnel

Nant'à u servitore, per rotte à i siti bluccati, aghju utilizatu una tavola separata in BIRD è ùn si interseca cù u SO in ogni modu.

Stu schema hà un inconveniente: u primu pacchettu SYN da u cliente, assai prubabilmente, avarà u tempu di lascià attraversu u fornitore domesticu. a strada ùn hè micca annunziatu immediatamente. E quì l'opzioni sò pussibuli secondu cumu u fornitore faci u bloccu. S'ellu solu abbanduneghja u trafficu, allora ùn ci hè micca prublema. È s'ellu redirige à qualchì DPI, allora (teoricamente) effetti speciali sò pussibuli.

Hè ancu pussibule chì i clienti ùn rispettanu micca i miraculi DNS TTL, chì ponu causà à u cliente per aduprà alcune entrate stale da u so cache putrettu invece di dumandà à Unbound.

In pratica, nè u primu nè u sicondu hà causatu prublemi per mè, ma u vostru chilometru pò varià.

Sintonizazione di u servitore

Per facilità di rolling, aghju scrittu rolu per Ansible. Pò cunfigurà i servitori è i clienti basati in Linux (cuncepitu per distribuzioni basate in deb). Tutti i paràmetri sò abbastanza evidenti è sò stallati inventariu.yml. Stu rolu hè tagliatu da u mo grande playbook, cusì pò cuntene errori - richieste di pull benvenutu 🙂

Andemu à traversu i cumpunenti principali.

Bgp

L'esecuzione di dui demoni BGP nantu à u stessu òspite hà un prublema fundamentale: BIRD ùn vole micca cunfigurà u peering BGP cù l'host locale (o qualsiasi interfaccia lucale). Da a parolla in tuttu. A ricerca di Google è a lettura di e mailing-lists ùn anu micca aiutu, dicenu chì questu hè di designu. Forse ci hè un modu, ma ùn aghju micca trovu.

Pudete pruvà un altru daemon BGP, ma mi piace BIRD è hè utilizatu in ogni locu per mè, ùn vogliu micca pruduce entità.

Per quessa, aghju oculatu dnstap-bgp in u spaziu di nomi di a rete, chì hè cunnessu à a radica attraversu l'interfaccia veth: hè cum'è una pipa, l'estremità di u quali spuntanu in diversi spazii di nomi. In ognuna di queste fini, pendemu l'indirizzi IP p2p privati ​​​​chì ùn vanu fora di l'ospitu, perchè ponu esse qualcosa. Questu hè u stessu mecanismu utilizatu per accede à i prucessi in l'internu amatu da tutti Docker è altri cuntenituri.

Per questu hè statu scrittu script è a funziunalità digià descritta sopra per trascinà per i capelli à un altru spaziu di nomi hè stata aghjunta à dnstap-bgp. Per quessa, deve esse eseguitu cum'è root o emessu à u binariu CAP_SYS_ADMIN via u cumandamentu setcap.

Esempiu di script per creà un spaziu di nomi

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

Per automaticamente, in Ubuntu, u binariu Unbound hè chjapputu da u prufilu AppArmor, chì impedisce di cunnette à ogni tipu di socket DNSTap. Pudete sia sguassà stu prufilu, o disattivà lu:

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

Questu probabilmente deve esse aghjuntu à u playbook. Hè l'ideale, sicuru, per correggerà u prufilu è emette i diritti necessarii, ma eru troppu pigra.

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

Scaricamentu è trasfurmazioni di listi

Script per scaricà è trasfurmà una lista di indirizzi IP
Scaricate a lista, riassume à u prefissu pfx. L' nun_add и nun_summarize pudete dì à l'IP è a rete per saltà o micca riassume. Ne avia bisognu. a subnet di u mo VPS era in u blocklist 🙂

A cosa divertente hè chì l'API RosKomSvoboda blucca e dumande cù l'agente d'utilizatore Python predeterminatu. Sembra chì u script-kiddy hà capitu. Dunque, cambiamu in Ognelis.

Finu a ora, funziona solu cù IPv4. a parte di IPv6 hè chjuca, ma serà faciule di riparà. A menu chì avete aduprà bird6 ancu.

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)

Script per aghjurnà
I run it on the crown once a day, forsi vale a pena tirallu ogni 4 ore. questu, in my opinion, hè u periodu di rinnuvamentu chì u RKN esige da i fornituri. In più, anu qualchì altru bloccu super-urgente, chì pò ghjunghje più veloce.

Face i seguenti:

  • Esegue u primu script è aghjurnà a lista di rotte (rkn_routes.list) per BIRD
  • Ricarica BIRD
  • Aghjurnate è pulisce a lista di domini per dnstap-bgp
  • Ricaricate 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

Sò stati scritti senza assai pensamentu, perchè se vede qualcosa chì pò esse migliuratu - vai per questu.

Configurazione di u cliente

Quì daraghju esempi per i routers Linux, ma in u casu di Mikrotik / Cisco duverebbe esse ancu più faciule.

Prima, avemu stabilitu 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;
}

Cusì, sincronizeremu e rotte ricevute da BGP cù a tabella di routing di u kernel numeru 222.

Dopu quì, hè abbastanza per dumandà à u kernel per fighjà sta piastra prima di guardà u predeterminatu:

# 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

Tuttu, resta à cunfigurà DHCP in u router per distribuisce l'indirizzu IP di u tunnel di u servitore cum'è DNS, è u schema hè prestu.

shortcomings

Cù l'algoritmu attuale per generà è trasfurmà a lista di domini, include, frà altre cose, youtube.com è i so CDN.

È questu porta à u fattu chì tutti i video passanu per a VPN, chì pò obstruisce tuttu u canali. Forsi vale a pena di cumpilà una lista di domini populari-exclusions chì bluccà u RKN per u mumentu, i guts sò magre. È saltate durante l'analisi.

cunchiusioni

U metudu descrittu permette di passà quasi ogni bloccu chì i fornituri attualmente implementanu.

In principiu, dnstap-bgp pò esse usatu per qualsiasi altru scopu induve qualchì livellu di cuntrollu di trafficu hè necessariu basatu annantu à u nome di duminiu. Basta à tene in mente chì in u nostru tempu, mille siti ponu appiccà nantu à u stessu indirizzu IP (darrettu qualchì Cloudflare, per esempiu), cusì stu metudu hà una precisione piuttostu bassa.

Ma per i bisogni di bypassing locks, questu hè abbastanza.

Addizzioni, modifiche, richieste di pull - benvenutu!

Source: www.habr.com

Add a comment