Bypass ILV blocking sareng DNSTap sareng BGP

Bypass ILV blocking sareng DNSTap sareng BGP

Topikna lumayan lumayan, kuring terang. Contona, aya alus teuing artikel, tapi ngan bagian IP tina blocklist nu dianggap aya. Urang ogé bakal nambahan domain.

Kusabab kanyataan yén pangadilan sareng RKN ngahalangan sadayana kénca sareng katuhu, sareng panyadia narékahan pikeun henteu digolongkeun dina denda anu dikaluarkeun ku Revizorro, karugian anu aya hubunganana tina pemblokiran cukup ageung. Sareng diantara situs anu "sah" diblokir aya seueur anu mangpaat (halo, rutracker)

Kuring cicing di luar yurisdiksi RKN, tapi kolot, baraya jeung babaturan tetep di tanah air. Janten éta diputuskeun pikeun nyiptakeun cara anu gampang pikeun jalma anu jauh ti IT pikeun ngaliwat blokiran, langkung saé tanpa partisipasina.

Dina catetan ieu, kuring moal ngajelaskeun hal jaringan dasar step by step, tapi bakal ngajelaskeun prinsip umum kumaha skéma ieu bisa dilaksanakeun. Jadi pangaweruh ngeunaan kumaha jaringan jalan sacara umum sarta dina Linux Ubuntu hususna kudu boga.

Jenis konci

Kahiji, hayu urang refresh memori urang ngeunaan naon anu diblokir.

Aya sababaraha jinis konci dina XML anu diunduh tina RKN:

  • IP
  • Домен
  • URL

Pikeun kesederhanaan, urang bakal ngurangan kana dua: IP na domain, sarta ti blocking ku URL urang ngan saukur bakal narik kaluar domain (atawa rada, ieu geus dipigawé pikeun urang).

jalma alus ti Roskomsvoboda dilaksanakeun éndah API, ngaliwatan nu urang bisa meunangkeun naon urang kudu:

Aksés ka situs anu diblokir

Jang ngalampahkeun ieu, urang peryogi sababaraha VPS asing leutik, preferably kalawan lalulintas taya - aya loba di antarana pikeun 3-5 bucks. Anjeun kedah ngagaleuh di caket luar negeri supados pingna henteu luhur teuing, tapi émut deui yén Internét sareng géografi henteu salawasna pas. Sarta saprak euweuh SLA pikeun 5 bucks, éta hadé nyandak 2+ potongan ti panyadia béda pikeun kasabaran sesar.

Salajengna, urang kedah nyetél torowongan énkripsi tina router klien ka VPS. Kuring nganggo Wireguard salaku panggancangna sareng panggampangna pikeun ngonpigurasikeun sabab ... Router klien kuring ogé dumasar kana Linux (APU2 atawa hal on OpenWRT). Dina kasus sababaraha Mikrotik / Cisco, anjeun tiasa nganggo protokol anu aya dina aranjeunna sapertos OpenVPN sareng GRE-over-IPSEC.

Idéntifikasi jeung alihan lalulintas dipikaresep

Anjeun tiasa, tangtosna, ngeureunkeun sadaya lalu lintas Internét tina ka luar negeri. Tapi, paling dipikaresep, laju gawé bareng eusi lokal bakal sangsara greatly tina ieu. Tambih Deui, sarat rubakpita dina VPS bakal leuwih luhur.

Ku alatan éta, urang bakal kudu kumaha bae ngasingkeun lalulintas keur situs diblokir tur selektif jalur kana torowongan. Malah lamun sababaraha lalulintas "tambahan" meunang aya, éta masih leuwih hadé ti nyetir sagalana ngaliwatan torowongan.

Pikeun ngatur lalu lintas, kami bakal nganggo protokol BGP sareng ngiklankeun rute ka jaringan anu diperyogikeun ti VPS kami ka klien. Hayu urang nyandak BIRD salaku daemon BGP, sabab éta salah sahiji anu paling fungsional sareng merenah.

IP

Sadayana jelas sareng pameungpeuk IP: urang ngan saukur ngumumkeun sadaya IP anu diblokir tina VPS. Masalahna nyaeta aya ngeunaan 600 sarébu subnets dina daptar disadiakeun ku API, sarta Lolobana aranjeunna / 32 sarwa. Jumlah rute ieu tiasa ngalieurkeun router klien anu lemah.

Ku alatan éta, nalika ngolah daptar, éta mutuskeun pikeun nyimpulkeun kana jaringan /24 upami aya 2 atanapi langkung host di jerona. Ku kituna, jumlah rute diréduksi jadi ~100 rébu. Skrip pikeun ieu bakal nuturkeun.

Domain

