Aihe on aika päihtynyt, tiedän. Esimerkiksi siellä on hieno artikkeli, mutta vain estolistan IP-osa otetaan huomioon. Lisäämme myös verkkotunnuksia.
Koska tuomioistuimet ja RKN estävät kaiken oikealle ja vasemmalle, ja palveluntarjoajat yrittävät kovasti olla joutumatta Revizorron myöntämien sakkojen alle, estoon liittyvät tappiot ovat melko suuria. Ja "laillisesti" estettyjen sivustojen joukossa on monia hyödyllisiä (hei, rutracker)
Asun RKN:n toimialueen ulkopuolella, mutta vanhempani, sukulaiseni ja ystäväni jäivät kotiin. Niinpä päätettiin keksiä helppo tapa IT:stä kaukana oleville ihmisille ohittaa esto, mieluiten ilman heidän osallistumistaan.
Tässä muistiinpanossa en kuvaile verkon perusasioita vaiheittain, vaan kuvaan yleiset periaatteet, miten tämä malli voidaan toteuttaa. Joten tieto verkon toiminnasta yleensä ja erityisesti Linuxissa on pakollinen.
Lukkojen tyypit
Virkistetään ensin muistimme siitä, mikä on estetty.
RKN:stä lataamattomassa XML:ssä on useita eri tyyppejä:
IP
Verkkotunnuksen nimi
URL
Yksinkertaisuuden vuoksi vähennämme ne kahteen: IP ja verkkotunnus, ja poistamme verkkotunnuksen URL-osoitteen eston (tarkemmin sanottuna he ovat jo tehneet tämän puolestamme).
hyviä ihmisiä Roskomsvoboda tajusi upeaa API, jonka kautta saamme tarvitsemamme:
Tätä varten tarvitsemme pienen ulkomaisen VPS:n, mieluiten rajoittamattomalla liikenteellä - näitä on monia 3-5 taalalla. Sinun on otettava se lähiulkomailta, jotta ping ei ole kovin suuri, mutta ota jälleen huomioon, että Internet ja maantiede eivät aina ole samat. Ja koska 5 taalalla ei ole SLA:ta, on parempi ottaa 2+ kappaletta eri toimittajilta vikasietoisuuden vuoksi.
Seuraavaksi meidän on määritettävä salattu tunneli asiakasreitittimestä VPS:ään. Käytän Wireguardia nopeimmin ja helpoimmin asennettavana. Minulla on myös Linux-pohjaisia asiakasreitittimiä (APU2 tai jotain OpenWRT:ssä). Joidenkin Mikrotik / Ciscon tapauksessa voit käyttää niissä saatavilla olevia protokollia, kuten OpenVPN ja GRE-over-IPSEC.
Kiinnostavan liikenteen tunnistaminen ja uudelleenohjaus
Voit tietysti sammuttaa kaiken Internet-liikenteen ulkomailla. Mutta todennäköisesti paikallisen sisällön kanssa työskentelyn nopeus kärsii tästä suuresti. Lisäksi VPS:n kaistanleveysvaatimukset ovat paljon korkeammat.
Siksi meidän on jotenkin kohdennettava liikenne estettyihin sivustoihin ja ohjattava se valikoivasti tunneliin. Vaikka osa "ylimääräisestä" liikenteestä pääsisi sinne, se on silti paljon parempi kuin ajaa kaikki tunnelin läpi.
Liikenteen hallintaan käytämme BGP-protokollaa ja ilmoitamme reitit tarvittaviin verkkoihin VPS:stä asiakkaillemme. Otetaan BIRD yhdeksi toimivimmista ja kätevimmistä BGP-daemoneista.
IP
IP-estolla kaikki on selvää: ilmoitamme vain kaikista estetyistä IP-osoitteista VPS:llä. Ongelmana on, että luettelossa, jonka API palauttaa, on noin 600 tuhatta aliverkkoa, ja suurin osa niistä on /32-isäntiä. Tämä reittien määrä voi hämmentää heikkoja asiakasreitittimiä.
Siksi luetteloa käsiteltäessä päätettiin tehdä yhteenveto verkkoon / 24 asti, jos sillä on 2 tai useampia isäntiä. Näin reittien määrä väheni ~100 tuhanteen. Tämän käsikirjoitus seuraa.
Verkkotunnukset
Se on monimutkaisempi ja siihen on useita tapoja. Voit esimerkiksi asentaa läpinäkyvän Squidin jokaiseen asiakasreitittimeen ja tehdä siellä HTTP-sieppauksen ja kurkistaa TLS-kättelyyn saadaksesi pyydetyn URL-osoitteen ensimmäisessä tapauksessa ja verkkotunnuksen SNI:ltä toisessa.
Mutta kaikenlaisten uusien TLS1.3 + eSNI:n vuoksi HTTPS-analyysi on yhä vähemmän todellista joka päivä. Kyllä, ja asiakaspuolen infrastruktuurista on tulossa monimutkaisempi - sinun on käytettävä vähintään OpenWRT: tä.
Siksi päätin ottaa polun siepata vastaukset DNS-pyyntöihin. Myös täällä DNS-over-TLS / HTTPS alkaa leijua pään päällä, mutta voimme (toistaiseksi) hallita tätä osaa asiakkaalla - joko poistaa sen käytöstä tai käyttää omaa palvelinta DoT / DoH: lle.
Kuinka siepata DNS?
Tässäkin voi olla useita lähestymistapoja.
DNS-liikenteen sieppaus PCAP:n tai NFLOGin kautta
Molemmat näistä sieppausmenetelmistä on otettu käyttöön apuohjelmassa sidmat. Mutta sitä ei ole tuettu pitkään aikaan ja toiminnallisuus on erittäin alkeellista, joten sinun on silti kirjoitettava siihen valjaat.
DNS-palvelimen lokien analyysi
Valitettavasti tuntemani rekursorit eivät pysty kirjaamaan vastauksia, vaan vain pyyntöjä. Periaatteessa tämä on loogista, koska toisin kuin pyynnöillä, vastauksilla on monimutkainen rakenne ja niitä on vaikea kirjoittaa tekstimuotoon.
DNSTap
Onneksi monet heistä tukevat jo DNSTapia tähän tarkoitukseen.
Mikä on DNSTap?
Se on protokollapuskureihin ja kehysvirtoihin perustuva asiakas-palvelin-protokolla, jolla siirretään DNS-palvelimelta jäsenneltyjen DNS-kyselyjen ja -vastausten kerääjää. Pohjimmiltaan DNS-palvelin lähettää kyselyn ja vastauksen metatiedot (viestin tyyppi, asiakkaan/palvelimen IP-osoite jne.) sekä täydelliset DNS-viestit (binäärimuodossa), jossa se toimii niiden kanssa verkon yli.
On tärkeää ymmärtää, että DNSTap-paradigmassa DNS-palvelin toimii asiakkaana ja kerääjä toimii palvelimena. Eli DNS-palvelin muodostaa yhteyden kerääjään, ei päinvastoin.
Nykyään DNSTap on tuettu kaikissa suosituissa DNS-palvelimissa. Mutta esimerkiksi BIND monissa jakeluissa (kuten Ubuntu LTS) on usein rakennettu jostain syystä ilman sen tukea. Joten älkäämme vaivautuko kokoamiseen, vaan otamme kevyemmän ja nopeamman rekursorin - Sitoutumaton.
Kuinka saada DNSTap kiinni?
On jonkin verrannumero CLI-apuohjelmat DNSTap-tapahtumavirran kanssa työskentelemiseen, mutta ne eivät sovellu ongelmamme ratkaisemiseen. Siksi päätin keksiä oman polkupyöräni, joka tekee kaiken tarvittavan: dnstap-bgp
Työn algoritmi:
Kun se käynnistetään, se lataa luettelon verkkotunnuksista tekstitiedostosta, kääntää ne (habr.com -> com.habr), sulkee pois katkoviivat, kaksoiskappaleet ja aliverkkotunnukset (eli jos luettelo sisältää habr.com ja www.habr.com, se ladataan vain ensimmäisen) ja rakentaa etuliitepuun nopeaa hakua varten tässä luettelossa
Se toimii DNSTap-palvelimena ja odottaa yhteyttä DNS-palvelimelta. Periaatteessa se tukee sekä UNIX- että TCP-pistokkeita, mutta tuntemani DNS-palvelimet voivat käyttää vain UNIX-pistokkeita
Saapuvat DNSTap-paketit sarjoitetaan ensin Protobuf-rakenteeseen ja sitten itse binääri DNS-viesti, joka sijaitsee yhdessä Protobuf-kentistä, jäsennetään DNS RR -tietueiden tasolle.
Tarkistetaan, onko pyydetty isäntä (tai sen pääverkkotunnus) latausluettelossa, jos ei, vastaus jätetään huomioimatta
Vain A/AAAA/CNAME RR:t valitaan vastauksesta ja vastaavat IPv4/IPv6-osoitteet poimitaan niistä.
IP-osoitteet tallennetaan välimuistiin konfiguroitavalla TTL:llä ja mainostetaan kaikille määritetyille BGP-vertaisyrityksille
Kun vastaanotetaan vastaus, joka osoittaa jo välimuistissa olevaan IP-osoitteeseen, sen TTL päivitetään
Kun TTL vanhenee, merkintä poistetaan välimuistista ja BGP-ilmoituksista
Lisätoiminnot:
SIGHUP lukee verkkotunnusluettelon uudelleen
Välimuistin pitäminen synkronoituna muiden esiintymien kanssa dnstap-bgp HTTP/JSONin kautta
Kopioi välimuisti levyllä (BoltDB-tietokannassa) palauttaaksesi sen sisällön uudelleenkäynnistyksen jälkeen
Tuki vaihtamiselle toiseen verkon nimiavaruuteen (miksi sitä tarvitaan, kuvataan alla)
IPv6 tuki
rajoituksia:
IDN-verkkotunnuksia ei vielä tueta
Vähän BGP-asetuksia
keräsin RPM ja DEB paketit helppoa asennusta varten. Pitäisi toimia kaikissa suhteellisen uusissa käyttöjärjestelmissä, joissa on systemd. heillä ei ole riippuvuuksia.
ohjelma
Joten aloitetaan kaikkien komponenttien kokoaminen yhteen. Tämän seurauksena meidän pitäisi saada jotain tämänkaltaista verkkotopologiaa:
Työn logiikka on mielestäni selkeä kaaviosta:
Asiakkaalla on palvelimemme määritetty DNS:ksi, ja myös DNS-kyselyiden on mentävä VPN:n yli. Tämä on välttämätöntä, jotta palveluntarjoaja ei voi käyttää DNS-sieppausta estämään.
Kun avaat sivuston, asiakas lähettää DNS-kyselyn, kuten "mitä ovat xxx.orgin IP-osoitteet"
sitomaton ratkaisee xxx.org:n (tai ottaa sen välimuistista) ja lähettää vastauksen asiakkaalle "xxx.orgilla on sellainen ja sellainen IP-osoite", monistamalla sen rinnakkain DNSTapin kautta
dnstap-bgp ilmoittaa nämä osoitteet LINTU BGP:n kautta, jos verkkotunnus on estettyjen luettelossa
LINTU mainostaa reittiä näihin IP-osoitteisiin next-hop self asiakasreititin
Myöhemmät paketit asiakkaalta näille IP-osoitteille kulkevat tunnelin läpi
Palvelimella käytän reiteille estetyille sivustoille erillistä taulukkoa BIRD:n sisällä, eikä se leikkaa käyttöjärjestelmän kanssa millään tavalla.
Tällä järjestelmällä on haittapuoli: asiakkaan ensimmäisellä SYN-paketilla on todennäköisesti aikaa lähteä kotimaisen palveluntarjoajan kautta. reittiä ei ilmoiteta heti. Ja tässä vaihtoehdot ovat mahdollisia riippuen siitä, kuinka palveluntarjoaja tekee eston. Jos hän vain pudottaa liikennettä, ei ole ongelmaa. Ja jos hän ohjaa sen johonkin DPI:hen, niin (teoreettisesti) erikoistehosteet ovat mahdollisia.
On myös mahdollista, että asiakkaat eivät kunnioita DNS TTL-ihmeitä, mikä voi saada asiakkaan käyttämään joitain vanhentuneita merkintöjä mätäneestä välimuististaan sen sijaan, että hän kysyisi Sitoutumatonta.
Käytännössä ensimmäinen tai toinen ei aiheuttanut minulle ongelmia, mutta kilometrimääräsi voi vaihdella.
Palvelimen viritys
Rullaamisen helpottamiseksi kirjoitin rooli Ansiblelle. Se voi määrittää sekä palvelimia että asiakkaita, jotka perustuvat Linuxiin (suunniteltu deb-pohjaisiin jakeluihin). Kaikki asetukset ovat melko ilmeisiä ja asetettu inventory.yml. Tämä rooli on leikattu suuresta pelikirjastani, joten se voi sisältää virheitä - vetopyynnöt tervetuloa 🙂
Käydään läpi pääkomponentit.
BGP
Kun ajetaan kahta BGP-daemonia samalla isännällä, syntyy perustavanlaatuinen ongelma: BIRD ei halua aloittaa BGP-liikennettä paikallispalvelimen (tai minkä tahansa paikallisen käyttöliittymän) kanssa. Sanasta ollenkaan. Googlaaminen ja postituslistojen lukeminen ei auttanut, he väittävät, että tämä on suunniteltu. Ehkä on olemassa keino, mutta en löytänyt sitä.
Voit kokeilla toista BGP-demonia, mutta pidän BIRDistä ja käytän sitä kaikkialla, en halua tuottaa kokonaisuuksia.
Siksi piilotin dnsap-bgp:n verkon nimiavaruuden sisään, joka on yhdistetty juuriin veth-rajapinnan kautta: se on kuin putki, jonka päät työntyvät esiin eri nimiavaruuksissa. Kumpaankin näistä päistä ripustamme yksityisiä p2p-IP-osoitteita, jotka eivät ylitä isäntää, joten ne voivat olla mitä tahansa. Tämä on sama mekanismi, jota käytetään pääsyyn sisäisiin prosesseihin kaikkien rakastama Docker ja muut kontit.
Tätä varten se kirjoitettiin käsikirjoitus ja dnstap-bgp:hen lisättiin jo yllä kuvattu toiminto hiuksistasi raahaamiseksi toiseen nimiavaruuteen. Tästä syystä se on suoritettava pääkäyttäjänä tai annettava CAP_SYS_ADMIN-binäärille setcap-komennolla.
Esimerkkikomentosarja nimitilan luomiseen
#!/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
Oletusarvoisesti Ubuntussa Unbound binääri on kiinnitetty AppArmor-profiililla, joka estää sitä muodostamasta yhteyttä kaikenlaisiin DNSTap-pistokkeisiin. Voit joko poistaa tämän profiilin tai poistaa sen käytöstä:
Tämä pitäisi varmaan lisätä pelikirjaan. On tietysti ihanteellista korjata profiilia ja myöntää tarvittavat oikeudet, mutta olin liian laiska.
sitomaton.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
Listojen lataaminen ja käsittely
Komentosarja IP-osoiteluettelon lataamiseen ja käsittelyyn
Se lataa luettelon, summaa etuliitteeksi pfx. Sisään älä_lisää и dont_summarize voit käskeä IP-osoitteet ja verkot ohittamaan tai jättämään yhteenvedon. Tarvitsin sitä. VPS:ni aliverkko oli estoluettelossa 🙂
Hauska asia on, että RosKomSvoboda API estää pyynnöt oletusarvoisella Python-käyttäjäagentilla. Näyttää siltä, että käsikirjoituslapsi ymmärsi sen. Siksi vaihdamme sen Ognelikseksi.
Toistaiseksi se toimii vain IPv4: n kanssa. IPv6:n osuus on pieni, mutta se on helppo korjata. Ellei sinun tarvitse käyttää myös bird6:ta.
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)
Päivitettävä komentosarja
Ajan sen kruunulle kerran päivässä, ehkä kannattaa vetää 4 tunnin välein. Tämä on mielestäni uusimisaika, jonka RKN vaatii palveluntarjoajilta. Lisäksi niillä on muita erittäin kiireellisiä estoja, jotka voivat saapua nopeammin.
Toimii seuraavasti:
Suorittaa ensimmäisen skriptin ja päivittää reittiluettelon (rkn_routes.list) BIRDille
Lataa BIRD uudelleen
Päivittää ja puhdistaa dnsap-bgp:n verkkotunnusluettelon
Lataa dnsap-bgp uudelleen
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
Ne on kirjoitettu ajattelematta, joten jos näet jotain, mitä voidaan parantaa - mene siihen.
Asiakkaan asetukset
Tässä annan esimerkkejä Linux-reitittimistä, mutta Mikrotikin / Ciscon tapauksessa sen pitäisi olla vielä helpompaa.
Ensin määritimme BIRDin:
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;
}
Näin ollen synkronoimme BGP:ltä vastaanotetut reitit ytimen reititystaulukon numero 222 kanssa.
Sen jälkeen riittää, kun pyydät ydintä katsomaan tätä levyä ennen kuin katsot oletuslevyä:
# 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
Kaikki, on vielä määritettävä reitittimen DHCP jakamaan palvelimen tunnelin IP-osoite DNS:nä, ja järjestelmä on valmis.
Rajoitukset
Nykyisellä toimialueluettelon luomis- ja käsittelyalgoritmilla se sisältää mm. youtube.com ja sen CDN:t.
Ja tämä johtaa siihen, että kaikki videot kulkevat VPN:n kautta, mikä voi tukkia koko kanavan. Ehkä kannattaa koota lista suosituista verkkotunnuksista-poissulkemisista, jotka estävät RKN:n toistaiseksi, sisu on ohut. Ja ohita ne jäsennettäessä.
Johtopäätös
Kuvatun menetelmän avulla voit ohittaa lähes kaikki palveluntarjoajien tällä hetkellä toteuttamat estot.
Periaatteessa dnstap-bgp voidaan käyttää mihin tahansa muuhun tarkoitukseen, jossa tarvitaan jonkin verran liikenteenohjausta verkkotunnuksen perusteella. Muista vain, että meidän aikanamme tuhat sivustoa voi roikkua samassa IP-osoitteessa (esimerkiksi jonkin Cloudflaren takana), joten tällä menetelmällä on melko alhainen tarkkuus.