ipipou: pli ol nur neĉifrita tunelo

Kion ni diras al la Dio de IPv6?

ipipou: pli ol nur neĉifrita tunelo
Ĝuste, ni diros la samon al la dio de ĉifrado hodiaŭ.

Ĉi tie ni parolos pri neĉifrita IPv4 tunelo, sed ne pri "varma lampo", sed pri moderna "LED". Kaj ankaŭ estas krudaj ingoj fulmantaj ĉi tie, kaj laboro okazas kun pakoj en uzantspaco.

Estas N tunelaj protokoloj por ĉiu gusto kaj koloro:

  • eleganta, moda, juneco WireGuard
  • multfunkciaj, kiel svisaj tranĉiloj, OpenVPN kaj SSH
  • malnova kaj ne malbona GRE
  • la plej simpla, rapida, tute neĉifrita IPIP
  • aktive evoluanta GENEVE
  • multaj aliaj.

Sed mi estas programisto, do mi pliigos N ​​nur je frakcio, kaj lasos la disvolviĝon de realaj protokoloj al programistoj de Kommersant.

En unu nenaskita projektoKion mi nun faras, estas atingi gastigantojn malantaŭ NAT de ekstere. Uzante protokolojn kun plenkreska kriptografio por tio, mi ne povis skui la senton, ke ĝi estas kiel pafi paserojn el kanono. Ĉar la tunelo estas uzata plejparte nur por trui en NAT-e, interna trafiko estas kutime ankaŭ ĉifrita, sed ili ankoraŭ dronas en HTTPS.

Dum esplorado de diversaj tunelaj protokoloj, la atento de mia interna perfektisto estis tirita al IPIP ree kaj ree pro ĝia minimuma superkosto. Sed ĝi havas unu kaj duonon gravajn malavantaĝojn por miaj taskoj:

  • ĝi postulas publikajn IP-ojn ambaŭflanke,
  • kaj neniu aŭtentigo por vi.

Tial, la perfektisto estis pelita reen en la malhelan angulon de la kranio, aŭ kie ajn li sidas tie.

Kaj tiam unu tagon, dum legado de artikoloj denaske subtenataj tuneloj en Linukso mi renkontis FOU (Foo-over-UDP), t.e. kio ajn, envolvita en UDP. Ĝis nun, nur IPIP kaj GUE (Generic UDP Encapsulation) estas subtenataj.

“Jen la arĝenta kuglo! Simpla IPIP sufiĉas por mi.” - Mi pensis.

Fakte, la kuglo montriĝis ne tute arĝenta. Enkapsuligo en UDP solvas la unuan problemon - vi povas konektiĝi al klientoj malantaŭ NAT de ekstere uzante antaŭestablitan konekton, sed ĉi tie duono de la sekva malavantaĝo de IPIP floras en nova lumo - iu ajn el privata reto povas kaŝi sin malantaŭ la videbla. publika IP kaj klienta haveno (en pura IPIP ĉi tiu problemo ne ekzistas).

Por solvi ĉi tiun unu kaj duonon problemon, la utileco naskiĝis ipipou. Ĝi efektivigas memfaritan mekanismon por aŭtentikigi malproksiman gastiganton, sen interrompi la funkciadon de la kerno FOU, kiu rapide kaj efike prilaboros pakaĵetojn en kernspaco.

Ni ne bezonas vian skripton!

Bone, se vi konas la publikan havenon kaj IP de la kliento (ekzemple, ĉiuj malantaŭ ĝi ne iras ien, NAT provas mapi pordojn 1-en-1), vi povas krei IPIP-super-FOU tunelon kun la sekvaj komandoj, sen ajnaj skriptoj.

sur servilo:

# Подгрузить модуль ядра 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

sur la kliento:

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

kie

  • ipipou* — nomo de la loka tunela reto-interfaco
  • 203.0.113.1 — publika IP-servilo
  • 198.51.100.2 — publika IP de la kliento
  • 192.168.0.2 — klienta IP asignita al interfaco eth0
  • 10001 — loka klienta haveno por FOU
  • 20001 — publika klienta haveno por FOU
  • 10000 — publika servila haveno por FOU
  • encap-csum — opcio aldoni UDP-kontrolsumon al enkapsuligitaj UDP-pakaĵoj; povas esti anstataŭigita per noencap-csum, sen mencii, integreco jam estas kontrolita per la ekstera enkapsuliga tavolo (dum la pakaĵeto estas ene de la tunelo)
  • eth0 — loka interfaco al kiu la ipip-tunelo estos ligita
  • 172.28.0.1 — IP de la klienta tunela interfaco (privata)
  • 172.28.0.0 — IP-tunela servila interfaco (privata)

