تجاوز تأمين ILV مع DNSTap و BGP


الموضوع جميل من الصورة ، وأنا أعلم. على سبيل المثال ، هناك مقال ممتاز ، ولكن فقط جزء IP من قائمة الحظر يعتبر هناك. سنضيف أيضا المجالات.


نظرًا لحقيقة أن المحاكم و ILV تسد كل شيء إلى اليمين واليسار ، ويحاول مقدمو الخدمات جاهدة عدم الوقوع في الغرامات الصادرة عن "Revizorro" - الخسائر المرتبطة بالأقفال كبيرة جدًا. نعم ، ومن بين المواقع "المحظورة قانونًا" هناك العديد من المواقع المفيدة (مرحبًا ، rutracker)


أعيش خارج نطاق اختصاص ILV ، لكن والدي وأقاربي وأصدقائي ظلوا في المنزل. لذلك تقرر التوصل إلى طريقة لتجاوز الأقفال السهلة لمن بعيدون عن تكنولوجيا المعلومات ، ويفضل أن يكون ذلك دون مشاركتهم.


في هذه المقالة ، لن أصف أشياء الشبكة الأساسية في خطوات ، لكنني أصف المبادئ العامة لكيفية تنفيذ هذا المخطط. لذا فإن معرفة كيفية عمل الشبكة بشكل عام وفي نظام Linux بشكل خاص أمر لا بد منه.


أنواع الأقفال


أولاً ، دعونا نجدد ما تم حظره.


هناك عدة أنواع من الأقفال في XML المقسم إلى صفحات من ILV:


  • IP
  • نطاق
  • URL

للبساطة ، سنقوم بتقليلها إلى قسمين: IP والمجال ، وسنقوم ببساطة بسحب المجال من حظر عناوين URL (بشكل أكثر دقة ، لقد قمنا بذلك بالفعل).


لقد قام أهل الخير من Roskomsvoboda بتنفيذ واجهة برمجة تطبيقات رائعة يمكننا من خلالها الحصول على ما نحتاج إليه:



الوصول إلى المواقع المحجوبة


للقيام بذلك ، نحن بحاجة إلى بعض VPS الأجنبية الصغيرة ، ويفضل أن يكون ذلك مع حركة مرور غير محدودة - هناك العديد من 3-5 دولارات. تحتاج إلى أخذها في الخارج القريب حتى لا يكون حجم ping كبيرًا جدًا ، لكن يجب مراعاة أن الإنترنت والجغرافيا لا يتطابقان دائمًا. وبما أنه لا يوجد جيش تحرير السودان لمدة 5 دولارات ، فمن الأفضل أن تأخذ قطعتين + من مزودي خدمات مختلفين لتحمل الأخطاء.


بعد ذلك ، نحتاج إلى تكوين النفق المشفر من جهاز توجيه العميل إلى VPS. يمكنني استخدام Wireguard كأسرع وأسهل لتكوين منذ ذلك الحين لدي أيضًا أجهزة توجيه عميل تستند إلى Linux ( APU2 أو شيء ما على OpenWRT). في حالة بعض Mikrotik / Cisco ، يمكنك استخدام البروتوكولات المتاحة عليها مثل OpenVPN و GRE-over-IPSEC.


تحديد وإعادة توجيه حركة الاهتمام


يمكنك ، بالطبع ، اختتام كل حركة المرور على الإنترنت عبر الخارج. ولكن ، على الأرجح ، ستعاني سرعة العمل مع المحتوى المحلي بشكل كبير من هذا. بالإضافة إلى ذلك ، ستكون متطلبات النطاق الترددي على VPS أعلى بكثير.


لذلك ، سنحتاج إلى تخصيص حركة مرور بطريقة ما للمواقع المحظورة وإرسالها بشكل انتقائي إلى النفق. حتى إذا كان هناك جزء من حركة المرور "الإضافية" ، فإنه لا يزال أفضل بكثير من قيادة كل شيء عبر نفق.


لإدارة حركة المرور ، سوف نستخدم بروتوكول BGP ونعلن عن الطرق المؤدية إلى الشبكات الضرورية من VPS إلى العملاء. بصفتك خفيًا لـ BGP ، دعنا نأخذ BIRD ، كواحد من أكثر الوظائف عملية وملاءمة.


