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!


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)

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;
}

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.


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


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- ...


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.


@ 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. .. "


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


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.


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


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


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.


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


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.


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

-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


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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.