Bypass pamblokiran ILV nganggo DNSTap lan BGP

Bypass pamblokiran ILV nganggo DNSTap lan BGP

Topik iki cukup diantemi munggah, Aku ngerti. Contone, ana gedhe artikel, nanging mung bagean IP saka dhaptar blokir sing dianggep ana. Kita uga bakal nambah domain.

Amarga kasunyatan sing pengadilan lan RKN mblokir kabeh tengen lan kiwa, lan panyedhiya nyoba hard kanggo ora tiba ing denda ditanggepi dening Revizorro, losses gadhah pamblokiran cukup gedhe. Lan ing antarane situs sing diblokir kanthi "sah" ana akeh sing migunani (halo, rutracker)

Aku manggon ing njaba wilayah RKN, nanging wong tuwa, sedulur lan kanca-kanca tetep ing omah. Dadi diputusake nggawe cara sing gampang kanggo wong sing adoh saka IT kanggo ngliwati pamblokiran, luwih becik tanpa partisipasi.

Ing cathetan iki, aku ora bakal njlèntrèhaké bab jaringan dhasar ing langkah-langkah, nanging aku bakal njlèntrèhaké prinsip umum carane rencana iki bisa dipun ginakaken. Dadi kawruh babagan cara kerja jaringan ing umum lan khusus ing Linux kudu diduweni.

Jinis kunci

Pisanan, ayo refresh memori babagan apa sing diblokir.

Ana sawetara jinis kunci ing XML sing dibongkar saka RKN:

  • IP
  • Домен
  • URL

Kanggo kesederhanaan, kita bakal ngurangi dadi loro: IP lan domain, lan kita mung bakal narik metu domain saka pamblokiran dening URL (luwih tepat, padha wis nindakake iki kanggo kita).

wong apik saka Roskomsvoboda temen maujud apik API, liwat kang kita bisa njaluk apa kita kudu:

Akses menyang situs sing diblokir

Kanggo nindakake iki, kita butuh sawetara VPS manca cilik, luwih apik karo lalu lintas tanpa wates - ana akeh iki kanggo 3-5 dolar. Sampeyan kudu njupuk ing cedhak luar negeri supaya ping ora gedhe banget, nanging maneh, njupuk menyang akun sing Internet lan geografi ora tansah pas. Lan wiwit ora ana SLA kanggo 5 dolar, iku luwih apik kanggo njupuk 2+ bêsik saka panyedhiya beda kanggo toleransi fault.

Sabanjure, kita kudu nyiyapake trowongan sing dienkripsi saka router klien menyang VPS. Aku nggunakake Wireguard minangka sing paling cepet lan paling gampang kanggo nyetel. Aku uga duwe router klien adhedhasar Linux (APU2 utawa soko ing OpenWRT). Ing kasus sawetara Mikrotik / Cisco, sampeyan bisa nggunakake protokol sing kasedhiya ing wong-wong mau kaya OpenVPN lan GRE-over-IPSEC.

Identifikasi lan pangalihan lalu lintas kapentingan

Sampeyan bisa, mesthi, mateni kabeh lalu lintas Internet liwat negara manca. Nanging, paling kamungkinan, kacepetan nggarap konten lokal bakal nandhang sangsara banget saka iki. Kajaba iku, syarat bandwidth ing VPS bakal luwih dhuwur.

Mulane, kita kudu piye wae nyedhiyakake lalu lintas menyang situs sing diblokir lan kanthi selektif ngarahake menyang trowongan. Sanajan sawetara lalu lintas "ekstra" tekan ing kana, iku isih luwih apik tinimbang nyopir kabeh liwat trowongan.

Kanggo ngatur lalu lintas, kita bakal nggunakake protokol BGP lan ngumumake rute menyang jaringan sing dibutuhake saka VPS menyang klien. Ayo dadi BIRD minangka salah sawijining daemon BGP sing paling fungsional lan trep.

IP

Kanthi pamblokiran IP, kabeh wis jelas: kita mung ngumumake kabeh IP sing diblokir nganggo VPS. Masalahe yaiku ana udakara 600 ewu subnet ing dhaptar sing ngasilake API, lan sing paling akeh yaiku / 32 host. Jumlah rute iki bisa mbingungake router klien sing lemah.

Mulane, nalika ngolah dhaptar, diputusake kanggo ngringkes nganti jaringan / 24 yen duwe 2 utawa luwih host. Dadi, jumlah rute dikurangi dadi ~100 ewu. Skrip kanggo iki bakal tindakake.

