2017-12-20 235 views
18

Tôi có mã C# sau, xây dựng cuộc gọi https với chứng chỉ tùy chỉnh. Khi sử dụng Tls 1.1, cuộc gọi hoạt động tốt. Khi sử dụng Tls 1.2, ngắt cuộc gọi. Tôi sử dụng curl, sử dụng tls 1.2 hoạt động tốt là tốt.C# và dotnet 4.7.1 không thêm chứng chỉ tùy chỉnh cho TLS 1.2 gọi

C# Code:

X509Certificate2Collection collection = new X509Certificate2Collection(); 
collection.Import("C:\\SomePath\\MyCertificate.pfx", "MyPassword", X509KeyStorageFlags.PersistKeySet); 
var cert = collection[0]; 

ServicePointManager.SecurityProtocol = ...; 

ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, errors) => true; 
HttpClientHandler handler = new HttpClientHandler(); 
handler.ServerCertificateCustomValidationCallback = (message, certificate2, arg3, arg4) => true; 
handler.ClientCertificates.Add(cert); 

var content = new ByteArrayContent(Encoding.GetEncoding("latin1").GetBytes("Hello world")); 
HttpClient client = new HttpClient(handler); 
var resp = client.PostAsync(requestUri: url, content: content).Result.Content.ReadAsStringAsync().Result; 

Hoạt động trên:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11; 

Lỗi với:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; 

thông báo lỗi Net: SocketException: Một kết nối hiện đã buộc phải đóng cửa do máy chủ từ xa

Net phiên bản: 4.7.1

