DNSTap ve BGP ile ILV engellemesini atlayın

DNSTap ve BGP ile ILV engellemesini atlayın

Konu oldukça yıpranmış biliyorum. Örneğin, harika bir şey var makale, ancak burada engellenenler listesinin yalnızca IP kısmı dikkate alınır. Ayrıca alan adları da ekleyeceğiz.

Mahkemelerin ve RKN'nin sağda ve solda her şeyi bloke etmesi ve sağlayıcıların Revizorro'nun kestiği cezalara düşmemek için yoğun çaba harcaması nedeniyle, engellemeden kaynaklanan kayıplar oldukça büyük. Ve "yasal olarak" engellenen siteler arasında pek çok yararlı site var (merhaba, rutracker)

RKN'nin yetki alanının dışında yaşıyorum ama ailem, akrabalarım ve arkadaşlarım evde kaldı. Bu nedenle, BT'den uzak kişilerin, tercihen onların katılımı olmadan, engellemeyi atlaması için kolay bir yol bulmaya karar verildi.

Bu notta temel ağ olaylarını adım adım anlatmayacağım, ancak bu şemanın nasıl uygulanabileceğine dair genel ilkeleri anlatacağım. Dolayısıyla ağın genel olarak ve özel olarak Linux'ta nasıl çalıştığına dair bilgi sahibi olunması gereken bir şeydir.

kilit türleri

Öncelikle neyin engellendiğine dair hafızamızı tazeleyelim.

RKN'den indirilen XML'de birkaç tür kilit vardır:

  • IP
  • Alan Adı
  • URL

Basit olması açısından, bunları ikiye indireceğiz: IP ve etki alanı ve etki alanını URL'ye göre engellemeden çıkaracağız (daha doğrusu, bunu bizim için zaten yaptılar).

gelen iyi insanlar Roskomsvoboda harika bir şey farkettim API, bu sayede ihtiyacımız olanı alabiliriz:

Engellenen sitelere erişim

Bunu yapmak için, tercihen sınırsız trafiğe sahip bazı küçük yabancı VPS'lere ihtiyacımız var - bunlardan birçoğu 3-5 dolara var. Ping'in çok büyük olmaması için yakın yurt dışına almanız gerekiyor ancak yine de İnternet ve coğrafyanın her zaman örtüşmediğini hesaba katmalısınız. Ve 5 dolarlık SLA olmadığından, hata toleransı için farklı sağlayıcılardan 2'den fazla parça almak daha iyidir.

