ipipou: أكثر من مجرد نفق غير مشفر

ماذا نقول لإله IPv6؟

ipipou: أكثر من مجرد نفق غير مشفر
هذا صحيح، سنقول الشيء نفسه لإله التشفير اليوم.

سنتحدث هنا عن نفق IPv4 غير مشفر، ولكن ليس عن "المصباح الدافئ"، ولكن عن "LED" الحديث. وهناك أيضًا وميض مآخذ خام هنا، والعمل جارٍ مع الحزم الموجودة في مساحة المستخدم.

توجد بروتوكولات نفق N لكل ذوق ولون:

  • أنيق، عصري، شبابي WireGuard
  • متعددة الوظائف، مثل السكاكين السويسرية وOpenVPN وSSH
  • GRE القديم وليس الشر
  • IPIP الأكثر بساطة وسرعة وغير مشفرة تمامًا
  • النامية بنشاط جنيف
  • آخرين كثر.

لكنني مبرمج، لذلك سأزيد N فقط بكسر، وترك تطوير البروتوكولات الحقيقية لمطوري Kommersant.

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

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

  • يتطلب عناوين IP عامة على كلا الجانبين،
  • ولا مصادقة بالنسبة لك.

لذلك، تم إرجاع الباحث عن الكمال إلى الزاوية المظلمة من الجمجمة، أو أينما كان يجلس هناك.

ثم ذات يوم أثناء قراءة المقالات الأنفاق المدعومة محليا في Linux، صادفت FOU (Foo-over-UDP)، أي. أيا كان، ملفوفة في UDP. حتى الآن، يتم دعم IPIP وGUE (تغليف UDP العام) فقط.

"هذه هي الرصاصة الفضية! IPIP البسيط يكفي بالنسبة لي. - اعتقدت.

في الواقع، تبين أن الرصاصة ليست فضية بالكامل. التغليف في UDP يحل المشكلة الأولى - يمكنك الاتصال بالعملاء خلف NAT من الخارج باستخدام اتصال محدد مسبقًا، ولكن هنا يزدهر نصف العيب التالي لـ IPIP في ضوء جديد - يمكن لأي شخص من شبكة خاصة الاختباء خلف المرئي IP العام ومنفذ العميل (في IPIP النقي لا توجد هذه المشكلة).

لحل هذه المشكلة ونصف، ولدت الأداة المساعدة ipipou. إنه يطبق آلية محلية الصنع لمصادقة مضيف بعيد، دون تعطيل تشغيل kernel FOU، والتي ستقوم بمعالجة الحزم بسرعة وكفاءة في مساحة kernel.

نحن لسنا بحاجة إلى النص الخاص بك!

حسنًا، إذا كنت تعرف المنفذ العام وعنوان IP الخاص بالعميل (على سبيل المثال، كل من يقف خلفه لا يذهب إلى أي مكان، ويحاول NAT تعيين منافذ 1 في 1)، فيمكنك إنشاء نفق IPIP-over-FOU باستخدام الأمر الأوامر التالية، دون أي البرامج النصية.

على الخادم:

# Подгрузить модуль ядра FOU
modprobe fou

# Создать IPIP туннель с инкапсуляцией в FOU.
# Модуль ipip подгрузится автоматически.
ip link add name ipipou0 type ipip 
    remote 198.51.100.2 local 203.0.113.1 
    encap fou encap-sport 10000 encap-dport 20001 
    mode ipip dev eth0

# Добавить порт на котором будет слушать FOU для этого туннеля
ip fou add port 10000 ipproto 4 local 203.0.113.1 dev eth0

# Назначить IP адрес туннелю
ip address add 172.28.0.0 peer 172.28.0.1 dev ipipou0

# Поднять туннель
ip link set ipipou0 up

على العميل:

modprobe fou

ip link add name ipipou1 type ipip 
    remote 203.0.113.1 local 192.168.0.2 
    encap fou encap-sport 10001 encap-dport 10000 encap-csum 
    mode ipip dev eth0

# Опции local, peer, peer_port, dev могут не поддерживаться старыми ядрами, можно их опустить.
# peer и peer_port используются для создания соединения сразу при создании FOU-listener-а.
ip fou add port 10001 ipproto 4 local 192.168.0.2 peer 203.0.113.1 peer_port 10000 dev eth0

ip address add 172.28.0.1 peer 172.28.0.0 dev ipipou1

ip link set ipipou1 up

