핸드셰이크가 완료되고 클라이언트가 최근 전송 카운터를 보여 주는데도 같은 서버의 서비스로 보낸 요청이 실패한다. 이 조합이 사람들을 혼란스럽게 하는 이유는 터널이 분명히 동작하기 때문이다. 증명되지 않은 것은 로컬 전달이며, 패킷은 호스트에 도착했지만 호스트는 여전히 그것을 올바른 소켓에서 받아들여 응답 권한이 있는 프로세스로 넘겨야 한다. 이 세 지점을 순서대로 확인하자.

성립하지 않는 첫 지점에서 멈추고, 나머지를 위해 규칙을 추가하지 말 것.

핸드셰이크는 터널만 증명한다

WireGuard의 핸드셰이크는 피어 사이에 키를 세우고 각 피어가 나열한 대역에 대해 트래픽을 허용한다. 서버에서 어떤 프로세스가 수신 중인지는 말하지 않고, 호스트 방화벽이 자기 주소 중 하나로 온 패킷을 받아들이는지도 말하지 않는다.

가장 자주 놓치는 마지막 구분은 호스트 자체로 가는 트래픽은 로컬 입력이고 호스트를 거쳐 다른 곳으로 가는 트래픽은 포워딩이라는 것이다. 둘은 서로 다른 방화벽 체인과 다른 설정으로 처리된다. 잘못된 체인을 확인하면 오후가 사라지고 무해해 보이는 카운터가 돌아온다.

수신자와 경로를 읽는다

클라이언트에서 서버의 터널 주소가 터널로 라우팅되는지 확인한다. 서버에서 클라이언트가 쓰는 주소에 소켓이 있는지, 그 뒤의 프로세스가 의도한 것인지 확인한다.

wg show
ip route get 10.66.0.1
ss -lntup | grep -E ':80|:443'
nft list ruleset | grep -A6 'chain input'
curl -vk --max-time 5 https://10.66.0.1/

127.0.0.1 에서 수신하는 것은 방화벽이 무엇을 허용하든 10.66.0.1 로 보낸 요청에 절대 응답하지 않는다. 와일드카드 주소에서 수신하는 것은 규칙이 막지 않는 한 응답한다. 따라서 소켓 목록은 어떤 규칙을 보기도 전에 절반의 사례를 정리한다. 포트와 주소가 함께 요청이 도달할 수 있는지를 결정한다.

클라이언트가 쓰는 주소를 서버가 터널 인터페이스에서 실제로 가진 주소와 비교한다. 어느 한쪽의 오래된 설정은 그 주소가 없는 피어로 올바르게 라우팅된 요청을 만든다.

포워딩이 아니라 로컬 입력에 규칙을 적용한다

패킷이 도착하고 소켓이 있으면 남은 경계는 입력 정책이다. 포워딩을 허용하는 규칙은 로컬 전달을 허용하지 않고, 하나의 인터페이스로 제한된 규칙은 기대하는 터널 인터페이스 이름과 맞지 않을 수 있다.

호스트를 여는 대신 의도한 서비스로 허용된 포트 하나로 시험한다. 그다음 허용 목록, 계정 요구 사항, 특정 호스트 이름에 대한 바인딩이 네트워크가 성공적으로 전달한 요청을 거부할 수 있으므로 애플리케이션 자체의 인가를 확인한다.

인증서 검사를 그대로 두어라. 예상치 못한 인증서 신원은 어느 호스트가 응답했는지에 대한 정보이지 피해야 할 장애물이 아니다. 클릭해서 넘어가면 잘못된 서비스를 식별하는 유일한 단서가 가려진다.

이름, 크기, 신원 실패를 나눈다

주소로는 동작하지만 이름으로는 실패하는 서비스는 DNS 문제이며, 수정은 방화벽이 아니라 클라이언트로 배포하는 리졸버 설정에 속한다. 작은 요청에는 응답하지만 큰 응답에서 멈추는 서비스는 패킷 크기와 MTU를 가리키며, 이는 전혀 다른 조사다.

잘못된 호스트를 지목하는 HTTPS 오류는 보통 요청이 다른 서비스에 도달했음을 뜻하며, 흔히 프록시나 다른 수신자가 그 포트를 점유하고 있기 때문이다. 인증서의 주체를 읽고 도달하려던 호스트와 비교하라. 그 비교는 비용이 들지 않고 조사를 끝내는 경우가 많다.

소켓, 입력 규칙, 애플리케이션 정책 중 어느 지점에서 실패했는지 기록한다. 그 한 줄이 네트워크 결함과 인가 결정을 구분한다. 다음 사람이 문제가 아니었던 포트를 여는 것도 막는다.

관련 글