의도는 합리적입니다: 한 회사 도메인의 모든 트래픽을 터널로 보내고 나머지는 그대로 두려는 것입니다. 편집 중인 지시문은 라우트를 설치하며, 라우트에는 비교할 호스트 이름이라는 개념이 없습니다. 여기에 와일드카드를 쓰려는 모든 시도는 구문 분석 오류를 내거나, 더 나쁘게는 이름이 하나의 주소로 확인되었기 때문에 오늘 우연히 동작하는 라우트를 만듭니다. 서로 다른 두 메커니즘에게 상대의 일을 하라고 요구하는 셈입니다.

라우트가 설치하는 것, 그리고 결코 읽지 않는 것

라우트 항목은 목적지 접두사가 인터페이스를 통해 도달 가능하다고 말합니다. 커널은 패킷을 그 접두사들과 비교하므로 관련된 식별자는 주소와 마스크뿐입니다. 호스트 이름은 전달 결정에 결코 나타나지 않으며, 그래서 거기서 패턴을 비교할 수 없습니다.

OpenVPN은 일부 라우트 매개변수에서 확인 가능한 이름을 받아들일 수 있으며, 그 관용이 혼란의 원천입니다. 이름은 구성이 적용되는 동안 확인되어 일반 라우트가 되는 하나 이상의 주소를 만들어 냅니다. 그 후 이름은 그림에서 완전히 사라집니다.

따라서 이름으로 만든 라우트는 규칙이 아니라 스냅샷입니다. 터널이 시작된 순간 그 이름이 확인된 대상만을 포함하며, 변화하는 호스트 집단에 원하지 않는 바로 그 동작입니다. 내일 옮겨 갈 레코드는 라우트를 어제를 가리킨 채로 남깁니다.

목적지가 정말 접두사일 때

대상이 알려진 사설 네트워크라면 접두사를 쓰세요: 문서화 공간의 예를 들면, 단일 호스트와 서브넷은 다음과 같습니다.

route 10.60.4.20 255.255.255.255
route 10.60.0.0 255.255.0.0

두 항목 모두 주소와 마스크를 지정하며, 둘 다 이름에 의존하는 부분이 없어 DNS 변경을 견딥니다. 이것이 장점의 전부입니다: 라우트는 한 번 일어난 조회가 아니라 토폴로지에 대한 진술입니다.

하나의 DNS 응답에서 큰 접두사를 추론하지 마세요. 하나의 주소로 확인되는 하나의 호스트 이름은 그 뒤에 있는 네트워크 크기에 대해 아무것도 알려주지 않으며, 추측한 접두사는 터널이 아무도 의도하지 않은 트래픽을 붙잡게 되는 방식입니다. 조회에서 추론하는 대신 네트워크 소유자에게 실제 접두사를 물으세요.

작업 단위가 호스트 이름일 때

도메인으로 선택하려면 도메인을 읽는 무언가, 즉 애플리케이션 계층 구성 요소가 필요합니다. 일반적인 답은 터널 건너편에 있는 HTTP 프록시이며, 클라이언트가 어떤 요청을 보낼지 고릅니다.

프록시 구성 파일이 그 선택을 표현할 수 있습니다: 아래 예시 규칙은 하나의 도메인과 그 하위 도메인을 프록시로, 나머지 전부를 직접으로 보냅니다.

function FindProxyForURL(url, host) {
    var h = host.toLowerCase();
    if (h === "corp.example" || dnsDomainIs(h, ".corp.example")) {
        return "PROXY 10.60.0.12:3128";
    }
    return "DIRECT";
}

정확한 이름 비교는 도메인 자체를 포함하고, 접미사 비교는 비슷한 문자로 끝나기만 하는 이름과 일치하지 않으면서 그 자식들을 포함합니다. 둘 다 필요하며, 하나를 빼면 올바르게 보이지만 정점이나 사칭자를 건너뛰는 규칙이 됩니다.

이 규칙들은 프록시를 선택하며, 프록시를 만들지 않고 운영체제의 라우트도 바꾸지 않습니다. 프록시 주소는 여전히 터널을 통과하는 자체 경로가 필요하고, 직접으로 표시된 요청은 머신에 이미 있는 라우팅 정책을 따릅니다.

프록시 옵션이 다루지 않는 것

브라우저의 프록시 구성을 무시하는 프로그램은 이 모든 것의 영향을 받지 않습니다. 명령줄 도구, 업데이터, 자체 네트워크 스택을 가진 애플리케이션은 PAC 파일이 아니라 라우트 테이블을 사용하므로, 그런 경우에는 지원되는 애플리케이션별 메커니즘이나 다른 설계가 필요합니다. 브라우저 규칙이 워크플로를 다룬다고 약속하기 전에 중요한 클라이언트를 목록화하세요.

직접으로 돌아가는 것도 탈출구가 아닙니다. 머신의 라우팅 정책이 이미 모든 것을 터널로 보내고 있다면, 직접으로 표시된 요청은, 프록시 선택과 라우트 테이블이 서로 다른 계층에서 내려지는 별개의 결정이기 때문에, 그 안에 남습니다.

이름 확인은 세 번째 별도의 질문입니다. 어떤 요청이 프록시로 갈지 고르는 것은 어떤 리졸버가 그에 답하는지에 대해 아무것도 말하지 않으며, 둘을 하나의 설정으로 다루면 외부에서 누군가 시험할 때까지 보이지 않는 누출이 생깁니다. 각 쿼리가 어디서 답해지는지 정하고 그 결정을 프록시 규칙 옆에 적으세요. 터널이 올라와서 바뀌는 리졸버는 조용히 답을 옮깁니다.

두 경로 모두 시험하기, 좋은 쪽만이 아니라

일치해야 하는 호스트 이름, 일치하지 않아야 하는 호스트 이름, 그리고 접미사만 쓰는 규칙이 가장 자주 놓치는 도메인의 정점을 시험하세요. 그런 다음 페이지가 로드되었는지로 추론하는 대신 각 요청이 실제로 어느 경로를 탔는지 확인하세요.

마지막으로 실패 분기를 시험하세요. 도달할 수 없는 프록시는 조용히 직접 연결로 되돌아가는 대신 미리 정한 방식으로 실패해야 합니다. 네트워크 옵션 참조는 라우트 매개변수를 정확히 문서화하며, 이 설계의 도메인 절반은 완전히 그 바깥에 있습니다.

관련 글