Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tls client does not accept certificates with IPv6 subjectAltNames #14736

Closed
mattiash opened this issue Aug 10, 2017 · 1 comment
Closed

tls client does not accept certificates with IPv6 subjectAltNames #14736

mattiash opened this issue Aug 10, 2017 · 1 comment
Labels
http Issues or PRs related to the http subsystem. tls Issues and PRs related to the tls subsystem.

Comments

@mattiash
Copy link

  • Version: 6.3.1 and 8.2.1 (at least)
  • Platform: OS X and Linux (at least)
  • Subsystem: tls

TL;DR

Node's tls client does not accept certificates signing IPv6 addresses, only certificates with IPv4 addresses are accepted. Both IPv6 and IPv4 should be accepted.

Long version

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://12.34.56.78 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 '['...

I have written code to reproduce the problem in https://github.com/mattiash/test-checkServerIdentity

@mattiash
Copy link
Author

With the following patch

diff --git a/lib/_http_agent.js b/lib/_http_agent.js
index ddd36c158e..5b0cc1d7ab 100644
--- a/lib/_http_agent.js
+++ b/lib/_http_agent.js
@@ -152,7 +152,7 @@ Agent.prototype.addRequest = function addRequest(req, options, port/*legacy*/,
     options.servername = options.host;
     const hostHeader = req.getHeader('host');
     if (hostHeader) {
-      options.servername = hostHeader.replace(/:.*$/, '');
+//      options.servername = hostHeader.replace(/:.*$/, '');
     }
   }

the error-message printed by the testcase changes to

Test 1 failed: Shall connect to ::1. Error:  IP: ::1 is not in the cert's list: 127.0.0.1, 0:0:0:0:0:0:0:1

Now we also need to change all IPv6 addresses into some canonical format before the comparison. And do a proper patch for _http_agent that doesn't break other stuff...

@addaleax addaleax added tls Issues and PRs related to the tls subsystem. http Issues or PRs related to the http subsystem. labels Aug 10, 2017
mattiash pushed a commit to mattiash/node that referenced this issue Sep 23, 2017
When an http-client requests a url with the hostname
specified as an IPv6 address, the Host: header will
have the following format:

Host: [::1]:3000

The servername in this case should be '::1'.

Fixes: nodejs#14736
mattiash pushed a commit to mattiash/node that referenced this issue Sep 23, 2017
When comparing IP addresses against addresses in the subjectAltName
field of a certificate, format the address correctly before
doing the string comparison.

Fixes: nodejs#14736
mattiash pushed a commit to mattiash/agentkeepalive that referenced this issue Sep 29, 2017
When a url uses an ipv6-addresses as the host part, the host-header of the request will be

[::1]:3000

(for ipv6 address ::1). To verify the IP address against a TLS certificate, we need to extract the
IP-address correctly.

Requires node with nodejs/node#14736 resolved to work.
mattiash pushed a commit to mattiash/node that referenced this issue Oct 10, 2017
When an http-client requests a url with the hostname
specified as an IPv6 address, the Host: header will
have the following format:

Host: [::1]:3000

The servername in this case should be '::1'.

Fixes: nodejs#14736
mattiash pushed a commit to mattiash/node that referenced this issue Oct 10, 2017
When comparing IP addresses against addresses in the subjectAltName
field of a certificate, format the address correctly before
doing the string comparison.

Fixes: nodejs#14736
cjihrig pushed a commit to cjihrig/node that referenced this issue Nov 6, 2017
- Properly handle IPv6 in Host header when setting servername.
- When comparing IP addresses against addresses in the subjectAltName
  field of a certificate, format the address correctly before
  doing the string comparison.

PR-URL: nodejs#14772
Fixes: nodejs#14736
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Anatoli Papirovski <apapirovski@mac.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
MylesBorins pushed a commit that referenced this issue Dec 8, 2017
- Properly handle IPv6 in Host header when setting servername.
- When comparing IP addresses against addresses in the subjectAltName
  field of a certificate, format the address correctly before
  doing the string comparison.

PR-URL: #14772
Fixes: #14736
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Anatoli Papirovski <apapirovski@mac.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
mattiasholmlund added a commit to mattiasholmlund/node that referenced this issue Jan 23, 2018
- Properly handle IPv6 in Host header when setting servername.
- When comparing IP addresses against addresses in the subjectAltName
  field of a certificate, format the address correctly before
  doing the string comparison.

PR-URL: nodejs#14772
Fixes: nodejs#14736
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Anatoli Papirovski <apapirovski@mac.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
gibfahn pushed a commit that referenced this issue Jan 26, 2018
- Properly handle IPv6 in Host header when setting servername.
- When comparing IP addresses against addresses in the subjectAltName
  field of a certificate, format the address correctly before
  doing the string comparison.

PR-URL: #14772
Fixes: #14736
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Anatoli Papirovski <apapirovski@mac.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
MylesBorins pushed a commit that referenced this issue Feb 27, 2018
- Properly handle IPv6 in Host header when setting servername.
- When comparing IP addresses against addresses in the subjectAltName
  field of a certificate, format the address correctly before
  doing the string comparison.

PR-URL: #14772
Fixes: #14736
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Anatoli Papirovski <apapirovski@mac.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
mattiash pushed a commit to mattiash/agentkeepalive that referenced this issue Mar 7, 2018
When a url uses an ipv6-addresses as the host part, the host-header of the request will be

[::1]:3000

(for ipv6 address ::1). To verify the IP address against a TLS certificate, we need to extract the
IP-address correctly.

Requires node with nodejs/node#14736 resolved to work.
fengmk2 pushed a commit to node-modules/agentkeepalive that referenced this issue Mar 8, 2018
When a url uses an ipv6-addresses as the host part, the host-header of the request will be

[::1]:3000

(for ipv6 address ::1). To verify the IP address against a TLS certificate, we need to extract the
IP-address correctly.

Requires node with nodejs/node#14736 resolved to work.

* Add ca certificate and check that certs are valid
* Add tests for certificates with ipv6 addresses
* Fix check for supported node version
* Skip test if ipv6 is not available
ccloli added a commit to ccloli/DNSProxy that referenced this issue Aug 25, 2018
all Node.js releases before `v8.10.0` and Node.js `v9.0.0` have a critical bug that cannot compare IPv6 address with TLS certificates `IP Address` field correctly (see nodejs/node#14736)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
http Issues or PRs related to the http subsystem. tls Issues and PRs related to the tls subsystem.
Projects
None yet
Development

No branches or pull requests

2 participants