Không thể thiết lập mối quan hệ tin cậy cho kênh bảo mật SSL / TLS - SOAP


325

Tôi có một cuộc gọi dịch vụ web đơn giản, được tạo bởi ứng dụng windows .NET (C #) 2.0, thông qua proxy dịch vụ web được tạo bởi Visual Studio, cho một dịch vụ web cũng được viết bằng C # (2.0). Điều này đã làm việc trong nhiều năm, và tiếp tục làm như vậy tại hàng chục nơi mà nó đang chạy.

Một cài đặt mới tại một trang web mới đang gặp vấn đề. Khi cố gắng gọi dịch vụ web, nó không thành công với thông báo:

Không thể thiết lập mối quan hệ tin cậy cho kênh bảo mật SSL / TLS

URL của dịch vụ web sử dụng SSL (https: //) - nhưng điều này đã hoạt động trong một thời gian dài (và tiếp tục như vậy) từ nhiều địa điểm khác.

Tôi tìm ở đâu? Đây có thể là một vấn đề bảo mật giữa Windows và .NET là duy nhất cho cài đặt này? Nếu vậy, tôi sẽ thiết lập mối quan hệ tin cậy ở đâu? Tôi bị lạc!


Trong trường hợp của tôi, lỗi này là do chuyển tiếp địa chỉ IP.
cja

Câu trả lời:


166

Suy nghĩ (dựa trên nỗi đau trong quá khứ):

  • Bạn có DNS và tầm nhìn đến máy chủ không?
  • bạn đang sử dụng tên chính xác từ giấy chứng nhận?
  • Giấy chứng nhận vẫn còn hiệu lực?
  • là một cân bằng tải cấu hình xấu làm rối tung mọi thứ?
  • máy chủ mới có đồng hồ được đặt chính xác không (nghĩa là thời gian UTC là chính xác [bỏ qua giờ địa phương, phần lớn không liên quan]) - điều này chắc chắn có vấn đề với WCF, vì vậy có thể ảnh hưởng đến SOAP thường xuyên không?
  • Có một vấn đề chuỗi chứng chỉ tin cậy? Nếu bạn duyệt từ máy chủ đến dịch vụ xà phòng, bạn có thể nhận được SSL không?
  • liên quan đến vấn đề trên - chứng chỉ đã được cài đặt đúng vị trí chưa? (bạn có thể cần một bản sao trong Cơ quan chứng nhận gốc đáng tin cậy)
  • proxy cấp độ máy của máy chủ có được đặt chính xác không? (khác với proxy của người dùng); xem proxycfg cho XP / 2003 (không chắc chắn về Vista, v.v.)

2
1) Dịch vụ web trên web. Chúng tôi có thể duyệt qua nó thông qua một trình duyệt. 2) Máy mới không phải là máy chủ - đó là máy tính để bàn chạy ứng dụng của tôi, tập hợp thông tin đặt hàng và tải lên thông qua dịch vụ SOAP 3) Có, chúng tôi có thể duyệt đến nó. 4) Điều này là mới đối với tôi: proxy cấp độ máy?
Rob Schripsema

2
Đúng; mã không sử dụng cài đặt proxy IE; nó sử dụng một cửa hàng riêng biệt ... điều quan trọng là nó được cấu hình (nếu bạn đang sử dụng proxy). Trên XP, tùy chọn dễ nhất là (IIRC) "proxycfg -i" để nhập cài đặt IE.
Marc Gravell

11
Cảm ơn Marc. Điều này đã giúp tôi và vấn đề là máy chủ đã có chứng nhận được ký bởi CA bên thứ 3 mà tôi chưa tin tưởng. Giải pháp là thêm CA đó vào danh sách CA gốc đáng tin cậy.
p.campbell

1
Máy tính có ngoại lệ này không thể đồng bộ hóa thời gian hệ thống bằng máy chủ thời gian. Tôi đã phải đi vào và đồng bộ hóa thủ công thời gian trước khi nó hoạt động.
Chris - Haddox Technologies

