로컬 기본 경로를 유지하려고 한 줄을 추가했더니 그 뒤로 터널이 내부 DNS 서버에 닿지 않습니다. 그 줄은 pull-filter ignore "route"였는데, 이것은 "이 경로를 무시하라"는 뜻이 아닙니다. "텍스트가 그 다섯 글자로 시작하는 모든 푸시된 옵션을 버려라"는 뜻이며, 일반 서버에서는 경로 자체와 함께 route-gateway, route-metric, route-ipv6도 포함됩니다. 아래 체크리스트는 다른 사람이 써야 하는 프로필을 건드리기 전에 제가 실행하는 것입니다.

필터는 푸시된 옵션에만 적용됩니다

pull-filter는 터널이 설정된 뒤 서버가 보내는 옵션 줄에만 작용하며 다른 어떤 것에도 작용하지 않습니다. 로컬 파일에 적은 옵션은 영향을 받지 않고 애플리케이션 트래픽도 마찬가지입니다. 프로세스가 터널을 쓰지 못하게 하려던 것이라면 이것은 완전히 잘못된 도구이고 어떤 필터 조합으로도 되지 않습니다.

이 범위는 유용합니다. 서버 구성을 그대로 두고도 그 일부를 로컬에서 거부할 수 있기 때문입니다. 티켓에 적어 둘 만한 한계이기도 합니다. 필터는 이 클라이언트가 무엇을 받아들이는지를 바꾸는 것이지 서버가 무엇을 제공하는지를 바꾸는 것이 아닙니다. 같은 프로필의 다른 사용자에게는 아무 영향이 없습니다. 이 옵션을 구현하지 않는 다른 클라이언트로 옮기면 유지되지도 않으며, 그 위에 워크플로를 만들기 전에 알아 둘 만합니다.

패턴을 쓰기 전에 서버가 실제로 무엇을 보내는지 확인하세요. 상세도가 높으면 클라이언트가 받은 푸시된 옵션 문자열을 출력하며, 비교하는 정확한 텍스트에 대한 유일한 정직한 출처입니다.

sudo openvpn --config /etc/openvpn/corp.ovpn --verb 4
sudo grep -n 'pull-filter' /etc/openvpn/corp.ovpn

푸시된 줄을 쉼표로 구분된 옵션 목록으로 읽고, 옵션 이름과 인수가 공백으로 구분된다는 점에 주의하세요. 필터 텍스트는 그 스트림과 비교되므로 다음 단계에서 공백이 그렇게 중요합니다.

일치는 접두사이므로 공백이 전부입니다

비교는 문자열 접두사이지 파싱된 옵션 이름이 아닙니다. 따라서 "route"는 route-gateway 10.8.0.1, route-ipv6 2001:db8::/32, route-metric 100와 일치합니다. 끝에 공백을 하나 더하면 의도한 계열로 좁혀지고, 전체 접두사를 넣으면 특정 목적지로 더 좁혀집니다.

Filter textWhat it actually matchesTypical outcome
"route"Every option beginning with those lettersRoutes, gateway, metric and IPv6 routes all dropped
"route "Route entries only, not the hyphenated siblingsThe routes go, the rest survives
"route 10.60."A single destination rangeThe narrowest rule, and the easiest to audit
"dhcp-option DNS"Pushed DNS settingsResolver stays local, internal names stop resolving

마지막 행은 분할 터널 작업 중에 사람들을 잡는 행입니다. 자체 리졸버를 유지하는 것은 정당한 선택이며, 이제 모든 내부 이름이 사설 영역을 볼 수 없는 리졸버에 의존한다는 뜻입니다. 그것은 의도적으로 받아들이는 결과이지 운영에서 발견할 부작용이 아닙니다.

접두사 일치는 규칙이 나중에 조용히 넓어질 수 있다는 뜻이기도 합니다. 서버가 당신의 텍스트로 시작하는 새 옵션을 추가하면, 아무도 프로필을 편집하지 않아도 필터가 그것에 적용되기 시작합니다. 이것이 설계로 대비해야 할 실패 모드이며, 완화책은 옵션의 가능한 한 많은 부분을 일치시키는 것이지 가능한 한 적게가 아닙니다.