Domain

Iku luwih rumit lan ana sawetara cara. Contone, sampeyan bisa nginstal Cumi-cumi transparan ing saben router klien lan nindakake intersepsi HTTP ing kana lan ngintip menyang jabat tangan TLS kanggo entuk URL sing dijaluk ing kasus pisanan lan domain saka SNI ing kaloro.

Nanging amarga kabeh jinis TLS1.3 + eSNI anyar, analisis HTTPS dadi kurang nyata saben dina. Ya, lan infrastruktur ing sisih klien dadi luwih rumit - sampeyan kudu nggunakake paling ora OpenWRT.

Mulane, aku mutusake kanggo njupuk dalan intercepting respon kanggo pitakon DNS. Ing kene uga, DNS-over-TLS / HTTPS wiwit nglayang ing sirah sampeyan, nanging kita bisa (saiki) ngontrol bagean iki ing klien - bisa mateni utawa nggunakake server sampeyan dhewe kanggo DoT / DoH.

Kepiye carane nyegat DNS?

Ing kene uga bisa uga ana sawetara pendekatan.

  • Interception lalu lintas DNS liwat PCAP utawa NFLOG
    Loro-lorone cara interception iki dileksanakake ing sarana sidmat. Nanging wis suwe ora didhukung lan fungsine primitif banget, mula sampeyan isih kudu nulis sabuk kasebut.
  • Analisis log server DNS
    Sayange, recursors dikenal kanggo kula ora bisa kanggo log respon, nanging mung panjalukan. Ing asas, iki logis, amarga, ora kaya panjalukan, jawaban duwe struktur Komplek lan angel kanggo nulis ing wangun teks.
  • DNSTap
    Untunge, akeh sing wis ndhukung DNSTap kanggo tujuan iki.

Apa DNSTap?

Bypass pamblokiran ILV nganggo DNSTap lan BGP

Iki minangka protokol klien-server adhedhasar Protocol Buffers lan Frame Streams kanggo nransfer saka server DNS menyang kolektor pitakon lan tanggapan DNS terstruktur. Ateges, server DNS ngirim metadata pitakon lan respon (jinis pesen, IP klien / server, lsp.) ditambah pesen DNS lengkap ing wangun (biner) sing bisa digunakake ing jaringan kasebut.

Penting kanggo mangerteni yen ing paradigma DNSTap, server DNS tumindak minangka klien lan kolektor tumindak minangka server. Yaiku, server DNS nyambung menyang kolektor, lan ora kosok balene.

Dina iki DNSTap didhukung ing kabeh server DNS populer. Nanging, contone, BIND ing akeh distribusi (kaya Ubuntu LTS) asring dibangun kanthi alesan tanpa dhukungan. Dadi ayo ora keganggu reassembly, nanging njupuk rekursor korek lan luwih cepet - Unbound.

Kepiye carane nyekel DNSTap?

Ana sawetara jumlah Utilitas CLI kanggo nggarap aliran acara DNSTap, nanging ora cocog kanggo ngrampungake masalah kita. Mulane, aku mutusake kanggo nggawe sepedha dhewe sing bakal nindakake kabeh sing perlu: dnstap-bgp

Algoritma kerja:

  • Nalika diluncurake, ngemot dhaptar domain saka file teks, ngowahi (habr.com -> com.habr), ora kalebu garis rusak, duplikat lan subdomain (yaiku yen dhaptar kasebut ngemot habr.com lan www.habr.com, bakal dimuat mung sing pisanan) lan mbangun wit ater-ater kanggo nggoleki kanthi cepet liwat dhaptar iki
  • Tumindak minangka server DNSTap, ngenteni sambungan saka server DNS. Ing asas, ndhukung loro soket UNIX lan TCP, nanging server DNS aku ngerti mung bisa nggunakake soket UNIX.
  • Paket DNSTap mlebu pisanan deserialized dadi struktur Protobuf, banjur pesen DNS biner dhewe, dumunung ing salah siji lapangan Protobuf, diuraikan menyang tingkat cathetan DNS RR.
  • Dipriksa manawa host sing dijaluk (utawa domain induke) ana ing dhaptar sing dimuat, yen ora, respon ora digatekake
  • Mung A/AAAA/CNAME RR sing dipilih saka respon lan alamat IPv4/IPv6 sing cocog dijupuk saka
  • Alamat IP di-cache nganggo TTL sing bisa dikonfigurasi lan diiklanake menyang kabeh kanca BGP sing dikonfigurasi
  • Nalika nampa respon sing nuduhake IP sing wis di-cache, TTL kasebut dianyari
  • Sawise TTL kadaluwarsa, entri kasebut dibusak saka cache lan saka pengumuman BGP