Dum la UDP-konekto estos viva, la tunelo estos en funkciado, sed se ĝi rompiĝos, vi estos bonŝanca - se la IP: haveno de la kliento restas la sama - ĝi vivos, se ili ŝanĝiĝos - ĝi rompiĝos.

La plej facila maniero reŝalti ĉion estas malŝarĝi la kernajn modulojn: modprobe -r fou ipip

Eĉ se aŭtentigo ne estas postulata, la publika IP kaj haveno de la kliento ne estas ĉiam konataj kaj ofte estas neantaŭvideblaj aŭ variaj (depende de la NAT-tipo). Se vi preterlasas encap-dport ĉe la servilo, la tunelo ne funkcios, ĝi ne estas sufiĉe inteligenta por preni la foran konektan havenon. En ĉi tiu kazo, ipipou ankaŭ povas helpi, aŭ WireGuard kaj aliaj similaj povas helpi vin.

Kiel ĝi funkcias?

La kliento (kiu kutime estas malantaŭ NAT) malfermas tunelon (kiel en la supra ekzemplo), kaj sendas aŭtentikigpakaĵon al la servilo por ke ĝi agordu la tunelon sur sia flanko. Depende de la agordoj, ĉi tio povas esti malplena pako (nur por ke la servilo povu vidi la publikan IP: konekta haveno), aŭ kun datumoj per kiuj la servilo povas identigi la klienton. La datumoj povas esti simpla pasfrazo en klara teksto (pensas la analogio kun HTTP Basic Auth) aŭ speciale dezajnitaj datumoj subskribitaj per privata ŝlosilo (simila al HTTP Digest Auth nur pli forta, vidu funkcion). client_auth en la kodo).

Sur la servilo (la flanko kun la publika IP), kiam ipipou komenciĝas, ĝi kreas nfqueue queue-traktilon kaj agordas netfilter tiel ke la necesaj pakaĵetoj estas senditaj kie ili devus esti: pakaĵetoj praviganta la konekton al la nfqueue queue, kaj [preskaŭ] ĉiuj ceteraj iras rekte al la aŭskultanto FOU.

Por tiuj, kiuj ne scias, nfqueue (aŭ NetfilterQueue) estas speciala afero por amatoroj, kiuj ne scias kiel evoluigi kernajn modulojn, kiuj uzante netfilter (nftables/iptables) ebligas al vi redirekti retpakaĵojn al uzantspaco kaj prilabori ilin tie uzante primitiva signifas ĉemane: modifi (laŭvola ) kaj redoni ĝin al la kerno, aŭ forĵeti ĝin.

Por iuj programlingvoj ekzistas ligoj por labori kun nfqueue, por bash ne estis (he, ne mirinde), mi devis uzi python: ipipou uzas NetfilterQueue.

Se agado ne estas kritika, uzante ĉi tiun aferon vi povas relative rapide kaj facile elpensi vian propran logikon por labori kun pakaĵetoj je sufiĉe malalta nivelo, ekzemple, krei eksperimentajn transigajn protokolojn, aŭ troli lokajn kaj forajn servojn kun ne-norma konduto.

Krudaj ingoj funkcias man-en-mane kun nfqueue, ekzemple, kiam la tunelo jam estas agordita kaj FOU aŭskultas sur la dezirata haveno, vi ne povos sendi paketon el la sama haveno laŭ la kutima maniero - ĝi estas okupata, sed vi povas preni kaj sendi hazarde generitan pakaĵeton rekte al la reto-interfaco uzante krudan ingon, kvankam generi tian pakaĵeton postulos iom pli da tuŝado. Tiel estas kreitaj pakoj kun aŭtentigo en ipipou.

Ĉar ipipou prilaboras nur la unuajn pakaĵetojn de la konekto (kaj tiujn, kiuj sukcesis liki en la voston antaŭ ol la konekto estis establita), rendimento preskaŭ ne suferas.

Tuj kiam la ipipou-servilo ricevas aŭtentikigitan pakaĵeton, tunelo estas kreita kaj ĉiuj postaj pakoj en la konekto jam estas prilaboritaj de la kerno preterpasante nfqueue. Se la konekto malsukcesas, tiam la unua pako de la sekva estos sendita al la nfqueue-vico, depende de la agordoj, se ĝi ne estas pako kun aŭtentigo, sed de la lasta memorita IP kaj klienta haveno, ĝi povas aŭ esti preterpasita. sur aŭ forĵetita. Se aŭtentikigita pako venas de nova IP kaj haveno, la tunelo estas reagordita por uzi ilin.

