2011-12-09 9 views
54

Questi possono essere formulati come domande separate per chiarezza, ma sono tutti correlati allo stesso problema.Come vengono risolti i nomi dei server di certificati SSL/È possibile aggiungere nomi alternativi utilizzando keytool?

Come vengono risolti i nomi dei server di certificati SSL?

Perché i browser sembrano utilizzare il campo CN del certificato, ma il meccanismo di Java sembra guardare solo "nomi alternativi di soggetto"?

È possibile aggiungere nomi alternativi a un certificato SSL utilizzando keytool? Se no, sta usando openSSL invece una buona opzione ??

Solo un piccolo background: Ho bisogno di ottenere un server principale per comunicare con diversi server utilizzando HTTPS. Ovviamente, non vogliamo acquistare certificati SSL per ogni server (ce ne potrebbero essere molti), quindi voglio usare certificati autofirmati (ho usato keytool per generarli). Dopo aver aggiunto i certificati come affidabili nel sistema operativo, i browser (IE e Chrome) accettano felicemente la connessione come attendibile. Tuttavia, anche dopo aver aggiunto i certificati a cacerts di Java, Java continua a non accettare la connessione come affidabile e getta la seguente eccezione:

Causato da: java.security.cert.CertificateException: Nessun soggetto nomi alternativi presente all'indirizzo sun.security.util.HostnameChecker.matchIP (NomehostChecker.java:142) all'indirizzo sun.security.util.HostnameChecker.match (NomehostChecker.java:75) su com.sun.net.ssl.internal.ssl. X509TrustManagerImpl.checkIdentity (X509T rustManagerImpl.java:264) in com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted ( X509TrustManagerImpl.java:250) a com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate (Clien tHandshaker.java:1185) ... more 14

ho scoperto che posso fare Java attendibile il certificato attuazione mia proprio HostNameVerifier, che ho copiato da qui: com.sun.jbi.internal.security.https.DefaultHostnameVerifier solo per testare (a proposito, l'hostname passato come argomento a HostnameVerifier è corretto, quindi penso che avrebbe dovuto essere accettato).

Ho utilizzato il campo del certificato CN come nome host (in genere l'indirizzo IP).

Qualcuno può dirmi se sto facendo qualcosa di sbagliato e indicarmi la direzione giusta?

+1

Il collegamento è interrotto. – axiopisty

+1

Scegli la tua alternativa: http://grepcode.com/search?query=DefaultHostnameVerifier&n= – Renato

risposta

82

Come la verifica del nome host deve essere eseguita in RFC 6125, che è piuttosto recente e generalizza la pratica a tutti i protocolli e sostituisce RFC 2818, che era specifico per HTTPS. (Io non sono nemmeno sicuro di Java 7 utilizza RFC 6125, che potrebbe essere troppo recente di questo.)

Da RFC 2818 (Section 3.1):

Se è presente un'estensione subjectAltName di tipo dNSName, che deve essere utilizzato come l'identità. In caso contrario, DEVE essere utilizzato il campo (più specifico) Nome comune nel campo Oggetto del certificato. Anche se l'uso del nome comune è una pratica esistente, è deprecato e le autorità di certificazione sono invece incoraggiate a utilizzare dNSName.

[...]

In alcuni casi, l'URI è specificato come un indirizzo IP anziché un nome host . In questo caso, il NomeAloggettoNomeIndirizzo iP deve essere presente nel certificato e deve corrispondere esattamente all'IP nell'URI.

In sostanza, il problema specifico deriva dal fatto che si stanno utilizzando indirizzi IP nel CN ​​e non in un nome host. Alcuni browser potrebbero funzionare perché non tutti gli strumenti seguono questa specifica in modo rigoroso, in particolare perché "più specifico" in RFC 2818 non è chiaramente definito (vedere le discussioni in RFC 6215).

Se stai usando keytool, as of Java 7, keytool ha un'opzione per includere un nome alternativo soggetto (vedere la tabella nella documentazione per -ext): si potrebbe usare -ext san=dns:www.example.com o -ext san=ip:10.0.0.1.

EDIT:

È possibile richiedere una SAN in OpenSSL cambiando openssl.cnf (si riprenderà la copia nella directory corrente se non si desidera modificare la configurazione globale, per quanto mi ricordo, oppure puoi scegliere una posizione esplicita usando la variabile di ambiente OPENSSL_CONF).

impostare le seguenti opzioni (per saperne di apposite sezioni tra parentesi prima):

[req] 
req_extensions = v3_req 

[ v3_req ] 
subjectAltName=IP:10.0.0.1 
# or subjectAltName=DNS:www.example.com 

C'è anche un bel trucco per utilizzare una variabile d'ambiente per questo (piuttosto che risolverlo in un file di configurazione) qui: http://www.crsr.net/Notes/SSL.html

+0

Questo è esattamente quello che dovevo sapere ... tuttavia, sembra che Java 6 non abbia questa opzione -ext. Proverò a cambiare la mia VM in Java 7 e testarlo. – Renato

+2

Si noti che è possibile utilizzare keytool da Java 7 su un altro computer e copiare il keystore in un secondo momento (non è necessario che sia in esecuzione Java 7). In alternativa, ho modificato la mia risposta per farlo con OpenSSL. Detto questo, potresti trovare più flessibile l'uso dei nomi host al posto degli indirizzi IP a lungo termine (usare comunque le SAN è comunque una buona idea). – Bruno

+0

L'opzione -ext non funziona in Java6! Passerò a Java 7 e vedrò se posso farlo usando semplicemente keytool ... Grazie mille per la risposta .. (PS accetterò la risposta una volta che l'ho provato) – Renato

Problemi correlati