Como resolver "Não foi possível estabelecer uma relação de confiança para o canal seguro SSL / TLS com autoridade"

135

Realmente pensei que eu tinha esse problema corrigido, mas só estava disfarçado antes.

Eu tenho um serviço WCF hospedado no IIS 7 usando HTTPS. Quando eu vá para este site no Internet Explorer, ele funciona como um encanto, é porque eu ter adicionado o certificado para a loja local da autoridade de certificação raiz.

Estou desenvolvendo em uma máquina, então cliente e servidor são a mesma máquina. O certificado é autoassinado diretamente do snap-in de gerenciamento do IIS 7.

Eu recebo esse erro continuamente agora ...

Não foi possível estabelecer relação de confiança para o canal seguro SSL / TLS com autoridade.

... quando chamado do console do cliente.

Eu me dei manualmente permissões e serviço de rede ao certificado, usando findprivatekeye usando cacls.exe.

Tentei me conectar ao serviço usando SOAPUI, e isso funciona, por isso deve ser um problema no meu aplicativo cliente, que é um código baseado no que costumava funcionar com http.

Onde mais posso procurar? Parece que esgotou todas as possibilidades de por que não consigo me conectar?

JL.
fonte
Se você tem controle sobre a criação dos certificados, não se esqueça de "Nome da entidade alternativa". Como se você pudesse colocar um curinga em "* .full.domainname.com". Veja digicert.com/subject-alternative-name.htm
granadaCoder

Respostas:

198

Como solução alternativa, você pode adicionar um manipulador aos ServicePointManager's ServerCertificateValidationCallbackno lado do cliente:

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

mas lembre-se de que isso não é uma boa prática , pois ignora completamente o certificado do servidor e informa ao gerente do ponto de serviço que qualquer certificado está correto, o que pode comprometer seriamente a segurança do cliente. Você pode refinar isso e fazer uma verificação personalizada (para o nome do certificado, hash etc.). pelo menos você pode contornar problemas durante o desenvolvimento ao usar certificados de teste.

Joachim Kerschbaumer
fonte
9
Acho que a maioria das configurações públicas usará um certificado adquirido, mas durante o desenvolvimento use o código acima nas instruções #if condicionais. Devs empresa deve geralmente configurar um servidor CA interna >> technet.microsoft.com/en-us/library/cc875810.aspx
Luke Puplett
2
Ajudou-me a descobrir como obter minha chamada SSL SSL WCF trabalhando com o Fiddler2 para depuração.
Roger Willcocks
2
@karank Considere colocá-lo no método Application_Start no Global.asax (consulte stackoverflow.com/a/12507094/1175419 ). Eu recomendaria fortemente o uso de uma diretiva de compilador #if DEBUG ou algo semelhante, como mencionado no comentário de Luke.
C Rich
4
Impressionante! você pode usar a expressão lambda como System.Net.ServicePointManager.ServerCertificateValidationCallback + = (se, cert, chain, sslerror) => true;
Dhanuka777
Um pouco de explicação adicional pode ser encontrada aqui: blog.effectivemessaging.com/2015_09_01_archive.html
granadaCoder
40

Quando eu tenho esse problema, é porque o client.config tinha seus pontos de extremidade como:

 https://myserver/myservice.svc 

mas o certificado estava esperando

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

Alterar os pontos de extremidade para corresponder ao FQDN do servidor resolve meu problema. Eu sei que essa não é a única causa desse problema.

Mike Cheel
fonte
Acabei de ter esse problema novamente e desta vez teve a ver com o certificado errado sendo usado. Parece que nos dois casos isso tem a ver com a correspondência correta de nomes.
Mike Cheel
3
Minha configuração gerada automaticamente teve <endpoint address = " localhost / myservice.svc " alterando isso para <endpoint address = " mymachine.mydoman.com/myservice.svc " resolvido isso.
knightscharge
Esse foi absolutamente o meu problema e levei dois dias para encontrar sua resposta. +1, eu daria +1000 se pudesse.
AussieJoe 4/03
20

