Bypass ILV Blocking mat DNSTap a BGP

Bypass ILV Blocking mat DNSTap a BGP

D'Thema ass zimlech geschloen, ech weess. Zum Beispill gëtt et eng grouss en Artikel, awer nëmmen den IP-Deel vun der Blocklëscht gëtt do ugesinn. Mir wäerten och Domainen addéieren.

Wéinst der Tatsaach, datt d'Geriichter an d'RKN alles riets a lénks blockéieren, an d'Provider probéieren schwéier net ënner de Geldstrofen ze falen, déi vum Revizorro erausginn sinn, sinn déi assoziéiert Verloschter aus der Spär zimlech grouss. An ënnert de "gesetzlech" blockéierte Siten ginn et vill nëtzlech (Moien, Rutracker)

Ech liewen ausserhalb vun der Juridictioun vum RKN, awer meng Elteren, Famill a Frënn sinn doheem bliwwen. Also gouf decidéiert mat engem einfache Wee ze kommen fir Leit wäit vun IT fir d'Blockéierung ëmzegoen, am léifsten ouni hir Participatioun iwwerhaapt.

An dëser Note wäert ech net déi elementar Reseau Saachen an Schrëtt beschreiwen, mee ech wäert déi allgemeng Prinzipien beschreiwen, wéi dëst Schema ëmgesat ginn. Also Wëssen iwwer wéi d'Netzwierk am Allgemengen funktionnéiert an am Linux besonnesch ass e Must-Have.

Zorte vu Schleisen

Als éischt, loosst eis Erënnerung un dat wat blockéiert gëtt erfrëschen.

Et gi verschidden Aarte vu Spären am entlaaschte XML vum RKN:

  • IP
  • Domain Numm
  • URL

Fir d'Einfachheet wäerte mir se op zwee reduzéieren: IP an Domain, a mir wäerten d'Domain einfach aus der URL blockéieren (méi präzis, si hunn dat scho fir eis gemaach).

gutt Leit aus Roskomsvoboda realiséiert eng wonnerbar API, duerch déi mir kënne kréien wat mir brauchen:

Zougang zu blockéierte Siten

Fir dëst ze maachen, brauche mir e puer kleng auslännesch VPS, am léifsten mat onlimitéierten Traffic - et gi vill vun dësen fir 3-5 Dollar. Dir musst et an der noer Ausland huelen, sou datt de Ping net ganz grouss ass, awer nach eng Kéier, berücksichtegt datt d'Internet an d'Geographie net ëmmer zesummekommen. A well et kee SLA fir 5 Dollar ass, ass et besser 2+ Stécker vu verschiddene Fournisseuren fir Feelertoleranz ze huelen.

Als nächst musse mir e verschlësselten Tunnel vum Client Router op de VPS opsetzen. Ech benotzen Wireguard als déi schnellsten an einfachst opzestellen. Ech hunn och Client Router baséiert op Linux (APU 2 oder eppes an OpenWRT). Am Fall vun e puer Mikrotik / Cisco, kënnt Dir d'Protokoller benotzen déi op hinnen verfügbar sinn wéi OpenVPN a GRE-over-IPSEC.

Identifikatioun a Viruleedung vum Traffic vun Interesse

Dir kënnt natierlech all Internetverkéier duerch Auslänner ausschalten. Awer héchstwahrscheinlech wäert d'Geschwindegkeet vun der Aarbecht mat lokalen Inhalter immens leiden. Plus, d'Bandbreedungsfuerderunge op VPS wäerte vill méi héich sinn.

Dofir musse mir iergendwéi Traffic op blockéierte Site verdeelen a se selektiv an den Tunnel riichten. Och wann en Deel vum "extra" Verkéier dohinner kënnt, ass et nach vill besser wéi alles duerch den Tunnel ze fueren.

