-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Description
Summary
In request.js:295 the Host header is set to the URI hostname when the URI port match the protocol port.
According to the RFCs, the Host header should be the host of the uri.
https://tools.ietf.org/html/rfc7230#section-5.4
https://tools.ietf.org/html/rfc7230#section-2.7.1
https://tools.ietf.org/html/rfc3986#section-3.2.2
The main difference here is with ipv6 where self.uri.host contains the ip between bracket + the port (eg. [2001:db8::1]:443) and self.uri.hostname only contains the ip without brackets (eg. 2001:db8::1).
This cause ipv6 URI to fail TLS verification as the calculateServerName function expect an ipv6 enclosed by brackets (https://github.com/nodejs/node/blob/a494d127236d09e4413631c33ee95c1324eb8814/lib/_http_agent.js#L275)
error: Hostname/IP does not match certificate's altnames: Host: 2001. is not in the cert's altnames: DNS:localhost, IP Address:0:0:0:0:0:0:0:1, IP Address:2001:DB8:1:0:0:242:AC11:2
Simplest Example to Reproduce
- Generate a CA and a certificate valid for any ipv6 like 2001:db8::1 (::1 is a special case)
- Run a webserver on this ipv6 with this certificate
- Try to GET a ipv6 url (like https://[2001:db8::1]:443/
const request = require('request');
const fs = require('fs')
const options = {
url: `https://[2001:db8::1]:443/`,
ca: fs.readFileSync('ca.crt'),
strictSSL: true,
};
request(options, function (error, response, body) {
if (error) {
console.log('error:', error.message); // Print the error if one occurred
}
console.log('statusCode:', response && response.statusCode); // Print the response status code if a response was received
console.log('body:', body); // Print the HTML for the Google homepage.
});I made a docker image which does everything: setup certificates, run a server, try to get (fail), patch and retry (successfully): https://github.com/bengentil/request-ipv6-issue
Expected Behavior
Having a Host header matching the URI host (ipv6 with brackets)
Current Behavior
When using ipv6 + a standard port in the URI, the Host header become the ipv6 without the brackets
Possible Solution
Removing the condition that sets the Host header to the URI hostname
Context
https://github.com/cilium/hubble-ui/ won't work with ipv6 without this fixed
Your Environment
Latest node docker image
| software | version |
|---|---|
| request | 2.88.2 |
| node | v13.8.0 |
| npm | 6.13.6 |
| Operating System | Debian stretch |