IP


مع حظر IP ، كل شيء واضح: نعلن فقط عن جميع عناوين IP المحظورة باستخدام VPS. المشكلة هي أن هناك حوالي 600 ألف شبكة فرعية في القائمة التي تعطيها API ، والغالبية العظمى منها / 32 مضيفًا. قد يكون هذا العدد من الطرق مربكًا لأجهزة التوجيه العميلة الضعيفة.


لذلك ، تقرر تلخيص الشبكة / 24 عند معالجة القائمة إذا كان هناك مضيفان أو أكثر. وبالتالي ، تم تخفيض عدد الطرق إلى ~ 100 ألف. البرنامج النصي لهذا سيكون التالي.


المجالات


الأمر أكثر تعقيدًا وهناك عدة طرق. على سبيل المثال ، يمكنك وضع Squid شفاف على كل جهاز توجيه عميل والقيام باعتراض HTTP والتصفح في مصافحة TLS من أجل الحصول على عنوان URL المطلوب في الحالة الأولى والمجال من SNI في الثانية.


ولكن نظرًا لجميع تقنيات TLS1.3 + eSNI الجديدة ، أصبح تحليل HTTPS أقل واقعية كل يوم. وأصبحت البنية التحتية في جانب العميل أكثر تعقيدًا - سيتعين عليك استخدام OpenWRT على الأقل.


لذلك ، قررت أن تأخذ مسار اعتراض الردود على استفسارات DNS. هنا أيضًا ، يبدأ أي DNS-over-TLS / HTTPS في الارتفاع فوق رؤوسنا ، لكن يمكننا (في الوقت الحالي) التحكم في هذا الجزء على العميل - إما تعطيله أو استخدام خادمنا الخاص بـ DoT / DoH.


كيفية اعتراض DNS؟


قد يكون هناك أيضا العديد من النهج.


  • اعتراض حركة مرور DNS من خلال PCAP أو NFLOG
    يتم تطبيق كل من أساليب الاعتراض هذه في الأداة المساعدة sidmat . ولكن لم يتم دعمها لفترة طويلة وكانت الوظيفة بدائية للغاية ، لذلك تحتاج إلى كتابة رابط إليها على أي حال.
  • تحليل سجل خادم DNS
    لسوء الحظ ، لا تعرف المصادر التي أعرفها كيفية تسجيل الإجابات ، ولكن الطلبات فقط. من حيث المبدأ ، هذا منطقي ، لأنه على عكس الطلبات ، فإن الإجابات لها بنية معقدة ومن الصعب كتابتها في شكل نصي.
  • DNSTap
    لحسن الحظ ، العديد منهم يدعمون بالفعل DNSTap لهذه الأغراض.

ما هو DNSTap؟



هذا بروتوكول خادم عميل يستند إلى "مخازن بروتوكول" و "تدفقات إطار" للنقل من خادم DNS إلى مجموعة من استعلامات DNS المنظمة واستجاباتها. في الواقع ، ينقل خادم DNS البيانات الوصفية للطلبات والاستجابات (نوع الرسالة ، عنوان IP للعميل / الخادم ، وما إلى ذلك) بالإضافة إلى رسائل DNS الكاملة في النموذج (الثنائي) الذي يعمل به معهم عبر الشبكة.


من المهم أن نفهم أنه في نموذج DNSTap ، يعمل خادم DNS كعميل ، والمجمع كخادم. أي أن خادم DNS يتصل بالجامع ، وليس العكس.


يتم دعم DNSTap اليوم في جميع خوادم DNS الشائعة. ولكن ، على سبيل المثال ، يتم إنشاء BIND في العديد من التوزيعات (مثل Ubuntu LTS) غالبًا لسبب ما دون دعمها. لذلك لن نزعج عملية إعادة الإعمار ، لكننا نأخذ دور العداد أخف وأسرع - غير محدود.


كيفية التقاط DNSTap؟


هناك عدد من الأدوات المساعدة CLI للعمل مع دفق من أحداث DNSTap ، لكنها لا تعمل بشكل جيد لمهمتنا. لذلك قررت أن أخترع دراجتي الخاصة التي ستفعل كل ما يتطلبه الأمر: dnstap-bgp


