iptables 규칙이 브리지된 VPN 트래픽을 절대 보지 못하는 이유
브리지된 프레임은 감시 중인 IP 체인을 우회할 수 있습니다. 다른 규칙을 추가하기 전에 네이티브 bridge 패밀리와 오래된 br_netfilter를 비교하세요.
같은 호스트의 가상 머신 두 대가 브리지를 통해 LAN에 도달하는데, ip forward 체인에 넣은 규칙의 카운터는 전혀 움직이지 않습니다. 프레임은 실제이고 트래픽도 지나가고 있는데 규칙이 그저 경로 위에 없을 뿐입니다. Linux가 브리지 트래픽을 드러내는 두 방식을 비교하면 이 침묵이 설명되고, 오래된 모듈 하나를 읽는 것이 보기보다 나쁜 답인 이유도 설명됩니다.
호스트 하나를 지나는 두 경로
패킷이 이 호스트를 떠나는 방식은 크게 두 가지이며, 그 차이가 어떤 훅이 패킷을 보는지를 결정합니다.목적지가 물리 포트 너머에 있고 프레임이 브리지의 두 포트 사이에서 스위칭되면 호스트는 이더넷 프레임을 전달하고, 라우팅 코드는 호출되지 않으며 라우팅된 홉도 발생하지 않습니다.목적지가 호스트 자신이거나 터널 인터페이스로 도달하는 네트워크라면 패킷은 라우팅되고 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로 향하는 트래픽은 forward가 아니라 input에 도착하며, 어느 패밀리를 고르든 forward의 규칙은 그것을 절대 보지 못합니다.세 경우, 두 패밀리, 한 가지 교훈으로, 경로가 훅을 결정하고 훅이 규칙의 존재 여부를 결정합니다.