RFC 7540

sesame·2023년 4월 28일
0

규격

목록 보기
6/8

1. HTTP/2 Stream


1.1. Stream

  • HTTP/2에서 stream은 client와 server connection 사이의 독립적이고 양방향성을 가진 frame들의 sequence
  • HTTP/2 connection에는 동시에 다수의 stream 존재 가능
  • stream은 client와 server가 일방적으로 사용하거나 공유하여 사용 가능
  • 각 endpoint는 stream을 종료 가능
  • 개별 stream에서 frame의 순서가 중요(HEADER, DATA frame 등은 수신 순서에 따라 처리)

1.2. Stream Identifiers (31bit unsigned integer) (0: connection flow control)

  • 한 Session내에서 Stream id는 재사용 불가
  • Stream id는 HEADERS, PUSH_PROMISE를 통해 새로운 stream의 state가 open 혹은 reserved로 변경될 시점에 생성
  • 새로운 Stream id 생성이 불가능 할 경우 client는 새로운 connection을 수립하고, server는 client가 새로운 connection을 수립하도록 기존 connection에 대해 GOAWAY frame을 전송

2. HTTP/2 Protocol 기본 단위 Frames

2.1. frame size

고정된 octet data header(9byte) + payload size

  • SETTING frame의 SETTINGS_MAX_FRAME_SIZE로 크기 지정
    • default = 2^14 (16,384) byte
    • 최대 2^24 -1 (16,777,215) 까지 설정 가능
    • SETTING_MAX_FRAME_SIZE 크게 잡으면 RST_STREAM, WINDOW_UPDATE, PRIORITY frame과 같은 즉각 반영이 필요한 frame 처리 지연 발생
  • PING frame
    • payload data에 허용되는 size 제한 별도 존재
  • size over시 FRAME_SIZE_ERROR 오류 코드 전송(MUST) → connection error로 처리

2.2. frame header

  • Length
    frame header를 제외한 payload 길이 (unsigned 24bit integer)

  • Type

  • Flags
    Frames Type에 따라 정의된 boolean 형의 flag 영역

  • R
    Reserved 1 bit ( default 0 )

  • Stream Identifier
    Stream id ( 0인 경우 connection control)


3. HTTP/2 Connection

TCP connection 위에서 실행되는 application layer protocol

HTTP/1.1과 동일하게 TLS위에서 동작하는 h2와 cleartext TCP위에서 동작하는 h2c로 구분

server의 HTTP/2 지원 여부를 모르는 client의 request 전송
1. HTTP/1.1과 동일한 request를 전송

2. Server가 HTTP/2를 지원한다면 101 response를 통해 protocol 전환

3.1. HTTP/2 Preface

HTTP/2 connection 수립 후, 각 endpoint는 서로 다른 preface를 전송

Client

  • 24byte의 octets data 전송 (Magic)

0x505249202a20485454502f322e300d0a0d0a534d0d0a0d0a
(srting: PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n)

  • Client는 Server의 connection preface 수신 전, 추가 frame 전송 가능

Server

  • SETTINGS frame 전송

4. Header Compression

4.1. HTTP/2 Header (key:value)

  • http/2 protocol에서 header는 HEADERS, CONTINUATION, PUSH_PROMISE frame을 통해 전송 가능
  • Pseudo-Header Fields(ASCII 0x3a): ':'으로 시작하는 pseudo-header는 정의된 것만 사용 가능

ex)

  • Request
    :method
    :scheme
    :authority
    :path

  • Response
    :status
  • 나머지 header field는 소문자만 사용하여 encoding
  • SETTINGS_HEADER_TABLE_SIZE값을 0으로 수신한 경우 Static Table(RFC7541에 정의된 61개)만으로 Header Compression

4.2. HPACK Compression(RFC 7541)

  • 각 endpoint는 connection 별 header field table을 가지고 header index를 공유하며 update
  • 동일 connection request에 대해 중복된 header를 1byte의 index로 전송

5. Flow control 및 prioritization을 통해 multiplexed streams 관리

Multiplexed stream 간 간섭을 제한하기 위해 stream들의 flow control 및 priority 제어가 필요

5.1. Flow control

  • Flow control 대상은 DATA frame payload
  • hop-by-hop 단위로 적용
  • SETTINGS frame으로 flow control

5.2. Stream Priority

  • HTTP/2 개별 stream은 가중치와 종속성을 포함(1~256 정수)
  • 타 stream에 대한 명시적 종속성 부여
  • Stream의 종속성 및 가중치가 특정 처리나 전송 순서를 보장하지 않음
  • Client가 특정 순서로 Stream 처리를 강요할 수 없음 (우선 순위가 높은 stream이 차단된 경우 종속 stream에 대한 처리 지연 발생 방지)

