რატომ ვერ ხედავს თქვენი 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 |
nft ბრძანების გამოყენება iptables-ის ნაცვლად თავისთავად არ ათავსებს წესს სწორ ოჯახში. 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-ის წესი ვერასოდეს დაინახავს მას, რომელ ოჯახსაც არ უნდა აირჩიოთ. სამი შემთხვევა, ორი ოჯახი, ერთი გაკვეთილი: გზა წყვეტს კაუჭს, და კაუჭი წყვეტს, საერთოდ არსებობს თუ არა თქვენი წესი.