Framhjá ILV-blokkun með DNSTap og BGP

Framhjá ILV-blokkun með DNSTap og BGP

Umræðuefnið er ansi slegið, ég veit. Það er til dæmis frábært grein, en aðeins IP-hluti blokkunarlistans er talinn þar. Við munum einnig bæta við lénum.

Vegna þess að dómstólar og RKN loka á allt til hægri og vinstri, og veitendur reyna að lenda ekki undir sektunum sem Revizorro hefur gefið út, er tilheyrandi tap af lokun nokkuð mikið. Og meðal „löglega“ lokaðra vefsvæða eru margar gagnlegar (halló, rutracker)

Ég bý utan lögsögu RKN, en foreldrar mínir, ættingjar og vinir voru áfram heima. Því var ákveðið að koma upp auðveldri leið fyrir fólk fjarri upplýsingatækni til að komast framhjá blokkun, helst án þátttöku þeirra.

Í þessari athugasemd mun ég ekki lýsa grunnþáttum netkerfisins í skrefum, en mun lýsa almennum meginreglum um hvernig hægt er að útfæra þetta kerfi. Þannig að þekking á því hvernig netið virkar almennt og í Linux sérstaklega er nauðsynleg.

Tegundir læsinga

Fyrst skulum við hressa upp á minni okkar um það sem verið er að loka á.

Það eru nokkrar gerðir af læsingum í óhlaðnum XML frá RKN:

  • IP
  • Домен
  • URL

Til einföldunar munum við fækka þeim í tvö: IP og lén, og við munum einfaldlega draga lénið úr lokun með slóð (nánar tiltekið, þeir hafa þegar gert þetta fyrir okkur).

gott fólk frá Roskomsvoboda áttaði sig á dásamlegu API, þar sem við getum fengið það sem við þurfum:

Aðgangur að lokuðum síðum

Til þess þurfum við lítið erlent VPS, helst með ótakmarkaðri umferð - það eru margir slíkir fyrir 3-5 dollara. Þú þarft að taka það í náinni útlöndum svo að pingið sé ekki mjög stórt, en aftur, taktu tillit til þess að internetið og landafræðin fara ekki alltaf saman. Og þar sem það er ekkert SLA fyrir 5 dollara, þá er betra að taka 2+ stykki frá mismunandi veitendum fyrir bilanaþol.

Næst þurfum við að setja upp dulkóðuð göng frá biðlarabeini til VPS. Ég nota Wireguard sem fljótlegast og auðveldast að setja upp. Ég er líka með biðlarabeina byggða á Linux (APU2 eða eitthvað í OpenWRT). Í tilviki sumra Mikrotik / Cisco geturðu notað samskiptareglurnar sem eru tiltækar á þeim eins og OpenVPN og GRE-over-IPSEC.

Auðkenning og tilvísun hagsmunaumferðar

Þú getur að sjálfsögðu slökkt á allri netumferð um útlönd. En líklega mun hraðinn við að vinna með staðbundið efni verða fyrir miklum skaða af þessu. Auk þess verða bandbreiddarkröfur á VPS miklu hærri.

Þess vegna verðum við einhvern veginn að úthluta umferð á lokaðar síður og beina henni sértækt í göngin. Jafnvel þó eitthvað af "auka" umferðinni komist þangað er það samt miklu betra en að keyra allt í gegnum göngin.

Til að stjórna umferð munum við nota BGP siðareglur og tilkynna leiðir til nauðsynlegra neta frá VPS okkar til viðskiptavina. Við skulum taka BIRD sem einn af hagnýtustu og þægilegustu BGP púkunum.

IP

Með lokun með IP er allt ljóst: við tilkynnum einfaldlega allar læstar IP-tölur með VPS. Vandamálið er að það eru um 600 þúsund undirnet á listanum sem API skilar og langflestir þeirra eru /32 hýslar. Þessi fjöldi leiða getur ruglað veika biðlarabeina.

Þess vegna var ákveðið við vinnslu listans að taka saman upp á netið / 24 ef það hefur 2 eða fleiri vélar. Þannig var leiðum fækkað niður í ~100 þúsund. Handritið að þessu mun fylgja.

Lén

Það er flóknara og það eru nokkrar leiðir. Til dæmis geturðu sett upp gagnsæjan Squid á hvern biðlarabeini og gert HTTP hlerun þar og kíkt inn í TLS handabandið til að fá umbeðna vefslóð í fyrra tilvikinu og lénið frá SNI í því síðara.

