Anashkaloni bllokimin ILV me DNSTAp dhe BGP

Anashkaloni bllokimin ILV me DNSTAp dhe BGP

Tema është goxha e rrahur, e di. Për shembull, ka një të madhe artikull, por aty merret parasysh vetëm pjesa IP e listës së bllokimit. Ne gjithashtu do të shtojmë domene.

Për shkak të faktit se gjykatat dhe RKN bllokojnë gjithçka djathtas dhe majtas, dhe ofruesit po përpiqen shumë që të mos bien nën gjobat e lëshuara nga Revizorro, humbjet e lidhura nga bllokimi janë mjaft të mëdha. Dhe midis faqeve të bllokuara "me ligj" ka shumë të dobishme (përshëndetje, rutracker)

Unë jetoj jashtë juridiksionit të RKN-së, por prindërit, të afërmit dhe miqtë e mi kanë mbetur në shtëpi. Kështu u vendos që të krijohej një mënyrë e thjeshtë për njerëzit larg IT-së për të anashkaluar bllokimin, mundësisht pa pjesëmarrjen e tyre fare.

Në këtë shënim, unë nuk do t'i përshkruaj gjërat bazë të rrjetit me hapa, por do të përshkruaj parimet e përgjithshme se si mund të zbatohet kjo skemë. Pra, njohuria se si funksionon rrjeti në përgjithësi dhe në Linux në veçanti është një domosdoshmëri.

Llojet e bravave

Së pari, le të rifreskojmë kujtesën tonë për atë që po bllokohet.

Ekzistojnë disa lloje bravash në XML-në e shkarkuar nga RKN:

  • IP
  • Домен
  • URL

Për thjeshtësi, ne do t'i reduktojmë ato në dy: IP dhe domen, dhe thjesht do ta heqim domenin nga bllokimi me URL (më saktë, ata tashmë e kanë bërë këtë për ne).

njerëz të mirë nga Roskomsvoboda realizoi një të mrekullueshme API, përmes së cilës ne mund të marrim atë që na nevojitet:

Qasja në faqet e bllokuara

Për ta bërë këtë, na duhen disa VPS të vogla të huaja, mundësisht me trafik të pakufizuar - ka shumë prej tyre për 3-5 dollarë. Ju duhet ta merrni atë në afërsi jashtë vendit, në mënyrë që ping-u të mos jetë shumë i madh, por përsëri, merrni parasysh që interneti dhe gjeografia nuk përkojnë gjithmonë. Dhe meqenëse nuk ka SLA për 5 dollarë, është më mirë të marrësh 2+ pjesë nga ofrues të ndryshëm për tolerancën e gabimeve.

Më pas, duhet të konfigurojmë një tunel të koduar nga ruteri i klientit në VPS. Unë përdor Wireguard si konfigurimin më të shpejtë dhe më të lehtë. Unë gjithashtu kam ruter klientësh të bazuar në Linux (APU2 ose diçka në OpenWRT). Në rastin e disa Mikrotik / Cisco, mund të përdorni protokollet e disponueshme në to si OpenVPN dhe GRE-over-IPSEC.

Identifikimi dhe ridrejtimi i trafikut me interes

Sigurisht, mund të fikni të gjithë trafikun e Internetit përmes vendeve të huaja. Por, ka shumë të ngjarë, shpejtësia e punës me përmbajtje lokale do të vuajë shumë nga kjo. Plus, kërkesat e gjerësisë së brezit në VPS do të jenë shumë më të larta.

Prandaj, do të duhet të ndajmë disi trafikun në faqet e bllokuara dhe ta drejtojmë në mënyrë selektive në tunel. Edhe nëse një pjesë e trafikut "shtesë" arrin atje, është akoma shumë më mirë sesa të ngasësh gjithçka përmes tunelit.

