성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] Working with Rust Libraries from C#...
[정성태] Detecting blocking calls using asyn...
[정성태] 아쉽게도, 커뮤니티는 아니고 개인 블로그입니다. ^^
[정성태] 질문이 잘 이해가 안 됩니다. 우선, 해당 소스코드에서 ILis...
[양승조
] var대신 dinamic으로 선언해서 해결은 했습니다. 맞는 해...
[양승조
] 또 막혔습니다. ㅠㅠ var list = props[i].Ge...
[양승조
] 아. 감사합니다. 어제는 안됐던것 같은데....정신을 차려야겠네...
[정성태] "props[i].GetValue(props[i])" 코드에서 ...
[정성태] 저렇게 조각 코드 말고, 실제로 재현이 되는 예제 프로젝트를 압...
[정성태] Modules 창(Ctrl+Shift+U)을 띄워서, 해당 Op...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>IIS의 HTTP/2 지원 여부 - h2, h2c</h1> <p> 우선 h2, h2c에 대한 용어부터 정리해야겠습니다. ^^<br /> <br /> 글을 읽다 보면, 간혹 HTTP/1.1을 h1, HTTP/2.0을 h2로 표기하는 것을 보게 됩니다. 사실 이게 엄밀히 말해서, 그냥 줄여서 표현하기 위해 그런 것인지 공식적으로 저 명칭이 있는 것인지는 잘 모르겠습니다. 가령 HTTP/1.1 RFC 문서에서는,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Hypertext Transfer Protocol -- HTTP/1.1 ; <a target='tab' href='https://tools.ietf.org/html/rfc2616'>https://tools.ietf.org/html/rfc2616</a> </pre> <br /> "h1"이라는 단어 자체가 없습니다. 따라서, 아마도 문맥에 따라 h1을 기존의 HTTP/1.1로 이해하는 것이 맞을 수 있습니다. (혹시 이에 대한 이력을 알고 계신 분은 덧글 부탁드립니다. ^^)<br /> <br /> 그런데, h2의 경우에는 좀 다릅니다. HTTP/2 공식 문서에는,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Hypertext Transfer Protocol Version 2 (HTTP/2) ; <a target='tab' href='https://tools.ietf.org/html/rfc7540'>https://tools.ietf.org/html/rfc7540</a> ; <a target='tab' href='https://httpwg.org/specs/rfc7540.html'>https://httpwg.org/specs/rfc7540.html</a> </pre> <br /> 분명히 버전 식별자로써 이에 대한 설명이 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 3.1. HTTP/2 Version Identification The protocol defined in this document has two identifiers. o The string "<span style='color: blue; font-weight: bold'>h2</span>" identifies the protocol where HTTP/2 uses Transport Layer Security (TLS) [TLS12]. This identifier is used in the TLS application-layer protocol negotiation (ALPN) extension [TLS-ALPN] field and in any place where HTTP/2 over TLS is identified. The "h2" string is serialized into an ALPN protocol identifier as the two-octet sequence: 0x68, 0x32. </pre> <br /> 즉, (문맥에 따라 줄임말일 수 있지만) HTTP/2에 대한 줄임말로서의 "h2"가 아니라, TLS 통신과 함께 그것의 <a target='tab' href='https://tools.ietf.org/html/rfc7301'>ALPN 확장</a>이 쌍을 이뤄 사용하는 HTTP/2의 프로토콜 식별자입니다. 그리고, TLS를 사용하지 않는 일반 평문 통신에서 HTTP/2의 프로토콜 식별자를 의미하는 h2c가 있습니다. (h2c의 c는 cleartext를 의미합니다.)<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > o The string "<span style='color: blue; font-weight: bold'>h2c</span>" identifies the protocol where HTTP/2 is run over cleartext TCP. This identifier is used in the HTTP/1.1 Upgrade header field and in any place where HTTP/2 over TCP is identified. The "h2c" string is reserved from the ALPN identifier space but describes a protocol that does not use TLS. </pre> <br /> 즉, 간단하게 정리하면 h2는 https 위에서, h2c는 http 위에서 동작하는 HTTP/2.0에 대한 프로토콜 식별자인 것입니다.<br /> <br /> <hr style='width: 50%' /><br /> <a name='h2c_upgrade'></a> <br /> h2, h2c를 이야기할 때 언급해야 할 것이 또 하나 있다면 바로 "협상"입니다. 웹 브라우저 입장에서는 서버 측에서 HTTP/2 프로토콜을 제공하지 않는다면 HTTP/1.1로도 통신이 가능하게 만들어야 하므로 서버가 HTTP/2를 구현하고 있는지 알아내는 과정이 필요합니다.<br /> <br /> 우선, h2의 경우에는 어차피 TLS 협상이 필요하기 때문에 이 과정에 얹어서 함께 진행되므로 별도의 협상 과정이 필요 없습니다. 반면, h2c의 경우에는 다릅니다. http:// 통신은 소켓 연결 후 곧바로 HTTP 헤더를 보내 통신을 게시하므로 처음부터 HTTP/2 통신을 진행할 수는 없고 일단 HTTP/1.1 요청을 보낸 후 서버의 응답 결과에 따라 이후 HTTP/2 통신을 게시합니다. 이에 대해서는 <a target='tab' href='https://tools.ietf.org/html/rfc7540'>RFC7540</a> 문서에서 명시하고 있는데, 우선 웹 브라우저는 다음의 요청을 서버에 보내고,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > GET / HTTP/1.1 Host: server.example.com <span style='color: blue; font-weight: bold'>Connection: Upgrade, HTTP2-Settings</span> <span style='color: blue; font-weight: bold'>Upgrade: h2c</span> HTTP2-Settings: <base64url encoding of HTTP/2 SETTINGS payload> </pre> <br /> 만약 서버가 HTTP/2를 지원하지 않는다면 응답 헤더에 "Upgrade" 헤더를 포함하지 않는 식으로 클라이언트에 GET 요청에 따른 리소스와 함께 응답합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > HTTP/1.1 200 OK Content-Length: 243 Content-Type: text/html ... </pre> <br /> 결국 HTTP/1.1의 요청과 응답으로 이뤄지기 때문에 기존 HTTP/1.1 통신의 입장에서는 협상에 따른 별도의 부하가 발생하는 것은 아닙니다. <br /> <br /> 반면, 만약 HTTP/2.0을 지원한다면 프로토콜 스위치를 위한 "Upgrade: h2c" 헤더를 함께 응답에 추가하고,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > HTTP/1.1 <span style='color: blue; font-weight: bold'>101</span> Switching Protocols Connection: Upgrade <span style='color: blue; font-weight: bold'>Upgrade: h2c</span> [ HTTP/2 connection ...] </pre> <br /> 이후부터는 자연스럽게 HTTP/2.0 규약에 맞게 통신을 지속합니다. 즉, 협상을 한다고 해도 첫 번째 요청에 대해서만 HTTP/1.1 통신을 하는 것일 뿐 이후의 통신 과정은 HTTP/2.0을 따르므로 마찬가지로 협상으로 인한 부하가 발생하는 것은 아닙니다.<br /> <br /> 또한, h2c 방식에서도 저렇게 협상을 하지 않고 곧바로 HTTP/2.0 규격으로 통신을 게시할 수 있습니다. (당연히, 이런 경우에는 HTTP/2.0을 지원하지 않는 서버와는 정상적인 통신을 하지 못합니다.)<br /> <br /> <hr style='width: 50%' /><br /> <a name='curl_http2'></a> <br /> 자, 그럼 실제로 저 차이점들을 간단하게 curl.exe를 이용해 확인해 볼까요? ^^ (윈도우 사용자는 WSL2 환경의 리눅스에 있는 curl을 권장합니다.)<br /> <br /> 서버는 잘 알려진 nghttp2.org를 이용할 수 있으므로, 다음은 h2c + 협상을 이용해 HTTP/2 통신을 한 결과를 보여줍니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > $ <span style='color: blue; font-weight: bold'>curl --http2 -I nghttp2.org</span> <span style='color: blue; font-weight: bold'>HTTP/1.1 101 Switching Protocols</span> Connection: Upgrade Upgrade: h2c <span style='color: blue; font-weight: bold'>HTTP/2 200</span> date: Sat, 16 Jan 2021 06:42:43 GMT content-type: text/html last-modified: Mon, 23 Nov 2020 15:07:46 GMT etag: "5fbbd042-19d8" accept-ranges: bytes content-length: 6616 x-backend-header-rtt: 0.002868 server: nghttpx via: 2 nghttpx alt-svc: h3-29=":443"; ma=3600 x-frame-options: SAMEORIGIN x-xss-protection: 1; mode=block x-content-type-options: nosniff </pre> <br /> <a name='http2_prior'></a> 반면, 협상 없이 무조건 HTTP/2 프로토콜로 h2c 통신을 하려면 이렇게 옵션을 추가하면 됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > $ <span style='color: blue; font-weight: bold'>curl --http2-prior-knowledge -I nghttp2.org</span> <span style='color: blue; font-weight: bold'>HTTP/2 200</span> date: Sat, 16 Jan 2021 06:42:56 GMT content-type: text/html last-modified: Mon, 23 Nov 2020 15:07:46 GMT etag: "5fbbd042-19d8" accept-ranges: bytes content-length: 6616 x-backend-header-rtt: 0.00316 server: nghttpx via: 2 nghttpx alt-svc: h3-29=":443"; ma=3600 x-frame-options: SAMEORIGIN x-xss-protection: 1; mode=block x-content-type-options: nosniff </pre> <br /> 마지막으로, h2 통신을 실습해 보면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > $ <span style='color: blue; font-weight: bold'>curl --http2 -I https://nghttp2.org</span> <span style='color: blue; font-weight: bold'>HTTP/2 200</span> date: Sat, 16 Jan 2021 07:03:19 GMT content-type: text/html last-modified: Mon, 23 Nov 2020 15:07:46 GMT etag: "5fbbd042-19d8" accept-ranges: bytes content-length: 6616 x-backend-header-rtt: 0.004217 strict-transport-security: max-age=31536000 server: nghttpx via: 2 nghttpx alt-svc: h3-29=":443"; ma=3600 x-frame-options: SAMEORIGIN x-xss-protection: 1; mode=block x-content-type-options: nosniff // 어차피 TLS 협상이므로 굳이 --http2 옵션을 주지 않아도 https 접근 시에 h2를 설정하는 듯합니다. $ curl -I <span style='color: blue; font-weight: bold'>https://nghttp2.org</span> <span style='color: blue; font-weight: bold'>HTTP/2 200</span> date: Sat, 16 Jan 2021 07:04:32 GMT content-type: text/html last-modified: Mon, 23 Nov 2020 15:07:46 GMT etag: "5fbbd042-19d8" accept-ranges: bytes content-length: 6616 x-backend-header-rtt: 0.001008 strict-transport-security: max-age=31536000 server: nghttpx via: 2 nghttpx alt-svc: h3-29=":443"; ma=3600 x-frame-options: SAMEORIGIN x-xss-protection: 1; mode=block x-content-type-options: nosniff </pre> <br /> "https"로 인해 TLS 협상이 이뤄지고 결국 h2c 테스트의 --http2-prior-knowledge 옵션과 동일하게 별도의 "101 Switching Protocols" 과정 없이 진행된 것을 확인할 수 있습니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> 자, 길고 긴 서문을 지나서 이제야 제목에 맞는 글을 쓰게 되는군요. ^^<br /> <br /> 우선, 공식 문서를 보면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > HTTP/2 on IIS ; <a target='tab' href='https://learn.microsoft.com/en-us/iis/get-started/whats-new-in-iis-10/http2-on-iis'>https://learn.microsoft.com/en-us/iis/get-started/whats-new-in-iis-10/http2-on-iis</a> </pre> <br /> <a target='tab' href='https://en.wikipedia.org/wiki/Internet_Information_Services'>Windows 10의 경우 1607 버전, Windows Server의 경우에는 2016 버전</a>에 탑재된 IIS 10.0부터 HTTP/2를 지원하며, 이와 함께 다음의 제약이 있다고 합니다.<br /> <br /> <ul> <li>Windows authentication (NTLM/Kerberos/Negotiate) is not supported with HTTP/2. In this case IIS will fall back to HTTP/1.1.</li> <li><span style='color: blue; font-weight: bold'>Clear text</span> - as mentioned above, IIS currently only supports HTTP/2 over TLS. Again, IIS will fall back to HTTP/1.1.</li> <li>Bandwidth throttling - IIS has a feature to limit bandwidth (in Inetmgr, select the site, 'Limits' under Configure of the Action pane). This applies to HTTP/1.1 but is not enforced for HTTP/2 (will proceed with no errors or bandwidth limiting).</li> </ul> <br /> 음... h2c 방식은 지원하지 않는다는 건데, 그래도 최신 버전인 Windows 10의 20H2 업데이트(버전 19042)에 있는 IIS는 뭔가 달라질 수도 있으니 nghttp2.org에 했던 것과 유사하게 테스트를 해보겠습니다. 우선 가장 궁금한 h2c, 즉 평문으로 HTTP/2.0 통신이 가능한지 이렇게 명령을 내리면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > /* IIS 서버 IP: 210.91.106.100 */ $ <span style='color: blue; font-weight: bold'>curl --http2-prior-knowledge -I http://210.91.106.100</span> curl: (16) Error in the HTTP2 framing layer </pre> <br /> 지원을 안 하는군요. ^^ 그래도 --http2 옵션을 지정하면 협상을 진행하기 때문에 HTTP/1.1로 통신이 진행됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > $ <span style='color: blue; font-weight: bold'>curl --http2 -I http://210.91.106.100</span> <span style='color: blue; font-weight: bold'>HTTP/1.1 200 OK</span> Content-Length: 696 Content-Type: text/html Last-Modified: Fri, 12 Jun 2020 04:28:37 GMT Accept-Ranges: bytes ETag: "38365f17140d61:0" Server: Microsoft-IIS/10.0 X-Powered-By: ASP.NET Date: Sat, 16 Jan 2021 08:08:27 GMT </pre> <br /> 물론, (문서에 명시했으므로 당연하겠지만) h2 방식은 지원합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > /* https 인증서: 테스트 인증서를 사용했으므로 curl에 -k 옵션 추가 */ $ <span style='color: blue; font-weight: bold'>curl --http2 -k -I https://210.91.106.100</span> <span style='color: blue; font-weight: bold'>HTTP/2 200</span> content-length: 696 content-type: text/html last-modified: Fri, 12 Jun 2020 04:28:37 GMT accept-ranges: bytes etag: "38365f17140d61:0" server: Microsoft-IIS/10.0 x-powered-by: ASP.NET date: Sat, 16 Jan 2021 08:06:54 GMT $ <span style='color: blue; font-weight: bold'>curl -k -I https://210.91.106.100</span> <span style='color: blue; font-weight: bold'>HTTP/2 200</span> content-length: 696 content-type: text/html last-modified: Fri, 12 Jun 2020 04:28:37 GMT accept-ranges: bytes etag: "38365f17140d61:0" server: Microsoft-IIS/10.0 x-powered-by: ASP.NET date: Sat, 16 Jan 2021 08:06:58 GMT </pre> <br /> <hr style='width: 50%' /><br /> <br /> 참고로 아래의 글에 나온,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > I get the message: "Cant connect securely to this page. This might be because the site uses outdated or unsafe TLS security settings. ; <a target='tab' href='https://learn.microsoft.com/en-us/windows-server/manage/windows-admin-center/support/troubleshooting#i-get-the-message-cant-connect-securely-to-this-page-this-might-be-because-the-site-uses-outdated-or-unsafe-tls-security-settings'>https://learn.microsoft.com/en-us/windows-server/manage/windows-admin-center/support/troubleshooting#i-get-the-message-cant-connect-securely-to-this-page-this-might-be-because-the-site-uses-outdated-or-unsafe-tls-security-settings</a> </pre> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > EnableHttp2Tls REG_DWORD 0 EnableHttp2Cleartext REG_DWORD 0 </pre> <br /> EnableHttp2Cleartext를 1로 설정해봤으나, h2c는 여전히 안 됩니다. 일단, 공식 문서 상으로 h2c에 대한 언급이 없으니 IIS에서는 안 되는 게 맞습니다. ^^<br /> <br /> 그 외에, 간혹 보면 HTTP/2를 활성화하기 위해 DuoEnabled 레지스트리 키를 설정하라는 글이 나오는데,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Microsoft IIS 10.0 - Installing HTTP/2 on IIS 10.0 ; <a target='tab' href='https://devopspoints.com/microsoft-iis-10-0-installing-http-2-on-iis-10-0-999.html'>https://devopspoints.com/microsoft-iis-10-0-installing-http-2-on-iis-10-0-999.html</a> </pre> <br /> 이것은 Windows 10 CTP 버전에 한해서이고, 현재의 버전에서는 해당 레지스트리 설정이 아무런 역할을 하지 않습니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> Windows 10 사용자의 경우, (Windows 10 1803 빌드부터 기본 포함되어 있기도 한) curl.exe를 사용해 --http2 옵션을 테스트하면 다음과 같은 오류가 발생합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C:\temp> <span style='color: blue; font-weight: bold'>curl --http2 -I https://nghttp2.org</span> curl: (1) Unsupported protocol C:\temp> <span style='color: blue; font-weight: bold'>curl --version</span> curl 7.55.1 (Windows) libcurl/7.55.1 WinSSL Release-Date: 2017-11-14, security patched: 2019-11-05 Protocols: dict file ftp ftps http https imap imaps pop3 pop3s smtp smtps telnet tftp Features: AsynchDNS IPv6 Largefile SSPI Kerberos SPNEGO NTLM SSL </pre> <br /> 이에 대해서는 이미 알려져 있는데,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Curl shipped with Windows does not support HTTP2 #3141 ; <a target='tab' href='https://github.com/microsoft/WSL/issues/3141'>https://github.com/microsoft/WSL/issues/3141</a> </pre> <br /> "curl --version"의 출력 결과에 "nghttp2" 문구가 있는 버전을 사용해야 합니다. 따라서 별도로 다른 도구와 설치된 curl.exe를 사용하거나, (약간 불안하지만 지원이 되도록 빌드한) <a target='tab' href='https://winampplugins.co.uk/curl/'>바이너리를 다운로드</a>하거나, 또는 직접 빌드하거나 셋 중 하나를 선택하면 됩니다.<br /> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
1731
(왼쪽의 숫자를 입력해야 합니다.)