터널의 클라이언트는 게이트웨이에 도달할 수 있고 게이트웨이는 내부 리졸버에 도달할 수 있으므로 DNS가 작동해야 합니다. 하지만 작동하지 않습니다, 왜냐하면 이는 서로 다른 두 권한이고 작동하는 DNS 서비스는 세 번째 사항이기 때문입니다. 리스너는 클라이언트가 도달할 수 있는 주소에 있어야 하고, 방화벽은 그 주소로의 쿼리를 허용해야 하며, 클라이언트에는 그것을 사용하라고 알려야 합니다. 터널을 양방향으로 여는 것은 처음 두 가지를 우연히 해결하고 세 번째는 미완으로 남깁니다.

리스너는 두 방향을 가진 로컬 서비스입니다

인바운드로 클라이언트는 게이트웨이의 터널 주소 53번 포트로 쿼리를 보냅니다. 아웃바운드로 데몬은 그 쿼리를 설정된 업스트림으로 전달합니다. 두 절반 모두 작동해야 하며 서로 다른 방식으로 실패합니다.

클라이언트가 보고하는 타임아웃과 게이트웨이에서 보이는 타임아웃은 같은 고장이 아닙니다.

터널 주소를 바인딩하고, 모든 주소를 바인딩하지 마세요

이 작업 전용 dnsmasq 인스턴스에는 명시적 수신 주소, 시작 후 터널이 나타나는 것을 견디는 바인딩 모드, 하나의 명확한 업스트림이 필요합니다. 제가 쓰는 가장 작은 버전입니다:

listen-address=127.0.0.1,10.90.0.1
bind-dynamic
no-resolv
no-hosts
server=192.168.50.53

bind-dynamic 개별 주소를 바인딩하고 tun0 나중에 나타날 때도 처리하며, VPN 서비스가 재시작되는 호스트에서는 이것이 중요합니다. loopback을 나열하면 공용 리스너를 추가하지 않고도 로컬 도구가 계속 작동합니다. no-resolv 데몬이 호스트의 리졸버 설정에서 업스트림을 상속하지 못하게 하고, no-hosts 이 인스턴스가 게이트웨이의 hosts 파일을 게시하지 못하게 합니다. 이 옵션 중 어느 것도 누구에게 서비스 쿼리 권한을 주지 않습니다.

두 번째 데몬을 시작하기 전에 53번 포트에 이미 있는 리스너 가 있는지 확인하고, 잘못된 디렉터리의 떠돌이 파일 대신 배포판의 설정 소유자를 사용하세요.

DNS 입력을 허용하고, 터널 통과는 허용하지 마세요

이것을 작동시키는 방화벽 규칙은 터널 인터페이스, 클라이언트 풀, 게이트웨이 주소, 53번 포트로 범위가 한정된 로컬 입력 규칙입니다. 프로토콜마다 하나씩 두 규칙이면 충분합니다:

sudo ufw allow in on tun0 proto udp from 10.90.0.0/24 to 10.90.0.1 port 53
sudo ufw allow in on tun0 proto tcp from 10.90.0.0/24 to 10.90.0.1 port 53

DNS는 UDP뿐 아니라 TCP로도 동작하므로 UDP만 다루는 규칙은 큰 응답이 간헐적으로 보이는 방식으로 실패하게 둡니다. 이것은 ufw route 권한이 아니며 tun0 에 대한 광범위한 허용이 되어서는 안 됩니다. 순서는 내용만큼 중요합니다: tun0 에서 모든 입력을 버리는 이전 규칙이 여전히 이기며, 최종 드롭 아래에 허용을 추가해도 아무것도 만들어지지 않습니다.

게이트웨이 DNS가 이제 설계의 일부라면 그 이전 정책을 의도적으로 검토하고 이유를 기록하세요.

업스트림 절반은 별도의 경로입니다

쿼리는 게이트웨이를 떠나 자체 주소에서 업스트림 리졸버로 향하므로 게이트웨이의 경로와 그 리졸버에 대한 출력 정책이 이 교환을 허용해야 합니다. 이는 클라이언트가 리스너에 도달하도록 하는 규칙과 다른 규칙이며 다른 증상으로 실패합니다.

응답이 작동하도록 무제한 터널 출력을 추가하지 마세요; 추적되는 응답에는 필요하지 않습니다.

옵션을 푸시한 다음 핸드오프를 확인하세요

서버는 푸시된 옵션으로 리졸버를 클라이언트에 알릴 수 있습니다. 그것은 옵션이며 운영 체제가 따라야 하는 지시가 아닙니다:

push "dhcp-option DNS 10.90.0.1"

Linux 명령줄 클라이언트는 연결 관리자의 리졸버 통합이 필요할 수 있고, 관리되는 기기는 관리 프로필 업데이트가 필요할 수 있습니다. 연결 후 클라이언트의 활성 리졸버를 확인하고, 푸시가 적용되었다고 가정하지 마세요. 두 메커니즘이 동시에 DNS를 설정하려 하면 해석이 깜빡이는 것처럼 보이는 경쟁이 생깁니다.

목표는 클라이언트 리졸버 설정의 소유자를 하나로 두는 것이며, 푸시는 보통 클라이언트 플랫폼이 동의할 때만 그 소유자가 됩니다.

실제로 구축한 것을 테스트하세요

사설 정규화된 이름 하나와 허용된 외부 이름 하나를 터널 주소에 직접 UDP와 TCP 모두로 쿼리하세요. 그런 다음 앱의 일반 조회 경로로 반복하세요.

직접 쿼리는 작동하지만 앱이 여전히 실패한다면 고장은 서버가 아니라 핸드오프에 있습니다:

  • 클라이언트는 푸시된 옵션을 한 번도 적용하지 않았습니다.
  • 나중에 다른 리졸버가 설정되어 경쟁에서 이겼습니다.
  • 앱은 자체 리졸버 라이브러리나 캐시된 응답을 사용합니다.

승인된 VPN 경로 밖의 소스가 리스너를 전혀 사용할 수 없음을 확인하며 마무리하세요. 성공적인 해석은 반환된 주소를 승인하지 않으므로 이 두 질문을 분리해 두세요.

관련 글