Додавање другог OpenVPN клијента на један Linux домаћин не успева на једном од два места. Или унутрашњи клијент не може да стигне до свог сервера јер је спољни тунел заузео тај транспорт, или други клијент преписује табелу рута и први тунел престаје да ради. Оба проблема су у рутирању, не у шифровању, и оба се решавају пре него нови тунел пренесе било какав апликацијски саобраћај. Адресе овде су илустративне: tun0 је спољни тунел, 203.0.113.9 је унутрашњи сервер, а TCP 9999 је ток који мора да користи унутрашњи пут.

Два режима отказа, једна табела рута

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

Други отказ долази од push-а сервера. Уобичајени push је redirect-gateway def1, који поставља 0.0.0.0/1 и 128.0.0.0/1 уместо да замени подразумевану руту. Зато се два клијента која сваки постави свој пар /1 сударају, и најновији пар побеђује за скоро свако одредиште. Потражите та два префикса у табели када тунел умре након што се други повеже, јер сама подразумевана рута можда никада није промењена.

Означите ток и дајте му табелу

Усмерите изабрани саобраћај означавањем у mangle табели и подударањем ознаке у правилу политике. Правило показује на наменску табелу чија је подразумевана рута унутрашњи уређај, тако да само означени пакети иду унутрашњим путем.

iptables -t mangle -A PREROUTING -p tcp -m multiport --dport 9999 -j MARK --set-mark 0x9999
ip rule add fwmark 0x9999 table 200 pref 1000
ip route add default dev tun1 table 200

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

Одузмите власништво над рутама другом клијенту

Две опције спречавају други клијент да уређује табелу, и делују на различитим местима. route-nopull игнорише push-оване опције рута, па се ништа не поставља. route-noexec прихвата push-оване опције у окружење клијента, али промену табеле оставља hook-у, и то је оно што желите када треба да видите шта је сервер понудио.

Hook се извршава са push-ованим вредностима у свом окружењу, и требало би да дода само уносе које сте одобрили. Учините га idempotent: испразните табелу коју поседује пре поновне изградње, и не претпостављајте да је претходно извршавање оставило чисто стање. Поновно повезивање поново позива hook, а hook који додаје без чишћења накупља дупликате рута.

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

Причврстите обе адресе сервера

Унутрашњем серверу је потребна хост-рута кроз спољни уређај пре него што се унутрашњи клијент повеже. Тај унос држи унутрашњи транспорт унутар спољног тунела уместо да му дозволи да прати подразумевану руту.

ip route add 203.0.113.9/32 dev tun0
ip route get 203.0.113.9

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

Проверите претрагу уместо да читате целу табелу. Излаз претраге руте наводи уређај и изворну адресу које ће kernel користити, и то је тачно оно што клијент добија када отвори свој сокет.

Тестирајте ланац и учините отказ видљивим

Снимајте на спољном интерфејсу док се унутрашњи клијент повезује. Унутрашње руковање треба да се појави као шифровани терет унутар спољног тунела; ако се појави као обичан UDP ка 203.0.113.9, хост-рута недостаје и ланац никада није изграђен.

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

Завршите са два тока и једним исписом правила: означена и неозначена веза треба да иду различитим путевима, а ip rule show треба да наведе приоритет који сте намеравали. Ако оба тока иду истим путем, ознака се не примењује тамо где мислите.

Повезани чланци