6. Server Push 기능

  • Client 요청에 대한 응답 외, 추가적으로 예상되는 정보를 client cache로 타 stream을 통해 전송
  • Client의 중복 요청을 방지하기 위해 PUSH_PROMISE frame은 Client 요청에 대한 응답 data보다 먼저 전송

server push 예

  • Server는 stream 1로 수신된 request에 대한 응답으로 page.html 응답을 전송
  • page.html 을 수신한 client는 script.js, style.css 파일을 추가 요청할 것으로 예상하고 PUSH_PROMISE frame을 전송하여 2, 4 stream을 예약
  • Stream 1, 2, 4를 통해 page.html, script.js, style.css DATA frame을 전송

7. HTTP/2 Frames Definition

7.1. DATA (0x00)

Data Frame은 반드시 stream id와 함께 전송
DATA Frame Payload

  • 가변길이 binary data 를 전송
    • Pad Length: 보안을 위한 Padding data length ( padded flag 설정 시 유효)
    • DATA: 실제 data 영역
  • Flag
    • END_STREAM(0x01): Stream의 마지막 frame을 나타냄
    • PADDED(0x08): Padding data 존재 시, 설정

7.2. HEADERS (0x01)

stream을 열기 위해 사용
HEADERS Frame Payload

  • Pad Length: 보안을 위한 Padding data length ( padded flag 설정 시 유효 )

  • E: Stream priority 설정의 exclusive 설정 유무

  • Stream Dependency: 새로 생성한 stream이 종속되는 상위 stream id

  • Weight: Priority 가중치 ( PRIORITY flag 설정 시 유효 )

  • Header Block Fragment: HPACK으로 압축한 header data 영역

  • Flag

    • END_STREAM(0x01): Stream의 마지막 frame을 나타냄
    • END_HEADER(0x04): 추가적인 CONTINUATION frame이 없음을 의미
    • PADDED(0x08): Padding data 존재 시, 설정
    • PRIORITY(0x20): Priority 설정 존재 시, 설정

7.3. PRIORITY (0x02)

Stream 가중치 설정을 위한 frame
PRIORITY frame은 반드시 stream id와 함께 전송
PRIORITY Frame Payload

  • E: Stream priority 설정의 exclusive 설정 유무

  • Stream Dependency: 새로 생성한 stream이 종속되는 상위 stream id

  • Weight: Priority 가중치 (PRIORITY flag 설정 시 유효)

  • Flag

    • N/A

7.4. RST_STREAM (0x03)

Stream 즉시 종료를 위한 frame
취소 요청 혹은 오류 발생을 알리기 위해 전송
RST_STREAM Frame Payload

  • Error Code ( Stream 종료 reason )

    • NO_ERROR(0x00)
    • PROTOCOL_ERROR(0x01): endpoint의 protocol 오류
    • INTERNAL_ERROR(0x02): endpoint의 내부 오류
    • FLOW_CONTROL_ERROR(0x03): flow control에 대한 합의 무시
    • SETTINGS_TIMEOUT(0x04): SETTINGS frame 전송 후, 응답 timeout
    • STREAM_CLOSED(0x05): half-closed state에서 frame 수신
    • FRAME_SIZE_ERROR(0x06): 비정상 size의 frame 수신
    • REFUSED_STREAM(0x07): 해당 stream에서 처리 거부
    • CANCEL(0x08): Stream이 더 이상 필요하지 않음
    • COMPRESSION_ERROR(0x09): Endpoint가 connection에 대한 압축 context 유지 불가
    • CONNECT_ERROR(0x0a): Connection 비정상 종료
    • ENHANCE_YOUR_CALM(0x0b): 상대 endpoint의 과부화 발생 동작 확인
    • INADEQUATE_SECURITY(0x0c): 최소한의 보안 요건 미 충족
    • HTTP_1_1_REQUIRED(0x0d): HTTP/1.1 사용해야 할 경우
  • Flag

    • N/A

7.5. SETTINGS (0x04)

