Não foi possível estabelecer relação de confiança para o canal seguro SSL / TLS - SOAP

326

Eu tenho uma chamada de serviço da web simples, gerada por um aplicativo do Windows .NET (C #) 2.0, por meio do proxy de serviço da web gerado pelo Visual Studio, para um serviço da Web também escrito em C # (2.0). Isso funcionou por vários anos e continua a fazê-lo em cerca de uma dúzia de locais onde está sendo executado.

Uma nova instalação em um novo site está com problemas. Ao tentar chamar o serviço da web, ele falha com a mensagem dizendo:

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

A URL do serviço da web usa SSL (https: //) - mas isso funciona há muito tempo (e continua a fazê-lo) em muitos outros locais.

Onde eu olho? Esse problema de segurança entre o Windows e o .NET pode ser exclusivo desta instalação? Em caso afirmativo, onde eu estabeleço relações de confiança? Estou perdido!

Rob Schripsema
fonte
No meu caso, esse erro foi causado pelo encaminhamento de endereço IP.
Cja

Respostas:

166

Pensamentos (baseados na dor do passado):

  • você tem DNS e linha de visão para o servidor?
  • você está usando o nome correto do certificado?
  • o certificado ainda é válido?
  • um balanceador de carga mal configurado está atrapalhando as coisas?
  • a nova máquina do servidor tem o relógio ajustado corretamente (ou seja, para que a hora UTC esteja correta [ignore a hora local, é em grande parte irrelevante]) - isso certamente é importante para o WCF, portanto pode afetar o SOAP normal?
  • existe um problema de cadeia confiável de certificados? se você navegar do servidor para o serviço de sabão, você pode obter SSL?
  • relacionado ao acima - o certificado foi instalado no local correto? (você pode precisar de uma cópia nas Autoridades de certificação raiz confiáveis)
  • o proxy no nível da máquina do servidor está definido corretamente? (que diferente do proxy do usuário); veja proxycfg para XP / 2003 (não tenho certeza sobre o Vista etc)
Marc Gravell
fonte
2
1) O serviço da web está na web. Podemos navegar até ele através de um navegador. 2) A nova máquina não é um servidor - é uma área de trabalho executando meu aplicativo, que reúne informações de pedidos e carregamentos através do serviço SOAP 3) Sim, podemos navegar até ele. 4) Isso é novo para mim: proxy no nível da máquina?
31420 Rob Schripsema
2
Sim; código não usa as configurações de proxy do IE; ele usa um armazenamento separado ... é importante que isso esteja configurado (se você estiver usando um proxy). No XP, a opção mais fácil é (IIRC) "proxycfg -i" para importar as configurações do IE.
Marc Gravell
11
Obrigado Marc. Isso me ajudou, e o problema era que o servidor tinha um certificado assinado por uma autoridade de certificação de terceiros em que eu ainda não confiava. A solução foi adicionar essa CA à lista de CA Raiz Confiável.
P.campbell 03/12/2009
1
O computador que estava tendo essa exceção não conseguiu sincronizar a hora do sistema usando os servidores de hora. Eu tive que entrar e sincronizar manualmente o tempo antes que funcionasse.
Chris - Haddox Technologies
4
Você pode conseguir isso se estiver usando o Fiddler para depurar chamadas de serviço e tiver usado o modo de interceptação de certificado. Basta remover a intercepção nas opções do violinista e você deve ser bom
Ruskin
363

Os seguintes trechos corrigirão o caso em que há algo errado com o certificado SSL no servidor que você está chamando. Por exemplo, pode ser autoassinado ou o nome do host entre o certificado e o servidor pode não corresponder.

Isso é perigoso se você estiver chamando um servidor fora de seu controle direto, pois não poderá mais ter certeza de que está falando com o servidor ao qual pensa estar conectado. No entanto, se você estiver lidando com servidores internos e obter um certificado "correto" não for prático, use o seguinte para dizer ao serviço da Web que ignore os problemas de certificado e continue bravamente.