En vegna alls kyns nýmóðins TLS1.3 + eSNI er HTTPS greining að verða minna og minna raunverulegt á hverjum degi. Já, og innviðir viðskiptavinamegin eru að verða flóknari - þú verður að nota að minnsta kosti OpenWRT.

Þess vegna ákvað ég að fara þá leið að stöðva svör við DNS beiðnum. Hér líka byrjar allir DNS-yfir-TLS / HTTPS að sveima yfir höfðinu á þér, en við getum (í bili) stjórnað þessum hluta á biðlaranum - annað hvort slökkt á honum eða notað þinn eigin netþjón fyrir DoT / DoH.

Hvernig á að stöðva DNS?

Hér geta líka verið nokkrar aðferðir.

  • Hlerun á DNS umferð í gegnum PCAP eða NFLOG
    Báðar þessar hlerunaraðferðir eru útfærðar í tólinu sidmat. En það hefur ekki verið stutt í langan tíma og virknin er mjög frumstæð, svo þú þarft samt að skrifa beisli fyrir það.
  • Greining á DNS netþjónsskrám
    Því miður geta þeir endurtekningar sem ég þekki ekki skráð svör, heldur aðeins beiðnir. Í grundvallaratriðum er þetta rökrétt þar sem, ólíkt beiðnum, hafa svör flókna uppbyggingu og erfitt er að skrifa þau í textaformi.
  • DNSTap
    Sem betur fer styðja margir þeirra nú þegar DNSTap í þessum tilgangi.

Hvað er DNSTap?

Framhjá ILV-blokkun með DNSTap og BGP

Það er samskiptareglur biðlara-miðlara sem byggjast á samskiptaþjöppum og rammastraumum til að flytja frá DNS netþjóni yfir í safnara skipulagðra DNS fyrirspurna og svara. Í meginatriðum sendir DNS-þjónninn lýsigögn fyrirspurna og svars (tegund skilaboða, IP-tölu viðskiptavinar/miðlara osfrv.) ásamt fullkomnum DNS-skilaboðum í (tvíundar) formi sem hann vinnur með þeim yfir netið.

Það er mikilvægt að skilja að í DNSTap hugmyndafræðinni virkar DNS þjónninn sem viðskiptavinur og safnarinn virkar sem þjónn. Það er að segja að DNS þjónninn tengist safnaranum og ekki öfugt.

Í dag er DNSTap stutt á öllum vinsælum DNS netþjónum. En til dæmis er BIND í mörgum dreifingum (eins og Ubuntu LTS) oft smíðað af einhverjum ástæðum án stuðnings þess. Við skulum því ekki nenna að setja saman aftur, heldur taka léttari og hraðari endurtekningu - Óbundið.

Hvernig á að ná DNSTap?

Það er sumir Fjöldi CLI tól til að vinna með straum af DNSTap viðburðum, en þau henta ekki til að leysa vandamál okkar. Þess vegna ákvað ég að finna upp mitt eigið hjól sem gerir allt sem þarf: dnstap-bgp

Vinnualgrím:

  • Þegar það er opnað hleður það lista yfir lén úr textaskrá, snýr þeim við (habr.com -> com.habr), útilokar brotnar línur, afrit og undirlén (þ.e. ef listinn inniheldur habr.com og www.habr.com, það verður aðeins hlaðið það fyrsta) og byggir upp forskeytitré til að leita hratt í gegnum þennan lista
  • Hann starfar sem DNSTap netþjónn og bíður eftir tengingu frá DNS netþjóni. Í grundvallaratriðum styður það bæði UNIX og TCP innstungur, en DNS netþjónarnir sem ég þekki geta aðeins notað UNIX innstungur
  • Komandi DNSTap pakkar eru fyrst afserialized í Protobuf uppbyggingu, og síðan eru tvöfaldur DNS skilaboðin sjálf, sem eru staðsett í einu af Protobuf reitunum, flokkuð á stig DNS RR færslur
  • Athugað er hvort umbeðinn gestgjafi (eða móðurlén hans) sé á hlaðna listanum, ef ekki er svarið hunsað
  • Aðeins A/AAAA/CNAME RR eru valin úr svarinu og samsvarandi IPv4/IPv6 vistföng eru dregin út úr þeim
  • IP tölur eru í skyndiminni með stillanlegum TTL og auglýst fyrir alla stillta BGP jafningja
  • Þegar svar berst sem bendir á IP-tölu sem þegar er í skyndiminni er TTL þess uppfærð
  • Eftir að TTL rennur út er færslan fjarlægð úr skyndiminni og frá BGP tilkynningum

