OpenVPN 클라이언트 차단 규칙이 FORWARD에 닿지 않는 이유
클라이언트 간 트래픽은 OpenVPN 프로세스 안에 머물러 호스트의 FORWARD 체인을 지나지 않을 수 있으므로 카운터가 0이라고 해서 아무것도 증명되지 않는다.
같은 OpenVPN 서버에 있는 두 클라이언트는 그들의 풀에 DROP 규칙을 추가한 뒤에도 서로 통신할 수 있다. 규칙은 FORWARD 체인에 있고 트래픽은 분명히 흐르는데도 그 규칙의 카운터는 영에 머문다. 자연스러운 결론은 방화벽이 고장 났다는 것이다. 그러나 대개는 패킷이 체인에 아예 들어가지 않았다.
OpenVPN 서버를 지나는 피어 패킷이 갈 수 있는 경로는 두 가지이며, 그것은 방화벽이 아니라 설정이 결정한다. 어느 경로가 사용 중인지 알면 호스트 규칙이 올바른 위치에 있는지조차 알 수 있다.
피어 패킷이 갈 수 있는 두 경로
내부 전달 옵션이 꺼져 있으면 클라이언트 A의 패킷이 클라이언트 B에 할당된 주소 안을 목적지로 하여 터널 인터페이스로 도착한다. 서버의 라우팅 테이블은 B 주소로 가는 경로를 서버가 가지고 있기 때문에 같은 터널 인터페이스로 그대로 다시 보낸다. 이것이 호스트를 거쳐 들어오고 나가는 흐름이며, IPv4 전달 경로가 이를 평가한다.
내부 전달 옵션이 켜져 있으면 서버 프로세스가 패킷을 연결된 클라이언트와 짝지어 그 클라이언트에게 직접 다시 쓴다. 패킷은 데몬 안에서 처리되고 터널 장치로 다시 들어가지 않으므로 호스트의 전달 경로는 완전히 건너뛰어진다. OpenVPN 2.6 설명서는 이 옵션을 내부 클라이언트 간 전달이라고 부르며, 호스트 방화벽 규칙이 그것을 볼 수 없는 이유가 바로 여기에 있다.
데이터 채널을 커널 모듈로 오프로드하는 구성에는 세 번째 변형이 있다. 전달 결정과 암호화가 사용자 공간을 떠나고, netfilter가 그 흐름을 보는지는 오프로드 경로가 어떻게 만들어졌는지에 달려 있다. 오래된 규칙 집합이 오프로드된 서버에서 사용자 공간 서버와 똑같이 동작한다고 절대 가정하지 말라. 모드는 패키지 버전이 아니라 실행 중인 설정에서 확인하라.
카운터가 전혀 움직이지 않을 때
카운터가 영이라는 것은 그 지점에서 패킷이 그 규칙과 일치하지 않았다는 뜻이며 이유는 여러 가지다. 첫째는 위에서 말한 우회로로, 트래픽이 체인에 도달하지 않았다. 둘째는 인터페이스, 방향, 출발지 또는 목적지의 불일치로, 풀이 다시 번호가 매겨졌는데 규칙이 아직 옛 접두사를 가리킬 때 흔하다.
셋째는 위치다. 체인 앞쪽의 규칙이 당신의 DROP이 평가되기 전에 흐름을 받아들일 수 있고, 뒤쪽의 규칙이 실제로 결과를 결정하는 규칙일 수 있다. 카운터가 보이도록 체인을 순서대로 읽고, 테스트를 반복할 때 어느 규칙의 수가 늘어나는지 확인하라.
실제 주소를 기억 속의 임대가 아니라 서버 자체의 상태에서 확인한 두 클라이언트 사이에서 통제된 교환을 한 번 수행하라. 해당 카운터가 여전히 움직이지 않으면 일치 조건을 다시 쓰기 전에 경로를 의심하라. 움직이는데도 연결이 성공한다면 드롭이 나중에 덮어써지고 있으며 문제는 순서에 있다. 그 답이 수리가 규칙 변경인지 토폴로지 변경인지를 결정하므로 무엇이든 편집하기 전에 얻어야 한다.
필터할 수 있는 경계 고르기
정책이 꼭 호스트 방화벽에 있어야 한다면, 방화벽이 볼 수 있는 곳에 트래픽을 두어라. 내부 전달을 끄는 것이 피어 트래픽을 터널 인터페이스와 전달 경로로 지나가게 하는 지원되는 방법이며, 대가로 모든 피어 패킷이 호스트 스택을 거친다.
그다음 흐름을 정확히 일치시켜라. 트래픽은 양방향 모두 터널 인터페이스로 들어와 터널 인터페이스에서 나가므로, 물리 인터페이스만 고려하는 규칙은 일치하지 않는다. 주소 기반 규칙에는 현재 풀이 필요하고, 되돌아오는 방향도 나가는 방향만큼 고려해야 한다.
많은 구성에서는 클라이언트나 그룹 수준에서 필터링하는 편이 낫다. 거기서는 신원이 알려져 있고 정책이 재접속 때 바뀌는 주소가 아니라 사용자를 따르며, 이것은 호스트 체인과 다른 메커니즘이므로 분명한 이유 없이 둘을 섞어서는 안 된다.
옛 토폴로지의 규칙 집합을 마이그레이션에서 그대로 가져오지 말라. 주소 풀, 인터페이스 이름, 전달 모드는 모두 규칙이 일치하는지에 영향을 주며, 예전에 동작하던 복사된 규칙은 가장 오해를 부르는 종류의 증거다. 허용하려는 흐름에서 시작해 그것과 일치하는 규칙을 작성하라.
규칙을 믿는 대신 격리를 시험하기
금지된 경우와 허용된 경우를 같은 실행에서 시험하라. 한 클라이언트에서 다른 클라이언트로 새 연결을 시작해 실패하는지 확인하고, 그다음 허용되어야 할 연결이 여전히 동작하는지 확인하라. 첫 번째만 시험하면 모든 것을 막는 방화벽이 성공처럼 보인다.
서버 설정을 다시 불러온 뒤와 클라이언트가 재접속한 뒤에 반복하라. 내부 전달과 풀 할당은 실행 시간 상태이므로 카운터를 양방향으로 확인해야 하며, 한 방향과는 일치하고 응답과는 일치하지 않는 규칙은 빠른 시험에서 알아채기 어려운 부분 격리를 만든다.
격리는 흐름을 실제로 나르는 경계에서 관측된 결과다. 호스트 어딘가의 DROP 규칙은 증거가 아니며, 실패한 연결과 그것을 일으킨 규칙의 움직인 카운터가 증거다.