"Temel bağlantı kapatıldı: Göndermede beklenmeyen bir hata oluştu." SSL Sertifikası ile


120

Sorun: Günlüklerimde "ANA BAĞLANTI KAPATILDI: BİR GÖNDERİMDE BEKLENMEYEN BİR HATA OLUŞTURULDU" şeklinde bir istisna alıyorum ve [1 saat - 4 saat] arasında değişen rastgele zamanlarda OEM entegrasyonumuzu e-posta pazarlama sistemimizle bozuyor

Web sitem, IIS 7.5.7600 ile bir Windows sunucusu 2008 R2'de barındırılıyor. Bu web sitesinde çok sayıda OEM bileşeni ve kapsamlı bir kontrol paneli vardır. Kontrol panelimizde iframe çözümü olarak kullandığımız e-posta pazarlama bileşenimizden biri dışında her şey web sitesinin diğer tüm öğeleriyle iyi çalışıyor. İşleyiş şekli, tüm kimlik bilgileriyle birlikte bir httpWebRequestobject gönderiyorum ve bir iframe'e koyduğum bir url geri alıyorum ve çalışıyor. Ancak yalnızca belirli bir süre [1 saat - 4 saat] çalışır ve ardından aşağıdaki istisnayı alıyorum: "ANA BAĞLANTI KAPATILDI: BİR GÖNDERİMDE BEKLENMEYEN BİR HATA OLUŞTU" ve sistem URL'yi httpWebRequest'ten almaya çalışsa bile aynı istisna ile başarısız olur. Tekrar çalışmasını sağlamanın tek yolu uygulama havuzunu geri dönüştürmektir veya herhangi bir şey web.config dosyasında düzenlenir.

Seçenek denendi

Açıkça eklendi, keep-alive = false

keep-alive = true

Zaman aşımını artırdı: <httpRuntime maxRequestLength="2097151" executionTimeout="9999999" enable="true" requestValidationMode="2.0" />

Üretim sunucumuzdaki SSL sertifikasının bağlantı kurup kurmadığını kontrol etmek için bu sayfayı SSL olmayan bir web sitesine yükledim.

Çözüme yönelik herhangi bir yön büyük beğeni topluyor.

