میدونم موضوع خیلی خرابه به عنوان مثال، یک بزرگ وجود دارد مقاله، اما فقط قسمت IP از لیست بلاک در آنجا در نظر گرفته می شود. دامنه ها را نیز اضافه خواهیم کرد.
با توجه به این واقعیت که دادگاه ها و RKN همه چیز را به راست و چپ مسدود می کنند و ارائه دهندگان تلاش زیادی می کنند تا تحت جریمه های صادر شده توسط Revizorro قرار نگیرند، ضررهای مربوط به مسدود کردن بسیار زیاد است. و در بین سایت های مسدود شده "قانونی" موارد مفید زیادی وجود دارد (سلام، rutracker)
من خارج از حوزه قضایی RKN زندگی می کنم، اما والدین، بستگان و دوستانم در خانه ماندند. بنابراین تصمیم گرفته شد که راه آسانی برای دور زدن مسدود کردن افراد دور از فناوری اطلاعات، ترجیحاً بدون مشارکت آنها ارائه شود.
در این یادداشت، موارد اولیه شبکه را به صورت مرحله ای شرح نمی دهم، اما اصول کلی نحوه اجرای این طرح را شرح می دهم. بنابراین آگاهی از نحوه عملکرد شبکه به طور کلی و در لینوکس به طور خاص ضروری است.
انواع قفل
ابتدا بیایید حافظه خود را از مواردی که مسدود شده است تجدید کنیم.
چندین نوع قفل در XML بارگیری نشده از RKN وجود دارد:
IP
Домен
URL
برای سادگی، ما آنها را به دو مورد کاهش می دهیم: IP و دامنه، و به سادگی دامنه را از مسدود شدن با URL خارج می کنیم (به طور دقیق تر، آنها قبلاً این کار را برای ما انجام داده اند).
مردم خوب از روسکومسوبودا متوجه فوق العاده شد API، که از طریق آن می توانیم آنچه را که نیاز داریم بدست آوریم:
برای انجام این کار، به تعدادی VPS خارجی کوچک، ترجیحا با ترافیک نامحدود نیاز داریم - بسیاری از اینها با قیمت 3-5 دلار وجود دارد. شما باید آن را در خارج از کشور نزدیک ببرید تا پینگ خیلی زیاد نباشد، اما باز هم باید در نظر بگیرید که اینترنت و جغرافیا همیشه با هم مطابقت ندارند. و از آنجایی که SLA برای 5 دلار وجود ندارد، بهتر است 2+ قطعه را از ارائه دهندگان مختلف برای تحمل خطا بگیرید.
در مرحله بعد، باید یک تونل رمزگذاری شده از روتر مشتری به VPS راه اندازی کنیم. من از Wireguard به عنوان سریع ترین و آسان ترین راه اندازی استفاده می کنم. من همچنین روترهای مشتری مبتنی بر لینوکس دارم (APU2 یا چیزی در OpenWRT). در مورد برخی از Mikrotik / Cisco، می توانید از پروتکل های موجود در آنها مانند OpenVPN و GRE-over-IPSEC استفاده کنید.
شناسایی و تغییر مسیر ترافیک مورد علاقه
البته می توانید تمام ترافیک اینترنت از طریق کشورهای خارجی را خاموش کنید. اما، به احتمال زیاد، سرعت کار با محتوای محلی از این امر بسیار آسیب خواهد دید. به علاوه، پهنای باند مورد نیاز در VPS بسیار بالاتر خواهد بود.
بنابراین، ما باید به نحوی ترافیک را به سایت های مسدود شده اختصاص دهیم و به طور انتخابی آن را به تونل هدایت کنیم. حتی اگر مقداری از ترافیک «اضافی» به آنجا برسد، باز هم بسیار بهتر از راندن همه چیز از طریق تونل است.
برای مدیریت ترافیک، از پروتکل BGP استفاده می کنیم و مسیرهای شبکه های لازم را از VPS خود به مشتریان اعلام می کنیم. بیایید BIRD را به عنوان یکی از کاربردی ترین و راحت ترین دیمون های BGP در نظر بگیریم.
IP
با مسدود کردن توسط IP، همه چیز واضح است: ما به سادگی تمام IP های مسدود شده را با VPS اعلام می کنیم. مشکل این است که حدود 600 هزار زیر شبکه در لیستی وجود دارد که API آنها را برمی گرداند و اکثریت قریب به اتفاق آن ها هاست /32 هستند. این تعداد مسیر می تواند روترهای ضعیف کلاینت را گیج کند.
بنابراین، هنگام پردازش لیست، تصمیم گرفته شد تا شبکه / 24 در صورت داشتن 2 یا بیشتر میزبان خلاصه شود. بدین ترتیب تعداد مسیرها به 100 هزار مسیر کاهش یافت. فیلمنامه این کار در ادامه خواهد آمد.
دامنه
این پیچیده تر است و راه های مختلفی وجود دارد. به عنوان مثال، میتوانید یک Squid شفاف را روی هر روتر کلاینت نصب کنید و رهگیری HTTP را در آنجا انجام دهید و به Handshake TLS نگاهی بیندازید تا در مورد اول URL درخواستی و در حالت دوم دامنه را از SNI بدست آورید.
اما به دلیل انواع TLS1.3 + eSNI جدید، تحلیل HTTPS هر روز کمتر و کمتر واقعی می شود. بله، و زیرساخت در سمت مشتری پیچیده تر می شود - شما باید حداقل از OpenWRT استفاده کنید.
بنابراین تصمیم گرفتم مسیر رهگیری پاسخ به درخواست های DNS را در پیش بگیرم. در اینجا نیز، هر DNS-over-TLS / HTTPS شروع به شناور شدن بالای سر شما می کند، اما ما (در حال حاضر) می توانیم این بخش را روی کلاینت کنترل کنیم - یا آن را غیرفعال کنیم یا از سرور خود برای DoT / DoH استفاده کنیم.
چگونه DNS را رهگیری کنیم؟
در اینجا نیز ممکن است چندین رویکرد وجود داشته باشد.
رهگیری ترافیک DNS از طریق PCAP یا NFLOG
هر دوی این روش های رهگیری در ابزار کاربردی اجرا می شوند سیدمت. اما مدت زیادی است که پشتیبانی نمی شود و عملکرد آن بسیار ابتدایی است، بنابراین هنوز باید برای آن یک مهار بنویسید.
تجزیه و تحلیل گزارش های سرور DNS
متأسفانه، مکررهای شناخته شده برای من قادر به ثبت پاسخ ها نیستند، بلکه فقط درخواست ها را ثبت می کنند. در اصل، این منطقی است، زیرا برخلاف درخواست ها، پاسخ ها ساختار پیچیده ای دارند و نوشتن آنها به صورت متن دشوار است.
DNSTap
خوشبختانه، بسیاری از آنها قبلاً از DNSTap برای این منظور پشتیبانی می کنند.
DNSTap چیست؟
این یک پروتکل سرویس گیرنده-سرور مبتنی بر بافرهای پروتکل و جریانهای فریم برای انتقال از سرور DNS به جمعآوری پرسشها و پاسخهای DNS ساختاریافته است. اساساً، سرور DNS فراداده پرس و جو و پاسخ (نوع پیام، IP سرویس گیرنده/سرور، و غیره) را به همراه پیام های DNS کامل به شکل (باینری) که در آن با آنها از طریق شبکه کار می کند، منتقل می کند.
درک این نکته مهم است که در پارادایم DNSTap، سرور DNS به عنوان یک مشتری و جمع کننده به عنوان یک سرور عمل می کند. یعنی سرور DNS به جمع کننده متصل می شود و نه برعکس.
امروزه DNSTap در تمام سرورهای DNS محبوب پشتیبانی می شود. اما، برای مثال، BIND در بسیاری از توزیع ها (مانند Ubuntu LTS) اغلب به دلایلی بدون پشتیبانی آن ساخته می شود. پس بیایید با مونتاژ مجدد خود را خسته نکنیم، اما یک بازگشتگر سبکتر و سریعتر انتخاب کنیم - Unbound.
چگونه DNSTap را بگیریم؟
وجود دارد مقداریشماره ابزارهای CLI برای کار با جریانی از رویدادهای DNSTap، اما برای حل مشکل ما مناسب نیستند. بنابراین، تصمیم گرفتم دوچرخه خود را اختراع کنم که هر کاری را که لازم است انجام دهد: dnstap-bgp
الگوریتم کار:
هنگام راهاندازی، فهرستی از دامنهها را از یک فایل متنی بارگیری میکند، آنها را معکوس میکند (habr.com -> com.habr)، خطوط شکسته، موارد تکراری و زیر دامنهها را حذف میکند (به عنوان مثال، اگر لیست حاوی habr.com و www.habr.com باشد، تنها مورد اول بارگذاری می شود) و یک درخت پیشوند برای جستجوی سریع در این لیست می سازد
به عنوان یک سرور DNSTap عمل می کند و منتظر اتصال از یک سرور DNS است. در اصل، از هر دو سوکت UNIX و TCP پشتیبانی می کند، اما سرورهای DNS که من می شناسم فقط می توانند از سوکت های یونیکس استفاده کنند.
بسته های DNSTap ورودی ابتدا در یک ساختار Protobuf deserialized می شوند و سپس خود پیام DNS باینری که در یکی از فیلدهای Protobuf قرار دارد تا سطح رکوردهای DNS RR تجزیه می شود.
بررسی می شود که آیا میزبان درخواستی (یا دامنه اصلی آن) در لیست بارگیری شده است یا خیر، اگر نه، پاسخ نادیده گرفته می شود.
فقط RRهای A/AAAA/CNAME از پاسخ انتخاب میشوند و آدرسهای IPv4/IPv6 مربوطه از آنها استخراج میشوند.
آدرسهای IP با TTL قابل تنظیم ذخیره میشوند و برای همه همتایان BGP پیکربندی شده تبلیغ میشوند.
هنگام دریافت پاسخی که به یک IP از قبل ذخیره شده در حافظه پنهان اشاره می کند، TTL آن به روز می شود
پس از انقضای TTL، ورودی از حافظه پنهان و از اطلاعیه های BGP حذف می شود
عملکرد اضافی:
بازخوانی لیست دامنه ها توسط SIGHUP
همگام نگه داشتن حافظه پنهان با نمونه های دیگر dnstap-bgp از طریق HTTP/JSON
حافظه پنهان روی دیسک (در پایگاه داده BoltDB) را کپی کنید تا محتویات آن پس از راه اندازی مجدد بازیابی شود.
پشتیبانی از جابجایی به فضای نام شبکه دیگر (چرا این مورد نیاز است در زیر توضیح داده خواهد شد)
پشتیبانی از IPv6
محدودیت ها:
دامنه های IDN هنوز پشتیبانی نمی شوند
چند تنظیمات BGP
من جمع آوری کردم RPM و DEB بسته هایی برای نصب آسان باید روی همه سیستمعاملهای نسبتاً جدید با systemd کار کند. هیچ وابستگی ندارند
طرح
بنابراین، اجازه دهید شروع به مونتاژ تمام اجزا با هم کنیم. در نتیجه، باید چیزی شبیه توپولوژی شبکه به دست آوریم:
منطق کار، به نظر من، از نمودار مشخص است:
سرویس گیرنده سرور ما را به عنوان DNS پیکربندی کرده است و پرس و جوهای DNS نیز باید از طریق VPN انجام شوند. این امر ضروری است تا ارائه دهنده نتواند از رهگیری DNS برای مسدود کردن استفاده کند.
هنگام باز کردن سایت، مشتری یک پرس و جوی DNS مانند "IP های xxx.org چیست" ارسال می کند.
رها شده xxx.org را حل می کند (یا آن را از حافظه پنهان می گیرد) و پاسخی را برای مشتری ارسال می کند که «xxx.org چنین IP دارد»، آن را به طور موازی از طریق DNSTap کپی می کند.
dnstap-bgp این آدرس ها را در پرنده اگر دامنه در لیست مسدود شده باشد، از طریق BGP
پرنده یک مسیر به این IP ها را با next-hop self روتر مشتری
بسته های بعدی از مشتری به این IP ها از طریق تونل عبور می کنند
در سرور برای مسیرهای سایت های مسدود شده از یک جدول جداگانه در داخل BIRD استفاده می کنم و به هیچ وجه با سیستم عامل تلاقی نمی کند.
این طرح یک اشکال دارد: اولین بسته SYN از مشتری، به احتمال زیاد، از طریق ارائه دهنده داخلی زمان خواهد داشت. مسیر بلافاصله اعلام نمی شود. و در اینجا بسته به نحوه مسدود کردن ارائه دهنده، گزینه هایی امکان پذیر است. اگر او فقط ترافیک را رها کند، مشکلی وجود ندارد. و اگر او آن را به برخی از DPI هدایت کند، (از لحاظ نظری) جلوه های ویژه امکان پذیر است.
همچنین ممکن است که کلاینتها به معجزات DNS TTL احترام نگذارند، که میتواند باعث شود کلاینت به جای درخواست Unbound از برخی ورودیهای قدیمی از حافظه پنهان پوسیده خود استفاده کند.
در عمل نه اولی و نه دومی مشکلی برای من ایجاد نکرد، اما ممکن است مسافت پیموده شده شما متفاوت باشد.
تنظیم سرور
برای سهولت در چرخیدن نوشتم نقش برای Ansible. این می تواند سرورها و کلاینت ها را بر اساس لینوکس (طراحی شده برای توزیع های مبتنی بر deb) پیکربندی کند. همه تنظیمات کاملا واضح هستند و تنظیم شده اند inventory.yml. این نقش از کتاب بازی بزرگ من بریده شده است، بنابراین ممکن است حاوی خطا باشد - درخواست را بکش خوش آمدید 🙂
بیایید اجزای اصلی را مرور کنیم.
BGP
اجرای دو دیمون BGP روی یک میزبان یک مشکل اساسی دارد: BIRD نمیخواهد همتاسازی BGP را با لوکال هاست (یا هر رابط محلی) تنظیم کند. اصلا از کلمه. گوگل کردن و خواندن لیست های پستی کمکی نکرد، آنها ادعا می کنند که این از روی طراحی است. شاید راهی وجود داشته باشد، اما من آن را پیدا نکردم.
شما می توانید یک شبح BGP دیگر را امتحان کنید، اما من BIRD را دوست دارم و در همه جا توسط من استفاده می شود، من نمی خواهم موجودیت تولید کنم.
بنابراین، dnstap-bgp را در فضای نام شبکه پنهان کردم، که از طریق رابط veth به ریشه متصل است: مانند لوله ای است که انتهای آن در فضای نام های مختلف بیرون می آید. در هر یک از این انتها، آدرسهای IP خصوصی p2p را آویزان میکنیم که فراتر از میزبان نیستند، بنابراین میتوانند هر چیزی باشند. این همان مکانیزمی است که برای دسترسی به فرآیندهای داخل استفاده می شود مورد علاقه همه داکر و سایر کانتینرها.
برای این نوشته شد اسکریپت و عملکردی که قبلا در بالا توضیح داده شد برای کشیدن موهای خود به فضای نام دیگری به dnstap-bgp اضافه شد. به همین دلیل، باید به صورت روت اجرا شود یا از طریق دستور setcap برای باینری CAP_SYS_ADMIN صادر شود.
اسکریپت مثال برای ایجاد فضای نام
#!/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
به طور پیشفرض، در اوبونتو، باینری Unbound توسط نمایه AppArmor بسته میشود، که آن را از اتصال به انواع سوکتهای DNSTap منع میکند. میتوانید این نمایه را حذف کنید یا آن را غیرفعال کنید:
این احتمالاً باید به کتاب بازی اضافه شود. ایده آل است، البته، برای اصلاح مشخصات و صدور حقوق لازم، اما من خیلی تنبل بودم.
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
دانلود و پردازش لیست ها
اسکریپت برای دانلود و پردازش لیستی از آدرس های IP
این لیست را دانلود می کند و به پیشوند خلاصه می شود pfxاست. به dont_add и خلاصه نکن می توانید به آی پی ها و شبکه ها بگویید که از جمع بندی صرف نظر کنند یا خیر. من به آن نیاز داشتم. زیرشبکه VPS من در لیست بلاک بود 🙂
نکته خنده دار این است که RosKomSvoboda API درخواست ها را با عامل پیش فرض کاربر Python مسدود می کند. به نظر می رسد که بچه فیلمنامه آن را فهمیده است. بنابراین، آن را به Ognelis تغییر می دهیم.
تا کنون فقط با IPv4 کار می کند. سهم IPv6 اندک است، اما رفع آن آسان خواهد بود. مگر اینکه مجبور باشید از bird6 هم استفاده کنید.
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)
اسکریپت برای به روز رسانی
من روزی یک بار آن را روی تاج می کشم، شاید ارزش کشیدن آن را هر 4 ساعت یکبار داشته باشد. به نظر من این دوره تمدید است که RKN از ارائه دهندگان می خواهد. بهعلاوه، آنها برخی مسدود کردن فوقالعاده فوری دیگر دارند که ممکن است سریعتر وارد شوند.
موارد زیر را انجام می دهد:
اولین اسکریپت را اجرا می کند و لیست مسیرها را به روز می کند (rkn_routes.list) برای BIRD
BIRD را بارگذاری مجدد کنید
لیست دامنه های dnstap-bgp را به روز می کند و پاک می کند
بارگیری مجدد 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
آنها بدون فکر زیاد نوشته شده اند، بنابراین اگر چیزی را می بینید که می تواند بهبود یابد - آن را دنبال کنید.
راه اندازی مشتری
در اینجا مثال هایی را برای روترهای لینوکس می آورم، اما در مورد Mikrotik / Cisco باید حتی ساده تر باشد.
ابتدا BIRD را راه اندازی کردیم:
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;
}
بنابراین مسیرهای دریافتی از BGP را با جدول مسیریابی هسته شماره 222 همگام خواهیم کرد.
پس از آن، کافی است قبل از مشاهده صفحه پیش فرض، از هسته بخواهید به این صفحه نگاه کند:
# 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
همه چیز، پیکربندی DHCP روی روتر برای توزیع آدرس IP تونل سرور به عنوان DNS باقی مانده است و طرح آماده است.
محدودیت ها
با الگوریتم فعلی برای تولید و پردازش لیست دامنه ها، از جمله موارد دیگر، youtube.com و CDN های آن
و این منجر به این واقعیت می شود که همه ویدیوها از طریق VPN عبور می کنند که می تواند کل کانال را مسدود کند. شاید ارزش آن را داشته باشد که فهرستی از دامنه های محبوب - استثناهایی که RKN را فعلاً مسدود می کنند جمع آوری کنیم. و هنگام تجزیه از آنها بگذرید.
نتیجه
روش توصیف شده به شما امکان می دهد تقریباً هر مسدودی را که ارائه دهندگان در حال حاضر اجرا می کنند دور بزنید.
در اصل، dnstap-bgp می تواند برای هر هدف دیگری که در آن سطحی از کنترل ترافیک بر اساس نام دامنه مورد نیاز است استفاده شود. فقط به خاطر داشته باشید که در زمان ما، هزاران سایت می توانند روی یک آدرس IP (مثلاً در پشت برخی از Cloudflare) قرار بگیرند، بنابراین این روش دقت نسبتاً کمی دارد.
اما برای نیازهای دور زدن قفل ها، این کاملاً کافی است.