Për të menaxhuar trafikun, ne do të përdorim protokollin BGP dhe do të njoftojmë rrugët drejt rrjeteve të nevojshme nga VPS-ja jonë te klientët. Le ta marrim BIRD si një nga demonët më funksionalë dhe më të përshtatshëm të BGP.

IP

Me bllokimin nga IP, gjithçka është e qartë: ne thjesht shpallim të gjitha IP-të e bllokuara me VPS. Problemi është se ka rreth 600 mijë nënrrjeta në listën që API kthen, dhe shumica dërrmuese e tyre janë /32 host. Ky numër rrugësh mund të ngatërrojë ruterat e dobët të klientëve.

Prandaj, gjatë përpunimit të listës, u vendos që të përmblidhet deri në rrjet / 24 nëse ka 2 ose më shumë host. Kështu, numri i rrugëve u reduktua në ~ 100 mijë. Skenari për këtë do të vijojë.

domains

Është më e ndërlikuar dhe ka disa mënyra. Për shembull, mund të instaloni një Squid transparent në çdo ruter klienti dhe të bëni përgjim HTTP atje dhe të shikoni në shtrëngimin e duarve TLS në mënyrë që të merrni URL-në e kërkuar në rastin e parë dhe domenin nga SNI në të dytin.

Por për shkak të të gjitha llojeve të TLS1.3 + eSNI të reja, analiza HTTPS po bëhet gjithnjë e më pak reale çdo ditë. Po, dhe infrastruktura në anën e klientit po bëhet më e ndërlikuar - do të duhet të përdorni të paktën OpenWRT.

Prandaj, vendosa të marr rrugën e përgjimit të përgjigjeve ndaj kërkesave DNS. Edhe këtu, çdo DNS-mbi-TLS / HTTPS fillon të rri pezull mbi kokën tuaj, por ne mund (për momentin) ta kontrollojmë këtë pjesë te klienti - ose ta çaktivizojmë ose të përdorim serverin tuaj për DoT / DoH.

Si të përgjoni DNS?

Këtu, gjithashtu, mund të ketë disa qasje.

  • Përgjimi i trafikut DNS nëpërmjet PCAP ose NFLOG
    Të dyja këto metoda të përgjimit zbatohen në shërbim sidmat. Por nuk është mbështetur për një kohë të gjatë dhe funksionaliteti është shumë primitiv, kështu që ju ende duhet të shkruani një parzmore për të.
  • Analiza e regjistrave të serverit DNS
    Fatkeqësisht, rekursorët e njohur për mua nuk janë në gjendje të regjistrojnë përgjigjet, por vetëm kërkesat. Në parim, kjo është logjike, pasi, ndryshe nga kërkesat, përgjigjet kanë një strukturë komplekse dhe është e vështirë t'i shkruash ato në formë teksti.
  • DNSTAp
    Për fat të mirë, shumë prej tyre tashmë mbështesin DNSTap për këtë qëllim.

Çfarë është DNSTap?

Anashkaloni bllokimin ILV me DNSTAp dhe BGP

Është një protokoll klient-server i bazuar në Protocol Buffers dhe Frame Streams për transferimin nga një server DNS në një koleksionues të pyetjeve dhe përgjigjeve të strukturuara DNS. Në thelb, serveri DNS transmeton metadatat e pyetjeve dhe përgjigjeve (lloji i mesazhit, IP-ja e klientit/serverit, etj.) plus mesazhet e plota DNS në formën (binare) në të cilën punon me ta përmes rrjetit.

Është e rëndësishme të kuptohet se në paradigmën DNSTap, serveri DNS vepron si klient dhe mbledhësi vepron si server. Kjo do të thotë, serveri DNS lidhet me kolektorin, dhe jo anasjelltas.

Sot DNSTap mbështetet në të gjithë serverët e njohur DNS. Por, për shembull, BIND në shumë shpërndarje (si Ubuntu LTS) shpesh ndërtohet për ndonjë arsye pa mbështetjen e tij. Pra, le të mos shqetësohemi me rimontimin, por të marrim një rekursor më të lehtë dhe më të shpejtë - Pa lidhje.

