VPN 두 개를 연결하기: 무엇을 가리고 무엇을 치르는가
중첩 터널은 누가 어느 끝점을 보는지를 바꿀 뿐, 누가 당신을 보는지를 바꾸지 않는다. 안쪽 끝점을 바깥 터널로 통과시키고 DNS, MTU, 대체 경로를 확인하라.
터널을 두 겹으로 쌓아도 익명이 되지는 않는다. 그것이 하는 일은 관측을 두 제공자에게 나누는 것이다. 그래서 어느 쪽도 당신의 집 주소와 목적지를 동시에 보지 못한다. 이는 실제이지만 좁은 이점이며, 처음으로 이것에 의존할 때 드러나는 라우팅, DNS, MTU 문제를 동반한다.
1. 두 번째 홉이 무엇을 위한 것인지 정하라
무엇이든 설정하기 전에 목표를 한 문장으로 적어라. ISP가 당신이 어떤 사이트를 방문하는지 보지 못하게 하는 것이 목표라면 터널 하나로 충분하다. 어떤 단일 제공자도 당신의 주소와 트래픽을 연결하지 못하게 하는 것이 목표라면 둘이 필요하다. 아무도 당신을 식별할 수 없게 하는 것이 목표라면, 홉을 몇 개 쌓아도 거기에는 닿지 않는다.
사슬의 강도는 더 약한 제공자의 로그와 두 회사가 보관하는 계정 기록만큼이다. 결제, 가입 이메일, 앱 텔레메트리는 터널 완전히 밖에 있다.
2. 안쪽 끝점을 바깥 터널을 통해 도달 가능하게 만들어라
흔한 실패는 안쪽 터널이 아예 수립되지 않는 것이다. 전체 터널 바깥 연결이 기본 경로를 차지하므로, 안쪽 클라이언트가 자기 끝점에 도달하려는 시도는 바깥 터널에 삼켜져 버려지거나 루프에 빠진다. 안쪽 끝점에는 바깥 인터페이스를 통한 명시적 경로가 필요하고, 이는 안쪽 클라이언트가 시작되기 전에 설치되어야 한다. 그렇지 않으면 핸드셰이크가 경로와 경쟁하다 진다.
WireGuard는 같은 충돌을 반대 방향에서 보여 준다. 각 피어의 AllowedIPs 는 어떤 목적지가 그 터널로 들어가는지를 정하므로, 모든 주소를 주장하는 안쪽 인터페이스는 더 구체적인 경로가 이기지 않는 한 바깥 끝점도 주장한다. 두 인터페이스에 걸친 AllowedIPs 의 중복은 한쪽이 조용히 지는 구성이다.
컨테이너 연결은 분리를 명시적으로, 함정을 뚜렷하게 만든다. 자체 네임스페이스와 자체 기본 경로, 내부 클라이언트를 가진 컨테이너는 호스트가 보낸 것을 전달한다. 호스트 스스로 그 경로를 쓰기 시작하지는 않는다. 포워딩을 켜고, 컨테이너 터널용 경로를 추가하고, 서비스를 컨테이너 주소로 향하게 하라.
3. DNS를 같은 경로에 두라
DNS는 트래픽이 가는 곳으로 가야 한다. 안쪽 제공자가 리졸버를 밀어 넣는데 호스트가 여전히 로컬 리졸버에 묻는다면, 그 조회는 터널이 숨기려던 사이트를 정확히 드러낸다. 클라이언트 상태 패널을 믿는 대신 각 터널 인터페이스에서 캡처로 확인하라. 여기서의 유출은 평소 브라우징에서는 보이지 않고 캡처에서는 뚜렷하다.
분할 DNS 설계는 이것을 어렵게 만든다. 로컬 이름에 대한 질의가 정당하게 터널 밖에 속할 수 있기 때문이다. 어떤 리졸버가 우연히 응답했는지로 예외 목록을 발견하지 말고 의도적으로 작성하라.
4. 사용자가 대신 알게 되기 전에 MTU를 설정하라
MTU는 또 하나의 예측 가능한 희생자다. 두 번 캡슐화하면 헤더가 둘 줄고, 경로 MTU를 이미 낮춘 바깥 터널은 안쪽 공간을 더 줄인다. 증상은 익숙하다. 작은 요청은 통과하고 큰 전송과 TLS 핸드셰이크가 멈춘다.
ip link set dev wg1 mtu 1280 는 거친 해법이고, 포워더에서 MSS를 조이는 것이 더 깔끔하다. 연결을 다시 시도하는 것은 해법이 전혀 아니다.
5. 실제로 겪을 장애를 시험하라
바깥 터널을 일부러 끊고 무슨 일이 일어나는지 보라. 바깥 홉이 죽을 때 조용히 직접 경로로 떨어지는 사슬은 사슬이 없는 것보다 나쁘다. 당신이 보호받는다고 믿은 바로 그 순간에 유출되기 때문이다. 목표로 삼을 동작은 모든 트래픽을 멈추는 킬 스위치다. 결과를 기록하라. 장애 한복판에서 그것을 다시 발견하고 싶지는 않을 것이다.
지연과 두 번째 장애 지점은 상시 비용이다. 두 홉은 불편한 시간에 뭔가 고장 났을 때 지원 창구가 둘이라는 뜻이기도 하다.