Viðbótarvirkni:

  • Endurlestur lista yfir lén eftir SIGHUP
  • Halda skyndiminni í samstillingu við önnur tilvik dnstap-bgp í gegnum HTTP/JSON
  • Afritaðu skyndiminni á disknum (í BoltDB gagnagrunninum) til að endurheimta innihald þess eftir endurræsingu
  • Stuðningur við að skipta yfir í annað netnafnarými (af hverju þetta er nauðsynlegt verður lýst hér að neðan)
  • IPv6 stuðningur

Takmarkanir:

  • IDN lén eru ekki studd ennþá
  • Fáar BGP stillingar

ég safnaði RPM og DEB pakkar til að auðvelda uppsetningu. Ætti að virka á öllum tiltölulega nýlegum stýrikerfi með systemd. þeir hafa enga ósjálfstæði.

Kerfið

Svo, við skulum byrja að setja alla íhlutina saman. Fyrir vikið ættum við að fá eitthvað eins og þessa netkerfisfræði:
Framhjá ILV-blokkun með DNSTap og BGP

Rökfræði vinnunnar, held ég, sé skýr af skýringarmyndinni:

  • Viðskiptavinurinn hefur netþjóninn okkar stilltan sem DNS og DNS fyrirspurnir verða einnig að fara yfir VPN. Þetta er nauðsynlegt svo að veitandinn geti ekki notað DNS-hlerun til að loka.
  • Þegar þú opnar síðuna sendir viðskiptavinurinn DNS fyrirspurn eins og „hverjar eru IP-tölur xxx.org“
  • Óbundið leysir xxx.org (eða tekur það úr skyndiminni) og sendir svar til viðskiptavinarins „xxx.org hefur svona og svo IP“, afritar það samhliða í gegnum DNSTap
  • dnstap-bgp tilkynnir þessi heimilisföng í FUGL í gegnum BGP ef lénið er á bannlista
  • FUGL auglýsir leið að þessum IP-tölum með next-hop self biðlara leið
  • Síðari pakkar frá viðskiptavininum til þessara IP-tölu fara í gegnum göngin

Á þjóninum, fyrir leiðir á lokaðar síður, nota ég sérstaka töflu inni í BIRD og hún skerast ekki stýrikerfið á nokkurn hátt.

Þetta kerfi hefur galli: fyrsti SYN pakkinn frá viðskiptavininum mun líklega hafa tíma til að fara í gegnum innlenda þjónustuaðila. leiðin er ekki auglýst strax. Og hér eru valkostir mögulegir eftir því hvernig veitandinn gerir lokunina. Ef hann fellur bara úr umferð, þá er ekkert vandamál. Og ef hann vísar því á einhvern DPI þá eru (fræðilega séð) tæknibrellur mögulegar.

Það er líka mögulegt að viðskiptavinir virði ekki DNS TTL kraftaverk, sem getur valdið því að viðskiptavinurinn notar einhverjar gamaldags færslur úr rotnu skyndiminni í stað þess að spyrja Óbundið.

Í reynd olli hvorki sá fyrri né sá síðari vandamál fyrir mig, en kílómetrafjöldinn þinn getur verið mismunandi.

Stilling miðlara

Til að auðvelda rúlluna skrifaði ég hlutverk Ansible. Það getur stillt bæði netþjóna og viðskiptavini byggt á Linux (hannað fyrir deb-undirstaða dreifingar). Allar stillingar eru nokkuð augljósar og eru settar inn inventory.yml. Þetta hlutverk er klippt úr stóru leikbókinni minni, svo það gæti innihaldið villur - draga beiðnir velkomin 🙂

Við skulum fara í gegnum helstu þættina.

BGP

Að keyra tvo BGP púka á sama hýsli hefur grundvallarvandamál: BIRD vill ekki setja upp BGP-peering með localhost (eða einhverju staðbundnu viðmóti). Frá orðinu yfirleitt. Það hjálpaði ekki að googla og lesa póstlista, þeir halda því fram að þetta sé eftir hönnun. Kannski er einhver leið, en ég fann hana ekki.

Þú getur prófað annan BGP púk, en mér líkar við BIRD og hann er notaður alls staðar af mér, ég vil ekki framleiða einingar.