Si të kapni DNSTap?

Ka disa numër Shërbimet CLI për të punuar me një rrymë ngjarjesh DNSTap, por ato nuk janë të përshtatshme për zgjidhjen e problemit tonë. Prandaj, vendosa të shpik biçikletën time që do të bëjë gjithçka që është e nevojshme: dnstap-bgp

Algoritmi i punës:

  • Kur lëshohet, ngarkon një listë domenesh nga një skedar teksti, i kthen ato (habr.com -> com.habr), përjashton linjat e prishura, dublikatat dhe nëndomainët (d.m.th. nëse lista përmban habr.com dhe www.habr.com, vetëm i pari do të ngarkohet) dhe ndërton një pemë prefikse për një kërkim të shpejtë në këtë listë.
  • Duke vepruar si një server DNSTap, ai pret për një lidhje nga një server DNS. Në parim, ai mbështet të dy bazat UNIX dhe TCP, por serverët DNS që unë njoh mund të përdorin vetëm bazat UNIX
  • Paketat hyrëse DNSTap fillimisht deserializohen në një strukturë Protobuf dhe më pas vetë mesazhi binar DNS, i vendosur në një nga fushat Protobuf, analizohet në nivelin e regjistrimeve DNS RR
  • Kontrollohet nëse hosti i kërkuar (ose domeni i tij prind) është në listën e ngarkuar, nëse jo, përgjigja shpërfillet
  • Vetëm RR-të A/AAAA/CNAME zgjidhen nga përgjigja dhe adresat përkatëse IPv4/IPv6 janë nxjerrë prej tyre
  • Adresat IP ruhen me TTL të konfigurueshme dhe u reklamohen të gjithë kolegëve të konfiguruar BGP
  • Kur merrni një përgjigje që tregon një IP tashmë të ruajtur në memorie, TTL-ja e saj përditësohet
  • Pas skadimit të TTL, hyrja hiqet nga cache dhe nga njoftimet BGP

Funksionalitet shtesë:

  • Rileximi i listës së domeneve nga SIGHUP
  • Mbajtja e cache-së në sinkron me instancat e tjera dnstap-bgp nëpërmjet HTTP/JSON
  • Dublikojeni cache-në në disk (në bazën e të dhënave BoltDB) për të rivendosur përmbajtjen e tij pas një rifillimi
  • Mbështetje për kalimin në një hapësirë ​​tjetër emri rrjeti (përse kjo është e nevojshme do të përshkruhet më poshtë)
  • Mbështetje IPv6

kufizimet:

  • Domenet IDN nuk mbështeten ende
  • Pak cilësime BGP

kam mbledhur RPM dhe DEB paketa për instalim të lehtë. Duhet të funksionojë në të gjitha OS-të relativisht të fundit me systemd. ata nuk kanë asnjë varësi.

skemë

Pra, le të fillojmë të montojmë të gjithë përbërësit së bashku. Si rezultat, ne duhet të marrim diçka si kjo topologji rrjeti:
Anashkaloni bllokimin ILV me DNSTAp dhe BGP

Logjika e punës, mendoj, është e qartë nga diagrami:

  • Klienti ka serverin tonë të konfiguruar si DNS, dhe pyetjet DNS duhet të kalojnë gjithashtu mbi VPN. Kjo është e nevojshme në mënyrë që ofruesi të mos mund të përdorë përgjimin DNS për të bllokuar.
  • Kur hap faqen, klienti dërgon një pyetje DNS si "cilat janë IP-të e xxx.org"
  • i pavarur zgjidh xxx.org (ose e merr atë nga cache) dhe i dërgon një përgjigje klientit "xxx.org ka këtë dhe atë IP", duke e dublikuar atë paralelisht nëpërmjet DNSTap
  • dnstap-bgp shpall këto adresa në BIRD nëpërmjet BGP nëse domeni është në listën e bllokuar
  • BIRD reklamon një rrugë drejt këtyre IP-ve me next-hop self ruteri i klientit
  • Paketat pasuese nga klienti në këto IP kalojnë nëpër tunel

