Cisco AnyConnect와 함께 제공되는 vpn 클라이언트는 대화처럼 동작합니다. 프롬프트를 출력하고, 한 줄을 기다린 뒤, 다음 프롬프트를 출력합니다. 그 대화를 파일이나 파이프로 흘려 넣으면 같은 바이너리가 무인으로 실행됩니다. 기법은 리디렉션 하나와 정렬된 답변 목록이며, 스크립트가 신뢰할 만한지를 결정하는 것은 리디렉션이 아니라 그 목록입니다.

실제로는 두 가지가 이를 깨뜨립니다. 게이트웨이가 추가 질문을 하면 프롬프트 순서가 바뀌고, 저장된 비밀번호는 한 번의 오타를 계정 잠금으로 바꿉니다. 순서를 버전 관리되는 데이터로 취급해 게이트웨이가 바뀔 때마다 비교하십시오. 다시 시도하는 대신 크게 실패하십시오. 반복이야말로 잘못 입력한 비밀번호가 잠긴 계정이 되는 경로이기 때문입니다.

하나의 순서, 클라이언트가 묻는 순서대로

클라이언트를 한 번 대화형으로 실행하고 나타나는 순서대로 모든 프롬프트를 적으십시오. 그 기록이 답변 파일이 됩니다. 파일을 바이너리로 리디렉션할 때 첫 줄은 연결 명령 자체여야 하며, 그래서 순서는 사용자 이름이 아니라 호스트 이름으로 시작합니다.

connect vpn.example.com
0
<username>
<password>
y
exit

맨 0 은 게이트웨이가 목록을 제공할 때 첫 연결 프로필을 선택합니다. 게이트웨이가 출력하는 인덱스를 쓰십시오. y 는 로그인 배너를 받아들이므로 배너가 없으면 그 줄을 지우고, 게이트웨이가 추가 질문을 하는 곳에 한 줄을 넣으십시오. 끝의 exit 은 마지막 답변이 소비된 뒤 클라이언트가 깔끔하게 종료되게 하는 것입니다.

/opt/cisco/anyconnect/bin/vpn -s < anyconnect.txt

여기서 비대화형 모드는 선택 사항이 아닙니다. -s 없이는 클라이언트가 터미널을 점유하고 리디렉션된 입력을 무시할 수 있습니다. 이것이 있으면 답변은 스트림에서 읽히고 프로세스는 반환됩니다. 바이너리에 상승된 권한이 필요하면 호출을 sudo -n 로 감싸 비밀번호 프롬프트에서 막히는 대신 즉시 실패하게 하십시오.

답변 파일이 새는 곳

비밀번호가 든 파일은 자격 증명이므로 자격 증명의 권한을 주십시오. 모드 600, 작업을 실행하는 계정 소유, 그리고 공유되거나 동기화된 디렉터리 안에는 절대 두지 마십시오. 나중에 고치는 대신 모드를 이미 적용해 만들어야 합니다. 쓰기와 chmod 사이에 파일이 잠시 모든 사람에게 읽히기 때문입니다.

install -m 600 /dev/null ~/.config/anyconnect.txt
chmod 700 ~/.config

나머지 절반은 argv입니다. 인자로 전달된 비밀번호는 프로세스를 나열하는 모든 로컬 사용자에게 보이고 셸 기록에도 남습니다. 대신 파일 디스크립터나 환경 변수에서 읽고, 페이로드를 인용해 셸이 내부에서 아무것도 확장하지 못하게 하십시오.

printf '%s\n' 'connect vpn.example.com' '0' "$VPN_USER" "$VPN_PASS" 'y' 'exit' \
  | sudo -n /opt/cisco/anyconnect/bin/vpn -s

인용에 주의하십시오. 큰따옴표 안에서는 ! 를 포함한 비밀번호가 클라이언트가 보기도 전에 대화형 셸에서 확장될 수 있고, 실패는 프로토콜 문제처럼 보이는 일반적인 event-not-found 오류로 도착합니다.

터널을 증명하고, 그런 다음 닫으십시오

연결됨 상태는 클라이언트가 세션이 있다고 믿는다는 것만 증명합니다. 사내 네트워크 안에서만 응답하는 호스트를 골라 다른 무엇을 하기 전에 한 번 시험하십시오. 거기서의 실패는 라우팅이나 정책 결함이며, 로그인을 다시 실행해도 바뀌지 않습니다.

/opt/cisco/anyconnect/bin/vpn state
curl -sS -o /dev/null -w '%{http_code}\n' --max-time 10 https://<internal-host>/
/opt/cisco/anyconnect/bin/vpn disconnect

연결 해제 전후에 상태 출력을 확인하십시오. 오래된 세션을 안고 남은 클라이언트는 다음 연결을 거부할 수 있는데 스크립트는 여전히 성공을 보고하며, 종료 코드만 보면 이 실패 유형은 보이지 않습니다. 두 번째 읽기만 믿지 말고 두 읽기를 비교하십시오. 셸 프로필의 별칭은 일상 사용에 충분하지만, 예약된 것은 다른 무인 작업과 같은 자격 증명과 신원 검토를 받을 만합니다.

고정된 목록이 더 이상 안전하지 않을 때

답변 파일은 오늘의 프롬프트 순서를 부호화합니다. 바뀐 배너, 강제 비밀번호 변경, 두 번째 요소 요구는 그것을 계정을 잠글 수 있는 반복으로 바꿉니다. 그래서 스크립트는 다시 시작하는 대신 첫 예상 밖의 답변에서 종료해야 합니다.

클라이언트가 출력한 것을 포착하고, 영이 아닌 상태를 반환하고, 결정은 호출자에게 맡기십시오. 게이트웨이가 두 번째 요소를 요구하는 곳에서 정직한 답은 그 프로필에 무인 로그인이 제공되지 않는다는 것이지, 순서에 한 줄이 더 필요하다는 것이 아닙니다.

교체도 같은 검토에 속합니다. 자격 증명이 저장된다면 누가 읽을 수 있는지, 언제 바뀌는지, 호스트가 재구축될 때 무엇이 그것을 지우는지 정하십시오. 아무도 비밀번호를 건드리지 않아 일 년 동안 도는 스크립트는 설계가 아니라 교체 정책을 기다리는 사고입니다.

AnyConnect가 아닌 프로필

Cisco의 오래된 자격 증명 스타일 두 가지가 이것과 혼동됩니다. vpnc 프로필은 IPSec ID를 요구하는데 실제로는 그룹 이름이며, 그다음 그룹 비밀, 그다음 자신의 자격 증명을 요구하고, 셋 모두 게이트웨이를 운영하는 사람에게서 옵니다. 레거시 Cisco IPsec은 AnyConnect와 다른 프로토콜이므로 vpnc 는 AnyConnect 전용 서비스에 도달할 수 없습니다. openconnect --protocol=anyconnect 이 그 작업을 위한 오픈 클라이언트입니다.

.pcf 파일은 오래된 클라이언트 프로필을 설명합니다. 그 안의 호스트, 그룹 이름, 그룹 비밀번호는 Cisco IPsec을 쓰는 클라이언트에서 손으로 다시 입력할 수 있지만, 파일은 보편적인 가져오기가 아니며 비표준 포트나 터널링 모드는 보통 전환에서 사라집니다.

게이트웨이가 실제로 제공하는 것에서 시작해 그 프로토콜을 쓰는 클라이언트를 고르십시오. 다른 사이트에서 프로필을 복사하는 것이 사람들이 문제도 아니었던 자격 증명을 디버깅하게 되는 길입니다.

관련 글