No se pudo crear un canal seguro SSL / TLS, a pesar de configurar ServerCertificateValidationCallback

83

Estoy intentando establecer una conexión SSL / TLS para probar el servidor con certificado autofirmado . La comunicación a través de un canal inseguro funcionó sin problemas.

Aquí está mi código de muestra, que escribí en base a estas soluciones: Permitir certificados SSL que no son de confianza con HttpClient C # ¿Ignorar los errores del certificado? Cliente .NET que se conecta a la API web ssl

ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;

var c = new HttpClient();
var r = c.GetAsync("https://10.3.0.1:8443/rest/v1").Result;
if (r.IsSuccessStatusCode)
{
    Log.AddMessage(r.Content.Get<string>());
}
else
{
    Log.AddMessage(string.Format("{0} ({1})", (int)r.StatusCode, r.ReasonPhrase));
}

también probé esto:

var handler = new WebRequestHandler();
handler.ServerCertificateValidationCallback = delegate { return true; };
var c = new HttpClient(handler);
...

y esto

ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

pero cada vez tengo una excepción:

InnerException: System.Net.Http.HttpRequestException
   _HResult=-2146233088
   _message=An error occurred while sending the request.
   HResult=-2146233088
   IsTransient=false
   Message=An error occurred while sending the request.
   InnerException: System.Net.WebException
        _HResult=-2146233079
        _message=The request was aborted: Could not create SSL/TLS secure channel.
        HResult=-2146233079
        IsTransient=false
        Message=The request was aborted: Could not create SSL/TLS secure channel.
        Source=System
        StackTrace:
             at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
             at System.Net.Http.HttpClientHandler.GetResponseCallback(IAsyncResult ar)
        InnerException: 

¿Qué hago mal? Por qué no puedo conectarme a este servidor (que tiene un certificado autofirmado no válido)

Marcin Konrad Ceglarek
fuente

Respuestas:

161

Lo está haciendo bien con ServerCertificateValidationCallback. Este no es el problema al que se enfrenta. Lo más probable es que el problema al que se enfrenta sea la versión del protocolo SSL / TLS.

Por ejemplo, si su servidor ofrece solo SSLv3 y TLSv10 y su cliente necesita TLSv12, recibirá este mensaje de error. Lo que debe hacer es asegurarse de que tanto el cliente como el servidor tengan una versión de protocolo común compatible.

Cuando necesito un cliente que pueda conectarse a tantos servidores como sea posible (en lugar de ser lo más seguro posible) utilizo esto (junto con la configuración de la devolución de llamada de validación):

  ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
Wapac
fuente
1
Tengo un problema similar. Debido al ataque POODLE nos vemos obligados a cerrar TLS 1.0 en nuestro servidor. Cuando hago esto, una aplicación de terceros deja de funcionar. Al descompilar el ensamblaje se muestra un código similar al suyo. Utiliza webclientc.SendAsync en lugar de GetAsync. Si copio el código en una aplicación de consola para probarlo, puedo reproducir el error y, al agregar ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11, funciona. Pensé que habría algún tipo de protocolo de enlace entre el servidor y el cliente para descubrir qué versión de TLS usar. ¿Por qué no elige automáticamente 1.1 cuando 1.0 está deshabilitado?
Engern
3
¡Gracias! Estuve luchando 3 horas con esto. Agregar esta línea lo hizo por mí:ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
Thomas T
1
Tenga en cuenta que la versión más reciente de .NET tiene esto habilitado de forma predeterminada, todo lo que teníamos que hacer es configurar la versión de .NET en 4.6.1
martinh_kentico
1
Significa exactamente que, válido o no, no te importa. Esa devolución de llamada le permite simplemente evitar cualquier control de seguridad en ese certificado.
Wapac
1
Gran respuesta, siento que este ServicePointManager.SecurityProtocolvalor debería ser el predeterminado. O al menos que debería haber más información directamente dentro de la excepción lanzada.
Chad
28

Hemos estado resolviendo el mismo problema hoy, y todo lo que necesita hacer es aumentar la versión en tiempo de ejecución de .NET

4.5.2 no funcionó para nosotros con el problema anterior, mientras que 4.6.1 estaba bien

Si necesita mantener la versión .NET, configure

ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
martinh_kentico
fuente
1
¿Cuál de las variantes usaste y cómo exactamente?
martinh_kentico
1
Tengo una aplicación .NET 4.5 que a partir de hoy no funcionará con un sitio SSL específico. Si cambio a 4.6.1 funciona bien, pero realmente no puedo cambiar. No estoy seguro de qué se puede hacer: |
Tsury
16

Solo como seguimiento para cualquiera que todavía se encuentre con esto, agregué las opciones ServicePointManager.SecurityProfile como se indica en la solución:

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

Y, sin embargo, seguí obteniendo el mismo error "La solicitud fue cancelada: No se pudo crear el canal seguro SSL / TLS". Estaba intentando conectarme a algunos servidores de voz más antiguos con interfaces HTTPS SOAP API (es decir, correo de voz, sistemas de telefonía IP, etc. instalados hace años). Estos solo admiten conexiones SSL3, ya que se actualizaron por última vez hace años.

