Java's keytool command with IP addresses

2019-02-19 19:47发布

问题:

I'm trying to get an image via an https URL, and am having some problems. I generate a keystore with Java's keytool command. If I specify the common name (CN) equal to my hostname, such as CN=JONMORRA, and then try to query via my hostname, such as https://JONMORRA:8443/ then it works fine. However, if I specify the common name as my ip address, such that CN=192.168.56.1, and try to query via my ip address, such as https://192.168.56.1:8443/ then I get an error

HTTPS hostname wrong: should be <192.168.56.1>

Which is stating that my hostname is wrong, even though that's what I specified in the keystore.

I would like to use ip addresses instead of hostnames so I can query between Linux and Windows boxes without worrying about hostnames.

Why is the CN not accepting ip addresses, and how can I fix it?

Thanks

回答1:

This snippet might work for you:

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;

HostnameVerifier hv = new HostnameVerifier() {
    public boolean verify(String urlHostName, SSLSession session) {
        System.out.println("Warning: URL Host: " + urlHostName + " vs. " + session.getPeerHost());
        return true;
    }
};

HttpsURLConnection.setDefaultHostnameVerifier(hv);

If you do try this code, and it doesn't work, please post what is printed for urlHostName and session.getPeerHost().

Also, why does having Windows and Linux boxes interoperating require the use of IP addresses rather than hostnames?



回答2:

The HTTPS specification (RFC 2818) is quite clear about the server identity verification with an IP address: a Subject Alternative Name (IP) entry must be present in the certificate (whereas the CN in the Subject DN would suffice as a fallback solution for a host name).

Although not all clients (in particular not all browsers) implement this verification strictly, Java default host name verifier does.

Creating a certificate with an IP SAN entry can be done with OpenSSL for example or (not available at the time this question was asked/answered), using Java 7's keytool.

See this question for details: How are SSL certificate server names resolved/Can I add alternative names using keytool?



回答3:

To acutally generate a valid certificate using keytool, use:

keytool -keystore keystore.jks -genkey -ext SAN=IP:{IP_ADDRESS}

e.g.:

keytool -keystore keystore.jks -genkey -ext SAN=IP:192.168.1.1