4
Bạn có thể nhận được điều này nếu bạn đã sử dụng Fiddler để gỡ lỗi các cuộc gọi dịch vụ và đã sử dụng chế độ chặn chứng chỉ của nó. Chỉ cần loại bỏ việc chặn trong các tùy chọn của fiddler và bạn sẽ ổn
Ruskin

363

Các đoạn mã sau sẽ khắc phục trường hợp có lỗi xảy ra với chứng chỉ SSL trên máy chủ bạn đang gọi. Ví dụ: nó có thể tự ký hoặc tên máy chủ giữa chứng chỉ và máy chủ có thể không khớp.

Điều này rất nguy hiểm nếu bạn đang gọi một máy chủ nằm ngoài sự kiểm soát trực tiếp của mình, vì bạn không còn có thể chắc chắn rằng bạn đang nói chuyện với máy chủ mà bạn nghĩ rằng bạn đã kết nối. Tuy nhiên, nếu bạn đang làm việc với các máy chủ nội bộ và nhận được chứng chỉ "chính xác" là không thực tế, hãy sử dụng các cách sau để thông báo cho dịch vụ web để bỏ qua các vấn đề về chứng chỉ và dũng cảm tiếp tục.

Hai cái đầu sử dụng biểu thức lambda, cái thứ ba sử dụng mã thông thường. Việc đầu tiên chấp nhận bất kỳ chứng chỉ. Hai cái cuối cùng ít nhất kiểm tra xem tên máy chủ trong chứng chỉ có phải là tên bạn mong đợi không.
... hy vọng bạn cảm thấy nó hữu ích

//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
Kinh nghiệm của tôi với ServicePointManager. Mọi thay đổi đối với nó sẽ ảnh hưởng đến toàn bộ miền ứng dụng. Mặc dù câu trả lời được giải thích rất rõ ràng làm thế nào điều này có thể được áp dụng, tôi muốn ném điểm này.
Amzath

Cài đặt gọi lại hoạt động trong .NET 4.5 cho tôi, nhưng không phải .NET 4.6
RJB

@Amzath Bạn có đề xuất nào về cách đặt lại yêu cầu này sau khi yêu cầu cụ thể hoàn tất không? Một người có thể cần phải thực hiện một yêu cầu đến một máy chủ không xác định, sau đó đưa mọi thứ trở lại như cũ.
Isaac Lyman

1
@Isaac Lyman: ServicePointManager.ServerCertificateValidationCallback = null;nên trở lại hành vi mặc định.
Mike Chamberlain

1
@MikeChamberlain Vấn đề duy nhất với đề xuất của bạn là các yêu cầu đồng thời có thể được đưa ra không an toàn do bạn đang xử lý cài đặt ứng dụng toàn cầu.
Isaac Lyman

178

Giải pháp "bắt tất cả" rất đơn giản là đây:

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

Giải pháp từ sebastian-castaldi chi tiết hơn một chút.


21
Tôi chỉ đặt điều này trong một #If CONFIG = "Debug"tuyên bố để nó chỉ được kích hoạt khi ở chế độ gỡ lỗi. Nó hoạt động rất tốt!
cjbarth

1
Chi tiết có thể là tốt, nhưng có một cái gì đó để nói cho một dòng mã nhanh chóng, ngắn và dễ dàng là tốt. Mã này là ngắn và thực hiện các mẹo.
allen1

hành động này chỉ hành động trên hành động hiện tại (ví dụ: sử dụng ASP MVC)? hoặc nó sẽ được đặt làm hành vi mặc định cho ứng dụng ASP.NET?
JeeShen Lee

2
Điều này sẽ chỉ được sử dụng cho mục đích thử nghiệm, giải pháp này tin tưởng bất kỳ giấy chứng nhận, ngay cả / không hợp lệ hết hạn cái
Shenron