خوارزمية التشغيل:


  • عند إطلاقه ، يقوم بتحميل قائمة بالنطاقات من ملف نصي ، ويحولها (habr.com -> com.habr) ، ويستبعد الخطوط المكررة والتكرارات والنطاقات الفرعية (أي إذا كان habr.com و www.habr.com في القائمة - سيتم تحميله فقط أول واحد) ويبني شجرة بادئة للبحث السريع في هذه القائمة
  • كخادم DNSTap ، فإنه ينتظر اتصال من خادم DNS. من حيث المبدأ ، يدعم كلا من مآخذ UNIX و TCP ، لكن خوادم DNS التي أعرفها لا يمكنها استخدام مآخذ UNIX
  • يتم إلغاء تسلسل حزم DNSTap الواردة أولاً إلى بنية Protobuf ، ثم يتم تحليل رسالة DNS الثنائية الموجودة في أحد حقول Protobuf إلى مستوى سجلات RR RR
  • يتم التحقق مما إذا كان المضيف المطلوب (أو المجال الأصلي له) في القائمة المحملة ، وإذا لم يكن الأمر كذلك ، فسيتم تجاهل الاستجابة
  • يتم تحديد فقط A / AAAA / CNAME RR من الاستجابة ويتم سحب عناوين IPv4 / IPv6 المقابلة منها
  • يتم تخزين عناوين IP مؤقتًا مع TTLs المخصصة ويتم الإعلان عنها لجميع أقران 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؟"
  • يقوم Unbound بحل xxx.org (أو يأخذها من ذاكرة التخزين المؤقت) ويرسل استجابة إلى العميل "xxx.org لديه مثل هذه IPs وما شابه ذلك" ، مع تكرارها بالتوازي من خلال DNSTap
  • تعلن dnstap-bgp هذه العناوين في BIRD بواسطة BGP إذا كان المجال في قائمة المحظورة
  • تعلن شركة BIRD عن توجيهها إلى عناوين IP هذه من next-hop self جهاز التوجيه next-hop self التوجيه العميل
  • تمر الحزم اللاحقة من العميل إلى عناوين IP هذه عبر النفق

على الخادم ، بالنسبة للطرق إلى المواقع المحجوبة ، لدي جدول منفصل داخل BIRD ولا يتقاطع مع نظام التشغيل.


هناك عيب في هذا المخطط: من المرجح أن تتاح لأول حزمة SYN من العميل الوقت لمغادرة المزود المحلي منذ لم يتم الإعلان عن الطريق على الفور. وهنا تكون الخيارات ممكنة اعتمادًا على كيفية قيام المزود بعمل القفل. إذا كان يسقط حركة المرور فقط ، فلا توجد مشاكل. وإذا كان يعيد توجيهه إلى بعض DPI ، فمن الممكن (نظريا) المؤثرات الخاصة.


المعجزات ممكنة أيضًا مع العملاء الذين لا يتابعون DNS TTL ، مما قد يؤدي إلى استخدام العميل بعض الإدخالات القديمة من ذاكرة التخزين المؤقت الفاسدة بدلاً من طلب Unbound.


في الممارسة العملية ، لم تسبب لي المشاكل الأولى أو الثانية ، ولكن قد تختلف المسافة المقطوعة.


إعداد الخادم


لسهولة المتداول ، كتبت دورًا لـ Ansible . يمكنه تكوين كل من الخوادم والعملاء المعتمدين على Linux (مصمم للتوزيعات المستندة إلى deb). جميع الإعدادات واضحة تمامًا ويتم ضبطها في الجرد . تم قطع هذا الدور عن كتاب اللعب الكبير الخاص بي ، لذا فقد يحتوي على أخطاء - نرحب بطلبات السحب :)


دعنا نذهب من خلال المكونات الرئيسية.


BGP


عند بدء تشغيل شياطين BGP على نفس المضيف ، تنشأ مشكلة أساسية: BIRD لا يريد رفع نظير BGP مع مضيف محلي (أو مع أي واجهة محلية). من الكلمة على الإطلاق. لم يساعد غوغل وقراءة القوائم البريدية ، يدعون أنه حسب التصميم. ربما هناك طريقة ما ، لكنني لم أجدها.


