통합과 배포 · 인증과 TLS · 이론
401 은 누군지 모르겠다는 뜻이고 403 은 알지만 안 된다는 뜻이다
한 줄 요약
인증 문제를 좁히는 가장 값싼 도구는 상태 코드 두 개이고, 인증서 문제를 좁히는 가장 값싼 도구는 서버가 실제로 보내는 인증서 장수다.
왜 이게 필요했나
FDE 는 남의 집 열쇠를 다루는 사람입니다. 그리고 인증 문제는 장애 신고 중 재현이 가장 까다로운 축에 듭니다. 토큰마다, 사용자마다, 시간대마다 다르게 실패하기 때문입니다.
그런데 이 복잡함을 절반으로 줄이는 구분이 하나 있습니다.
401 은 인증(authentication) 실패입니다. "네가 누구인지 확인할 수 없다." 토큰이 없거나, 형식이 틀렸거나, 만료됐거나, 서명이 안 맞습니다.
403 은 인가(authorization) 실패입니다. "네가 누구인지는 알겠는데 이건 못 하게 돼 있다." 신원 확인은 통과했고 권한이 모자란 것입니다.
이 둘을 구분하면 조사 방향이 정반대로 갈립니다. 401 이면 자격 증명 자체를 봅니다 — 토큰이 제대로 전달되고 있는지, 만료되지 않았는지. 403 이면 자격 증명은 건드릴 필요가 없고 권한 설정과 스코프를 봅니다. 이 구분 없이 "권한 오류" 라고 뭉뚱그리면 엉뚱한 쪽을 몇 시간 파게 됩니다.
한 가지 더. 401 이 반환됐는데 응답에 재인증 경로가 안내되지 않으면 클라이언트가 무한 재시도에 빠집니다. 토큰을 갱신할 방법을 모르는 채로 계속 같은 토큰을 보내기 때문입니다.
그리고 401 안에서도 이유가 갈립니다. 토큰 없음, 알 수 없는 토큰, 만료된 토큰은 전부 401 이지만 대응이 다릅니다. 그래서 응답 본문의 사유 문자열을 함께 봐야 합니다. 상태 코드만 보고 판단하면 "토큰을 새로 발급받으세요" 라고 답해야 할 상황에서 "설정을 확인해 보세요" 라고 답하게 됩니다.
어떻게 동작하나
인증서 문제는 실패 모드가 몇 가지로 정해져 있고, 각각 증거가 다릅니다.
만료 — notAfter 가 지났습니다. 그런데 여기서 반드시 함께 확인할 것이 있습니다. 클라이언트의 시계입니다. 시계 없는 임베디드 기기, 오래 정지했다 부팅한 VM, 호스트와 어긋난 컨테이너에서 "인증서가 만료됐다" 는 오류가 나는 경우가 상당히 많고, 그때 서버 인증서는 멀쩡합니다. 만료일과 현재 시각을 함께 찍어 보는 습관이 필요합니다.
이름 불일치 — 접속한 이름이 인증서에 없습니다. 여기서 자주 틀리는 것이 CN 을 보는 것입니다. 현대 클라이언트는 CN 을 아예 보지 않고 subjectAltName 만 검사합니다. CN 에 도메인을 넣었으니 괜찮다는 판단은 2017년 이후로 틀렸습니다.
중간 인증서 누락 — 이것이 FDE 가 가장 자주 만나는 유형이고, 증상이 특이합니다. 브라우저에서는 자물쇠가 정상인데 서버 대 서버 호출만 실패합니다. 원인은 클라이언트가 아니라 서버입니다. 서버가 중간 인증서를 함께 보내지 않고 있고, 브라우저는 인증서 안의 링크를 따라가 누락된 중간 인증서를 스스로 내려받아 서버의 실수를 대신 메워 주고 있을 뿐입니다. curl 이나 대부분의 언어 런타임은 그 링크를 따라가지 않습니다.
그래서 판정 방법이 단순합니다. 서버가 보내는 인증서가 몇 장인지 세면 됩니다. 종단 인증서 하나만 오면 그 순간 원인 확정이고, 고칠 곳은 클라이언트가 아니라 서버입니다.
현장에서 만나는 모습
여기서 FDE 가 자주 유혹당하는 지름길이 하나 있습니다. 검증을 끄는 것입니다.
증상은 즉시 사라집니다. 그리고 그 상태로 프로덕션에 배포되면 중간자 공격에 그대로 노출됩니다. 더 나쁜 것은, 검증을 끈 채로 개발하면 프로덕션에 존재하지 않는 환경에서 작업하게 되어 다른 문제들까지 함께 가려진다는 점입니다. 가려진 문제들은 나중에 한꺼번에 터집니다.
검증 끄기는 원인을 확정한 뒤 "지금 이 문제 때문이 맞다" 를 확인하는 용도로만 쓰고, 그 확인 직후에 되돌립니다.
다음 실습에서 할 것
토큰 네 가지를 각각 넣어 401 과 403 을 손으로 만들어 보고, 만료 사유 문자열을 확보하고, 만료된 인증서와 이름이 다른 인증서에서 각각 필요한 값을 뽑아 진단 보고서를 만듭니다.