1
Như đã giải thích trong các ý kiến ở trên, điều này không xác minh nếu kết nối SSL có giá trị nữa. Vì vậy, mối liên hệ giữa hệ thống của bạn và các hệ thống khác có thể bị tổn hại. Nó luôn luôn là một câu hỏi về những gì bạn cần điều này cho.
Remy

35

Tôi cá nhân như giải pháp sau đây nhất:

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

... sau đó trước khi bạn làm theo yêu cầu nhận được lỗi, hãy làm như sau

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

Các mặt hàng này sau khi trao đổi giải pháp Luke


4
Xem câu trả lời của Sebastian Castaldi để biết các biện pháp bảo mật cho phương pháp này.
Edward Brey

Rủi ro bảo mật của việc sử dụng này trong sản xuất là gì?
Amjad

@Amjad rủi ro bảo mật là nó hoàn toàn bỏ qua mọi lợi ích của việc sử dụng SSL / TLS. Máy chủ có thể xuất trình bất kỳ chứng chỉ nào họ thích và mã này sẽ bỏ qua lỗi
1800 THÔNG TIN

18

Nếu bạn đang sử dụng Windows 2003, bạn có thể thử điều này:

Mở Microsoft Management Console (Bắt đầu -> Chạy -> mmc.exe);

Chọn Tệp -> Thêm / Xóa Snap-in;

Trong tab Độc lập, chọn Thêm;

Chọn chứng chỉ đính kèm và nhấp vào Thêm;

Trong trình hướng dẫn, chọn Tài khoản máy tính, sau đó chọn Máy tính cục bộ. Nhấn Kết thúc để kết thúc trình hướng dẫn;

Đóng hộp thoại Thêm / Xóa Snap-in;

Điều hướng đến Chứng chỉ (Máy tính cục bộ) và chọn cửa hàng để nhập:

Nếu bạn có chứng chỉ Root CA cho công ty đã cấp chứng chỉ, hãy chọn Cơ quan chứng nhận gốc đáng tin cậy;

Nếu bạn có chứng chỉ cho chính máy chủ, hãy chọn Người khác

Nhấp chuột phải vào cửa hàng và chọn Tất cả tác vụ -> Nhập

Làm theo trình hướng dẫn và cung cấp tệp chứng chỉ mà bạn có;

Sau đó, chỉ cần khởi động lại IIS và thử gọi lại dịch vụ web.

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


2
Điều này đã cho tôi một phần của cách này, nhưng tôi cần phải có chứng chỉ trong phần Cơ quan chứng nhận gốc đáng tin cậy để làm cho nó hoạt động. Theo blogs.msdn.com/b/jpsanders/archive/2009/09/16/...
Jacob Ewald

17

Nếu bạn không tin tưởng một cách mù quáng vào mọi người và chỉ tạo một ngoại lệ tin cậy cho một số máy chủ nhất định thì giải pháp sau là phù hợp hơn.

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

Sau đó, chỉ cần gọi Ssl.EnableTrustedHosts khi bắt đầu ứng dụng của bạn.


@thelem Có đọc lại Tôi nghĩ rằng tôi đã đọc sai lần đầu tiên
Shiv

Các nguy cơ bảo mật của tin tưởng tất cả các chứng chỉ trong sản xuất là gì?
Amjad

@Amjad rủi ro bảo mật là bất kỳ ai giữa máy khách và máy chủ đều có thể tự chèn vào giữa các liên lạc, sử dụng chứng chỉ SSL của riêng họ và đọc tất cả lưu lượng giữa máy khách và máy chủ. Việc làm này làm mất hiệu lực một cách hiệu quả SSL.
Rob Prouse

Nó cũng làm việc khi iam sử dụng WCF addon để tạo ra các lớp từ wsdl?
Kamil

7

Luke đã viết một bài viết khá hay về điều này .. khá đơn giản .. hãy thử xem

Giải pháp Luke

