Pi-hole v6는 포트 53에서 DNS 쿼리를 받은 다음 도착한 패킷에 응답해도 되는지 판단합니다. WireGuard 호스트에서는 이 두 번째 판단 때문에 클라이언트가 시간 초과를 겪는 반면 LAN에서는 리졸버가 정상으로 보입니다. 포트는 열려 있고 FTL도 실행 중이지만 10.90.0.1에서는 아무것도 돌아오지 않습니다. 응답이 나가기 전에 세 가지가 함께 작용합니다: dns.interface, dns.listeningMode 그리고 둘 앞에 있는 방화벽입니다.

수신 소켓은 누가 응답을 받는지 결정하지 않습니다

FTL은 포트 53에서 UDP와 TCP 리스너를 엽니다. 기본 구성에서 소켓은 흔히 wildcard이므로 ss -lunp | grep :53 는 VPN 클라이언트에 서비스하든 아니든 0.0.0.0:53과 [::]:53을 보여 줍니다. wildcard 소켓이 패킷을 받아들이고, 그다음 FTL이 응답하기 전에 인터페이스와 출발지 규칙을 적용합니다. 그래서 "포트가 수신 중"이라는 말은 터널 클라이언트에 대해 거의 아무것도 증명하지 못합니다.

활성이라고 생각하는 파일이 아니라 실행 중인 구성을 읽으십시오. pihole-FTL --config dns.interface 그리고 pihole-FTL --config dns.listeningMode 는 실제 값을 출력하며, 컨테이너나 환경 변수, 배포 관리자가 그 설정을 소유하면 호스트 파일과 다를 수 있습니다. Pi-hole FTL 구성 참고서 는 모드와 그중 어느 것이 인터페이스를 기준으로 하는지 나열합니다.

LOCAL은 서브넷을 묻고, SINGLE은 인터페이스를 묻습니다

기본값인 LOCAL은 출발지 주소가 호스트 인터페이스 중 하나에 구성된 서브넷에 속하는 쿼리에 응답합니다. 10.90.0.1/24인 단순한 wg0는 이 시험을 통과합니다. 10.90.0.2의 클라이언트가 터널 서브넷 안에 있기 때문입니다. 피어 반대편에서 라우팅된 클라이언트나 다른 프리픽스에서 NAT 뒤에 숨은 클라이언트는 패킷이 wg0에 도착했더라도 통과하지 못하며, 로그에도 쿼리가 나타나지 않습니다.

SINGLE은 질문을 바꿉니다. dns.interface 에 지정된 인터페이스로 들어오는 쿼리를 루프백까지 포함해 받아들이고 출발지 서브넷은 무시합니다. 연결되거나 라우팅된 VPN 구성에서 살아남는 모드가 이것입니다. 모드만으로는 완전한 지시가 아니므로 두 키를 함께 설정하십시오:

sudo pihole-FTL --config dns.interface "wg0"
sudo pihole-FTL --config dns.listeningMode "SINGLE"

BIND는 소켓을 바꾸고, 그것에는 대가가 따릅니다

BIND는 wildcard 소켓을 걸러 내지 않습니다. 지정한 인터페이스에 존재하는 주소에만 포트 53을 묶으므로 다른 곳으로 온 패킷은 커널이 거부합니다. SINGLE보다 엄격하며 그 동의어가 아닙니다. 대가는 부팅 때 드러납니다. FTL이 시작할 때 wg0가 올라와 있지 않으면 묶을 주소가 없을 수 있고, 인터페이스가 나타나 FTL이 다시 시작될 때까지 리졸버가 리스너 없이 동작할 수 있습니다.

시작 순서를 제어할 때 BIND를 고르십시오. 예를 들어 WireGuard 인터페이스 뒤에 정렬한 systemd 유닛을 쓸 때입니다. 커널이 FTL이 보기 전에 떠돌이 패킷을 버리게 하고 싶을 때도 마찬가지입니다. 터널이 자주 오르내리거나 FTL보다 늦게 시작하는 도구가 인터페이스를 만들 때는 SINGLE을 고르십시오.

방화벽은 두 번째 관문입니다

올바른 FTL 모드라도 호스트 방화벽이 wg0의 포트 53을 버리면 실패합니다. 두 프로토콜 모두에 VPN 출발지 범위를 허용하고 인터넷 쪽은 닫아 두십시오. inet filter 테이블의 기존 input 체인을 쓰는 nftables에서는 규칙이 이렇게 됩니다:

sudo nft add rule inet filter input iifname "wg0" ip saddr 10.90.0.0/24 udp dport 53 accept
sudo nft add rule inet filter input iifname "wg0" ip saddr 10.90.0.0/24 tcp dport 53 accept

터널이 IPv6를 나른다면 대응하는 IPv6 규칙을 추가하고 체인의 drop 정책 앞에 두십시오. 호스트가 ufw나 firewalld를 쓴다면 도구를 섞지 말고 그 관리자에서 같은 일치를 표현하십시오. 인터넷 라우터에서 포트 53을 전달하지 마십시오. 클라이언트는 터널을 통해 리졸버의 VPN 주소에 도달해야 합니다.

두 경로는 분리된 채로 남습니다. 클라이언트 쿼리는 FTL에서 끝납니다. FTL 자체의 업스트림 조회는 호스트 라우팅 테이블에 따라 나가며 터널을 쓸 수도 쓰지 않을 수도 있으므로, 응답하지만 쓸모 있는 것을 돌려주지 않는 리졸버는 업스트림 문제입니다. 웹 관리 화면과 API는 자체 포트에서 수신하며 자체 제한이 필요합니다.

응답과 거부를 확인하십시오

VPN 클라이언트에서 두 프로토콜 모두로 리졸버 주소를 질의하십시오: dig @10.90.0.1 example.com 그리고 dig +tcp @10.90.0.1 example.com. 그다음 관리 화면의 쿼리 로그에서 FTL이 쿼리를 기록했는지 확인하십시오. 로그 항목 없이 클라이언트가 시간 초과하면 방화벽이나 인터페이스 필터를 가리키고, 응답 없는 로그 항목은 업스트림 해석을 가리킵니다.

VPN 밖의 호스트에서 거부 경로를 시험하십시오. dig @10.90.0.1 example.com 는 시간 초과해야 하고, ss -lunp 는 리졸버에서 포트 53이 공용 주소에 묶인 것으로 보이지 않아야 합니다. 서비스를 한 번 다시 시작한 다음 호스트를 재부팅하고 wg0가 다시 나타난 뒤에도 리졸버가 응답하는지 확인하십시오. 다음 재부팅까지만 동작하는 쿼리는 끝난 변경이 아닙니다.

관련 글