세 가지 동사, 세 가지 다른 결과

accept, ignore, reject는 같은 생각의 세 가지 철자가 아닙니다. 일치 시 클라이언트가 무엇을 하는지와 누가 알게 되는지가 다릅니다.

ignore는 일치하는 옵션을 조용히 버리며, 의도적으로 대체한 설정에 원하는 동작입니다. reject는 그것을 버리고 클라이언트가 불평하게 하며, 그 부재가 나중에 발견되는 대신 로그에 보여야 할 때 원하는 동작입니다. accept는 긍정 형태로, 개별 옵션을 제거하는 대신 허용 목록을 만들 때 사용합니다.

어떤 동사를 쓰든 필터는 나타나는 순서대로 적용되므로, 겹치는 두 규칙은 순서에 의존하는 결과를 만들어 검토가 매우 어렵습니다. 의도마다 규칙 하나를 유지하고 각각에 가장 구체적인 텍스트를 넣으세요. 허용 목록이 필요하면 같은 것을 합치는 ignore 규칙 더미보다 몇 개의 accept 규칙을 선호하세요. 그러면 검토자가 파일을 위에서 아래로 읽고 결과를 예측할 수 있으며, 그것이 확장되는 유일한 테스트입니다.

적용된 경로와 리졸버를 확인하고, 프로필은 보지 마세요

파일에서 올바르게 보이는 필터도 유용한 것을 전혀 라우팅하지 않는 터널을 남길 수 있습니다. 푸시된 옵션이 이미 적용되거나 버려진 실행 중인 시스템에서 효과를 확인하세요.

ip route show default
ip route show | grep -c 'proto static'
resolvectl status | grep -A4 'Link.*tun0'
curl -sS -o /dev/null -w '%{http_code}\n' --max-time 5 https://intranet.example.internal/

처음 두 줄은 푸시된 기본 경로가 도착했는지와 정적 항목이 몇 개 살아남았는지 알려 줍니다. 리졸버 질의는 터널 인터페이스가 실제로 어느 서버를 쓰는지 보여 주며, 보통 거기서 DNS 놀라움이 나타납니다. 마지막 줄은 사용자에게 중요한 유일한 질문에 답합니다.

거기 있는 동안 양방향을 모두 시험하세요. 로컬 인터넷은 계속 작동시키면서 내부 이름 해석을 조용히 깨뜨리는 규칙은 피상적인 점검을 통과하고 첫 실제 작업에서 실패하므로, 같은 시험에 내부 리소스 하나와 공개 사이트 하나를 넣으세요.

예외와 그 소유자를 기록하세요

필터는 운영자의 설계에 대한 예외이므로 이유와 검토 시점을 적어 두세요. "로컬 기본값을 유지하려고 푸시된 경로를 무시한다"는 검토 가능합니다. 프로필의 맨 줄 하나는 그렇지 않으며, 다음 사람이 그것을 지우거나 추측으로 확장할 것입니다.

버전도 여기서 중요합니다. 일치 동작과 정확히 허용되는 문법은 OpenVPN 2.4, 2.5, 2.6에서 다듬어졌으므로, 배포하는 빌드의 설명서로 패턴을 확인하고 구버전에 관한 포럼 글로 확인하지 마세요. OpenVPN 2.6 설명서가 이 옵션과 일치 규칙을 문서화합니다.

마지막으로, 서버를 운영하는 사람과 예외를 합의하세요. 의도된 서버 정책과 모순되는 클라이언트 측 필터는 다음 감사를 기다리는 지원 사건이며, 프로필이 배포된 뒤 누군가 경로가 빠진 것을 알아차린 뒤 해결하는 것보다 배포 전에 정리하는 편이 훨씬 쌉니다.

관련 글