การแจ้งเตือนการจับมือ SSL: ข้อผิดพลาดที่ไม่รู้จักตั้งแต่อัพเกรดเป็น Java 1.7.0


225

ฉันอัพเกรดจาก Java 1.6 เป็น Java 1.7 วันนี้ ตั้งแต่นั้นเกิดข้อผิดพลาดเมื่อฉันพยายามสร้างการเชื่อมต่อกับเว็บเซิร์ฟเวอร์ของฉันผ่าน SSL:

javax.net.ssl.SSLProtocolException: handshake alert:  unrecognized_name
    at sun.security.ssl.ClientHandshaker.handshakeAlert(ClientHandshaker.java:1288)
    at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1904)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1027)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1262)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1289)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1273)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:523)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1296)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
    at java.net.URL.openStream(URL.java:1035)

นี่คือรหัส:

SAXBuilder builder = new SAXBuilder();
Document document = null;

try {
    url = new URL(https://some url);
    document = (Document) builder.build(url.openStream());
} catch (NoSuchAlgorithmException ex) {
    Logger.getLogger(DownloadLoadiciousComputer.class.getName()).log(Level.SEVERE, null, ex);  
}

เป็นเพียงโครงการทดสอบที่ทำให้ฉันอนุญาตและใช้ใบรับรองที่ไม่น่าเชื่อถือด้วยรหัส:

TrustManager[] trustAllCerts = new TrustManager[]{
    new X509TrustManager() {

        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return null;
        }

        public void checkClientTrusted(
                java.security.cert.X509Certificate[] certs, String authType) {
        }

        public void checkServerTrusted(
                java.security.cert.X509Certificate[] certs, String authType) {
        }
    }
};

