누군가 프로필을 보내고, 당신이 그것을 가져오고, 삼십 초 뒤에는 아무도 확인하지 않은 목적지로 클라이언트가 접속하고 있다. 먼저 텍스트 편집기에서 파일을 읽어야 한다. 중요한 모든 것이 몇 개의 지시문에 담겨 있기 때문이다: remote, proto, port, ca, cert, tls-crypt, verify-x509-name. 나머지는 모두 기본값이며, 바로 그곳에 뜻밖의 일이 도사린다.

파일이 사용할 수 있는 모든 엔드포인트를 나열하라

엔드포인트부터 시작하라. 하나의 프로필에 여러 개가 들어 있을 수 있기 때문이다. grep -nE '^[[:space:]]*(remote|proto|port|remote-random|connection)' profile.ovpn 는 파일 순서대로 모든 후보를 출력하며, 인라인 <connection> 블록 안에 중첩된 것도 포함한다.

지시문이 포트를 생략하면 클라이언트는 수신기의 기본값으로 돌아가므로, remote vpn.example.com 만으로도 포트 1194를 뜻하며 파일 뒤쪽에 어떤 proto 이 나오든 상관없다. 여러 개의 단순한 remote 줄은 대안이다. 클라이언트는 remote-random 이 순서를 섞지 않는 한 차례로 시도하며, 다른 사업자의 호스트를 조용히 대체하는 일은 없다. 서로 무관한 도메인을 가리키는 remote 줄이 둘이라면, 어느 쪽이 의도된 것인지 멈춰서 물어야 할 지점이다.

proto 의 철자도 살펴보라. tcp 은 클라이언트 측 tcp-client 의 동의어로 받아들여지지만, 클라이언트 프로필에서 tcp-server 은 깔끔하게 실패하기보다 멈춰 버리는 구성 오류다.

먼저 이름을, 다음으로 포트를 확인하라

dig +short vpn.example.com 은 이름이 존재하는지, 어떤 주소를 반환하는지 알려 준다. 멀티홈이나 프록시 뒤의 엔드포인트가 여러 개를 반환하는 것은 정당하다. 이름 확인은 전제 조건일 뿐 소유권의 증거가 아니다. 누구나 이름을 어떤 주소로 향하게 할 수 있고, 하나의 주소가 여러 이름의 응답을 맡을 수 있다.

그다음 찾은 포트에서 수신기를 확인하라. 전송 계층에 맞춰야 한다. TCP 에서는 openssl s_client -connect vpn.example.com:1194 -servername vpn.example.com 이 서버가 제시하는 체인을 출력한다. UDP 에서는 DTLS 가 필요하다. openssl s_client -dtls1_2 -connect vpn.example.com:1194 이 데이터그램 위에서 같은 핸드셰이크를 수행한다. 완료된 핸드셰이크는 무언가가 수신 중이고 인증서를 보유하고 있음을 증명한다. 그것은 ping 이 보여 주는 것보다 많고, 프로필 자체의 신뢰 설정이 요구하는 것보다는 적다.

핸드셰이크가 실패하는데 호스트가 ping 에 응답한다면 포트가 틀렸거나 필터링된 것이다. 그것을 올바른 포트를 요청할 이유로 삼고, 근처 포트를 훑을 초대로 받아들이지 말라. nc -vzu 도 일부 스택에서는 아무것도 수신하지 않는데 성공을 보고하므로, 뒤에 핸드셰이크가 없는 맨 UDP 탐침은 아무 의미도 없다.

신뢰 핀은 주소와 따로 읽어라

주소는 클라이언트가 어디로 가는지를 정하고, 신뢰 블록은 도착한 뒤 누구를 믿을지를 정한다. verify-x509-name "vpn.example.com" name 은 주체의 일반 이름을 고정하고, remote-cert-tls server 은 서버 인증을 위한 확장 키 사용을 요구한다. 사업자가 건네준 프로필이라면 둘 다 갖춰야 한다.

