"기본 연결이 닫혔습니다. 전송시 예기치 않은 오류가 발생했습니다." SSL 인증서 사용


119

문제 : 내 로그에 "기본 연결이 닫혔습니다 : 전송시 예상치 못한 오류가 발생했습니다"라는 예외가 발생하고 [1 시간-4 시간]에서 임의의 시간에 OEM과 이메일 마케팅 시스템의 통합이 중단됩니다.

내 웹 사이트는 IIS 7.5.7600이 설치된 Windows Server 2008 R2에서 호스팅됩니다. 이 웹 사이트에는 많은 OEM 구성 요소와 포괄적 인 대시 보드가 있습니다. 대시 보드 내에서 iframe 솔루션으로 사용하는 이메일 마케팅 구성 요소 중 하나를 제외하고는 웹 사이트의 다른 모든 요소와 잘 작동합니다. 작동 방식은 모든 자격 증명과 함께 httpWebRequestobject를 보내고 iframe에 넣은 URL을 다시 얻습니다. 하지만 일정 시간 [1 시간-4 시간] 동안 만 작동하고 "기본 연결이 닫혔습니다 : 전송시 예기치 않은 오류가 발생했습니다"라는 예외가 발생하고 시스템이 httpWebRequest에서 URL을 가져 오려고 시도하더라도 동일한 예외로 실패합니다. 다시 작동하도록 만드는 유일한 방법은 응용 프로그램 풀을 재활용하는 것입니다. 그렇지 않으면 web.config에서 편집 할 수 있습니다.

시도한 옵션

명시 적으로 추가됨, keep-alive = false

keep-alive = true

시간 초과 증가 : <httpRuntime maxRequestLength="2097151" executionTimeout="9999999" enable="true" requestValidationMode="2.0" />

이 페이지를 SSL이 아닌 웹 사이트에 업로드하여 프로덕션 서버의 SSL 인증서가 연결을 끊고 있는지 확인했습니다.

해상도를 향한 모든 방향은 대단히 감사합니다.

코드 :

Public Function CreateHttpRequestJson(ByVal url) As String
    Try
        Dim result As String = String.Empty
        Dim httpWebRequest = DirectCast(WebRequest.Create("https://api.xxxxxxxxxxx.com/api/v3/externalsession.json"), HttpWebRequest)
        httpWebRequest.ContentType = "text/json"
        httpWebRequest.Method = "PUT"
        httpWebRequest.ContentType = "application/x-www-form-urlencoded"
        httpWebRequest.KeepAlive = False
        'ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3

        'TODO change the integratorID to the serviceproviders account Id, useremail 
        Using streamWriter = New StreamWriter(httpWebRequest.GetRequestStream())
            Dim json As String = New JavaScriptSerializer().Serialize(New With { _
            Key .Email = useremail, _
            Key .Chrome = "None", _
            Key .Url = url, _
            Key .IntegratorID = userIntegratorID, _
            Key .ClientID = clientIdGlobal _
            })

            'TODO move it to the web.config, Following API Key is holonis accounts API Key
            SetBasicAuthHeader(httpWebRequest, holonisApiKey, "")
            streamWriter.Write(json)
            streamWriter.Flush()
            streamWriter.Close()

            Dim httpResponse = DirectCast(httpWebRequest.GetResponse(), HttpWebResponse)
            Using streamReader = New StreamReader(httpResponse.GetResponseStream())
                result = streamReader.ReadToEnd()
                result = result.Split(New [Char]() {":"})(2)
                result = "https:" & result.Substring(0, result.Length - 2)
            End Using
        End Using
        Me.midFrame.Attributes("src") = result
    Catch ex As Exception
        objLog.WriteLog("Error:" & ex.Message)
        If (ex.Message.ToString().Contains("Invalid Email")) Then
            'TODO Show message on UI
        ElseIf (ex.Message.ToString().Contains("Email Taken")) Then
            'TODO Show message on UI
        ElseIf (ex.Message.ToString().Contains("Invalid Access Level")) Then
            'TODO Show message on UI
        ElseIf (ex.Message.ToString().Contains("Unsafe Password")) Then
            'TODO Show message on UI
        ElseIf (ex.Message.ToString().Contains("Invalid Password")) Then
            'TODO Show message on UI
        ElseIf (ex.Message.ToString().Contains("Empty Person Name")) Then
            'TODO Show message on UI
        End If
    End Try