try {

    SSLContext sc = SSLContext.getInstance("SSL");
    sc.init(null, trustAllCerts, new java.security.SecureRandom());
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {

    Logger.getLogger(DownloadManager.class.getName()).log(Level.SEVERE, null, e);
} 

ฉันพยายามเชื่อมต่อกับhttps://google.comสำเร็จแล้ว ความผิดของฉันอยู่ที่ไหน

ขอบคุณ

คำตอบ:


304

Java 7 แนะนำการสนับสนุน SNI ซึ่งเปิดใช้งานโดยค่าเริ่มต้น ฉันพบว่าเซิร์ฟเวอร์ที่กำหนดค่าผิดพลาดบางอย่างส่งคำเตือน "ชื่อที่ไม่รู้จัก" ในการจับมือ SSL ซึ่งไคลเอ็นต์ส่วนใหญ่จะไม่สนใจ ... ยกเว้น Java ดังที่@Bob Kernsพูดถึงวิศวกรของ Oracle ปฏิเสธที่จะ "แก้ไข" ข้อผิดพลาด / คุณสมบัตินี้

พวกเขาแนะนำให้ตั้งค่าjsse.enableSNIExtensionคุณสมบัติเป็นวิธีแก้ปัญหา หากต้องการอนุญาตให้โปรแกรมของคุณทำงานโดยไม่ต้องรวบรวมใหม่ให้เรียกใช้แอปของคุณเป็น:

java -Djsse.enableSNIExtension=false yourClass

โรงแรมแห่งนี้ยังสามารถตั้งค่าในรหัส Java แต่มันจะต้องตั้งค่าก่อนที่จะดำเนินการใด ๆ SSL เมื่อห้องสมุด SSL ที่มีการโหลดคุณสามารถเปลี่ยนสถานที่ แต่มันจะไม่ได้มีผลกระทบใด ๆกับสถานะ SNI หากต้องการปิดใช้งาน SNI บนรันไทม์ (ด้วยข้อ จำกัด ข้างต้น) ให้ใช้:

System.setProperty("jsse.enableSNIExtension", "false");

ข้อเสียของการตั้งค่าสถานะนี้คือ SNI ถูกปิดใช้งานทุกที่ในแอปพลิเคชัน เพื่อใช้ประโยชน์จาก SNI และยังคงสนับสนุนเซิร์ฟเวอร์ที่กำหนดค่าผิดพลาด:

  1. สร้าง a SSLSocketด้วยชื่อโฮสต์ที่คุณต้องการเชื่อมต่อ เรามาตั้งชื่อsslsockกัน
  2. sslsock.startHandshake()พยายามที่จะเรียก การดำเนินการนี้จะบล็อกจนกว่าจะเสร็จสิ้นหรือส่งข้อผิดพลาดเกิดขึ้น เมื่อใดก็ตามที่เกิดข้อผิดพลาดstartHandshake()ให้รับข้อความข้อยกเว้น หากเท่ากับhandshake alert: unrecognized_nameคุณจะพบเซิร์ฟเวอร์ที่กำหนดค่าผิดพลาด
  3. เมื่อคุณได้รับคำunrecognized_nameเตือน (ร้ายแรงใน Java) ให้ลองเปิดอีกครั้งSSLSocketแต่คราวนี้ไม่มีชื่อโฮสต์ ซึ่งจะเป็นการปิดการใช้งาน SNI ได้อย่างมีประสิทธิภาพ (หลังจากนั้นส่วนขยาย SNI นั้นเกี่ยวกับการเพิ่มชื่อโฮสต์ไปยังข้อความ ClientHello)

สำหรับพร็อกซี Webscarab SSL การกระทำนี้ใช้การตั้งค่าทางเลือก


5
มันได้ผลขอบคุณ! ไคลเอ็นต์การโค่นล้ม IntelliJ IDEA มีข้อผิดพลาดเดียวกันเมื่อเชื่อมต่อผ่าน HTTPS เพียงแค่ต้องอัปเดตไฟล์ idea.exe.vmoptions ด้วยบรรทัด: -Djsse.enableSNIExtension = false
Dima

2
สำหรับ Java webstart ให้ใช้สิ่งนี้: javaws -J-Djsse.enableSNIExtension = false yourClass
Torsten

ฉันมีปัญหาเดียวกันกับไคลเอนต์ Jersey ของฉันด้วยเซิร์ฟเวอร์ส่วนที่เหลือ https ปรากฎว่าฉันใช้เคล็ดลับของคุณและใช้งานได้ !! ขอบคุณ!
shahshi15

4
สำหรับผู้ที่สงสัยเกี่ยวกับ Java 8, Oracle ยังไม่ได้เปลี่ยนพฤติกรรมและยังต้องการให้โปรแกรมเมอร์จับเซิร์ฟเวอร์ที่ไม่สนับสนุน (อย่างเหมาะสม) SNI: docs.oracle.com/javase/8/docs/technotes/guides/security/jsse / …
Lekensteyn

2
@Blauhirn ติดต่อฝ่ายสนับสนุนเว็บโฮสต์ของคุณพวกเขาควรแก้ไขการกำหนดค่าของพวกเขา หากพวกเขาใช้ Apache ให้ดูการเปลี่ยนแปลงบางอย่างที่ต้องทำ
Lekensteyn

89

ฉันมีสิ่งที่ฉันเชื่อว่าปัญหาเดียวกันคือ ฉันพบว่าฉันต้องการปรับการตั้งค่า Apache เพื่อรวม ServerName หรือ ServerAlias ​​สำหรับโฮสต์

รหัสนี้ล้มเหลว:

public class a {
   public static void main(String [] a) throws Exception {
      java.net.URLConnection c = new java.net.URL("https://mydomain.com/").openConnection();
      c.setDoOutput(true);
      c.getOutputStream();
   }
}

และรหัสนี้ทำงาน:

public class a {
   public static void main(String [] a) throws Exception {
      java.net.URLConnection c = new java.net.URL("https://google.com/").openConnection();
      c.setDoOutput(true);
      c.getOutputStream();
   }
}

Wireshark เปิดเผยว่าในช่วง TSL / SSL สวัสดีเตือนการแจ้งเตือน (ระดับ: คำเตือน, คำอธิบาย: ชื่อที่ไม่รู้จัก), สวัสดีเซิร์ฟเวอร์ถูกส่งจากเซิร์ฟเวอร์ไปยังลูกค้า มันเป็นเพียงคำเตือน แต่ Java 7.1 นั้นตอบกลับทันทีด้วย "ร้ายแรง, คำอธิบาย: ข้อความที่ไม่คาดคิด" ซึ่งฉันถือว่าหมายความว่าไลบรารี Java SSL ไม่ต้องการเห็นคำเตือนของชื่อที่ไม่รู้จัก

จาก Wiki บน Transport Layer Security (TLS):

112 คำเตือนชื่อที่ไม่รู้จัก TLS เท่านั้น ตัวบ่งชี้ชื่อเซิร์ฟเวอร์ของไคลเอ็นต์ระบุชื่อโฮสต์ที่เซิร์ฟเวอร์ไม่รองรับ

นี่ทำให้ฉันดูไฟล์ config ของ Apache และพบว่าถ้าฉันเพิ่ม ServerName หรือ ServerAlias ​​สำหรับชื่อที่ส่งจากฝั่งไคลเอ็นต์ / java มันทำงานได้อย่างถูกต้องโดยไม่มีข้อผิดพลาดใด ๆ

<VirtualHost mydomain.com:443>
  ServerName mydomain.com
  ServerAlias www.mydomain.com

3
นี่ดูเหมือนข้อบกพร่องในการนำ TLS ไปใช้ของ Java
Paŭlo Ebermann

1
ฉันเปิด Bug สำหรับเรื่องนี้ ฉันได้รับหมายเลขนี้แล้ว (ยังไม่ปรากฏให้เห็น): bugs.sun.com/bugdatabase/view_bug.do?bug_id=7127374
eckes

1
ขอบคุณการเพิ่มServerAliasงานให้ฉัน ฉันเคยเห็น TLS Alert ตัวเดียวกันใน Wireshark
Jared Beck

2
สิ่งนี้ได้ผลกับฉันเช่นกัน (จะทำงานได้ดีขึ้นถ้าฉันเชื่อและไม่ไปตามเส้นทางอื่น)
ผู้ใช้ปลายทาง

10
@JosephShraibman บอกว่าพนักงาน Oracle เป็นคนงี่เง่าไม่เหมาะสม เมื่อคุณใช้สองServerNames, Apache ตอบสนองกับunrecognized_name คำเตือนการแจ้งเตือน (ซึ่งอาจจะเป็นอันตรายถึงชีวิตการแจ้งเตือน) RFC 6066พูดอย่างนี้ในหัวข้อนี้: " ไม่แนะนำให้ส่งการเตือนระดับ unrecognized_name (112) การแจ้งเตือนเนื่องจากพฤติกรรมของลูกค้าในการตอบสนองต่อการเตือนระดับการเตือนนั้นไม่สามารถคาดเดาได้ " ความผิดพลาดเพียงอย่างเดียวของพนักงานนี้คือการสันนิษฐานว่านี่เป็นการแจ้งเตือนที่ร้ายแรง นี่เป็นข้อผิดพลาด JRE มากเท่ากับ Apache หนึ่ง
บรูโน่

36

คุณสามารถปิดใช้งานการส่งระเบียน SNI ด้วยคุณสมบัติระบบ jsse.enableSNIExtension = false

หากคุณสามารถเปลี่ยนรหัสได้จะช่วยให้ใช้งานได้SSLCocketFactory#createSocket()(โดยไม่มีพารามิเตอร์โฮสต์หรือด้วยซ็อกเก็ตที่เชื่อมต่อ) ในกรณีนี้มันจะไม่ส่งการบ่งชี้ server_name


11
ซึ่งทำเช่นนี้:System.setProperty ("jsse.enableSNIExtension", "false");
jn1kk

ฉันพบว่ามันไม่ได้ผลเสมอไป ฉันไม่รู้ว่าทำไมมันถึงใช้ได้ในบางกรณี
โจเซฟ Shraibman

2
-Djsse.enableSNIExtension=falseทำงานให้ฉันด้วย แต่มันทำอะไรได้อีก? มันเป็นอันตรายสำหรับส่วนที่เหลือของการรักษาความปลอดภัย Javas?
ceving

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

17

นอกจากนี้เรายังพบข้อผิดพลาดนี้ในการสร้างเซิร์ฟเวอร์ Apache ใหม่

การแก้ไขในกรณีของเราคือกำหนด a ServerAliasในhttpd.confที่ตรงกับชื่อโฮสต์ที่ Java พยายามเชื่อมต่อ เราServerNameถูกตั้งค่าเป็นชื่อโฮสต์ภายใน ใบรับรอง SSL ของเรากำลังใช้ชื่อโฮสต์ภายนอก แต่ไม่เพียงพอที่จะหลีกเลี่ยงคำเตือน

เพื่อช่วยในการแก้ปัญหาคุณสามารถใช้คำสั่ง ssl นี้:

openssl s_client -servername <hostname> -connect <hostname>:443 -state

หากมีปัญหากับชื่อโฮสต์นั้นมันจะพิมพ์ข้อความนี้ใกล้ด้านบนของผลลัพธ์:

SSL3 alert read: warning:unrecognized name

ฉันควรทราบด้วยว่าเราไม่ได้รับข้อผิดพลาดนั้นเมื่อใช้คำสั่งนั้นเพื่อเชื่อมต่อกับชื่อโฮสต์ภายในแม้ว่าจะไม่ตรงกับใบรับรอง SSL


6
ขอขอบคุณที่รวมตัวอย่างเกี่ยวกับวิธีการทำให้เกิดปัญหาopensslอีกครั้งโดยใช้ มันมีประโยชน์มาก
sideshowbarker

2
มีวิธีใดที่ไคลเอ็นต์ openssl จะเห็นความแตกต่างของชื่อที่มาจากข้อความSSL3 alert read: warning:unrecognized nameหรือไม่? ฉันเห็นการแจ้งเตือนที่พิมพ์ออกมา แต่ผลลัพธ์ไม่ได้ช่วยให้ฉันเห็นความแตกต่างของการตั้งชื่อได้
จริงๆ

มันไม่ได้ผลสำหรับฉัน ทดสอบกับOpenSSL 1.0.1e-fips 11 Feb 2013, และOpenSSL 1.0.2k-fips 26 Jan 2017 LibreSSL 2.6.5
Greg Dubicki

15

แทนที่จะอาศัยกลไกโฮสต์เสมือนที่เป็นค่าเริ่มต้นใน apache คุณสามารถกำหนด virtualhost catchall สุดท้ายที่ใช้ ServerName โดยพลการและ ServerAlias ​​สัญลักษณ์แทนเช่น

ServerName catchall.mydomain.com
ServerAlias *.mydomain.com

ด้วยวิธีนี้คุณสามารถใช้ SNI และ apache จะไม่ส่งคำเตือน SSL กลับมา

แน่นอนว่าจะใช้งานได้หากคุณสามารถอธิบายโดเมนทั้งหมดของคุณได้อย่างง่ายดายโดยใช้ไวยากรณ์ไวด์การ์ด


เท่าที่ฉันเข้าใจ apache ส่งคำเตือนนี้เฉพาะในกรณีที่ลูกค้าใช้ชื่อที่ไม่ได้กำหนดค่าเป็น ServerName หรือ ServerAlias ดังนั้นหากคุณมีใบรับรองไวด์การ์ดให้ระบุโดเมนย่อยที่ใช้ทั้งหมดหรือใช้*.mydomain.comไวยากรณ์สำหรับ ServerAlias หมายเหตุที่คุณสามารถเพิ่มชื่อแทนหลายคนโดยใช้เช่นServerAlias ServerAlias *.mydomain.com mydomain.com *.myotherdomain.com
Michael Paesold

13

มันควรจะมีประโยชน์ หากต้องการลองข้อผิดพลาด SNI อีกครั้งใน Apache HttpClient 4.4 - วิธีที่ง่ายที่สุดที่เราคิด (ดูHTTPCLIENT-1522 ):

public class SniHttpClientConnectionOperator extends DefaultHttpClientConnectionOperator {

    public SniHttpClientConnectionOperator(Lookup<ConnectionSocketFactory> socketFactoryRegistry) {
        super(socketFactoryRegistry, null, null);
    }

    @Override
    public void connect(
            final ManagedHttpClientConnection conn,
            final HttpHost host,
            final InetSocketAddress localAddress,
            final int connectTimeout,
            final SocketConfig socketConfig,
            final HttpContext context) throws IOException {
        try {
            super.connect(conn, host, localAddress, connectTimeout, socketConfig, context);
        } catch (SSLProtocolException e) {
            Boolean enableSniValue = (Boolean) context.getAttribute(SniSSLSocketFactory.ENABLE_SNI);
            boolean enableSni = enableSniValue == null || enableSniValue;
            if (enableSni && e.getMessage() != null && e.getMessage().equals("handshake alert:  unrecognized_name")) {
                TimesLoggers.httpworker.warn("Server received saw wrong SNI host, retrying without SNI");
                context.setAttribute(SniSSLSocketFactory.ENABLE_SNI, false);
                super.connect(conn, host, localAddress, connectTimeout, socketConfig, context);
            } else {
                throw e;
            }
        }
    }
}

และ

public class SniSSLSocketFactory extends SSLConnectionSocketFactory {

    public static final String ENABLE_SNI = "__enable_sni__";

    /*
     * Implement any constructor you need for your particular application -
     * SSLConnectionSocketFactory has many variants
     */
    public SniSSLSocketFactory(final SSLContext sslContext, final HostnameVerifier verifier) {
        super(sslContext, verifier);
    }

    @Override
    public Socket createLayeredSocket(
            final Socket socket,
            final String target,
            final int port,
            final HttpContext context) throws IOException {
        Boolean enableSniValue = (Boolean) context.getAttribute(ENABLE_SNI);
        boolean enableSni = enableSniValue == null || enableSniValue;
        return super.createLayeredSocket(socket, enableSni ? target : "", port, context);
    }
}

และ

cm = new PoolingHttpClientConnectionManager(new SniHttpClientConnectionOperator(socketFactoryRegistry), null, -1, TimeUnit.MILLISECONDS);

ถ้าคุณทำแบบนี้ คุณจะทำอย่างไรจัดการกับverifyHostname(sslsock, target)ในSSLConnectionSocketFactory.createLayeredSocket? ตั้งแต่targetเปลี่ยนเป็นสตริงว่างverifyHostnameจะไม่ประสบความสำเร็จ ฉันขาดอะไรบางอย่างชัดเจนที่นี่?
Haozhun

2
นี่คือสิ่งที่ฉันกำลังมองหาขอบคุณมาก! ฉันไม่พบวิธีอื่นใดที่จะสนับสนุน SNI และเซิร์ฟเวอร์ที่ตอบสนองด้วยคำเตือน "unrecognized_name" นี้ในเวลาเดียวกัน
korpe

โซลูชันนี้ใช้งานได้เว้นแต่ว่าคุณกำลังใช้พร็อกซีเซิร์ฟเวอร์
mrog

หลังจากเพิ่งทำการดีบักอย่างรวดเร็วผ่านรหัสไคลเอนต์ Apache เริ่มต้นด้วย VerifyHostname () ฉันไม่สามารถดูวิธีการนี้สามารถทำงานได้โดยใช้ DefaultHostnameVerifier ฉันสงสัยว่าโซลูชันนี้จะต้องปิดใช้งานการตรวจสอบชื่อโฮสต์ (เช่นใช้ NoopHostnameVerifier) ​​ซึ่งไม่ใช่ความคิดที่ดีเพราะจะช่วยให้การโจมตีแบบ Man-in-the-middle
FlyingSheep


6

แก้ไขปัญหานี้ด้วยสปริงบูตและ jvm 1.7 และ 1.8 บน AWS เราไม่มีตัวเลือกในการเปลี่ยน ServerName และ ServerAlias ​​ให้ตรงกัน (ต่างกัน) ดังนั้นเราจึงทำสิ่งต่อไปนี้:

ในbuild.gradleเราได้เพิ่มสิ่งต่อไปนี้:

System.setProperty("jsse.enableSNIExtension", "false")
bootRun.systemProperties = System.properties

ที่ทำให้เราสามารถหลีกเลี่ยงปัญหาด้วย "ชื่อที่ไม่รู้จัก"


5

คุณไม่สามารถจัดหาคุณสมบัติของระบบให้กับเครื่องมือ jarsigner.exe ได้

ฉันส่งข้อบกพร่อง7177232แล้วการอ้างอิงข้อบกพร่อง@eckes ' 7127374และอธิบายว่าทำไมข้อผิดพลาดนี้ถึงปิดลง

ข้อบกพร่องของฉันเกี่ยวกับผลกระทบต่อเครื่องมือ jarsigner โดยเฉพาะ แต่อาจทำให้พวกเขาเปิดข้อบกพร่องอื่นอีกครั้งและแก้ไขปัญหาได้อย่างเหมาะสม

UPDATE:จริง ๆ แล้วปรากฎว่าคุณสามารถจัดหาคุณสมบัติของระบบให้กับเครื่องมือ Jarsigner ได้ แต่มันไม่ได้อยู่ในข้อความช่วยเหลือ ใช้jarsigner -J-Djsse.enableSNIExtension=false


1
ขอบคุณ Bob สำหรับการติดตาม น่าเศร้าที่ Oracle ยังไม่เข้าใจสิ่งทั้งหมด การแจ้งเตือนของ SNI นั้นไม่ได้เป็นเรื่องที่ร้ายแรง แต่ไคลเอนต์ SSL ทั่วไปส่วนใหญ่ (เช่นเบราว์เซอร์) เลือกที่จะเพิกเฉยเนื่องจากไม่ใช่ปัญหาด้านความปลอดภัยที่แท้จริง (เพราะคุณยังต้องตรวจสอบใบรับรองเซิร์ฟเวอร์และจะตรวจสอบจุดสิ้นสุดผิด) แน่นอนว่าเป็นเรื่องที่ CA ไม่สามารถตั้งค่าได้ ตั้งค่าเซิร์ฟเวอร์ https ที่กำหนดค่าอย่างเหมาะสม
eckes

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

BTW: ขณะนี้ฉันกำลังพูดถึงปัญหานี้ใน security-dev @ openjdk และในขณะที่ฉันกำลังประเมินดูเหมือนว่า Symantec จะแก้ไขเซิร์ฟเวอร์การประทับเวลา GEOTrust ตอนนี้ยอมรับ URL อย่างถูกต้องโดยไม่มีการเตือนล่วงหน้า แต่ฉันก็ยังคิดว่าควรจะแก้ไข ถ้าคุณต้องการที่จะมีรูปลักษณ์เป็นลูกค้าทดสอบโครงการและการอภิปราย :
Eckes

3

ฉันพบปัญหาเดียวกันและปรากฎว่า reverse DNS ไม่ได้ตั้งค่าที่ถูกต้องมันชี้ไปที่ชื่อโฮสต์ที่ไม่ถูกต้องสำหรับ IP หลังจากที่ฉันแก้ไข reverse DNS และรีสตาร์ท httpd คำเตือนจะหายไป (ถ้าฉันไม่แก้ไข DNS ย้อนกลับการเพิ่ม ServerName ก็เป็นการหลอกลวงสำหรับฉันเช่นกัน)


2

ของฉันVirtualHost's ServerNameได้รับการออกความเห็นโดยค่าเริ่มต้น มันทำงานหลังจากที่ไม่แสดงความคิดเห็น


กันที่นี่ ไม่มีชื่อเซิร์ฟเวอร์
ดาร์กสตาร์ 1

2

หากคุณกำลังสร้างไคลเอนต์ด้วย Resttemplate คุณสามารถตั้งค่าจุดสิ้นสุดได้ดังนี้: https: // IP / path_to_serviceและตั้ง requestFactory
ด้วยวิธีนี้คุณไม่จำเป็นต้องรีสตาร์ท TOMCAT หรือ Apache ของคุณ:

public static HttpComponentsClientHttpRequestFactory requestFactory(CloseableHttpClient httpClient) {
    TrustStrategy acceptingTrustStrategy = new TrustStrategy() {
        @Override
        public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            return true;
        }
    };

    SSLContext sslContext = null;
    try {
        sslContext = org.apache.http.ssl.SSLContexts.custom()
                .loadTrustMaterial(null, acceptingTrustStrategy)
                .build();
    } catch (Exception e) {
        logger.error(e.getMessage(), e);
    }   

    HostnameVerifier hostnameVerifier = new HostnameVerifier() {
        @Override
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    };

    final SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext,hostnameVerifier);

    final Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
            .register("http", new PlainConnectionSocketFactory())
            .register("https", csf)
            .build();

    final PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
    cm.setMaxTotal(100);
    httpClient = HttpClients.custom()
            .setSSLSocketFactory(csf)
            .setConnectionManager(cm)
            .build();

    HttpComponentsClientHttpRequestFactory requestFactory =
            new HttpComponentsClientHttpRequestFactory();

    requestFactory.setHttpClient(httpClient);

    return requestFactory;
}

