ипипоу: више од само нешифрованог тунела

Шта говоримо Богу ИПв6?

ипипоу: више од само нешифрованог тунела
Тако је, то ћемо данас рећи богу шифровања.

Овде ћемо говорити о нешифрованом ИПв4 тунелу, али не о „топлој лампи“, већ о модерном „ЛЕД“. А ту су и необрађени сокети који трепере овде, а у току је рад са пакетима у корисничком простору.

Постоји Н протокола за тунелирање за сваки укус и боју:

  • модеран, модеран, омладински ВиреГуард
  • мултифункционални, попут швајцарских ножева, ОпенВПН и ССХ
  • стар а не зао ГРЕ
  • најједноставнији, брзи, потпуно нешифровани ИПИП
  • активно се развија ЖАНОВ
  • многи други.

Али ја сам програмер, па ћу повећати Н само за делић, а развој правих протокола препустити програмерима Комерсант-а.

У једном нерођеном пројекатОно што сада радим је да споља дођем до хостова иза НАТ-а. Користећи за ово протоколе са криптографијом за одрасле, нисам могао да се отресем осећаја да је то као да пуцате на врапце из топа. Јер тунел се углавном користи само за бушење рупа у НАТ-е, интерни саобраћај је обично такође шифрован, али се и даље утапају у ХТТПС.

Док сам истраживао различите протоколе тунелирања, пажња мог унутрашњег перфекционисте је изнова и изнова привлачила ИПИП због минималних трошкова. Али има један и по значајних недостатака за моје задатке:

  • захтева јавне ИП адресе са обе стране,
  • и нема аутентификације за вас.

Стога је перфекциониста отеран назад у тамни угао лобање, или где год да седи.

А онда једног дана, док читате чланке даље изворно подржани тунели у Линуксу сам наишао на ФОУ (Фоо-овер-УДП), тј. било шта, умотано у УДП. До сада су подржани само ИПИП и ГУЕ (Генериц УДП Енцапсулатион).

„Ево сребрног метка! Довољан ми је једноставан ИПИП.” - Ја сам мислила.

У ствари, испоставило се да метак није потпуно сребрн. Енкапсулација у УДП решава први проблем - можете да се повежете са клијентима иза НАТ-а споља користећи унапред успостављену везу, али овде половина следећег недостатка ИПИП-а цвета у новом светлу - свако из приватне мреже може да се сакрије иза видљивог јавни ИП и порт клијента (у чистом ИПИП-у овај проблем не постоји).

Да би се решио овај један и по проблем, рођен је услужни програм ипипоу. Он имплементира домаћи механизам за аутентификацију удаљеног хоста, без ометања рада кернела ФОУ, који ће брзо и ефикасно обрадити пакете у простору кернела.

Не треба нам твој сценарио!

Ок, ако знате јавни порт и ИП клијента (на пример, сви иза њега не иду никуда, НАТ покушава да мапира портове 1-у-1), можете креирати ИПИП-овер-ФОУ тунел са следеће команде, без икаквих скрипти.

на серверу:

# Подгрузить модуль ядра 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 — јавни ИП сервер
  • 198.51.100.2 — јавна ИП адреса клијента
  • 192.168.0.2 — ИП клијента додељен интерфејсу етх0
  • 10001 — локални клијентски порт за ФОУ
  • 20001 — порт за јавни клијент за ФОУ
  • 10000 — порт за јавни сервер за ФОУ
  • encap-csum — опција за додавање УДП контролне суме инкапсулираним УДП пакетима; може се заменити са noencap-csum, да не спомињемо, интегритет је већ контролисан од стране спољашњег слоја енкапсулације (док је пакет унутар тунела)
  • eth0 — локални интерфејс за који ће ипип тунел бити везан
  • 172.28.0.1 — ИП интерфејса клијентског тунела (приватно)
  • 172.28.0.0 — ИП тунел серверски интерфејс (приватно)

Докле год је УДП веза жива, тунел ће бити у радном стању, али ако се поквари, имаћете среће – ако ИП: порт клијента остане исти – оживеће, ако се промене – поквариће се.

Најлакши начин да све вратите је да испразните модуле кернела: modprobe -r fou ipip

Чак и ако аутентификација није потребна, клијентов јавни ИП и порт нису увек познати и често су непредвидиви или променљиви (у зависности од типа НАТ-а). Ако изоставите encap-dport на страни сервера, тунел неће радити, није довољно паметан да преузме порт за удаљену везу. У овом случају, ипипоу такође може помоћи, или ВиреГуард и други слични могу вам помоћи.

Како то функционише?

Клијент (који се обично налази иза НАТ-а) отвара тунел (као у горњем примеру) и шаље аутентификациони пакет серверу тако да он конфигурише тунел на својој страни. У зависности од подешавања, ово може бити празан пакет (само да сервер види јавни ИП: порт за везу), или са подацима по којима сервер може да идентификује клијента. Подаци могу бити једноставна приступна фраза у чистом тексту (на памет ми пада аналогија са ХТТП Басиц Аутх) или посебно дизајнирани подаци потписани приватним кључем (слично ХТТП Дигест Аутх само јачи, погледајте функцију client_auth у коду).

На серверу (на страни са јавном ИП-ом), када се ипипоу покрене, креира нфкуеуе руковалац редом и конфигурише нетфилтер тако да се неопходни пакети шаљу тамо где би требало да буду: пакети који иницијализују везу са нфкуеуе редом и [скоро] сви остали иду директно слушаоцу ФОУ.