حيث

  • ipipou* - اسم واجهة شبكة النفق المحلية
  • 203.0.113.1 — خادم IP العام
  • 198.51.100.2 — IP العام للعميل
  • 192.168.0.2 - تم تعيين عنوان IP للعميل للواجهة eth0
  • 10001 - منفذ العميل المحلي لـ FOU
  • 20001 - منفذ العميل العام لـ FOU
  • 10000 - منفذ الخادم العام لـ FOU
  • encap-csum - خيار لإضافة المجموع الاختباري لـ UDP إلى حزم UDP المغلفة؛ يمكن استبداله ب noencap-csumناهيك عن أن السلامة يتم التحكم فيها بالفعل من خلال طبقة التغليف الخارجية (أثناء وجود الحزمة داخل النفق)
  • eth0 — الواجهة المحلية التي سيتم ربط نفق ipip بها
  • 172.28.0.1 — IP لواجهة نفق العميل (خاص)
  • 172.28.0.0 - واجهة خادم نفق IP (خاصة)

طالما أن اتصال UDP على قيد الحياة، فسيكون النفق في حالة جيدة، ولكن إذا انقطع، فستكون محظوظًا - إذا ظل IP الخاص بالعميل: المنفذ كما هو - فسيظل حيًا، وإذا تغير - فسوف ينقطع.

أسهل طريقة لإعادة كل شيء إلى الوراء هي إلغاء تحميل وحدات kernel: modprobe -r fou ipip

حتى إذا لم تكن المصادقة مطلوبة، فإن عنوان IP العام والمنفذ الخاص بالعميل لا يكونان معروفين دائمًا وغالبًا ما يكونان غير متوقعين أو متغيرين (اعتمادًا على نوع NAT). إذا أهملت encap-dport على جانب الخادم، لن يعمل النفق، وليس من الذكاء بما يكفي استخدام منفذ الاتصال عن بعد. في هذه الحالة، يمكن أن يساعدك ipipou أيضًا، أو يمكن أن يساعدك WireGuard وآخرون مثله.

كيف يعمل؟

يفتح العميل (الذي يكون عادةً خلف NAT) نفقًا (كما في المثال أعلاه)، ويرسل حزمة مصادقة إلى الخادم بحيث يقوم بتكوين النفق من جانبه. اعتمادًا على الإعدادات، يمكن أن تكون هذه حزمة فارغة (فقط حتى يتمكن الخادم من رؤية عنوان IP العام: منفذ الاتصال)، أو تحتوي على بيانات يمكن للخادم من خلالها التعرف على العميل. يمكن أن تكون البيانات عبارة مرور بسيطة بنص واضح (يتبادر إلى الذهن القياس مع HTTP Basic Auth) أو بيانات مصممة خصيصًا وموقعة بمفتاح خاص (على غرار HTTP Digest Auth فقط أقوى، راجع الوظيفة client_auth في الكود).

على الخادم (الجانب الذي يحتوي على عنوان IP العام)، عندما يبدأ ipipou، يقوم بإنشاء معالج قائمة انتظار nfqueue ويقوم بتكوين netfilter بحيث يتم إرسال الحزم الضرورية حيث يجب أن تكون: الحزم التي تهيئة الاتصال بقائمة انتظار nfqueue، و [تقريبًا] كل الباقي يذهب مباشرة إلى المستمع FOU.

بالنسبة لأولئك الذين لا يعرفون، يعد nfqueue (أو NetfilterQueue) أمرًا خاصًا للهواة الذين لا يعرفون كيفية تطوير وحدات kernel، والتي يسمح لك استخدام netfilter (nftables/iptables) بإعادة توجيه حزم الشبكة إلى مساحة المستخدم ومعالجتها هناك باستخدام الوسائل البدائية في متناول اليد: تعديل (اختياري ) وإعادته إلى النواة، أو تجاهله.

بالنسبة لبعض لغات البرمجة، هناك روابط للعمل مع nfqueue، بالنسبة لباش لم يكن هناك أي ارتباطات (هيه، ليس من المستغرب)، اضطررت إلى استخدام بايثون: يستخدم ipipou NetfilterQueue.

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

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

نظرًا لأن ipipou يعالج فقط الحزم الأولى من الاتصال (وتلك التي تمكنت من التسرب إلى قائمة الانتظار قبل إنشاء الاتصال)، فإن الأداء لا يتأثر تقريبًا.

بمجرد أن يتلقى خادم ipipou حزمة مصادق عليها، يتم إنشاء نفق وتتم بالفعل معالجة جميع الحزم اللاحقة في الاتصال بواسطة kernel لتجاوز nfqueue. إذا فشل الاتصال، فسيتم إرسال الحزمة الأولى من الحزمة التالية إلى قائمة انتظار nfqueue، اعتمادًا على الإعدادات، إذا لم تكن حزمة مع مصادقة، ولكن من آخر IP ومنفذ العميل الذي تم تذكره، فيمكن إما تمريرها على أو التخلص منها. إذا كانت الحزمة التي تمت مصادقتها تأتي من عنوان IP ومنفذ جديدين، تتم إعادة تكوين النفق لاستخدامهما.