Në server, për rrugët drejt sajteve të bllokuara, unë përdor një tabelë të veçantë brenda BIRD dhe ajo nuk ndërpritet në asnjë mënyrë me OS.

Kjo skemë ka një pengesë: paketa e parë SYN nga klienti, ka shumë të ngjarë, do të ketë kohë të largohet përmes ofruesit vendas. itinerari nuk shpallet menjëherë. Dhe këtu opsionet janë të mundshme në varësi të mënyrës se si ofruesi e bën bllokimin. Nëse ai thjesht heq trafikun, atëherë nuk ka asnjë problem. Dhe nëse ai e ridrejton atë në disa DPI, atëherë (teorikisht) efektet speciale janë të mundshme.

Është gjithashtu e mundur që klientët të mos respektojnë mrekullitë DNS TTL, gjë që mund të bëjë që klienti të përdorë disa hyrje të ndenjura nga cache e tij të kalbur në vend që të kërkojë Unbound.

Në praktikë, as e para dhe as e dyta nuk më shkaktuan probleme, por kilometrazhi juaj mund të ndryshojë.

Akordimi i serverit

Për lehtësinë e rrotullimit, kam shkruar rol për Ansible. Mund të konfigurojë si serverët ashtu edhe klientët bazuar në Linux (i projektuar për shpërndarje të bazuara në deb). Të gjitha cilësimet janë mjaft të dukshme dhe janë vendosur inventar.yml. Ky rol është prerë nga libri im i madh i lojërave, kështu që mund të përmbajë gabime - tërheq kërkesa mire se erdhe 🙂

Le të kalojmë nëpër komponentët kryesorë.

BGP

Drejtimi i dy demonëve BGP në të njëjtin host ka një problem thelbësor: BIRD nuk dëshiron të konfigurojë BGP peering me localhost (ose ndonjë ndërfaqe lokale). Nga fjala fare. Googlimi dhe leximi i listave të postës nuk ndihmuan, ata pretendojnë se kjo është me dizajn. Ndoshta ka ndonjë mënyrë, por nuk e gjeta.

Mund të provoni një demon tjetër BGP, por mua më pëlqen BIRD dhe përdoret kudo nga unë, nuk dua të prodhoj entitete.

Prandaj, fsheha dnstap-bgp brenda hapësirës së emrave të rrjetit, e cila është e lidhur me rrënjën përmes ndërfaqes veth: është si një tub, skajet e të cilit dalin në hapësira të ndryshme emrash. Në secilën prej këtyre skajeve, ne varim adresa IP private p2p që nuk shkojnë përtej hostit, kështu që ato mund të jenë çdo gjë. Ky është i njëjti mekanizëm që përdoret për të hyrë në proceset brenda e dashur nga të gjithë Docker dhe kontejnerë të tjerë.

Për këtë ishte shkruar skenar dhe funksionaliteti i përshkruar tashmë më sipër për të tërhequr veten nga flokët në një hapësirë ​​tjetër emri u shtua në dnstap-bgp. Për shkak të kësaj, ai duhet të ekzekutohet si rrënjë ose të lëshohet në binarin CAP_SYS_ADMIN nëpërmjet komandës setcap.

Shembull i skriptit për krijimin e hapësirës së emrave

#!/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",
]

zog.konf

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_rrugët.lista

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

Si parazgjedhje, në Ubuntu, binarja Unbound mbërthehet nga profili AppArmor, i cili e ndalon atë të lidhet me të gjitha llojet e prizave DNSTap. Ju ose mund ta fshini këtë profil ose ta çaktivizoni atë:

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