os dois primeiros usam lambda, o terceiro usa código regular ... espero que você ache ú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
fonte
1
// Confia em todos os certificados System.Net.ServicePointManager.ServerCertificateValidationCallback + = (se, cert, chain, sslerror) => {return true; }; // remetente confiável System.Net.ServicePointManager.ServerCertificateValidationCallback + = (se, cert, chain, sslerror) => {retornar cert.Subject.Contains ("ca-l-9wfvrm1.ceridian.ca"); };
VoodooChild
1
Qualquer cracker pode forjar um certificado passando em todos os testes acima. Isso é inseguro.
Bjartur Thorlacius
19

Seu problema surge porque você está usando uma chave autoassinada. O cliente não confia nessa chave nem fornece uma cadeia para validar ou uma lista de revogação de certificado.

Você tem algumas opções - você pode

  1. desative a validação de certificado no cliente (movimento ruim, ataques do tipo intermediário)

  2. use makecert para criar uma CA raiz e criar certificados a partir disso (ok, mova, mas ainda não há CRL)

  3. crie uma autoridade de certificação raiz interna usando o Windows Certificate Server ou outra solução PKI e confie nesse certificado raiz (um pouco trabalhoso de gerenciar)

  4. adquira um certificado SSL de uma das CAs confiáveis ​​(caras)

blowdart
fonte
3
Em relação a (4), o StartSSL fornece um certificado de Classe 1 gratuito que funciona em todos os principais navegadores. Eles funcionam muito bem para meus meia dúzia de sites de baixa largura de banda.
Moodboom 21/05
Acho que o número 2 nesta lista ... esse URL pode ajudar: blogs.technet.microsoft.com/jhoward/2005/02/02/… "Como usar o MakeCert para obter autoridade de certificação raiz confiável e emissão de certificado SSL"
granadaCoder
1
Nota: O StartCom não é mais confiável - e acabou de ser removido do Chrome pt.wikipedia.org/wiki/StartCom
Simon_Weaver
16

Uma solução de uma linha. Adicione isso em qualquer lugar antes de chamar o servidor no lado do cliente:

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

Isso deve ser usado apenas para fins de teste porque o cliente ignorará as verificações de segurança SSL / TLS.

Gaspa79
fonte
2
Uma solução brilhante para testes. Estamos consumindo um serviço cujo provedor tornou a segurança um inferno com uma cadeia complicada de certificados de segurança e, até que possamos obter seus certificados e encadeamentos instáveis ​​para funcionar corretamente, essa solução alternativa é a única coisa que nos permite continuar o desenvolvimento.
precisa saber é o seguinte
12

Encontrei o mesmo problema e resolvi-o com duas soluções: Primeiro, usei o snap-in "Certificados" do MMC para a "conta de computador" e arrastei o certificado autoassinado para a pasta "Autoridades de certificação raiz confiáveis" . Isso significa que o computador local (aquele que gerou o certificado) agora confiará nesse certificado. Em segundo lugar, notei que o certificado foi gerado para algum nome interno do computador, mas o serviço da web estava sendo acessado usando outro nome. Isso causou uma incompatibilidade ao validar o certificado. Geramos o certificado para computer.operations.local, mas acessamos o serviço da Web usando https://computer.internaldomain.companydomain.com . Quando trocamos o URL pelo URL usado para gerar o certificado, não tivemos mais erros.

Talvez apenas mudar URLs funcionasse, mas, ao tornar o certificado confiável, você também evita a tela vermelha no Internet Explorer, onde ele diz que não confia no certificado.

Jeroen-bart Engelen
fonte
11

Se você usa o núcleo .net, tente o seguinte:

client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication =
        new X509ServiceCertificateAuthentication()
        {
            CertificateValidationMode = X509CertificateValidationMode.None,
            RevocationMode = System.Security.Cryptography.X509Certificates.X509RevocationMode.NoCheck
        };
