วิธีแก้ปัญหา“ ไม่สามารถสร้างความสัมพันธ์ที่เชื่อถือได้สำหรับช่องทางที่ปลอดภัย SSL / TLS กับผู้มีอำนาจ”


139

จริงๆคิดว่าฉันได้แก้ไขปัญหานี้แล้ว แต่ก่อนหน้านี้มันเป็นเพียงการปลอมตัวเท่านั้น

ฉันมีบริการ WCF ที่โฮสต์ใน IIS 7 โดยใช้ HTTPS เมื่อฉันเรียกดูไซต์นี้ใน Internet Explorer มันใช้งานได้ดีนี่เป็นเพราะฉันได้เพิ่มใบรับรองไปยังที่เก็บใบรับรองหลักในเครื่อง

ฉันกำลังพัฒนาใน 1 เครื่องดังนั้นไคลเอนต์และเซิร์ฟเวอร์จึงเป็นเครื่องเดียวกัน ใบรับรองลงนามด้วยตนเองโดยตรงจากสแน็ปอินการจัดการ IIS 7

ฉันได้รับข้อผิดพลาดนี้อย่างต่อเนื่องในขณะนี้ ...

ไม่สามารถสร้างความสัมพันธ์ที่เชื่อถือได้สำหรับช่องสัญญาณที่ปลอดภัย SSL / TLS ที่มีอำนาจ

... เมื่อเรียกจากคอนโซลไคลเอนต์

ฉันเองให้ตัวเองสิทธิ์และเครือข่ายบริการกับใบรับรองที่ใช้และการใช้findprivatekeycacls.exe

ฉันพยายามเชื่อมต่อกับบริการโดยใช้ SOAPUI และใช้งานได้ดังนั้นจึงต้องมีปัญหาในแอปพลิเคชันไคลเอนต์ของฉันซึ่งเป็นรหัสตามสิ่งที่ใช้ในการทำงานกับ http

ฉันจะดูได้ที่ไหนอีกที่ดูเหมือนฉันจะหมดความเป็นไปได้ทั้งหมดว่าทำไมฉันถึงเชื่อมต่อไม่ได้



หากคุณสามารถควบคุมการสร้างใบรับรองได้อย่าลืมเกี่ยวกับ "ชื่อหัวเรื่องสำรอง" เช่นเดียวกับที่คุณใส่ไวลด์การ์ดใน "* .full.domainname.com" ดูdigicert.com/subject-alternative-name.htm
granadaCoder

คำตอบ:


199

เป็นวิธีแก้ปัญหาที่คุณสามารถเพิ่มตัวจัดการกับServicePointManager's ServerCertificateValidationCallbackบนฝั่งไคลเอ็นต์:

System.Net.ServicePointManager.ServerCertificateValidationCallback +=
    (se, cert, chain, sslerror) =>
        {
            return true;
        };

แต่โปรดทราบว่านี่ไม่ใช่แนวทางปฏิบัติที่ดีเนื่องจากจะเพิกเฉยต่อใบรับรองเซิร์ฟเวอร์โดยสิ้นเชิงและแจ้งให้ผู้จัดการจุดบริการทราบว่าใบรับรองใด ๆ ที่ใช้ได้ซึ่งอาจส่งผลต่อความปลอดภัยของไคลเอ็นต์อย่างร้ายแรง คุณสามารถปรับแต่งสิ่งนี้และทำการตรวจสอบแบบกำหนดเอง (สำหรับชื่อใบรับรองแฮช ฯลฯ ) อย่างน้อยคุณสามารถหลีกเลี่ยงปัญหาระหว่างการพัฒนาเมื่อใช้ใบรับรองการทดสอบ


9
ฉันคิดว่าการตั้งค่าสาธารณะส่วนใหญ่จะใช้ใบรับรองที่ซื้อมา แต่ในระหว่างการพัฒนาให้ใช้รหัสด้านบนภายในคำสั่งเงื่อนไข #if devs องค์กรควรโดยทั่วไปการติดตั้งเซิร์ฟเวอร์ CA ภายใน >> technet.microsoft.com/en-us/library/cc875810.aspx
ลุค Puplett

2
ช่วยฉันหาวิธีทำให้การเรียก SSL WCF ของฉันทำงานร่วมกับ Fiddler2 สำหรับการดีบัก
Roger Willcocks

