Tidak dapat membangun hubungan saling percaya untuk saluran aman SSL / TLS - SOAP


326

Saya memiliki panggilan layanan web sederhana, yang dihasilkan oleh aplikasi .NET (C #) windows 2.0, melalui proksi layanan web yang dihasilkan oleh Visual Studio, untuk layanan web yang juga ditulis dalam C # (2.0). Ini telah bekerja selama beberapa tahun, dan terus melakukannya di selusin tempat di mana ia berjalan.

Instalasi baru di situs baru mengalami masalah. Ketika mencoba menjalankan layanan web, itu gagal dengan pesan yang mengatakan:

Tidak dapat membangun hubungan saling percaya untuk saluran aman SSL / TLS

URL layanan web menggunakan SSL (https: //) - tetapi ini telah bekerja untuk waktu yang lama (dan terus melakukannya) dari banyak lokasi lain.

Di mana saya melihat? Mungkinkah ini masalah keamanan antara Windows dan .NET yang unik untuk pemasangan ini? Jika demikian, di mana saya mengatur hubungan saling percaya? Saya tersesat!


Dalam kasus saya kesalahan ini disebabkan oleh penerusan alamat IP.
cja

Jawaban:


166

Pikiran (berdasarkan rasa sakit di masa lalu):

  • apakah Anda memiliki DNS dan saling berhadapan dengan server?
  • apakah Anda menggunakan nama yang benar dari sertifikat?
  • apakah sertifikat masih berlaku?
  • Apakah penyeimbang beban yang dikonfigurasi dengan buruk mengacaukan segalanya?
  • apakah server baru mesin memiliki jam yang diatur dengan benar (yaitu agar waktu UTC benar [abaikan waktu setempat, sebagian besar tidak dapat dibatalkan]) - ini tentu penting untuk WCF, sehingga dapat berdampak pada sabun biasa?
  • apakah ada masalah rantai kepercayaan sertifikat? jika Anda menjelajah dari server ke layanan sabun, dapatkah Anda mendapatkan SSL?
  • terkait dengan hal di atas - sudahkah sertifikat dipasang ke lokasi yang benar? (Anda mungkin perlu salinan dalam Otoritas Sertifikasi Root Tepercaya)
  • Apakah proxy tingkat mesin server diatur dengan benar? (yang berbeda dengan proxy pengguna); lihat proxycfg untuk XP / 2003 (tidak yakin tentang Vista dll)

2
1) Layanan web ada di web. Kita dapat menjelajahinya melalui browser. 2) Mesin baru bukan server - ini adalah desktop yang menjalankan aplikasi saya, yang mengumpulkan info pesanan dan mengunggah melalui layanan SOAP 3) Ya, kami dapat menjelajahinya. 4) Ini baru bagi saya: proksi level mesin?
Rob Schripsema

2
Iya; kode tidak menggunakan pengaturan proksi IE; ia menggunakan toko terpisah ... penting bahwa ini dikonfigurasi (jika Anda menggunakan proxy). Di XP, opsi termudah adalah (IIRC) "proxycfg -i" untuk mengimpor pengaturan IE.
Marc Gravell

11
Terima kasih, Marc. Ini membantu saya, dan masalahnya adalah server memiliki sertifikat yang ditandatangani oleh CA pihak ke-3 yang belum saya percayai. Solusinya adalah menambahkan CA itu ke daftar CA Root Tepercaya.
p.campbell

1
Komputer yang mengalami pengecualian ini tidak dapat menyinkronkan waktu sistem menggunakan server waktu. Saya harus masuk dan menyinkronkan waktu secara manual sebelum berhasil.
Chris - Haddox Technologies

4
Anda dapat memperoleh ini jika Anda telah menggunakan Fiddler untuk men-debug panggilan layanan dan telah menggunakan mode intersepsi sertifikat. Hapus saja intersepsi dalam opsi fiddler dan Anda harus baik
Ruskin

363

Cuplikan berikut akan memperbaiki kasus di mana ada sesuatu yang salah dengan sertifikat SSL di server yang Anda panggil. Misalnya, mungkin ditandatangani sendiri atau nama host antara sertifikat dan server mungkin tidak cocok.

