Cómo resolver "No se pudo establecer una relación de confianza para el canal seguro SSL / TLS con autoridad"

135

Realmente pensé que tenía este problema solucionado, pero solo estaba disfrazado antes.

Tengo un servicio WCF alojado en IIS 7 usando HTTPS. Cuando busco este sitio en Internet Explorer, funciona de maravilla, esto se debe a que he agregado el certificado al almacén local de la autoridad de certificación raíz.

Estoy desarrollando en 1 máquina, por lo que el cliente y el servidor son la misma máquina. El certificado está autofirmado directamente desde el complemento de administración de IIS 7.

Continuamente recibo este error ahora ...

No se pudo establecer una relación de confianza para el canal seguro SSL / TLS con autoridad.

... cuando se llama desde la consola del cliente.

Me otorgé manualmente permisos y servicios de red para el certificado, usando findprivatekeyy usando cacls.exe.

Intenté conectarme al servicio usando SOAPUI, y eso funciona, por lo que debe ser un problema en mi aplicación cliente, que es un código basado en lo que solía funcionar con http.

¿Dónde más puedo mirar? Parece que he agotado todas las posibilidades de por qué no puedo conectarme.

JL
fuente
Si tiene control sobre la creación de los certificados, no se olvide del "Nombre alternativo del sujeto". Como si pudieras poner un comodín en "* .full.domainname.com". Ver digicert.com/subject-alternative-name.htm
granadaCoder

Respuestas:

198

Como solución alternativa, puede agregar un controlador al ServicePointManager's ServerCertificateValidationCallbacken el lado del cliente:

System.Net.ServicePointManager.ServerCertificateValidationCallback +=
    (se, cert, chain, sslerror) =>
        {
            return true;
        };

pero tenga en cuenta que esta no es una buena práctica, ya que ignora por completo el certificado del servidor y le dice al administrador del punto de servicio que cualquier certificado que esté bien puede comprometer seriamente la seguridad del cliente. Puede refinar esto y hacer algunas comprobaciones personalizadas (para el nombre del certificado, hash, etc.). al menos puede evitar problemas durante el desarrollo al usar certificados de prueba.

Joachim Kerschbaumer
fuente
9
Creo que la mayoría de las configuraciones públicas usarán un certificado comprado, pero durante el desarrollo, use el código anterior dentro de las declaraciones condicionales #if. Los desarrolladores empresariales generalmente deben configurar un servidor de CA interno >> technet.microsoft.com/en-us/library/cc875810.aspx
Luke Puplett
2
Me ayudó a descubrir cómo hacer que mi llamada SSL WCF funcione con Fiddler2 para la depuración.
Roger Willcocks
2
@karank Considere colocarlo en el método Application_Start en Global.asax (consulte stackoverflow.com/a/12507094/1175419 ). Recomiendo encarecidamente utilizar una directiva de compilación #if DEBUG o algo similar como se menciona en el comentario de Luke.
Rich C
44
¡Increíble! puede usar la expresión lambda como System.Net.ServicePointManager.ServerCertificateValidationCallback + = (se, cert, chain, sslerror) => true;
Dhanuka777
Una pequeña explicación adicional se puede encontrar aquí: blog.effectivemessaging.com/2015_09_01_archive.html
granadaCoder
40

Cuando tengo este problema es porque el client.config tenía sus puntos finales como:

 https://myserver/myservice.svc 

pero el certificado esperaba

 https://myserver.mydomain.com/myservice.svc

Cambiar los puntos finales para que coincidan con el FQDN del servidor resuelve mi problema. Sé que esta no es la única causa de este problema.

Mike Cheel
fuente
Acabo de tener este problema nuevamente y esta vez tuvo que ver con el uso del certificado incorrecto. Parece que en ambos casos tiene que ver con emparejar nombres correctamente.
Mike Cheel
3
Mi configuración generada automáticamente tenía <endpoint address = " localhost / myservice.svc " cambiando esto a <endpoint address = " mymachine.mydoman.com/myservice.svc " resolvió esto.
knightscharge
Este fue absolutamente mi problema y me tomó dos días encontrar su respuesta. +1, te daría +1000 si pudiera.
AussieJoe
20

