ID를 중복하지 않고 VPN 서버를 복원하는 방법
복원된 VPN 서버가 되돌리는 것은 파일이며 현재 접근 권한이 아니다. 두 번째 사본이 핸드셰이크에 응답하기 전에 폐기, 피어 키, 엔드포인트를 맞춰야 한다.
백업을 복원했고 서비스가 시작되었고 클라이언트가 첫 시도에 연결되었다. 그 성공이 함정이다. 복원은 스냅샷 시점에 서버가 가진 파일을 되돌려 줄 뿐, 그 뒤에 바뀐 접근 상태는 아니다. 이전 엔드포인트가 아직 도달 가능하면 이제 하나의 정체성에 응답하는 기계가 두 대다. 해결책은 더 좋은 백업이 아니라, 단 한 번의 핸드셰이크에 응답하기 전에 복원된 호스트가 무엇이어야 하는지 정하는 것이다.
백업이 되돌리는 것은 파일이며 권한이 아니다
스냅샷에는 백업이 실행된 시점의 서버 구성, 개인 키, 인증 기관, 피어 목록, 방화벽 규칙이 들어 있다. 그 뒤에 바뀐 것은 담을 수 없다. 폐기한 기기, 다시 발급한 키, 노트북을 팔 때 제거한 피어, 옮긴 서브넷이다. 복원은 파일을 그 시점으로 되감는다. 사람들이 그 뒤에 내린 결정은 되감지 않는다.
피해는 바로 이 틈에서 나온다. 백업 두 주 뒤에 폐기한 도난 노트북은 복원된 트리 안의 오래된 CRL로도 여전히 검증되는 인증서를 제시하고, 서버는 퇴역시킨 기기를 받아들인다. WireGuard는 더 노골적이다. 피어는 목록에 있다는 것만으로 승인되므로, 스냅샷 뒤에 삭제한 피어는 그냥 다시 존재한다. 아무도 그 접근을 다시 승인하지 않았다. 오래된 파일이 승인했다.
서버 정체성과 클라이언트 정체성은 서로 다르게 무너진다
WireGuard에서 서버 정체성은 wg0.conf의 개인 키이므로, 그 파일을 두 번째 도달 가능한 호스트로 복사하면 같은 정체성을 지니고 서로를 모르는 서버가 두 대 생긴다. 각자는 자기 피어 목록을 유지한다. 새 호스트에서 피어를 제거해도 옛 호스트는 여전히 받아들인다. 한쪽에서 wg show을 확인하면 진실의 절반만 보인다. 클라이언트도 스스로 넘어가지 않는다. 프로필은 Endpoint 하나를 담으므로 기기는 구성된 주소와 계속 대화하며, 그것이 퇴역시키려던 호스트일 수 있다.
OpenVPN은 같은 계층에서 서버 인증서, 그 개인 키, tls-auth 또는 tls-crypt 정적 키로 중복된다. 셋을 모두 복사하면 클라이언트는 인스턴스를 구별하지 못한다. 둘 다 도달 가능하면 재접속이 어느 쪽에든 떨어질 수 있고, 각 로그 파일은 절반의 이야기만 한다. 인증 기관이 더 깊은 복제다. 복원된 easy-rsa 트리는 두 번째 진실 원천으로, 준 어떤 이름에든 유효한 인증서를 발급할 수 있다.
클라이언트도 중복된다. 대개 이전 작업 그 자체에서다. 예비 기기에 «시험만» 하려고 프로필을 복사하면 같은 키와 같은 공통 이름을 가진 두 번째 기기가 생긴다. duplicate-cn이 있으면 두 세션이 동시에 살아 있을 수 있고, ccd나 ifconfig-pool-persist의 정적 주소 할당이 원래 기기와 충돌할 수 있다. 하나의 정체성을 걸친 두 기계이며, 서버 구성 어디에도 둘을 구별하는 것이 없다.
이전 엔드포인트에는 세 가지 상태 중 하나를 고른다
복원은 이전 엔드포인트의 운명이 정해진 뒤에야 안전하다. 퇴역시키려면 새 호스트가 시작되기 전에 이전 서비스가 VPN 포트 수용을 멈춰야 하고, 기기에 닿을 수 없다면 그 포트를 네트워크 경계에서 관리 출처 외 모두에게 막아야 한다. 같은 호스트를 고친다면 한 기기가 정체성을 쥐고 있으니 재사용은 괜찮지만, 그 뒤에 이전 키의 디스크 사본이나 VM 스냅샷을 파괴해 돌아오지 못하게 해야 한다. 가용성 쌍을 만든다면 두 호스트에 서로 다른 호스트 정체성과 하나의 공유 엔드포인트가 필요하다. 부동 주소, 부하 분산기, 옮길 수 있는 DNS 같은 것이다. 개인 키 복사는 페일오버 설계가 아니라 하나의 이름을 주장하는 두 서버다.
클라이언트를 건드리기 전에 실제로 어느 상태인지 확인한다. VPN 포트에서 응답하는 이전 호스트가 DNS가 옮겨졌더라도 폐기된 기기를 받아들이는 쪽이다. 리스너와 공개 키를 확인한다.
ss -lunp | grep -E ':51820|:1194'
wg show wg0
wg pubkey < /etc/wireguard/server.key
먼저 피어, 폐기, 주소를 맞춘다
복원이 주장하는 것과 현재 승인된 것을 나란히 적는다. WireGuard에서 wg show wg0는 각 피어의 키, 엔드포인트, 최근 핸드셰이크, 전송 카운터를 보여 주므로 더는 소유하지 않은 기기를 찾아낼 수 있다. wg set wg0 peer <key> remove로 실행 중에 제거하고, 그다음 구성도 편집한다. 그러지 않으면 다음 시작에서 피어가 돌아온다. wg show wg0 allowed-ips은 두 번째 문제를 드러낸다. 한 주소에 피어 둘, 또는 이미 다시 할당한 주소다.
OpenVPN에서 폐기 목록은 날짜가 있는 파일이고, 복원은 오래된 것을 되돌릴 수 있다. 클라이언트가 연결하기 전에 확인한다.
openssl crl -in /etc/openvpn/crl.pem -noout -lastupdate -nextupdate
grep -E 'crl-verify|reneg-sec' /etc/openvpn/server.conf
마지막 갱신이 폐기보다 앞서면 서버는 아직 폐기한 인증서를 존중하고 있다. OpenVPN 2.4 이후는 새 연결마다 CRL 파일을 다시 읽으므로 파일을 바꾸면 새 세션은 멈추지만, 이미 맺어진 터널은 재협상까지 남는다. reneg-sec의 기본값은 3600초이며, 그것을 낮추거나 서비스를 다시 시작하는 것이 지금 변경을 적용하는 방법이다. 오래된 빌드는 파일을 그만큼 확실히 읽지 않을 수 있으므로 해당 버전의 동작을 확인할 수 없으면 다시 시작한다. 위에서 쓴 피어 제거와 allowed-ips 문법은 wg(8) 매뉴얼이 다룬다.
더 이상 없는 기기의 정적 할당도 정리한다. 이전 프로필이 설치된 채로 퇴역 기기의 주소를 새 기기에 재사용하면 피하려던 중복이 그대로 생긴다.
폐기한 클라이언트로 검증한다
터널 밖 네트워크에서 순서대로 검사를 실행한다. 먼저 승인된 기기가 연결되어 푸시된 리졸버로 DNS를 풀고 사설 자원에 닿는다. 다음으로 폐기된 기기는 새 프로필이 아니라 기존 프로필로 실패해야 한다. 그다음 외부에서 이전 엔드포인트를 시험한다. VPN 포트가 아직 핸드셰이크를 완료하면 이전 호스트는 살아 있고 중복은 이론이 아니라 실제다.
복원한 호스트를 재부팅하고 승인과 폐기 검사를 반복한다. 구성 파일이 실행 중에 바꾼 것을 이기기 때문이다. 호스트의 공개 키나 인증서 지문을 퇴역 기기가 쓰던 것과 비교한다. 살아 있는 두 기계에서 지문이 같다면 복원이 정체성을 복제한 것이다. 한 기계에서만 같으면 정상이다. 복원된 버전, 키 지문, 폐기한 일련번호나 피어 키를 기록하고, 이 조정 뒤에 다음 백업을 떠서 지금의 서비스를 나타내게 한다. 동작하는 시험은 클라이언트가 연결되는 것이 아니다. 제거한 클라이언트가 밖에 남고 이전 엔드포인트가 닫힌 채로 있는 것이다.