VPN 클라이언트 스크립트 작성: 비밀번호보다 계층을 먼저 고르세요
벤더 CLI, rasdial, 앱 인텐트, UI 자동화는 각각 다른 방식으로 실패합니다. 계층을 고르고, 비밀을 argv 밖에 두고, 종료 코드가 아니라 상태를 기다리세요.
스크립트는 작성자가 고른 계층에서 VPN 클라이언트를 시작하며, 그 계층이 작업에 필요했던 계층인 경우는 드뭅니다. 벤더의 명령줄, 운영체제의 다이얼러, 모바일 앱 인텐트는 연결 수명의 서로 다른 시점에 반환합니다. 비밀 처리 방식도 다르며, 그 차이가 비밀번호가 머신의 모든 사용자에게 보이는지를 결정합니다. 스크립트 첫 줄을 쓰기 전에 계층을 고르세요.
계층 1: 벤더의 명령줄
대부분의 데스크톱 클라이언트는 프로필 이름과, 너무 자주 비밀번호를 받는 명령줄을 제공합니다. 시스코의 옛 클라이언트는 사용자와 비밀번호 인수를 붙인 connect 동사를 받아들였고, macOS는 networksetup을 통해 내장 서비스를 노출하며, NetworkManager는 nmcli에 응답합니다. 이 호출은 명령이 끝날 때 반환되며, 그것은 터널이 사용 가능해지는 시점과 같지 않습니다. 배포하는 버전에 대한 벤더의 자체 문서를 읽으세요, 이런 인터페이스는 바뀌고 일부는 완전히 제거되기 때문입니다.
nmcli connection up "Work VPN"
networksetup -connectpppoeservice "Work VPN"
장점은 벤더가 자체 프로필 저장소를 알기 때문에 호출이 GUI와 같은 구성을 쓴다는 것입니다. 단점은 벤더마다 고유한 동사를 만들어 한 클라이언트용 스크립트가 다른 클라이언트로 옮겨지지 않는다는 것입니다. 클라이언트가 고정되고 버전이 고정되어 있다면 이 계층을 최단 경로로 보세요.
계층 2: 운영체제 자체의 서비스
Windows에서 다이얼러는 운영체제의 일부이며 벤더의 프로필 저장소가 아니라 전화번호부 항목을 대상으로 동작합니다. 그래서 클라이언트 사이에서 이식성이 높고 서비스 계정에서 스크립트로 다루기 쉽습니다. 또한 연결이 한쪽에는 있고 다른 쪽에는 없을 수 있어 잘못된 목록을 보는 사람을 혼란스럽게 합니다.
rasdial "Work VPN" user pass
Get-VpnConnection -Name "Work VPN" | Select-Object ConnectionStatus
항목을 만들거나 지워야 할 때는 다이얼하는 대신 PowerShell 표면을 쓰세요. WMI와 cmdlet 계층은 같은 객체를 다른 이름으로 노출하며, 제거는 연결 해제와 별개의 작업입니다. 다이얼만 하는 스크립트는 마이그레이션 후 오래된 항목을 남깁니다. 정리가 일어난다고 약속하기 전에 자동화가 어느 저장소에 쓰는지 확인하세요.
Remove-VpnConnection -Name "Old VPN" -Force
Get-VpnConnection
macOS에서는 기존 서비스를 즉석에서 만드는 대신 이름으로 연결하는 네트워크 서비스 목록이 그에 해당합니다.
자격 증명은 모든 계층에서 새므로 채널을 고르세요
명령줄로 넘기는 것은 모두 로컬 사용자마다 프로세스 표에 나타나며 보통 셸 기록에도 남습니다. OpenVPN이 지원하는 대안은 비밀을 파일에서 읽는 것 이며 --askpass과 함께 쓰고, 파일 자체에도 신뢰에 맞는 권한이 필요합니다. 이름 있는 파이프는 비밀을 디스크에 쓰지 않지만 열 수 있는 모든 프로세스가 그곳에 쓸 수 있습니다. Windows에서는 자격 증명 관리자나 서비스 계정만 읽을 수 있는 파일에 비밀을 두고, 배치 파일에 리터럴로 두지 마세요.
openvpn --config /etc/openvpn/work.conf --askpass /etc/openvpn/work.secret --auth-nocache --daemon
ls -l /etc/openvpn/work.secret
같은 규칙이 토큰과 일회용 코드에도 적용됩니다: 자동화에 필요하다면 명령줄 인수가 아닌 채널이 필요합니다. 메커니즘을 바꿀 때는 옛 값이 어딘가 로그에 남아 있으므로 비밀을 회전하세요. 동작하면서 새는 스크립트는 동작하는 스크립트가 아닙니다.
상태를 기다린 뒤 단일 소유자를 감독하세요
이 호출은 모두 터널이 준비되기 전에 반환되므로 클라이언트가 노출하는 상태를 폴링하거나 터널 안의 목적지를 시간 제한을 두고 시험하세요. 연결 호출 직후 파일을 복사하거나 데이터베이스 연결을 여는 것은 경쟁이며, 네트워크 장애처럼 보이는 방식으로 간헐적으로 실패합니다.
ip link show tun0
nmcli -t -f GENERAL.STATE connection show "Work VPN"
curl -sS --max-time 5 https://app.internal.example/health -o /dev/null
연결 해제는 반대 방향으로 같은 문제가 있습니다: 경로가 사라지기 전에 프로세스가 종료될 수 있습니다. 클라이언트에 훅이 있으면, 예를 들어 OpenVPN의 up 및 down 스크립트나 systemd 유닛의 ExecStartPost를 쓰세요, 정말 중요한 시점에 실행되기 때문입니다. 훅은 호출한 것의 권한으로 실행되므로 네트워크를 재시작하는 훅에는 가정이 아니라 명시적 규칙이 필요합니다. 연결 수명 동안 소유자는 정확히 하나로 유지하세요.
두 감독자가 같은 프로필을 시작하고 중지하면 결과는 공급자 장애처럼 읽히는 재연결 루프입니다. 계층이 문서화되고, 비밀이 argv가 아닌 채널을 가지며, 대기 조건이 시간 제한이 있는 상태 확인이고, 하나의 프로세스가 수명 주기를 소유할 때 런북이 끝납니다.