Éta langkung rumit sareng aya sababaraha cara. Contona, anjeun tiasa install cumi transparan dina unggal router klien tur intercept HTTP aya na nénjo dina sasalaman TLS dina urutan pikeun ménta URL dipénta dina kasus nu pertama jeung domain ti SNI dina kadua.

Tapi alatan sagala TLS1.3 + eSNI newfangled, analisis HTTPS janten kirang realistis unggal poe. Sareng infrastruktur di sisi klien janten langkung pajeulit - anjeun kedah nganggo sahenteuna OpenWRT.

Ku alatan éta, kuring mutuskeun nyandak jalur intercepting réspon kana queries DNS. Di dieu, teuing, sagala sorts DNS-over-TLS / HTTPS mimiti hover leuwih huluna urang, tapi urang bisa (pikeun ayeuna) ngadalikeun bagian ieu dina klien nu - boh nganonaktipkeun atawa ngagunakeun server urang sorangan pikeun DoT / DoH.

Kumaha ngabajak DNS?

Aya ogé sababaraha pendekatan di dieu.

  • Intercepting lalulintas DNS via PCAP atanapi NFLOG
    Duanana métode interception ieu dilaksanakeun dina utiliti sidmat. Tapi geus lila teu dirojong sarta pungsionalitasna pisan primitif, jadi Anjeun masih kudu nulis beungkeutan pikeun eta.
  • Analisis log server DNS
    Hanjakal, recursors Kuring nyaho teu nyaho kumaha carana log réspon, tapi ngan requests. Sacara prinsip, ieu logis, sabab, teu saperti requests, réspon boga struktur kompléks jeung hese nulis aranjeunna dina formulir téks.
  • DNSTap
    Kabeneran, seueur di antarana parantos ngadukung DNSTap pikeun tujuan ieu.

Naon DNSTap?

Bypass ILV blocking sareng DNSTap sareng BGP

Ieu mangrupikeun protokol klien-server dumasar kana Protocol Buffers and Frame Streams pikeun nransfer query DNS terstruktur sareng réspon ti server DNS ka kolektor. Intina, server DNS ngirimkeun pamundut sareng metadata réspon (tipe pesen, IP klien / server, jsb) ditambah pesen DNS lengkep dina bentuk (binér) dimana éta tiasa dianggo sareng aranjeunna dina jaringan.

Penting pikeun ngarti yén dina paradigma DNSTap, server DNS bertindak salaku klien, sareng kolektor bertindak salaku server. Hartina, server DNS nyambung ka kolektor, sarta teu sabalikna.

Kiwari, DNSTap dirojong dina sadaya pangladén DNS anu populér. Tapi, contona, BIND dina seueur distribusi (sapertos Ubuntu LTS) sering disusun pikeun sababaraha alesan tanpa dukunganna. Ku kituna hayu urang teu ganggu ku rebuilding, tapi nyandak hiji recursor torek jeung gancang - Unbound.

Kumaha nyekel DNSTap?

aya sababaraha kuantitas Aya utilitas CLI pikeun damel sareng aliran acara DNSTap, tapi aranjeunna henteu cocog pikeun ngarengsekeun masalah urang. Janten kuring mutuskeun pikeun nyiptakeun sapédah kuring sorangan, anu bakal ngalakukeun sagala anu diperyogikeun: dnstap-bgp

Algoritma gawé:

  • Nalika diluncurkeun, éta muka daptar domain tina file téks, ngabalikeunana (habr.com -> com.habr), ngaluarkeun garis rusak, duplikat sareng subdomain (nyaéta upami daptar ngandung habr.com sareng www.habr.com, éta bakal dimuat ngan anu munggaran) sareng ngawangun tangkal awalan pikeun milarian gancang dina daptar ieu
  • Bertindak salaku server DNSTap, éta ngantosan sambungan tina server DNS. Sacara prinsip, éta ngadukung sockets UNIX sareng TCP, tapi server DNS anu kuring terang ngan ukur ngadukung sockets UNIX.
  • Bungkusan DNSTap anu asup mimitina deserialized kana struktur Protobuf, teras pesen DNS binér sorangan, ayana di salah sahiji widang Protobuf, diparse ka tingkat rékaman DNS RR.
  • Éta dipariksa naha host anu dipénta (atanapi domain indungna) aya dina daptar anu dimuat; upami henteu, résponna teu dipaliré
  • Ngan ukur A/AAAA/CNAME RRs anu dipilih tina réspon sareng alamat IPv4/IPv6 anu saluyu dicandak ti aranjeunna.
  • Alamat IP sindangan ku TTL anu tiasa dikonfigurasi sareng diémbarkeun ka sadaya peers BGP anu dikonpigurasi
  • Nalika nampi réspon anu nunjuk ka IP anu tos di-cache, TTL na diropéa
  • Saatos TTL kadaluwarsa, éntri dipiceun tina cache sareng tina pengumuman BGP