Ini berbahaya jika Anda memanggil server di luar kendali langsung Anda, karena Anda tidak lagi dapat memastikan bahwa Anda berbicara dengan server yang Anda pikir Anda terhubung. Namun, jika Anda berhadapan dengan server internal dan mendapatkan sertifikat "benar" tidak praktis, gunakan yang berikut ini untuk memberi tahu layanan web untuk mengabaikan masalah sertifikat dan terus mengaktifkan prajurit.

Dua yang pertama menggunakan ekspresi lambda, yang ketiga menggunakan kode reguler. Yang pertama menerima sertifikat apa pun. Dua yang terakhir setidaknya memeriksa bahwa nama host dalam sertifikat adalah yang Anda harapkan.
... semoga bermanfaat

//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
Pengalaman saya dengan ServicePointManager. Setiap perubahan akan memengaruhi seluruh domain aplikasi. Meskipun jawabannya sangat jelas menjelaskan bagaimana ini dapat diterapkan, saya suka membuang poin ini.
Amzath

Menyetel panggilan balik berfungsi di .NET 4.5 untuk saya, tetapi tidak. NET 4.6
RJB

@ Amzath Ada saran tentang cara mengatur ulang ini setelah permintaan tertentu selesai? Seseorang mungkin perlu membuat satu permintaan ke server yang tidak bersertifikat, lalu mengembalikan semuanya seperti semula.
Isaac Lyman

1
@Isaac Lyman: ServicePointManager.ServerCertificateValidationCallback = null;harus kembali ke perilaku default.
Mike Chamberlain

1
@MikeChamberlain Satu-satunya masalah dengan saran Anda adalah bahwa permintaan bersamaan mungkin dianggap tidak aman karena Anda berurusan dengan pengaturan aplikasi global.
Isaac Lyman

178

Solusi "tangkap semua" yang sangat sederhana adalah ini:

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

Solusi dari sebastian-castaldi sedikit lebih detail.


21
Saya hanya memasukkan ini dalam #If CONFIG = "Debug"pernyataan sehingga hanya diaktifkan saat dalam mode debug. Ini sangat bagus!
cjbarth

1
Detail bisa bagus, tetapi ada sesuatu yang bisa dikatakan untuk baris kode yang cepat, pendek, dan mudah juga. Kode ini pendek dan melakukan trik.
allen1

apakah ini hanya berlaku pada Tindakan saat ini (mis. ASP MVC digunakan)? atau akan ditetapkan sebagai perilaku default untuk aplikasi ASP.NET?
JeeShen Lee

2
Ini harus digunakan hanya untuk tujuan pengujian, solusi ini mempercayai sertifikat apa pun, bahkan yang tidak valid / kedaluwarsa
Shenron

1
Seperti yang dijelaskan dalam komentar di atas, ini tidak memverifikasi jika koneksi SSL valid lagi. Jadi koneksi antara sistem Anda dan sistem lain mungkin terganggu. Itu selalu merupakan pertanyaan untuk apa Anda membutuhkannya.
Remy

35

Saya pribadi paling suka solusi berikut:

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

... lalu sebelum Anda meminta kesalahan, lakukan yang berikut ini

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

Menemukan ini setelah berkonsultasi dengan Solusi Luke


4
Lihat jawaban Sebastian Castaldi untuk peringatan keamanan untuk pendekatan ini.
Edward Brey

Apa risiko keamanan menggunakan ini dalam produksi?
Amjad

@Amjad risiko keamanan adalah sepenuhnya menghindari manfaat menggunakan SSL / TLS. Server dapat menyajikan sertifikat apa pun yang disukainya, dan kode ini akan mengabaikan kesalahan
1800 INFORMASI

18

Jika Anda menggunakan Windows 2003, Anda dapat mencoba ini:

Buka Microsoft Management Console (Mulai -> Jalankan -> mmc.exe);

Pilih File -> Tambah / Hapus Snap-in;

Di tab Standalone, pilih Tambah;

Pilih snap-in Sertifikat, dan klik Tambah;

Di wisaya, pilih Akun Komputer, lalu pilih Komputer Lokal. Tekan Selesai untuk mengakhiri panduan;

Tutup dialog Tambah / Hapus Snap-in;