1

ฉันเจอปัญหานี้แล้วในขณะที่อัพเกรดจาก Java 1.6_29 เป็น 1.7

น่าตกใจที่ลูกค้าของฉันค้นพบการตั้งค่าในแผงควบคุม Java ซึ่งแก้ไขปัญหานี้

ในแท็บขั้นสูงคุณสามารถตรวจสอบ 'ใช้รูปแบบ ClientHello ที่รองรับ SSL 2.0'

ดูเหมือนว่าจะแก้ไขปัญหาได้

เรากำลังใช้ Java applets ในเบราว์เซอร์ Internet Explorer

หวังว่านี่จะช่วยได้


0

ฉันมีปัญหาเดียวกันกับเซิร์ฟเวอร์ Ubuntu Linux ที่ใช้การโค่นล้มเมื่อเข้าถึงผ่าน Eclipse

มันแสดงให้เห็นว่าปัญหาเกี่ยวข้องกับการเตือนเมื่อ Apache (ใหม่) เริ่มต้น:

[Mon Jun 30 22:27:10 2014] [warn] NameVirtualHost *:80 has no VirtualHosts

... waiting [Mon Jun 30 22:27:11 2014] [warn] NameVirtualHost *:80 has no VirtualHosts

นี้ได้รับเนื่องจากรายการใหม่ในports.confที่อื่นสั่งถูกป้อนควบคู่ไปกับคำสั่งในNameVirtualHostsites-enabled/000-default