Uno pensaría que incluir SSl3 en la lista de protocolos de seguridad funcionaría aquí, pero no fue así. La única forma en que podía forzar la conexión era incluir SOLO el protocolo Ssl3 y ningún otro:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;

Luego, la conexión se realiza; me parece un error, pero esto no comenzó a arrojar errores hasta hace poco en las herramientas que proporciono para estos servidores que han estado disponibles durante años.Creo que Microsoft ha comenzado a implementar cambios en el sistema que han actualizado esto. comportamiento para forzar conexiones TLS a menos que no haya otra alternativa.

De todos modos, si todavía se encuentra con esto en algunos sitios / servidores antiguos, vale la pena intentarlo.

Jeff Lindborg
fuente
1
Tenemos un módulo CUCMPowerShell para usar la API de Cisco Unified Communications AXL a través de PowerShell y su respuesta nos ayudó a solucionar este problema agregando [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Ssl3. ¡Gracias! El código completo se puede ver en Invoke-CUCMSOAPAPIFunction
Chris Magnuson
2
@Jeff: consulte el artículo vinculado. Creo que puede explicar por qué Ssl3 no funcionó y sugiere dos formas de volver a habilitar Ssl3. docs.microsoft.com/en-us/dotnet/framework/migration-guide/…
Scott
4

mueva esta línea: ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

Antes de esta línea: HttpWebRequest request = (HttpWebRequest) WebRequest.Create (uri);

Publicación original: KB4344167 actualización de seguridad rompe el código TLS

usuario2686690
fuente
1
Después de probar todo lo anterior en vano, esta fue la respuesta: ServicePointManager debe configurarse antes de crear HttpWebRequest.
Henry Rusted
1

En mi caso, TLS1_2 estaba habilitado tanto en el cliente como en el servidor, pero el servidor estaba usando MD5 mientras el cliente lo deshabilitaba. Entonces, pruebe tanto el cliente como el servidor en http://ssllabs.com o pruebe usando openssl / s_client para ver qué está sucediendo. Además, verifique el cifrado seleccionado usando Wireshark.

user960567
fuente
1

TLS 1.0 y 1.1 ahora son End of Life. Se actualizó un paquete en nuestro servidor web de Amazon y comenzamos a recibir este error.

La respuesta está arriba, pero no debería usar tlso tls11más.

Específicamente para ASP.Net, agregue esto a uno de sus métodos de inicio.

        public Startup()
        {
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12;

pero estoy seguro de que algo como esto funcionará en muchos otros casos.

Bluebaron
fuente
0

Si está utilizando un nuevo nombre de dominio, y ha hecho todo lo anterior y aún recibe el mismo error, verifique si borró la caché de DNS en su PC. Borre su DNS para obtener más detalles.

Windows® 8

Para borrar su caché de DNS si usa Windows 8, realice los siguientes pasos:

En su teclado, presione Win + X para abrir el menú WinX.

Haga clic con el botón derecho en Símbolo del sistema y seleccione Ejecutar como administrador.

Ejecute el siguiente comando:

ipconfig / flushdns

Si el comando tiene éxito, el sistema devuelve el siguiente mensaje:

La configuración de IP de Windows vació correctamente la caché de resolución de DNS.

Windows® 7

Para borrar su caché de DNS si usa Windows 7, realice los siguientes pasos:

Haga clic en Inicio.

Ingrese cmd en el cuadro de texto de búsqueda del menú Inicio.

Haga clic con el botón derecho en Símbolo del sistema y seleccione Ejecutar como administrador.

Ejecute el siguiente comando:

ipconfig / flushdns

Si el comando tiene éxito, el sistema devuelve el siguiente mensaje: La configuración de IP de Windows descargó correctamente la caché de resolución de DNS.

Michelle
fuente
ipconfig /flushdnsC ª# ?
Kiquenet
0

Me encontré con este hilo porque también tuve el error No se pudo crear un canal seguro SSL / TLS. En mi caso, estaba intentando acceder a una API REST de configuración de Siebel desde PowerShell usando Invoke-RestMethod, y ninguna de las sugerencias anteriores ayudó.

Finalmente me encontré con la causa de mi problema: el servidor con el que me estaba comunicando requería autenticación de certificado de cliente.

Para que las llamadas funcionen, tuve que proporcionar el certificado del cliente (incluida la clave privada) con el -Certificateparámetro:

$Pwd = 'certificatepassword'
$Pfx = New-Object -TypeName 'System.Security.Cryptography.X509Certificates.X509Certificate2'
$Pfx.Import('clientcert.p12', $Pwd, 'Exportable,PersistKeySet')
Invoke-RestMethod -Uri 'https://your.rest.host/api/' -Certificate $Pfx -OtherParam ...

Espero que mi experiencia pueda ayudar a alguien más que tenga mi sabor particular de este problema.

Paul
fuente