Aynen öyle, bugün aynısını şifreleme tanrısına da söyleyeceğiz.
Burada şifrelenmemiş bir IPv4 tünelinden bahsedeceğiz, ancak "sıcak lambalı" bir tünelden değil, modern bir "LED" tünelinden bahsedeceğiz. Ayrıca burada yanıp sönen ham soketler de var ve kullanıcı alanındaki paketlerle ilgili çalışmalar sürüyor.
Her zevke ve renge uygun N tünelleme protokolü vardır:
Ama ben bir programcıyım, bu yüzden N'yi yalnızca bir miktar artıracağım ve gerçek protokollerin geliştirilmesini Kommersant geliştiricilerine bırakacağım.
Doğmamış birinde projeŞu an yaptığım şey NAT'ın arkasındaki hostlara dışarıdan ulaşmak. Bunun için yetişkin kriptografisine sahip protokoller kullandığımda, bunun serçeleri toptan fırlatmaya benzediği hissinden kurtulamadım. Çünkü tünel çoğunlukla yalnızca NAT-e'de delik açmak için kullanılıyor, dahili trafik de genellikle şifreleniyor, ancak yine de HTTPS'de boğuluyorlar.
Çeşitli tünel protokollerini araştırırken, içimdeki mükemmeliyetçinin dikkati minimum ek yük nedeniyle tekrar tekrar IPIP'e çekildi. Ancak görevlerim açısından bir buçuk önemli dezavantajı var:
her iki tarafta da genel IP'ler gerektirir,
ve sizin için kimlik doğrulama yok.
Bu nedenle mükemmeliyetçi, kafatasının karanlık köşesine veya nerede oturuyorsa oraya geri sürülür.
Ve sonra bir gün, konuyla ilgili makaleleri okurken yerel olarak desteklenen tüneller Linux'ta FOU (UDP üzerinden Foo) ile karşılaştım, yani. her neyse, UDP'ye sarılmış. Şu ana kadar yalnızca IPIP ve GUE (Genel UDP Kapsülleme) desteklenmektedir.
“İşte gümüş kurşun! Basit bir IPIP benim için yeterli.” - Düşündüm.
Aslında merminin tamamen gümüş olmadığı ortaya çıktı. UDP'de kapsülleme ilk sorunu çözer - NAT'ın arkasındaki istemcilere önceden belirlenmiş bir bağlantıyı kullanarak dışarıdan bağlanabilirsiniz, ancak burada IPIP'in bir sonraki dezavantajının yarısı yeni bir ışıkta çiçek açar - özel bir ağdaki herkes görünenin arkasına saklanabilir genel IP ve istemci bağlantı noktası (saf IPIP'de bu sorun mevcut değildir).
Bu bir buçuk sorunu çözmek için yardımcı program doğdu ipipou. Çekirdek alanındaki paketleri hızlı ve verimli bir şekilde işleyecek olan çekirdek FOU'nun çalışmasını kesintiye uğratmadan uzak bir ana bilgisayarın kimliğini doğrulamak için ev yapımı bir mekanizma uygular.
Senaryonuza ihtiyacımız yok!
Tamam, istemcinin genel bağlantı noktasını ve IP'sini biliyorsanız (örneğin, arkasındaki herkes hiçbir yere gitmez, NAT bağlantı noktalarını 1'i 1 arada eşleştirmeye çalışır), FOU üzerinden IPIP tüneli oluşturabilirsiniz. herhangi bir komut dosyası olmadan komutları takip etmek.
sunucuda:
# Подгрузить модуль ядра 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
istemcide:
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
nerede
ipipou* — yerel tünel ağ arayüzünün adı
203.0.113.1 — genel IP sunucusu
198.51.100.2 — istemcinin genel IP'si
192.168.0.2 — eth0 arayüzüne atanan istemci IP'si
10001 — FOU için yerel istemci bağlantı noktası
20001 - FOU için genel istemci bağlantı noktası
10000 - FOU için genel sunucu bağlantı noktası
encap-csum — kapsüllenmiş UDP paketlerine UDP sağlama toplamı ekleme seçeneği; ile değiştirilebilir noencap-csumAyrıca bütünlük zaten dış kapsülleme katmanı tarafından kontrol ediliyor (paket tünelin içindeyken)
UDP bağlantısı canlı olduğu sürece tünel çalışır durumda olacaktır, ancak kesilirse şanslısınız - eğer istemcinin IP: bağlantı noktası aynı kalırsa - yaşayacak, değişirse - kopacaktır.
Her şeyi geri döndürmenin en kolay yolu çekirdek modüllerini boşaltmak: modprobe -r fou ipip
Kimlik doğrulama gerekmese bile, istemcinin genel IP'si ve bağlantı noktası her zaman bilinmez ve genellikle tahmin edilemez veya değişkendir (NAT türüne bağlı olarak). Eğer ihmal ederseniz encap-dport sunucu tarafında tünel çalışmayacak, uzak bağlantı portunu alacak kadar akıllı değil. Bu durumda ipipou da yardımcı olabilir veya WireGuard ve onun gibi diğerleri size yardımcı olabilir.
Nasıl çalışır?
İstemci (genellikle NAT'ın arkasındadır) bir tünel açar (yukarıdaki örnekte olduğu gibi) ve sunucuya bir kimlik doğrulama paketi göndererek tüneli kendi tarafında yapılandırır. Ayarlara bağlı olarak bu, boş bir paket (sunucunun genel IP: bağlantı portunu görebilmesi için) veya sunucunun istemciyi tanımlayabileceği verileri içeren bir paket olabilir. Veriler, açık metin halinde basit bir parola (akla HTTP Temel Kimlik Doğrulaması benzetmesi geliyor) veya özel bir anahtarla imzalanmış özel olarak tasarlanmış veriler (HTTP Digest Auth'a benzer, yalnızca daha güçlü, bkz. işlev) olabilir. client_auth kodda).
Sunucuda (genel IP'nin olduğu tarafta), ipipou başladığında, bir nfqueue kuyruk işleyicisi oluşturur ve netfilter'ı gerekli paketlerin olması gereken yere gönderileceği şekilde yapılandırır: nfqueue kuyruğuna bağlantıyı başlatan paketler ve [neredeyse] geri kalan her şey doğrudan dinleyici FOU'ya gider.
Bilmeyenler için, nfqueue (veya NetfilterQueue), çekirdek modüllerini nasıl geliştireceğini bilmeyen amatörler için özel bir şeydir; netfilter (nftables/iptables) kullanarak ağ paketlerini kullanıcı alanına yeniden yönlendirmenize ve bunları orada işlemenize olanak tanır. ilkel olmanın anlamı şudur: değiştirin (isteğe bağlı) ve onu çekirdeğe geri verin veya atın.
Bazı programlama dilleri için nfqueue ile çalışmaya yönelik bağlamalar vardır, bash için ise hiçbiri yoktu (heh, şaşırtıcı değil), python kullanmak zorunda kaldım: ipipou kullanır Netfilter Sırası.
Performans kritik değilse, bu şeyi kullanarak oldukça düşük düzeydeki paketlerle çalışmak için kendi mantığınızı nispeten hızlı ve kolay bir şekilde oluşturabilirsiniz, örneğin deneysel veri aktarım protokolleri oluşturabilir veya standart dışı davranışa sahip yerel ve uzak hizmetleri trolleyebilirsiniz.
Ham soketler nfqueue ile el ele çalışır; örneğin, tünel zaten yapılandırılmışsa ve FOU istenen bağlantı noktasını dinliyorsa, aynı bağlantı noktasından her zamanki gibi paket gönderemezsiniz - meşgul, ancak Rastgele oluşturulmuş bir paketi ham bir soket kullanarak doğrudan ağ arayüzüne alıp gönderebilirsiniz, ancak böyle bir paketin oluşturulması biraz daha fazla müdahale gerektirecektir. İpipou'da kimlik doğrulamalı paketler bu şekilde oluşturulur.
ipipou yalnızca bağlantıdan gelen ilk paketleri (ve bağlantı kurulmadan önce kuyruğa sızmayı başaran paketleri) işlediğinden, performans neredeyse hiç etkilenmez.
İpipou sunucusu kimliği doğrulanmış bir paket alır almaz, bir tünel oluşturulur ve bağlantıdaki sonraki tüm paketler, nfqueue'yu atlayarak çekirdek tarafından zaten işlenir. Bağlantı başarısız olursa, bir sonraki paketin ilk paketi ayarlara bağlı olarak nfqueue kuyruğuna gönderilir, kimlik doğrulamalı bir paket değilse, ancak son hatırlanan IP ve istemci bağlantı noktasından geçirilebilir. açık veya atılır. Kimliği doğrulanmış bir paket yeni bir IP ve bağlantı noktasından gelirse tünel bunları kullanacak şekilde yeniden yapılandırılır.
Her zamanki FOU üzerinden IPIP'nin NAT ile çalışırken bir sorunu daha vardır - aynı IP ile UDP'de kapsüllenmiş iki IPIP tüneli oluşturmak imkansızdır çünkü FOU ve IPIP modülleri birbirlerinden oldukça yalıtılmıştır. Onlar. aynı genel IP'nin arkasındaki bir çift istemci aynı sunucuya bu şekilde aynı anda bağlanamayacaktır. Gelecekte, belkikernel seviyesinde çözülecek ama bu kesin değil. Bu arada, NAT sorunları NAT tarafından çözülebilir - eğer bir çift IP adresi zaten başka bir tünel tarafından kullanılıyorsa, ipipou NAT'ı genelden alternatif bir özel IP'ye yapacaktır, işte! - Bağlantı noktaları bitene kadar tüneller oluşturabilirsiniz.
Çünkü Bağlantıdaki tüm paketler imzalanmadıysa, bu basit koruma MITM'e karşı savunmasızdır, dolayısıyla istemci ile sunucu arasındaki yolda trafiği dinleyip yönetebilen bir kötü adam varsa, kimliği doğrulanmış paketleri aracılığıyla yeniden yönlendirebilir. başka bir adrese gidin ve güvenilmeyen bir ana bilgisayardan bir tünel oluşturun.
Trafiğin büyük kısmını merkezde bırakarak bu durumu nasıl düzeltebileceğinize dair fikri olan varsa, konuşmaktan çekinmeyin.
Bu arada, UDP'deki kapsülleme kendini çok iyi kanıtladı. IP üzerinden kapsülleme ile karşılaştırıldığında, UDP başlığının ek yüküne rağmen çok daha kararlı ve genellikle daha hızlıdır. Bunun nedeni, İnternet'teki çoğu ana bilgisayarın yalnızca en popüler üç protokolle iyi çalışmasıdır: TCP, UDP, ICMP. Somut kısım, diğer her şeyi tamamen atabilir veya daha yavaş işleyebilir çünkü yalnızca bu üçü için optimize edilmiştir.
Örneğin, HTTP/3'ü temel alan QUICK'in IP'nin değil, UDP'nin üzerinde oluşturulmasının nedeni budur.
Yeterince kelime, "gerçek dünyada" nasıl çalıştığını görmenin zamanı geldi.
Savaş
Gerçek dünyayı taklit etmek için kullanılır iperf3. Gerçekliğe yakınlık derecesi açısından bu, Minecraft'ta gerçek dünyayı taklit etmekle yaklaşık olarak aynıdır, ancak şimdilik işe yarayacaktır.
Meraklıları için teknik veriler Metrikler aşağıdaki komutlarla alınır:
istemcide:
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", чтобы лишние пакеты не плодить и не портить производительность.