หลังจากลบคำสั่งports.confแล้วปัญหาก็หายไป (หลังจากรีสตาร์ท Apache ตามปกติ)


0

เพียงเพิ่มโซลูชันที่นี่ นี่อาจเป็นประโยชน์สำหรับผู้ใช้ LAMP

Options +FollowSymLinks -SymLinksIfOwnerMatch

บรรทัดที่กล่าวถึงข้างต้นในการกำหนดค่าโฮสต์เสมือนคือผู้ร้าย

การกำหนดค่าโฮสต์เสมือนเมื่อเกิดข้อผิดพลาด

<VirtualHost *:80>
    DocumentRoot /var/www/html/load/web
    ServerName dev.load.com
    <Directory "/var/www/html/load/web">
        Options +FollowSymLinks -SymLinksIfOwnerMatch
        AllowOverride All
        Require all granted
        Order Allow,Deny
        Allow from All
    </Directory>
     RewriteEngine on
     RewriteCond %{SERVER_PORT} !^443$
     RewriteRule ^/(.*) https://%{HTTP_HOST}/$1 [NC,R=301,L]
</VirtualHost>

การกำหนดค่าการทำงาน

<VirtualHost *:80>
    DocumentRoot /var/www/html/load/web

   ServerName dev.load.com
   <Directory "/var/www/html/load/web">

        AllowOverride All

        Options All

        Order Allow,Deny

        Allow from All

    </Directory>

    # To allow authorization header
    RewriteEngine On
    RewriteCond %{HTTP:Authorization} ^(.*)
    RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]

   # RewriteCond %{SERVER_PORT} !^443$
   # RewriteRule ^/(.*) https://%{HTTP_HOST}/$1 [NC,R=301,L]


