Означувањето на сообраќајот од една cgroup е лесниот дел. Три одделни одлуки мора да се поклопат пред една апликација да излезе низ физичкиот интерфејс, а сè друго да остане во тунелот: кој сокет припаѓа на исклучокот, кое пребарување на рута го активира ознаката и која изворна адреса ја носи пакетот кога излегува. Повеќето неуспешни обиди ја прават првата правилно, втората половично, а третата никогаш не ја гледаат.

Три одлуки, не една

Класификацијата одговара кој е изземен. Рутирањето одговара каде оди означениот пакет наместо тоа. Изборот на извор одговара што ќе види далечниот крај и каде треба да се врати одговорот.

Овие не успеваат независно. Пакетот може да биде класифициран, прерутиран на физичкиот интерфејс и се уште да носи приватна адреса што ниту еден нагорен рутер не може да ја врати, што создава истек на време што изгледа точно како блокирање од огнен ѕид. Ништо во чекорот на класификација не те предупредува за тоа. Ништо и во чекорот на рутирање.

Важен е и редоследот. Класификацијата се случува кога пакетот се создава, рутирањето потоа, а преводот во точката на излез.

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

Совпадни со cgroup што ќе постои и утре

nftables може да ја провери cgroup v2 припадноста на сокетот, што е навистина корисно зашто го следи процесот, а не одредиштето. Заседата е идентификаторот. Десктоп апликација стартувана од мени често живее во преоден scope чие име се менува при следното стартување.

nft list ruleset
systemctl status session.slice 2>/dev/null
cat /proc/self/cgroup

Копирањето на името на scope од една сесија и неговото тврдо кодирање создава правило што работи денес и тивко престанува да се совпаѓа утре. Наместо тоа, стави ја апликацијата во намерен, стабилен контекст на извршување, како посебен scope или unit што го контролираш, и совпадни со него. Тогаш правилото преживува рестартирања и ажурирања на пакети. Исто така станува нешто за што колега може да размислува без твојата историја на сесии.

Биди прецизен и за тоа кој механизам го користиш. net_cls класификацијата на cgroup v1 и совпаѓањето на сокети на cgroup v2 се различни работи, а слично именувано поле во документацијата не ги прави заменливи.

Второто пребарување го активира route-синџирот

За локално генериран сообраќај, типот на синџирот одлучува дали нешто ќе се случи откако ознаката е поставена. output-синџир од типот filter може да означи пакет и јадрото ќе продолжи да ја користи рутата што веќе ја избрало. Синџир од типот route е механизмот што бара ново пребарување.

table inet bypass {
  chain mark {
    type route hook output priority mangle; policy accept;
    socket cgroupv2 level 2 "app.slice" meta mark set 0x1 comment "app bypass"
  }
}
ip rule add fwmark 0x1 lookup 200
ip route add default via 203.0.113.1 dev wlan0 table 200

Потоа на ознаката и треба правило за политика што ја испраќа во табела, а таа табела мора да биде целосна: стандардна рута, локални одредишта што на апликацијата сè уште и требаат и нагорен гејтвеј што навистина одговара.

Избери ја вредноста на ознаката намерно. WireGuard користи свој fwmark за надворешниот транспорт, а случајното совпаѓање со истиот број може да ја попречи рутната исклучок на самиот тунел на начин што е болен за дијагностицирање.

Изворната адреса не ја следи рутата

Сокетот што веќе избрал изворна адреса за патеката на тунелот ја задржува таа адреса и по прерутирањето. Ништо во промената на рутата не ја препишува, затоа пакетот излегува низ физичкиот интерфејс со приватен извор што нагорната мрежа не може да го врати.

Видливиот симптом е апликација што изгледа како да испраќа податоци и никогаш не добива одговор, и дневник на огнен ѕид што не покажува ништо зашто пакетот никогаш не се вратил.

Тесната поправка е правило за превод на изворот ограничено на ознаката на таа апликација и нејзиниот вистински излезен интерфејс, интегрирано со NAT што веќе постои, наместо да го замени:

table inet bypass {
  chain postrouting {
    type nat hook postrouting priority srcnat; policy accept;
    meta mark 0x1 oifname "wlan0" masquerade
  }
}

Преведи го исклучокот и ништо друго. Општо правило за masquerade го поправа симптомот и ја уништува способноста да се каже кој сообраќај по кој пат отишол. Совпадни со ознаката, вистинскиот излезен интерфејс и, ако можеш, со адресата на самата апликација. Широките правила се лесни за пишување и речиси невозможни за подоцнежно ревидирање.

Што сè уште избегнува од исклучокот

Резолуцијата на имиња може да доаѓа од одделен resolver процес во друга cgroup, така што класификацијата на сокетот на прелистувачот не ги класифицира неговите пребарувања. Ако барањата на resolver-от останат во тунелот, а врската излезе надвор од него, split-horizon одговорите може да не се совпаднат со патеката. Тоа несовпаѓање создава дефекти што изгледаат како DNS грешки, а не се.

Детските процеси ја наследуваат cgroup во повеќето поставки, но помошникот што се преместува во сопствен scope не ја наследува. Провери наместо да претпоставуваш, особено за сè што се извршува повторно.

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

Поврзани статии