يواجه IPIP-over-FOU المعتاد مشكلة أخرى عند العمل مع NAT - من المستحيل إنشاء أنفاق IPIP مغلفة في UDP بنفس IP، لأن وحدات FOU وIPIP معزولة تمامًا عن بعضها البعض. أولئك. لن يتمكن زوج من العملاء خلف نفس عنوان IP العام من الاتصال بنفس الخادم بهذه الطريقة في نفس الوقت. في المستقبل، ربماسيتم حلها على مستوى النواة، لكن هذا غير مؤكد. في غضون ذلك، يمكن حل مشكلات NAT بواسطة NAT - إذا حدث أن زوجًا من عناوين IP مشغول بالفعل بواسطة نفق آخر، فسوف يقوم ipipou بإجراء NAT من عنوان IP عام إلى عنوان IP خاص بديل، فويلا! - يمكنك إنشاء الأنفاق حتى نفاد المنافذ.

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

إذا كان لدى أي شخص أفكار حول كيفية إصلاح ذلك مع ترك الجزء الأكبر من حركة المرور في المركز، فلا تتردد في التحدث.

بالمناسبة، أثبت التغليف في UDP نفسه بشكل جيد للغاية. مقارنةً بالتغليف عبر IP، فهو أكثر استقرارًا وأسرع غالبًا على الرغم من الحمل الإضافي لرأس UDP. ويرجع ذلك إلى حقيقة أن معظم المضيفين على الإنترنت يعملون بشكل جيد فقط مع البروتوكولات الثلاثة الأكثر شعبية: TCP، UDP، ICMP. يمكن للجزء الملموس أن يتجاهل كل شيء آخر تمامًا، أو يعالجه بشكل أبطأ، لأنه مُحسّن فقط لهذه العناصر الثلاثة.

على سبيل المثال، هذا هو السبب وراء إنشاء QUICK، الذي يعتمد عليه HTTP/3، فوق UDP، وليس فوق IP.

حسنًا، ما يكفي من الكلمات، حان الوقت لنرى كيف يتم ذلك في "العالم الحقيقي".

معركة

تستخدم لمحاكاة العالم الحقيقي iperf3. من حيث درجة القرب من الواقع، فهي تقريبًا نفس محاكاة العالم الحقيقي في Minecraft، لكنها ستفعل في الوقت الحالي.

المشاركون في المسابقة:

  • القناة الرئيسية المرجعية
  • بطل هذا المقال هو ipipou
  • OpenVPN مع مصادقة ولكن بدون تشفير
  • OpenVPN في الوضع الشامل
  • WireGuard بدون PresharedKey، مع MTU=1440 (منذ IPv4 فقط)

البيانات الفنية للمهوسين
يتم أخذ المقاييس بالأوامر التالية:

على العميل:

UDP

CPULOG=NAME.udp.cpu.log; sar 10 6 >"$CPULOG" & iperf3 -c SERVER_IP -4 -t 60 -f m -i 10 -B LOCAL_IP -P 2 -u -b 12M; tail -1 "$CPULOG"
# Где "-b 12M" это пропускная способность основного канала, делённая на число потоков "-P", чтобы лишние пакеты не плодить и не портить производительность.

TCP

CPULOG=NAME.tcp.cpu.log; sar 10 6 >"$CPULOG" & iperf3 -c SERVER_IP -4 -t 60 -f m -i 10 -B LOCAL_IP -P 2; tail -1 "$CPULOG"

زمن انتقال ICMP

ping -c 10 SERVER_IP | tail -1

على الخادم (يعمل في وقت واحد مع العميل):

UDP

CPULOG=NAME.udp.cpu.log; sar 10 6 >"$CPULOG" & iperf3 -s -i 10 -f m -1; tail -1 "$CPULOG"

TCP

CPULOG=NAME.tcp.cpu.log; sar 10 6 >"$CPULOG" & iperf3 -s -i 10 -f m -1; tail -1 "$CPULOG"

تكوين النفق

ipipou
الخادم
/etc/ipipou/server.conf:

server
number 0
fou-dev eth0
fou-local-port 10000
tunl-ip 172.28.0.0
auth-remote-pubkey-b64 eQYNhD/Xwl6Zaq+z3QXDzNI77x8CEKqY1n5kt9bKeEI=
auth-secret topsecret
auth-lifetime 3600
reply-on-auth-ok
verb 3

systemctl start ipipou@server

زبون
/etc/ipipou/client.conf:

client
number 0
fou-local @eth0
fou-remote SERVER_IP:10000
tunl-ip 172.28.0.1
# pubkey of auth-key-b64: eQYNhD/Xwl6Zaq+z3QXDzNI77x8CEKqY1n5kt9bKeEI=
auth-key-b64 RuBZkT23na2Q4QH1xfmZCfRgSgPt5s362UPAFbecTso=
auth-secret topsecret
keepalive 27
verb 3

systemctl start ipipou@client

openvpn (بدون تشفير، مع مصادقة)
الخادم

openvpn --genkey --secret ovpn.key  # Затем надо передать ovpn.key клиенту
openvpn --dev tun1 --local SERVER_IP --port 2000 --ifconfig 172.16.17.1 172.16.17.2 --cipher none --auth SHA1 --ncp-disable --secret ovpn.key

زبون

openvpn --dev tun1 --local LOCAL_IP --remote SERVER_IP --port 2000 --ifconfig 172.16.17.2 172.16.17.1 --cipher none --auth SHA1 --ncp-disable --secret ovpn.key

openvpn (مع التشفير، والمصادقة، عبر UDP، كل شيء كما هو متوقع)
تكوين باستخدام إدارة openvpn

حارس سلكي
الخادم
/etc/wireguard/server.conf:

[Interface]
Address=172.31.192.1/18
ListenPort=51820
PrivateKey=aMAG31yjt85zsVC5hn5jMskuFdF8C/LFSRYnhRGSKUQ=
MTU=1440

[Peer]
PublicKey=LyhhEIjVQPVmr/sJNdSRqTjxibsfDZ15sDuhvAQ3hVM=
AllowedIPs=172.31.192.2/32

systemctl start wg-quick@server

زبون
/etc/wireguard/client.conf:

[Interface]
Address=172.31.192.2/18
PrivateKey=uCluH7q2Hip5lLRSsVHc38nGKUGpZIUwGO/7k+6Ye3I=
MTU=1440

[Peer]
PublicKey=DjJRmGvhl6DWuSf1fldxNRBvqa701c0Sc7OpRr4gPXk=
AllowedIPs=172.31.192.1/32
Endpoint=SERVER_IP:51820

systemctl start wg-quick@client

النتائج

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

proto bandwidth[Mbps] CPU_idle_client[%] CPU_idle_server[%]
# 20 Mbps канал с микрокомпьютера (4 core) до VPS (1 core) через Атлантику
# pure
UDP 20.4      99.80 93.34
TCP 19.2      99.67 96.68
ICMP latency min/avg/max/mdev = 198.838/198.997/199.360/0.372 ms
# ipipou
UDP 19.8      98.45 99.47
TCP 18.8      99.56 96.75
ICMP latency min/avg/max/mdev = 199.562/208.919/220.222/7.905 ms
# openvpn0 (auth only, no encryption)
UDP 19.3      99.89 72.90
TCP 16.1      95.95 88.46
ICMP latency min/avg/max/mdev = 191.631/193.538/198.724/2.520 ms
# openvpn (full encryption, auth, etc)
UDP 19.6      99.75 72.35
TCP 17.0      94.47 87.99
ICMP latency min/avg/max/mdev = 202.168/202.377/202.900/0.451 ms
# wireguard
UDP 19.3      91.60 94.78
TCP 17.2      96.76 92.87
ICMP latency min/avg/max/mdev = 217.925/223.601/230.696/3.266 ms

## около-1Gbps канал между VPS Европы и США (1 core)
# pure
UDP 729      73.40 39.93
TCP 363      96.95 90.40
ICMP latency min/avg/max/mdev = 106.867/106.994/107.126/0.066 ms
# ipipou
UDP 714      63.10 23.53
TCP 431      95.65 64.56
ICMP latency min/avg/max/mdev = 107.444/107.523/107.648/0.058 ms
# openvpn0 (auth only, no encryption)
UDP 193      17.51  1.62
TCP  12      95.45 92.80
ICMP latency min/avg/max/mdev = 107.191/107.334/107.559/0.116 ms
# wireguard
UDP 629      22.26  2.62
TCP 198      77.40 55.98
ICMP latency min/avg/max/mdev = 107.616/107.788/108.038/0.128 ms

قناة 20 ميجابت في الثانية

ipipou: أكثر من مجرد نفق غير مشفر

ipipou: أكثر من مجرد نفق غير مشفر

قناة لكل 1 جيجابت في الثانية متفائلة

ipipou: أكثر من مجرد نفق غير مشفر

ipipou: أكثر من مجرد نفق غير مشفر

في جميع الحالات، أداء ipipou قريب جدًا من القناة الأساسية، وهو أمر رائع!

تصرف نفق openvpn غير المشفر بشكل غريب جدًا في كلتا الحالتين.

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

نرجو أن يكون IPv6 وNetPrickle معنا!

المصدر: www.habr.com

إضافة تعليق