ipipou: шифрланбаған туннель ғана емес

Біз IPv6 Құдайына не айтамыз?

ipipou: шифрланбаған туннель ғана емес
Дұрыс, біз бүгін шифрлау құдайына дәл осылай айтамыз.

Мұнда шифрланбаған IPv4 туннелі туралы сөйлесетін боламыз, бірақ «жылы шам» туралы емес, заманауи «жарық диодты» туралы. Сондай-ақ мұнда шикі розеткалар жыпылықтайды және пайдаланушы кеңістігінде пакеттермен жұмыс жүргізілуде.

Кез келген дәм мен түс үшін N туннельдеу протоколы бар:

  • стильді, сәнді, жастық WireGuard
  • көп функционалды, мысалы, швейцариялық пышақтар, OpenVPN және SSH
  • ескі және жаман емес GRE
  • ең қарапайым, жылдам, толығымен шифрланбаған IPIP
  • белсенді дамып келеді ЖЕНЕВ
  • көптеген басқалар.

Бірақ мен бағдарламашымын, сондықтан мен N-ді тек бір бөлікке көбейтемін және нақты хаттамаларды әзірлеуді Коммерсант әзірлеушілеріне тапсырамын.

Бір тумағанда жобаМен қазір NAT артындағы хосттарға сырттан қол жеткізу болып табылады. Бұл үшін ересектерге арналған криптографиясы бар хаттамаларды қолдана отырып, мен бұл зеңбіректен торғай ату сияқты сезімді сейілте алмадым. Өйткені туннель көбінесе NAT-e-де тесіктерді ашу үшін пайдаланылады, ішкі трафик әдетте шифрланады, бірақ олар әлі де HTTPS-те батып кетеді.

Әртүрлі туннельдеу хаттамаларын зерттей отырып, менің ішкі перфекционистімнің назары IPIP-ке оның минималды шығындарына байланысты қайта-қайта аударылды. Бірақ оның менің тапсырмаларым үшін бір жарым маңызды кемшіліктері бар:

  • ол екі жақта да жалпыға ортақ IP мекенжайларын қажет етеді,
  • және сіз үшін аутентификация жоқ.

Сондықтан, перфекционист бас сүйегінің қараңғы бұрышына немесе қайда отырса да, қайтадан айдалды.

Сосын бір күні мақалаларды оқып отырып жергілікті түрде қолдау көрсетілетін туннельдер Linux жүйесінде мен FOU (Foo-over-UDP) кездестірдім, яғни. бәрібір, UDP ішіне оралған. Әзірге тек IPIP және GUE (Жалпы UDP инкапсуляциясы) қолданылады.

«Міне, күміс оқ! Мен үшін қарапайым IPIP жеткілікті». - деп ойладым.

Шындығында, оқ толығымен күміс емес болып шықты. UDP ішіндегі инкапсуляция бірінші мәселені шешеді - сіз NAT артындағы клиенттерге алдын ала орнатылған қосылым арқылы сырттан қосыла аласыз, бірақ бұл жерде IPIP келесі кемшілігінің жартысы жаңа жарықта гүлдейді - жеке желідегі кез келген адам көрінетін желінің артына жасыра алады. жалпыға ортақ IP және клиент порты (таза IPIP-де бұл мәселе жоқ).

Осы бір жарым мәселені шешу үшін утилита дүниеге келді ipipou. Ол ядро ​​кеңістігіндегі пакеттерді жылдам және тиімді өңдейтін FOU ядросының жұмысын бұзбай, қашықтағы хосттың аутентификациясының үйде жасалған механизмін жүзеге асырады.

Бізге сіздің сценарийіңіз керек емес!

Жарайды, егер сіз клиенттің жалпыға қолжетімді портын және 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 — eth0 интерфейсіне тағайындалған клиенттік IP
  • 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: порты өзгеріссіз қалса - ол өмір сүреді, егер олар өзгерсе - ол үзіледі.

Барлығын кері қайтарудың ең оңай жолы - ядро ​​модульдерін босату: modprobe -r fou ipip

Аутентификация талап етілмесе де, клиенттің жалпы IP және порты әрқашан белгілі бола бермейді және жиі болжау мүмкін емес немесе айнымалы (NAT түріне байланысты). Егер сіз жіберіп алсаңыз encap-dport сервер жағында туннель жұмыс істемейді, қашықтағы қосылым портын қабылдауға жеткілікті ақылды емес. Бұл жағдайда ipipou да көмектесе алады немесе WireGuard және басқалары сізге көмектесе алады.

Бұл қалай жұмыс істейді?

Клиент (әдетте NAT артында орналасқан) туннельді ашады (жоғарыдағы мысалдағыдай) және туннельді өз жағында конфигурациялау үшін серверге аутентификация пакетін жібереді. Параметрлерге байланысты бұл бос пакет болуы мүмкін (сервер жалпыға ортақ IP: қосылым портын көре алатындай) немесе сервер клиентті анықтай алатын деректері бар. Деректер анық мәтіндегі қарапайым құпия фразалар болуы мүмкін (HTTP Basic Auth ұқсастығы еске түседі) немесе жеке кілтпен қол қойылған арнайы әзірленген деректер (HTTP Digest Auth сияқты тек күштірек, функцияны қараңыз) client_auth кодта).

Серверде (жалпыға ортақ IP бар жағында) ipipou іске қосылғанда, ол nfqueue кезек өңдеушісін жасайды және қажетті дестелер болуы керек жерге жіберілетіндей желі сүзгісін конфигурациялайды: nfqueue кезегіне қосылымды инициализациялайтын пакеттер және [дерлік] қалғаны FOU тыңдаушысына тікелей барады.