Fungsi tambahan:

  • Maca deui daptar domain ku SIGHUP
  • Singkronkeun cache sareng instansi anu sanés dnstap-bgp via HTTP/JSON
  • Duplikat cache dina disk (dina database BoltDB) pikeun mulangkeun eusina saatos balikan deui
  • Rojongan pikeun ngalih ka rohangan ngaran jaringan anu béda (naha ieu diperyogikeun bakal dijelaskeun di handap)
  • rojongan IPv6

larangan:

  • domain IDN teu acan dirojong
  • Sababaraha setélan BGP

Kuring ngumpulkeun RPM sareng DEB bungkusan pikeun instalasi gampang. Kedah dianggo dina sadaya OS anu kawilang anyar sareng systemd, sabab ... aranjeunna teu boga katergantungan.

Skéma

Ku kituna, hayu urang mimitian assembling sakabéh komponén babarengan. Hasilna, urang kedah kéngingkeun sapertos topologi jaringan ieu:
Bypass ILV blocking sareng DNSTap sareng BGP

Logika karya, kuring pikir, jelas tina diagram:

  • Klién parantos ngonpigurasikeun server kami salaku DNS, sareng pamundut DNS ogé kedah ngalangkungan VPN. Ieu diperlukeun ku kituna panyadia teu bisa maké DNS interception pikeun meungpeuk.
  • Nalika klien muka situs wéb, éta ngirimkeun pamundut DNS sapertos "IP naon anu xxx.org gaduh?"
  • Unbound ngabéréskeun xxx.org (atanapi nyandak tina cache) sareng ngirim réspon ka klien "xxx.org gaduh IP sapertos kitu", sakaligus duplikat via DNSTap
  • dnstap-bgp advertises alamat ieu di MANUK via BGP lamun domain aya dina daptar diblokir
  • MANUK advertises jalur ka IP ieu kalawan next-hop self router klien
  • Paket salajengna ti klien ka IP ieu ngalangkungan torowongan

Dina server, kuring nganggo tabel anu misah di jero BIRD pikeun rute ka situs anu diblokir sareng henteu motong sareng OS dina cara naon waé.

Aya kalemahan dina skéma ieu: pakét SYN munggaran ti klien kamungkinan bakal gaduh waktos ngaliwat panyadia domestik sabab Rutena henteu diumumkeun langsung. Sareng di dieu aya pilihan anu mungkin gumantung kana kumaha panyadia ngahalangan. Mun anjeunna ngan pakait lalulintas, teras teu aya masalah. Sareng upami éta alihan ka sababaraha DPI, maka (téoritis) épék khusus mungkin.

Miracles oge mungkin jeung klien teu respecting DNS TTL, nu bisa ngakibatkeun klien nu ngagunakeun sababaraha rékaman luntur tina cache busuk na tinimbang nanyakeun Unbound.

Dina prakték, boh nu kahiji atawa kadua ngabalukarkeun masalah pikeun kuring, tapi mileage Anjeun bisa rupa-rupa.

Server Tuning

Pikeun betah rolling kaluar, abdi wrote peran pikeun Ansible. Éta tiasa ngonpigurasikeun server sareng klien dumasar kana Linux (dirancang pikeun distribusi dumasar-deb). Sadaya setélan cukup atra sareng disetél inventory.yml. Peran ieu dipotong tina playbook ageung kuring, janten tiasa ngandung kasalahan - narik requests wilujeng sumping :)

Hayu urang ngaliwat komponén utama.

BGP

Nalika ngajalankeun dua daemon BGP dina host anu sami, timbul masalah dasar: BIRD henteu hoyong naékkeun BGP peering sareng localhost (atanapi nganggo antarmuka lokal). Tina kecap pancen. Googling sareng maca milis henteu ngabantosan, aranjeunna ngaku yén éta ku desain. Aya sababaraha cara, tapi kuring henteu mendakanana.

Anjeun tiasa nyobian daemon BGP sejen, tapi kuring resep manuk na kuring make eta madhab, Kuring teu hayang nyieun leuwih éntitas.

Ku alatan éta, kuring nyumput dnstap-bgp jero rohangan ngaran jaringan, nu disambungkeun ka akar ngaliwatan panganteur veth: éta kawas pipe a, tungtung nu lengket kaluar dina spasi ngaran béda. Dina unggal tungtung ieu kami ngagantelkeun alamat IP p2p swasta anu henteu ngalangkungan host, supados tiasa nanaon. Ieu mangrupikeun mékanisme anu sami anu dianggo pikeun ngaksés prosés internal karesep sarerea Docker jeung peti sejenna.