Lý do (trích dẫn từ bài viết của anh ấy (trừ lời chửi bới)) ".. Vấn đề với mã ở trên là nó không hoạt động nếu chứng chỉ của bạn không hợp lệ. Tại sao tôi lại đăng lên trang web có chứng chỉ SSL không hợp lệ? Tôi rẻ và tôi không cảm thấy muốn trả Verisign hoặc một trong những người khác ** - * cho một chứng nhận vào hộp kiểm tra của mình để tôi tự ký. Khi tôi gửi yêu cầu, tôi nhận được một ngoại lệ đáng yêu ném vào tôi:

System.Net.WebException Kết nối cơ bản đã được đóng. Không thể thiết lập mối quan hệ tin cậy với máy chủ từ xa.

Tôi không biết về bạn, nhưng với tôi, ngoại lệ đó trông giống như một thứ gì đó sẽ được gây ra bởi một lỗi ngớ ngẩn trong mã của tôi đã khiến POST bị lỗi. Vì vậy, tôi tiếp tục tìm kiếm, và tinh chỉnh và làm tất cả các loại điều kỳ lạ. Chỉ sau khi tôi googled điều *** n tôi mới phát hiện ra rằng hành vi mặc định sau khi gặp chứng chỉ SSL không hợp lệ là ném ngoại lệ này. .. "


1
Giải pháp này là một phản đối cho Net 4.5. Nếu bạn chỉ muốn chấp nhận tất cả các chứng chỉ, hãy xem Sebastian Castaldi hoặc câu trả lời của tôi dưới đây.
Remy

7

Công cụ chẩn đoán SSL của Microsoft có thể giúp xác định sự cố.

CẬP NHẬT liên kết đã được sửa chữa ngay bây giờ.


7
Tính đến hôm nay (tháng 8 năm 2012), liên kết đó đã bị hỏng.
tro999

Tìm kiếm thư mục tải xuống và không có Công cụ chẩn đoán SSL nào khả dụng nữa. :(
SASS_Shooter

2
Hãy để chúng tôi sửa chữa các liên kết. Sửa lỗi cho tôi Nếu tôi sai iis.net/doads/community/2009/09/ trên
Amzath

3

Tôi chỉ gặp phải vấn đề này. Giải pháp của tôi là cập nhật thời gian hệ thống bằng cách đồng bộ hóa thủ công với các máy chủ thời gian. Để làm điều này, bạn có thể:

  • Bấm chuột phải vào đồng hồ trên thanh tác vụ
  • Lựa chọn Adjust Date/Time
  • Chọn Internet Timetab
  • Nhấp chuột Change Settings
  • Lựa chọn Update Now

Trong trường hợp của tôi, điều này đã được đồng bộ hóa không chính xác vì vậy tôi phải nhấp vào nó nhiều lần trước khi cập nhật chính xác. Nếu nó tiếp tục cập nhật không chính xác, bạn thậm chí có thể thử sử dụng máy chủ thời gian khác từ trình đơn thả xuống của máy chủ.


CÔ GÁI Ran đập vào điều chính xác này. Cảm ơn đã sửa chữa dễ dàng!
TheGerm

3

Thử cái này:

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

Lưu ý rằng bạn phải làm việc ít nhất với 4.5 .NET framework


3

Tôi đã có một vấn đề tương tự trong .NETứng dụng trong trình duyệt Internet Explorer.

Tôi đã giải quyết vấn đề thêm chứng chỉ (chứng chỉ VeriSign Class 3 trong trường hợp của tôi) vào chứng chỉ biên tập viên đáng tin cậy.

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

Bạn có thể nhận được chứng chỉ nếu bạn xuất nó từ:

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

cảm ơn


1

Tôi gặp lỗi này khi chạy với máy chủ web có url như:

a.b.domain.com

nhưng không có chứng chỉ cho nó, vì vậy tôi nhận được một DNS được gọi là

a_b.domain.com

Chỉ cần đưa ra gợi ý cho giải pháp này ở đây vì nó đã đứng đầu trong google.


Trong trường hợp của tôi, trang web được định cấu hình theo chứng chỉ ssl ký tự đại diện (* .abcd.com). Khi được định cấu hình, liên kết trang web giống như xyz-abcd.com gây ra sự cố.
sree

1

Đối với những người gặp vấn đề này thông qua phía khách hàng VS đã thêm thành công tham chiếu dịch vụ và cố gắng thực hiện cuộc gọi đầu tiên có ngoại lệ này: Hồi Kết nối cơ bản đã bị đóng: Không thể thiết lập mối quan hệ tin cậy cho kênh bảo mật SSL / TLS. bạn đang sử dụng (như trường hợp của tôi) một URL điểm cuối có địa chỉ IP và có ngoại lệ này, thì có lẽ bạn cần phải thêm lại tham chiếu dịch vụ theo các bước này:

  • Mở URL điểm cuối trên Internet Explorer.
  • Nhấp vào lỗi chứng chỉ (biểu tượng màu đỏ trong thanh địa chỉ)
  • Bấm vào Xem chứng chỉ.
  • Lấy mã phát hành để: "tên" và thay thế địa chỉ IP hoặc bất kỳ tên nào chúng tôi đang sử dụng và nhận được lỗi cho "tên" này.

Thử lại :). Cảm ơn