Fungsi tambahan:

  • Maca maneh dhaptar domain dening SIGHUP
  • Nyelarasake cache karo kasus liyane dnstap-bgp liwat HTTP/JSON
  • Duplikat cache ing disk (ing database BoltDB) kanggo mulihake isine sawise miwiti maneh
  • Dhukungan kanggo ngalih menyang papan jeneng jaringan sing beda (kenapa iki dibutuhake bakal diterangake ing ngisor iki)
  • Dhukungan IPv6

Watesan:

  • Domain IDN durung didhukung
  • Sawetara setelan BGP

Aku nglumpukake RPM lan DEB paket kanggo instalasi gampang. Kudu bisa digunakake ing kabeh OS sing relatif anyar karo systemd. padha ora duwe dependensi.

Skema

Dadi, ayo miwiti ngumpulake kabeh komponen. Akibaté, kita kudu njaluk kaya topologi jaringan iki:
Bypass pamblokiran ILV nganggo DNSTap lan BGP

Logika kerja, aku mikir, jelas saka diagram:

  • Klien wis server kita diatur minangka DNS, lan pitakon DNS uga kudu liwat VPN. Iki perlu supaya panyedhiya ora bisa nggunakake interception DNS kanggo mblokir.
  • Nalika mbukak situs kasebut, klien ngirim pitakon DNS kaya "apa IP xxx.org"
  • diutyuli ngrampungake xxx.org (utawa njupuk saka cache) lan ngirim respon menyang klien "xxx.org duwe IP kasebut lan kaya ngono", duplikat kanthi paralel liwat DNSTap
  • dnstap-bgp ngumumake alamat kasebut ing BIRD liwat BGP yen domain ing dhaftar diblokir
  • BIRD advertises rute menyang IP iki karo next-hop self router klien
  • Paket sakteruse saka klien menyang IP kasebut ngliwati terowongan

Ing server, kanggo rute menyang situs sing diblokir, aku nggunakake tabel sing kapisah ing jero BIRD lan ora intersect karo OS kanthi cara apa wae.

Skema iki nduweni kekurangan: paket SYN pisanan saka klien, paling kamungkinan, bakal duwe wektu kanggo ninggalake liwat panyedhiya domestik. rute ora announced langsung. Lan ing kene opsi bisa gumantung saka cara panyedhiya nindakake pamblokiran. Yen dheweke mung ngeculake lalu lintas, mula ora ana masalah. Lan yen pangalihan menyang sawetara DPI, banjur (teoritis) efek khusus bisa.

Bisa uga klien ora ngurmati keajaiban DNS TTL, sing bisa nyebabake klien nggunakake sawetara entri basi saka cache bosok tinimbang takon Unbound.

Ing laku, ora pisanan utawa kaloro nyebabake masalah kanggo kula, nanging jarak tempuh sampeyan bisa beda-beda.

Server Tuning

Kanggo gampang muter, aku nulis peran kanggo Ansible. Bisa ngatur server lan klien adhedhasar Linux (dirancang kanggo distribusi adhedhasar deb). Kabeh setelan cukup jelas lan disetel persediaan.yml. Peran iki dipotong saka buku dolananku sing gedhe, mula bisa uga ana kesalahan - narik panjalukan sugeng rawuh 🙂

Ayo dadi liwat komponen utama.

BGP

Mlaku loro daemon BGP ing host sing padha duwe masalah dhasar: BIRD ora pengin nyetel BGP peering karo localhost (utawa antarmuka lokal). Saka tembung ing kabeh. Googling lan maca mailing-list ora mbantu, dheweke ngaku manawa iki dirancang. Mbok ana sawetara cara, nanging aku ora nemokake.

Sampeyan bisa nyoba daemon BGP liyane, nanging aku seneng BIRD lan digunakake ing endi wae dening kula, aku ora pengin gawé entitas.

Mulane, aku ndhelikake dnstap-bgp nang spasi jeneng jaringan, kang disambungake menyang ROOT liwat antarmuka veth: iku kaya pipa, ends kang kelet metu ing namespaces beda. Ing saben ujung iki, kita nyumerepi alamat IP p2p pribadi sing ora ngluwihi host, supaya bisa dadi apa wae. Iki minangka mekanisme sing padha digunakake kanggo ngakses proses ing njero tresna dening kabeh Docker lan wadhah liyane.

