HTTP/2 헤더 메모리
본문
HTTP/2 Header Memory Exhaustion (HTTP/2 헤더 메모리 고갈)
Traefik은 Go 표준 라이브러리를 통해 HTTP/2를 제공해요. HTTP/2에서는 단일 연결이 많은 동시 요청을 다중화할 수 있고, 각 요청은 자기만의 헤더 블록을 실어 나르죠.
클라이언트는 HPACK 헤더 압축을 HTTP/2 흐름 제어 윈도우와 함께 악용해, 작은 양의 와이어 데이터를 프록시의 큰 메모리 할당으로 확장하고, 스트림을 멈춰 세워 그 할당을 고정시킬 수 있어요. 동시 스트림과 연결이 충분히 많아지면 사용 가능한 메모리를 고갈시켜 Traefik 프로세스를 종료시킬 수 있어요.
두 엔트리포인트 옵션이 이 노출을 제한해요. 함께 사용하는 게 권장돼요.
요청 헤더 크기 제한하기
maxHeaderBytes 옵션은 Traefik이 각 요청에 대해 읽는 요청 헤더의 크기(바이트)를 상한으로 제한해요.
기본값(1048576, 즉 1 MiB)에서 여러분의 가장 큰 정당한 헤더가 필요한 가장 작은 값으로 낮추면, Traefik이 크게 확장되기 전에 과도하게 큰 헤더 블록을 거부할 수 있어요.
File (YAML)
entryPoints:
websecure:
address: ':443'
http:
maxHeaderBytes: 65536
File (TOML)
[entryPoints.websecure]
address = ":443"
[entryPoints.websecure.http]
maxHeaderBytes = 65536
CLI
--entryPoints.websecure.address=:443
--entryPoints.websecure.http.maxHeaderBytes=65536
연결당 동시 스트림 제한하기
maxConcurrentStreams 옵션은 각 클라이언트가 단일 연결에서 시작할 수 있는 동시 HTTP/2 스트림 수(기본값 250)를 상한으로 제한해요.
낮출수록 단일 연결이 고정할 수 있는 메모리 양이 줄어들어요.
File (YAML)
entryPoints:
websecure:
address: ':443'
http2:
maxConcurrentStreams: 100
File (TOML)
[entryPoints.websecure]
address = ":443"
[entryPoints.websecure.http2]
maxConcurrentStreams = 100
CLI
--entryPoints.websecure.address=:443
--entryPoints.websecure.http2.maxConcurrentStreams=100
심층 방어(Defense in Depth)
이 두 제한은 단일 연결이 소비할 수 있는 메모리를 제한해요. 추가 보호를 위해 앞단 로드 밸런서나 방화벽에서 출발지 IP당 동시 연결 수와 요청 비율도 제한하고, 예상되는 정당한 부하를 처리할 충분한 메모리로 Traefik 인스턴스를 프로비저닝하세요.