프로필을 데스크톱 클라이언트로 가져오면 첫 실패는 대개 클라이언트가 따르기를 거부하는 줄이다—실행하지 않을 스크립트 훅이거나, 너무 허용적이라고 판단하는 script-security 값이다. 숫자를 올리면 대화상자는 사라진다. 하지만 경고 하나를 없애기 위해 그 프로필이 당신의 기기에서 실행할 수 있는 범위를 넓히는 것이기도 하니 이상한 거래다. 가져오기에서 지시문까지 따라가면 결정은 구체적으로 바뀐다.

가져오기 대화상자에서 지시문까지

프로필은 지시문이 담긴 텍스트 파일이고, 클라이언트는 터널이 생기기 전에 그것을 읽는다. up, down, tls-verify 같은 지시문은 OpenVPN이 정해진 시점에 실행해야 하는 외부 프로그램을 지목한다. OpenVPN이 그것을 실행할지 여부는 script-security라는 별도 설정이며, 프로필은 보통 그 설정도 정한다.

그러므로 경고는 암호나 인증서에 관한 것이 아니다. 설정 파일이 클라이언트에게 호스트에서 무언가를 실행하라고 요청하고, 클라이언트가 현재 권한 수준으로 그 요청을 허용할 수 있는지 확인하는 이야기다.

이 단계에서는 서로 다른 두 실패가 비슷해 보인다. 클라이언트가 주지 않을 수준을 요구하는 프로필은 거부를 낳는다. 클라이언트가 주는 수준을 요구하지만 스크립트가 없는 프로필은 대신 실행 시점의 실패를 낳고, 지원 스레드에서는 둘이 뒤섞인다. 하나는 권한 문제이고 다른 하나는 패키징 문제다.

각 수준이 실제로 여는 것

수준 0은 외부 프로그램 호출을 전면 금지한다—도움 없이 자기 인터페이스를 설정하는 클라이언트에는 일관되고, 운영 체제를 호출하는 클라이언트에는 일관되지 않다. 수준 1(기본값)은 인터페이스와 경로 설정에 필요한 내장 실행 파일을 허용한다. 어느 수준도 사용자가 제공한 것을 실행하지 않는다.

LevelWhat OpenVPN may executeWhat it exposes
0No external programs at allInterface and route setup must not depend on helpers
1 (default)Built-in helpers such as ip, ifconfig, route or netshPrivileged commands the platform already ships
2Built-in helpers plus user-defined scriptsWhatever the named script does with the client's privileges
3Everything above, plus passwords in environment variablesCredentials visible to child processes and their logs

수준 2가 흥미로운 경계인데, 사용자 정의 스크립트를 받아들이기 때문이다. 그 시점부터 클라이언트의 권한은 당신이 읽어 본 적 없을 수도 있는 코드에 적용되고, 당신이 고르지 않은 순간에 호출되며, 연결 세부 정보가 담긴 환경에서 동작한다. 수준 3은 더 나아가 환경 변수로 비밀번호를 넘기도록 허용하며, 그래서 설명서는 잠재적으로 안전하지 않다고 적는다.

이 숫자들 중 어느 것도 강도 설정이 아니다. 수준 3의 프로필이 수준 1보다 나은 암호화를 갖는 것은 아니고, 실행 표면이 더 클 뿐이며 터널은 같다.

그 프로필에 무엇이 합당한지 결정하라

어느 수준이 필요한지 묻기 전에 그 스크립트가 무엇을 위한 것인지 물어라. DNS 설정을 밀어 넣거나 연결 후 경로를 고치는 훅은 무언가를 실행할 정당한 이유다. 임시 디렉터리에서 낯선 바이너리를 호출하는 훅은 멈출 이유다.

스크립트의 경로는 스크립트만큼 중요하다. 상대 경로는 클라이언트가 쓰는 디렉터리를 기준으로 해석되고, 쓰기 가능한 디렉터리는 일회성 가져오기를 영구적인 실행 슬롯으로 바꾼다. 사용자가 바꿀 수 없는 디렉터리의 절대 경로가 선호할 형태다.

스크립트는 클라이언트의 환경도 물려받으며, 거기에 자격 증명과 연결 메타데이터가 있다. 바로 이 상속 때문에 수준 3은 자기 환경을 기록하는 스크립트와 결합할 때 위험해지고, 스크립트를 켠 클라이언트의 진단 덤프를 티켓에 붙이기 전에 한 번 더 봐야 하는 이유도 여기에 있다. 공유하기 전에 환경을 지워라.

grep -nE 'script-security|^up |^down |tls-verify' client.ovpn

한 가지만 바꾸고, 끊기는 쪽도 살펴라

프로필에 정말 스크립트가 필요하면 수준만, 그 프로필에만 바꿔라—클라이언트를 전면에서 자세한 출력과 함께 실행해 스크립트 자체의 오류가 보이게 하라. 서비스 관리자가 삼키게 두어서는 안 된다.

openvpn --config client.ovpn --script-security 2 --verb 3
ip route show default

연결만이 아니라 전체 수명 주기를 시험하라. 종료 훅이 실패하면 경로가 죽은 터널을 가리킨 채 남고, 연결된 것처럼 보이지만 아무 데도 닿지 않는 기기가 된다. 변경을 끝났다고 하기 전에 한 번 다시 연결하고 한 번 끊고, 각각 뒤에 라우팅 테이블을 확인하라.

원본 프로필의 사본을 남겨라. 플랫폼 클라이언트가 같은 스크립트 모델을 구현하지 않는다면, 가져오기가 될 때까지 지시문을 지우는 일이 터널에 필요했던 DNS나 경로 통합을 없앨 수 있고, 그렇게 만들어진 연결은 인증만 완벽히 통과하고 아무것도 해석하지 못한다.

기록할 결정은 좁다—어떤 스크립트를, 어떤 경로에서, 어느 수준으로 허용했고, 어느 프로필을 위한 것인가. 프로필의 나머지는 그대로이고, 이것은 검토자가 확인할 수 있는 문장이다.

관련 글