Arahkan ke Sertifikat (Komputer Lokal) dan pilih toko yang akan diimpor:

Jika Anda memiliki sertifikat CA Root untuk perusahaan yang mengeluarkan sertifikat, pilih Otoritas Sertifikasi Root Tepercaya;

Jika Anda memiliki sertifikat untuk server itu sendiri, pilih Orang Lain

Klik kanan toko dan pilih Semua Tugas -> Impor

Ikuti wizard dan berikan file sertifikat yang Anda miliki;

Setelah itu, cukup restart IIS dan coba panggil layanan web lagi.

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


2
Ini membuat saya bagian dari jalan, tetapi saya perlu memiliki sertifikat di bagian Otoritas Sertifikasi Root Tepercaya untuk membuatnya berfungsi. Sesuai blogs.msdn.com/b/jpsanders/archive/2009/09/16/…
Jacob Ewald

17

Jika Anda tidak ingin mempercayai semua orang secara membabi buta dan membuat pengecualian kepercayaan hanya untuk host tertentu, solusi berikut ini lebih tepat.

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

Kemudian panggil Ssl.EnableTrustedHosts saat aplikasi Anda dimulai.


@ thelem Ya membaca kembali Saya pikir saya pasti salah membaca pertama kali
Shiv

Apa risiko keamanan dari mempercayai semua sertifikat dalam produksi?
Amjad

@Amjad risiko keamanannya adalah siapa pun antara klien dan server dapat menyisipkan dirinya di tengah komunikasi, menggunakan sertifikat SSL sendiri dan membaca semua lalu lintas antara klien dan server. Melakukan ini secara efektif membatalkan SSL.
Rob Prouse

Haruskah ini bekerja ketika saya menggunakan addon WCF untuk menghasilkan kelas dari wsdl?
Kamil

7

Luke menulis artikel yang cukup bagus tentang ini .. cukup jujur ​​.. coba ini

Solusi Luke

Alasan (kutipan dari artikelnya (minus kutukan)) ".. Masalah dengan kode di atas adalah tidak berfungsi jika sertifikat Anda tidak valid. Mengapa saya memposting ke halaman web dengan dan sertifikat SSL tidak valid? Karena Saya murah dan saya tidak merasa ingin membayar Verisign atau salah satu dari yang lain ** - * s untuk sertifikat ke kotak tes saya jadi saya sendiri yang menandatanganinya. Ketika saya mengirim permintaan, saya mendapat pengecualian yang indah:

System.Net.WebException Koneksi yang mendasarinya ditutup. Tidak dapat menjalin hubungan kepercayaan dengan server jauh.

Saya tidak tahu tentang Anda, tetapi bagi saya pengecualian itu tampak seperti sesuatu yang akan disebabkan oleh kesalahan konyol dalam kode saya yang menyebabkan POST gagal. Jadi saya terus mencari, dan mengutak-atik serta melakukan semua hal aneh. Hanya setelah saya mencari di Google hal yang saya temukan bahwa perilaku default setelah menemukan sertifikat SSL yang tidak valid adalah dengan membuang pengecualian ini. .. "


1
Solusi ini sudah tidak digunakan lagi untuk .Net 4.5. Jika Anda hanya ingin menerima semua sertifikat, lihat Sebastian Castaldi atau jawaban saya lebih lanjut di bawah ini.
Remy


3

Saya baru saja mengalami masalah ini. Resolusi saya adalah memperbarui waktu sistem dengan menyinkronkan secara manual ke server waktu. Untuk melakukan ini, Anda dapat:

  • Klik kanan jam di bilah tugas
  • Pilih Adjust Date/Time
  • Pilih menu Internet Time tab
  • Klik Change Settings
  • Pilih Update Now

Dalam kasus saya ini salah sinkronisasi sehingga saya harus mengkliknya beberapa kali sebelum diperbarui dengan benar. Jika pembaruan terus salah, Anda bahkan dapat mencoba menggunakan server waktu yang berbeda dari drop-down server.


ASTAGA. Ran menampar hal yang tepat ini. Terima kasih atas perbaikan yang mudah!
TheGerm

3

Coba ini:

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

