CRL을 다시 만든 직후 연결이 거부되었다고 클라이언트가 말하니 CRL이 범인처럼 보인다. 아니다. 거부는 전송 계층의 응답이고, 인증서 검증은 이후 터널 핸드셰이크 안에서 일어난다. 시점의 일치는 정황일 뿐 증거가 아니다.

두 가지 점검이 사건을 일 분도 안 되어 갈라놓으며, 둘 다 신뢰 설정을 건드리지 않는다.

오류를 만든 계층에서 읽어라

connect에서 나온 ECONNREFUSED는 전송 시도가 거부되었다는 뜻이다: 무언가가 reset으로 응답했거나, 스택이 도달할 수 없는 포트를 보고했다. 인증서 문제는 그 오류를 만들 수 없다. 전송 연결 없이는 TLS 핸드셰이크가 시작되지 않기 때문이다. 거부가 보인다면 클라이언트는 인증서를 제시할 단계까지 가지도 못한 것이다. 이 한 가지 사실만으로 폐기가 원인이라는 가능성이 배제된다.

반대도 성립한다. 폐기된 인증서는 TCP 연결을 끝까지 맺은 뒤 핸드셰이크에서 실패하며, 서버에는 검증 오류로 기록된다.

TCP 거부: 아무도 듣고 있지 않다

TCP라면 의도한 인스턴스가 실행 중이며 프로필의 주소와 포트에 바인딩되어 있는지 확인한다. ss -lntp은 리스너를 보여 주며, 리스너가 없는 것이 흔한 설명이다. 연결을 버리지 않고 거부하는 방화벽도 클라이언트 쪽에 같은 메시지를 만들기 때문에 둘 다 확인한다.

주소 체계도 확인한다. 127.0.0.1이나 IPv6에만 바인딩된 서비스는 다른 쪽으로 해석되는 클라이언트를 거부한다.

그다음 추측하지 말고 서비스 로그를 읽는다. CA 유지보수 후 재시작이 읽을 수 없거나 없는 파일에서 실패해 수신 상태에 이르지 못할 수 있고, 로그에는 그 파일 이름이 나온다. 이는 시작 실패이며, 거부된 인증서와는 다른 버그다.

UDP에는 거부할 핸드셰이크가 없다

UDP 기반 OpenVPN은 TCP 의미의 연결을 맺지 않으므로 connect 시점에 거부할 것이 없다. Linux에서는 UDP 소켓이 보여 주는 오류가 앞선 데이터그램이 만든 ICMP port-unreachable에서 올 수 있다. udp(7) 매뉴얼 페이지가 그 비동기 동작을 설명한다.

그래서 UDP 클라이언트는 서버 프로세스가 실행 중이지만 기대한 주소에 바인딩되지 않은 상태에서도 거부를 출력할 수 있다.

CRL이 실제로 검사되는 지점

CRL은 TLS 핸드셰이크 중, 상대가 인증서를 제시한 뒤에, 그리고 서버 구성이 허용할 때만 참조된다. OpenVPN의 crl-verify 옵션이 파일을 가리키며, 실패는 서버 로그에 인증서 이름을 붙인 검증 오류로 나타난다.

따라서 폐기된 클라이언트는 전송 계층에서는 연결되고 그다음 인증에서 실패한다. 같은 서버, 같은 포트, 전혀 다른 메시지다.

그 단계에 이르면 CRL의 발급자와 유효 기간을 확인한다. 잘못된 CA가 서명한 CRL, 또는 클라이언트가 연결되기 전에 만료된 CRL은 클라이언트 자신의 인증서와 무관한 검증 오류를 만든다.

다음번을 위한 짧은 런북

먼저 전송을 확인한다: 리스너가 있고, 주소 체계가 맞고, 방화벽이 거부하지 않는지. 그다음 시작 로그를 읽어 서비스가 수신 상태에 이르렀는지 확인한다. 그리고 나서야 검증 메시지를 찾아 핸드셰이크 오류를 본다. 이 순서를 고정하라. 각 단계가 원인의 한 부류를 통째로 제거하기 때문이다.

전송, 해석된 목적지, 포트, 오류의 정확한 문구를 적어 둔다. 클라이언트 재설치는 그 증거를 없애고 보통 아무것도 바꾸지 않는다.

관련 글