Kjo ndoshta duhet të shtohet në librin e lojërave. Është ideale, sigurisht, të korrigjoj profilin dhe të lëshoj të drejtat e nevojshme, por unë isha shumë dembel.

i palidhur.konf

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

Shkarkimi dhe përpunimi i listave

Skript për shkarkimin dhe përpunimin e një liste adresash IP
Ai shkarkon listën, përmbledh në prefiksin pfx. Në mos_shto и mos_përmbledh ju mund t'u thoni IP-ve dhe rrjeteve të kalojnë ose të mos përmbledhin. Më duhej. nënrrjeti i VPS-së sime ishte në listën e bllokimit 🙂

Gjëja qesharake është se API RosKomSvoboda bllokon kërkesat me agjentin e parazgjedhur të përdoruesit Python. Duket se djali i skenarit e ka kuptuar. Prandaj, ne e ndryshojmë atë në Ognelis.

Deri më tani, funksionon vetëm me IPv4. pjesa e IPv6 është e vogël, por do të jetë e lehtë të rregullohet. Përveç nëse duhet të përdorni edhe 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)

Skript për përditësim
E drejtoj në kurorë një herë në ditë, ndoshta ia vlen ta tërheq çdo 4 orë. kjo, për mendimin tim, është periudha e rinovimit që RKN kërkon nga ofruesit. Plus, ata kanë disa bllokime të tjera super-urgjente, të cilat mund të arrijnë më shpejt.

Bën sa vijon:

  • Ekzekuton skriptin e parë dhe përditëson listën e rrugëve (rkn_routes.list) për BIRD
  • Ringarko BIRD
  • Përditëson dhe pastron listën e domeneve për dnstap-bgp
  • Ringarko 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

Ato janë shkruar pa u menduar shumë, kështu që nëse shihni diçka që mund të përmirësohet - shkoni për të.

Konfigurimi i klientit

Këtu do të jap shembuj për ruterat Linux, por në rastin e Mikrotik / Cisco duhet të jetë edhe më e lehtë.

Së pari, ne vendosëm BIRD:

zog.konf

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;
}

Kështu, ne do të sinkronizojmë rrugët e marra nga BGP me tabelën e kursimit të kernelit numër 222.

Pas kësaj, mjafton t'i kërkoni kernelit të shikojë këtë pllakë përpara se të shikoni atë të paracaktuar:

# 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

Gjithçka, mbetet të konfiguroni DHCP në ruter për të shpërndarë adresën IP të tunelit të serverit si DNS, dhe skema është gati.

Kufizimet

Me algoritmin aktual për gjenerimin dhe përpunimin e listës së domeneve, ai përfshin ndër të tjera, youtube.com dhe CDN-të e tij.

Dhe kjo çon në faktin se të gjitha videot do të kalojnë përmes VPN, i cili mund të bllokojë të gjithë kanalin. Ndoshta ia vlen të përpilohet një listë e domeneve-përjashtimeve të njohura që bllokojnë RKN për momentin, guximi është i hollë. Dhe kaloni ato kur analizoni.

Përfundim

Metoda e përshkruar ju lejon të anashkaloni pothuajse çdo bllokim që ofruesit aktualisht zbatojnë.

Në parim, dnstap-bgp mund të përdoret për çdo qëllim tjetër ku nevojitet një nivel i caktuar i kontrollit të trafikut bazuar në emrin e domenit. Vetëm mbani në mend se në kohën tonë, një mijë sajte mund të varen në të njëjtën adresë IP (prapa disa Cloudflare, për shembull), kështu që kjo metodë ka një saktësi mjaft të ulët.

Por për nevojat e anashkalimit të bravave, kjo është mjaft e mjaftueshme.

Shtesa, modifikime, kërkesa për tërheqje - mirëpritur!

Burimi: www.habr.com

Shto një koment