los dos primeros usan lambda, el tercero usa código regular ... espero que les sea útil

            //Trust all certificates
            System.Net.ServicePointManager.ServerCertificateValidationCallback =
                ((sender, certificate, chain, sslPolicyErrors) => true);

            // trust sender
            System.Net.ServicePointManager.ServerCertificateValidationCallback
                = ((sender, cert, chain, errors) => cert.Subject.Contains("YourServerName"));

            // validate cert by calling a function
            ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(ValidateRemoteCertificate);

    // callback used to validate the certificate in an SSL conversation
    private static bool ValidateRemoteCertificate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors policyErrors)
    {
        bool result = false;
        if (cert.Subject.ToUpper().Contains("YourServerName"))
        {
            result = true;
        }

        return result;
    }
Sebastian Castaldi
fuente
1
// Confíe en todos los certificados System.Net.ServicePointManager.ServerCertificateValidationCallback + = (se, cert, chain, sslerror) => {return true; }; // remitente de confianza System.Net.ServicePointManager.ServerCertificateValidationCallback + = (se, cert, chain, sslerror) => {return cert.Subject.Contains ("ca-l-9wfvrm1.ceridian.ca"); };
VoodooChild
1
Cualquier cracker podría falsificar un certificado que pase todas las pruebas anteriores. Esto no es seguro.
Bjartur Thorlacius
19

Su problema surge porque está utilizando una clave autofirmada. El cliente no confía en esta clave, ni la clave en sí misma proporciona una cadena para validar o una lista de revocación de certificados.

Tienes algunas opciones: puedes

  1. desactivar la validación de certificado en el cliente (movimiento incorrecto, abundan los ataques de hombre en el medio)

  2. use makecert para crear una CA raíz y crear certificados a partir de eso (movimiento correcto, pero todavía no hay CRL)

  3. cree una CA raíz interna utilizando Windows Certificate Server u otra solución PKI y luego confíe en ese certificado raíz (un poco difícil de manejar)

  4. comprar un certificado SSL de una de las CA de confianza (caro)

soplar el dardo
fuente
3
Con respecto a (4), StartSSL realmente le dará un certificado de Clase 1 gratuito que funciona en todos los principales navegadores. Funcionan muy bien para mí para mi media docena de sitios de bajo ancho de banda.
moodboom
Creo que # 2 en esta lista ... esta url podría ayudar: blogs.technet.microsoft.com/jhoward/2005/02/02/… "Cómo usar MakeCert para la autoridad de certificación raíz de confianza y la emisión de certificados SSL"
granadaCoder
1
Nota: StartCom ya no es confiable, y acaba de ser eliminado de Chrome en.wikipedia.org/wiki/StartCom
Simon_Weaver
16

Una solución de una línea. Agregue esto en cualquier lugar antes de llamar al servidor en el lado del cliente:

System.Net.ServicePointManager.ServerCertificateValidationCallback += delegate { return true; };

Esto solo debe usarse con fines de prueba porque el cliente omitirá las comprobaciones de seguridad SSL / TLS.

Gaspa79
fuente
2
Una solución alternativa brillante para las pruebas. Estamos consumiendo un servicio cuyo proveedor ha convertido la seguridad en un infierno con una cadena complicada de certificados de seguridad y hasta que podamos conseguir que sus certificaciones inestables y su encadenamiento funcionen correctamente, esta solución es lo único que nos permite continuar con el desarrollo.
markaaronky
12

Encontré el mismo problema y pude resolverlo con dos soluciones: primero, utilicé el complemento MMC "Certificados" para la "Cuenta de equipo" y arrastré el certificado autofirmado a la carpeta "Autoridades de certificación raíz de confianza" . Esto significa que la computadora local (la que generó el certificado) ahora confiará en ese certificado. En segundo lugar, noté que el certificado se generó para un nombre interno de computadora, pero se estaba accediendo al servicio web con otro nombre. Esto provocó una falta de coincidencia al validar el certificado. Generamos el certificado para computer.operations.local, pero accedimos al servicio web usando https://computer.internaldomain.companydomain.com . Cuando cambiamos la URL a la utilizada para generar el certificado, no obtuvimos más errores.

Tal vez solo cambiar las URL hubiera funcionado, pero al hacer que el certificado sea confiable, también evita la pantalla roja en Internet Explorer, donde le dice que no confía en el certificado.

Jeroen-bart Engelen
fuente
11

Si usa .net core intente esto:

client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication =
        new X509ServiceCertificateAuthentication()
        {
            CertificateValidationMode = X509CertificateValidationMode.None,
            RevocationMode = System.Security.Cryptography.X509Certificates.X509RevocationMode.NoCheck
        };