Hệ điều hành: Windows 10 phiên bản 1703 (được hỗ trợ danh sách mật mã: https://msdn.microsoft.com/en-us/library/windows/desktop/mt808163(v=vs.85).aspx) - và máy chủ xác định TLS_RSA_WITH_AES_256_GCM_SHA384 được sử dụng, đó là một trong những thuật toán mã hóa được hỗ trợ.

Trong wireshark tôi có thể thấy rằng với các cuộc gọi đang hoạt động (C#/Tls 1.1 và Curl Tls 1.2) chứng chỉ đang được gửi đến máy chủ. Đây là bãi Wireshark cho C# tls 1.1 gọi:

Wireshark dump - Csharp tls 1.1

Tuy nhiên, cũng trong Wireshark, tôi có thể thấy rằng với C#/TLS 1.2 không có giấy chứng nhận được gửi từ máy khách đến máy chủ. Đây là bãi Wireshark cho C# tls 1.2 gọi:

enter image description here

bất cứ ai có thể nhìn thấy những gì tôi đang thiếu ở đây?

CẬP NHẬT

Dường như giấy chứng nhận có chữ ký md5 mà không được hỗ trợ bởi Schannel trong cửa sổ kết hợp với tls 1.2. Nhà cung cấp của chúng tôi đã tạo một chứng chỉ khác cho chúng tôi như một giải pháp.

Tôi đã xem qua chủ đề ngẫu nhiên này mà thảo luận về vấn đề này: https://community.qualys.com/thread/15498

+0

Tôi gặp sự cố tương tự với ứng dụng máy khách/ứng dụng .NET Core 2.0. Tôi đã giải quyết bằng cách buộc TLS 1.2 trên máy chủ. Bằng cách này, khách hàng thương lượng giao thức và chứng chỉ đúng cách. Bạn có thể thử kết nối với một máy chủ bị buộc phải chỉ TLS 1.2 và xem bạn có hành vi tương tự với .NET Framework không. – Ghigo

+0

thay đổi điều này trên máy chủ không thực sự là một tùy chọn ở đây vì máy chủ thuộc về một nhà cung cấp. Và nó không quan trọng nếu tôi thêm tls 1.1 cùng. Miễn là tls 1.2 chỉ là một trong số các giao thức được phép, vấn đề này xảy ra. Tôi cần phải biết lý do tại sao. Net cư xử theo cách này khi curl hoạt động tốt. Và tôi cần kích hoạt tls 1.2 vì đây là cài đặt tĩnh và các kết nối khác phụ thuộc vào tls 1.2 trong cùng một ứng dụng. Nếu tôi có thể chuyển tls 1,3 cho cuộc gọi duy nhất này, nó sẽ làm. Nhưng thiết lập các giao thức trên đối tượng xử lý ném một ngoại lệ nói rằng điều này là không thể trong env hiện tại. –

+1

Trông giống như một bản sao của câu hỏi này https://stackoverflow.com/questions/44751179/tls-1-2-not-negotiated-in-net-4-7-without-explicit-servicepointmanager-security –

Trả lời

0

Tôi tin rằng mã này được che một số loại lỗi chứng chỉ bằng cách luôn luôn mù quáng trở thành sự thật:

tôi khuyên bạn nên có một chức năng thực sự phân tích kết quả của arg4. Đó là lỗi chính sách SSL của bạn. Đăng nhập chúng và bạn sẽ nhận được câu trả lời của bạn. Trong ví dụ của tôi, tôi ghi vào bảng điều khiển, nhưng bạn có thể ghi vào dấu vết hoặc tệp. Bạn sẽ nhận được một số sẽ được liên kết với một giá trị cho liệt kê SslPolicyErrors. Dựa trên kết quả bạn có thể cần phải kiểm tra arg3 của bạn, đó là chuỗi của bạn.

ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => { 

SslPolicyErrors errs = sslPolicyErrors; 
Console.WriteLine("Policy Errors " + sslPolicyErrors.ToString());   
return true;}; 
+0

Trước hết, cảm ơn bạn đã bình luận! Tuy nhiên, chức năng gọi lại không bao giờ được gọi. Tôi chỉ cần thêm một cơ thể để chức năng với một breakpoint và một giao diện điều khiển ghi cuộc gọi và không ai trong số này được nhấn. –

+0

Ctznkane thực sự, mặc dù nó không được gọi khi sử dụng tls 1.2, nó thực sự được gọi là khi sử dụng tls 1.1 và chỉ định loại lỗi "System.Net.Security.SslPolicyErrors.RemoteCertificateChainErrors". Phương thức này trả về true, cho phép cuộc gọi trong tls 1.1 nhưng có lẽ tls 1.2 sẽ không cho phép điều này do các tiêu chuẩn bảo mật cao hơn? Đặt cược tốt nhất của tôi là để tìm hiểu lý do tại sao các lỗi chuỗi xảy ra với tls 1.1 bây giờ và sau đó sửa lỗi và thử với tls 1.2 một lần nữa. Tôi sẽ trở lại với kết quả. –

+0

Sau khi đào một ít trong các đối tượng được chứng minh cho phương thức gọi lại, tôi thấy thông báo này sâu xuống: "Chuỗi chứng chỉ được xử lý nhưng bị chấm dứt trong chứng chỉ gốc không được nhà cung cấp tin cậy tin tưởng". - Tôi sẽ đi google cho lỗi này đặc biệt. –

0

Bạn có nên chỉ định thuộc tính SslProtocols của người xử lý không?

Hãy thử thêm dòng này sau khi hander định nghĩa:

handler.SslProtocols = SslProtocols.Tls12; 
1

Bạn đang đúng vào nguyên nhân gốc rễ của vấn đề này: Theo mặc định, khách hàng SCHANNEL dựa trên cung cấp SHA1, SHA256, SHA384 và SHA512 (trên Win10/Server 2016). Vì vậy, các máy chủ TLS 1.2 không được phép gửi chứng chỉ MD5 của họ đến các máy khách này.

Máy khách (HttpClient) không liệt kê MD5 trong phần mở rộng signature_algorithms, do đó bắt tay TLS 1.2 không thành công. Việc sửa chữa là sử dụng một cert máy chủ an toàn.

Các vấn đề liên quan