2
@karank ลองใส่ลงในเมธอด Application_Start ใน Global.asax (ดูstackoverflow.com/a/12507094/1175419 ) ฉันขอแนะนำอย่างยิ่งให้ใช้คำสั่งคอมไพเลอร์ #if DEBUG หรือสิ่งที่คล้ายกันตามที่กล่าวไว้ในความคิดเห็นของลุค
Rich C

4
สุดยอด! คุณสามารถใช้ lambda expression เป็น System.Net.ServicePointManager.ServerCertificateValidationCallback + = (se, cert, chain, sslerror) => true;
Dhanuka777

ดูคำอธิบายเพิ่มเติมเล็กน้อยได้ที่นี่: blog.effectivemessaging.com/2015_09_01_archive.html
granadaCoder

41

เมื่อฉันมีปัญหานี้เป็นเพราะ client.config มีจุดสิ้นสุดเช่น:

 https://myserver/myservice.svc 

แต่ใบรับรองกำลังคาดหวัง

 https://myserver.mydomain.com/myservice.svc

การเปลี่ยนจุดสิ้นสุดให้ตรงกับ FQDN ของเซิร์ฟเวอร์ช่วยแก้ปัญหาของฉัน ฉันรู้ว่านี่ไม่ใช่สาเหตุเดียวของปัญหานี้


ฉันเพิ่งมีปัญหานี้อีกครั้งและคราวนี้ต้องใช้ใบรับรองที่ไม่ถูกต้อง ดูเหมือนว่าทั้งสองกรณีจะเกี่ยวข้องกับการจับคู่ชื่ออย่างถูกต้อง
Mike Cheel

3
การกำหนดค่าที่สร้างขึ้นโดยอัตโนมัติของฉันมี <endpoint address = " localhost / myservice.svc " เปลี่ยนเป็น <endpoint address = " mymachine.mydoman.com/myservice.svc " แก้ไขปัญหานี้ได้
knightscharge

นี่เป็นปัญหาของฉันอย่างแน่นอนและฉันใช้เวลาสองวันในการค้นหาคำตอบของคุณ +1 ฉันจะให้คุณ +1000 ถ้าทำได้
AussieJoe

20

ปัญหาของคุณเกิดขึ้นเนื่องจากคุณใช้คีย์ที่ลงนามด้วยตนเอง ไคลเอนต์ไม่เชื่อถือคีย์นี้และคีย์เองก็ไม่ได้จัดเตรียมห่วงโซ่เพื่อตรวจสอบความถูกต้องหรือรายการเพิกถอนใบรับรอง

คุณมีทางเลือกไม่กี่ทาง - คุณทำได้

  1. ปิดการตรวจสอบใบรับรองบนไคลเอนต์ (การเคลื่อนไหวที่ไม่ดีคนที่อยู่ตรงกลางมีการโจมตีมากมาย)

  2. ใช้ makecert เพื่อสร้าง CA หลักและสร้างใบรับรองจากสิ่งนั้น (ตกลงย้าย แต่ยังไม่มี CRL)

  3. สร้าง CA หลักภายในโดยใช้ Windows Certificate Server หรือโซลูชัน PKI อื่น ๆ จากนั้นวางใจใบรับรองรูทนั้น (ค่อนข้างลำบากในการจัดการ)

  4. ซื้อใบรับรอง SSL จาก CA ที่เชื่อถือได้ (ราคาแพง)


3
เกี่ยวกับ (4) StartSSLจะให้ใบรับรอง Class 1 ฟรีซึ่งใช้งานได้กับเบราว์เซอร์หลักทั้งหมด พวกเขาทำงานได้ดีสำหรับฉันสำหรับไซต์แบนด์วิดท์ต่ำครึ่งโหลของฉัน
moodboom

ฉันคิดว่า # 2 ในรายการนี้ ... url นี้อาจช่วยได้: blogs.technet.microsoft.com/jhoward/2005/02/02/… "วิธีใช้ MakeCert สำหรับผู้ออกใบรับรองหลักที่เชื่อถือได้และการออกใบรับรอง SSL"
granadaCoder

1
หมายเหตุ: StartCom ไม่น่าเชื่อถืออีกต่อไป - และเพิ่งถูกลบออกจาก Chrome en.wikipedia.org/wiki/StartCom
Simon_Weaver

20

สองตัวแรกใช้แลมด้าอันที่สามใช้รหัสปกติ ... หวังว่าจะเป็นประโยชน์

            //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 = false;
        if (cert.Subject.ToUpper().Contains("YourServerName"))
        {
            result = true;
        }

        return result;
    }