0

Trong trường hợp của tôi, tôi đã thử kiểm tra SSL trong môi trường Visual Studio bằng IIS 7.

Đây là những gì tôi đã làm để làm cho nó hoạt động:

  • Trong trang web của tôi trong phần 'Ràng buộc ...' ở bên phải trong IIS, tôi đã phải thêm liên kết 'https' vào cổng 443 và chọn "Chứng chỉ phát triển IIS Express".

  • Trong trang web của tôi trong phần 'Cài đặt nâng cao ...' ở bên phải, tôi đã phải thay đổi 'Giao thức được bật' từ "http" thành "https".

  • Trong biểu tượng 'Cài đặt SSL', tôi đã chọn 'Chấp nhận' cho chứng chỉ ứng dụng khách.

  • Sau đó tôi phải tái chế hồ bơi ứng dụng.

  • Tôi cũng đã phải nhập chứng chỉ máy chủ cục bộ vào cửa hàng cá nhân của mình bằng mmc.exe.

web.configTập tin của tôi đã được cấu hình đúng, vì vậy sau khi tôi sắp xếp tất cả các mục trên, tôi có thể tiếp tục thử nghiệm.


web.config của bạn được cấu hình như thế nào?
Chazt3n

@ Chazt3n Tôi không thể nói với bạn, đó là một thời gian trước, nhưng nó sẽ là một ràng buộc http cơ bản được thiết lập, tôi thường sử dụng svcutil để tạo thông tin cấu hình cho thông tin máy khách dịch vụ web.
Popo

0

Giải pháp của tôi (VB.Net, phiên bản "dàn dựng" (UAT) của ứng dụng này cần phải hoạt động với chứng chỉ "dàn" nhưng không ảnh hưởng đến các yêu cầu khi chúng ở trên trang web trực tiếp):

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

Nếu không hoạt động chứng chỉ xấu, khi ServerCertertValidationCallback trở lại đúng; Mã máy chủ của tôiCertertValidationCallback:

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

Mã của tôi mà ngăn chặn thực thi ServerCertertValidationCallback:

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

Hàm OnValidateCertertError:

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

Tôi đã vô hiệu hóa mã Chứng nhận và ServerCertertValidationCallback chạy rất tốt


Bạn không bao giờ nên vô hiệu hóa bất kỳ xác nhận chứng chỉ. Thay vào đó, khắc phục sự cố gây ra xác nhận thất bại.
Dan

Rủi ro bảo mật của việc sử dụng này trong sản xuất là gì?
Amjad
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.