Ինչու ձեր iptables կանոնը երբեք չի տեսնում կամրջով անցնող VPN երթևեկությունը
Կամրջով անցնող շրջանակները կարող են շրջանցել ձեր դիտարկած IP շղթան։ Համեմատեք բնիկ bridge ընտանիքը հին br_netfilter-ի հետ, նախքան ևս մեկ կանոն ավելացնելը։
Նույն հոսթի վրա երկու վիրտուալ մեքենա LAN-ին հասնում են կամրջով, իսկ ip forward շղթայում դրված կանոնը ցույց է տալիս հաշվիչ, որը երբեք չի շարժվում։ Շրջանակները իրական են, երթևեկությունն անցնում է, և կանոնը պարզապես իր ուղու վրա չէ։ Linux-ի՝ կամրջով անցնող երթևեկությունը ցուցադրելու երկու եղանակների համեմատությունը բացատրում է այս լռությունը, և այն նաև բացատրում է, թե ինչու մեկ հին մոդուլ բեռնելը ավելի վատ պատասխան է, քան թվում է։
Երկու ուղի մեկ հոսթով
Փաթեթը կարող է լքել այս հոսթը երկու շատ տարբեր եղանակներով, և տարբերությունը որոշում է, թե որ կեռիկները կտեսնեն այն։ Եթե նպատակակետը ֆիզիկական պորտից այն կողմ է, և շրջանակը փոխարկվում է կամրջի երկու պորտերի միջև, հոսթը փոխանցում է Ethernet շրջանակ, երթուղավորման կոդը չի հարցվում, և ոչ մի երթուղավորված թռիչք տեղի չի ունենում։ Եթե նպատակակետը հոսթն ինքն է կամ թունելային ինտերֆեյսով հասանելի ցանց, փաթեթը երթուղավորվում է, և IP շերտի կեռիկները իսկապես գործում են։ Պահեք այս պատառաքաղը մտքում, որովհետև շղթաների և ընտանիքների մասին յուրաքանչյուր հետագա հարց բխում է նրանից, թե շրջանակը երկու ուղիներից որն է ընտրում։
Այդ տարբերակումը այն ամբողջ պատմությունն է, որ ընկած է ոչինչ չհաշվող կանոնի հետևում։ Կամրջով անցնող շրջանակը veth9a1-ից enp3s0 անցնում է կամուրջը, ոչ թե IP կույտը, ուստի ip forward շղթան ոչինչ չի տեսնում համապատասխանեցնելու համար։ Ավելի հին օրինակի ինտերֆեյսի անունները չեն որոշում, թե որ ուղին ունեք, և դրա համար էլ առաջին քայլը տոպոլոգիային նայելն է, ոչ թե կանոնների հավաքածուին։
Թունելը ավելացնում է երրորդ դեպք, որն արժանի է անվանման։ TUN սարքը IP փաթեթներ է հանձնում հոսթին, ուստի դրանք երթուղավորվում են և իսկապես անցնում IP շղթաներով, մինչդեռ կամրջին միացված TAP սարքը շրջանակներ է հանձնում և վարվում է կամրջի դեպքի նման։ Սարքի տեսակն է որոշում, ոչ թե արտադրանքի անունը։
Համեմատեք այն երկու ընտանիքները, որոնք կարող են տեսնել կամրջով անցնող շրջանակը
Linux-ը աջակցում է բնիկ կամրջային զտմանը nftables-ի bridge ընտանիքի միջոցով, և թռիչքի ընթացքում շրջանակները ստուգելու ու գցելու համար նրան պետք չէ ոչ մի հին մոդուլ։ Միջուկի սեփական կամրջի փաստաթղթերը ուղղակիորեն տալիս են այդ խորհուրդը, ինչը արժե իմանալ նախքան որոնման արդյունքը ձեզ կասի մոդուլ բեռնել։
| Observation point | What it sees | What it costs |
|---|---|---|
nftables bridge family chains | Ethernet frames forwarded between bridge ports, in both directions | Rules must be written in bridge syntax with link-layer matches |
Legacy br_netfilter plus an ip chain | Bridged IPv4 and IPv6 packets, re-exposed through IP-layer hooks | Existing host rules may begin matching traffic they never saw before |
inet chain for routed traffic | Packets the host routes, including traffic arriving from a TUN device | No visibility into purely switched frames |
iptables-ի փոխարեն nft հրամանն օգտագործելը ինքնին կանոնը չի դնում ճիշտ ընտանիքում։ bridge ընտանիքում հայտարարված շղթան տեսնում է շրջանակները, ip, ip6 կամ inet ընտանիքում հայտարարված շղթան դրանք չի տեսնում, անկախ նրանից, թե որ բինարն է ստեղծել այն։ Ընտանիքը շղթայի հատկությունն է, ոչ թե այն մեքենագրող գործիքինը։
Հին ուղին այլ կերպ է աշխատում, և հենց դա է պատճառը համեմատելու, այլ ոչ թե սովորությամբ կողմ ընտրելու։ br_netfilter բեռնելը և bridge-nf-call կարգավորումների միացումը կրկին բացահայտում են կամրջով անցնող IPv4 և IPv6 երթևեկությունը IP շերտի կեռիկների միջոցով, այնպես որ սովորական iptables կանոնը վերջապես կարող է համապատասխանել դրան։ Շրջանակները չեն փոխվում, փոխվում է այն կեռիկների հավաքածուն, որոնցով դրանք անցնում են, ինչը նշանակում է, որ հոսթի յուրաքանչյուր գոյություն ունեցող կանոն հիմա նոր լսարան ունի։
Կարդացեք փաստացի ուղին նախքան կանոն ավելացնելը
Երեք հրաման հաստատում են, թե որտեղ եք, ինչին է միացված կամուրջը, արդյոք հին մոդուլն ակտիվ է, և ինչ շղթաներ արդեն կան bridge ընտանիքում։ Գործարկեք դրանք նախքան որևէ բան գրելը, որովհետև պատասխանը որոշում է, թե երկու նախագծերից որն եք ընդլայնում։ Այս քայլը բաց թողնելը հենց այն ձևն է, որով ճիշտ կանոնը հայտնվում է մի շղթայում, որով ոչինչ չի անցնում։
bridge link show
lsmod | grep br_netfilter
nft list ruleset | grep -A4 "chain forward"
Ելքը դեպքերը մաքուր բաժանում է։ Կամրջի տակ թվարկված պորտերը ձեզ ասում են, թե որ ինտերֆեյսներն են փոխարկվում, lsmod-ի դատարկ արդյունքը նշանակում է կամրջով անցնող շրջանակների IP շերտի տեսանելիության իսպառ բացակայություն, bridge ընտանիքի գոյություն ունեցող forward շղթան նշանակում է, որ քաղաքականության տերն արդեն կա, և ձեր կանոնը պատկանում է այնտեղ, այլ ոչ թե իր նոր շղթային։
Ապա ավելացրեք մեկ կանոն, որը հեշտ է հետ կարդալ, հաշվիչով և առանց վճիռը փոխելու, և կամրջով անցկացրեք մեկ ներկայացուցչական հոսք։ Շարժվող հաշվիչը ապացուցում է, որ շրջանակը հասել է կանոնին։ Դա այն ամենն է, ինչ այն ապացուցում է, ուստի հետևեք նաև մերժված ուղուն, քանի որ ամեն ինչ ընդունող քաղաքականությունը նույնպես շարժվող հաշվիչ է տալիս։
nft add rule bridge filter forward iifname "veth9a1" oifname "enp3s0" counter acceptՈրտեղ հին մոդուլը փոխում է վարքը
Գործող կամրջի վրա հին ուղին միացնելը տեսանելիություն ավելացնելու չեզոք գործողություն չէ։ Կանոնները, որոնք նախկինում անհասանելի էին կամրջով անցնող երթևեկության համար, դառնում են հասանելի, ներառյալ այլ ինտերֆեյսի համար գրված հոսթի կանոնները, և ip forward շղթայի լռելյայն drop քաղաքականությունը կարող է հանկարծ կիրառվել շրջանակների վրա, որոնք նախկինում անցնում էին անձեռնմխելի։ Այն հոսթի վրա, որը կառավարվում է այդ կամրջով, արդյունքը կոնսոլ չունեցող արգելափակումն է։ Սա հիպոթետիկ խափանման ռեժիմ չէ, սա կեռիկների հավաքածուն ընդլայնելու սովորական հետևանքն է այն մեքենայի վրա, որին հասնում եք հենց նոր ընդլայնված ուղով։
Ավելի անվտանգ հաջորդականությունն է որոշել, թե որ ընտանիքն է տիրում քաղաքականությանը, գրել կանոնները այնտեղ, և պահել անկախ վերականգնման ուղի նախքան որևէ sysctl փոխելը։ Եթե երկու ընտանիքներն էլ կանոններ ունեն, փաստաթղթավորեք, թե որն է հեղինակավոր, երկու համընկնող քաղաքականություններն են այն պատճառը, որ փաթեթը մի տեղ ընդունվում է և մեկ այլ տեղ գցվում՝ առանց մեկ ֆայլ կարդալու հնարավորության։
Մեկուսացումն ինքը դեռ ամբողջական նախագիծ է պահանջում։ Մեկ աղբյուրին մեկ նպատակակետ թույլատրելը միայն ապացուցում է, որ մեկ հոսք աշխատում է, մինչդեռ պահանջը սովորաբար այն է, որ VM-ը չկարողանա հասնել իր հարևաններին կամ հոսթին։ Մերժման կանոնների հաշվիչներն ավելի կարևոր են, քան ընդունման կանոնի հաշվիչը, որովհետև ընդունման հաշվիչն այն է, որն արդեն սպասում էիք, որ կշարժվի։
Վերջապես, հոսթի մուտքի դեպքը պահեք առանձին։ Կամրջի սեփական IP-ին ուղղված երթևեկությունը հասնում է input-ին, ոչ forward-ին, և forward-ի կանոնը երբեք չի տեսնի այն, ինչ ընտանիք էլ ընտրեք։ Երեք դեպք, երկու ընտանիք, մեկ դաս, ուղին որոշում է կեռիկը, և կեռիկը որոշում է, թե ձեր կանոնն ընդհանրապես գոյություն ունի արդյոք։