1
// เชื่อถือใบรับรองทั้งหมด System.Net.ServicePointManager.ServerCertificateValidationCallback + = (se, cert, chain, sslerror) => {return true; }; // เชื่อถือผู้ส่ง System.Net.ServicePointManager.ServerCertificateValidationCallback + = (se, cert, chain, sslerror) => {return cert.Subject.Contains ("ca-l-9wfvrm1.ceridian.ca"); };
VoodooChild

1
แครกเกอร์ใด ๆ สามารถปลอมใบรับรองที่ผ่านการทดสอบข้างต้นทั้งหมด สิ่งนี้ไม่ปลอดภัย
Bjartur Thorlacius

16

โซลูชันบรรทัดเดียว เพิ่มสิ่งนี้ที่ใดก็ได้ก่อนที่จะเรียกเซิร์ฟเวอร์ในฝั่งไคลเอ็นต์:

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

ควรใช้เพื่อวัตถุประสงค์ในการทดสอบเท่านั้นเนื่องจากไคลเอนต์จะข้ามการตรวจสอบความปลอดภัย SSL / TLS


2
วิธีแก้ปัญหาที่ยอดเยี่ยมสำหรับการทดสอบ เรากำลังใช้บริการที่ผู้ให้บริการได้ทำให้การรักษาความปลอดภัยกลายเป็นนรกที่มีชีวิตด้วยใบรับรองความปลอดภัยที่ซับซ้อนและจนกว่าเราจะได้รับใบรับรองและการผูกมัดที่ซับซ้อนเพื่อให้ทำงานได้อย่างถูกต้องวิธีแก้ปัญหานี้เป็นเพียงสิ่งเดียวที่ทำให้เราพัฒนาต่อไปได้
markaaronky

13

ฉันพบปัญหาเดียวกันและสามารถแก้ไขได้ด้วยสองวิธี: ขั้นแรกฉันใช้ "ใบรับรอง" แบบสแน็ปอิน MMC สำหรับ "บัญชีคอมพิวเตอร์" และลากใบรับรองที่ลงนามด้วยตนเองไปยังโฟลเดอร์ "Trusted Root Certification Authorities" . ซึ่งหมายความว่าคอมพิวเตอร์ในระบบ (เครื่องที่สร้างใบรับรอง) จะเชื่อถือใบรับรองนั้น ประการที่สองฉันสังเกตเห็นว่าใบรับรองถูกสร้างขึ้นสำหรับชื่อคอมพิวเตอร์ภายในบางเครื่อง แต่มีการเข้าถึงบริการเว็บโดยใช้ชื่ออื่น สิ่งนี้ทำให้เกิดความไม่ตรงกันเมื่อตรวจสอบใบรับรอง เราสร้างใบรับรองสำหรับ computer.operations.local แต่เข้าถึงบริการเว็บโดยใช้https://computer.internaldomain.companydomain.com https://computer.internaldomain.companydomain.comเมื่อเราเปลี่ยน URL เป็น URL ที่ใช้ในการสร้างใบรับรองเราก็ไม่มีข้อผิดพลาดอีกต่อไป

บางทีการเปลี่ยน URL อาจใช้งานได้ แต่การทำให้ใบรับรองเชื่อถือได้คุณยังหลีกเลี่ยงหน้าจอสีแดงใน Internet Explorer ซึ่งจะบอกคุณว่าไม่เชื่อถือใบรับรอง


สิ่งนี้ไม่ได้ผลสำหรับฉันในตอนแรก ฉันต้องทำการแก้ไขหนึ่งขั้นตอนข้างต้น: เมื่อลากใบรับรองตรวจสอบให้แน่ใจว่าได้กดปุ่ม Ctrl ค้างไว้เพื่อให้คัดลอกใบรับรองไม่ย้ายจากส่วนบุคคล / ใบรับรองไปยังผู้ออกใบรับรอง / ใบรับรองที่เชื่อถือได้
Metalogic

11

หากคุณใช้. net core ให้ลองทำดังนี้:

client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication =
        new X509ServiceCertificateAuthentication()
        {
            CertificateValidationMode = X509CertificateValidationMode.None,
            RevocationMode = System.Security.Cryptography.X509Certificates.X509RevocationMode.NoCheck
        };

1
ขอบคุณมันได้ผล แต่มันไม่มีอะไรเกี่ยวข้องกับ. net core เป็นสูตรสากล :)
Alexander