Os dois primeiros usam expressões lambda, o terceiro usa código regular. O primeiro aceita qualquer certificado. Os dois últimos, pelo menos, verificam se o nome do host no certificado é o que você espera.
... 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 = cert.Subject.Contains("YourServerName");
    return result;
}
Sebastian Castaldi
fonte
6
Minha experiência com o ServicePointManager. Qualquer alteração afetaria todo o domínio do aplicativo. Embora a resposta seja explicada com muita clareza como isso pode ser aplicado, eu gosto de apresentar esse ponto.
Amzath
Definir o retorno de chamada funciona no .NET 4.5 para mim, mas não no .NET 4.6
RJB 14/15
@ Ammath Alguma sugestão sobre como redefinir isso após a conclusão de uma solicitação específica? Uma pessoa pode precisar fazer uma solicitação para um servidor não certificado e depois colocar as coisas de volta do jeito que eram.
Isaac Lyman
1
@ Isaac Lyman: ServicePointManager.ServerCertificateValidationCallback = null;deve reverter para o comportamento padrão.
Mike Chamberlain
1
@MikeChamberlain O único problema com sua sugestão é que solicitações simultâneas podem ficar inseguras, pois você está lidando com uma configuração global de aplicativo.
22316 Isaac Lyman
178

A solução muito simples "pegar tudo" é esta:

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

A solução de sebastian-castaldi é um pouco mais detalhada.

Remy
fonte
21
Eu apenas coloquei isso em uma #If CONFIG = "Debug"instrução para que ele seja ativado somente no modo de depuração. Funciona muito bem!
precisa saber é o seguinte
1
Os detalhes podem ser bons, mas há algo a ser dito para uma linha de código rápida, curta e fácil também. Este código é curto e faz o truque.
allen1
isso funcionará apenas na ação atual (por exemplo, o ASP MVC é usado)? ou será definido como o comportamento padrão para o aplicativo ASP.NET?
perfil completo de JeeShen Lee
2
Isso deve ser usado apenas para testar propósito, esta solução confiança qualquer certificado, mesmo / inválido expirado queridos
Shenron
1
Conforme explicado nos comentários acima, isso não verifica se a conexão SSL é mais válida. Portanto, a conexão entre seu sistema e outros sistemas pode ser comprometida. É sempre uma questão do que você precisa disso.
Remy
35

Pessoalmente, gosto mais da seguinte solução:

using System.Security.Cryptography.X509Certificates;
using System.Net.Security;

... antes de solicitar a obtenção do erro, faça o seguinte

System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; };

Encontrei isso depois de consultar a Solução de Lucas

cusman
fonte
4
Veja a resposta de Sebastian Castaldi para obter advertências de segurança sobre essa abordagem.
Edward Brey 11/02
Qual é o risco de segurança de usá-lo na produção?
22418 Amjad
@Amjad o risco de segurança é que ele evita completamente todos os benefícios do uso de SSL / TLS. O servidor pode apresentar qualquer certificado que desejar e esse código ignorará o erro
1800 INFORMAÇÃO
18

Se você estiver usando o Windows 2003, pode tentar o seguinte:

Abra o Console de Gerenciamento Microsoft (Iniciar -> Executar -> mmc.exe);

Escolha Arquivo -> Adicionar / Remover Snap-in;

Na guia Independente, escolha Adicionar;

Escolha o snap-in Certificados e clique em Adicionar;

No assistente, escolha a conta do computador e, em seguida, escolha computador local. Pressione Concluir para finalizar o assistente;

Feche a caixa de diálogo Adicionar / remover snap-in;

Navegue para Certificados (Computador Local) e escolha uma loja para importar:

Se você possui o certificado de CA raiz da empresa que emitiu o certificado, escolha Autoridades de certificação raiz confiáveis;

Se você possui o certificado para o próprio servidor, escolha Outras Pessoas

Clique com o botão direito do mouse na loja e escolha Todas as Tarefas -> Importar

Siga o assistente e forneça o arquivo de certificado que você possui;

Depois disso, basta reiniciar o IIS e tente chamar o serviço da web novamente.

Referência: http://www.outsystems.com/NetworkForums/ViewTopic.aspx?Topic=Web-Services:-Could-not-establish-trust-relationship-for-the-SSL/TLS- ...

Diogo
fonte
2
Isso me deixou parte do caminho, mas eu precisava do certificado na seção Autoridades de certificação raiz confiáveis ​​para fazê-lo funcionar. Conforme blogs.msdn.com/b/jpsanders/archive/2009/09/16/…
Jacob Ewald
17

Se você não deseja confiar cegamente em todos e criar uma exceção de confiança apenas para determinados hosts, a solução a seguir é mais apropriada.

public static class Ssl
{
    private static readonly string[] TrustedHosts = new[] {
      "host1.domain.com", 
      "host2.domain.com"
    };