Fir de Traffic ze managen, benotze mir de BGP Protokoll an annoncéieren Strecken op déi néideg Netzwierker vun eisem VPS un Clienten. Loosst eis BIRD als ee vun de funktionellsten a prakteschste BGP Daemonen huelen.

IP

Mat Blockéierung duerch IP ass alles kloer: mir annoncéieren einfach all blockéiert IPs mat VPS. De Problem ass datt et ongeféier 600 Tausend Subnets an der Lëscht sinn déi d'API zréckkënnt, an déi grouss Majoritéit vun hinnen sinn /32 Hosten. Dës Zuel vu routes kann schwaach Client routers duercherneen bréngen.

Dofir, wann Dir d'Lëscht veraarbecht, gouf decidéiert, bis zum Netz / 24 ze resuméieren wann et 2 oder méi Hosten huet. Sou gouf d'Zuel vun de Strecken op ~100 dausend reduzéiert. D'Skript fir dëst wäert verfollegen.

Domains

Et ass méi komplizéiert an et gi verschidde Weeër. Zum Beispill kënnt Dir en transparenten Squid op all Client Router installéieren an do HTTP-Interceptioun maachen an an den TLS-Handshake kucken fir déi ugefrote URL am éischte Fall an d'Domain vum SNI am zweeten ze kréien.

Mä wéinst all Zorte vun neierfanks TLS1.3 + eSNI, HTTPS Analyse gëtt manner a manner real all Dag. Jo, an d'Infrastruktur op der Client Säit gëtt méi komplizéiert - Dir musst op d'mannst OpenWRT benotzen.

Dofir hunn ech décidéiert de Wee ze huelen fir Äntwerten op DNS Ufroen ze interceptéieren. Och hei fänkt all DNS-iwwer-TLS / HTTPS iwwer Äre Kapp ze hänken, awer mir kënnen (fir elo) dësen Deel um Client kontrolléieren - entweder deaktivéieren oder Ären eegene Server fir DoT / DoH benotzen.

Wéi interceptéiert DNS?

Och hei kënne verschidde Approche ginn.

  • Interceptioun vum DNS-Traffic iwwer PCAP oder NFLOG
    Béid vun dëse Methode vun der Interceptioun ginn am Utility implementéiert sidmat. Awer et gouf net laang ënnerstëtzt an d'Funktionalitéit ass ganz primitiv, also musst Dir nach ëmmer e Gurte schreiwen.
  • Analyse vun DNS Server Logbicher
    Leider sinn déi mir bekannte Recursoren net fäeg Äntwerten ze protokolléieren, awer nëmmen Ufroen. Am Prinzip ass dat logesch, well, am Géigesaz zu Ufroen, Äntwerten eng komplex Struktur hunn an et ass schwéier se an Textform ze schreiwen.
  • DNSTap
    Glécklecherweis ënnerstëtzen vill vun hinnen schonn DNSTap fir dësen Zweck.

Wat ass DNSTap?

Bypass ILV Blocking mat DNSTap a BGP

Et ass e Client-Server Protokoll baséiert op Protokollbuffer a Frame Streams fir vun engem DNS Server op e Sammler vu strukturéierten DNS Ufroen an Äntwerten ze transferéieren. Wesentlech iwwerdréit den DNS-Server Ufro- an Äntwert Metadaten (Typ vu Message, Client/Server IP, etc.) plus komplett DNS Messagen an der (binärer) Form, an där et mat hinnen iwwer d'Netzwierk funktionnéiert.

Et ass wichteg ze verstoen datt am DNSTap Paradigma den DNS Server als Client handelt an de Sammler als Server handelt. Dat ass, den DNS-Server verbënnt mam Sammler, an net vice versa.

Haut gëtt DNSTap an all populäre DNS Server ënnerstëtzt. Awer zum Beispill, BIND a ville Verdeelungen (wéi Ubuntu LTS) gëtt dacks aus iergendengem Grond ouni seng Ënnerstëtzung gebaut. Also loosst eis net mat der Remontéierung beméien, awer e méi liicht a méi séier Rekursor huelen - Unbound.

