OpenVPN 클라이언트 하나 일시 중지: 폐기가 잘못된 지렛대인 이유
세션을 끊는 것은 되돌릴 수 있지만 인증서 폐기는 그렇지 않다. 사안에 어떤 지렛대가 필요한지 정하고, 맞을 때만 CRL을 다시 만든다.
클라이언트 하나의 접근을 잠시 멈추는 것과 영구히 제거하는 것은 둘 중 하나를 되돌리려 하기 전까지 같은 작업처럼 보인다. 인증서 폐기는 서버가 최종으로 취급하는 기록을 남기며, 그것을 되돌리려면 발급자의 데이터베이스를 손으로 고쳐야 한다. 살아 있는 터널을 끊는 것은 신뢰에 아무것도 바꾸지 않는 관리 명령이다. 요청이 얼마나 급해 보이는지가 아니라 키를 여전히 신뢰할 수 있는지를 물어 지렛대를 고른다.
믿음: 폐기와 정지는 같은 것이다
계약자를 일주일 정지시키면 반사적으로 폐기를 고르게 된다. 폐기는 무언가를 끄는 것처럼 들리기 때문이다. 깔끔해 보이고 십 초면 끝나며, 되돌아가는 유일한 길로 데이터베이스 편집을 남긴다. 이 반사는 이해할 만하고 문을 닫는 것보다 여권을 태우는 쪽에 가깝다. 정지된 기기와 노출된 키는 다른 처리가 필요하며, 값싸게 되돌릴 수 있는 것은 둘 중 하나뿐이다.
차이는 사람이 아니라 자격 증명에 있다. 여전히 올바른 손에 있는 키는 신뢰를 잃지 않고 정지했다가 다시 시작할 수 있다. 복사되었을 수 있는 키는 절대 복원해서는 안 된다. 복원은 복사본이 존재하지 않는다고 주장하는 것이기 때문이다.
두 시스템 중 어느 쪽이든 건드리기 전에 답을 적어 둔다. 키가 노출되었는지 말할 수 없다면 보수적인 답은 교체다.
관리 인터페이스로 살아 있는 세션을 끊는다
OpenVPN 은 세션을 나열하고 공통 이름으로 그중 하나를 종료할 수 있는 관리 인터페이스를 제공한다. localhost에서 켜고, 공용 인터페이스에서 멀리 두고, 세션을 지금 사라져야 할 때 종료 명령을 보낸다. 명령은 그 터널만 닫고 다른 모든 클라이언트는 계속 동작한다.
이것은 진행 중인 문제에 대한 대응이지 정지 정책이 아니다. 같은 프로파일은 일 분 안에 다시 연결될 수 있다. 자격 증명에 아무것도 바뀌지 않았기 때문이다. 세션을 보내야 하고 오래가는 결정이 아직 진행 중일 때 쓴다.
종료하기 전에 세션이 연결되어 있었는지 확인한다. 한 번도 연결되지 않은 클라이언트를 쫓지 않기 위해서다. 아래 상태 명령은 지금 연결된 것을 출력한다.
printf 'status 2\nquit\n' | nc 127.0.0.1 7506
printf 'kill kiosk-14\nquit\n' | nc 127.0.0.1 7506종료 명령이 그런 클라이언트가 없다고 알리면, 인증서의 공통 이름은 입력한 문자열이 아니다. 프로파일 파일 이름이 아니라 상태 출력을 읽는다.
CRL이 실제로 통제하는 것
서버는 인증서에 저장된 폐기 플래그를 보지 않는다. crl-verify에 지정된 인증서 폐기 목록을 새 연결마다 읽고, 그 목록에 일련번호가 있는 인증서를 거부한다. 여기서 두 가지 결과가 나오고 둘 다 운영상 중요하다. 파일은 서버가 권한을 낮추는 계정에서 읽을 수 있어야 하고, 이미 연결된 클라이언트는 다시 연결할 때까지 계속 동작한다.
두 번째 결과는 사고 중에 사람들을 놀라게 한다. 인증서를 폐기해도 지금 그 인증서를 쓰는 터널은 닫히지 않는다. 세션을 즉시 끝내야 한다면 폐기를 관리 종료와 짝지어야 하고, 두 동작을 절차서에서 별개의 단계로 다뤄야 한다.
마지막으로 복사한 파일의 시각을 믿는 대신 목록을 살펴 서버가 실제로 무엇을 강제하는지 본다. 중요한 부분은 일련번호 개수다.
openssl crl -in /etc/openvpn/server/crl.pem -noout -text | sed -n '1,14p'
ls -l /etc/openvpn/server/crl.pem항목이 없는 목록과 올바른 항목이 있는 목록은 디렉터리 목록에서 똑같아 보인다. 그래서 일련번호 개수를 출력할 가치가 있다. 권한 줄도 마찬가지로 중요하다. 데몬이 읽을 수 없는 파일은 거부된 클라이언트처럼 보이는 장애를 만든다.
기록 복원, 신중하게
인증서를 복원한다는 것은 발급 데이터베이스의 기록을 뒤집고 새 목록을 게시하는 것이다. easy-rsa 3 은 그 데이터베이스를 PKI 디렉터리 아래 index.txt 로 유지하며, 더 오래된 배치는 다른 구성을 썼다. 행은 상태 문자와 만료 날짜로 시작한다. 폐기된 행은 일련번호, 인증서 파일 이름, 식별 이름으로 이어지기 전에 폐기 시각을 삽입한다. 행을 되돌린다는 것은 그 시각을 지우고 문자를 뒤집으며 나머지는 그대로 두는 것이다.
먼저 파일을 백업하고, 텍스트 편집기에서 입력하는 대신 스크립트로 편집한다. 행이 가진 필드 수를 바꾸는 오타는 이후에 추가되는 모든 인증서의 발급을 깨뜨린다. 그래서 변경을 자동화하고 건드리기 전에 파일을 복사해야 한다.
같은 이름의 두 번째 폐기도 자주 실패한다. 첫 실행이 그 인증서와 키를 도구가 기대하는 디렉터리 밖으로 옮겼기 때문이다. 그러면 도구는 폐기하라고 한 것을 찾지 못하고, 오류 메시지가 이유를 항상 분명히 밝히지는 않는다.
cp /etc/easy-rsa/pki/index.txt /root/index.txt.$(date +%F-%H%M)
grep -c '^R' /etc/easy-rsa/pki/index.txt
easyrsa gen-crl새 목록을 게시하고 소유권을 고치고 서버가 그것을 읽게 한다. 대부분의 설치에서는 다시 읽기로 충분하지만, 확인은 새 연결에서 와야 한다. 기존 세션은 아무것도 다시 확인하지 않았기 때문이다.
사안에 어떤 지렛대가 어울리는지 확인한다
절차서 전체를 결정하는 한 가지 질문을 던진다. 개인 키가 여전히 있어야 할 곳에만 있는가. 그렇다면 세션 종료와 문서화된 일시 중지로 사안이 덮이고 영구 기록이 남지 않는다. 그렇지 않다면 유일하게 안전한 답은 새 키이고, 오래된 인증서는 폐기된 채로 둔다.
그다음에는 구성 차이가 아니라 연결 시도로 결과를 검증한다. 차이는 의도를 알려 주고, 연결은 서버가 무엇을 강제하는지 알려 준다.
openssl crl -in /etc/openvpn/server/crl.pem -noout -text | grep -c 'Serial Number'
printf 'status 2\nquit\n' | nc 127.0.0.1 7506복원한 클라이언트가 연결되어 상태 출력에 나타나면 기록 편집이 동작한 것이다. 폐기된 클라이언트가 거부되고 로그가 CRL을 지목하면 폐기가 동작한 것이다. 그 사이의 무엇이든 권한이나 다시 읽기 문제이며, 다음 요청이 오기 전에 고칠 가치가 있다.