End Function


Public Sub SetBasicAuthHeader(ByVal request As WebRequest, ByVal userName As [String], ByVal userPassword As [String])
    Dim authInfo As String = Convert.ToString(userName) & ":" & Convert.ToString(userPassword)
    authInfo = Convert.ToBase64String(Encoding.[Default].GetBytes(authInfo))
    request.Headers("Authorization") = "Basic " & authInfo
End Sub`

이걸 알아 냈어?
Brett G

11
예 나는이 코드 ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls 또는 SecurityProtocolType.Ssl3 작업을 얻을 수 있었다
아빈 Morwal

나는 같은 문제로 죽을 참이었다. 같은 문제로 고생하는 데 몇 시간이 걸렸습니다. 의견을 보내 주셔서 감사합니다.
Sameers Javed 2015-04-23

2
@ user3458212 당신은 대답으로 당신의 코멘트를 추가해야합니다
icc97

2
필자의 경우 Visual Studio 15에서 웹 사이트를 실행하면 모든 것이 잘되지만 결국에는 서버에서 프레임 워크를 업그레이드 할 수없고 TLS 1.2를 강제 실행하고 연결 유지를 비활성화하는 것이 작동하지 않기 때문에 중간을 설정해야했습니다. 연결을 끊는 대상 웹 서버를 프록시하는 웹 서버.
José Roberto García Chico

답변:


193

나를 위해 그것은 tls12였습니다.

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

42
이 변경은 AppDomain에 전역 적으로 적용되며 TLS 1.2를 제공하지 않는 모든 사이트에 대한 호출이 실패하게되므로주의해야합니다 (전송할 데이터가 정말 민감한 경우 선호 할 수 있음). TLS 1.2를 선호하지만 여전히 1.1과 1.0을 허용하려면 OR을 수행해야합니다.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
Dusty

여기에 같은, 당신은 내 인생, RestSharp와 무엇이 잘못된 것인지 알아 내기 위해 너무 많은 시간을 보냈다 저장
darul75

이 솔루션은 RestSharp를 사용하지 않는 사용자와 ServicePointManager를 사용하지 않는 사용자에게도 적용됩니다. WebRequest 호출 전에 위의 줄을 복사하여 붙여 넣거나 요청하는 데 사용하는 모든 것을 붙여 넣으십시오. 위의 이유 때문에 처음에는이 솔루션을 무시했습니다.
goku_da_master

아니면 그냥 ... 이미 무엇에 추가 System.Net.ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12;
uosjead

8
PowerShell에서이 작업을 수행하려면 다음과 같이 "이진 또는"함께 사용하십시오.[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls
Adam S

62

.Net 4.0을 사용하고 있고 대상 사이트가 TLS 1.2를 사용하는 경우 다음 줄이 대신 필요합니다. ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;

출처 : TLS 1.2 및 .NET 지원 : 연결 오류를 방지하는 방법


5
대박! (SecurityProtocolType)768"Tls11"(즉, TLS 1.1)에 사용할 수있는 것을 추가합니다 .
Solomon Rutzky

2
이것은 정말 도움이됩니다. 그것은 내 하루를 구했습니다. .Net 2.0을 고수해야합니다.
Hao Nguyen

22

아래 코드로 문제가 해결되었습니다.

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls Or SecurityProtocolType.Ssl3

5
그러나 이것은 작동하지만 ServicePointManager.SecurityProtocol이 값을 변경하면 모든 하위 시퀀스 WebRequest또는 WebClient호출에 영향을주는 정적 개체라는 점을 명심하십시오 . 다른 설정 AppDomain을 원하면 별도로 만들 수 있습니다 ServicePointManager. 자세한 내용은 stackoverflow.com/questions/3791629/… 을 참조하십시오.
stack247

1
유용한 추가 독서는이 코드가 무엇을하고 있는지 이해하기 : stackoverflow.com/questions/26389899/...
존 슈나이더

@Marnee 나는 그것을 내 애플리케이션의 컴포지션 루트에 넣었으므로 I / O가 발생하기 전에 설정됩니다.
JG in SD

@Marnee 정적 생성자에 넣으면 클래스가 처음 액세스 될 때 정확히 한 번 실행됩니다. 하지만 모든 경우를 다루기 위해 모든 프로토콜을 활성화해야했습니다.
Nyerguds

14

나는 "이전에 일했던"통합과 함께 며칠 동안 같은 문제를 겪어왔다.

순수한 우울증에서 난 그냥

 ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Ssl3;

이것은 통합이 엄격하게 SSLv3만을 사용하더라도 나를 위해 그것을 해결했습니다.

나는 Fiddler가 "빈 TLS 협상 암호"또는 이와 유사한 것이 있다고보고 한 이후로 뭔가 꺼져 있으면 뭔가를 깨달았습니다.

잘하면 작동합니다!


코드에 TLS가 필요하지 않더라도 통신중인 서버가 DOES를 사용하면 TLS와 협상을 시도하고 그렇지 않으면 실패합니다. 빈 TLS 협상 암호는 결국 제공 한 TLS 프로토콜 교환을 예상하는 슬롯이었습니다. 서버 관리자가 응용 프로그램이 통신하는 서버에서 TLS를 활성화했을 가능성이 높기 때문에 "이전 작업에 사용 된"것 같습니다.
vapcguy

13

제 경우에는 연결하려는 사이트가 TLS 1.2로 업그레이드되었습니다. 결과적으로 나는 그것을 지원하기 위해 웹 서버에 .net 4.5.2를 설치해야했다.


머신의 레지스트리 수준에서이 작업을 수행 할 수 있습니까? TLS 1.0, 1.1, 1.2는 그대로두고 모든 SSL 프로토콜을 비활성화했지만 PCI를 준수하려면 TLS 1.2 미만은 곧 제거해야한다는 것을 이해하고 있습니다.
brendo234

13

web.config / App.config로 이동하여 사용중인 .net 런타임을 확인하십시오.

  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
  </startup>

해결책은 다음과 같습니다.

  1. .NET 4.6 이상. TLS 1.2를 지원하기 위해 추가 작업을 수행 할 필요가 없으며 기본적으로 지원됩니다.

  2. .NET 4.5. TLS 1.2가 지원되지만 기본 프로토콜은 아닙니다. 사용하려면 선택해야합니다. 다음 코드는 TLS 1.2를 기본값으로 설정하고 보안 리소스에 연결하기 전에 실행해야합니다.

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12

  1. .NET 4.0. TLS 1.2는 지원되지 않지만 시스템에 .NET 4.5 (또는 그 이상)가 설치되어있는 경우 애플리케이션 프레임 워크에서 지원하지 않더라도 TLS 1.2를 선택할 수 있습니다. 유일한 문제는 .NET 4.0의 SecurityProtocolType에 TLS1.2에 대한 항목이 없기 때문에이 열거 형 값의 숫자 표현을 사용해야한다는 것입니다.

ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;

  1. .NET 3.5 이하. TLS 1.2는 지원되지 않으며 (*) 해결 방법이 없습니다. 애플리케이션을 최신 버전의 프레임 워크로 업그레이드합니다.

6

이것이 코드를 배포하는 서버에 TLS 1.1 또는 TLS 1.2를 지원하지 않는 오래된 .NET 프레임 워크가 설치되어 있다는 신호라는 것을 발견했습니다. 해결 단계 :

  1. 최신 .NET 런타임 설치프로덕션 서버 (IIS 및 SQL)에
  2. 개발 컴퓨터에 최신 .NET 개발자 팩 을 설치합니다 .
  3. Visual Studio 프로젝트의 "대상 프레임 워크"설정을 최신 .NET 프레임 워크로 변경합니다.

다음 URL에서 최신 .NET 개발자 팩 및 런타임을 얻을 수 있습니다. http://getdotnet.azurewebsites.net/target-dotnet-platforms.html


대상 프레임 워크를 4.5.2에서 4.6.1로 변경하고 작업을 시작했습니다. Patrick에게 감사합니다.
Vivek Sharma

4

API에 액세스하는 웹 사이트에 "기본 연결이 닫혔습니다. 전송시 예기치 않은 오류가 발생했습니다."라는 문제가 발생했습니다. 메시지.

그들의 코드는 .NET 3.x와 2.2가 혼합되어 있었는데, 내가 이해하기로는 TLS 1.0을 사용하고 있음을 의미합니다.

아래 답변은 TLS 1.0, SSL 2 및 SSL3을 활성화하여 문제를 진단하는 데 도움이 될 수 있지만, 세 가지 프로토콜 모두가 안전하지 않은 것으로 간주되어 더 이상 안전하지 않아야 하므로 장기적으로 수행하고 싶지는 않습니다. 사용 :

IIS가 API 호출에 응답하도록하려면 IIS 서버에 레지스트리 설정을 추가하여 TLS 버전을 명시 적으로 활성화해야했습니다. 참고 : 다음과 같이 변경 한 후에는 Windows 서버 (IIS 서비스뿐만 아니라)를 다시 시작해야합니다.

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS
1.0\Client] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS
1.0\Server] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS
1.1\Client] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS
1.1\Server] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS
1.2\Client] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS
1.2\Server] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001

그렇지 않은 경우 SSL 2.0 항목을 추가해 볼 수도 있습니다.

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0\Client]
"DisabledByDefault"=dword:00000000
"Enabled"=dword:00000001

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0\Server]
"DisabledByDefault"=dword:00000000
"Enabled"=dword:00000001

분명히 이것은 좋은 해결책이 아니며 올바른 해결책은 발신자가 TLS 1.2를 사용하도록하는 것이지만 위의 방법은 이것이 문제임을 진단하는 데 도움이 될 수 있습니다.

이 powershell 스크립트를 사용하여 해당 reg 항목을 빠르게 추가 할 수 있습니다.

$ProtocolList       = @("SSL 2.0","SSL 3.0","TLS 1.0", "TLS 1.1", "TLS 1.2")
$ProtocolSubKeyList = @("Client", "Server")
$DisabledByDefault = "DisabledByDefault"
$Enabled = "Enabled"
$registryPath = "HKLM:\\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\"

foreach($Protocol in $ProtocolList)
{
    Write-Host " In 1st For loop"
        foreach($key in $ProtocolSubKeyList)
        {         
            $currentRegPath = $registryPath + $Protocol + "\" + $key
            Write-Host " Current Registry Path $currentRegPath"
            if(!(Test-Path $currentRegPath))
            {
                Write-Host "creating the registry"
                    New-Item -Path $currentRegPath -Force | out-Null             
            }
            Write-Host "Adding protocol"
                New-ItemProperty -Path $currentRegPath -Name $DisabledByDefault -Value "0" -PropertyType DWORD -Force | Out-Null
                New-ItemProperty -Path $currentRegPath -Name $Enabled -Value "1" -PropertyType DWORD -Force | Out-Null    
    }
}
 
Exit 0

VMM 용 TLS 설정에 대한 Microsoft 도움말 페이지의 수정 된 버전의 스크립트입니다 . 이 basics.net 기사 는 원래 이러한 설정을 살펴볼 수있는 아이디어를 제공 한 페이지였습니다.


우리의 문제는 라이브 서버의 인증서를 변경했을 때 갑자기 중단 된 Team City를 통한 릴리스 파이프 라인에 관한 것이 었습니다. 우리는 이미 TLS1.2 만 사용하도록 서버를 변경했고 Team City 파이프 라인이 작동을 멈췄습니다 ... 꿈처럼 작동했습니다 ... reg 항목을 추가하고 서버를 다시 시작했습니다 ... BOOM !!! 감사합니다 tomRedox !!
Gwasshoppa

@Gwasshoppa, 위의 내용은 문제를 진단하기위한 임시 방편 일뿐입니다. 이제 TLS 버전 문제라는 것을 알았습니다. 해결책은 TLS1.2에서 작동 할 수 있도록 릴리스 파이프 라인을 변경 한 다음 TLS <1.2 및 SSL 2 및 3을 다시 끄는 것입니다. 나는 그것을 강조하기 위해 위의 답변을 약간 업데이트했습니다.
tomRedox

4

다음을 추가하십시오.

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;


1
답변과 함께 설명을 입력하십시오.
Word

4
이 답변은 이전 답변에도 아무것도 추가하지 않습니다.
Arvindh Mani

2

누군가를 돕는다면 우리는 인증서 누락 문제였습니다. 환경은 .Net 4.6이 포함 된 Windows Server 2016 Standard입니다.

Service.Open ()이 오류없이 실행되는 자체 호스팅 WCF 서비스 https URI가 있습니다. 다른 스레드가 https : // OurIp : 443 / OurService? wsdl에 계속 액세스합니다 . 에 하여 서비스를 사용할 수 있는지 확인합니다. 실패하는 데 사용 된 WSDL 액세스 :

기본 연결이 닫혔습니다. 전송시 예기치 않은 오류가 발생했습니다.

사용 ServicePointManager.SecurityProtocol을 적용 설정은 작동하지 않았다. 서버 역할과 기능을 가지고 노는 것도 도움이되지 않았습니다. 그런 다음 SE 인 Jaise George방문 하여 몇 분 안에 문제를 해결했습니다. Jaise 는 IIS에 자체 서명 된 인증서를 설치하여 문제를 해결했습니다. 이 문제를 해결하기 위해 그가 한 일입니다.

(1) IIS 관리자 (inetmgr)를 엽니 다. (2) 왼쪽 패널에서 서버 노드를 클릭하고 "서버 인증서"를 두 번 클릭합니다. (3) 오른쪽 패널에서 "자체 서명 된 인증서 만들기"를 클릭하고 친숙한 이름으로 원하는 것을 입력합니다. (4) 왼쪽 패널에서 "기본 웹 사이트"를 클릭하고 오른쪽 패널에서 "바인딩"을 클릭 한 다음 "추가"를 클릭하고 "https"를 선택하고 방금 만든 인증서를 선택한 다음 "확인"을 클릭합니다. (5) 액세스 https URL에 액세스 할 수 있어야합니다.


하지만 서버 관리자가 SSL 인증서를 추가했을 것이라고 생각했을 것입니다! 오! 롤 :) 나는 이것이 일어나는 것을 볼 수 있습니다-또는 갱신이 필요한 만료 된 인증서가 더 적용 가능한 시나리오 일 것입니다.
vapcguy

2

4.0에서 4.6으로 애플리케이션 버전을 변경하고 해당 코드를 게시하기 만하면됩니다.

또한 아래 코드 줄을 추가하십시오.

httpRequest.ProtocolVersion = HttpVersion.Version10; 
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;

1

HTTP 디버깅 프록시를 사용하면 Fiddler와 같은 문제가 발생할 수 있습니다.

로컬 파일 (Apple.com에 대한 인증)에서 PFX 인증서를로드했는데 Fiddler가이 인증서를 전달할 수 없어서 실패했습니다.

Fiddler를 비활성화하여 확인하고 이것이 해결책인지 확인하려면 컴퓨터에 인증서를 설치하거나 Fiddler에서 사용할 수있는 방식으로 인증서를 설치해야합니다.


0

아래 코드는 내 문제를 해결했습니다.

request.ProtocolVersion = HttpVersion.Version10; // THIS DOES THE TRICK
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.