"Keep 는 자기 열쇠를 갖고 있지 않아. 체크인은 뇌한테 부탁하고, 이 머신에서만 일주일 동안 통하는 손목띠를 채워 줄 뿐이야."
Keep 는 PIN 을 저장하지 않아
정문은 PIN 인데, 반전이 하나 있어. Keep 는 PIN 을 갖고 있지 않다는 거야. PIN 검증은 loopback 을 거쳐 cwkPippa 에 맡겨. 네가 PIN 을 입력하면 Keep 는 같은 머신 안의 cwkPippa 한테 "이거 맞아?" 하고 물어보고, cwkPippa 가 답해 줘. Keep 는 비밀을 손에 쥐는 일이 없어. 이건 일부러 그은 경계야. 정체성을 소유한 시스템인 cwkPippa 가 credential 검증까지 맡고, 금융 표면인 Keep 는 비밀 보관업에서 아예 발을 빼는 거지. PIN 이 사는 곳이 하나 줄면, 샐 수 있는 곳도 하나 주니까.
손목띠의 정체, IP 와 시간에 묶인 쿠키
검증에 성공하면 세션 쿠키가 발급되는데, 속성 하나하나가 의도를 갖고 있어. HMAC 서명이라 위조하거나 고치면 티가 나. IP 에 묶여 있어서 발급받은 주소에서만 통해. 훔쳐 가도 다른 데선 무용지물이야. 7일이면 만료되니 접근이 영구적이지 않고, HttpOnly 라 JavaScript 가 읽을 수 없어서 script injection 으로 훔치기도 어렵고, SameSite=Strict 라 cross-site 요청에 실려 가지 않으니 CSRF 한 부류가 통째로 막혀. 속성마다 공격 하나씩을 잠그는 거야. 다 합치면 훔치기 어렵고, 훔쳐 봐야 쓸모없는 손목띠가 돼.
다들 놓치는 HTTP 와 HTTPS 분리
Keep 에 닿는 길은 두 갈래야. LAN 과 tailnet 의 평문 HTTP, 그리고 Tailscale Serve 를 통한 HTTPS. 여기에 설계가 미리 막아 둔 미묘한 함정이 있어. 브라우저 쿠키는 hostname 단위로 구분되지 port 로는 구분되지 않아. 그러니 아무 생각 없이 만들면 HTTP 쪽 쿠키와 HTTPS 쪽 쿠키가 같은 이름을 쓰게 되고, 서로를 조용히 덮어쓰면서 덜 안전한 세션이 더 안전한 세션을 갈아치울 수 있어. Keep 는 HTTP 와 HTTPS 에 서로 다른 쿠키 이름을 써서 두 세션이 절대 부딪히지 않게 했어. 그리고 HTTPS 세션에만 Secure flag 가 붙어. 신뢰된 loopback proxy 헤더 덕분에 가능한 일이지. 더 안전한 경로가 어쩌다 하향되는 일 없이, 정말로 더 안전하게 유지되는 거야.