7

โปรดทำตามขั้นตอนต่อไปนี้:

  1. เปิดลิงค์บริการใน IE

  2. คลิกที่การระบุข้อผิดพลาดของใบรับรองในแถบที่อยู่และคลิกที่ดูใบรับรอง

  3. ออกเช็คให้: ชื่อ.

  4. ใช้ชื่อที่ออกและแทนที่การกล่าวถึง localhost ในบริการและชื่อที่อยู่ฐานปลายทางของไคลเอ็นต์ด้วยชื่อโดเมนแบบเต็ม (FQDN)

ตัวอย่าง: https: // localhost : 203 / SampleService.svc ถึง https: // INL-126166-.groupinfra.com : 203 / SampleService.svc


ดีมากขอบคุณสำหรับคำตอบนี้! แก้ไขปัญหาโดยไม่ต้องเปลี่ยนแปลงรหัสใด ๆ
Vipin Dubey

6

นอกเหนือจากคำตอบข้างต้นคุณอาจพบข้อผิดพลาดนี้หากไคลเอ็นต์ของคุณใช้งาน TLS เวอร์ชันที่ไม่ถูกต้องเช่นเซิร์ฟเวอร์กำลังเรียกใช้ TLS 1.2

คุณสามารถแก้ไขได้โดยใช้:

// tested in .NET 4.5:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

ในกรณีของฉันคำตอบที่ได้รับการยอมรับไม่ได้ช่วยฉัน แต่อันนี้หลอกลวง
Sergey

นี่เป็นคำตอบเดียวที่แก้ไขข้อผิดพลาดในกรณีของฉัน
Tolga

นี่เป็นเคล็ดลับที่ช่วยฉันแม้ว่าจะมี. Net 4.7.2
phifi

5

ผมมีปัญหาเหมือนกัน. ฉันได้เพิ่มใบรับรอง CA ในร้านค้าในพื้นที่แล้วด้วย แต่ฉันทำผิดวิธี

การใช้ mmc Console (Start -> Run -> mmc ) คุณควรเพิ่มใบรับรองสแน็ปอินเป็นบัญชีบริการ (เลือกบัญชีบริการของ IIS) หรือบัญชีคอมพิวเตอร์ (จะเพิ่มสำหรับทุกบัญชีในเครื่อง)

นี่คือภาพของสิ่งที่ฉันกำลังพูดถึง เพิ่มสแน็ปอินสำหรับบัญชีบริการหรือบัญชีคอมพิวเตอร์

จากที่นี่คุณสามารถเพิ่มใบรับรอง CA ( Trusted Root CAsและIntermediate CAs ) และทุกอย่างจะทำงานได้ดี


4

ฉันมีปัญหาคล้ายกันกับใบรับรองที่ลงนามด้วยตนเอง ฉันสามารถแก้ไขได้โดยใช้ชื่อใบรับรองเดียวกับ FQDN ของเซิร์ฟเวอร์

ตามหลักการแล้วควรจัดการส่วน SSL ที่ฝั่งเซิร์ฟเวอร์ ไคลเอนต์ไม่จำเป็นต้องติดตั้งใบรับรองใด ๆ สำหรับ SSL นอกจากนี้บางส่วนของโพสต์ที่กล่าวถึงเกี่ยวกับการข้าม SSL จากรหัสไคลเอนต์ แต่ฉันไม่เห็นด้วยอย่างยิ่งกับเรื่องนี้


3

ฉันเพิ่งลากใบรับรองไปไว้ในโฟลเดอร์ "Trusted Root Certification Authorities" และทุกอย่างก็ใช้ได้ดี

โอ้. และก่อนอื่นฉันได้เพิ่มสิ่งต่อไปนี้จากพรอมต์คำสั่งของผู้ดูแลระบบ:

netsh http add urlacl url=https://+:8732/Servicename user=NT-MYNDIGHET\INTERAKTIV

ฉันไม่แน่ใจในชื่อที่คุณต้องการสำหรับผู้ใช้ (ของฉันเป็นภาษานอร์เวย์อย่างที่คุณเห็น!) : user=NT-AUTHORITY/INTERACTIVE?

คุณสามารถดู urlacl ที่มีอยู่ทั้งหมดได้โดยใช้คำสั่ง: netsh http show urlacl


0

