2012-03-25 64 views
16

Tôi đang phát triển một ứng dụng web ASP.NET gửi yêu cầu đến một máy chủ khác bằng cách sử dụng HttpWebRequest. Nó gửi yêu cầu qua HTTPS và máy chủ từ xa yêu cầu chứng chỉ ứng dụng khách. Yêu cầu không thành công trong ứng dụng .NET, dường như không thể gửi chứng chỉ ứng dụng khách chính xác. Tôi am có thể kết nối thành công và gửi chứng chỉ ứng dụng khách nếu tôi chỉ cần truy cập url bằng trình duyệt web (cụ thể là Chrome).Ứng dụng .NET không gửi chứng chỉ ứng dụng khách - Win 7 và Win XP?

Mã dưới đây là bản sao đơn giản, chỉ với yêu cầu GET cơ bản.

var r = WebRequest.Create(url) as HttpWebRequest; 
r.ClientCertificates = new X509CertificateCollection { myX509Cert }; 
using (var resp = r.GetResponse() as HttpWebResponse) { 
    ... 
} 

Tôi nhận được ngoại lệ yêu thích, "Không thể tạo kênh bảo mật SSL/TLS". Thông thường, các loại sự cố này trỏ đến các vấn đề với quyền trên khóa riêng của chứng chỉ của bạn. Tôi đã thử tất cả mọi thứ tôi có thể nghĩ đến để đảm bảo điều này là tất cả các cấu hình một cách chính xác, nhưng có lẽ tôi đã bỏ lỡ một cái gì đó. Dài câu chuyện ngắn, máy chủ từ xa đang gửi TLS CertificateRequest với danh sách có vẻ như xác định đúng chứng chỉ ứng dụng khách của tôi, nhưng sự tán thành của tôi không phản hồi với bất kỳ chứng chỉ ứng dụng khách nào.

Đây là thiết lập của tôi:

  • Windows 7 chuyên nghiệp 64 bit
  • Có khả năng tái tạo các vấn đề trong một 3/NET 4 ứng dụng ASP.NET MVC chạy trong máy chủ Studio dev Visual, ASP. Ứng dụng NET WebForms/.NET 3.5 chạy trong IIS cục bộ và trong ứng dụng .NET console/.NET 4
  • Microsoft .NET Framework 4.5 đã được cài đặt gần đây. Chưa kiểm tra nhưng liệu điều này có thể là một vấn đề

Dưới đây là tất cả những gì tôi đã cố gắng, và những gì tôi biết:

  • Mã này dường như làm việc tốt khi chạy trên một máy tính Windows XP
  • Tôi đảm bảo rằng chứng chỉ ứng dụng khách của tôi được nhập vào máy tính cục bộ, chứng chỉ cá nhân, với quyền khóa cá nhân được cấu hình đúng cho bản thân và tất cả người dùng IIS liên quan
  • Tôi đã thử cài đặt lại chứng chỉ trên máy của mình vài lần
  • Tôi đã xác nhận rằng ứng dụng .NET có thể truy cập chứng chỉ X509 và HasPrivateKey = true
  • Đảm bảo rằng chứng chỉ ứng dụng khách của tôi là hợp lệ. Đó thực sự là chứng chỉ SSL cho máy chủ web mà ứng dụng này sẽ chạy
  • Tôi đặt PreAuthenticate = true trong đối tượng yêu cầu. Không tạo sự khác biệt
  • tôi đã cố gắng thiết lập ServicePointManager.Expect100Continue = false, không tạo sự khác biệt
  • tôi đã cố gắng thiết lập ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3, nhưng dường như các máy chủ từ xa yêu cầu TLS để không giúp
  • tôi thiết lập một đại biểu ServicePointManager.ServerCertificateValidationCallback để luôn trở thành sự thật. Nhưng yêu cầu không thành công trước đó trong việc bắt tay TLS, trước khi nó được gọi tới đại biểu này
  • Khi tôi truy cập URL trong Chrome, nó yêu cầu tôi cung cấp chứng chỉ ứng dụng khách. , Tôi chọn chứng chỉ đó và tôi nhận được phản hồi hợp lệ. Cũng hoạt động đúng khi tôi xây dựng một yêu cầu trong Fiddler. Vì vậy, nó chắc chắn có vẻ là một vấn đề cụ thể với mã .NET của tôi, không phải bản thân chứng chỉ, hoặc máy chủ từ xa, v.v.
  • Nhà cung cấp mà tôi đang làm việc có cùng một dịch vụ được thiết lập trên một máy chủ từ xa khác và dịch vụ đó yêu cầu một chứng chỉ ứng dụng khách khác. Vì vậy, tôi đã cố gắng điều tương tự với địa chỉ URL và khách hàng khác nhau cert và nhận được sự thất bại cùng