    public static void EnableTrustedHosts()
    {
      ServicePointManager.ServerCertificateValidationCallback = 
      (sender, certificate, chain, errors) =>
      {
        if (errors == SslPolicyErrors.None)
        {
          return true;
        }

        var request = sender as HttpWebRequest;
        if (request != null)
        {
          return TrustedHosts.Contains(request.RequestUri.Host);
        }

        return false;
      };
    }
}

Em seguida, basta ligar para Ssl.EnableTrustedHosts quando o aplicativo iniciar.

Gregor Slavec
fonte
@ thelem Sim relendo Acho que devo ter interpretado mal pela primeira vez #
Shiv
Qual é o risco de segurança de confiar em todos os certificados na produção?
22418 Amjad
@Amjad o risco de segurança é que qualquer pessoa entre o cliente e o servidor possa se inserir no meio das comunicações, usar seu próprio certificado SSL e ler todo o tráfego entre o cliente e o servidor. Isso efetivamente invalida o SSL.
Rob Prouse
Deveria funcionar quando iam usando o WCF addon para gerar classes a partir do wsdl?
Kamil
7

Luke escreveu um artigo muito bom sobre isso .. bastante direto .. faça uma tentativa

Solução de Lucas

Motivo (citação de seu artigo (menos xingamentos)) ".. O problema com o código acima é que ele não funciona se o seu certificado não for válido. Por que eu estaria postando em uma página da Web com um certificado SSL inválido? Sou barato e não estava com vontade de pagar à Verisign ou a uma das outras ** - * s por um certificado para minha caixa de teste, então eu o assinei.Quando enviei a solicitação, recebi uma exceção adorável:

System.Net.WebException A conexão subjacente foi fechada. Não foi possível estabelecer relação de confiança com o servidor remoto.

Eu não sei sobre você, mas para mim essa exceção parecia algo que seria causado por um erro bobo no meu código que estava causando a falha do POST. Então eu continuei pesquisando, aprimorando e fazendo todo tipo de coisas estranhas. Somente depois que pesquisei no *** n, descobri que o comportamento padrão após encontrar um certificado SSL inválido é lançar essa mesma exceção. .. "

Hans
fonte
1
Esta solução está obsoleta para o .Net 4.5. Se você quer apenas aceitar todos os certificados, consulte Sebastian Castaldi ou minha resposta mais abaixo.
Remy
7

A Ferramenta de diagnóstico SSL da Microsoft pode ajudar a identificar o problema.

ATUALIZAÇÃO o link foi corrigido agora.

sipwiz
fonte
7
A partir de hoje (agosto de 2012), esse link está quebrado.
ashes999
Pesquisou no diretório de download e nenhuma ferramenta de diagnóstico SSL está disponível por mais tempo. :(
SASS_Shooter
2
Vamos consertar o link. Corrija-me Se eu estiver errado iis.net/downloads/community/2009/09/…
Amzath
3

Acabei de encontrar esse problema. Minha resolução foi atualizar a hora do sistema sincronizando manualmente com os servidores de hora. Para fazer isso, você pode:

  • Clique com o botão direito do mouse no relógio na barra de tarefas
  • Selecione Adjust Date/Time
  • Selecione a Internet Timeguia
  • Clique Change Settings
  • Selecione Update Now

No meu caso, isso estava sincronizando incorretamente, então tive que clicar nele várias vezes antes de atualizar corretamente. Se a atualização continuar incorreta, você pode tentar usar um servidor de horário diferente no menu suspenso do servidor.

Chris - Tecnologias Haddox
fonte
VACA SAGRADA. Ran bateu exatamente nessa coisa. Obrigado pela correção fácil!
TheGerm 27/01
3

Tente o seguinte:

System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12;

Observe que você precisa trabalhar pelo menos com o 4.5 .NET framework

Manuel Roldan
fonte
3

Eu tive um problema semelhante no .NETaplicativo no Internet Explorer.

Resolvi o problema de adicionar o certificado (certificado VeriSign Classe 3 no meu caso) a certificados de editores confiáveis.

Go to Internet Options-> Content -> Publishers and import it

Você pode obter o certificado se exportá-lo de:

Internet Options-> Content -> Certificates -> Intermediate Certification Authorities -> VeriSign Class 3 Public Primary Certification Authority - G5

obrigado

debiasej
fonte
1

Eu tive esse erro sendo executado em um servidor web com URL como:

a.b.domain.com

mas não havia certificado para isso, então recebi um DNS chamado

a_b.domain.com

Basta dar uma dica para essa solução aqui, pois ela apareceu no topo do google.

Thomas Koelle
fonte
No meu caso, o site foi configurado sob um certificado SSL curinga (* .abcd.com). Quando configurada, a ligação do site era como xyz-abcd.com, que estava causando o problema.
sree
1

Para aqueles que estão enfrentando esse problema pelo lado do cliente VS, uma vez que adicionaram uma referência de serviço com êxito e tentaram executar a primeira chamada, receberam esta exceção: "A conexão subjacente foi fechada: não foi possível estabelecer relação de confiança para o canal seguro SSL / TLS" você está usando (como no meu caso) um URL de terminal com o endereço IP e recebeu essa exceção, provavelmente precisará adicionar novamente a referência de serviço, executando estas etapas:

  • Abra o URL do terminal no Internet Explorer.
  • Clique no erro de certificado (ícone vermelho na barra de endereços)
  • Clique em Exibir certificados.
  • Pegue o emitido para: "name" e substitua o endereço IP ou qualquer outro nome que estávamos usando e obtendo o erro para esse "name".

Tente novamente :). obrigado