Þess vegna faldi ég dnstap-bgp inni í nafnrými netsins, sem er tengt við rótina í gegnum veth viðmótið: það er eins og pípa, endar þeirra standa út í mismunandi nafnasvæðum. Á hvern þessara enda hengjum við upp einka p2p IP tölur sem fara ekki út fyrir hýsilinn, svo þær geta verið hvað sem er. Þetta er sama vélbúnaður og notaður til að fá aðgang að ferlum inni elskaður af öllum Docker og aðrir gámar.

Fyrir þetta var skrifað handrit og virkninni sem þegar hefur verið lýst hér að ofan til að draga þig í hárið í annað nafnrými var bætt við dnstap-bgp. Vegna þessa verður að keyra það sem rót eða gefa það út á CAP_SYS_ADMIN tvöfaldann með setcap skipuninni.

Dæmi um skriftu til að búa til nafnrými

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

Sjálfgefið er, í Ubuntu, að Unbound binary er klemmd af AppArmor prófílnum, sem bannar því að tengjast alls kyns DNSTap innstungum. Þú getur annað hvort eytt þessum prófíl eða slökkt á því:

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

Þessu ætti líklega að bæta við leikbókina. Það er auðvitað tilvalið að leiðrétta prófílinn og gefa út nauðsynleg réttindi, en ég var of latur.

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

Niðurhal og vinnsla lista

Forskrift til að hlaða niður og vinna úr lista yfir IP tölur
Það hleður niður listanum, summar upp að forskeytinu pfx. Í ekki_bæta við и ekki_taka saman þú getur sagt IP-tölum og netkerfum að sleppa eða ekki draga saman. Ég þurfti þess. undirnet VPS minnar var á blokkunarlistanum 🙂

Það fyndna er að RosKomSvoboda API hindrar beiðnir með sjálfgefnum Python notendaumboðsmanni. Svo virðist sem handritsbarnið hafi náð því. Þess vegna breytum við því í Ognelis.

Enn sem komið er virkar það aðeins með IPv4. hlutur IPv6 er lítill, en það verður auðvelt að laga það. Nema þú þurfir líka að nota 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)

Handrit til að uppfæra
Ég keyri það á kórónuna einu sinni á dag, kannski er þess virði að draga það á 4 tíma fresti. þetta er að mínu mati endurnýjunartíminn sem RKN krefst af veitendum. Auk þess eru þeir með einhverja aðra ofurbrýna lokun, sem gæti komið hraðar.

Gerir eftirfarandi:

  • Keyrir fyrstu forskriftina og uppfærir lista yfir leiðir (rkn_routes.list) fyrir FUGL
  • Endurhlaða BIRD
  • Uppfærir og hreinsar upp lista yfir lén fyrir dnstap-bgp
  • Endurhlaða 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

Þau voru skrifuð án mikillar umhugsunar, svo ef þú sérð eitthvað sem má bæta - farðu í það.

Uppsetning viðskiptavinar

Hér mun ég gefa dæmi fyrir Linux beinar, en í tilfelli Mikrotik / Cisco ætti það að vera enn auðveldara.

Fyrst settum við upp 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;
}

Þannig munum við samstilla leiðirnar sem berast frá BGP við kjarnaleiðartöfluna númer 222.

Eftir það er nóg að biðja kjarnann að skoða þennan plötu áður en þú horfir á sjálfgefna:

# 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

Allt, það er eftir að stilla DHCP á leiðinni til að dreifa IP-tölu göng þjónsins sem DNS, og kerfið er tilbúið.

Takmarkanir

Með núverandi reiknirit til að búa til og vinna úr lista yfir lén, felur það m.a. youtube.com og CDN þess.

Og þetta leiðir til þess að öll myndbönd fara í gegnum VPN, sem getur stíflað alla rásina. Kannski er það þess virði að setja saman lista yfir vinsælar útilokanir á lénum sem loka á RKN í bili, þörmunum er þunnt. Og slepptu þeim við þáttun.

Ályktun

Aðferðin sem lýst er gerir þér kleift að komast framhjá næstum hvers kyns lokun sem veitendur innleiða nú.

Í grundvallaratriðum dnstap-bgp hægt að nota í hvaða öðrum tilgangi sem er þar sem þörf er á einhverri umferðarstjórnun út frá léninu. Hafðu bara í huga að á okkar tímum geta þúsund síður hangið á sömu IP tölunni (á bak við suma Cloudflare, til dæmis), þannig að þessi aðferð hefur frekar litla nákvæmni.

En fyrir þarfir þess að fara framhjá læsingum er þetta alveg nóg.

Viðbætur, breytingar, dráttarbeiðnir - velkomin!

Heimild: www.habr.com

Bæta við athugasemd