Kod:

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`

Bunu hiç çözdün mü?
Brett G

12
evet, ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls veya SecurityProtocolType.Ssl3
Arvind Morwal

Ben de aynı sorun yüzünden ölmek üzereydim. Aynı sorunla uğraşmak birkaç saatimi aldı. Yorumlarınız için teşekkürler, günümü kurtardı.
Sameers

2
@ user3458212 yorumunuzu cevap olarak eklemelisiniz
icc97

2
Benim durumumda, web sitesini Visual Studio 15'te çalıştırmak her şey yolunda gidiyor, ancak sonunda, sunucudaki çerçeveyi yükseltemediğim için ve TLS 1.2'yi zorlamak ve canlı tutmayı devre dışı bırakmak işe yaramıyor, bir orta seviye kurmak zorunda kaldım Bağlantıyı kesen hedef web sunucusunu proxy yapmak için web sunucusu.
José Roberto García Chico

Yanıtlar:


194

Benim için tls12 idi:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

42
Dikkatli olmanız gerektiğini unutmayın çünkü bu değişiklik AppDomain için geneldir ve TLS 1.2'yi sunmayan herhangi bir siteye yapılan çağrıların başarısız olmasına neden olacaktır (taşınacak veriler gerçekten hassas ise tercih edebilirsiniz). TLS 1.2'yi tercih etmek, ancak yine de 1.1 ve 1.0'a izin vermek için, bunları VEYA şunları yapmanız gerekir:ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
Dusty

aynısı burada, hayatımı kurtardın, RestSharp'ta neyin yanlış olduğunu anlamak için çok zaman harcadın
darul75

Bu çözüm, RestSharp kullanmayanların yanı sıra ServicePointManager kullanmayanlar için de işe yarar. WebRequest çağrınızdan önce veya istekte bulunmak için kullandığınız her şeyi kopyalayıp yapıştırmanız yeterlidir. Yukarıdaki nedenlerden dolayı başlangıçta bu çözümü görmezden geldim.
goku_da_master

ya da zaten orada olana ekleyin ... System.Net.ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12;
uosjead

8
Bunu PowerShell'de yapmak için, "ikili veya" birlikte "şu şekilde:[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls
Adam S

64

Net 4.0 ile takıldıysanız ve hedef site TLS 1.2 kullanıyorsa, bunun yerine aşağıdaki satırı kullanmanız gerekir. ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;

kaynak: TLS 1.2 ve .NET Desteği: Bağlantı Hatalarını Önleme


5
Müthiş! Ben sadece (SecurityProtocolType)768"Tls11" (yani TLS 1.1) için kullanılabileceğini ekleyeceğim .
Solomon Rutzky

2
Bu gerçekten yardımcı oluyor. Günümü kurtardı. .Net 2.0'a bağlı kalmalıyım.
Hao Nguyen

24

Aşağıdaki kod sorunu çözdü

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls Or SecurityProtocolType.Ssl3

6
Bu işe yarayabilir, ancak ServicePointManager.SecurityProtocolbunun statik bir nesne olduğunu ve bu değerin değiştirilmesinin tüm alt dizileri WebRequestveya WebClientçağrıları etkileyeceği anlamına geldiğini unutmayın . Farklı ayarlara sahip AppDomainolmak istiyorsanız ServicePointManager, ayrı oluşturabilirsiniz . Daha fazla ayrıntı için stackoverflow.com/questions/3791629/… adresini ziyaret edin.
stack247

1
Bu kodun ne yaptığını anlamak için yararlı ek okumalar: stackoverflow.com/questions/26389899/…
Jon Schneider

@Marnee Onu uygulamamın kompozisyon köküne koydum, böylece meydana gelen herhangi bir G / Ç'den önce ayarlandı
JG,

@Marnee Bunu statik bir kurucuya koyun, böylece sınıfa ilk erişildiğinde tam olarak bir kez çalıştırılır. Yine de tüm durumları kapsayacak şekilde tüm protokolleri etkinleştirmem gerekiyordu.
Nyerguds 01

14

Günlerdir aynı sorunu, sadece "eskiden çalışıyordu" olan bir entegrasyonla yaşıyorum.

Tamamen depresyondan, sadece denedim

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

Bu benim için sorunu çözdü ... Entegrasyon kesinlikle sadece SSLv3 kullanıyor olsa da.

Fiddler'ın "boş bir TLS müzakere şifresi" veya benzeri bir şey olduğunu söylediğinden beri bir şeyin yanlış olduğunu fark ettim.

Umarım işe yarar!


Kodunuzun TLS'ye ihtiyacı olmasa bile, DOES ile iletişim kurduğu sunucu TLS ile pazarlık etmeye çalışacak ve yapamazsa başarısız olacaktır. Boş TLS görüşme şifresi, sonunda sağladığınız TLS protokol değişimini bekleyen yuvaydı. Sunucu yöneticisi büyük olasılıkla uygulamanızın iletişim kurduğu sunucuda TLS'yi kısa süre önce etkinleştirdiği için "eskiden çalışıyordu".
vapcguy

13

Benim durumumda, bağlandığım site TLS 1.2'ye yükseltildi. Sonuç olarak, desteklemek için web sunucuma .net 4.5.2 kurmam gerekti.


Bu, makinede kayıt düzeyinde yapılabilir mi? TLS 1.0, 1.1, 1.2'yi bırakarak tüm SSL protokollerini devre dışı bıraktım, ancak anladığım kadarıyla, PCI uyumlu olmak için TLS 1.2'den daha azının yakında kaldırılması gerekiyor.
brendo234

13

Hangi .net çalışma zamanını kullandığınızı doğrulamak için web.config / App.config dosyanıza gidin

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

İşte çözüm:

  1. .NET 4.6 ve üzeri. TLS 1.2'yi desteklemek için herhangi bir ek iş yapmanız gerekmez, varsayılan olarak desteklenir.

  2. .NET 4.5. TLS 1.2 desteklenir, ancak bu varsayılan bir protokol değildir. Kullanmak için kaydolmanız gerekir. Aşağıdaki kod TLS 1.2'yi varsayılan yapacaktır, güvenli kaynağa bağlantı yapmadan önce onu çalıştırdığınızdan emin olun:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12

  1. .NET 4.0. TLS 1.2 desteklenmez, ancak sistemde .NET 4.5 (veya üstü) kuruluysa, uygulama çerçeveniz desteklemese bile TLS 1.2'yi tercih edebilirsiniz. Tek sorun, .NET 4.0'daki SecurityProtocolType'ın TLS1.2 için bir girişe sahip olmamasıdır, bu nedenle bu enum değerinin sayısal bir temsilini kullanmamız gerekir:

ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;

  1. .NET 3.5 veya altı. TLS 1.2 desteklenmez (*) ve geçici bir çözüm yoktur. Uygulamanızı çerçevenin daha yeni sürümüne yükseltin.

6

Bunun, kodu dağıttığınız sunucuda TLS 1.1 veya TLS 1.2'yi desteklemeyen eski bir .NET çerçevesinin yüklü olduğuna dair bir işaret olduğunu buldum. Düzeltilecek adımlar:

  1. Üretim sunucularınıza (IIS ve SQL) en son .NET Runtime'ı yükleme
  2. Geliştirme makinelerinize en son .NET Geliştirici Paketini yükleme .
  3. Visual Studio projelerinizdeki "Hedef çerçeve" ayarlarını en son .NET çerçevesiyle değiştirin.

En son .NET Developer Pack ve Runtime'ı şu URL'den edinebilirsiniz: http://getdotnet.azurewebsites.net/target-dotnet-platforms.html


Hedef çerçeve 4.5.2'den 4.6.1'e değiştirildi ve çalışmaya başladı, teşekkürler Patrick.
Vivek Sharma

4

API'mıza erişen bir web sitesinin "Temel bağlantı kapatıldı: Göndermede beklenmeyen bir hata oluştu" şeklinde bir sorunla karşılaştık. İleti.

Kodları .NET 3.x ve 2.2'nin bir karışımıydı, bu da anladığım kadarıyla TLS 1.0 kullandıkları anlamına geliyor.

Aşağıdaki cevap, TLS 1.0, SSL 2 ve SSL3'ü etkinleştirerek sorunu teşhis etmenize yardımcı olabilir, ancak çok açık olmak gerekirse, bu üç protokolün de güvensiz olarak görülmesi ve artık olmaması gerektiği için uzun vadede bunu yapmak istemezsiniz. kullanılmış :

IIS'imizin API çağrılarına yanıt vermesini sağlamak için, TLS sürümlerini açıkça etkinleştirmek için IIS sunucusuna kayıt defteri ayarlarını eklememiz gerekiyordu - NOT: Bu değişiklikleri yaptıktan sonra Windows sunucusunu (yalnızca IIS hizmetini değil) yeniden başlatmanız gerekir:

[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

Bu işe yaramazsa, SSL 2.0 girişini eklemeyi de deneyebilirsiniz:

[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

Açık olmak gerekirse, bu iyi bir çözüm değildir ve doğru çözüm arayanın TLS 1.2'yi kullanmasını sağlamaktır, ancak yukarıdakiler sorunun bu olduğunu teşhis etmeye yardımcı olabilir.

Bu powershell betiği ile bu reg girişlerini eklemeyi hızlandırabilirsiniz:

$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

Bu , VMM için TLS'yi Ayarlama için Microsoft yardım sayfasındaki komut dosyasının değiştirilmiş bir sürümüdür . Bu basics.net makalesi , başlangıçta bana bu ayarlara bakma fikrini veren sayfaydı .


Sorunumuz, sizin için canlı sunucunuz için sertifikayı değiştirdiğimizde aniden duran Team City aracılığıyla bir yayın hattıyla ilgiliydi. Sunucuyu yalnızca TLS1.2 kullanacak şekilde değiştirmiştik ve Team City ardışık düzenimiz çalışmayı durdurdu ... Bir rüya gibi çalıştı ... reg girişlerini ekledi ve sunucuyu yeniden başlattı ... BOOM !!! Teşekkürler tomRedox !!
Gwasshoppa

@Gwasshoppa, sadece yukarıdakilerin sorunu teşhis etmek için sadece geçici bir nokta olduğunu tekrarlamak için. Artık bunun bir TLS sürümü sorunu olduğunu biliyorsunuz, çözüm, sürüm ardışık düzenini TLS1.2 ile çalışacak şekilde değiştirip ardından TLS <1.2 ve SSL 2 ve 3'ü tekrar kapatmaktır. Bunu da vurgulamak için yukarıdaki cevabı biraz güncelledim.
tomRedox

4

Sadece ekle:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;


1
Lütfen cevabınızla birlikte bir açıklama yapınız.
Kelime Yeniden

4
Bu cevap da öncekilere hiçbir şey eklemiyor.
Arvindh Mani

2

Birine yardımcı oluyorsa, bizimki eksik sertifika ile ilgili bir sorundu. Ortam, .Net 4.6 ile Windows Server 2016 Standardıdır.

Service.Open () öğesinin hatasız olarak yürütüleceği, kendi kendine barındırılan bir WCF hizmeti https URI'si vardır. Hizmetin kullanılabilir olduğundan emin olmak için başka bir iş parçacığı https: // OurIp: 443 / OurService? Wsdl'ye erişmeye devam edecektir . WSDL'ye erişim, aşağıdakilerle başarısız oluyordu:

Temeldeki bağlantı kapatıldı: Göndermede beklenmeyen bir hata oluştu.

ServicePointManager.SecurityProtocol'u uygulanabilir ayarlarla kullanmak işe yaramadı. Sunucu rolleri ve özellikleriyle oynamak da yardımcı olmadı. Daha sonra SE, Jaise George'a adım atarak sorunu birkaç dakika içinde çözdü. Jaise , sorunu ortadan kaldıran IIS'ye kendinden imzalı bir sertifika yükledi. Sorunu çözmek için yaptığı şey buydu:

(1) IIS yöneticisini açın (inetmgr) (2) Sol paneldeki sunucu düğümüne tıklayın ve "Sunucu sertifikaları" na çift tıklayın. (3) Sağ paneldeki "Kendinden İmzalı Sertifika Oluştur" u tıklayın ve kolay ad için istediğiniz herhangi bir şeyi yazın. (4) Sol panelde "Varsayılan Web sitesi" üzerine tıklayın, sağ panelde "Bağlantılar" a tıklayın, "Ekle" ye tıklayın, "https" yi seçin, yeni oluşturduğunuz sertifikayı seçin ve "Tamam" a tıklayın (5) Erişim https URL, erişilebilir olmalıdır.


Yine de, sunucu yöneticisinin SSL sertifikasını ekleyeceğini düşünürdünüz! D'oh! lol :) Yine de bunun olduğunu görebiliyorum - veya yenilenmesi gereken süresi dolmuş bir sertifika muhtemelen daha uygulanabilir bir senaryo olacaktır.
vapcguy

2

Yalnızca uygulama sürümünüzü 4.0 gibi 4.6 olarak değiştirir ve bu kodu yayınlarsınız.

Ayrıca aşağıdaki kod satırlarını ekleyin:

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

1

HTTP hata ayıklama proxy'si kullanmak buna neden olabilir - Fiddler gibi.

Yerel bir dosyadan (Apple.com'a kimlik doğrulama) bir PFX sertifikası yüklüyordum ve Fiddler bu sertifikayı geçemediği için başarısız oldu.

Kontrol etmek için Fiddler'ı devre dışı bırakmayı deneyin ve çözüm buysa, muhtemelen sertifikayı makinenize veya Fiddler'ın kullanabileceği bir şekilde yüklemeniz gerekir.


0

Aşağıdaki kod sorunumu çözdü:

request.ProtocolVersion = HttpVersion.Version10; // THIS DOES THE TRICK
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.