4. HTTP/1.1의 신택스: 고속화와 안전성을 추구한 확장
•
통신 고속화
◦
Keep-Alive가 기본값
◦
파이프 라이닝
•
TLS 암호화 통신
•
메서드 추가
◦
PUT, DELETE가 필수로 변환
◦
OPTION, TRACE, CONNECT가 추가
•
프로토콜 업그레이드
•
이름을 사용한 가상 호스트 지원
•
청크 전송 인코딩
4.1 통신 고속화
Keep-Alive를 통해서 TCP/IP 통신의 효율화시킬 수 있습니다.
Keep-Alive가 없다면 모든 통신마다 열고 닫고를 해야하지만, 있다면 TCP/IP의 접속시간이 줄어들고, 처리량이 많아져 속도가 올라간 것처럼 느껴지기 때문입니다.
이는 통신이 끊킬때까지 계속됩니다.
Connection: close
JavaScript
복사
단, 이는 모든 통신이 끝났는지를 확신하지 못하기때문에 타임아웃을 기다립니다.
4.1.2 파이프라이닝
파이프라이닝이란 최초의 요청이 완료되기전 다음 요청을 보내는 기술입니다.
하지만 중간에 HTTP/1.0만 해석하는 프록시가 있으면 제대로 지원하지 않는 서버에선 정상적으로 동작하지 않습니다.
또한 긴 시간이 걸리는 작업에선 다른 응답에 영향을 주는데 이를 HOL Blocking이라 부릅니다.
HTTP HOL(Head Of Line) Blocking
1개의 TCP 커넥션 상에서 a, b, c를 받게되었을 때 리퀘스트는 a,b,c 순서대로 보냅니다.
|——————a.png——————||——b.png——||——c.png——|
이때 a의 요청이 오래 걸릴 시 b,c가 아무리 빨라도 전체적으로 느려집니다.
HTTP/2에선 priority를 부여해 이를 해결했습니다.
TCP HOL(Head Of Line) Blocking
TCP에서 패킷이 손실될 시 재전송하게되는데, 이는 순서를 보장하기 위해 패킷이 대기하는데, 이때 발생하게 됩니다.
4.2 전송 계층 보안(TLS)
HTTP/1.1에선 TLS(Transport Layer Security)가 규격화되었습니다. HTTP/1.0에선 SSL(Secure Socket Layer) 3.0이 탑재되었고, TLS는 이를 바탕으로 표준화되었습니다. 과거에 SSL이라고도 불렸기 때문에 TLS 라이브러리가 OpenSSL등 SSL이름을 사용하고 있습니다.
•
-l, —tlsv1: TLS로 접속
•
-tlsv1.0, —tlsv1.1, —tlsv1.2: TLS 접속 시 버전 강제 지정
•
—cert-status: 인증서 확인
•
-k, —insecure: 자가 서명 인증서라도 오류가 되지 않음
$ curl --cert-status -v https://example.com
...
SSL certificate status: good (0)
...
Shell
복사
4.2.1 해시 함수
'잘게 저민 조각'이란 뜻으로 다운로드한 파일이 깨졌는지 여부, git등에서 사용됩니다.
•
같은 알고리즘, 같은 입력 이라면 결과는 같다.
•
알고리즘이 같으면 길이가 항상 같다.
•
해시 값에선 원래 데이터를 알기 어렵다.
•
같은 해시값은 거의 나오지 않는다.
4.2.2 공통 키 암호와 공개 키 암호 그리고 디지털 서명
암호화에서 알고리즘이 알려져도 안전해야 하단 것 입니다. TLS에선 공통키 방식과 공개키 방식 두가지가 있습니다.
공통 키 방식
잠글때와 열 때 같은 열쇠를 사용하는 방식입니다. 대칭 암호라고하며, TLS에선 일반 통신의 암호화에 사용합니다.
공개 키 방식
공개 키와 비밀 키가 필요하고, 암호화 키(공개키 → 자물쇠)와 암호해독 키(비밀 키 → 열쇠)가 따로 있습니다.
디지털 서명은 공개 키 방식을 응용했습니다. 열쇠를 나눠주고 자물쇠를 비밀로 합니다. 통신시에 본문을 자물쇠로 잡궈 첨부해서 보내면, 받은 사람은 공개키를사용해 자물쇠를 열었을 때 데이터가 동일하다면 메시지가 조작되지 않았다고 가정하는 방식입니다.
4.2.3 키 교환
간단한 방법으론 클라이언트에서 공통 키를 생성한 뒤 서버 인증서의 공개 키로 암호화해서 보내거나, 키교환 전용 알고리즘을 사용합니다. 디피-헬먼 키 교환 알고리즘을 설명하고, 실제로는 일시 디피-헬먼 엘고리즘이 사용됩니다.
핵심은 키 자체를 교환하는것이 아닌, 서버와 클라이언트에서 키 재료를 만들어 서로 교환해서 각자 계산해서 같은 키를 얻는 것 입니다.
4.2.4 공통 키 방식과 공개 키 방식을 구분해서 사용하는 이유
공개 키 방식이 안전성은 높지만 연산에 3~10배의 시간이 걸리기 때문입니다.
4.2.5 TLS 통신 절차
1.
핸드세이크 프로토콜로 통신 확립
2.
레코드 프로토콜
3.
SessionTicket 구조를 이용한 재접속 시의 고속 핸드세이크
서버의 신뢰성 확인
서버의 신뢰성을 보증하는 구조는 공개 키를 보증하는 구조이기 때문에, 공개 키 기반구조(PKI)라고 불립니다. 브라우저는 서버에서 서버의 SSL인증서를 우선 가져옵니다. 해당 인증서엔 발행자가 있는데, 상위 발행자의 인증서를 차례로 검증해 최종적으론 발행자와 주체자가 동일한 인증서가 나오고 이를 루트 인증기관이라 합니다. 이와 사전에 브라우저가 가지고있는 인증기관의 인증서와 대조해 서버가 승인된 것임을 확인합니다.
키 교환과 통신 시작
난수를 사용해 통신용 공통 키를 만듭니다. 그리고 서버 인증서에 첨부된 공개 키로 통신용 공통 키를 암호화해 그 키르 ㄹ서버에 보냅니다. 서버는 비밀키를 가지고 있어 이를 복호화해 공통키를 꺼내 사용합니다.
통신의 고속화
일반적인 접속에선 TCP/IP 단계에서 1.5RTT, TLS 핸드세이크 2RTT, 통신에서 1RTT가 걸립니다. 추가로 TCP/IP 마지막 0.5RTT와 그후 최초 통신은 함께 이루어져 총 4RTT가 걸립니다.
이를 Keep-Alive를 통해서 최초 요청 이후 1RTT를 유지해 속도를 높일 수 있습니다.
4.2.6 암호 강도
암호 방식에서 비트 수가 1 증가하면 두배로 강해집니다. 64비트의 경우 빠르게 해독되고, 256비트는 양자 컴퓨터 공격에 내성이 있다 생각합니다. 단 이가 너무 커질 시 서버 쪽 부담이 너무 커져 DDoS 공격에 취약해집니다.
4.2.6 암호화 스위트
'서버를 인증하고, 키를 교환해서 통신한다'라는 TLS의 흐름은 크게 달라지지 않았습니다. 이때 세부 알고리즘들은 계속 바뀌어왔는데, 이러한 세트를 암호화 스위트라고 부릅니다.
4.2.8 프로토콜 선택
TLS가 제공하는 기능중 애플리케이션 계층 프로토콜을 선택확장하는 기능은 매주 중요합니다. 처음에는 구글이 NPN을 이후 ALPN 확장 방식이 선택되었습니다.
ALPN에선 TLS의 최초 핸드세이크 시 클라이언트가 서버에 '클라이언트가 이용할 수 있는 프로토콜 목록'을 보내고, 서버에선 응답으로 키 교환을 하고 인증서와 함께 선택한 프로토콜을 보냅니다. TLS를 사용시 프록시의 간섭을 받지 않고, 프로토콜 버전을 사전에 조정해 호환성이 없는 프로토콜도 사용 가능합니다.
4.2.9 TLS가 지키는 것
TLS는 통신 경로의 안전을 지키기 위한 구조로 통신 신뢰도를 높였습니다.
1.3에선 인증된 암호 모드 알고리즘을 통해 통신 내부가 보이지 않도록하고, 1.2에선 공개 키 암호로 키 교환 방법으 ㄹ제공합니다. 이와같은 여러 방법을 통해 보안 구멍들을 서로 막아주고있습니다.
4.3 PUT 메서드와 DELETE 메서드의 표준화
1.0에선 옵션이였던 PUT과 DELETE가 필수로 추가되었습니다. 이는 HTML의 폼으로는 보낼 수 없고, XMLHttpRequest를 사용해야합니다.
4.4 OPTIONS, TRACT, CONNECT 메서드 추가
4.4.1 OPTIONS
서버가 받아들일 수 있는 메서드 목록을 반환합니다. 단 대부분의 웹 서버에선 이를 허용하지 않습니다.
$ curl -X OPTIONS -v https://example.com
...
allow: OPTIONS, GET, HEAD, POST
Shell
복사
4.4.2 TRACE(TRACK)
서버는 TRACE 메서드를 받으면 Content-Type에 message/http를 설정하고고, 200을 붙어 그대로 반환합니다.
4.4.3 CONNECT
HTTP 프로토콜상에 다른 프로토콜의 패킷을 흘릴 수 있게합니다. 프록시 서버를 거쳐 대상 서버에 접속하는 것이 목표이며, 주로 https 통신을 중계합니다.
4.5 프로토콜 업그레이드
HTTP/1.1부터 HTTP 이외의 프로토콜로 업그레이드 가능합니다.
•
TLS를 이용한 통신
◦
보안이 지켜지지않습니다만 모든 통신이 TLS화 되어있습니다.
◦
TLS 자체가 갖는 핸드세이크시 프로토콜 선택기능(ALAN)을 사용하는것으 ㄹ권장합니다.
•
웹소켓
◦
현재 프로토콜 업그레이드가 주로 사용되는 곳입니다.
•
HTTP/2
◦
프로토콜 업그레이드 기능이 삭제되었습니다.
4.5.1 클라이언트 쪽에서 업그레이드를 요청
클라이언트 쪽에서 업그레이드하는 경우 Upgrade와 Connection 헤더를 포함한 요청을 보냅니다. 이후 서버에선 업그레이드가 가능하다면 아래와 같은 응답이 옵니다.
4.5.2 서버 쪽에서 업그레이드를 요청
스테이터스 코드에 426을 붙여 요청하고, 클라이언트에서 다시 프로토콜 전환 요청을 보낸 뒤 핸드세이크가 이루어집니다.
4.5.3 TLS 업그레이드의 문제점
이는 프론시가 악의를 가지고 정보를 훔치거나, 중간자 공격에 약합니다. 이외에 TLS 통신으로의 업그레이드 방법이 있는데 Redirect 기능을 통해 https://로 시작하는 도메인에서 업그레이드 ㅎ는 방법인데 검색점수에도 영향이 없는 방법이라 합니다.
4.6 가상 호스트 지원
HTTP/1.0에선 한대의 웹서버가 하나의 도메인만을 다루었는데 하나의 웹서버로 여러 웹 서비스를 운영하는 방법이 1.1에서부터 지원됩니다. 이는 클라이언트가 Host헤더에 요청을 보내고자하는 서버 이름을 적어넣어주는 것이 의무가 되었기 때문에 가능해졌습니다.
4.7 청크
데이터를 전체를 한번에 전송하지 않고, 작게 나눠 전송하는 방식입니다. 이를 통해 다운로드된 부분만 표시해주는 등 방법으로 응답속도를 빠르게 해줄 수 있습니다.
4.7.1 메시지 끝에 헤더 추가
Trailer: Content-Type
Shell
복사
이는 메시지 끝에 헤더를 추가해주면 되는데, 여기서 부여한 헤더는 바디를 보낸 후 전송된다를 알려줍니다.
4.8 바디 전송 확인
클라이언트에서 서버로 한번에 데이터를 보내는 것이아닌 받아들일 수 있는지 확인하고나서 데이터를 전송하는 2단계 전송이 가능해졌습니다. 우선 클라이언트는 헤더와 바디를 제외한 모든 헤더를 지정해 문의합니다.
Expect: 100-continue
Shell
복사
이후 서버로부터 100 Continue를 보내면 서버에 바디를 붙여 전송합니다.