La kutima IPIP-over-FOU havas unu plian problemon kiam laboras kun NAT - estas neeble krei du IPIP-tunelojn enkapsuligitajn en UDP kun la sama IP, ĉar la FOU kaj IPIP-moduloj estas sufiĉe izolitaj unu de la alia. Tiuj. paro da klientoj malantaŭ la sama publika IP ne povos samtempe konektiĝi al la sama servilo tiamaniere. Estontece, eble, ĝi estos solvita ĉe la kerna nivelo, sed ĉi tio ne estas certa. Intertempe NAT-problemoj povas esti solvitaj per NAT - se okazas, ke paro da IP-adresoj jam estas okupata de alia tunelo, ipipou faros NAT de publika al alternativa privata IP, voila! - vi povas krei tunelojn ĝis la havenoj finiĝas.

Ĉar Ne ĉiuj pakaĵetoj en la konekto estas subskribitaj, tiam ĉi tiu simpla protekto estas vundebla al MITM, do se estas fiulo kaŝatendanta sur la vojo inter la kliento kaj la servilo, kiu povas aŭskulti la trafikon kaj manipuli ĝin, li povas redirekti aŭtentikigitajn pakaĵojn tra alian adreson kaj kreu tunelon de nefidinda gastiganto.

Se iu havas ideojn pri kiel ripari ĉi tion lasante la plej grandan parton de la trafiko en la kerno, ne hezitu paroli.

Cetere, enkapsuligo en UDP pruvis sin tre bone. Kompare kun enkapsulado super IP, ĝi estas multe pli stabila kaj ofte pli rapida malgraŭ la kroma supraĵo de la UDP-kapo. Ĉi tio estas pro la fakto, ke plej multaj gastigantoj en Interreto funkcias bone nur kun la tri plej popularaj protokoloj: TCP, UDP, ICMP. La palpebla parto povas tute forĵeti ĉion alian, aŭ prilabori ĝin pli malrapide, ĉar ĝi estas optimumigita nur por ĉi tiuj tri.

Ekzemple, jen kial QUICK, sur kiu baziĝas HTTP/3, estis kreita aldone al UDP, kaj ne al IP.

Nu, sufiĉas vortoj, estas tempo por vidi kiel ĝi funkcias en la "reala mondo".

Batalo

Uzita por imiti la realan mondon iperf3. Koncerne la gradon de proksimeco al realeco, ĉi tio estas proksimume la sama kiel kopii la realan mondon en Minecraft, sed nuntempe ĝi faros.

Partoprenantoj en la konkurso:

  • referenca ĉefa kanalo
  • la heroo de ĉi tiu artikolo estas ipipou
  • OpenVPN kun aŭtentigo sed sen ĉifrado
  • OpenVPN en ĉio-inkluziva reĝimo
  • WireGuard sen PresharedKey, kun MTU=1440 (ekde IPv4-nur)

Teknikaj datumoj por geeks
Metrikoj estas prenitaj per la sekvaj komandoj:

sur la kliento:

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 latenteco

ping -c 10 SERVER_IP | tail -1

sur la servilo (funkcias samtempe kun la kliento):

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"

Tunela agordo

ipipou
servilo
/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

kliento
/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 (neniu ĉifrado, kun aŭtentigo)
servilo

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

kliento

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 (kun ĉifrado, aŭtentikigo, per UDP, ĉio kiel atendite)
Agordita uzante openvpn-administri

teleservisto
servilo
/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

kliento
/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

Результаты

Malseka malbela signo
Servila CPU-ŝarĝo ne estas tre indika, ĉar... Tie funkcias multaj aliaj servoj, foje ili manĝas rimedojn:

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 Mbps kanalo

ipipou: pli ol nur neĉifrita tunelo

ipipou: pli ol nur neĉifrita tunelo

kanalo po 1 optimisma Gbps

ipipou: pli ol nur neĉifrita tunelo

ipipou: pli ol nur neĉifrita tunelo

En ĉiuj kazoj, ipipou estas sufiĉe proksima en rendimento al la baza kanalo, kio estas bonega!

La neĉifrita openvpn tunelo kondutis sufiĉe strange en ambaŭ kazoj.

Se iu provos ĝin, estos interese aŭdi komentojn.

Ke IPv6 kaj NetPrickle estu kun ni!

fonto: www.habr.com

Aldoni komenton