- #Etc
HTTP Method가 뭔데요 (5)
Prolip
2024-05-26
남은 메서드 다 알아보고 끝내기... CONNECT랑 OPTIONS랑 TRACE...
시작..
이번 포스팅에서 나머지 메서드 3개 정리하고 진짜 끝내보려고 합니다..
CONNECT
사실 전 CONNECT 메서드를 한 번도 사용해보지 않았습니다… 그래서 어렴풋이 알고 있는 다른 메서드들과 다르게 정말 하나도 모르는 상태로 정리 중입니다..
CONNECT 메서드의 목적
우선 문서에서 가장 먼저 설명하는 내용을 살펴봅시다…
The CONNECT method requests that the recipient establish a tunnel to the destination origin server identified by the request target and, if successful, thereafter restrict its behavior to blind forwarding of data, in both directions, until the tunnel is closed.
ㅋㅋ 뭐 터널을 설정한다는데요?
CONNECT 메서드는 프록시 서버에게 요청 대상에 의해 식별된 오리진 서버로 가는 터널을 설정하라고 요청하고, 이 요청이 성공하면 프록시 서버는 터널이 폐쇄될 때까지 데이터의 양방향 블라인드 포워딩을 시작한다고 합니다.
그냥 쉽게 CONNECT 메서드는 프록시 서버에게 클라이언트가 실제로 접속하려고 하는 최종 목적지 서버(gojimin.com:443)로 가는 터널을 설정하라고 요청하는 겁니다!!
여기서 터널은 네트워크에서 두 지점 간의 데이터 통신을 위한 안전한 경로를 만드는 것을 의미하는데 이 터널은 프록시 서버를 통해 만들어지고 클라이언트와 서버 간의 모든 데이터가 이 경로를 통해 전달됩니다.
다음으로 블라인드 포워딩은 이 터널 안에서 일어나는 데이터 전달 방식을 의미하며 프록시 서버가 터널을 통해 클라이언트와 오리진 서버 간의 데이터를 내용을 열람하거나 수정하지 않고 그대로 전달하는 것을 뜻합니다.
즉 여기서 말하는 CONNECT 메서드는 클라이언트가 프록시 서버에 요청을 보내면 프록시 서버가 클라이언트와 서버 간에 터널을 설정해주는데 이 터널은 클라이언트와 서버 간의 데이터 전송 통로로 이 전송 통로에서 데이터를 열람하거나 수정하지 않고 그대로 전달되며 이 전달 방식을 블라인드 포워딩 방식이라고 합니다.
그리고 문단의 마지막을 보면 TLS를 사용한 암호화된 통신을 지원할 수 있다고 합니다.
CONNECT 메서드와 TLS의 관계
TLS는 Transfort Layer Security. 클라이언트와 서버 간의 데이터를 암호화하여 네트워크 상에서 중간에 위치한 장치나 서버가 그 데이터를 도청하거나 변조하지 못하도록 보호하는 보안 프로토콜입니다.
HTTPS가 바로 TLS를 이용한 대표적인 통신 방식으로 웹 브라우저에서 HTTPS로 접속할 때, 클라이언트와 서버 간의 데이터가 TLS로 암호화됩니다.
근데 방금 문단에서 말한 내용에 따르면 CONNECT 메서드는 블라인드 포워딩 방식으로 중간 서버가 데이터에 관여할 수 없다고 했지 않나요? 근데 뭐하러 TLS를 사용해 데이터를 암호화할까요?
- 프록시 서버 외 다른 중간자 공격 방지
프록시 서버가 데이터를 수정하지 않고 단순히 전달하는 것은 맞습니다. 하지만 프록시 서버 외에도 네트워크 상의 다른 구간에서 데이터가 변조될 수 있는 위험이 있습니다. 라우터나 스위치 등을 통해서 서버로 갈테니까요.
TLS를 통해 데이터를 암호화하면 네트워크 상에서 데이터를 도청하거나 변조하려는 공격자들이 암호화된 데이터를 해독할 수 없기 때문에 데이터를 보호할 수 있게 됩니다!
- 프록시 서버를 신뢰할 수 없는 경우
프록시 서버가 블라인드 포워딩 방식으로 동작하도록 설정되어 있어도 모든 프록시 서버가 신뢰할 수 있는 것은 아닙니다. 아닌척 악의적으로 데이터를 열람하거나 수정할 수도 있으니까요.
TLS를 사용한다면 프록시 서버가 데이터를 중계할 뿐 프록시 서버조차도 내용을 볼 수 없게 됩니다. 이는 데이터의 기밀성을 유지해 프록시 서버가 데이터 내용을 확인할 수 없도록 보호합니다.
- 무결성 보장
TLS는 데이터의 무결성을 보장합니다. 이는 데이터를 중간에서 변조하지 않았다는 것을 확인할 수 있는 메커니즘을 제공합니다.
만약 TLS를 사용하지 않고 터널만 설정했다면 중간 경로에서 데이터가 변조되었을 가능성을 가지게 됩니다. 하지만 TLS는 데이터가 전송되는 동안 변조되지 않았음을 보장하기 때문에 안전한 통신을 위한 중요한 역할을 합니다.
- 데이터 기밀성 유지
CONNECT 메서드는 단순히 터널을 통해 데이터를 포워딩하는 역할만을 수행합니다. 이 터널은 중간에서 데이터를 수정하거나 열람하지 않도록 보장할 수 있지만 데이터 자체는 평문으로 전송될 수 있습니다.
TLS는 데이터가 암호화된 상태로 전송되므로 터널을 통해 데이터를 전달하더라도 그 내용은 기밀로 유지됩니다.
아하 그럼 CONNECT 메서드는 터널을 설정하고 데이터를 단순히 전달하는 역할을 하지만 TLS는 데이터가 전송되는 과정에서 발생할 수 있는 다른 보안적인 위협을 방지하는군요!
TLS를 사용하면 프록시 서버를 포함한 어떠한 중간자도 데이터를 열람하거나 수정할 수 없고 데이터의 기밀성과 무결성을 보장하게 됩니다.
요약해보자면..
- CONNECT 메서드를 사용하여 프록시 서버는 클라이언트와 오리진 서버 사이에 터널을 형성합니다.
- 터널은 클라이언트와 오리진 서버 사이에 안전한 데이터 전송 통로를 형성하며 이 터널을 통해 양방향 데이터 통신이 가능해집니다.
- 데이터는 블라인드 포워딩 방식으로 처리되며, 프록시 서버는 데이터의 내용에 대해 관여하지 않고 단순히 전달만 합니다.
- CONNECT 메서드를 통해 설정된 터널이 TLS를 사용한 암호화된 통신을 지원할 수 있으며 이는 보안적인 위협을 방지하며 데이터의 기밀성과 무결성을 보장하기 위해 사용 가능합니다.
CONNECT 요청 대상에서의 포트 번호
우선 해당 문단의 내용에 앞서 포트 번호란 네트워크에서 데이터를 주고받기 위해 사용되는 가상의 통신 경로를 의미하는데 네트워크 상에서 서버와 클라이언트는 IP 주소를 통해 서로를 식별하지만 IP 주소만으로는 어떤 서비스에 접근하려는지 알 수 없습니다.
여기서 포트 번호가 중요한 역할을 하는데 각 서버는 여러 포트 번호를 사용해 서비스를 제공하며 특정 어플리케이션이나 서비스에 대한 연결을 식별하는데 사용됩니다.
예를 들어 일반적인 HTTP 통신은 80 포트를 사용해 데이터를 주고받고, HTTPS는 443 포트, 이메일 서버는 주로 25 포트를 사용합니다.
이제 다시 문단의 내용을 살펴보겠습니다.
- CONNECT 메서드의 request target은 호스트명과 포트 번호로 구성됩니다.
클라이언트가 프록시 서버에 인증서로 암호화된 우리 블로그에 대한 CONNECT 요청을 보낼 때 request target은 gojimin.com:443이 됩니다.
여기서 gojimin.com은 오리진 서버의 호스트명이고 443은 해당 서버와 연결할 때 사용할 포트 번호입니다. 그럼 형식은 아래와 같습니다.
CONNECT gojimin.com:443 HTTP/1.1
- 포트 번호의 중요성
CONNECT 메서드를 사용한다면 포트 번호는 필수로 명시해야만 합니다. 포트 번호가 없다면 서버가 요청을 처리할 수 업습니다.
예를 들어 보안 연결을 위해 443 포트를 사용할지 혹은 80 포트를 사용할지에 따라 통신 방식이 달라집니다.
위의 이유로 클라이언트는 CONNECT 요청을 보낼 때 포트 번호를 반드시 포함해야만 합니다. 이는 서버가 정확히 어떤 서비스에 연결할지를 식별할 수 있도록 도와줍니다.
- 잘못된 포트 번호 요청 처리
문서에 따르면 서버는 잘못된 포트 번호 또는 포트 번호가 없는 CONNECT 요청을 반드시 거부해야한다고 합니다.
포트 번호가 명확하게 지정되지 않았거나 잘못된 번호라면 서버는 400 Bad Request 상태 코드를 반환해 요청을 거부합니다. 이는 프록시 서버가 잘못된 요청을 처리하지 않도록 하기 위한 규정입니다.
아래와 같은 요청은 포트 번호가 누락되어 요청을 거부하고 400 코드를 반환하게 됩니다.
CONNECT gojimin.com HTTP/1.1
Host: gojimin.com
그렇다면 왜 포트 번호가 중요할까요?
포트 번호는 서버에서 어떤 서비스(위에서 설명한 HTTP, HTTPS, 이메일)에 연결할지를 정확히 구분할 수 있게 도와줍니다. 특히 프록시 서버는 클라이언트가 요청하는 서비스를 중계해주는 역할을 하므로 클라이언트가 어떤 포트로 연결하려는지 명확히 알아야 합니다.
예를 들어보자면 80 포트로 연결 요청이 들어오면 서버는 HTTP 프로토콜을 사용해 데이터를 주고 받고, 443 포트로 연결 요청이 들어오면 HTTPS로 암호화된 통신을 하게 됩니다.
따라서 포트 번호가 없다면 서버는 클라이언트가 어떤 프로토콜을 사용하고자 하는지 알 수 없기 때문에 연결을 설정할 수 없게 됩니다.
요약해보자면..
- 포트 번호는 네트워크에서 특정 서비스에 대한 접근을 식별하는 중요한 요소입니다.
- CONNECT 요청의 request target에는 반드시 호스트명과 포트 번호를 함께 명시해야하며, 포트 번호가 없다면 서버는 요청을 이해하지 못하고 거부하게 됩니다.
- 서버는 잘못된 포트 번호 혹은 지정되지 않은 요청에 대해 반드시 400 Bad Request 상태 코드를 반환해 거부해야 합니다.
CONNECT 메서드는 HTTP 요청, 응답의 일반적인 구조를 변경
Because CONNECT changes the request/response nature of an HTTP connection, specific HTTP versions might have different ways of mapping its semantics into the protocol's wire format.
일반적인 HTTP 프로토콜은 클라이언트가 요청을 보내고 서버가 그에 응답하는 구조입니다. 하지만 CONNECT 메서드는 이러한 구조를 변경합니다.
터널을 설정해 클라이언트와 오리진 서버 간에 직접적인 데이터 통신 경로를 제공하며 이로 인해 프록시 서버는 중간에서 데이터를 열람하거나 수정하지 않고 전달만 하고 이후의 데이터 통신은 기존의 HTTP 요청, 응답 구조를 따르지 않게 됩니다.
HTTP 버전에 따른 차이로 각 HTTP 버전(HTTP/1.1, HTTP/2, HTTP/3 등)에서 CONNECT 메서드가 처리되는 방식이나 전송되는 데이터의 형식이 달라질 수 있다고 합니다.
- HTTP/1.1: 전통적인 방식으로 클라이언트와 프록시 서버 간 명시적인 터널 요청과 응답이 이루어집니다.
- HTTP/2: 데이터 전송을 프레임 단위로 처리하므로 CONNECT 메서드를 통해 터널이 설정되면 그 이후의 데이터가 바이트 스트림으로 전송되며 프레임 구조를 더 사용하지 않습니다.
- HTTP/3: UDP 기반의 QUIC 프로토콜을 사용하므로 CONNECT 메서드를 처리할 때 연결 설정 방식이나 전송되는 데이터의 형식이 다른 프로토콜 버전에 비해 다를 수 있습니다.
- 여담으로 이 프로토콜은 기존의 방식과 다르게 한번 HTTP 연결이 이루어지면 handshake 과정을 더 필요로 하지 않는다고 하며 항상 암호화된 전송을 지원한다고 합니다.
CONNECT는 주로 프록시 서버를 대상으로 사용
문서에 따르면 CONNECT 메서드는 주로 프록시 서버를 대상으로 사용되며 프록시 서버는 request target에 있는 오리진 서버와 직접 연결을 설정하거나 다른 프록시 서버로 이 요청을 전달할 수 있다고 합니다.
오리진 서버도 CONNECT 요청을 받을 수 있지만 대부분의 오리진 서버는 CONNECT 메서드를 구현하지 않는다고 합니다.
우선 CONNECT 메서드는 프록시 서버를 통해 터널을 설정하고 이 터널을 통해 클라이언트와 오리진 서버 간의 암호화된 데이터가 안전하게 전달되는 것은 위에서 정리한 내용으로 알 수 있었습니다.
여기서 프록시 서버는 네트워크 상에서 클라이언트와 오리진 서버 사이에 위치해 클라이언트가 오리진 서버에 직접 접근하지 않고 프록시 서버를 거쳐 통신할 수 있게 해줍니다.
CONNECT 메서드를 사용하면 프록시 서버는 클라이언트의 요청을 받아 오리진 서버와 연결을 시도하고 그 연결을 통해 클라이언트와 서버 간의 데이터를 중계하는 터널을 설정하게 됩니다. 여기까지는 이제 다 아는 내용이군요!
이제 다른 프록시 서버로 전달하는 것은 무슨 뜻일까요?
- 프록시 서버는 다른 프록시 서버로 CONNECT 요청을 전달할 수도 있습니다. 다중 프록시 서버를 사용한다면 발생할 수 있는 상황입니다.
- 클라이언트가 첫 번째 프록시 서버에 CONNECT 요청을 보내면 해당 프록시 서버는 요청된 오리진 서버와 직접 연결하거나 다음 프록시 서버로 그 요청을 전달해 최정적으로 오리진 서버에 도달하게 할 수 있습니다.
그럼 오리진 서버가 CONNECT 메서드를 구현하지 않을까요?
- 오리진 서버는 대부분 CONNECT 메서드를 구현하지 않습니다. 이유는 CONNECT 메서드의 주된 목적이 프록시 서버를 통해 터널을 설정하는 것이기 때문입니다.
- 일반적으로 오리진 서버는 프록시 역할을 하지 않기 때문에 클라이언트와 직접 통신하기 위한 터널을 설정할 필요가 없습니다. 대신 클라이언트는 프록시 서버를 사용해 오리진 서버와 통신할 수 있도록 터널을 요청하게 됩니다.
왜 CONNECT 메서드는 주로 프록시 서버에서 사용될까요?
- 프록시 서버의 역할
우선 프록시 서버는 클라이언트와 오리진 서버 사이에서 중계자 역할을 수행합니다. 클라이언트는 프록시 서버에 연결하고 프록시 서버가 대신해 오리진 서버와 통신을 시도합니다.
이 과정에서 클라이언트와 오리진 서버 사이의 직접적인 연결 대신 프록시 서버를 통해 우회하는 방식으로 통신이 이루어집니다.
- 터널링을 통한 암호화된 통신 지원
CONNECT 메서드를 통해 설정된 터널은 클라이언트와 오리진 서버 간에 암호화된 통신을 지원할 수 있습니다. 위에서 TLS를 통해 암호화할 수 있음을 알았습니다. 특히 HTTPS와 같은 보안 프로토콜을 사용한다면 프록시 서버는 암호화된 데이터를 해석하지 않고 터널을 통해 그대로 전달합니다.
프록시 서버는 이러한 이유로 암호화된 데이터에 접근할 수 없으며 프록시 서버를 통과하는 동안 클라이언트와 서버 간의 데이터 기밀성이 유지됩니다.
- 보안과 접근 통제
프록시 서버는 보통 보안 및 접근 통제를 위해 자주 사용되는데 프록시 서버를 통해 트래픽 관리, 필터링이 가능합니다.
아하 즉 역할 일치의 이유가 크겠군요!
요약해보자면
- 프록시 서버는 클라이언트와 오리진 서버 간의 중계 역할을 수행하기 때문에 CONNECT 메서드를 통해 터널을 설정해 데이터를 중계할 수 있습니다. 프록시 서버의 본래 역할이 중계이므로, CONNECT 메서드와 이 역할이 일치합니다.
- 오리진 서버는 클라이언트가 요청한 데이터를 제공하는 최종 목적지로서 중계 역할을 수행하지 않기 때문에 CONNECT 메서드를 구현하지 않습니다. 대신 오리진 서버는 클라이언트의 요청에 대한 데이터를 제공하는 역할을 수행합니다.
성공적인 응답(2xx 상태 코드)의 의미
- 2xx 응답은 터널이 성공적으로 설정되었음을 의미합니다.
2xx 상태 코드는 HTTP에서 성공을 의미하는 코드입니다. CONNECT 메서드에서 2xx 응답이 오면 이는 프록시 서버가 클라이언트의 요청을 받아들여 터널을 성공적으로 설정했음을 나타냅니다.
이 시점부터 프록시 서버는 터널링 모드로 전환되어 클라이언트와 오리진 서버 간의 데이터를 중계하는 역할만 수행합니다.
- 헤더 이후에 전송되는 데이터는 오리진 서버로부터 온 것!
2xx 응답 이후에 전송되는 데이터는 프록시 서버가 클라이언트와 오리진 서버 간에 설정한 터널을 통해 주고받는 데이터입니다.
헤더 섹션 이후 클라이언트가 받는 데이터는 프록시 서버가 생성한 데이터가 아닌 오리진 서버에서 전송된 데이터입니다. 프록시 서버는 데이터의 내용을 확인하지 않고 블라인드 포워딩 방식으로 전달만 합니다.
- 성공하지 않은 응답은 터널이 설정되지 않았음을 의미
만약 2xx가 아닌 다른 응답 코드가 반환돤다면 이는 터널이 성공적으로 설정되지 않았음을 의미합니다. 이 경우 데이터 전송이 이루어지지 않습니다.
터널이 닫히는 조건
터널은 클라이언트와 오리진 서버 간 양방향 통신 경로로 어느 한 쪽이 연결을 닫는다면 터널도 함께 닫힙니다.
터널링에서 프록시 서버는 클라이언트와 서버 간의 데이터를 단순히 전달하는 역할을 수행하므로 한 쪽에서 연결을 끊으면 프록시 서버는 해당 터널을 닫아야 합니다.
이 때 프록시 서버는 터널이 닫히기 전에 닫힌 쪽에서 미처 전송되지 않은 데이터가 있다면 다른 쪽에 전송하려고 시도해야 합니다. 이후 남은 데이터가 모두 보내지면 연결을 완전히 닫습니다.
연결이 닫히면 프록시 서버가 남은 데이터를 모두 처리한 뒤 양쪽의 연결을 완전히 종료해야 합니다. 이후에 아직 전송되지 않은 데이터가 남아있다면 해당 데이터는 폐기되며 프록시 서버는 더 이상 데이터를 중계하지 않고 모든 연결을 정리하게 됩니다.
프록시 인증
프록시 인증은 클라이언트가 프록시 서버에 요청을 보낼 때 프록시 서버에서 클라이언트의 신원을 확인하기 위한 인증 과정으로 클라이언트가 프록시 서버를 통해 터널을 설정하려면 먼저 프록시 서버에 대해 인증된 사용자임을 증명해야 합니다.
프록시 서버는 프록시 인증을 요구해 터널 설정 전에 클라이언트가 허가된 사용자임을 확인할 수 있습니다
CONNECT 메서드를 통해 터널을 설정할 때 클라이언트는 인증 정보를 포함해 프록시 서버에 요청을 보낼 수 있습니다.
CONNECT server.example.com:443 HTTP/1.1
Host: server.example.com:443
Proxy-Authorization: basic aGVsbG86d29ybGQ=
문서의 예시에서는 클라이언트가 server.example.com:443에 대한 CONNECT 요청을 보낼 때 Proxy-Authorization 헤더를 통해 인증 정보를 함께 전송하고 있습니다.
여기서 Proxy-Authorization 헤더는 클라이언트가 프록시 서버에 제공하는 인증 정보로 Base64를 이용한 인코딩 문자열로 디코딩하면 hello:world가 됩니다. 이는 사용자명은 hello 비밀번호는 world를 뜻합니다.
이러한 과정은 프록시 서버가 네트워크 트래픽을 관리하거나 특정 사용자만이 프록시를 사용할 수 있도록 제한하기 위한 과정입니다.
CONNECT 메서드를 통한 터널 설정의 위험
문서에선 CONNECT 메서드를 사용해 터널을 설정할 때 발생할 수 있는 보안 위협을 설명하고 있습니다.
CONNECT 메서드를 통해 클라이언트가 임의의 서버와 포트로 터널을 설정하려고 할 때 보안적인 위험이 발생할 수 있다고 합니다.
특정 서비스나 포트는 웹 트래픽을 위한 것이 아닌 다른 용도로 사용되는데 예를 들어 포트 25는 SMTP 트래픽을 처리하는데 사용됩니다.
문서에선 클라이언트가 example.com:25로 CONNECT 요청을 보내면 이는 프록시 서버가 아닌 SMTP 서버에 연결될 수 있음을 경고하고 있습니다.
SMTP는 주로 이메일을 전송하는데 사용되는 프로토콜로 이를 통해 프록시 서버가 이메일을 중계할 수 있습니다. 이러한 상황은 프록시 서버가 악용되어 스팸성 메일을 중계하게 되는 보안 위협을 초래할 수 있다고 합니다.
클라이언트가 의도적으로 SMTP 포트로 CONNECT 요청을 보내면 프록시 서버를 이용해 스팸 메일을 대량으로 전송할 수 있습니다.
다음으로 프록시 서버가 CONNECT 메서드를 지원하는 경우 보안 위협을 줄이기 위해 CONNECT 메서드의 사용을 제한하는 것이 권장된다고 합니다.
프록시 서버는 특정한 서비스 포트인 80번 포트(HTTP), 443번 포트(HTTPS) 또는 안전한 목적지 서버 목록에 대해서만 CONNECT 메서드를 허용해야만 합니다.
이를 통해 임의의 포트나 위험한 서비스로의 터널 설정을 방지할 수 있으며 프록시 서버의 악용을 차단할 수 있습니다.
2xx 응답에서의 Transfer-Encoding 또는 Content-Length 헤더 제한
문서에 따르면 CONNECT 메서드의 성공적인 응답에서 특정 헤더 필드가 사용되지 않아야 하며 클라이언트도 이를 무시해야 한다고 합니다.
우선 Transfer-Encoding와 Content-Length가 무엇일가요?
- Transfer-Encoding: 서버가 클라이언트로 데이터를 전송할 때 데이터를 어떻게 인코딩해 전송할지를 명시하는 헤더로 chunked 방식은 데이터를 조각으로 전송하는 것을 의미합니다.
- Content-Length: 전송될 데이터의 길이를 나타내는 헤더로 데이터의 크기를 미리 알 수 있습니다. HEAD로 데이터 미리 받아보는 거 전에 정리했었죠?-?
그럼 어째서 CONNECT 응답에선 제한될까요?
CONNECT 메서드의 목적이 HTTP 요청, 응답 형식의 데이터 교환이 아닌 터널을 설정하는 것이기 때문에 응답에서 제한됩니다.
터널이 성공적으로 설정된 후에는 클라이언트와 오리진 서버 간의 직접적인 데이터 통신이 이루어지며 본문 데이터를 교환하는 것이 아니므로 데이터 크기나 인코딩 방식에 대한 정보가 필요하지 않습니다.
이러한 이유로 응답에선 사용될 필요가 없으며 만약 서버가 실수로라도 해당 헤더를 응답에 포함시킨다면 클라이언트는 이 헤더 필드를 무시해야 합니다.
CONNECT 요청 메세지의 특성
앞서 정리한 내용에서 계속해서 등장하지만 CONNECT 메서드는 터널을 설정하는 메서드로 데이터 교환의 목적을 가지지 않습니다.
그러한 이유로 CONNECT 메서드의 요청 메세지에는 본문을 포함하지 않습니다. 즉 POST처럼 데이터를 전송하기 위한 payload가 필요하지 않습니다.
CONNECT 메서드의 주요 목적은 터널 설정으로 실제 데이터 전송은 터널이 설정된 후 이루어지기 때문에 CONNECT 요청 자체에는 본문이 필요하지 않은 것입니다.
또한 터널이 설정된 후 데이터가 어떻게 해석되는지는 사용 중인 HTTP 버전에 따라 다를 수 있으며 버전에 따라 데이터 전송 방식이 약간씩 다를 수 있다고 합니다. 이도 위에서 알아본 내용입니다.
응답이 캐시되지 않음
CONNECT 메서드는 터널을 통해 실시간으로 데이터를 주고받기 위한 요청으로 캐시할 수 없습니다.
CONNECT 응답은 터널 설정에 대한 정보를 제공하며 이후에 전송되는 데이터는 실시간으로 교환됩니다. 이 데이터는 고정된 리소스가 아닌 때에 따라 달라지는 실시간 데이터이기 때문에 캐시의 의미가 없습니다.
OPTIONS
가끔 개발자 도구 네트워크 탭 보면 요청 응답으로 OPTIONS가 올 때 있지 않나요?
OPTIONS 메서드의 목적
- 정보 요청
OPTIONS 메서드는 클라이언트가 특정 리소스 또는 서버와의 통신 옵션을 확인하기 위해 사용합니다.
리소스에 대한 구체적인 동작을 수행하는 것이 아닌 해당 리소스나 서버에서 어떤 HTTP 메서드나 기능을 지원하는지를 알아내는 용도로 사용됩니다.
- 특정 리소스 또는 서버의 기능을 확인하기 위해
클라이언트가 특정 리소스에 대한 OPTIONS 요청을 보내면 해당 리소스에 대해 지원되는 HTTP 메서드나 필요한 요구 사항 등을 확인할 수 있습니다.
예를 들자면 OPTIONS 메서드를 사용해 서버가 어떤 메서드(GET, POST, PUT, …)를 지원하는지 알 수 있습니다.
서버의 전반적인 기능이나 리소스의 요구 사항을 확인하기 위해 사용되며 리소스를 변경하거나 데이터를 가져오는 작업을 수행하지는 않습니다.
“*” 대상 사용 시의 의미
An OPTIONS request with an asterisk ("*") as the request target (Section 7.1) applies to the server in general rather than to a specific resource.
요청 대상이 특정 리소스가 아닌 서버 전체일 때 ”*“를 사용한다고 합니다. 와일드 카드인가요?
- “*”를 사용한 OPTIONS 요청의 의미
OPTIONS 메서드는 보통 특정 리소스에 대한 통신 옵션을 확인하기 위해 사용됩니다.
하지만 요청 대상에 “*”를 사용하면 이는 특정 리소스가 아닌 서버 전체에 대해 적용되며 이 요청은 서버 자체의 전반적인 통신 옵션을 확인하는 요청이 됩니다.
예를 들어 특정 리소스에 적용되는 통신 옵션이 아닌 서버가 전반적으로 어떤 HTTP 메서드와 기능을 지원하는지 확인하고자 할 때 사용할 수 있습니다.
- “*” 요청은 리소스별 차이를 무시
일반적인 OPTIONS 요청은 특정 리소스에 대한 정보를 반환합니다. 즉 그 리소스에 대해 서버가 어떤 메서드를 지원하는지 추가적인 요구 사항이 있는지 등을 확인할 수 있습니다.
반면 “*” 요청은 리소스별로 적용되는 차이를 무시하고 서버 전체에 대한 통신 옵션을 확인합니다. 예를 들자면 서버가 HTTP/1.1을 지원하는지, 일반적인 메서드(GET, POST 등)를 지원하는지 확인 가능합니다.
- 사용 목적
이러한 요청은 특정 리소스와는 무관하게 서버 전체의 기능을 테스트하거나 확인하는데 유용합니다. 어떤 HTTP 사양을 준수하는지 확인할 수 있으니까요
그러나 문서에서는 “*”를 사용하는 OPTIONS 요청이 주로 ping, no-operation 방식으로 사용된다고 설명하고 있습니다.
ping은 클라이언트가 서버에 테스트 요청을 보내 서버가 응답할 수 있는 상태인지를 확인할 때 사용됩니다. 이는 네트워크 연결 상태나 서버의 가용성을 테스트하는 목적입니다.
no-op은 특정 작업을 수행하지 않으면서 서버의 기능을 확인하는 방식으로 리소스를 변경하거나 조회하지 않고 단순히 서버의 옵션이나 상태를 확인하는 것입니다.
OPTIONS * HTTP/1.1
Host: www.gojimin.com
OPTIONS 요청에서 서버의 응답
문서에선 OPTIONS 요청에 대한 서버의 응답 방식도 설명하고 있습니다.
- 서버의 성공적인 응답
서버는 OPTIONS 요청에 대해 성공적인 응답을 생성할 때 해당 리소스나 서버에서 지원하는 기능을 나타내는 헤더 필드를 포함해야 한다고 합니다.
예를 들어 Allow 헤더를 통해 해당 리소스에서 지원하는 HTTP 메서드 목록을 클라이언트에 제공할 수 있습니다.
ÒPTIONS /post-1 HTTP/1.1
Host: www.gojimin.com
HTTP/1.1 200 OK
Allow: GET
- 확장 기능
서버는 RFC에 정의된 HTTP 메서드 외에도 추가적인 확장 기능이나 서버 고유의 기능을 제공할 수 있습니다.
문서에선 OPTIONS 응답에서 서버가 지원하는 확장 기능을 명시할 수 있음을 설명하고 있습니다. 이 확장 기능은 해당 리소스에서만 지원되는 특별한 메서드일 수도 있고 HTTP 사양에 정의되지 않은 특별한 기능일 수도 있습니다.
- 기계나 사람이 읽을 수 있는 응답
서버는 OPTIONS 응답에서 기계가 읽을 수 있는 형식 또는 사람이 읽을 수 있는 형식으로 서버의 통신 옵션을 설명하는 내용을 본문에 포함할 수 있다고 합니다.
예를 들어 JSON이나 XML 형식으로 서버의 지원 옵션을 제공할 수 있으며 이를 통해 클라이언트가 응답 내용을 해석할 수 있습니다.
그러나 RFC 문서에서는 어떤 형식으로 정보를 제공해야 하는지에 대한 명확한 표준은 없고 미래에 이러한 형식이 정의될 수 있다고 합니다..
Max-Forwards 헤더
우선 Max-Forwards 헤더는 클라이언트가 보낸 요청이 중간 서버를 몇 번 거처야 하는지를 제어하는 HTTP 헤더로 프록시 서버나 다른 중계 서버가 요청을 처리할 때 유용합니다.
이 헤더는 요청이 얼마나 많은 서버를 거칠 수 있는지에 대한 제한 횟수를 설정하며 값이 0에 도달하면 요청이 더 이상 전달되지 않고 해당 서버에서 요청을 처리하게 됩니다.
OPTIONS 메서드에서의 용도
OPTIONS 메서드에서 Max-Forwards는 클라이언트가 특정 서버에 요청을 전달하고 싶을 때 사용될 수 있습니다.
클라이언트가 여러 프록시 서버를 거쳐 원하는 목적지 서버에 OPTIONS 요청을 보내고자 할 때 해당 헤더를 사용해 요청이 중간 서버에서 멈추지 않고 정확히 몇 번의 중계를 통해 최종 목적지 서버까지 도달할지 제어할 수 있습니다.
동작 방식
Max-Forwards의 값이 클라이언트에 의해 설정되면 요청이 각 중간 서버를 지날 때마다 1씩 감소하게 됩니다.
이 값이 0에 도달하면 해당 요청이 더 전달되지 않고 해당 중간 서버에서 응답을 처리하게 되는데 이를 통해 프록시 체인을 통해 요청이 전달되는 깊이를 제어할 수 있게 됩니다.
프록시 서버의 규칙
프록시 서버는 Max-Forwards 헤더를 임의로 생성할 수 없습니다. 클라이언트로부터 받은 OPTIONS 요청에 의해 Max-Forwards 헤더가 포함되어 있는 경우에만 그 값을 감소시키며 요청을 전달합니다.
클라이언트가 Max-Forwards 헤더 없이 OPTIONS 요청을 보낸 경우 프록시 서브는 임의로 해당 헤더를 추가할 수 없습니다.
OPTIONS /post/412 HTTP/1.1
Host: gojimin.com
Max-Forwards: 3
위의 요청은 첫 번째 중계 서버에 도착하면 Max-Forwards 값이 2로 감소하고 두 번째 중계 서버에 도착하면 1로, 세 번째 서버에서는 0이 됩니다. 0에 도달한 서버는 더 전달하지 않고 OPTIONS 요청에 대한 응답을 처리하게 됩니다.
OPTIONS 요청에서 콘텐츠가 포함된 경우
문서에선 OPTIONS 요청에 본문이 포함된 경우 클라이언트가 어떻게 처리해야 하는지 설명하고 있습니다.
일반적으로 OPTIONS 요청은 본문을 포함하지 않는 경우가 많습니다. OPTIONS 요청은 리소스에 대한 정보나 서버의 기능을 확인하기 위한 것이므로 본문이 필요하지 않은 경우가 대부분입니다.
하지만 클라이언트가 특정한 이유로 본문을 포함한 OPTIONS 요청을 보내고자 할 때 본문의 형식과 미디어 타입을 명확히 정의해야 합니다.
OPTIONS 요청에 본문이 포함된 경우 클라이언트는 반드시 Content-Type 헤더를 사용해 본문이 어떤 형식인지를 서버에 알려한다고 합니다.
예를 들어 본문이 JSON 타입이라면 Content-Type: application/json과 같은 헤더를 사용해야 합니다.
문서에서도 대부분의 OPTIONS 요청은 본문을 필요로 하지 않음을 말하고 있으며 서버는 OPTIONS 요청의 본문 없이도 충분한 정보를 제공할 수 있습니다.
하지만 클라이언트가 특정한 용도로 본문을 포함한다면 반드시 Content-Type을 포함하는 규칙을 지켜야만 합니다.
OPTIONS 응답은 캐시되지 않음
OPTIONS 메서드는 특정 리소스나 서버의 통신 옵션을 실시간으로 확인하기 위한 메서드로 서버의 통신 옵션은 시간이 지남에 따라 변경될 수 있습니다.
따라서 OPTIONS 메서드에 대한 응답은 캐시되지 않아야 합니다.
클라이언트는 매 번 변경된 정보를 받기 위해 OPTIONS 요청을 다시 보내야 하며 이전 응답을 캐시해 사용하는 것은 적절하지 않습니다.
TRACE
사실 전 TRACE는 정말 단 한 번도 사용해본 기억이 없습니다.
TRACE 메서드란?
The TRACE method requests a remote, application-level loop-back of the request message.
TRACE 메서드는 클라이언트가 서버에 자신의 요청을 그대로 돌려받도록 요청하는 메서드입니다. loop-back 이라고 적혀있네요..
음.. 말 그대로 서버는 클라이언트로부터 받은 요청을 그대로 복사해 클라이언트에게 다시 응답으로 돌려보냅니다. 이 응답으로 클라이언트는 요청이 서버에 도달했을 때 어떻게 처리되었는지 확인할 수 있게 됩니다.
TRACE는 리소스를 변경하거나 조회하는 것이 아니라 디버깅 및 네트워크 진단용으로 사용된다고 합니다. 이 메서드를 통해 요청이 원래 의도한 대로 서버에 도착했는지, 혹은 중간 경로에서 요청이 어떻게 변경되었는지를 확인할 수 있습니다.
여기서 최종 수신자는 오리진 서버가 될 수도 있고 위에서 살펴본 Max-Forwards 헤더의 값이 0에 도달한 서버가 될 수도 있습니다.
이 말은! 클라이언트가 TRACE 요청을 여러 서버를 거쳐 보낸다면 Max-Forwards 값이 0이 되는 서버가 요청을 처리하는 최종 수신자가 될 수 있음을 의미합니다.
TRACE /posts/411 HTTP/1.1
Host: gojimin.com
그럼 이 요청은 제 블로그 서버에 보내진 요청으로 서버는 이 요청을 그대로 복사해 클라이언트에게 응답하게 됩니다.
TRACE 요청에서의 민감한 데이터 처리
A client MUST NOT generate fields in a TRACE request containing sensitive data that might be disclosed by the response.
문서에선 TRACE 요청에서 민감한 데이터를 어떻게 처리해야 하는지 설명하고 있습니다.
TRACE 요청은 클라이언트의 요청을 그대로 서버가 응답으로 반사하는 방식이기 때문에 민감한 데이터를 포함해서는 안됩니다.
여기서 민감한 데이터는 사용자 인증 정보인 비밀번호, 토큰 혹은 쿠키와 같은 정보를 의미합니다.
TRACE 요청이 네트워크 상에서 쉽게 노출될 수 있기 때문에 TRACE 요청에 민감한 정보가 포함될 경우 보안적인 문제가 발생할 수 있습니다.
위와 같은 문제로 TRACE 요청을 받은 최종 수신자 서버는 응답을 생성할 때 민감한 데이터가 포함된 필드는 제외해야 합니다.
TRACE 메서드를 통한 경로 추적
TRACE의 주요 기능은 요청 경로를 확인하는 기능입니다.
TRACE 메서드는 클라이언트가 보낸 요청이 서버에서 어떻게 처리되었는지 확인할 수 있는 디버깅 도구로 볼 수 있습니다.
클라이언트가 TRACE 요청을 보내면 서버는 그대로 반사해 보내주게 되는데 이 때 클라이언트는 요청이 서버에 도달했을 때 이 요청이 어떻게 보였는지를 확인할 수 있고 특히 네트워크를 통해 이동하며 중간 서버에서 이 요청이 변경되었거나 추가된 정보가 있는지 확인하는데 유용하다고 합니다.
Via 헤더
문서에선 이 Via 헤더가 TRACE 메서드에서 경로를 추적하는데 있어 매우 중요한 역할을 수행한다고 합니다.
Via 헤더는 요청이 어떤 서버들을 거쳤는지를 기록하는 헤더로 각 중간 서버는 요청을 처리할 때 이 헤더에 자신을 추가하게 됩니다.
따라서 클라이언트는 TRACE 응답에서 Via 헤더를 분석함으로써 요청이 어떤 중계 서버들을 거쳐 최종 서버에 도달했는지를 확인할 수 있게 됩니다.
TRACE /posts/411 HTTP/1.1
Host: gojimin.com
HTTP/1.1 200 OK
Via: 1.1 jiminProxy1, 1.1 jiminProxy2
만약 이런 응답이 온다면 우리는 jiminProxy1, jiminProxy2를 거쳐 요청이 전달되었음을 확인할 수 있습니다. 이 정보를 통해 네트워크 상에서 일어난 문제를 추적하거나 의도하지 않은 경로를 거쳤는지 확인할 수 있게 됩니다.
Max-Forwards 헤더와의 연관성
계속해서 등장하는 Max-Forwards 헤더는 TRACE 요청에서 이 요청이 중간 서버를 얼마나 거쳐 전달될 수 있는지를 제한하게 됩니다.
클라이언트가 이 값을 설정하며 거칠 때마다 1씩 감소하겠죠? 그러다 0이 되면 해당 서버가 최종 목적지 서버가 되어 요청을 처리하게 되겠군요?
그럼 클라이언트가 특정 중계 서버에서 TRACE 요청이 멈추도록 제어할 수 있고 해당 서버까지의 경로를 추적하는데에도 사용이 가능하게 됩니다.
위와 같은 특성으로 TRACE 메서드는 주로 네트워크 진단 및 디버깅 용도로 사용됩니다. 클라이언트가 요청을 서버로 보낼 때 중간에 있는 프록시 서버나 네트워크 장치들이 이 요청을 어떻게 처리했는지를 정확히 알고자 할 때 TRACE 메서드를 사용합니다.
혹시 중간 서버에서 변형되었거나, 우리가 예상하지 못한 추가 헤더가 삽입되었는지를 확인할 수 있게 됩니다.
본문 처리 금지
TRACE 요청은 본문을 포함하지 않는다고 합니다.
당연하게도 TRACE 요청은 요청 자체가 서버에 의해 반사되는 것이기 때문에 클라이언트는 TRACE 요청에 본문을 포함할 수 없습니다.
필요하지도 않고, 요청 헤더에 있는 정보만으로도 충분히 서버와 클라이언트 간의 loop-back 기능을 수행하기 충분합니다.
본질 자체도 요청 자체의 경로 추적이며 리소스를 조회하거나 변경하는 작업이 아니며 요청이 서버에 어떻게 도달했는지를 확인하는 메서드입니다.
따라서 본문을 포함할 필요가 없으며 본문을 포함하면 안된다는 규칙이 있습니다.
바로 밑에 캐시 안된다고 나와있는데 위의 이유로 캐시의 필요도 없습니다..
마치며…
이번 포스팅으로 드디어 HTTP 메서드에 대해 정리를 어느정도 끝냈습니다..
사실 중간에 후회를 많이 한 이유로 이거 진짜 너무 오래 걸렸습니다. 진짜 끔찍한 시간이었습니다.
그냥 정리하다가 아니 근데 왜 이렇게 말하지? 싶으면 또 찾아보고.. 그러다가 아니 여기서 이 말은 또 왜 나와? 싶어서 또 찾아보고 사실 뭐 일주일이면 끝나겠지 ㅋ 하고 시작한게 이렇게 오래 걸릴 줄 몰랐습니다.
근데 이렇게 끝내놓고 보니 얻어가는 것도 많다고 느껴지고 사실 제가 정리한 내용이라 나중에 제가 다시 꺼내보기도 좋잖아요?
여담인데 전 지하철이나 버스 처럼 짧게? 10분, 20분 이동하는 시간에 제 블로그 다시 읽어보면서 공부하는 거 좋아합니다. 제가 써서 그런지 다시 읽을 때 이해가 잘 가기도 합니다.
사실 다시 읽다가 오타 발견하면 아.. 집 가서 수정해야지.. 하다가 집 오면 다른 거 하느라 또 까먹고 다음에 다시 보고 아.. 오늘은 진짜 고쳐야지.. 합니다..
뭐 하여튼 여기까지 읽어주셨다면 정말 감사합니다…
.
.
.
뿅..