Connection 설정 parameter 교환을 위한 frame
동일 connectoin에 대해 각 endpoint는 서로 다른 값을 설정할 수 있음
SETTING frame에 대한 응답은 ACK flag 설정 후 응답
Setting Frame Payload
( Identifier – Value ) pair 1개 이상으로 구성

  • Identifier: 설정 parameter id
    SETTINGS parameter value
  • Value: 설정 parameter value
    • SETTINGS_HEADER_TABLE_SIZE(0x01)
      • Sender 가 header 블록을 octet 단위로 디코딩 하는데 사용되는 헤더 압축 테이블의 최대 크기
    • SETTINGS_ENABLE_PUSH(0x02)
      • 1: Server Push 가능, 0: Server Push 불가능
    • SETTINGS_MAX_CONCURRENT_STREAMS(0x03)
      • 동시에 처리할 수 있는 최대 Stream 수
    • SETTINGS_INITIAL_WINDOW_SIZE(0x04)
      • DATA frame에만 적용
      • Client에서 SETTINGS frame으로 window size 2000 byte 지정해주면, Server에서 2000 byte씩 끊어서 보내야함
      • Client에서 WINDOW_UPDATE frame으로 1000 byte의 공간이 생겼다고 전송하면, Server에서 나머지 1000 byte를 전송
      • Stream id가 0일때 Connection SETTINGS frame, 0이 아닐 때 Stream SETTINGS frame
    • SETTINGS_MAX_FRAME_SIZE(0x05)
      • TLS 최대 Frame size: 16384
    • SETTINGS_MAX_HEADER_LIST_SIZE(0x06)
      • Sender가 수신 가능한 header 목록의 최대 크기
      • 압축되지 않은 헤더 필드의 크기 기준

DATA frame 전송 시 세가지 check

  • Session 전체에 대한 window size가 얼마나 남았는지
  • Stream에 대한 window size가 얼마나 남았는지
  • Max frame size가 얼마나 남았는지
  • Flag
    • ACK(0x01): SETTINGS frame의 응답 시 설정 (ACK flag 설정 시, payload size는 반드시 0)

7.6. PUSH_PROMISE (0x05)

PUSH data 전송을 위한 Stream reserved로 생성
PUSH data 내용에 대한 header 정보를 전송

  • Pad Length: 보안을 위한 Padding data length (padded flag 설정 시 유효)

  • R: Reserved bit

  • Header Block Fragment: HPACK으로 압축한 header data 영역

  • Flag

    • END_HEADER(0x04): 추가적인 CONTINUATION frame이 없음을 의미
    • PADDED(0x08): Padding data 존재 시, 설정

7.7. PING (0x06)

Endpoint간 최소 round-trip 시간 측정을 위한 frame
모든 endpoint가 전송 가능
최우선으로 처리해야 하고 응답 시, ACK flag를 설정하여 수신한 opaque data를 다시 전송

  • Flag
    • ACK(0x01): PING frame의 응답 시 설정

7.8. GOAWAY (0x07)

Connection 종료 혹은 오류 발생 전송을 위한 frame
새로운 stream open을 위한 peer와 GOAWAY frame 전송 시 race-condition 발생 가능하여 반드시 peer가 open한 마지막 stream id를 전송
두 개 이상의 프로세스가 공통 자원을 병행적으로 읽거나 쓰는 동작을 할 때, 공용 데이터에 대한 접근이 어떤 순서에 따라 이루어졌는지에 따라 그 실행 결과가 같지 않고 달라지는 상황

  • Last-Stream-ID: Peer가 open한 가장 높은 stream id

  • Error Code: Connection 종료 reason

  • Additional Debug Data: 추가적인 debug data 영역

  • Flag

    • N/A

7.9. WINDOW_UPDATE (0x08)

Flow control을 위한 frame
Frame header의 stream id가
0인 경우: connection의 flow control
0이 아닌 경우: stream의 flow control

  • Window Size Increment: Window size 증가 값 (1 ~ 2^31-1)

  • Flag

    • N/A

8.10.CONTINUATION (0x09)

추가적인 header 정보를 전송하기 위해 사용
HEADERS, PUSH_PROMISE frame 전송시, size 제한으로 한번에 전송 못하는 경우 CONTINUATION으로 나누어 전송

  • Header Block Fragment: HPACK으로 압축한 header data 영역

  • Flag

    • END_HEADER(0x04): 추가적인 CONTINUATION frame이 없음을 의미

8. Stream의 States

stream은 idle state에서 시작


9. HTTP/2 ERROR Handling

9.1. Connectoin Error Handling

connection Error는 frame layer의 추가 처리를 방해하거나 연결 상태를 손상시키는 모든 오류

  • connection Error가 발생한 endpoint는 GOAWAY frame을 보낸다(SHOULD)
  • 하지만 GOAWAY frame이 수신되지않을수도있다.

9.2. Stream Error Handling