Grzegorz J
fonte
1
Obrigado, funciona. Mas isso não tem nada a ver com o núcleo .net. É uma receita universal :)
Alexander
7

Por favor, siga os seguintes passos:

  1. Abra o link de serviço no IE.

  2. Clique na menção de erro de certificado na barra de endereços e clique em Exibir certificados.

  3. Cheque emitido para: nome.

  4. Pegue o nome emitido e substitua a menção localhost no serviço e no nome do endereço base do terminal do cliente por Um nome de domínio totalmente qualificado (FQDN).

Por exemplo: https: // localhost : 203 / SampleService.svc Para https: // INL-126166-.groupinfra.com : 203 / SampleService.svc

Rahul Rai
fonte
Ótimo, obrigado por esta resposta! Resolvidos os problemas sem fazer alterações no código.
Vipin Dubey
6

Além das respostas acima, você poderá encontrar esse erro se o seu cliente estiver executando a versão TLS errada, por exemplo, se o servidor estiver executando apenas o TLS 1.2.

Você pode corrigi-lo usando:

// tested in .NET 4.5:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
NMrt
fonte
no meu caso resposta aceita não me ajudar, mas este fez um truque
Sergey
Esta é a única resposta que corrigiu o erro no meu caso.
Tolga
5

Eu tive o mesmo problema. Eu também adicionei certificados de CA na loja local, mas fiz da maneira ERRADA.

Usando o console mmc (Iniciar -> Executar -> mmc ), você deve adicionar Certificados snap-in como conta de serviço (escolhendo a conta de serviço do IIS) ou conta de computador (que é adicionada a todas as contas da máquina)

Aqui está uma imagem do que estou falando Adicionar snap-in para uma conta de serviço ou a conta do computador

A partir daqui agora, você pode adicionar certificados de CAs ( CAs raiz confiáveis e CAs intermediárias ) e tudo funcionará bem

dar0x
fonte
4

Eu tive um problema semelhante com o certificado autoassinado. Eu poderia resolvê-lo usando o nome do certificado igual ao FQDN do servidor.

Idealmente, a parte SSL deve ser gerenciada no lado do servidor. O cliente não é obrigado a instalar nenhum certificado para SSL. Além disso, algumas das postagens mencionadas sobre como ignorar o SSL do código do cliente. Mas eu discordo totalmente disso.

Umesh Bhavsar
fonte
3

Eu apenas arrastei o certificado para a pasta "Autoridades de certificação raiz confiáveis" e pronto tudo funcionou bem.

Oh E adicionei o seguinte em um prompt de comando do administrador:

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

Não tenho certeza do nome que você precisa para o usuário (o meu é norueguês, como você pode ver!) user=NT-AUTHORITY/INTERACTIVE:?

Você pode ver todos os URLs existentes emitindo o comando: netsh http show urlacl

Haguna
fonte
0

Isso ocorreu ao tentar se conectar ao serviço WCF via. o IP, por exemplo, https://111.11.111.1:port/MyService.svcenquanto estiver usando um certificado vinculado a um nome, por exemplo, mysite.com.

Mudando para o https://mysite.com:port/MyService.svcresolvido.

lko
fonte
0

Corrigido um problema semelhante.

Percebi que tinha um pool de aplicativos em execução em uma conta que só tinha permissão de leitura do certificado usado.

O aplicativo .NET pôde recuperar corretamente o certificado, mas essa exceção foi lançada somente quando GetRequestStream () foi chamado.

As permissões de certificados podem ser gerenciadas via console do MMC

Alberto
fonte
0

Se você estiver usando o núcleo .net, durante o desenvolvimento, poderá ignorar a validação de certificado usando diretivas do compilador. Dessa maneira, somente validará o certificado para liberação e não para depuração:

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

Adicione isso ao seu código de cliente:

ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(
    delegate
    {
        return true;
    });
user662285
fonte
4
Essa resposta não é muito boa, pois não explica os riscos associados ao código.
Daved