Ernest
fonte
0

No meu caso, eu estava tentando testar o SSL no meu ambiente do Visual Studio usando o IIS 7.

Isto é o que acabei fazendo para fazê-lo funcionar:

  • No meu site, na seção 'Ligações ...' à direita no IIS, tive que adicionar a ligação 'https' à porta 443 e selecionar "Certificado de Desenvolvimento do IIS Express".

  • No meu site, na seção 'Configurações avançadas ...' à direita, tive que alterar os 'Protocolos ativados' de "http" para "https".

  • Sob o ícone 'Configurações SSL', selecione 'Aceitar' para certificados de cliente.

  • Então eu tive que reciclar o pool de aplicativos.

  • Eu também tive que importar o certificado de host local para minha loja pessoal usando o mmc.exe.

Meu web.configarquivo já estava configurado corretamente, então, depois de ter resolvido tudo o que foi dito acima, pude continuar meus testes.

Popo
fonte
como foi configurado o seu web.config?
precisa saber é o seguinte
@ Chazt3n Eu não sabia, isso foi há um tempo, mas teria sido uma configuração básica de ligação http, eu normalmente uso o svcutil para gerar informações de configuração para informações do cliente de serviço da web.
Popo
0

Minha solução (VB.Net, a versão "temporária" (UAT) desse aplicativo precisa trabalhar com o certificado "temporária", mas não afeta as solicitações quando elas estão no site ativo:

    ...
        Dim url As String = ConfigurationManager.AppSettings("APIURL") & "token"
        If url.ToLower().Contains("staging") Then
           System.Net.ServicePointManager.ServerCertificateValidationCallback = AddressOf AcceptAllCertifications
        End If
    ...

    Private  Function AcceptAllCertifications(ByVal sender As Object, ByVal certification As System.Security.Cryptography.X509Certificates.X509Certificate, ByVal chain As System.Security.Cryptography.X509Certificates.X509Chain, ByVal sslPolicyErrors As System.Net.Security.SslPolicyErrors) As Boolean
        Return True
    End Function
GreenRock
fonte
-3

Se não funcionar com um certificado inválido, quando ServerCertificateValidationCallback retornar true; Código My ServerCertificateValidationCallback:

ServicePointManager.ServerCertificateValidationCallback += delegate
{
    LogWriter.LogInfo("Проверка сертификата отключена, на уровне ServerCertificateValidationCallback");
    return true;
};

Meu código que impediu executar ServerCertificateValidationCallback:

     if (!(ServicePointManager.CertificatePolicy is CertificateValidation))
    {
        CertificateValidation certValidate = new CertificateValidation();
        certValidate.ValidatingError += new CertificateValidation.ValidateCertificateEventHandler(this.OnValidateCertificateError);
        ServicePointManager.CertificatePolicy = certValidate;
    }

Função OnValidateCertificateError:

private void OnValidateCertificateError(object sender, CertificateValidationEventArgs e)
{
    string msg = string.Format(Strings.OnValidateCertificateError, e.Request.RequestUri, e.Certificate.GetName(), e.Problem, new Win32Exception(e.Problem).Message);
    LogWriter.LogError(msg);
    //Message.ShowError(msg);
}

Desabilitei o código CertificateValidation e ServerCertificateValidationCallback executando muito bem

Roberto Gata
fonte
Você nunca deve desativar qualquer validação de certificado. Em vez disso, corrija o problema que está causando a falha na validação.
Dan
Qual é o risco de segurança de usá-lo na produção?
22418 Amjad