[java] एसएसएल हैंडशेक चेतावनी: जावा 1.7.0 में अपग्रेड के बाद unrecognized_name त्रुटि



7 Answers

मेरे पास वही था जो मुझे विश्वास है कि एक ही मुद्दा है। मैंने पाया कि मेजबान के लिए सर्वरनाम या सर्वरअलीस को शामिल करने के लिए मुझे अपाचे कॉन्फ़िगरेशन को समायोजित करने की आवश्यकता है।

यह कोड असफल रहा:

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

वायर्सहार्क ने खुलासा किया कि टीएसएल / एसएसएल के दौरान चेतावनी चेतावनी है (स्तर: चेतावनी, विवरण: अपरिचित नाम), सर्वर हैलो सर्वर से क्लाइंट को भेजा जा रहा था। यह केवल एक चेतावनी थी, हालांकि, जावा 7.1 ने तुरंत "घातक, विवरण: अप्रत्याशित संदेश" के साथ जवाब दिया, जिसका मुझे लगता है कि जावा एसएसएल पुस्तकालयों को अपरिचित नाम की चेतावनी देखना पसंद नहीं है।

परिवहन परत सुरक्षा (टीएलएस) पर विकी से:

112 अपरिचित नाम चेतावनी केवल टीएलएस; क्लाइंट के सर्वर नाम संकेतक ने एक होस्टनाम निर्दिष्ट किया जो सर्वर द्वारा समर्थित नहीं है

इससे मुझे मेरी अपाचे कॉन्फ़िगरेशन फ़ाइलों को देखने का मौका मिला और मैंने पाया कि यदि मैंने क्लाइंट / जावा पक्ष से भेजे गए नाम के लिए सर्वरनाम या सर्वरअलीस जोड़ा है, तो यह बिना किसी त्रुटि के सही तरीके से काम करता है।

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

मैंने आज जावा 1.6 से जावा 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 से कनेक्ट करने का प्रयास किया। मेरी गलती कहां है?

धन्यवाद।




एक आसान तरीका है जहां आप निश्चित रूप से कुछ कनेक्शनों पर भरोसा करने के लिए अपने स्वयं के होस्टनाम सत्यापनकर्ता का उपयोग कर सकते हैं। यह समस्या जावा 1.7 के साथ आता है जहां एसएनआई एक्सटेंशन जोड़े गए हैं और आपकी त्रुटि सर्वर गलत कॉन्फ़िगरेशन के कारण है।

आप या तो पूरे जेवीएम में एसएनआई को अक्षम करने के लिए "-Djsse.enableSNIExtension = false" का उपयोग कर सकते हैं या मेरे ब्लॉग को पढ़ सकते हैं जहां मैं एक यूआरएल कनेक्शन के शीर्ष पर एक कस्टम सत्यापनकर्ता को कार्यान्वित करने का तरीका बताता हूं।




मैंने एक ही समस्या को मारा और यह पता चला कि रिवर्स डीएनएस सही सेटअप नहीं किया गया था, यह आईपी के लिए गलत होस्टनाम की ओर इशारा करता था। रिवर्स डीएनएस को सही करने और httpd को पुनरारंभ करने के बाद, चेतावनी समाप्त हो गई है। (अगर मैं रिवर्स डीएनएस को सही नहीं करता हूं, तो सर्वरनाम ने मेरे लिए भी चाल बनाई है)




यह उपयोगी होना चाहिए। 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);



अपाचे में डिफ़ॉल्ट वर्चुअल होस्ट तंत्र पर भरोसा करने के बजाय, आप एक अंतिम कैचुअल वर्चुअलहोस्ट को परिभाषित कर सकते हैं जो एक मनमानी सर्वरनाम और वाइल्डकार्ड सर्वरअलीस का उपयोग करता है, उदाहरण के लिए

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

इस तरह आप एसएनआई का उपयोग कर सकते हैं और अपाचे एसएसएल चेतावनी वापस नहीं भेज पाएगा।

बेशक, यह केवल तभी काम करता है जब आप वाइल्डकार्ड सिंटैक्स का उपयोग करके आसानी से अपने सभी डोमेन का वर्णन कर सकें।




ग्रहण के माध्यम से उपयोग किए जाने पर मुझे उबंटू लिनक्स सर्वर चलने वाले विचलन के साथ एक ही समस्या थी।

यह दिखाया गया है कि अपाचे (पुनः) शुरू होने पर समस्या को चेतावनी के साथ करना था:

[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 में एक नई प्रविष्टि के कारण ports.conf , जहां sites-enabled/000-default में निर्देश के साथ एक और नाम ports.conf निर्देश दर्ज किया गया था।

ports.conf में निर्देश को हटाने के बाद, समस्या गायब हो गई थी (स्वाभाविक रूप से अपाचे को पुनरारंभ करने के बाद)




जावा 1.6_2 9 से 1.7 तक अपग्रेड करते समय भी मैं इस मुद्दे पर आया हूं।

खतरनाक रूप से, मेरे ग्राहक ने जावा नियंत्रण कक्ष में एक सेटिंग की खोज की है जो इसे हल करता है।

उन्नत टैब में आप 'एसएसएल 2.0 संगत क्लाइंटहेल्लो प्रारूप का उपयोग करें' की जांच कर सकते हैं।

यह इस मुद्दे को हल करने लगता है।

हम एक इंटरनेट एक्सप्लोरर ब्राउज़र में जावा एप्लेट का उपयोग कर रहे हैं।

उम्मीद है की यह मदद करेगा।




दुर्भाग्यवश, jarsigner.exe उपकरण में सिस्टम गुणों की आपूर्ति नहीं कर सकते हैं।

मैंने दोषों को 7177232 प्रस्तुत किया है, जो @Eckes 'दोष bugs.sun.com/bugdatabase/view_bug.do?bug_id=7127374 संदर्भ bugs.sun.com/bugdatabase/view_bug.do?bug_id=7127374 और यह समझाता है कि यह त्रुटि में क्यों बंद था।

मेरा दोष विशेष रूप से jarsigner उपकरण पर प्रभाव के बारे में है, लेकिन शायद यह उन्हें अन्य दोष को फिर से खोलने और इस मुद्दे को ठीक से संबोधित करने के लिए नेतृत्व करेगा।

अद्यतन: असल में, यह पता चला है कि आप Jarsigner उपकरण को सिस्टम गुणों की आपूर्ति कर सकते हैं, यह केवल सहायता संदेश में नहीं है। jarsigner -J-Djsse.enableSNIExtension=false प्रयोग करें




Related



Tags

java java   ssl