ca, 인라인 <ca> 블록, 그리고 tls-crypt 또는 tls-auth 을 찾아라. tls-auth 을 쓰는 프로필은 서버 쪽이 방향 0을 쓸 때 클라이언트에 key-direction 1 이 필요하며, 불일치는 인증서 결함처럼 읽히는 TLS 오류로 핸드셰이크를 실패시킨다. 방금 이름을 확인한 사업자의 것이 아닌 인라인 CA 는 파일이 두 출처에서 조립되었음을 뜻하며, 바로 그 경우를 단호히 거부해야 한다.

verify-x509-name 은 name, name-prefix 또는 subject 모드를 받아들이고, 마지막 것은 서버가 출력하는 바로 그 순서의 완전한 식별 이름을 기대한다. 값의 모양에 맞는 모드를 고르라. 클라이언트는 근접한 불일치를 경고하는 대신 모든 연결을 거부하기 때문이다. 당신이 쓰지 않은 파일에는 단순한 호스트 이름과 함께 쓰는 name 이 가장 놀랍지 않은 선택이다.

조용히 실패하는 옵션을 점검하라

OpenVPN 2.6 은 data-ciphers 을 통해 암호를 협상하며, 오래된 cipher AES-256-CBC 줄만 지닌 프로필은 제어 채널을 마치고 나서 데이터에서 멈출 수 있다. 그 값을 읽으면 파일이 접속하려는 서버보다 오래되었는지 알 수 있다. 2.6 의 매뉴얼 페이지에는 협상 순서가 실려 있으니 사업자에게 인용해 줄 필요가 있을 때 쓰라.

파일 이름이 없는 auth-user-pass 은 클라이언트가 물어본다는 뜻이므로, 스스로 완전해 보이는 프로필도 자격 증명이 필요하다. auth-user-pass credentials.txt 은 아마 당신에게 보내지 않은 파일을 기대한다는 뜻이다. nobind 과 resolv-retry infinite 은 평범하고 무해하지만, explicit-exit-notify 은 UDP 전용이며 TCP 에서는 쓸모없다.

이 중 어느 것도 프로필이 어디로 연결되는지를 바꾸지 않지만, 각각은 연결 자체가 되는지를 바꾸며, 어느 것도 클라이언트의 가져오기 대화상자에 보이지 않는다.

결정하고, 결정한 내용을 기록하라

이 읽기 후에 세 가지 결과가 있고, 가져오기는 그중 하나뿐이다. 엔드포인트와 핀이 별도 경로로 받은 지시와 맞으면 가져오라. 엔드포인트는 맞아 보이지만 핀이나 CA 가 맞지 않으면 수정된 파일을 요청하라. 파일이 서로 다른 출처의 엔드포인트나 CA 자료를 섞으면 삭제하고 새 사본을 요청하라.

검토한 해시를 기록해 두면 다음 사람이 파일이 바뀌었는지 알 수 있다: sha256sum profile.ovpn 을 메모의 엔드포인트 옆에 붙여 두라. 프로필은 주소 목록이 아니라 전체적인 배치이므로, 작동하는 remote 를 남의 신뢰 블록에 그들의 자격 증명을 유지한 채 끼워 넣어서는 안 된다.

메모를 대조하는 동안 개인 키와 암호를 화면 캡처와 채팅 스레드에 남기지 말라. 엔드포인트와 비밀이 아닌 옵션만으로도 정확한 질문을 할 수 있고, 나머지는 파일에 두는 것이 맞다.

그래도 가져왔는데 첫 시도가 실패하면 클라이언트를 --verb 3 와 함께 실행하고 처음 열 줄을 읽어라. 확인된 remote 주소, 협상된 proto, TLS 오류가 이 순서로 나타나며, 위의 어떤 점검을 건너뛰었는지 알려 준다.

관련 글