Perhatikan bahwa Anda harus bekerja setidaknya dengan 4.5 .NET framework


3

Saya punya masalah serupa di .NETaplikasi di Internet Explorer.

Saya memecahkan masalah dengan menambahkan sertifikat (sertifikat VeriSign Kelas 3 dalam kasus saya) ke sertifikat editor tepercaya.

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

Anda bisa mendapatkan sertifikat jika Anda mengekspornya dari:

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

Terima kasih


1

Saya mengalami kesalahan ini berjalan melawan server web dengan url seperti:

a.b.domain.com

tapi tidak ada sertifikat untuk itu, jadi saya mendapat DNS yang disebut

a_b.domain.com

Hanya memberi petunjuk untuk solusi ini di sini karena ini muncul di google.


Dalam kasus saya, situs web dikonfigurasikan di bawah sertifikat wildcard ssl (* .abcd.com). Ketika dikonfigurasi, pengikatan situs web seperti xyz-abcd.com yang menyebabkan masalah.
sree

1

Bagi mereka yang mengalami masalah ini melalui sisi klien VS sekali berhasil menambahkan referensi layanan dan mencoba untuk melakukan panggilan pertama mendapat pengecualian ini: "Koneksi yang mendasarinya ditutup: Tidak dapat membangun hubungan kepercayaan untuk saluran aman SSL / TLS" Jika Anda menggunakan (seperti kasus saya) URL titik akhir dengan alamat IP dan mendapatkan pengecualian ini, maka Anda mungkin harus menambahkan kembali referensi layanan melakukan langkah-langkah ini:

  • Buka URL titik akhir di Internet Explorer.
  • Klik pada kesalahan sertifikat (ikon merah di bilah alamat)
  • Klik pada Lihat sertifikat.
  • Ambil yang dikeluarkan untuk: "nama" dan ganti alamat IP atau nama apa pun yang kami gunakan dan dapatkan kesalahan untuk "nama" ini.

Coba lagi :). Terima kasih


0

Dalam kasus saya, saya mencoba menguji SSL di lingkungan Visual Studio saya menggunakan IIS 7.

Inilah yang akhirnya saya lakukan untuk membuatnya bekerja:

  • Di bawah situs saya di bagian 'Bindings ...' di sebelah kanan di IIS, saya harus menambahkan 'https' yang mengikat ke port 443 dan pilih "IIS Express Developement Certificate".

  • Di bawah situs saya di bagian 'Pengaturan Lanjut ...' di sebelah kanan saya harus mengubah 'Protokol yang Diaktifkan' dari "http" menjadi "https".

  • Di bawah ikon 'Pengaturan SSL' saya memilih 'Terima' untuk sertifikat klien.

  • Kemudian saya harus mendaur ulang kumpulan aplikasi.

  • Saya juga harus mengimpor sertifikat host lokal ke toko pribadi saya menggunakan mmc.exe.

web.configFile saya sudah dikonfigurasi dengan benar, jadi setelah saya menyelesaikan semua hal di atas, saya dapat melanjutkan pengujian saya.


bagaimana konfigurasi web.config Anda?
Chazt3n

@ Chazt3n Saya tidak bisa memberi tahu Anda, itu beberapa waktu yang lalu, tapi itu akan menjadi dasar pengikatan http, saya biasanya menggunakan svcutil untuk menghasilkan info konfigurasi untuk info klien layanan web.
Popo

0

Solusi saya (VB.Net, versi "staging" (UAT) aplikasi ini perlu bekerja dengan sertifikat "staging" tetapi tidak mempengaruhi permintaan begitu mereka berada di situs langsung):

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

Jika tidak bekerja sertifikat buruk, ketika ServerCertificateValidationCallback mengembalikan true; Kode ServerCertificateValidationCallback saya:

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

Kode saya yang dicegah menjalankan ServerCertificateValidationCallback:

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

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

Saya menonaktifkan kode CertificateValidation dan ServerCertificateValidationCallback berjalan sangat baik


Anda tidak boleh menonaktifkan validasi sertifikat apa pun. Alih-alih, perbaiki masalah yang menyebabkan validasi yang gagal.
Dan

Apa risiko keamanan menggunakan ini dalam produksi?
Amjad
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.