Grzegorz J
fuente
1
Gracias funciona. Pero no tiene nada que ver con .net core. Es una receta universal :)
Alexander
7

Por favor, siga los siguientes pasos:

  1. Enlace de servicio abierto en IE.

  2. Haga clic en la mención de error de certificado en la barra de direcciones y haga clic en Ver certificados.

  3. Cheque emitido a: nombre.

  4. Tome el nombre emitido y reemplace la mención localhost en el servicio y el nombre de la dirección base del punto final del cliente con un nombre de dominio completo (FQDN).

Por ejemplo: https: // localhost : 203 / SampleService.svc a https: // INL-126166-.groupinfra.com : 203 / SampleService.svc

Rahul Rai
fuente
Genial, gracias por esta respuesta! Resolvió los problemas sin hacer ningún cambio en el código.
Vipin Dubey
6

Además de las respuestas anteriores, puede encontrar este error si su cliente ejecuta una versión TLS incorrecta, por ejemplo, si el servidor solo ejecuta TLS 1.2.

Puedes arreglarlo usando:

// tested in .NET 4.5:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
NMrt
fuente
en mi caso la respuesta aceptada no me ayudó, pero esta fue una trampa
Sergey
Esta es la única respuesta que corrigió el error en mi caso.
Tolga
5

Yo tuve el mismo problema. También había agregado certificados de CA en la tienda local, pero lo hice de manera INCORRECTA.

Con la consola mmc (Inicio -> Ejecutar -> mmc ), debe agregar el complemento Certificados como cuenta de servicio (eligiendo la cuenta de servicio de IIS) o la cuenta de computadora (se agrega para cada cuenta en la máquina)

Aquí una imagen de lo que estoy hablando Agregar complemento para una cuenta de servicio o la cuenta de computadora

Desde aquí ahora, puede agregar certificados de CA ( CA raíz de confianza y CA intermedia ), y todo funcionará bien

dar0x
fuente
4

Tuve un problema similar con el certificado autofirmado. Podría resolverlo usando el nombre del certificado igual que el FQDN del servidor.

Idealmente, la parte SSL debe administrarse en el lado del servidor. No se requiere que el cliente instale ningún certificado para SSL. Además, algunas de las publicaciones mencionadas sobre eludir el SSL del código del cliente. Pero estoy totalmente en desacuerdo con eso.

Umesh Bhavsar
fuente
3

Acabo de arrastrar el certificado a la carpeta "Autoridades de certificación raíz de confianza" y listo, todo funcionó bien.

Oh. Y primero agregué lo siguiente desde un símbolo del sistema del administrador:

netsh http add urlacl url=https://+:8732/Servicename user=NT-MYNDIGHET\INTERAKTIV

No estoy seguro del nombre que necesita para el usuario (¡el mío es noruego como puede ver!) user=NT-AUTHORITY/INTERACTIVE:?

Puede ver todos los urlacl existentes emitiendo el comando: netsh http show urlacl

Haguna
fuente
0

Esto ocurrió al intentar conectarse al servicio WCF a través de. la IP, por ejemplo, https://111.11.111.1:port/MyService.svcmientras se usa un certificado vinculado a un nombre, por ejemplo, mysite.com.

Cambiando al https://mysite.com:port/MyService.svcresuelto.

lko
fuente
0

Solo solucioné un problema similar.

Me di cuenta de que tenía un grupo de aplicaciones que se ejecutaba bajo una cuenta que solo tenía permiso de lectura sobre el certificado que se usaba.

La aplicación .NET pudo recuperar correctamente el certificado, pero esa excepción se produjo solo cuando se llamó a GetRequestStream ().

Los permisos de certificados se pueden administrar a través de la consola MMC

Alberto
fuente
0

Si está utilizando .net core, durante el desarrollo puede omitir la validación de certificados mediante el uso de directivas del compilador. De esta manera solo se validará el certificado para su lanzamiento y no para la depuración:

#if (DEBUG)
        client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication =
                new X509ServiceCertificateAuthentication()
                {
                    CertificateValidationMode = X509CertificateValidationMode.None,
                    RevocationMode = System.Security.Cryptography.X509Certificates.X509RevocationMode.NoCheck
                };   #endif
Panayiotis Hiripis
fuente
-6

Agregue esto a su código de cliente:

ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(
    delegate
    {
        return true;
    });
usuario662285
fuente
44
Esta respuesta no es muy buena, ya que no explica los riesgos asociados con el código.
DaveD