Daha sonra istemci yönlendiricisinden VPS'ye şifreli bir tünel kurmamız gerekiyor. Kurulumu en hızlı ve en kolayı olarak Wireguard'ı kullanıyorum. Ayrıca Linux tabanlı istemci yönlendiricilerim var (APU2 veya OpenWRT'deki bir şey). Bazı Mikrotik / Cisco durumunda, OpenVPN ve GRE-over-IPSEC gibi üzerlerinde bulunan protokolleri kullanabilirsiniz.

İlgilenilen trafiğin tanımlanması ve yönlendirilmesi

Elbette yabancı ülkelerden geçen tüm İnternet trafiğini kapatabilirsiniz. Ancak büyük olasılıkla yerel içerikle çalışma hızı bundan büyük ölçüde zarar görecektir. Ayrıca VPS'deki bant genişliği gereksinimleri çok daha yüksek olacaktır.

Bu nedenle trafiği bir şekilde engellenen sitelere ayırmamız ve onu seçici olarak tünele yönlendirmemiz gerekecek. "Ekstra" trafiğin bir kısmı oraya ulaşsa bile, yine de her şeyi tünelden geçirmekten çok daha iyidir.

Trafiği yönetmek için BGP protokolünü kullanacağız ve gerekli ağlara giden yolları VPS'mizden istemcilere duyuracağız. BIRD'i en işlevsel ve kullanışlı BGP programlarından biri olarak ele alalım.

IP

IP ile engellemede her şey açıktır: engellenen tüm IP'leri VPS ile duyuruyoruz. Sorun şu ki, API'nin döndürdüğü listede yaklaşık 600 bin alt ağ var ve bunların büyük çoğunluğu /32 ana bilgisayarlardan oluşuyor. Bu sayıdaki rotalar zayıf istemci yönlendiricilerinin kafasını karıştırabilir.

Bu nedenle liste işlenirken ağın 24 veya daha fazla ana bilgisayarı varsa / 2'e kadar özetlenmesine karar verildi. Böylece güzergah sayısı ~100 bine düşürüldü. Bunun için komut dosyası takip edecektir.

Etki

Daha karmaşıktır ve birkaç yolu vardır. Örneğin, her istemci yönlendiricisine şeffaf bir Squid yükleyebilir ve orada HTTP müdahalesi yapabilir ve ilk durumda istenen URL'yi ve ikinci durumda SNI'dan etki alanını elde etmek için TLS anlaşmasına göz atabilirsiniz.

Ancak her türlü yeni çıkan TLS1.3 + eSNI nedeniyle, HTTPS analizi her geçen gün daha az gerçek hale geliyor. Evet ve müşteri tarafındaki altyapı daha karmaşık hale geliyor - en azından OpenWRT kullanmanız gerekecek.

Bu nedenle DNS isteklerine verilen yanıtları yakalama yolunu seçmeye karar verdim. Burada da herhangi bir TLS üzerinden DNS / HTTPS başınızın üzerinde gezinmeye başlar, ancak (şimdilik) istemcideki bu kısmı kontrol edebiliriz - ya devre dışı bırakır ya da DoT / DoH için kendi sunucunuzu kullanırız.

DNS nasıl ele geçirilir?

Burada da çeşitli yaklaşımlar olabilir.

  • PCAP veya NFLOG aracılığıyla DNS trafiğinin kesilmesi
    Bu müdahale yöntemlerinin her ikisi de kamu hizmetinde uygulanmaktadır. sidmat. Ancak uzun süredir desteklenmiyor ve işlevsellik çok ilkel olduğundan, bunun için yine de bir koşum takımı yazmanız gerekiyor.
  • DNS sunucusu günlüklerinin analizi
    Ne yazık ki, bildiğim yineleyiciler yanıtları kaydedemiyor, yalnızca istekleri kaydedebiliyor. Prensip olarak bu mantıklıdır, çünkü isteklerden farklı olarak yanıtlar karmaşık bir yapıya sahiptir ve bunları metin biçiminde yazmak zordur.
  • DNSTap
    Neyse ki birçoğu bu amaçla DNSTap'i zaten destekliyor.

DNSTap nedir?

DNSTap ve BGP ile ILV engellemesini atlayın

Bir DNS sunucusundan yapılandırılmış DNS sorguları ve yanıtlarının toplayıcısına aktarım için Protokol Tamponlarına ve Çerçeve Akışlarına dayalı bir istemci-sunucu protokolüdür. Temel olarak, DNS sunucusu sorgu ve yanıt meta verilerini (mesaj türü, istemci/sunucu IP'si vb.) artı tam DNS mesajlarını ağ üzerinden onlarla birlikte çalıştığı (ikili) biçimde iletir.

DNSTap paradigmasında DNS sunucusunun istemci, toplayıcının da sunucu gibi davrandığını anlamak önemlidir. Yani, DNS sunucusu toplayıcıya bağlanır ve bunun tersi mümkün değildir.

Bugün DNSTap tüm popüler DNS sunucularında desteklenmektedir. Ancak, örneğin birçok dağıtımdaki BIND (Ubuntu LTS gibi) genellikle bir nedenden dolayı desteği olmadan oluşturulur. Öyleyse yeniden birleştirmeyle uğraşmayalım, daha hafif ve daha hızlı bir yineleyici alalım - Sınırsız.

DNSTap nasıl yakalanır?

Var bazı sayı DNSTap olay akışıyla çalışmak için CLI yardımcı programları vardır, ancak bunlar sorunumuzu çözmeye uygun değildir. Bu nedenle gerekli olan her şeyi yapacak kendi bisikletimi icat etmeye karar verdim: dnstap-bgp

İş algoritması:

  • Başlatıldığında, bir metin dosyasından alan adlarının bir listesini yükler, bunları ters çevirir (habr.com -> com.habr), kesikli satırları, kopyaları ve alt alan adlarını hariç tutar (örn. listede habr.com ve www.habr.com varsa, yalnızca ilki yüklenecektir) ve bu listede hızlı arama yapmak için bir önek ağacı oluşturur
  • DNSTap sunucusu gibi davranarak bir DNS sunucusundan bağlantı bekler. Prensip olarak hem UNIX hem de TCP yuvalarını destekliyor ancak benim bildiğim DNS sunucuları yalnızca UNIX yuvalarını kullanabiliyor
  • Gelen DNSTap paketleri ilk olarak bir Protobuf yapısında seri durumdan çıkarılır ve ardından Protobuf alanlarından birinde bulunan ikili DNS mesajının kendisi, DNS RR kayıtları düzeyine ayrıştırılır.
  • İstenilen ana bilgisayarın (veya ana etki alanının) yüklenenler listesinde olup olmadığı kontrol edilir, değilse yanıt dikkate alınmaz.
  • Yanıttan yalnızca A/AAAA/CNAME RR'ler seçilir ve karşılık gelen IPv4/IPv6 adresleri bunlardan çıkarılır
  • IP adresleri yapılandırılabilir TTL ile önbelleğe alınır ve yapılandırılmış tüm BGP eşlerine duyurulur
  • Zaten önbelleğe alınmış bir IP'ye işaret eden bir yanıt alındığında, TTL'si güncellenir
  • TTL'nin süresi dolduktan sonra giriş önbellekten ve BGP duyurularından kaldırılır

Ek işlevsellik:

  • SIGHUP tarafından alan adları listesi yeniden okunuyor
  • Önbelleği diğer örneklerle senkronize tutma dnstap-bgp HTTP/JSON aracılığıyla
  • Yeniden başlatmanın ardından içeriğini geri yüklemek için diskteki (BoltDB veritabanındaki) önbelleği çoğaltın
  • Farklı bir ağ ad alanına geçiş desteği (bunun neden gerekli olduğu aşağıda açıklanacaktır)
  • IPv6 desteği

Sınırlamalar:

  • IDN alanları henüz desteklenmiyor
  • Birkaç BGP ayarı

biriktirdim RPM ve DEB Kolay kurulum için paketler. Systemd ile nispeten yeni olan tüm işletim sistemlerinde çalışmalıdır. herhangi bir bağımlılıkları yoktur.

düzen

Öyleyse tüm bileşenleri bir araya toplamaya başlayalım. Sonuç olarak şu ağ topolojisine benzer bir şey elde etmeliyiz:
DNSTap ve BGP ile ILV engellemesini atlayın

İşin mantığı sanırım şemadan açıkça anlaşılıyor:

  • İstemcinin sunucumuz DNS olarak yapılandırılmıştır ve DNS sorgularının da VPN üzerinden geçmesi gerekir. Bu, sağlayıcının engellemek için DNS müdahalesini kullanamaması için gereklidir.
  • Siteyi açarken istemci “xxx.org’un IP’leri nedir” gibi bir DNS sorgusu gönderir.
  • bağsız xxx.org'u çözer (veya önbellekten alır) ve istemciye "xxx.org'un şu IP'si var" yanıtını gönderir ve bunu DNSTap aracılığıyla paralel olarak çoğaltır
  • dnstap-bgp bu adresleri şu adreste duyurur: BIRD Alan adı engellenenler listesindeyse BGP aracılığıyla
  • BIRD ile bu IP'lere bir rota tanıtır next-hop self istemci yönlendirici
  • İstemciden bu IP'lere sonraki paketler tünelden geçer

Sunucuda engellenen sitelere giden rotalar için BIRD içinde ayrı bir tablo kullanıyorum ve bu tablo işletim sistemiyle hiçbir şekilde kesişmiyor.

Bu planın bir dezavantajı var: Müşteriden gelen ilk SYN paketinin büyük olasılıkla yerli sağlayıcıdan ayrılmak için zamanı olacak. rota hemen açıklanmadı. Ve burada sağlayıcının engellemeyi nasıl yaptığına bağlı olarak seçenekler mümkündür. Sadece trafiği bırakırsa sorun olmaz. Ve eğer onu bir DPI'ya yönlendirirse, o zaman (teorik olarak) özel efektler mümkündür.

İstemcilerin DNS TTL mucizelerine saygı göstermemesi de mümkündür, bu da istemcinin Unbound'u sormak yerine çürümüş önbelleğindeki bazı eski girdileri kullanmasına neden olabilir.

Pratikte ne birincisi ne de ikincisi benim için sorun yaratmadı, ancak kilometreniz değişebilir.

Sunucu Ayarlama

Yuvarlanma kolaylığı için yazdım Ansible'ın rolü. Hem sunucuları hem de istemcileri Linux tabanlı (deb tabanlı dağıtımlar için tasarlanmıştır) yapılandırabilir. Tüm ayarlar oldukça açıktır ve envanter.yml. Bu rol benim büyük taktik kitabımdan çıkarıldı, dolayısıyla hatalar içerebilir - istekleri çekme hoşgeldin 🙂

Ana bileşenleri inceleyelim.

BGP

Aynı ana bilgisayarda iki BGP arka plan programının çalıştırılmasının temel bir sorunu var: BIRD, localhost (veya herhangi bir yerel arayüz) ile BGP eşlemesini ayarlamak istemiyor. Kesinlikle kelimeden. Google'da araştırma yapmak ve e-posta listelerini okumak işe yaramadı; bunun tasarım gereği olduğunu iddia ediyorlar. Belki bir yolu vardır ama ben bulamadım.

Başka bir BGP arka plan programı deneyebilirsiniz, ancak BIRD'i seviyorum ve benim tarafımdan her yerde kullanılıyor, varlıklar üretmek istemiyorum.

Bu nedenle, dnstap-bgp'yi veth arayüzü aracılığıyla köke bağlanan ağ ad alanının içine sakladım: uçları farklı ad alanlarında çıkıntı yapan bir boruya benziyor. Bu uçların her birine, ana bilgisayarın ötesine geçmeyen özel p2p IP adreslerini asıyoruz, böylece bunlar herhangi bir şey olabilir. Bu, içerideki işlemlere erişmek için kullanılan mekanizmanın aynısıdır. herkes tarafından sevildi Docker ve diğer konteynerler.

Bunun için yazıldı senaryo ve kendinizi saçınızdan başka bir ad alanına sürüklemeye yönelik yukarıda açıklanan işlevsellik dnstap-bgp'ye eklendi. Bu nedenle root olarak çalıştırılması veya setcap komutu aracılığıyla CAP_SYS_ADMIN ikili dosyasına verilmesi gerekir.

Ad alanı oluşturmaya yönelik örnek komut dosyası

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

kuş.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

Varsayılan olarak, Ubuntu'da İlişkisiz ikili dosya, her türlü DNSTap soketine bağlanmasını yasaklayan AppArmor profili tarafından sıkıştırılır. Bu profili silebilir veya devre dışı bırakabilirsiniz:

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

Bu muhtemelen oyun kitabına eklenmelidir. Profili düzeltmek ve gerekli hakları vermek elbette ideal ama ben çok tembeldim.

sınırsız.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

Listeleri indirme ve işleme

IP adresleri listesini indirmek ve işlemek için komut dosyası
Listeyi indirir, öneki özetler pfx. ekleme_ekleme и özetleme IP'lere ve ağlara atlamalarını veya özetlememelerini söyleyebilirsiniz. Ona ihtiyacım vardı. VPS'imin alt ağı engelleme listesindeydi 🙂

Komik olan şey, RosKomSvoboda API'sinin varsayılan Python kullanıcı aracısıyla istekleri engellemesidir. Görünüşe göre senaryo çocuğu anlamış. Bu nedenle onu Ognelis olarak değiştiriyoruz.

Şu ana kadar yalnızca IPv4 ile çalışıyor. IPv6'nın payı azdır ancak düzeltilmesi kolay olacaktır. Bird6'yı da kullanmak zorunda olmadığınız sürece.

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)

Güncellenecek komut dosyası
Günde bir kez taç üzerinde çalıştırıyorum, belki 4 saatte bir çekmeye değer. bence bu, RKN'nin sağlayıcılardan talep ettiği yenileme süresidir. Ayrıca, daha hızlı ulaşabilecek başka süper acil engellemeler de var.

Aşağıdakileri yapar:

  • İlk betiği çalıştırır ve rotaların listesini günceller (rkn_routes.list) KUŞ için
  • BIRD'i yeniden yükle
  • Dnstap-bgp için alan adları listesini günceller ve temizler
  • Dnstap-bgp'yi yeniden yükle

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

Çok fazla düşünmeden yazılmışlardı, bu yüzden geliştirilebilecek bir şey görürseniz devam edin.

İstemci kurulumu

Burada Linux yönlendiriciler için örnekler vereceğim ancak Mikrotik/Cisco söz konusu olduğunda bu daha da kolay olmalı.

İlk önce BIRD'i kurduk:

kuş.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;
}