stream 오류는 다른 stream의 처리에 영향을 미치지 않는 특정 stream과 관련된 오류입니다.

  • stream Error를 감지한 endpoint는 오류가 발생한 RST_STREAM frame을 보낸다

  • RST_STREAM은 endpoint가 stream에서 보낼 수 있는 마지막 frame입니다.

RST_STREAM frame을 전송하는 peer는 원격 peer가 전송했거나 전송을 위해 대기열에 넣은 모든 frame을 수신할 준비가 되어있어야 합니다.

이러한 frame은 연결 상태(헤더 압축 또는 flow control)를 수정하는 경우를 제외하고는 무시할 수 있습니다.

  • looping을 피하기 위해 endpoint는 RST_STREAM에 대한 응답으로 RST_STREAM을 보내면 안된다.

    looping
    frame이 네트워크 상에서 무한정으로 목적지에 도달하지 못하고 네트워크를 점유하는 상태
    네트워크를 점유하는 frame이 사라질 때까지 네트워크는 통신이 불가능한 상태가 되는 현상


10. Additional HTTP Requirements/Considerations

10.1. Connect Method

CONNECT Method는 Client와 Server가 SSL handshake를 맺도록 하기위해 Client가 Proxy에게 Server와 TCP Connection을 맺으라 지시할 때 쓰인다.

10.2. Connection Management

  • HTTP/2 연결은 지속적
  • 클라이언트가 종료될 때까지(서버와 더 이상 통신할 필요가 없다고 결정했을 때) 연결을 닫지 않을 것
  • 클라이언트는 주어진 하나 이상의 HTTP/2 연결을 열면 안된다(SHOULD NOT)
  • 호스트(URI) port 쌍
  • 추가 연결 생성할 수 있는 경우
    • 사용 가능한 stream id를 거의 소진한 연결 교체 시
    • TLS 연결에 대한 key material을 리프레쉬할 때
    • 오류가 발생한 connection을 교체 시
    • 같은 IP address와 TCP port를 이용하고 다른 server 명으로 구성된 여러 연결을 열 수 있다

10.3. Connection Reuse

CONNECT method를 사용하여 생성된 터널을 통해 또는 직접적으로 original 서버에 대한 연결은 여러 다른 URI 권한 구성 요소가 있는 요청에 재사용될 수 있다.

10.4. status code 421

요청이 응답을 생성할 수 없는 서버로 전달되었다


11. TLS

HTTP/2 구현은 TLS 1.2 이상 사용해야 함
TLS 구현은 서버 이름 표시(SNI)를 지원해야 합니다.

11.1. HTTP/2와 TLS 1.2 함께 쓸 때 제한 사항

  • TLS 압축 기능을 비활성화
    • HTTP/2에서 압축 기능을 제공함

renegotiation
기존 보안 세션 내에서 새로운 handshake 협상을 시작하는 것

  • TLS 재협상(renegotiation)기능을 비활성화
    • end point는 TLS 재협상을 PROTOCOL_ERROR 유형의 연결 오류로 처리해야 함
    • 기본 암호 그룹이 암호화할 수 있는 메시지 수 제한으로 인해 수명이 긴 연결을 사용할 수 없게 될 수 있음
      • end point는 재협상을 사용하여 handshake에서 제공되는 클라이언트 자격 증명에 대한 기밀 보호를 제공할 수 있지만 재협상은 반드시 connection preface을 보내기 전에 이루어져야 한다
      • HTTP_1_1_REQUIRED유형의 오류를 사용하여 클라이언트가 재협상 지원하는 프로토콜을 사용하도록 요청할 수 있음

11.2. TLS 1.2 암호화 스위트(Cipher Suites)

  • TLS 1.2를 통한 HTTP/2 배포는 암호 그룹 블랙 리스트에 나열된 암호 그룹을 사용하면 안된다.
  • end point는 블랙 리스트의 암호 그룹 중 하나가 협상되는 경우 INADEQUATE_SECURITY 오류 생성 가능

12. 보안 고려 사항

12.1. Cross-Protocol Attacks(교차 프로토콜 공격)

HTTP/2의 clear text 버전은 교차 프로토콜 공격에 대해 최소한의 보호 기능을 제공

connection preface에는 HTTP/1.1 서버를 혼동하도록 설계된 문자열이 포함되어 있지만 다른 프로토콜에 대해서는 특별한 보호가 제공되지 않는다.

클라이언트 connection preface 외에 업그레이드 헤더 필드가 포함된 HTTP/1.1 요청의 일부를 무시하려는 서버는 교차 프로토콜 공격에 노출될 수 있다.

12.2. 중간 캡슐화 공격(Intermediary Encapsulation Attacks)