يمكنك تجربة برنامج آخر لـ BGP ، لكني أحب BIRD ويتم استخدامه في كل مكان معي ، لا أريد إنتاج كيانات.


لذلك ، اختبأت dnstap-bgp داخل مساحة اسم الشبكة ، التي تتصل بالجذر عبر واجهة veth: إنها تشبه الأنابيب التي تنتهي نهاياتها في مساحة اسم مختلفة. على كل من هذه الغايات ، نقوم بتعليق عناوين IP p2p الخاصة التي لا تذهب خارج المضيف ، بحيث يمكن أن تكون موجودة. هذه هي نفس الآلية التي يتم استخدامها للوصول إلى العمليات داخل حوض السفن المحبوب والحاويات الأخرى.


لهذا الغرض ، تمت كتابة البرنامج النصي وفي dnstap-bgp تمت إضافة الوظيفة الموضحة أعلاه لسحب نفسه من الشعر إلى مساحة اسم أخرى. لهذا السبب ، يجب تشغيله كجذر أو إرجاعه إلى ملف CAP_SYS_ADMIN الثنائي عبر أمر setcap.


مثال البرنامج النصي لإنشاء مساحة الاسم
 #!/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


بشكل افتراضي ، في Ubuntu ، يتم تثبيت الثنائي غير المنضم بواسطة ملف تعريف AppArmor ، مما يمنعه من الاتصال بأي مآخذ DNSTap هناك. يمكنك إما إزالة ملف التعريف هذا أو تعطيله:


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

ربما ينبغي أن يضاف هذا إلى قواعد اللعبة التي تمارسها. من المثالي ، بالطبع ، تصحيح الملف الشخصي وإصدار الحقوق اللازمة ، لكنني كنت كسولًا جدًا.


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 و dont_summarize ، يمكنك إخبار IP والشبكات بتخطي أو عدم تلخيصها. أنا في حاجة إليها ل كانت شبكة VPS الخاصة بي في قائمة الحظر :)


الطريف في الأمر هو أن واجهة برمجة تطبيقات RosKomSvoboda تحظر الطلبات باستخدام وكيل مستخدم Python الافتراضي. يبدو وكأنه سيندي حصلت عليه. لذلك ، نغيره إلى Firelis.


حتى الآن ، يعمل فقط مع 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 ساعات ، لأنه هذا ، في رأيي ، هو فترة التحديث التي يتطلبها ILV من مقدمي الخدمات. بالإضافة إلى ذلك ، هناك بعض الأقفال العاجلة الإضافية التي يمكن أن تطير بشكل أسرع.


هل ما يلي:


  • يقوم بتشغيل البرنامج النصي الأول وتحديث قائمة rkn_routes.list ( 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 

لقد تم كتابتها دون تفكير كثير ، لذا إذا رأيت ما يمكن تحسينه ، فابحث عنه.


إعداد العميل


سأقدم هنا أمثلة لأجهزة توجيه Linux ، ولكن في حالة 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 مع جدول توجيه kernel رقم 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 و CDNs فيه.


وهذا يؤدي إلى حقيقة أن جميع مقاطع الفيديو سوف تمر عبر VPN ، والتي يمكن أن تسد القناة بأكملها. ربما يستحق الأمر تجميع قائمة من مجالات الاستثناء الشائعة المحظورة في ILV في الوقت الحالي. وتخطيهم أثناء التحليل.


استنتاج


تسمح لك الطريقة الموصوفة بتجاوز أي أقفال تقريبًا يقوم المزودون بتنفيذها حاليًا.


من حيث المبدأ ، يمكن استخدام dnstap-bgp لأي غرض آخر حيث يلزم مستوى معين من التحكم في حركة المرور بناءً على اسم المجال. فقط ضع في اعتبارك أنه في الوقت الحالي ، يمكن أن يتم تعليق ألف موقع على نفس عنوان IP (بالنسبة لبعض Cloudflare ، على سبيل المثال) ، وبالتالي فإن هذه الطريقة تتميز بالدقة المنخفضة.


ولكن لاحتياجات تجاوز الأقفال ، وهذا يكفي تماما.


الإضافات والتعديلات وسحب المهام موضع ترحيب!

Source: https://habr.com/ru/post/ar467547/


All Articles