Böylece BGP'den aldığımız rotaları 222 numaralı çekirdek yönlendirme tablosuyla senkronize edeceğiz.

Bundan sonra, çekirdeğin varsayılan plakaya bakmadan önce bu plakaya bakmasını istemek yeterlidir:

# 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

Her şey, sunucunun tünel IP adresini DNS olarak dağıtmak için yönlendiricideki DHCP'yi yapılandırmaya devam ediyor ve şema hazır.

Dezavantajları:

Etki alanları listesinin oluşturulmasına ve işlenmesine yönelik mevcut algoritma, diğer şeylerin yanı sıra şunları içerir: youtube.com ve CDN'leri.

Bu da tüm videoların VPN üzerinden geçmesine neden olur ve bu da tüm kanalı tıkayabilir. Belki de şimdilik RKN'yi engelleyen popüler alan hariç tutmaların bir listesini derlemeye değer, cesaret zayıf. Ve ayrıştırırken bunları atlayın.

Sonuç

Açıklanan yöntem, sağlayıcıların halihazırda uyguladığı neredeyse tüm engellemeleri atlamanıza olanak tanır.

Prensip olarak, dnstap-bgp alan adına bağlı olarak belirli düzeyde trafik kontrolünün gerekli olduğu başka herhangi bir amaç için kullanılabilir. Günümüzde binlerce sitenin aynı IP adresini (örneğin bazı Cloudflare'in arkasında) takabildiğini, dolayısıyla bu yöntemin oldukça düşük bir doğruluğa sahip olduğunu unutmayın.

Ancak kilitleri atlama ihtiyaçları için bu oldukça yeterli.

Eklemeler, düzenlemeler, çekme istekleri - hoş geldiniz!

Kaynak: habr.com

Yorum ekle