За оне који нису упознати, нфкуеуе (или НетфилтерКуеуе) је посебна ствар за аматере који не знају како да развију модуле кернела, који помоћу нетфилтера (нфтаблес/иптаблес) омогућавају да преусмерите мрежне пакете у кориснички простор и тамо их обрађујете користећи примитивно средство при руци: модификовати (опционо) и вратити га језгру, или га одбацити.

За неке програмске језике постоје везе за рад са нфкуеуе-ом, за басх их није било (хех, није изненађујуће), морао сам да користим питхон: ипипоу користи НетфилтерКуеуе.

Ако перформансе нису критичне, помоћу ове ствари можете релативно брзо и лако смислити сопствену логику за рад са пакетима на прилично ниском нивоу, на пример, креирати експерименталне протоколе за пренос података или троловати локалне и удаљене услуге са нестандардним понашањем.

Рав утичнице раде руку под руку са нфкуеуе-ом, на пример, када је тунел већ конфигурисан и ФОУ слуша на жељеном порту, нећете моћи да пошаљете пакет са истог порта на уобичајен начин - заузет је, али можете узети и послати насумично генерисани пакет директно на мрежни интерфејс користећи необрађену утичницу, иако ће генерисање таквог пакета захтевати мало више поправљања. Овако се креирају пакети са аутентификацијом у ипипоу.

Пошто ипипоу обрађује само прве пакете из везе (и оне који су успели да прођу у ред пре него што је веза успостављена), перформансе готово да не трпе.

Чим ипипоу сервер прими аутентификовани пакет, креира се тунел и сви наредни пакети у вези се већ обрађују од стране кернела заобилазећи нфкуеуе. Ако веза не успе, онда ће први пакет следећег бити послат у нфкуеуе ред, у зависности од подешавања, ако није пакет са аутентификацијом, али са последњег запамћеног ИП-а и клијентског порта, може се или проследити на или одбачен. Ако аутентификовани пакет долази са нове ИП адресе и порта, тунел се реконфигурише да их користи.

Уобичајени ИПИП-овер-ФОУ има још један проблем када ради са НАТ-ом - немогуће је креирати два ИПИП тунела инкапсулирана у УДП са истим ИП-ом, јер су ФОУ и ИПИП модули прилично изоловани један од другог. Оне. пар клијената иза исте јавне ИП адресе неће моћи истовремено да се повеже на исти сервер на овај начин. У будућности, можда, биће решено на нивоу кернела, али то није извесно. У међувремену, НАТ проблеме може решити НАТ - ако се деси да је пар ИП адреса већ заузет другим тунелом, ипипоу ће извршити НАТ са јавног на алтернативни приватни ИП, воила! - можете креирати тунеле док не понестане портова.

Јер Нису сви пакети у вези потписани, онда је ова једноставна заштита рањива на МИТМ, тако да ако постоји негативац који вреба на путу између клијента и сервера који може да слуша саобраћај и манипулише њиме, он може да преусмери аутентификоване пакете кроз другу адресу и направите тунел од непоузданог хоста.

Ако неко има идеје како да ово поправи, а да највећи део саобраћаја остане у језгру, не оклевајте да проговорите.

Иначе, инкапсулација у УДП-у се веома добро показала. У поређењу са енкапсулацијом преко ИП-а, она је много стабилнија и често бржа упркос додатним оптерећењима УДП заглавља. То је због чињенице да већина хостова на Интернету добро ради само са три најпопуларнија протокола: ТЦП, УДП, ИЦМП. Опипљиви део може потпуно да одбаци све остало, или да га обрађује спорије, јер је оптимизован само за ово троје.

На пример, ово је разлог зашто је КУИЦК, на коме је заснован ХТТП/3, креиран на врху УДП-а, а не на врху ИП-а.

Па, довољно речи, време је да видимо како то функционише у „стварном свету“.

Битка

Користи се за опонашање стварног света iperf3. У погледу степена блискости са стварношћу, ово је приближно исто као и емулација стварног света у Минецрафт-у, али за сада ће то бити довољно.

Учесници такмичења:

  • референтни главни канал
  • јунак овог чланка је ипипоу
  • ОпенВПН са аутентификацијом, али без шифровања
  • ОпенВПН у свеобухватном режиму
  • ВиреГуард без ПресхаредКеи-а, са МТУ=1440 (од само ИПв4)

Технички подаци за штреберке
Метрике се узимају следећим командама:

на клијенту:

УДП

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", чтобы лишние пакеты не плодить и не портить производительность.

ТЦП

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"

ИЦМП латенција

ping -c 10 SERVER_IP | tail -1

на серверу (ради истовремено са клијентом):

УДП

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

ТЦП

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

Конфигурација тунела

ипипоу
сервер
/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 --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

опенвпн (са шифровањем, аутентификацијом, преко УДП-а, све како се очекује)
Конфигурисано помоћу опенвпн-манаге

жичани штитник
сервер
/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 Мбпс канал

ипипоу: више од само нешифрованог тунела

ипипоу: више од само нешифрованог тунела

канал по 1 оптимистичком Гбпс

ипипоу: више од само нешифрованог тунела

ипипоу: више од само нешифрованог тунела

У свим случајевима, ипипоу је по перформансама прилично близу основном каналу, што је одлично!

Нешифровани опенвпн тунел се понашао прилично чудно у оба случаја.

Ако ће неко то тестирати, биће занимљиво чути повратне информације.

Нека ИПв6 и НетПрицкле буду са нама!

Извор: ввв.хабр.цом

Додај коментар