Wéi fangen ech DNSTap?

et ginn puer количество CLI Utilities fir mat engem Stroum vun DNSTap Eventer ze schaffen, awer si sinn net gëeegent fir eise Problem ze léisen. Dofir hunn ech decidéiert mäin eegene Vëlo ze erfannen deen alles mécht wat néideg ass: dnstap-bgp

Aarbechtsalgorithmus:

  • Wann et lancéiert gëtt, lued et eng Lëscht vun Domainen aus enger Textdatei, invertéiert se (habr.com -> com.habr), schléisst gebrach Linnen, Duplikate an Ënnerdomainen aus (dh wann d'Lëscht habr.com an www.habr.com enthält, et gëtt nëmmen déi éischt gelueden) a baut e Präfix Bam fir eng séier Sich duerch dës Lëscht
  • Als DNSTap Server handelt et op eng Verbindung vun engem DNS Server. Am Prinzip ënnerstëtzt et souwuel UNIX an TCP Sockets, awer d'DNS-Server, déi ech weess, kënnen nëmmen UNIX-Sockets benotzen
  • Entréeën DNSTap Pakete ginn als éischt an eng Protobuf Struktur deserialiséiert, an dann gëtt de binäre DNS Message selwer, an engem vun de Protobuf Felder, op den Niveau vun DNS RR records parséiert.
  • Et gëtt gepréift ob den ugefrote Host (oder säin Elterendomain) an der gelueden Lëscht ass, wann net, gëtt d'Äntwert ignoréiert
  • Nëmmen A/AAAA/CNAME RRs ginn aus der Äntwert ausgewielt an déi entspriechend IPv4/IPv6 Adresse ginn aus hinnen extrahéiert
  • IP Adresse ginn mat konfiguréierbaren TTL cachéiert an un all konfiguréiert BGP Peer ugekënnegt
  • Wann Dir eng Äntwert kritt, déi op eng schonn cache IP weist, gëtt säin TTL aktualiséiert
  • Nodeems den TTL ofgelaf ass, gëtt d'Entrée aus dem Cache an aus BGP Ukënnegung geläscht

Zousätzlech Funktionalitéit:

  • D'Lëscht vun den Domainen vum SIGHUP nei liesen
  • Den Cache synchroniséiert mat anere Fäll ze halen dnstap-bgp iwwer HTTP/JSON
  • Duplizéieren den Cache op der Disk (an der BoltDB Datebank) fir säin Inhalt no engem Restart ze restauréieren
  • Ënnerstëtzung fir op en anert Netzwierk Nummraum ze wiesselen (firwat dat gebraucht gëtt gëtt hei ënnen beschriwwen)
  • IPv6 Ënnerstëtzung

Beschränkungen:

  • IDN Domains ginn nach net ënnerstëtzt
  • Puer BGP Astellunge

Ech gesammelt RPM an DEB Packagen fir einfach Installatioun. Sollt op all relativ rezent OSes mat systemd schaffen. si hu keng Ofhängegkeeten.

De Schema

Also, loosst eis ufänken all d'Komponenten zesummen ze sammelen. Als Resultat sollte mir eppes wéi dës Netzwierktopologie kréien:
Bypass ILV Blocking mat DNSTap a BGP

D'Logik vun der Aarbecht, mengen ech, ass kloer aus dem Diagramm:

  • De Client huet eise Server als DNS konfiguréiert, an DNS Ufroe mussen och iwwer de VPN goen. Dëst ass néideg fir datt de Provider d'DNS-Interceptioun net benotze kann fir ze blockéieren.
  • Wann Dir de Site opmaacht, schéckt de Client eng DNS Ufro wéi "Wat sinn d'IPs vun xxx.org"
  • Ongebonnen léist xxx.org (oder hëlt et aus dem Cache) a schéckt eng Äntwert op de Client "xxx.org huet esou an esou IP", duplizéiert se parallel iwwer DNSTap
  • dnstap-bgp annoncéiert dës Adressen an Vugel iwwer BGP wann d'Domain op der blockéierter Lëscht ass
  • Vugel annoncéiert e Wee op dës IPen mat next-hop self Client Router
  • Spéider Pakete vum Client op dës IPe ginn duerch den Tunnel

Um Server, fir Strecken op blockéiert Siten, benotzen ech eng separat Tabelle bannent BIRD an et schneide sech op kee Fall mam OS.

Dëse Schema huet en Nodeel: den éischte SYN-Paket vum Client, wahrscheinlech, wäert Zäit hunn duerch den Inlandse Provider ze verloossen. de Wee gëtt net direkt ugekënnegt. An hei sinn Optiounen méiglech ofhängeg wéi de Provider d'Blockéierung mécht. Wann hien just de Verkéier fällt, da gëtt et kee Problem. A wann hien et op e puer DPI redirectéiert, da sinn (theoretesch) Spezialeffekter méiglech.

Et ass och méiglech datt d'Clienten d'DNS TTL Wonner net respektéieren, wat de Client verursaache kann e puer verréckte Entréen aus sengem verfaultem Cache ze benotzen anstatt Unbound ze froen.

An der Praxis huet weder déi éischt nach déi zweet Problemer fir mech verursaacht, awer Äre Kilometer kann variéieren.

Server Tuning

Fir einfach ze rullen, hunn ech geschriwwen Roll fir Ansible. Et kann souwuel Serveren a Clienten baséiert op Linux konfiguréieren (entworf fir deb-baséiert Verdeelungen). All Astellunge sinn zimlech offensichtlech a sinn agestallt inventar.yml. Dës Roll ass aus mengem grousse Spillbuch ofgeschnidden, sou datt et Feeler enthält - Zousätzlech Ufroen wëllkomm 🙂

Loosst eis duerch d'Haaptkomponenten goen.

BGP

Zwee BGP-Dämonen um selwechten Host lafen huet e fundamentale Problem: BIRD wëll net BGP-Peering mam localhost (oder all lokalen Interface) opsetzen. Vum Wuert iwwerhaapt. Googelen an Mailinglëschten liesen huet net gehollef, si behaapten datt dëst vum Design ass. Vläicht gëtt et e Wee, awer ech hunn et net fonnt.

Dir kënnt en anere BGP Daemon probéieren, awer ech hunn BIRD gär an et gëtt iwwerall vu mir benotzt, ech wëll net Entitéite produzéieren.

Dofir hunn ech dnstap-bgp am Netznummraum verstoppt, deen duerch d'Veth-Interface mat der Wuerzel verbonnen ass: et ass wéi e Päif, d'Enn vun deenen a verschiddene Nummraim eraushänken. Op jiddereng vun dësen Enn hänke mir privat p2p IP Adressen déi net iwwer de Host goen, sou datt se alles kënne sinn. Dëst ass deeselwechte Mechanismus dee benotzt gëtt fir Zougang zu Prozesser dobannen ze kréien gär vun all Docker an aner Container.

Fir dëst gouf geschriwwen Schrëft an d'Funktionalitéit, déi schonn uewe beschriwwen ass, fir Iech selwer mat den Hoer an en anert Nummraum ze zéien, gouf op dnstap-bgp bäigefüügt. Dofir muss et als Root lafen oder op de CAP_SYS_ADMIN Binär iwwer de Setcap Kommando ausgestallt ginn.

Beispill Skript fir Nummraum ze kreéieren

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

Par défaut, an Ubuntu, gëtt den Unbound Binär vum AppArmor Profil ageklemmt, wat et verbitt fir mat all Zorte vun DNSTap Sockets ze verbannen. Dir kënnt entweder dëse Profil läschen oder desaktivéieren:

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

Dëst sollt wahrscheinlech an d'Spillbuch bäigefüügt ginn. Et ass ideal, natierlech, de Profil ze korrigéieren an déi néideg Rechter erausginn, awer ech war ze faul.

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

Eroflueden an Veraarbechtung Lëschte

Skript fir erofzelueden a veraarbecht eng Lëscht vun IP Adressen
Et lued d'Lëscht erof, summéiert de Präfix pfx. d' dont_add и dont_summarize Dir kënnt d'IPen an d'Netzwierker soen fir ze sprangen oder net ze resuméieren. Ech hunn et gebraucht. de Subnet vu mengem VPS war an der Blocklist 🙂

Déi witzeg Saach ass datt de RosKomSvoboda API Ufroe blockéiert mam Standard Python User Agent. Gesäit aus wéi wann de Skript-Kiddy et kritt huet. Dofir änneren mir et op Ognelis.

Bis elo funktionnéiert et nëmme mat IPv4. den Undeel vun IPv6 ass kleng, awer et wäert einfach sinn ze fixéieren. Ausser Dir musst bird6 och benotzen.

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 fir ze aktualiséieren
Ech lafen et eemol am Dag op der Kroun, vläicht ass et derwäert all 4 Stonnen ze zéien. dëst, menger Meenung no, ass d'Erneierung Period datt d'RKN vun Providere verlaangt. Plus, si hunn e puer aner super-dréngend Blockéierung, déi méi séier kommen.

Maacht déi folgend:

  • Féiert den éischte Skript an aktualiséiert d'Lëscht vun de Strecken (rkn_routes.list) fir BIRD
  • Reload BIRD
  • Updates a botzt d'Lëscht vun den Domainen fir dnstap-bgp
  • Reload 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

Si goufen ouni vill Gedanken geschriwwen, also wann Dir eppes gesitt wat verbessert ka ginn - gitt dofir.

Client Setup

Hei ginn ech Beispiller fir Linux Router, awer am Fall vu Mikrotik / Cisco sollt et nach méi einfach sinn.

Als éischt hu mir BIRD opgeriicht:

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

Also synchroniséiere mir d'Strecken, déi vu BGP kritt goufen, mat der Kernel Routing Tabell Nummer 222.

Duerno ass et genuch fir de Kernel ze froen fir dës Plack ze kucken ier Dir de Standard kuckt:

# 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

Alles bleift fir DHCP um Router ze konfiguréieren fir den Tunnel IP Adress vum Server als DNS ze verdeelen, an de Schema ass prett.

Defiziter

Mam aktuellen Algorithmus fir d'Lëscht vun den Domainen ze generéieren an ze veraarbecht, enthält et ënner anerem, youtube.com a seng CDNs.

An dëst féiert zu der Tatsaach datt all Videoen duerch de VPN goen, wat de ganze Kanal verstoppe kann. Vläicht ass et derwäert eng Lëscht vu populäre Domain-Ausgrenzungen ze kompiléieren déi de RKN fir de Moment blockéieren, d'Darm sinn dënn. A sprangen se beim Parsing.

Konklusioun

Déi beschriwwe Method erlaabt Iech bal all Blockéierung z'entgoen, déi d'Provider aktuell implementéieren.

Haaptsächlech, dnstap-bgp kann fir all aner Zweck benotzt ginn, wou e gewëssen Niveau vun der Verkéierskontroll gebraucht gëtt baséiert op dem Domain Numm. Denkt just drun datt an eiser Zäit dausend Siten op der selwechter IP Adress hänke kënnen (hannert e puer Cloudflare, zum Beispill), sou datt dës Method eng zimlech niddereg Genauegkeet huet.

Awer fir d'Bedierfnesser vum Contournement vu Schleisen ass dëst ganz genuch.

Ergänzunge, Ännerungen, Pull Ufroen - wëllkomm!

Source: will.com

Setzt e Commentaire