HTTP/2는 헤더 필드로 어떤 문자열이든 허용하기 때문에 HTTP/2 메시지를 중간의 프록시가 HTTP/1.1로 변환할 때 메시지가 위조될 가능성이 있다.

인코딩할 수 있는 대부분의 값은 헤더 필드 구문 분석을 변경하지 않지만 CR, LF는 공격자가 악용할 수 있다.

12.3. 푸시된 응답의 캐시 가능성(Cacheability of Pushed Responses)

PUSH_PROMISE frame으로 푸시된 응답에는 클라이언트의 명시적 요청이 없다.

Cache-Control 헤더 필드의 원본 서버에서 제공하는 지침에 따라 푸시되는 응답을 캐싱할 수 있다.

  • 단일 서버가 둘 이상의 tenant를 호스트하는 경우 문제가 발생
    • 여러 tenant가 동일한 서버에서 공간을 공유하는 경우(서버는 여러 사용자에게 URI 공간의 작은 부분을 제공)
    • tenant가 제공하는 실제 표현을 무시하고, 캐시에서 제공되는 표현을 제공할 수 있음
    • 따라서 해당 서버는 tenant가 권한이 없는 리소스 표현을 푸시할 수 없도록 해야함

12.4. 서비스 거부 고려 사항(Denial-of-Service Considerations)

HTTP/2 연결은 HTTP/1.1 연결보다 작동하기 위해 더 많은 리소스를 요구할 수 있다.

  • SETTINGS frame

    • 처리 시간 소비
    • 의미 없이 SETTINGS 매개변수를 변경
    • 정의되지 않은 여러 매개변수를 설정
    • 동일한 설정 여러번 변경
  • WINDOW_UPDATE 또는 PRIORITY frame

    • 리소스 낭비
  • small frames

    • 프레임 헤더를 처리하는데 시간을 소비
    • 스트림의 끝에서 빈 DATA또는 CONTINUATION frame을 보내는 것과 같은 일부 사용은 전적으로 합법적
  • header compression

    • 리소스를 낭비

이러한 모든 기능( SETTINGS changes, small frames, header compression)은 합법적으로 사용된다.
이러한 기능은 불필요하게 사용하거나 과도하게 사용할 때만 부담이 된다.

이 동작을 모니터링하지 않는 end point는 서비스 거부 공격의 위험에 노출되기 때문에 이 기능의 사용을 추적하고 사용제한을 설정해야한다.

  • Limits on Header Block Size
    end point는 SETTINGS_MAX_HEADER_LIST_SIZE를 사용해 제한을 설정

이 설정은 권고사항일뿐 이 제한을 초과하는 header block을 보낼 수 있음 → 요청/응답이 잘못된 형식으로 처리될 위험

중개자는 설정된 제한을 전달하여 문제를 피하려고 시도할 수 있지만 의무는 없음

서버에서 처리할 수 있는 것보다 더 큰 header block을 수신하면 HTTP 431 status code 전송

클라이언트는 처리할 수 없는 응답을 삭제가능

  • CONNECT Issues
    TCP 연결의 생성 및 유지 관리보다 스트림 생성이 상대적으로 저렴

스트림 수는 SETTINGS_MAX_CONCURRENT_STREAMS으로 관리

종료되는 TCP 연결이 TIME_WAIT 상태로 남아있기 때문에 프록시는 CONNECT 요청을 전달하는 스트림을 닫은 후에도 TCP 연결에 대한 일부 리소스를 유지할 수 있다.

따라서 프록시는 CONNECT 요청에 사용되는 리소스를 제한하기 위해 SETTINGS_MAX_CONCURRENT_STREAMS에만 의존할 수 없다.

12.5. 압축 사용

TLS에서 제공하는 것과 같은 일반 스트림 압축은 HTTP/2와 함께 사용하면 안 된다.

압축을 사용하면 공격자가 제어하는 데이터와 동일한 컨텍스트에서 압축될 때 공격자가 데이터를 복구할 수 있다.

12.6. padding

압축, 비활성화 또는 제한에 의존하는 공격을 완화하기 위해 대책으로 패딩보다 압축이 더 나을 수 있다.

  • HTTP내의 특정 공격, 예를 들어 압축 콘텐츠에 공격자가 제어하는 일반 텍스트와 비밀 데이터가 모두 포함되는 공격을 완화하기 위해 제공

  • 공격자가 관찰해야 하는 프레임 수를 늘려 공격자가 길이 정보를 유추하는 것을 어렵게 만드는 역할만 함

  • 예측 가능한 분포를 가진 무작위 패딩은 거의 보호를 제공하지 않는다.


Flow

0개의 댓글