</VirtualHost>

0

นี่คือวิธีแก้ปัญหาสำหรับ Appache httpclient 4.5.11 *.hostname.comฉันมีปัญหากับใบรับรองที่มีสัญลักษณ์แทนเรื่อง มันทำให้ฉันมีข้อยกเว้นเหมือนกัน แต่ฉันไม่ได้ใช้การปิดใช้งานโดยคุณสมบัติSystem.setProperty("jsse.enableSNIExtension", "false");เนื่องจากมันทำให้เกิดข้อผิดพลาดในไคลเอนต์ตำแหน่ง Google

ฉันพบวิธีแก้ไขง่ายๆ

import io.micronaut.context.annotation.Bean;
import io.micronaut.context.annotation.Factory;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;

import javax.inject.Named;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLSocket;
import java.io.IOException;
import java.util.List;

@Factory
public class BeanFactory {

    @Bean
    @Named("without_verify")
    public HttpClient provideHttpClient() {
        SSLConnectionSocketFactory connectionSocketFactory = new SSLConnectionSocketFactory(SSLContexts.createDefault(), NoopHostnameVerifier.INSTANCE) {
            @Override
            protected void prepareSocket(SSLSocket socket) throws IOException {
                SSLParameters parameters = socket.getSSLParameters();
                parameters.setServerNames(List.of());
                socket.setSSLParameters(parameters);
                super.prepareSocket(socket);
            }
        };

        return HttpClients.custom()
                .setSSLSocketFactory(connectionSocketFactory)
                .build();
    }


}

-1

มีวิธีที่ง่ายกว่าที่คุณสามารถใช้ HostnameVerifier ของคุณเองเพื่อเชื่อถือการเชื่อมต่อบางอย่างโดยปริยาย ปัญหามาพร้อมกับ Java 1.7 ซึ่งมีการเพิ่มส่วนขยาย SNI และข้อผิดพลาดของคุณเกิดจากการกำหนดค่าเซิร์ฟเวอร์ผิด

คุณสามารถใช้ "-Djsse.enableSNIExtension = false" เพื่อปิดใช้งาน SNI ใน JVM ทั้งหมดหรืออ่านบล็อกของฉันที่ฉันอธิบายวิธีการใช้เครื่องมือตรวจสอบแบบกำหนดเองที่ด้านบนของการเชื่อมต่อ URL

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