Kanggo iki ditulis naskah lan fungsi sing wis diterangake ing ndhuwur kanggo nyeret dhewe nganggo rambut menyang papan jeneng liyane ditambahake menyang dnstap-bgp. Amarga iki, kudu mbukak minangka root utawa ditanggepi menyang binar CAP_SYS_ADMIN liwat perintah setcap.

Tuladha skrip kanggo nggawe 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

Kanthi gawan, ing Ubuntu, binar Unbound dijepit dening profil AppArmor, sing nglarang nyambungake menyang kabeh jinis soket DNSTap. Sampeyan bisa mbusak profil iki, utawa mateni:

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

Iki mbokmenawa kudu ditambahake menyang playbook. Iku becik, mesthi, kanggo mbenerake profil lan ngetokake hak sing perlu, nanging aku kesed.

ora kaiket.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

Ngunduh lan ngolah dhaptar

Skrip kanggo ngundhuh lan ngolah dhaptar alamat IP
Iku ngundhuh dhaptar, sums nganti awalan pfx. ing ora_tambah и ora_ngringkes sampeyan bisa ngandhani IP lan jaringan kanggo skip utawa ora ngringkes. Aku butuh. subnet VPSku ana ing daftar blokir 🙂

Sing lucu yaiku RosKomSvoboda API ngalangi panjaluk karo agen pangguna Python standar. Katon kaya script-kiddy entuk. Mulane, kita ngganti menyang Ognelis.

Nganti saiki, mung bisa digunakake karo IPv4. nuduhake IPv6 cilik, nanging bakal gampang kanggo ndandani. Kajaba sampeyan kudu nggunakake bird6 uga.

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 kanggo nganyari
Aku mbukak ing makutha sapisan dina, Mungkin iku worth narik iku saben 4 jam. iki, ing mratelakake panemume, iku wektu nganyari maneh sing RKN mbutuhake saka panyedhiya. Kajaba iku, dheweke duwe pamblokiran super-urgent liyane, sing bisa teka luwih cepet.

Apa ing ngisor iki:

  • Nganggo skrip pisanan lan nganyari dhaptar rute (rkn_routes.list) kanggo BIRD
  • Reload BIRD
  • Nganyari lan ngresiki dhaptar domain kanggo dnstap-bgp
  • Muat ulang 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

Dheweke ditulis tanpa dipikirake, mula yen sampeyan ndeleng apa sing bisa ditambah - goleki.

Setelan klien

Ing kene aku bakal menehi conto kanggo router Linux, nanging ing kasus Mikrotik / Cisco kudu luwih gampang.

Pisanan, kita nyiyapake 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;
}

Mangkono, kita bakal nyinkronake rute sing ditampa saka BGP karo tabel routing kernel nomer 222.

Sawise iku, cukup takon kernel kanggo ndeleng piring iki sadurunge ndeleng 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

Kabeh, iku tetep kanggo ngatur DHCP ing dalan kanggo nyebarake alamat IP trowongan server minangka DNS, lan rencana wis siyap.

Kekurangan

Kanthi algoritma saiki kanggo ngasilake lan ngolah dhaptar domain, kalebu, ing antarane, youtube.com lan CDN sawijining.

Lan iki ndadékaké kasunyatan sing kabeh video bakal liwat VPN, kang bisa clog kabeh saluran. Mbok menawa perlu nyusun dhaptar domain-pengecualian populer sing mblokir RKN kanggo wektu iki, guts tipis. Lan skip nalika parsing.

kesimpulan

Cara sing diterangake ngidini sampeyan ngliwati meh kabeh pamblokiran sing saiki ditindakake panyedhiya.

Ing asas, dnstap-bgp bisa digunakake kanggo maksud apa wae ing ngendi sawetara tingkat kontrol lalu lintas dibutuhake adhedhasar jeneng domain. Elinga yen ing jaman saiki, sewu situs bisa digantung ing alamat IP sing padha (contone, sawetara Cloudflare), mula metode iki nduweni akurasi sing rada kurang.

Nanging kanggo kabutuhan nglewati kunci, iki cukup.

Tambahan, suntingan, panjalukan tarik - welcome!

Source: www.habr.com

Add a comment