다음을 통해 공유


IIS에서 HTTP 400 오류 문제 해결

적용 대상: 인터넷 정보 서비스

이 문서에서는 IIS를 사용할 때 다양한 HTTP 400 오류의 원인을 식별하는 문제 해결 단계를 설명합니다.

개요

HTTP 클라이언트(예: Microsoft Edge)가 IIS 서버에 HTTP 요청을 보낸 후 다음과 같은 유형의 오류 메시지가 표시될 수 있습니다.

HTTP 400 - 잘못된 요청

이 시나리오에서 IIS는 요청이 서버의 HTTP 구문 분석 규칙을 충족하지 않거나 시간 제한을 초과하거나 IIS 또는 HTTP.sys 들어오는 요청을 준수해야 하는 다른 규칙에 실패하기 때문에 클라이언트의 HTTP 요청을 거부합니다. IIS는 HTTP 400 - Bad Request 상태를 클라이언트로 다시 보낸 다음 TCP 연결을 종료합니다.

도구

문제 해결 방법

HTTP 400 조건 문제를 해결할 때 기본 문제는 클라이언트가 HTTP.sys 적용하는 하나 이상의 규칙을 위반하는 요청을 IIS에 보냈다는 것입니다. 이 점을 염두에 두고 클라이언트가 IIS에 정확히 무엇을 보내는지 확인할 수 있습니다. 이렇게 하려면 잘못된 요청을 보내는 클라이언트의 네트워크 추적을 캡처합니다. 추적을 분석하여 클라이언트가 IIS에 보내는 원시 데이터를 확인하고 IIS가 클라이언트로 다시 보내는 원시 응답 데이터를 볼 수 있습니다. 클라이언트와 서버가 SSL을 통해 통신하는 경우에도 HTTP 헤더를 볼 수 있도록 해주는 훌륭한 도구인 Fiddler라는 HTTP 스니퍼 도구를 사용할 수도 있습니다.

사용하는 다음 데이터 항목은 C:\Windows\System32\LogFiles\HTTPERR\httperr.log 파일입니다. IIS에서 HTTP.sys 구성 요소는 들어오는 HTTP 요청을 IIS에 전달하기 전에 처리하고 IIS 요구 사항을 충족하지 않는 요청을 차단합니다. HTTP.sys 요청을 차단하면 잘못된 요청 및 차단된 이유에 관한 정보를 httperr.log 파일에 기록합니다.

참고 항목

HTTP.sys 제공하는 HTTP API 오류 로깅에 대한 자세한 내용은 HTTP API의 오류 로깅을 참조하세요.

기술적으로는 가능하지만 클라이언트가 http 400 응답을 받을 수 있으며 httperr.log 파일에 연결된 로그 항목 이 없습니다. ISAPI 필터 또는 확장 또는 IIS의 HTTP 모듈이 400 상태를 설정하는 경우 발생할 수 있습니다. 이 경우 IIS 로그에서 자세한 내용을 확인할 수 있습니다. 또한 프록시 서버 또는 다른 네트워크 디바이스와 같이 클라이언트와 서버 간의 엔터티가 IIS의 응답을 가로채서 자체 400 상태 및/또는 "잘못된 요청" 오류로 재정의하는 경우에도 발생할 수 있습니다.

참고 항목

이 문서에서는 웹 사이트에 도달하기 전에 일반적인 HTTP 400 오류에 대해 주로 설명합니다. 일부 시나리오에서는 웹 사이트가 사용자 지정 코드 논리 또는 런타임(예: ASP.NET) 구성으로 인해 클라이언트에 HTTP 400 오류를 반환할 수도 있습니다. 다음 섹션의 단계를 수행한 후에도 HTTP 400 오류를 해결할 수 없는 경우 IIS에서 실패한 요청 추적 기능을 사용하여 문제를 해결해 보세요. http 400 오류가 실제로 웹 사이트의 해당 런타임 처리기(예: ASP.NET)에 의해 설정되는 경우 HTTP 400 오류의 원인을 이해하려면 웹 사이트의 관련 코드 논리 및 런타임 구성과 함께 요청 및 응답의 세부 정보를 검사해야 할 수 있습니다.

샘플 시나리오

다음은 클라이언트가 IIS에 잘못된 요청을 보내고 서버가 "HTTP 400 - 잘못된 요청" 메시지를 다시 보내는 HTTP 400 시나리오의 예입니다.

클라이언트가 요청을 보내면 다시 가져오는 브라우저 오류는 다음과 같습니다.

잘못된 요청(헤더 필드가 너무 깁니다.)

요청 및 응답의 네트워크 추적을 캡처하면 다음과 같은 출력이 표시됩니다.

요청:

HTTP: GET Request from Client
HTTP: Request Method =GET
HTTP: Uniform Resource Identifier =/1234567890123456789012345678901234567890/time.asp
HTTP: Protocol Version =HTTP/1.1
HTTP: Accept-Language =en-us
HTTP: UA-cpu =x86
HTTP: Accept-Encoding =gzip, deflate
HTTP: Host =iisserver
HTTP: Connection =Keep-Alive
HTTP: Data: Number of data bytes remaining = 14 (0x000E)

응답:

HTTP: Response to Client; HTTP/1.1; Status Code = 400 - Bad Request
HTTP: Protocol Version =HTTP/1.1
HTTP: Status Code = Bad Request
HTTP: Reason =Bad Request
HTTP: Content-Type =text/html
HTTP: Date =Wed, 14 Nov 2012 20:36:36 GMT
HTTP: Connection =close
HTTP: Content-Length =44
HTTP: Data: Number of data bytes remaining = 63 (0x003F)

응답 헤더는 브라우저의 오류 메시지만큼 알려주지 않습니다. 그러나 응답 본문에서 원시 데이터를 보면 다음과 같은 내용이 표시됩니다.

00000030                                           48 54               HT
00000040 54 50 2F 31 2E 31 20 34 30 30 20 42 61 64 20 52 TP/1.1.400.Bad.R
00000050 65 71 75 65 73 74 0D 0A 43 6F 6E 74 65 6E 74 2D equest..Content-
00000060 54 79 70 65 3A 20 74 65 78 74 2F 68 74 6D 6C 0D Type:.text/html.
00000070 0A 44 61 74 65 3A 20 57 65 64 2C 20 32 38 20 4A .Date:.Wed,.28.J
00000080 61 6E 20 32 30 30 39 20 32 30 3A 33 36 3A 33 36 an.2009.20:36:36
00000090 20 47 4D 54 0D 0A 43 6F 6E 6E 65 63 74 69 6F 6E .GMT..Connection
000000A0 3A 20 63 6C 6F 73 65 0D 0A 43 6F 6E 74 65 6E 74 :.close..Content
000000B0 2D 4C 65 6E 67 74 68 3A 20 34 34 0D 0A 0D 0A 3C -Length:.44....<
000000C0 68 31 3E 42 61 64 20 52 65 71 75 65 73 74 20 28 h1>Bad.Request.(
000000D0 48 65 61 64 65 72 20 46 69 65 6C 64 20 54 6F 6F Header.Field.Too
000000E0 20 4C 6F 6E 67 29 3C 2F 68 31 3E 01 02 03 04 05 .Long).....
000000F0 05 06 0E 94 63 D6 68 37 1B 8C 16 FE 3F D5       ....c.h7....?.

브라우저에 표시되는 오류 메시지 텍스트는 네트워크 추적의 원시 응답 데이터에서도 볼 수 있습니다.

다음 단계는 C:\Windows\System32\LogFiles\HTTPERR 디렉터리에서 잘못된 요청에 해당하는 항목에 대한 httperr.log 파일을 살펴보는 것입니다.

#Software: Microsoft HTTP API 1.0
#Version: 1.0
#Date: 2012-11-14 20:35:02
#Fields: date time cs-version cs-method cs-uri sc-status s-reason 
2012-11-14 20:36:36 HTTP/1.1 GET /1234567890/time.asp 400 FieldLength

이 시나리오 Reason 에서 httperr.log 파일의 필드는 문제를 진단하는 데 필요한 정확한 정보를 제공합니다. 이 HTTP.sys 이 요청 실패의 원인 구로 기록된 FieldLength 것을 볼 수 있습니다. 이유 구를 알고 나면 HTTP API에서 섹션을 기록하는 오류 종류에서 테이블을 확인하여 설명을 가져옵니다.

FieldLength: 필드 길이 제한을 초과했습니다.

따라서 이 시점에서 브라우저 오류 메시지와 HTTP API 오류 로깅에서 요청에 허용되는 길이 제한을 초과하는 HTTP 헤더 중 하나에 데이터가 포함되어 있음을 알 수 있습니다. 이 예제에서는 HTTP: Uniform Resource Identifier header 의도적으로 긴 /1234567890123456789012345678901234567890/time.asp.

이 예제 문제 해결의 마지막 단계는 IIS에 대한 HTTP.sys 레지스트리 키 및 기본 설정을 확인하는 것입니다.

구문과 오류가 머리글 필드 길이가 제한을 초과하는 것을 제안하는 이유를 알고 있으므로 레지스트리 키 테이블에서 검색 범위를 좁힐 수 있습니다. 주요 후보는 다음과 같습니다.

레지스트리 키 Default value 유효한 값 범위 레지스트리 키 함수 경고 코드
MaxFieldLength 16384 64 - 65534(64k - 2) 바이트 각 헤더에 대한 상한을 설정합니다. MaxRequestBytes을 참조하세요. 이 제한은 URL에 대해 약 32k 문자로 변환됩니다. 1

이 예제 MaxFieldLength 에 대해 이 오류를 재현하기 위해 레지스트리 키가 값 2로 설정되었습니다. 요청된 URL에 문자가 두 개 이상 있는 HTTP: Uniform Resource Identifier header 필드가 있으므로 요청이 이유 구로 FieldLength 차단되었습니다.

또 다른 일반적인 HTTP 400 시나리오는 HTTP 요청을 만드는 사용자가 다수의 Active Directory 그룹의 구성원이며 웹 사이트가 사용자 Kerberos 인증으로 구성된 시나리오입니다. 이 시나리오가 발생하면 다음과 유사한 오류 메시지가 사용자에게 표시됩니다.

잘못된 요청(요청 헤더가 너무 깁니다.)

이 시나리오에서는 클라이언트의 HTTP 요청의 일부로 포함된 인증 토큰이 너무 커서 http.sys 적용되는 크기 제한을 초과합니다. 이 문제는 HTTP 요청에 대한 HTTP 400 - 잘못된 요청(요청 헤더가 너무 깁니다) 응답에서 솔루션과 함께 자세히 설명합니다.

참조