Білмейтіндер үшін nfqueue (немесе NetfilterQueue) ядро ​​модульдерін әзірлеуді білмейтін әуесқойлар үшін ерекше нәрсе, ол netfilter (nftables/iptables) көмегімен желі пакеттерін пайдаланушы кеңістігіне қайта бағыттауға және оларды сол жерде өңдеуге мүмкіндік береді. Қарапайым құралдар: өзгерту (міндетті емес ) және оны ядроға қайтарыңыз немесе оны тастаңыз.

Кейбір бағдарламалау тілдері үшін nfqueue-мен жұмыс істеу үшін байланыстырулар бар, bash үшін олар жоқ (хе, таңқаларлық емес), мен python-ды қолдануға тура келді: ipipou пайдаланады NetfilterQueue.

Егер өнімділік маңызды болмаса, осы нәрсені пайдаланып, салыстырмалы түрде төмен деңгейде дестелермен жұмыс істеу үшін өзіңіздің жеке логикаңызды тез және оңай құрастыра аласыз, мысалы, эксперименттік деректерді беру хаттамаларын жасай аласыз немесе стандартты емес әрекетпен жергілікті және қашықтағы қызметтерді троллей аласыз.

Raw розеткалары nfqueue-мен бірге жұмыс істейді, мысалы, туннель әлдеқашан конфигурацияланған кезде және FOU қажетті портты тыңдап жатқанда, сіз сол порттан әдеттегі жолмен пакетті жібере алмайсыз - бос емес, бірақ кездейсоқ жасалған пакетті шикі розетка арқылы тікелей желілік интерфейске қабылдауға және жіберуге болады, дегенмен мұндай пакетті жасау аздап көп өңдеуді қажет етеді. Ipipou-да аутентификациясы бар пакеттер осылай жасалады.

ipipou тек қосылымның алғашқы пакеттерін өңдейтіндіктен (және қосылым орнатылмай тұрып кезекке ағып кеткен), өнімділік дерлік зардап шекпейді.

Ipipou сервері аутентификацияланған пакетті алғаннан кейін туннель жасалады және қосылымдағы барлық келесі пакеттер nfqueue-ді айналып өтетін ядро ​​арқылы өңделеді. Егер қосылым сәтсіз болса, келесінің бірінші пакеті параметрлерге байланысты nfqueue кезегіне жіберіледі, егер ол аутентификациясы бар пакет болмаса, бірақ соңғы есте қалған IP және клиент портынан болса, оны жіберуге болады. қосулы немесе лақтырылған. Аутентификацияланған пакет жаңа IP және порттан келсе, туннель оларды пайдалану үшін қайта конфигурацияланады.

Әдеттегі IPIP-over-FOU-да NAT-пен жұмыс істеу кезінде тағы бір мәселе бар - бірдей IP-мен UDP-де инкапсуляцияланған екі IPIP туннелін жасау мүмкін емес, өйткені FOU және IPIP модульдері бір-бірінен айтарлықтай оқшауланған. Анау. бір жалпыға ортақ IP артындағы клиенттер жұбы бір серверге осылайша бір уақытта қосыла алмайды. Болашақта, мүмкін, ол ядро ​​деңгейінде шешіледі, бірақ бұл сенімді емес. Осы уақытта NAT мәселелерін NAT шешуге болады - егер жұп IP мекенжайлары басқа туннельде тұрып қалса, ipipou NAT-ты жалпыдан балама жеке IP-ге жасайды, voila! - порттар біткенше туннельдер жасауға болады.

Өйткені Қосылымдағы барлық пакеттерге қол қойылмаған, бұл қарапайым қорғаныс MITM-ге осал, сондықтан клиент пен сервер арасындағы жолда трафикті тыңдай алатын және оны басқара алатын зұлым адам болса, ол аутентификацияланған пакеттерді қайта бағыттай алады. басқа мекенжай және сенімсіз хосттан туннель жасаңыз.

Егер біреуде трафиктің негізгі бөлігін қалдырып, мұны қалай түзетуге болатыны туралы идеялары болса, айтудан тартынбаңыз.

Айтпақшы, UDP-де инкапсуляция өзін жақсы дәлелдеді. IP арқылы инкапсуляциямен салыстырғанда, UDP тақырыбының қосымша шығынына қарамастан, ол әлдеқайда тұрақты және жиі жылдамырақ. Бұл Интернеттегі хосттардың көпшілігінің тек ең танымал үш хаттамамен жақсы жұмыс істейтініне байланысты: TCP, UDP, ICMP. Материалдық бөлік қалғанның бәрін толығымен тастай алады немесе оны баяу өңдеуі мүмкін, өйткені ол тек осы үшеуі үшін оңтайландырылған.

Мысалы, сондықтан HTTP/3 негізіндегі QUICK IP үстіне емес, UDP үстіне жасалған.

Сөздер жеткілікті, оның «нақты әлемде» қалай жұмыс істейтінін көретін кез келді.

Шайқас

Нақты әлемге еліктеу үшін қолданылады iperf3. Шындыққа жақындық дәрежесі бойынша бұл Minecraft-тағы нақты әлемді еліктеумен бірдей, бірақ әзірге ол солай болады.

Байқауға қатысушылар:

  • анықтамалық негізгі арна
  • осы мақаланың кейіпкері - ipipou
  • Аутентификациясы бар, бірақ шифрлаусыз OpenVPN
  • OpenVPN барлығын қамтитын режимде
  • PresharedKey жоқ WireGuard, 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

нәтижелері

Ылғалды ұсқынсыз белгі
Сервердің CPU жүктемесі өте индикативті емес, себебі... Онда көптеген басқа қызметтер жұмыс істейді, кейде олар ресурстарды жейді:

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

пікір қалдыру