OpenConnect는 웹 로그인과 VPN 터널이라는 두 개의 별개 교환을 하나의 짧은 수명 값으로 묶으며, 첫 번째 교환은 평범한 HTTPS입니다. 자격 증명, SAML 왕복 또는 토큰이 게이트웨이로 가고 응답이 인증 쿠키를 실어 옵니다. 두 번째 교환은 그 쿠키를 같은 게이트웨이에 제시해 웹 단계가 이미 끝났다는 증거로 삼고, 그때서야 터널이 올라옵니다.

로그인 중에는 터널에 대해 아무것도 협상되지 않으며, 바로 이 점을 이해해야 합니다. 대부분의 스크립트 오류는 쿠키를 저장할 비밀번호나 트래픽을 지키는 열쇠라고 가정하지만, 실제로 그것은 특정 게이트웨이 세션을 위한 운반용 티켓입니다.

클라이언트와 게이트웨이가 순서대로 주고받는 것

인증 단계는 평범한 보호된 웹사이트처럼 보입니다. OpenConnect는 사용자의 자격 증명을 보내거나 게이트웨이의 리디렉션을 따라 신원 제공자에게 가고, 게이트웨이는 인증 쿠키를 넣은 문서로 응답합니다. AnyConnect 프로토콜에서 그 값은 이어지는 요청의 쿠키 헤더로, 보통 webvpn 같은 이름으로 이동하며, 설명서는 이를 세션을 앞으로 나르는 자격 증명으로 취급합니다.

두 번째 단계는 그 쿠키를 붙인 게이트웨이의 VPN 엔드포인트로 가는 CONNECT 요청입니다. 게이트웨이는 이를 확인하고 주소를 할당하며, 클라이언트는 TLS 위에서 CSTP를 시작하고 세션이 생기면 DTLS가 선택적인 더 빠른 데이터 경로가 됩니다. 터널 매개변수, 경로, DNS 설정, 세션의 트래픽 키가 확정되는 것은 이 시점뿐입니다. 쿠키는 클라이언트를 문 안으로 통과시켰을 뿐 아무것도 암호화하지 않았습니다.

이 순서가 openconnect --authenticate가 존재하는 이유를 설명합니다. 실행하면 웹 단계를 수행하고 COOKIE, HOST, CONNECT_URL, FINGERPRINT 같은 셸 변수의 작은 블록을 출력한 뒤 어떤 터널도 만들기 전에 종료합니다. 그다음 래퍼 스크립트가 그 값으로 실제 연결을 시작할 수 있고, 이것이 헤드리스나 두 컨테이너 배포에 필요한 바로 그 분리입니다.

쿠키는 세션 운반자이지 열쇠가 아니다

그 값을 웹 애플리케이션의 세션 ID처럼 다루십시오. 수명 동안 그것을 가진 사람은 그 세션에 주어진 터널을 게이트웨이에 요구할 수 있으므로 비밀성이 중요합니다. 그러나 복사해도 트래픽이 드러나지는 않는데, 터널의 기밀성은 TLS 핸드셰이크와 거기서 파생된 키에서 오고 쿠키 문자열에서 오지 않기 때문입니다.

영구적인 허가도 아닙니다. 세션이 얼마나 사는지는 게이트웨이와 신원 제공자가 정하며, 아직 로그인된 페이지를 보여 주는 브라우저는 터널 세션이 유효한지에 대해 아무것도 말해 주지 않습니다. 만료 뒤 다시 연결한다는 것은 웹 단계를 반복하고 새 쿠키를 만드는 일이며, 그것이 재인증의 목적이지 공학으로 피해야 할 성가심이 아닙니다.

쿠키를 다른 자격 증명의 만능 대체물로 여기지 마십시오. SAML 어서션, 브라우저 비밀번호, 다른 서비스가 발급한 쿠키는 서로 다른 대상을 가진 다른 객체이며, 하나를 다른 것의 칸에 붙이면 보통 게이트웨이에서 실패하거나 더 나쁘게는 잘못된 신뢰 경계를 상대로 성공합니다.

사본을 남기지 않고 쿠키 넘기기

리눅스에서 가장 안전한 기계적 인계는 표준 입력이며, --cookie-on-stdin은 값을 stdin에서 읽으므로 쿠키가 프로세스 인수 목록에 나타나지 않습니다. 그곳에서는 어떤 로컬 사용자든 ps로 읽을 수 있습니다. 한 프로세스에서 인증하고 다른 프로세스에서 터널을 먹이는 파이프라인은 값을 파일이나 환경 변수가 아니라 파이프에 둡니다.

인수와 환경 변수는 각기 다른 이유로 약합니다. 인수는 클라이언트의 수명 내내 프로세스 표에 보이고 자주 셸 기록에 남습니다. 환경 변수는 자식 프로세스로 상속되며, 유닛 파일에서 이를 설정하는 systemd 유닛은 비밀을 읽을 수 있는 구성에 저장합니다. 꼭 파일이 필요하다면 서비스 계정으로 제한하고 세션이 끝나면 삭제하십시오.

권한 경계도 의도적으로 유지하십시오. 신원 제공자와 이야기하고 어쩌면 브라우저를 여는 프로세스는 그 로그인을 소유한 사용자로 실행되어야 합니다. 경로, DNS, 터널 장치를 구성하는 프로세스는 더 많은 권한이 필요할 수 있습니다. root 소유 터널에 쿠키를 넘기려고 브라우저 전체를 root로 돌리는 것은 잘못된 맞바꿈이며, 현대의 OpenConnect 설정은 그 경계를 넘어 값을 명시적으로 전달할 수 있습니다.

로깅도 같은 의심을 받을 만합니다. 상세한 클라이언트 출력, 보조 스크립트, 게이트웨이 진단은 모두 요청 재료를 되풀이할 수 있고, 모든 로그 수준이 쿠키를 가리는 것은 아닙니다. 필요한 가장 작은 오류 기록만 잡고, 공유 채널 밖에 두고, 티켓에 첨부하기 전에 가린 표본을 확인하십시오.

두 번째 단계의 검증과 만료

두 번째 단계도 서버를 검증해야 합니다. --authenticate가 출력하는 FINGERPRINT는 pin-sha256: 형식의 인증서 핀이며, 이를 --servercert로 터널 호출에 넘기면 검사가 인증한 게이트웨이에 고정된 채로 남습니다. 스크립트를 간단히 하려고 인증서 검사를 끄는 것은 쿠키가 의도한 호스트로 전달된다는 유일한 증거를 버리는 일입니다.

게이트웨이가 쿠키를 거부할 때의 해법은 더 긴 캐시가 아니라 새 인증 한 바퀴입니다. 쿠키는 연결 수명 동안만 보관하고, 종료할 때 임시 파일을 지우고, 세션이 노출되거나 장치를 잃었을 때는 신원 제공자나 게이트웨이의 세션 제거 절차를 쓰십시오. 캐시한 쿠키는 MFA의 면제가 아닙니다.

이것을 자동화하기 전에, 터널이 올바른 계정으로 돌고 쿠키가 stdin으로 도착하고 인증서 지문이 고정되어 있으며 터널이 닫히면 세션을 버리는지 확인하십시오. 하나라도 빠지면 그 자동화는 수동 흐름을 재현한 것이 아니라 쿠키에 대한 신뢰를 넓힌 것입니다.

관련 글