เหตุการณ์นี้เกิดขึ้นเมื่อพยายามเชื่อมต่อกับบริการ WCF ผ่าน IP เช่นhttps://111.11.111.1:port/MyService.svcในขณะที่ใช้ใบรับรองที่เชื่อมโยงกับชื่อเช่น mysite.com

เปลี่ยนเป็นhttps://mysite.com:port/MyService.svcแก้ไขแล้ว


0

สิ่งนี้เกิดขึ้นเมื่อพยายามเชื่อมต่อกับบริการ WCF โดยใช้ชื่อโฮสต์เท่านั้นเช่นhttps: //host/MyService.svcในขณะที่ใช้ใบรับรองที่เชื่อมโยงกับชื่อเช่น host.mysite.com

เปลี่ยนไปใช้https://host.mysite.com/MyService.svcและสิ่งนี้แก้ไขได้


0

เพิ่งแก้ไขปัญหาที่คล้ายกัน

ฉันรู้ว่าฉันมีกลุ่มแอปพลิเคชันที่ทำงานภายใต้บัญชีที่มีสิทธิ์ในการอ่านผ่านใบรับรองที่ใช้เท่านั้น

แอปพลิเคชัน. NET สามารถดึงใบรับรองได้อย่างถูกต้อง แต่ข้อยกเว้นนั้นเกิดขึ้นเฉพาะเมื่อเรียก GetRequestStream ()

สามารถจัดการสิทธิ์ใบรับรองผ่านคอนโซล MMC


0

หากคุณใช้. net core ระหว่างการพัฒนาคุณสามารถข้ามการตรวจสอบใบรับรองโดยใช้คำสั่งคอมไพเลอร์ วิธีนี้จะตรวจสอบใบรับรองสำหรับรีลีสเท่านั้นไม่ใช่สำหรับการดีบัก:

#if (DEBUG)
        client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication =
                new X509ServiceCertificateAuthentication()
                {
                    CertificateValidationMode = X509CertificateValidationMode.None,
                    RevocationMode = System.Security.Cryptography.X509Certificates.X509RevocationMode.NoCheck
                };   #endif

0

ฉันแค่อยากจะเพิ่มบางอย่างในคำตอบของ @NMrt ที่ชี้ให้เห็นแล้ว:

คุณอาจพบข้อผิดพลาดนี้หากไคลเอนต์ของคุณใช้ TLS เวอร์ชันที่ไม่ถูกต้องตัวอย่างเช่นหากเซิร์ฟเวอร์กำลังเรียกใช้ TLS 1.2 เท่านั้น

ด้วย Framework 4.7.2 หากคุณไม่ได้กำหนดค่ากรอบเป้าหมายอย่างชัดเจนใน web.config ของคุณเช่นนี้

<system.web>
  <compilation targetFramework="4.7" />
  <httpRuntime targetFramework="4.7" />
</system.web>

โปรโตคอลความปลอดภัยเริ่มต้นของระบบของคุณจะถูกละเว้นและอาจใช้บางอย่างที่ "ต่ำกว่า" แทน ในกรณีของฉัน Ssl3 / Tls แทนที่จะเป็น Tls13

  • คุณสามารถแก้ไขสิ่งนี้ในโค้ดได้ด้วยการตั้งค่า SecurityProtocol (ทำให้โปรโตคอลอื่นทำงาน)

    System.Net.ServicePointManager.SecurityProtocol |= System.Net.SecurityProtocolType.Tls12 | System.Net.SecurityProtocolType.Tls11;
    System.Net.ServicePointManager.SecurityProtocol &= ~System.Net.SecurityProtocolType.Ssl3;
    
  • หรือแม้กระทั่งการเพิ่มคีย์รีจิสทรีเพื่อเปิดหรือปิดการเข้ารหัสลับที่แข็งแกร่ง

    [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319]
    "SchUseStrongCrypto"=dword:00000001
    

โพสต์บล็อกนี้ชี้ให้ฉันเห็นทิศทางที่ถูกต้องและอธิบายภูมิหลังได้ดีกว่าที่ฉันทำได้:

https://www.ryadel.com/en/asp-net-client-server-cannot-comunicate-because-they-possess-common-algorithm-how-to-fix-c-sharp/


-6

เพิ่มสิ่งนี้ในรหัสลูกค้าของคุณ:

ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(
    delegate
    {
        return true;
    });

4
คำตอบนี้ไม่ค่อยดีนักเนื่องจากไม่ได้อธิบายถึงความเสี่ยงที่เกี่ยวข้องกับรหัส
daveD
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.