tôi thêm System.Net trace và thấy điều này:

SecureChannel # 26.717.201 - Chúng tôi có giấy chứng nhận người dùng cung cấp. Máy chủ đã chỉ định 6 tổ chức phát hành. Tìm kiếm chứng chỉ phù hợp với bất kỳ tổ chức phát hành nào.

SecureChannel # 26717201 - Còn lại với 0 chứng chỉ ứng dụng khách để chọn.

...

InitializeSecurityContext (In-Buffers count = 2, Out-Buffer chiều dài = 0, trả về mã = ​​CertUnknown).

tôi kích hoạt đầy đủ SCHANNEL logging, và nhìn thấy cảnh báo này:

Các máy chủ từ xa đã yêu cầu chứng thực SSL client, nhưng không có giấy chứng nhận của khách hàng phù hợp có thể được tìm thấy. Một kết nối vô danh sẽ được cố gắng. Yêu cầu kết nối SSL này có thể thành công hoặc không thành công, tùy thuộc vào cài đặt chính sách của máy chủ.

Tôi chạy Wireshark, và thấy máy chủ từ xa đã gửi một CertificateRequest, và nó dường như có một mục Distinguished Name với O giá trị CN \ OU \ chứng nhận thân chủ tôi xác định chính xác. Sau đó, ứng dụng của tôi sẽ gửi một phản hồi Chứng chỉ mà không có chứng chỉ nào.

Có vẻ như tôi đang thiếu thứ gì đó với việc thiết lập chứng chỉ này để hoạt động đúng với các ứng dụng .NET trong Windows 7. Dự đoán tốt nhất của tôi là có gì đó khác trên máy Windows 7 mới của tôi, so với máy XP, đang gây ra lỗi này ngay bây giờ. Tôi không có quyền truy cập vào môi trường Windows XP vào lúc này để xác nhận điều này; Tôi sẽ trong một vài ngày nhưng thực sự muốn giải quyết ASAP này.

Bất kỳ ý tưởng nào cũng sẽ được đánh giá cao. Cảm ơn!

EDIT Như được mô tả ở trên, khi kết nối với URL trong Chrome, trình duyệt yêu cầu tôi cấp chứng chỉ ứng dụng và tôi có thể cung cấp chứng chỉ chính xác và kết nối thành công. Tuy nhiên, tôi không thể làm điều này thành công trong Internet Explorer (9). Tôi chỉ đơn giản là có được "Internet Explorer không thể hiển thị trang web", không có lời nhắc hoặc giải thích khác. Tôi đã nói rằng điều này có thể có liên quan như WebRequest.Create có hành vi tương tự như IE. Tôi đang xem xét điều này có ý nghĩa gì, nhưng sẽ đánh giá cao bất kỳ suy nghĩ nào về điều này.

EDIT Ngoài ra, tôi nên lưu ý rằng máy chủ từ xa sử dụng chứng chỉ SSL tự ký. Ban đầu tôi nghĩ rằng đó có thể là vấn đề, vì vậy tôi đã thêm cert làm một thư mục gốc đáng tin cậy trong MMC để chứng chỉ xuất hiện hợp lệ trên máy của tôi. Điều này không khắc phục được vấn đề.

+1

Chứng chỉ có bao gồm phần mở rộng Sử dụng khóa nâng cao "Xác thực ứng dụng khách (1.3.6.1.5.5.7.3.2)" không? Nếu không, nó có thể là Chrome là nghịch ngợm trong việc cho phép nó được lựa chọn. –

+0

Hóa ra là chứng chỉ ứng dụng khách không có tiện ích mở rộng Sử dụng khóa nâng cao này. Tôi khá chắc chắn mã này đã hoạt động chính xác trong quá khứ khi nó được trỏ đến một URL từ xa khác và chứng chỉ ứng dụng khách khác, mặc dù chứng chỉ ứng dụng khách đó không có quyền sử dụng khóa nâng cao Xác thực ứng dụng khách. Điều này mang lại cho tôi một con đường để điều tra mặc dù, cảm ơn. –

+0

Thực ra Damien, tôi đã sai - tất cả các chứng chỉ này đều bao gồm phần mở rộng sử dụng khóa nâng cao xác thực ứng dụng khách. –

Trả lời

8

