Угнежђени WireGuard: средњи скок не може да одговори на сопствени порт
Када средњи скок све шаље у један тунел, одговори на његову улазну услугу одлазе погрешним путем. Правило изворног порта на интерфејсу то исправља.
Три WireGuard скока стижу до мреже без јавне адресе, а затим средња машина престаје да одговара на порту на којем је требало да слуша. Тунел даље и даље ради, удаљени домаћин и даље одговара, и само је средњи сервер утихнуо споља. Та комбинација збуњује управо зато што је сама себи нанета: средњи скок слуша своју сопствену табелу рутирања, а табела шаље његове одговоре на погрешну страну.
Ланац који ради док не проговориш са средњом кутијом
Узмите илустративан ланац: клијент A стиже до сервера B преко UDP 500, а B иде даље до сервера C преко UDP 500. C прихвата саобраћај само са адресе свог јединог партнера, што га чини листом и одржава његово понашање једноставним. B није лист, и све занимљиво у вези са овим кваром дешава се управо тамо.
Разлика је важна јер улоге листа и средине вуку у супротним смеровима. Лист може послати све у један тунел без последица, јер ништа друго не зависи од њега. Средњи скок је истовремено крајња тачка за клијенте и клијент према удаљеној страни, а та два посла желе различито рутирање.
Зашто одговор излази кроз тунел
На B, интерфејс окренут ка C носи AllowedIPs = 0.0.0.0/0 заједно са одговарајућом подразумеваном рутом. Зато сваки пакет који B створи одлази у тај тунел, осим ако нешто конкретније не добије предност.
Пакет од A упућен B стиже и бива прихваћен, јер је B одредиште и локална достава се дешава прва. Одговор је потпуно нов, локално генерисан пакет усмерен на A-ову јавну адресу, а то одредиште одговара подразумеваној рути у тунел. C га прима, не поседује ту адресу и одбацује га.
Симптом изгледа као проблем са заштитним зидом или неусклађеност кључа, а овде ниједно није тачно. Снимак на тунелу према C показује да одговори иду у погрешном смеру. То једно запажање штеди више времена од било каквог читања конфигурације, па га запишите пре него што почнете да мењате кључеве. Свако ко није видео снимак претпоставиће да је сам тунел покварен.
Уско поправљање: правила политике која одговарају изворном порту
Одговори са B-овог сокета за слушање излазе са изворним портом 500. Правило политике може се поклопити с тим и вратити те пакете назад у обичну табелу:
ip rule add sport 500 table main priority 100
ip rule add sport 8080 table main priority 101
Правила политике се прегледају по редоследу приоритета, а главна табела стоји на 32766, па се правило на 100 пита пре него што подразумевана рута тунела добије реч. Додајте по један унос за сваки порт који мора остати доступан споља и ништа више, како би прослеђени саобраћај наставио да користи тунел за који је направљен.
Знајте границу овог трика. Селектор sport одговара локално генерисаним пакетима, што покрива тачно случај одговора и намерно не покрива саобраћај који B само прослеђује за неког другог. Услуга хостована иза B и даље захтева сопствени одговор, а тврђење супротног даје поправку која ради за прву услугу а пада за другу.
Дајте правилу власника
Правило откуцано у командној линији нестаје следећи пут кад се интерфејс поново изгради. У WireGuard подешавању ставите га тамо где се интерфејс ствара и уклања:
PostUp = ip rule add sport 500 table main priority 100
PostDown = ip rule del sport 500 table main priority 100
Ако интерфејсом управља NetworkManager, хук дистрибуције или улазна тачка контејнера, пар припада том власнику, а не ручно уређеној датотеци. Проверите ефективна правила након поновног повезивања, не само након првог покретања, јер је прво покретање случај који увек ради.
Упоредите алтернативе искрено
Правило изворног порта један је од четири излаза и најужји је од њих. Предност му је што уопште не дира политику тунела, због чега обично преживи касније измене. Уске поправке такође гласно падају кад престану да важе, док широки изузетак тихо наставља да ради дуго након што је разлог за њега нестао. Та разлика је важнија од елеганције кад после две године кутијом управља неко други.
| Approach | What it costs | Where it breaks |
|---|---|---|
| Source-port policy rule | One rule per exposed port | Anything B forwards rather than originates |
| Destination exception route | A route pinned to specific client addresses | Clients whose address changes |
| Stop full-tunnelling on B | Loses the catch-all path toward C | Designs that depend on it |
| Split into two tunnels | More interfaces and more policy | Nothing, at the cost of complexity |
Проверите са оба краја након што одаберете. Са A стране започните везу ка B-овом порту и држите је заузетом неко време. На B натерајте кернел да оправда пут одговора нечим попут ip route get <address-of-A> sport 500 и потврдите да наводи WAN интерфејс, а не тунел. Након тога проверите да нешто иза C још увек одговара кроз ланац, што доказује да је изузетак остао узак уместо да се претвори у заобилазницу. На крају запишите портове у дизајнерске белешке, иначе следећи оператер открије ово на другој услузи.