2026-04-28 학습 노트 - HttpOnly cookie, Secure, SameSite
배우고 정리한 내용을 가볍게 기록한다.
공부한 내용을 짧게 기록한다
HttpOnly cookie, Secure, SameSite
기억할 점
기존에는 토큰을 LocalStorage에 평문으로 저장
이 경우 js에서 접근하여 탈취할 수 있어 위험(XSS 공격 취약)
HttpOnly cookie를 도입하여 토큰 탈취를 방지
서버가 응답 본문에 토큰을 echo 하거나 디버그 로그에 찍으면 그 경로로 토큰이 새어나감
MITM - 중간자 공격[네트워크 탈취] 방지
Secure 플래그가 있으면 HTTPS 요청에만 첨부
다만, 첫 요청의 경우 HTTP로 시도하게 되는데 이때 공격자가 평문 요청을 탈취 가능
사용자가 공격자 페이지에서 로그인 시도를 하면 문제 발생
HSTS(HTTP Strict Transport Security) 설정을 하여 1차 보안
HSTS 설정을 하게 되면 한 번이라도 접속한다면 설정한 시간까지 이후 접속은 전부 HTTPS로 강제
HSTS가 없으면 사용자가 직접 http:// 입력했을 때 평문 요청이 시도됨
CloudFlare에서 HSTS를 키기위해 확인해보니 SSL 모드가 꺼져있는 것을 확인
CloudFlare 접근은 HTTPS로 접근하고 있었으나 CloudFlare에서 EC2 서버로는 HTTP 요청 중으로 확인(Flexible)
Full (strict) 환경으로 변경(SSL 처리)
Origin Certificate, Private Key nginx 등록 및 테스트 완료
첫 요청도 막는 방법
https://hstspreload.org/ 등록 요청
브라우저 자체에 HTTPS로만 접속하게 해달라고 등록 요청 하는 방법
확실히 보장되지만 등록/제거 시간이 많이걸림
내 프로젝트에는 적합하지 않다고 판단
nginx 리다이렉트 설정 사용(HTTP -> HTTPS)
- nginx conf 적용이 안될경우 nginx.conf 내부 확인(매칭 필요)
nginx 설정에 대해서 맛볼 수 있었다(프록시 설정)
nginx 의 역할은 사용자 요청을 받아 내부 서비스(frontend/backend) 로 전달하는 리버스 프록시
외부는 nginx 만 보고 내부에 어떤 서비스가 몇 개 떠있는지 모름
upstream 블록 — 내부 서비스를 이름으로 묶음
location 분기 — 경로별로 어디로 보낼지 라우팅
proxy_pass — 실제 요청을 어디로 보낼지
proxy_set_header — 백엔드로 보낼 때 추가하는 헤더
WebSocket location - 일반 HTTP 는 1요청-1응답 후 끊음, WebSocket 은 같은 TCP 위에서 양방향 유지
Cloudflare 521, 522
521 Web Server Is Down -> TCP 도달은 하였으나 nginx 443 접근 실패(443 안떠있었음)
522 Connection time out -> TCP 도달 자체가 안됨(보안 그룹 이슈)
다음에 더 볼 것
SSL/HSTS/CAA/DNSSEC은 같은 보안 영역이지만 막는 공격 종류가 다 다름
TLS handshake 흐름
- ClientHello → ServerHello → Certificate → KeyExchange → Finished
- Origin CA 인증서가 Cloudflare↔EC2 사이의 handshake 에서 어떻게 검증되는가
- TLS 1.3 은 1-RTT 로 단축, 0-RTT 옵션도 있음 (replay 공격 위험과 트레이드오프)
SNI (Server Name Indication)
- 한 IP 에서 여러 도메인 호스팅 시 어떤 인증서를 쓸지 ClientHello 단계에서 알려주는 확장
- TLS 1.2/1.3 에서 SNI 가 평문이라 ISP·검열 시스템이 어느 사이트 가는지 봄 → ECH (Encrypted Client Hello) 가 차세대, Cloudflare 가 2023~ 부분 지원 시작
HTTP/2 vs HTTP/1.1 — 왜 nginx 에서 켜는가
- HTTP/2 : 멀티플렉싱(한 TCP 위에서 여러 요청 동시), 헤더 압축(HPACK)
- HTTP/1.1 : 요청당 1 응답, head-of-line blocking 발생
- WebSocket 은 HTTP/1.1 Upgrade 만 가능 — 그래서 ws location 에 proxy_http_version 1.1 명시
- HTTP/3 (QUIC) 도 있는데 운영 안정 후 검토할 영역
X-Forwarded-* 헤더의 신뢰 체인
- 사용자 → Cloudflare → nginx → Spring
- 각 단계가 X-Forwarded-For 에 자기 본 IP 추가
- Spring 이 신뢰할 단계 수(trusted proxies) 명시 안 하면 클라이언트가 헤더 위조 가능
- server.forward-headers-strategy=framework + Cloudflare 의 CF-Connecting-IP 활용 검토
Cloudflare ↔ origin 의 keep-alive 와 TCP 풀
- 매 요청마다 TLS handshake 새로 하면 비용 큼
- Cloudflare 는 origin 과 keep-alive 연결 풀 유지 — 한 번 handshake 후 재사용
- nginx 의 keepalive_timeout 너무 짧으면 풀이 자주 끊겨 latency ↑
Cloudflare Origin CA 가 공인 CA 가 아닌 이유
- Cloudflare 만 신뢰하는 사설 CA 체인
- 공인 CA 발급은 도메인 검증 절차 + ACME 프로토콜 + CA/B Forum 규정 → 비용·복잡도 ↑
- Cloudflare 는 자기 인프라에서만 쓰는 인증서라 공인일 필요 없음
- 15년이라는 긴 유효기간도 그래서 가능 (공인 CA 는 보통 90일 ~ 1~2년)
Authoritative DNS vs Recursive resolver
- Cloudflare 가 우리 도메인 DNS 의 Authoritative 측
- 사용자 PC 의 1.1.1.1 / 8.8.8.8 은 Recursive 측 — 캐싱·재귀 조회
- CAA 레코드는 Authoritative 가 답하고 CA 가 인증서 발급 직전 조회
- DNS TTL 짧을수록 변경 반영 빠르지만 부하 ↑
종합 회고
페어 프로그래밍을 자칭했지만 코드를 전체 보지 않고 올려 문제가 발생한 이슈가 있었다(#40 issue)
코드를 전체적으로 쭉 보고 한번 프로젝트 리뷰를 한번 해야겠다
그래도 처음으로 왜? 되물으며 파고들어 본 좋은 경험이었다