Điều này hóa ra là một vấn đề khá đơn giản, nhưng thật khó để phát hiện ra. Máy chủ từ xa mà ứng dụng của tôi có chứng chỉ ứng dụng khách của tôi trong kho khóa của nó, nhưng không phải bất kỳ chứng chỉ gốc nào trong chuỗi tin cậy của chứng chỉ ứng dụng khách của tôi.

Tôi đã có thể sử dụng mã của mình để gửi thành công yêu cầu đến một máy chủ khác yêu cầu chứng chỉ ứng dụng khách.Tôi đã chụp trong Wireshark trong khi gửi yêu cầu thành công này, và cũng đã chụp trong khi gửi yêu cầu không thành công đến máy chủ khác. Trong Wireshark capture, tôi tìm thấy "Server Hello" và so sánh các tin nhắn được gửi từ các máy chủ từ xa. Máy chủ từ xa "tốt" cũng đã gửi chứng chỉ ứng dụng khách của tôi và cũng cũng chứng chỉ gốc của nó trong phần "Yêu cầu chứng chỉ" của thông báo đó. Máy chủ từ xa "xấu" chỉ gửi chứng chỉ ứng dụng khách của tôi.

Điều này nhắc tôi rằng dấu vết chẩn đoán System.Net đã đọc "Máy chủ đã chỉ định 6 tổ chức phát hành ... Còn lại với 0 chứng chỉ ứng dụng khách để chọn". Vì vậy, nó chỉ ra rằng "tổ chức phát hành" là thuật ngữ quan trọng ở đây. Thật dễ dàng để bỏ qua ban đầu vì trong phân tích ban đầu của tôi về bắt tay TLS, máy chủ đã gửi chứng chỉ ứng dụng khách của tôi trong Yêu cầu chứng chỉ. Trong nhận thức muộn, có nghĩa là máy chủ phải gửi chứng chỉ gốc của bạn chứ không phải chính chứng chỉ ứng dụng khách của bạn.

+5

Bạn có thể giúp làm rõ những gì bạn đã làm để giải quyết vấn đề này? Tôi đang sử dụng chứng chỉ tự ký và chỉ sử dụng các thông tin sau để xác thực chứng chỉ: ServicePointManager.ServerCertificateValidationCallback = delegate (đối tượng s, X509Giấy chứng nhận chứng nhận, X509Chuỗi chuỗi, SslPolicyErrors sslPolicyErrors) {return true; }; Máy chủ của tôi đã cập nhật thành .net 4.5 và giờ đây dịch vụ của tôi trả về lỗi sau "Không thể tạo kênh bảo mật SSL/TLS" – Watson

+0

Điều này cũng giải quyết được sự cố của tôi. Tôi mất cả 2 tuần để tìm ra điều này. Máy chủ từ xa chỉ gửi chứng chỉ ứng dụng khách, không bao gồm chứng chỉ gốc RSA CA. Khi tôi đọc câu trả lời này và đề xuất giải pháp bao gồm chứng chỉ gốc RSA CA trên bắt tay "yêu cầu chứng chỉ", nó đã giải quyết được vấn đề. Cảm ơn bạn!!! – vampire203

7

Tôi muốn thêm một "giải pháp" khác cho sự cố.

Máy chủ không thể gửi danh sách nhà cung cấp chính xác nếu danh sách đó quá dài. Điều này có vẻ là một hạn chế của Microsoft. http://support.microsoft.com/kb/933430

Nguồn: http://netsekure.org/2011/04/tls-client-authentication-and-trusted-issuers-list/

Giải pháp là yêu cầu máy chủ không gửi danh sách ở tất cả. (Bằng cách chỉnh sửa một giá trị registry)

HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Control \ SecurityProviders \ SCHANNEL

Tên giá trị: SendTrustedIssuerList loại Value: REG_DWORD Value data: 0 (False)

0

Đối với tôi, những triệu chứng chính xác này đã được gây ra bằng cách sử dụng TLS 1.0, mà máy chủ không cho phép. Điều này có thể được tìm thấy trong các dấu vết các bản ghi như vậy:

System.Net Thông tin: 0: ProcessAuthentication (Nghị định thư = TLS, Cipher = TripleDES 168 chút sức mạnh, Hash = SHA1 160 chút sức mạnh, chính Trao đổi = RsaKeyX cường độ bit 2048).

TLS 1.0 là mặc định cho .NET 4.5, nhưng nó có thể được ghi đè bằng cách thiết lập:

ServicePointManager.SecurityProtocol = 
    SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; 

Ngoài ra còn có some registry flags cho phép thiết lập này mà không thay đổi mã hiện tại.

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