Ieu naha ieu ditulis naskah sareng pungsionalitas anu parantos didadarkeun di luhur nyaéta nyered diri anjeun ku rambut ka rohangan ngaran anu sanés ditambah kana dnstap-bgp. Kusabab ieu, éta kedah dijalankeun salaku akar atanapi dipasihkeun ka binér CAP_SYS_ADMIN via paréntah setcap.

Conto naskah pikeun nyieun namespace

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

manuk.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

Sacara standar, dina Ubuntu, binér Unbound dijepit ku profil AppArmor, anu ngalarang éta nyambung ka soket DNSTap. Anjeun tiasa ngahapus profil ieu atanapi nganonaktipkeun:

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

Ieu meureun kudu ditambahkeun kana playbook nu. Éta idéal, tangtosna, pikeun ngabenerkeun profil sareng ngaluarkeun hak anu diperyogikeun, tapi kuring teuing puguh.

teu kabeungkeut.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

Ngundeur tur ngolah daptar

Skrip pikeun ngundeur sareng ngolah daptar alamat IP
Éta ngaunduh daptar, nyimpulkeun kana awalan pfx. The tong_tambahkeun и tong_nyimpulkeun anjeun tiasa nyarioskeun IP sareng jaringan anu kedah dilewatan atanapi henteu diringkeskeun. Abdi peryogi ieu kusabab ... subnet VPS abdi aya dina daptar blok :)

Anu lucu nyaéta yén RosKomSvoboda API meungpeuk pamundut sareng agén pangguna Python standar. Sigana mah maranéhna meunang naskah kiddy. Kituna, urang ngarobah kana Ognelis.

Pikeun ayeuna éta ngan tiasa dianggo sareng IPv4 sabab ... Pangsa IPv6 leutik, tapi bakal gampang dibenerkeun. Iwal mun ogé kudu maké manuk6.

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)

Skrip pikeun apdet
Kuring ngajalankeun éta sakali sapoé ngaliwatan makuta, meureun éta patut ngajalankeun eta sakali unggal 4 jam sabab ... Ieu, dina pamanggih kuring, nyaéta periode pembaharuan anu RKN merlukeun ti panyadia. Tambih Deui, aranjeunna gaduh sababaraha blocking super-urgent séjén anu tiasa sumping langkung gancang.

Ngalakukeun di handap:

  • Jalankeun skrip munggaran sareng ngapdet daptar rute (rkn_routes.list) pikeun MANUK
  • Muat deui BIRD
  • Apdet sarta cleans up daptar domain pikeun dnstap-bgp
  • Muat deui 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

Tembok ditulis tanpa loba pamikiran, jadi lamun ningali hal nu bisa ningkat, balik pikeun eta.

Setélan klien

Di dieu kuring bakal masihan conto pikeun router Linux, tapi dina kasus Mikrotik / Cisco kedah langkung saderhana.

Mimiti, nyetél BIRD:

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

Ku cara ieu urang bakal nyinkronkeun rute anu ditampi ti BGP sareng tabel routing kernel nomer 222.

Saatos ieu, cukup pikeun naroskeun kernel pikeun ningali tabel ieu sateuacan ningali anu standar:

# 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

Éta waé, anu sésana nyaéta ngonpigurasikeun DHCP dina router pikeun nyebarkeun alamat IP torowongan server salaku DNS sareng skéma parantos siap.

shortcomings

Kalayan algoritma ayeuna pikeun ngahasilkeun sareng ngolah daptar domain, éta kalebet, diantarana, youtube.com sareng CDN na.

Sareng ieu nyababkeun kanyataan yén sadaya pidéo bakal dikirim ngaliwatan VPN, anu tiasa ngahambat sadayana saluran. Éta patut nyusun daptar domain pengecualian populér anu RKN masih lemah teuing pikeun diblokir. Jeung skip aranjeunna nalika parsing.

kacindekan

Metoda anu dijelaskeun ngamungkinkeun anjeun ngaliwat ampir sagala blokiran anu ayeuna dilaksanakeun ku panyadia.

Pokokna, dnstap-bgp tiasa dianggo pikeun tujuan anu sanés dimana tingkat manajemén lalu lintas anu tangtu dumasar kana nami domain diperyogikeun. Anjeun ngan perlu tumut kana akun nu kiwari sarébu situs bisa ngagantung dina alamat IP sarua (balik sababaraha Cloudflare, contona), jadi metoda ieu boga akurasi rada low.

Tapi pikeun kaperluan bypassing blocking, ieu cukup.

Tambihan, éditan, pamundut tarik wilujeng sumping!

sumber: www.habr.com

Tambahkeun komentar