Поврзете два OpenVPN клиенти на еден Linux домаќин со fwmark
Двата клиенти ја сакаат стандардната рута. Закачете го внатрешниот сервер со хост-рута, спречете го вториот клиент да препишува табели, потоа насочете ги тековите со fwmark.
Додавањето втор 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Повеќето откажувања во овој сет правила доаѓаат од две грешки. Вредноста на ознаката што ја поставува firewall-от и вредноста што ја совпаѓа правилото мора да бидат идентични, бидејќи несовпаѓањето не дава ни грешка ни ефект. А 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 треба да го наведе приоритетот што сте го намеравале. Ако двата тека одат по истиот пат, ознаката не се применува таму каде што мислите.