<repo_name>mattiash/test-checkServerIdentity<file_sep>/README.md
# Nodejs problem with IPv6 subjectAltNames

## Background

It is possible to generate TLS certificates that sign IP addresses
if you add the IP addresses as alternative names for the certificate.
This allows you to connect to url:s such as https://172.16.58.3 if
the server at that IP address has a certificate that signs that IP
address.

It is as far as I know not possible to buy a certificate that signs
an IP address from the usual certificate vendors. It is however
possible to use such certificates if you have your own CA and
explicitly trust certificates signed by your own CA. This is very
useful for clustering solutions where DNS only complicates the design.

Node has support for everything described above as long as you use IPv4
addresses. However, if you use IPv6 addresses it does not work as expected.
If you try to connect to https://\[::1\],
the node https-client refuses to accept the certificate with the error

    Host: [. is not in the cert's altnames: IP Address:127.0.0.1, IP Address:0:0:0:0:0:0:0:1

Note that the error message specifically says that the certificate
includes the ip-address 0:0:0:0:0:0:0:1 (which is another representation of ::1),
so it should accept the certificate.

The code that builds the error-message is in tls.js https://github.com/nodejs/node/blob/master/lib/tls.js#L216

    reason = `Host: ${host}. is not in the cert's altnames: ${altNames}`

The code seems to think that the hostname in the url is '['...

## Reproducing the problem

This repository contains code to reproduce the problem. Run it with

    ./generate-certificates
    node index.js

It will print the following result

    Test 1 failed: Shall connect to ::1. Error:  Host: [. is not in the cert's altnames: IP Address:127.0.0.1, IP Address:0:0:0:0:0:0:0:1
    Test 2 ok: Shall connect to 127.0.0.1

The test will also leave the server running, so you can check that curl
accepts the certificate provided by the server when you give curl
the ca-certificate generated by generate-certificates:

    curl --cacert ca.pem https://[::1]:3000

Note that curl on OS X does not support the cacert-parameter (https://github.com/curl/curl/issues/976). If you
want to test with curl, try linux instead.
<file_sep>/generate-certificates
#!/bin/bash

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

# Generate ca key and pem
openssl req -new -x509 -nodes -days 9999 -config $DIR/ca.cnf -keyout ca.key -out ca.pem

# Generate server key
openssl genrsa -out server.key 2048

# Generate a certificate signing request for server.key
openssl req -new -config server.cnf -key server.key -out server.csr

# Sign the csr with the ca certificate, generating server.pem
openssl x509 -req -extfile server.cnf -days 999 -passin "<PASSWORD>:<PASSWORD>" -extensions v3_req -in server.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out server.pem
