From d28f6d25b094128727a3ef9d6c45b5c506565dc4 Mon Sep 17 00:00:00 2001 From: Free Wortley Date: Sat, 19 Feb 2022 03:00:24 +0000 Subject: [PATCH 01/18] Fix TLS bug preventing HTTPS-over-HTTP(S) proxying Without this fix, you see this error when attempting to use an HTTPS proxy. `Error [ERR_TLS_CERT_ALTNAME_INVALID]: Hostname/IP does not match certificate's altnames: Host: foo.com. is not in the cert's altnames: DNS:*.bar.com, DNS:bar.com` The `servername` attribute is able to fix this behavior when passed to the underlying `tls.connect()` call inside of the `https` module. (see the Node [docs](https://nodejs.org/api/https.html#httpsrequesturl-options-callback)) This was very painful to debug but now I understand how `CONNECT` works extremely well! Cheers. FIxes #43 --- index.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/index.js b/index.js index ad37aac..ab8f6f9 100644 --- a/index.js +++ b/index.js @@ -73,6 +73,11 @@ class HttpsProxyAgent extends https.Agent { const base64 = Buffer.from(`${this.proxy.username || ''}:${this.proxy.password || ''}`).toString('base64') requestOptions.headers['proxy-authorization'] = `Basic ${base64}` } + + // Necessary for the TLS check with the proxy to succeed. + if (this.proxy.protocol === 'https:') { + requestOptions.servername = this.proxy.hostname; + } const request = (this.proxy.protocol === 'http:' ? http : https).request(requestOptions) request.once('connect', (response, socket, head) => { From c68715d16b10f8781d5cd137966e2f5f123eb9f6 Mon Sep 17 00:00:00 2001 From: Raghu Saxena Date: Mon, 2 May 2022 12:01:03 +0800 Subject: [PATCH 02/18] Run lint (standard) --- index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index ab8f6f9..da97e6f 100644 --- a/index.js +++ b/index.js @@ -73,10 +73,10 @@ class HttpsProxyAgent extends https.Agent { const base64 = Buffer.from(`${this.proxy.username || ''}:${this.proxy.password || ''}`).toString('base64') requestOptions.headers['proxy-authorization'] = `Basic ${base64}` } - + // Necessary for the TLS check with the proxy to succeed. if (this.proxy.protocol === 'https:') { - requestOptions.servername = this.proxy.hostname; + requestOptions.servername = this.proxy.hostname } const request = (this.proxy.protocol === 'http:' ? http : https).request(requestOptions) From b9d8ae175b04cf610a2377f129ade722421d282b Mon Sep 17 00:00:00 2001 From: Raghu Saxena Date: Mon, 2 May 2022 13:36:08 +0800 Subject: [PATCH 03/18] Gen certs, keys, fix https-over-http --- test/cert_proxy.pem | 25 ++++++++++++++++ test/cert_server.pem | 25 ++++++++++++++++ test/certs_unit_test.pem | 50 ++++++++++++++++++++++++++++++++ test/https-http.test.js | 20 +++++++------ test/https-https.test.js | 25 ++++++++++++++-- test/key_proxy.pem | 28 ++++++++++++++++++ test/key_server.pem | 28 ++++++++++++++++++ test/ssl.cert | 19 ------------- test/ssl.key | 27 ------------------ test/utils.js | 61 ++++++++++++++++++++++++++++++++++------ 10 files changed, 242 insertions(+), 66 deletions(-) create mode 100644 test/cert_proxy.pem create mode 100644 test/cert_server.pem create mode 100644 test/certs_unit_test.pem create mode 100644 test/key_proxy.pem create mode 100644 test/key_server.pem delete mode 100644 test/ssl.cert delete mode 100644 test/ssl.key diff --git a/test/cert_proxy.pem b/test/cert_proxy.pem new file mode 100644 index 0000000..ee6f658 --- /dev/null +++ b/test/cert_proxy.pem @@ -0,0 +1,25 @@ +-----BEGIN CERTIFICATE----- +MIIERzCCAy+gAwIBAgIUQD0nJ3V7h98ZMrCxv5vFhUs6swwwDQYJKoZIhvcNAQEL +BQAwgbIxCzAJBgNVBAYTAkhLMQswCQYDVQQIDAJISzESMBAGA1UEBwwJSG9uZyBL +b25nMRowGAYDVQQKDBFIcGFnZW50IFVuaXQgVGVzdDEaMBgGA1UECwwRSHBhZ2Vu +dCBVbml0IFRlc3QxJDAiBgNVBAMMG3Byb3h5LmhwYWdlbnQtdW5pdC10ZXN0LmNv +bTEkMCIGCSqGSIb3DQEJARYVZmFrZS1lbWFpbEBkb21haW4uY29tMB4XDTIyMDUw +MjA1MTcwN1oXDTMyMDQyOTA1MTcwN1owgbIxCzAJBgNVBAYTAkhLMQswCQYDVQQI +DAJISzESMBAGA1UEBwwJSG9uZyBLb25nMRowGAYDVQQKDBFIcGFnZW50IFVuaXQg +VGVzdDEaMBgGA1UECwwRSHBhZ2VudCBVbml0IFRlc3QxJDAiBgNVBAMMG3Byb3h5 +LmhwYWdlbnQtdW5pdC10ZXN0LmNvbTEkMCIGCSqGSIb3DQEJARYVZmFrZS1lbWFp +bEBkb21haW4uY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxJXt +0aN6mIhYAyrA1/M4Rvhyyg3LSsf3tFW3OZg3dSFJz2nQmVc/+KwjyGZ6/XjgE8Cy +n5L3hMIuU1+wtHwSHSKFubaluMGBDRJjCJLye5x8nESrPEXfq5gS5Aj6o8cYrYMM +lgONXysiahhDGAMX8ftxfJmc2FpKfz3FwcR9VQOfZGyDrlDL+9zMwtR+YZb3EVPA +mxPvs5ZB3pBL1Q77/PWSb1ixd2k2qadWDxhWiSrsQ/n2SlWiNb5SYQn1gu3NrUuV +ncXGMSUBG7K0bqv8DTrctJuaX2pRiPtGMSHKS9uzHjonrhTbl8hWj3fw5hS5MsqC +fciwGFFxfKHzIEix+wIDAQABo1MwUTAdBgNVHQ4EFgQUMeEK6ngZr+3GIgrdtoJd +AMCpM8gwHwYDVR0jBBgwFoAUMeEK6ngZr+3GIgrdtoJdAMCpM8gwDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAEqLwNTWgLGAUw0jB2j8ZX2oPk3KV +EugXnmmAnXfT3lCaP3MFyCN/IIBAsHTL2p1TxXAwEUXmGHhsEGH69o1+V7uz/GKW +9yr+su7RpSua6YVjnaGnPDGIhYRh2PBvujeYDFyb3Facjn/AkzxJITWtTQSJoYhW +YRhjuMZWIjetlCSieUFIPQ/E/ZD5fIq4ZrFC1IXciK7LqLljvwzfhGmTe8Ve/uz7 +S8Aep3Vgo3xsjti0RKjHf0Lcf5kxxDcptdphInm7NZcxghrTlC7/29AY+fe9wPCX +6Zis1At4XACkrFcD8nSL3hw0AbzNtzoONi+06Ragdm8K+uFGPjDvgMjhUg== +-----END CERTIFICATE----- diff --git a/test/cert_server.pem b/test/cert_server.pem new file mode 100644 index 0000000..5058df1 --- /dev/null +++ b/test/cert_server.pem @@ -0,0 +1,25 @@ +-----BEGIN CERTIFICATE----- +MIIESTCCAzGgAwIBAgIUf4sUokGui8gK0SABNivmlSRhcp0wDQYJKoZIhvcNAQEL +BQAwgbMxCzAJBgNVBAYTAkhLMQswCQYDVQQIDAJISzESMBAGA1UEBwwJSG9uZyBL +b25nMRowGAYDVQQKDBFIcGFnZW50IFVuaXQgVGVzdDEaMBgGA1UECwwRSHBhZ2Vu +dCBVbml0IFRlc3QxJTAjBgNVBAMMHHNlcnZlci5ocGFnZW50LXVuaXQtdGVzdC5j +b20xJDAiBgkqhkiG9w0BCQEWFWZha2UtZW1haWxAZG9tYWluLmNvbTAeFw0yMjA1 +MDIwNTE2MThaFw0zMjA0MjkwNTE2MThaMIGzMQswCQYDVQQGEwJISzELMAkGA1UE +CAwCSEsxEjAQBgNVBAcMCUhvbmcgS29uZzEaMBgGA1UECgwRSHBhZ2VudCBVbml0 +IFRlc3QxGjAYBgNVBAsMEUhwYWdlbnQgVW5pdCBUZXN0MSUwIwYDVQQDDBxzZXJ2 +ZXIuaHBhZ2VudC11bml0LXRlc3QuY29tMSQwIgYJKoZIhvcNAQkBFhVmYWtlLWVt +YWlsQGRvbWFpbi5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDm +z2AKeJ7OeWvJRBSTjDwp3OgdPIg91IgFYPaEarCoLyf2fyk1houXAENpewrKDG9n +IKuNF1hFIi1P7X/rAf5T/GqQ20VHY+wpAc0fKoXfECqyrLLJ5GmpdElRSCfNUJQR +ZlCYUsE5oLCxKxR5qoS1fKUC4mmIMO5xd+E2yqijHsstFcTAaqJ5rkpjH/1bAGI6 +Z5oNf1ML+09o2y8DpxmnW3NyqqJ5De9yZr4vejaiVVer56K3Nnl32y42wjgBxc7O +iouIXL8D6o5KV0BbIZMc+YPMZUy1zpFfBbFy4FpldQl76eEmTW264UwGF3ttmhfC +Ex83GtnTKW3hi+br2JC3AgMBAAGjUzBRMB0GA1UdDgQWBBTpGNtxuuUfjk3+/1Db +lxLgUmxCTDAfBgNVHSMEGDAWgBTpGNtxuuUfjk3+/1DblxLgUmxCTDAPBgNVHRMB +Af8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAQ0n/t+KkpaKoxgclsRD8vL8tk +Ni6w04gWCTro+x4NOCU5VClY/ryYzY64KVbHWiLBw9l3lz2UnV2Moc497wxpFCIL +accfqZVPABx7pG8CxQ4aEwpHP8wtxe6J9t+im17eGy7QaE/jv888fdgCENEdEfY7 +pG17kb0q9+6uOWnUxVeYecQW016iogezvWJH7Y7KXSVidEY8EoTTbORwfU+DU828 +6gcL4st94FthmHuE6JwOmiMDss8P21+/DF4/jyAjsKyakPVMdZuqyGgpe0gryi1s +lM/xDOAPSsbbOONdYvNNp19eIqllNl2vfPt2p3qzmeZ5fGw8MefjR4TwoMef +-----END CERTIFICATE----- diff --git a/test/certs_unit_test.pem b/test/certs_unit_test.pem new file mode 100644 index 0000000..d797993 --- /dev/null +++ b/test/certs_unit_test.pem @@ -0,0 +1,50 @@ +-----BEGIN CERTIFICATE----- +MIIERzCCAy+gAwIBAgIUQD0nJ3V7h98ZMrCxv5vFhUs6swwwDQYJKoZIhvcNAQEL +BQAwgbIxCzAJBgNVBAYTAkhLMQswCQYDVQQIDAJISzESMBAGA1UEBwwJSG9uZyBL +b25nMRowGAYDVQQKDBFIcGFnZW50IFVuaXQgVGVzdDEaMBgGA1UECwwRSHBhZ2Vu +dCBVbml0IFRlc3QxJDAiBgNVBAMMG3Byb3h5LmhwYWdlbnQtdW5pdC10ZXN0LmNv +bTEkMCIGCSqGSIb3DQEJARYVZmFrZS1lbWFpbEBkb21haW4uY29tMB4XDTIyMDUw +MjA1MTcwN1oXDTMyMDQyOTA1MTcwN1owgbIxCzAJBgNVBAYTAkhLMQswCQYDVQQI +DAJISzESMBAGA1UEBwwJSG9uZyBLb25nMRowGAYDVQQKDBFIcGFnZW50IFVuaXQg +VGVzdDEaMBgGA1UECwwRSHBhZ2VudCBVbml0IFRlc3QxJDAiBgNVBAMMG3Byb3h5 +LmhwYWdlbnQtdW5pdC10ZXN0LmNvbTEkMCIGCSqGSIb3DQEJARYVZmFrZS1lbWFp +bEBkb21haW4uY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxJXt +0aN6mIhYAyrA1/M4Rvhyyg3LSsf3tFW3OZg3dSFJz2nQmVc/+KwjyGZ6/XjgE8Cy +n5L3hMIuU1+wtHwSHSKFubaluMGBDRJjCJLye5x8nESrPEXfq5gS5Aj6o8cYrYMM +lgONXysiahhDGAMX8ftxfJmc2FpKfz3FwcR9VQOfZGyDrlDL+9zMwtR+YZb3EVPA +mxPvs5ZB3pBL1Q77/PWSb1ixd2k2qadWDxhWiSrsQ/n2SlWiNb5SYQn1gu3NrUuV +ncXGMSUBG7K0bqv8DTrctJuaX2pRiPtGMSHKS9uzHjonrhTbl8hWj3fw5hS5MsqC +fciwGFFxfKHzIEix+wIDAQABo1MwUTAdBgNVHQ4EFgQUMeEK6ngZr+3GIgrdtoJd +AMCpM8gwHwYDVR0jBBgwFoAUMeEK6ngZr+3GIgrdtoJdAMCpM8gwDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAEqLwNTWgLGAUw0jB2j8ZX2oPk3KV +EugXnmmAnXfT3lCaP3MFyCN/IIBAsHTL2p1TxXAwEUXmGHhsEGH69o1+V7uz/GKW +9yr+su7RpSua6YVjnaGnPDGIhYRh2PBvujeYDFyb3Facjn/AkzxJITWtTQSJoYhW +YRhjuMZWIjetlCSieUFIPQ/E/ZD5fIq4ZrFC1IXciK7LqLljvwzfhGmTe8Ve/uz7 +S8Aep3Vgo3xsjti0RKjHf0Lcf5kxxDcptdphInm7NZcxghrTlC7/29AY+fe9wPCX +6Zis1At4XACkrFcD8nSL3hw0AbzNtzoONi+06Ragdm8K+uFGPjDvgMjhUg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIESTCCAzGgAwIBAgIUf4sUokGui8gK0SABNivmlSRhcp0wDQYJKoZIhvcNAQEL +BQAwgbMxCzAJBgNVBAYTAkhLMQswCQYDVQQIDAJISzESMBAGA1UEBwwJSG9uZyBL +b25nMRowGAYDVQQKDBFIcGFnZW50IFVuaXQgVGVzdDEaMBgGA1UECwwRSHBhZ2Vu +dCBVbml0IFRlc3QxJTAjBgNVBAMMHHNlcnZlci5ocGFnZW50LXVuaXQtdGVzdC5j +b20xJDAiBgkqhkiG9w0BCQEWFWZha2UtZW1haWxAZG9tYWluLmNvbTAeFw0yMjA1 +MDIwNTE2MThaFw0zMjA0MjkwNTE2MThaMIGzMQswCQYDVQQGEwJISzELMAkGA1UE +CAwCSEsxEjAQBgNVBAcMCUhvbmcgS29uZzEaMBgGA1UECgwRSHBhZ2VudCBVbml0 +IFRlc3QxGjAYBgNVBAsMEUhwYWdlbnQgVW5pdCBUZXN0MSUwIwYDVQQDDBxzZXJ2 +ZXIuaHBhZ2VudC11bml0LXRlc3QuY29tMSQwIgYJKoZIhvcNAQkBFhVmYWtlLWVt +YWlsQGRvbWFpbi5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDm +z2AKeJ7OeWvJRBSTjDwp3OgdPIg91IgFYPaEarCoLyf2fyk1houXAENpewrKDG9n +IKuNF1hFIi1P7X/rAf5T/GqQ20VHY+wpAc0fKoXfECqyrLLJ5GmpdElRSCfNUJQR +ZlCYUsE5oLCxKxR5qoS1fKUC4mmIMO5xd+E2yqijHsstFcTAaqJ5rkpjH/1bAGI6 +Z5oNf1ML+09o2y8DpxmnW3NyqqJ5De9yZr4vejaiVVer56K3Nnl32y42wjgBxc7O +iouIXL8D6o5KV0BbIZMc+YPMZUy1zpFfBbFy4FpldQl76eEmTW264UwGF3ttmhfC +Ex83GtnTKW3hi+br2JC3AgMBAAGjUzBRMB0GA1UdDgQWBBTpGNtxuuUfjk3+/1Db +lxLgUmxCTDAfBgNVHSMEGDAWgBTpGNtxuuUfjk3+/1DblxLgUmxCTDAPBgNVHRMB +Af8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAQ0n/t+KkpaKoxgclsRD8vL8tk +Ni6w04gWCTro+x4NOCU5VClY/ryYzY64KVbHWiLBw9l3lz2UnV2Moc497wxpFCIL +accfqZVPABx7pG8CxQ4aEwpHP8wtxe6J9t+im17eGy7QaE/jv888fdgCENEdEfY7 +pG17kb0q9+6uOWnUxVeYecQW016iogezvWJH7Y7KXSVidEY8EoTTbORwfU+DU828 +6gcL4st94FthmHuE6JwOmiMDss8P21+/DF4/jyAjsKyakPVMdZuqyGgpe0gryi1s +lM/xDOAPSsbbOONdYvNNp19eIqllNl2vfPt2p3qzmeZ5fGw8MefjR4TwoMef +-----END CERTIFICATE----- diff --git a/test/https-http.test.js b/test/https-http.test.js index 8d6a47c..7183724 100644 --- a/test/https-http.test.js +++ b/test/https-http.test.js @@ -2,7 +2,7 @@ const http = require('http') const test = require('ava') -const { createServer, createSecureProxy } = require('./utils') +const { createServer, createSecureProxy, PROXY_HOSTNAME } = require('./utils') const { HttpProxyAgent } = require('../') function request (opts) { @@ -18,6 +18,8 @@ test('Basic', async t => { const proxy = await createSecureProxy() server.on('request', (req, res) => res.end('ok')) + + const response = await request({ method: 'GET', hostname: server.address().address, @@ -29,8 +31,8 @@ test('Basic', async t => { maxSockets: 256, maxFreeSockets: 256, scheduling: 'lifo', - proxy: `https://${proxy.address().address}:${proxy.address().port}` - }) + proxy: `https://${PROXY_HOSTNAME}:${proxy.address().port}` + }), }) let body = '' @@ -67,7 +69,7 @@ test('Connection header (keep-alive)', async t => { maxSockets: 256, maxFreeSockets: 256, scheduling: 'lifo', - proxy: `https://${proxy.address().address}:${proxy.address().port}` + proxy: `https://${PROXY_HOSTNAME}:${proxy.address().port}` }) }) @@ -105,7 +107,7 @@ test('Connection header (close)', async t => { maxSockets: Infinity, maxFreeSockets: 256, scheduling: 'lifo', - proxy: `https://${proxy.address().address}:${proxy.address().port}` + proxy: `https://${PROXY_HOSTNAME}:${proxy.address().port}` }) }) @@ -142,7 +144,7 @@ test('Proxy authentication (empty)', async t => { maxSockets: 256, maxFreeSockets: 256, scheduling: 'lifo', - proxy: `https://${proxy.address().address}:${proxy.address().port}` + proxy: `https://${PROXY_HOSTNAME}:${proxy.address().port}` }) }) @@ -179,7 +181,7 @@ test('Proxy authentication', async t => { maxSockets: 256, maxFreeSockets: 256, scheduling: 'lifo', - proxy: `https://hello:world@${proxy.address().address}:${proxy.address().port}` + proxy: `https://hello:world@${PROXY_HOSTNAME}:${proxy.address().port}` }) }) @@ -213,7 +215,7 @@ test('Configure the agent to reuse sockets', async t => { maxSockets: 256, maxFreeSockets: 256, scheduling: 'lifo', - proxy: `https://${proxy.address().address}:${proxy.address().port}` + proxy: `https://${PROXY_HOSTNAME}:${proxy.address().port}` }) let response = await request({ @@ -271,7 +273,7 @@ test('Configure the agent to NOT reuse sockets', async t => { maxSockets: Infinity, maxFreeSockets: 256, scheduling: 'lifo', - proxy: `https://${proxy.address().address}:${proxy.address().port}` + proxy: `https://${PROXY_HOSTNAME}:${proxy.address().port}` }) let response = await request({ diff --git a/test/https-https.test.js b/test/https-https.test.js index b718e52..cb9ecca 100644 --- a/test/https-https.test.js +++ b/test/https-https.test.js @@ -2,6 +2,7 @@ const https = require('https') const test = require('ava') +const dns = require('dns'); const { createSecureServer, createSecureProxy } = require('./utils') const { HttpsProxyAgent } = require('../') @@ -18,9 +19,27 @@ test('Basic', async t => { const proxy = await createSecureProxy() server.on('request', (req, res) => res.end('ok')) + dns.lookup = (hostname, opts, cb) => { + cb(null, '127.0.0.1', 4); + } + + // const dnsOverrideAgent = new HttpProxyAgent({ + // keepAlive: true, + // keepAliveMsecs: 1000, + // maxSockets: 256, + // maxFreeSockets: 256, + // scheduling: 'lifo', + // proxy: `https://proxy-domain.net:${proxy.address().port}` + // }); + + // We need to override DNS resolution... + // dnsOverrideAgent.lookup = (hostname, opts, cb) => { + // cb(null, '127.0.0.1', 4); + // } + const response = await request({ method: 'GET', - hostname: server.address().address, + hostname: 'server.unit-test.com', port: server.address().port, path: '/', agent: new HttpsProxyAgent({ @@ -29,8 +48,8 @@ test('Basic', async t => { maxSockets: 256, maxFreeSockets: 256, scheduling: 'lifo', - proxy: `https://${proxy.address().address}:${proxy.address().port}` - }) + proxy: `https://proxy-domain.net:${proxy.address().port}` + }), }) let body = '' diff --git a/test/key_proxy.pem b/test/key_proxy.pem new file mode 100644 index 0000000..a74e3ed --- /dev/null +++ b/test/key_proxy.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDEle3Ro3qYiFgD +KsDX8zhG+HLKDctKx/e0Vbc5mDd1IUnPadCZVz/4rCPIZnr9eOATwLKfkveEwi5T +X7C0fBIdIoW5tqW4wYENEmMIkvJ7nHycRKs8Rd+rmBLkCPqjxxitgwyWA41fKyJq +GEMYAxfx+3F8mZzYWkp/PcXBxH1VA59kbIOuUMv73MzC1H5hlvcRU8CbE++zlkHe +kEvVDvv89ZJvWLF3aTapp1YPGFaJKuxD+fZKVaI1vlJhCfWC7c2tS5WdxcYxJQEb +srRuq/wNOty0m5pfalGI+0YxIcpL27MeOieuFNuXyFaPd/DmFLkyyoJ9yLAYUXF8 +ofMgSLH7AgMBAAECggEALlKyBotCMT03mA9z/68FXNvgmLIlbEqwmOL12PGAZ+5f +KSvjBq8jmOJfUDKt2pqoGp92t9l2z+a96dGLnwv5bLoczsU2SdH3KfBiO7v8vZoD +VwNrYjmI2jNsiCWBgiRBMWnHBnZx0rIkWuG6tabM9q1scZL0/ZpRIaiZt+4oJmbZ +WoeHgpGzUsbw3L2TnFX/xlsdvjP5N7lpMfzPpjSO0SVVuN0SMlMW0Nn2ScFYIQyt +2FT8ITb6KmnfVpvNgDUCFarG1CAdpsjuEf/e8MEbVs61vkBdaC1orDKUjphACKxe +7xN3S9s0VuQX4YSLk4c/13lM1E/Aex568bTbPfzB8QKBgQDndj9cUN8lgMccETsO +nAZDoxlBJsI4Z9sURgJdYPZAIuMRj0UaUl7ZIowOfApg+0IrRip7jZmwuiHdHaYh +w4Ciw/ZiyTBSvoRlx7xHJgBmmaMGUFvv2yC9t3BiEZPiwFGqK/mYUeorZ0loiwz+ +gBzGAl5h9RSPvxdLwyw/YiR2KQKBgQDZbSipJTpAX+TX799JYXIyfPNlp7Z/a2IL +X8tbCH3FUoCYFHarsZfIPEgAlFZJdgZYgYBupjRA5a/08tbriSUE8FBmSY17KGKx +l5kdjeU4hZQU+IMsdKAHiHutanxnvKq/gJwPMnvQMr49zypC8fcINqcrbnxQkszN +x6cvgofDgwKBgCJYtKxBP+uzwVgT4nyXgIJ26F93neh62NKYVO+AXOpFgwZvCSUP +xg1YiAn6NBwSDM6ZGeK9r2m/JRlHtghal3MPuzcLfcU5ijIEQpcYN4UCFWPxdsMP +9DrSxrV2wEgsm7Gx1tbYiPQp3oXJ5IK7hgmH/nNwx71Q8OcILj+1k42JAoGAKI0a +W0mtLppz9O4xB9+by9zQDHKWL/eYJqTsKYNQ6b90amjOpUEPHPJZP3prCXJwxosI +qBppfn0YLygne3Btrhkf9aPcNk8W8SZkEUYIrV0EfFDJLj5mJmGHJ5XHtBVVBzh2 +YsM4omEEaES+DhRQzYBb91a46tImTm7hOJQwu/8CgYBZxh/19uga8Y7ufuiJ3tFx +kOwt0Ajj6GvgjATvK6s8fEIOGQILLdGsZVUAwMF6oI2LqUmTQDBM3jSfiCbSubhq +Jwoa2xY5CCW6DYf9rfWWgOLkZTRMDYQEyHXX4aIVuIe+kzvlJcr3b4xYoGNnWnb1 +pk0N6M/ck2cZ3Aq3Osnobg== +-----END PRIVATE KEY----- diff --git a/test/key_server.pem b/test/key_server.pem new file mode 100644 index 0000000..acf49f9 --- /dev/null +++ b/test/key_server.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDmz2AKeJ7OeWvJ +RBSTjDwp3OgdPIg91IgFYPaEarCoLyf2fyk1houXAENpewrKDG9nIKuNF1hFIi1P +7X/rAf5T/GqQ20VHY+wpAc0fKoXfECqyrLLJ5GmpdElRSCfNUJQRZlCYUsE5oLCx +KxR5qoS1fKUC4mmIMO5xd+E2yqijHsstFcTAaqJ5rkpjH/1bAGI6Z5oNf1ML+09o +2y8DpxmnW3NyqqJ5De9yZr4vejaiVVer56K3Nnl32y42wjgBxc7OiouIXL8D6o5K +V0BbIZMc+YPMZUy1zpFfBbFy4FpldQl76eEmTW264UwGF3ttmhfCEx83GtnTKW3h +i+br2JC3AgMBAAECggEBAIls3eU+LmgHmarLc2jqrYPLeRS3TvNpkNeLBRyQncB1 +21iEHBg3lPOCf6DVVvY4czg3Fo26YZ9AGzSk124o0LJW72hydgxsrVc5MFWnLvBC +ovmhpA5bhqITj/fqe3Be0tqNTd10IIJcb/f9C4LpiXy5y1ItVuJ1J/O9igXioogE +Ewi1sD8OlxDXcTJeNTYj2Fksvz4a5sSUAkHRWF2qlUognFy5MPPJibOgYfqMiDfp +ipUPiX83B6wTobhEXtzKNsMTneFmzFxCcJqdMpq/FMeRg3N+0+XCjegsaRMnxStt +tUn84fj9G2MtBVnH+ocxNVM1c5mqgiHvqGzDmAwnAKECgYEA/QRLCQpFBNarfId+ +1Ps642Gjmf0/R2zm9cEL07L3EdB21Wr3tTK469feMHl7tXyLXC3o3mjrbnidnZfI +YUGKg9O8nC0O4BbPkp3IUSgyzX2llvJZycPyA1LWNJtuuc0acLvhdEFfcuYSAsjP +7J3DZwVA8aZf+qShhzEv6uhRZ2cCgYEA6YgNoAcPPKLKhv3s71+jz3F2Vw0RPj1X +cj01u7JKICXy1LJ120yFpPW0gWJROm2mA5w2XtyCfLDmExJw/bg6Ktt0nqKh/6FY +YmYr2UEUUI0iKcQ+C4TUFl1qmMXUagybpYaKoG9YD89lAgnvMQcDxxzqRrYUHda+ +yNQ4IdSgSjECgYAmnkghqhqcwXNNP5UhRvNXD2kcMOY+raWW7w8yEcfaRTpOGtSS +KJrHDJzSQ0iZi9ftiuhXQiZlJy3PhwJDrfBJbMEGCW6Sz4iBNWoE0SDn8nyazITd +4fWHglZFk0/UNjUJ7fNcfjnmXK11FVd/IxlXGRsvhxhxNj2dV+mbbjg2kwKBgQCl +jpOCOJ7/sLT9oHThep8KCHkJ27S2uAwPa/908j+ErQKK8X2GG6i/OoVeGFJXprZD +5vHQrGlBdrOVH8TEyl9KVMxHTiqkrECZea9qVK3PMU7f50TJK8CjnlRcvBsLl6ac +YVZTyLvYcYI9QMe2rS9rcD9SI/D8+mnEvFaS/UcpcQKBgQDWfIMOqCS740M8Ddkv +Ng/G9yMHPB6y1dS2ig4HULb1zeU+KsF89ujkJK1XqRFmeu+1NT9LoPrV4PVO3Whx +3PBFB52OAUU9GJ4K81g2lV3iBQJtMIsqg7Jr74P2gF1zamFqnZPQfl7ZJO6Y0BuZ +drwLCgb52cR9ooD41834W/rv0A== +-----END PRIVATE KEY----- diff --git a/test/ssl.cert b/test/ssl.cert deleted file mode 100644 index d859cfa..0000000 --- a/test/ssl.cert +++ /dev/null @@ -1,19 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDBzCCAe+gAwIBAgIJALbQMeb7k/WqMA0GCSqGSIb3DQEBBQUAMBoxGDAWBgNV -BAMMD3d3dy5mYXN0aWZ5Lm9yZzAeFw0xNzAyMDcyMDE5NDJaFw0yNzAyMDUyMDE5 -NDJaMBoxGDAWBgNVBAMMD3d3dy5mYXN0aWZ5Lm9yZzCCASIwDQYJKoZIhvcNAQEB -BQADggEPADCCAQoCggEBAKtfXzDMmU+n3A7oVVOiqp6Z5cgu1t+qgj7TadwXONvO -RZvuOcE8BZpM9tQEDE5XEIdcszDx0tWKHHSobgZAxDaEuK1PMhh/RTNvw1KzYJFm -2G38mqgm11JUni87xmIFqpgJfeCApHnWUv+3/npuQniOoVSL13jdXEifeFM8onQn -R73TVDyvMOjljTulMo0n9V8pYhVSzPnm2uxTu03p5+HosQE2bU0QKj7k8/8dwRVX -EqnTtbLoW+Wf7V2W3cr/UnfPH8JSaBWTqct0pgXqYIqOSTiWQkO7pE69mGPHrRlm -7+whp4WRriTacB3Ul+Cbx28wHU+D83ver4A8LKGVDSECAwEAAaNQME4wHQYDVR0O -BBYEFHVzTr/tNziIUrR75UHXXA84yqmgMB8GA1UdIwQYMBaAFHVzTr/tNziIUrR7 -5UHXXA84yqmgMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAKVSdGeF -vYcZOi0TG2WX7O3tSmu4G4nGxTldFiEVF89G0AU+HhNy9iwKXQLjDB7zMe/ZKbtJ -cQgc6s8eZWxBk/OoPD1WNFGstx2EO2kRkSUBKhwnOct7CIS5X+NPXyHx2Yi03JHX -unMA4WaHyo0dK4vAuali4OYdQqajNwL74avkRIxXFnZQeHzaq6tc6gX+ryB4dDSr -tYn46Lo14D5jH6PtZ8DlGK+jIzM4IE7TEp2iv0CgaTU4ryt/SHPnLxfwZUpl7gSO -EqkMAy3TlRMpv0oXM2Vh/CsyJzq2P/nY/O3bolsashSPWo9WsQTH4giYVA51ZVDK -lGksQD+oWpfa3X0= ------END CERTIFICATE----- diff --git a/test/ssl.key b/test/ssl.key deleted file mode 100644 index e3778a1..0000000 --- a/test/ssl.key +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpQIBAAKCAQEAq19fMMyZT6fcDuhVU6KqnpnlyC7W36qCPtNp3Bc4285Fm+45 -wTwFmkz21AQMTlcQh1yzMPHS1YocdKhuBkDENoS4rU8yGH9FM2/DUrNgkWbYbfya -qCbXUlSeLzvGYgWqmAl94ICkedZS/7f+em5CeI6hVIvXeN1cSJ94UzyidCdHvdNU -PK8w6OWNO6UyjSf1XyliFVLM+eba7FO7Tenn4eixATZtTRAqPuTz/x3BFVcSqdO1 -suhb5Z/tXZbdyv9Sd88fwlJoFZOpy3SmBepgio5JOJZCQ7ukTr2YY8etGWbv7CGn -hZGuJNpwHdSX4JvHbzAdT4Pze96vgDwsoZUNIQIDAQABAoIBAG278ys/R8he1yVg -lgqo9ZH7P8zwWTz9ZMsv+vAomor9SUtwvuDCO2AzejYGpY6gZ4AV1tQ3dOaxukjk -9Rbh8AJs+AhZ1t0i2b/3B95z6BkS/vFmt+2GeYhJkMT0BLMNp9AU+9p+5VLy71C5 -k6T3525k/l8x8HZ/YDFMk/LQt8GhvM6A3J3BNElKraiDVO6ZIWgQQ5wiefJkApo1 -BsptHNTx83FbnkEbAahmOR8PfKcRdKY/mZDM2WrlfoU2uwVzPV0/KdYucpsfg2et -jb5bdJzcvZDuDF4GsPi1asCSC1c403R0XGuPFW9TiBuOPxbfhYK2o60yTggX6H2X -39WBc/ECgYEA3KNGgXEWzDSLpGciUisP+MzulOdQPawBTUHNykpQklEppnZbNWCX -07dv6uasnp0pFHG4WlhZJ4+IQBpZH6xAVy9y68PvN7IDYdgMiEiYPSyqQu0rvJGa -2ZR79SHDokZ8K5oofocC839RzleNRqWqxIwhHt29sxVs73kvml6OQm0CgYEAxtbA -zbQwf6DXtFwutSgfOLgdXQK72beBdyeTcpUGbkonl5xHSbtz0CFmRpKiPnXfgg4W -GXlTrqlYF/o048B7dU9+jCKY5DXx1Yzg/EFisEIClad3WXMhNOz1vBYVH6xU3Zq1 -YuYr5dcqiCWDv89e6Y6WJOhwIDZi6RqikD2EJQUCgYEAnWSAJFCnIa8OOo4z5oe/ -kg2m2GQWUphEKXeatQbEaUwquQvPTsmEJUzDMr+xPkkAiAwDpbdGijkSyh/Bmh2H -nGpFwbf5CzMaxI6ZihK3P1SAdNO5koAQBcytjJW0eCtt4rDK2E+5pDgcBGVia5Y8 -to78BYfLDlhnaIF7mtR/CRUCgYEAvGCuzvOcUv4F/eirk5NMaQb9QqYZZD2XWVTU -O2T2b7yvX9J+M1t1cESESe4X6cbwlp1T0JSCdGIZhLXWL8Om80/52zfX07VLxP6w -FCy6G7SeEDxVNRh+6E5qzOO65YP17vDoUacxBZJgyBWKiUkkaW9dzd+sgsgj0yYZ -xz+QlyUCgYEAxdNWQnz0pR5Rt2dbIedPs7wmiZ7eAe0VjCdhMa52IyJpejdeB6Bn -Es+3lkHr0Xzty8XlQZcpbswhM8UZRgPVoBvvwQdQbv5yV+LdUu69pLM7InsdZy8u -opPY/+q9lRdJt4Pbep3pOWYeLP7k5l4vei2vOEMHRjHnoqM5etSb6RU= ------END RSA PRIVATE KEY----- diff --git a/test/utils.js b/test/utils.js index 96e352f..c92a0bc 100644 --- a/test/utils.js +++ b/test/utils.js @@ -1,17 +1,58 @@ 'use strict' // We are using self-signed certificates -process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0 +// process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0 const proxy = require('proxy') const { readFileSync } = require('fs') const { join } = require('path') const http = require('http') const https = require('https') +const dns = require('dns'); -const ssl = { - key: readFileSync(join(__dirname, 'ssl.key')), - cert: readFileSync(join(__dirname, 'ssl.cert')) +/** + * We've manually created self signed certificates for the proxy + * and for the server, with the following domains (Subject CN) + * proxy.hpagent-unit-test.com + * server.hpagent-unit-test.com + * + * This will allow us to properly test the TLS-over-TLS proxy, + * specifically that the first handshake provides the proxy SNI, not the server SNI. + * + * These certs were generated using openssl: + * openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout key_server.pem -out cert_server.pem + * openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout key_proxy.pem -out cert_proxy.pem + * + * The certs are concatenated to the can be passed to Node.JS as trusted certs: + * $ cat cert_proxy.pem > certs_unit_test.pem + * $ cat cert_server.pem >> certs_unit_test.pem + * + * using `NODE_EXTRA_CA_CERTS` (https://nodejs.org/api/cli.html#node_extra_ca_certsfile) + * + * This allows actual verification of the certs w/ hostname instead of ignoring all errors + */ + +const sslProxy = { + key: readFileSync(join(__dirname, 'key_proxy.pem')), + cert: readFileSync(join(__dirname, 'cert_proxy.pem')) +} + +const sslServer = { + key: readFileSync(join(__dirname, 'key_server.pem')), + cert: readFileSync(join(__dirname, 'cert_server.pem')) +} + +/** + * We override all DNS requests from the node process (for unit test) to resolve to + * 127.0.0.1. This allows us to use the self signed certs we made for the fake + * domains to be verified, and then the connection made to localhost. + */ + dns.lookup = (hostname, opts, cb) => { + if (typeof opts === 'function'){ + return opts(null, '127.0.0.1', 4); + } + + return cb(null, '127.0.0.1', 4); } function createProxy () { @@ -25,7 +66,7 @@ function createProxy () { function createSecureProxy () { return new Promise((resolve, reject) => { - const server = proxy(https.createServer(ssl)) + const server = proxy(https.createServer(sslProxy)) server.listen(0, '127.0.0.1', () => { resolve(server) }) @@ -43,17 +84,21 @@ function createServer (handler, callback) { function createSecureServer (handler, callback) { return new Promise((resolve, reject) => { - const server = https.createServer(ssl) + const server = https.createServer(sslServer) server.listen(0, '127.0.0.1', () => { resolve(server) }) }) } +const PROXY_HOSTNAME = `proxy.hpagent-unit-test.com`; +const SERVER_HOSTNAME = `server.hpagent-unit-test.com`; + module.exports = { - ssl, createProxy, createSecureProxy, createServer, - createSecureServer + createSecureServer, + PROXY_HOSTNAME, + SERVER_HOSTNAME } From f67e9159c0de989730471a6f6ca37c95738b6fb6 Mon Sep 17 00:00:00 2001 From: Raghu Saxena Date: Mon, 2 May 2022 13:38:50 +0800 Subject: [PATCH 04/18] Fix https over https --- test/https-https.test.js | 53 +++++++++++++--------------------------- 1 file changed, 17 insertions(+), 36 deletions(-) diff --git a/test/https-https.test.js b/test/https-https.test.js index cb9ecca..69ba951 100644 --- a/test/https-https.test.js +++ b/test/https-https.test.js @@ -2,8 +2,7 @@ const https = require('https') const test = require('ava') -const dns = require('dns'); -const { createSecureServer, createSecureProxy } = require('./utils') +const { createSecureServer, createSecureProxy, PROXY_HOSTNAME, SERVER_HOSTNAME } = require('./utils') const { HttpsProxyAgent } = require('../') function request (opts) { @@ -19,27 +18,9 @@ test('Basic', async t => { const proxy = await createSecureProxy() server.on('request', (req, res) => res.end('ok')) - dns.lookup = (hostname, opts, cb) => { - cb(null, '127.0.0.1', 4); - } - - // const dnsOverrideAgent = new HttpProxyAgent({ - // keepAlive: true, - // keepAliveMsecs: 1000, - // maxSockets: 256, - // maxFreeSockets: 256, - // scheduling: 'lifo', - // proxy: `https://proxy-domain.net:${proxy.address().port}` - // }); - - // We need to override DNS resolution... - // dnsOverrideAgent.lookup = (hostname, opts, cb) => { - // cb(null, '127.0.0.1', 4); - // } - const response = await request({ method: 'GET', - hostname: 'server.unit-test.com', + hostname: SERVER_HOSTNAME, port: server.address().port, path: '/', agent: new HttpsProxyAgent({ @@ -48,7 +29,7 @@ test('Basic', async t => { maxSockets: 256, maxFreeSockets: 256, scheduling: 'lifo', - proxy: `https://proxy-domain.net:${proxy.address().port}` + proxy: `https://${PROXY_HOSTNAME}:${proxy.address().port}` }), }) @@ -77,7 +58,7 @@ test('Connection header (keep-alive)', async t => { const response = await request({ method: 'GET', - hostname: server.address().address, + hostname: SERVER_HOSTNAME, port: server.address().port, path: '/', agent: new HttpsProxyAgent({ @@ -86,7 +67,7 @@ test('Connection header (keep-alive)', async t => { maxSockets: 256, maxFreeSockets: 256, scheduling: 'lifo', - proxy: `https://${proxy.address().address}:${proxy.address().port}` + proxy: `https://${PROXY_HOSTNAME}:${proxy.address().port}` }) }) @@ -115,7 +96,7 @@ test('Connection header (close)', async t => { const response = await request({ method: 'GET', - hostname: server.address().address, + hostname: SERVER_HOSTNAME, port: server.address().port, path: '/', agent: new HttpsProxyAgent({ @@ -124,7 +105,7 @@ test('Connection header (close)', async t => { maxSockets: Infinity, maxFreeSockets: 256, scheduling: 'lifo', - proxy: `https://${proxy.address().address}:${proxy.address().port}` + proxy: `https://${PROXY_HOSTNAME}:${proxy.address().port}` }) }) @@ -152,7 +133,7 @@ test('Proxy authentication (empty)', async t => { const response = await request({ method: 'GET', - hostname: server.address().address, + hostname: SERVER_HOSTNAME, port: server.address().port, path: '/', agent: new HttpsProxyAgent({ @@ -161,7 +142,7 @@ test('Proxy authentication (empty)', async t => { maxSockets: 256, maxFreeSockets: 256, scheduling: 'lifo', - proxy: `https://${proxy.address().address}:${proxy.address().port}` + proxy: `https://${PROXY_HOSTNAME}:${proxy.address().port}` }) }) @@ -189,7 +170,7 @@ test('Proxy authentication', async t => { const response = await request({ method: 'GET', - hostname: server.address().address, + hostname: SERVER_HOSTNAME, port: server.address().port, path: '/', agent: new HttpsProxyAgent({ @@ -198,7 +179,7 @@ test('Proxy authentication', async t => { maxSockets: 256, maxFreeSockets: 256, scheduling: 'lifo', - proxy: `https://hello:world@${proxy.address().address}:${proxy.address().port}` + proxy: `https://hello:world@${PROXY_HOSTNAME}:${proxy.address().port}` }) }) @@ -232,12 +213,12 @@ test('Configure the agent to reuse sockets', async t => { maxSockets: 256, maxFreeSockets: 256, scheduling: 'lifo', - proxy: `https://${proxy.address().address}:${proxy.address().port}` + proxy: `https://${PROXY_HOSTNAME}:${proxy.address().port}` }) let response = await request({ method: 'GET', - hostname: server.address().address, + hostname: SERVER_HOSTNAME, port: server.address().port, path: '/', agent @@ -254,7 +235,7 @@ test('Configure the agent to reuse sockets', async t => { response = await request({ method: 'GET', - hostname: server.address().address, + hostname: SERVER_HOSTNAME, port: server.address().port, path: '/', agent @@ -290,12 +271,12 @@ test('Configure the agent to NOT reuse sockets', async t => { maxSockets: Infinity, maxFreeSockets: 256, scheduling: 'lifo', - proxy: `https://${proxy.address().address}:${proxy.address().port}` + proxy: `https://${PROXY_HOSTNAME}:${proxy.address().port}` }) let response = await request({ method: 'GET', - hostname: server.address().address, + hostname: SERVER_HOSTNAME, port: server.address().port, path: '/', agent @@ -312,7 +293,7 @@ test('Configure the agent to NOT reuse sockets', async t => { response = await request({ method: 'GET', - hostname: server.address().address, + hostname: SERVER_HOSTNAME, port: server.address().port, path: '/', agent From 1ab5f06cb9d162258d594eba5f5c80ceaa3b1f4e Mon Sep 17 00:00:00 2001 From: Raghu Saxena Date: Mon, 2 May 2022 13:41:14 +0800 Subject: [PATCH 05/18] Fix http over https --- test/http-https.test.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/test/http-https.test.js b/test/http-https.test.js index f59bdd2..c6be10c 100644 --- a/test/http-https.test.js +++ b/test/http-https.test.js @@ -2,7 +2,7 @@ const https = require('https') const test = require('ava') -const { createSecureServer, createProxy } = require('./utils') +const { createSecureServer, createProxy, SERVER_HOSTNAME } = require('./utils') const { HttpsProxyAgent } = require('../') function request (opts) { @@ -20,7 +20,7 @@ test('Basic', async t => { const response = await request({ method: 'GET', - hostname: server.address().address, + hostname: SERVER_HOSTNAME, port: server.address().port, path: '/', agent: new HttpsProxyAgent({ @@ -58,7 +58,7 @@ test('Connection header (keep-alive)', async t => { const response = await request({ method: 'GET', - hostname: server.address().address, + hostname: SERVER_HOSTNAME, port: server.address().port, path: '/', agent: new HttpsProxyAgent({ @@ -96,7 +96,7 @@ test('Connection header (close)', async t => { const response = await request({ method: 'GET', - hostname: server.address().address, + hostname: SERVER_HOSTNAME, port: server.address().port, path: '/', agent: new HttpsProxyAgent({ @@ -133,7 +133,7 @@ test('Proxy authentication (empty)', async t => { const response = await request({ method: 'GET', - hostname: server.address().address, + hostname: SERVER_HOSTNAME, port: server.address().port, path: '/', agent: new HttpsProxyAgent({ @@ -170,7 +170,7 @@ test('Proxy authentication', async t => { const response = await request({ method: 'GET', - hostname: server.address().address, + hostname: SERVER_HOSTNAME, port: server.address().port, path: '/', agent: new HttpsProxyAgent({ @@ -218,7 +218,7 @@ test('Configure the agent to reuse sockets', async t => { let response = await request({ method: 'GET', - hostname: server.address().address, + hostname: SERVER_HOSTNAME, port: server.address().port, path: '/', agent @@ -235,7 +235,7 @@ test('Configure the agent to reuse sockets', async t => { response = await request({ method: 'GET', - hostname: server.address().address, + hostname: SERVER_HOSTNAME, port: server.address().port, path: '/', agent @@ -276,7 +276,7 @@ test('Configure the agent to NOT reuse sockets', async t => { let response = await request({ method: 'GET', - hostname: server.address().address, + hostname: SERVER_HOSTNAME, port: server.address().port, path: '/', agent @@ -293,7 +293,7 @@ test('Configure the agent to NOT reuse sockets', async t => { response = await request({ method: 'GET', - hostname: server.address().address, + hostname: SERVER_HOSTNAME, port: server.address().port, path: '/', agent From e7686db6c95f05f559331e0e44817b975cd56009 Mon Sep 17 00:00:00 2001 From: Raghu Saxena Date: Mon, 2 May 2022 13:43:19 +0800 Subject: [PATCH 06/18] Fix got --- test/got.test.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/test/got.test.js b/test/got.test.js index bb69b5a..f400aca 100644 --- a/test/got.test.js +++ b/test/got.test.js @@ -6,7 +6,9 @@ const { createServer, createSecureServer, createProxy, - createSecureProxy + createSecureProxy, + PROXY_HOSTNAME, + SERVER_HOSTNAME } = require('./utils') const { HttpProxyAgent, HttpsProxyAgent } = require('../') @@ -48,7 +50,7 @@ test('https to http', async t => { maxSockets: 256, maxFreeSockets: 256, scheduling: 'lifo', - proxy: `https://${proxy.address().address}:${proxy.address().port}` + proxy: `https://${PROXY_HOSTNAME}:${proxy.address().port}` }) } }) @@ -65,7 +67,7 @@ test('http to https', async t => { const proxy = await createProxy() server.on('request', (req, res) => res.end('ok')) - const response = await got(`https://${server.address().address}:${server.address().port}`, { + const response = await got(`https://${SERVER_HOSTNAME}:${server.address().port}`, { agent: { http: new HttpsProxyAgent({ keepAlive: true, @@ -90,7 +92,7 @@ test('https to https', async t => { const proxy = await createSecureProxy() server.on('request', (req, res) => res.end('ok')) - const response = await got(`https://${server.address().address}:${server.address().port}`, { + const response = await got(`https://${SERVER_HOSTNAME}:${server.address().port}`, { agent: { http: new HttpsProxyAgent({ keepAlive: true, @@ -98,7 +100,7 @@ test('https to https', async t => { maxSockets: 256, maxFreeSockets: 256, scheduling: 'lifo', - proxy: `https://${proxy.address().address}:${proxy.address().port}` + proxy: `https://${PROXY_HOSTNAME}:${proxy.address().port}` }) } }) From 42b104c7afb595a6051970a4447df86bc09a140e Mon Sep 17 00:00:00 2001 From: Raghu Saxena Date: Mon, 2 May 2022 13:44:17 +0800 Subject: [PATCH 07/18] needle fix --- test/needle.test.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/test/needle.test.js b/test/needle.test.js index 814d8a2..41d156f 100644 --- a/test/needle.test.js +++ b/test/needle.test.js @@ -6,7 +6,9 @@ const { createServer, createSecureServer, createProxy, - createSecureProxy + createSecureProxy, + PROXY_HOSTNAME, + SERVER_HOSTNAME } = require('./utils') const { HttpProxyAgent, HttpsProxyAgent } = require('../') @@ -45,7 +47,7 @@ test('https to http', async t => { maxSockets: 256, maxFreeSockets: 256, scheduling: 'lifo', - proxy: `https://${proxy.address().address}:${proxy.address().port}` + proxy: `https://${PROXY_HOSTNAME}:${proxy.address().port}` }) }) @@ -61,7 +63,7 @@ test('http to https', async t => { const proxy = await createProxy() server.on('request', (req, res) => res.end('ok')) - const response = await needle('get', `https://${server.address().address}:${server.address().port}`, { + const response = await needle('get', `https://${SERVER_HOSTNAME}:${server.address().port}`, { agent: new HttpsProxyAgent({ keepAlive: true, keepAliveMsecs: 1000, @@ -84,14 +86,14 @@ test('https to https', async t => { const proxy = await createSecureProxy() server.on('request', (req, res) => res.end('ok')) - const response = await needle('get', `https://${server.address().address}:${server.address().port}`, { + const response = await needle('get', `https://${SERVER_HOSTNAME}:${server.address().port}`, { agent: new HttpsProxyAgent({ keepAlive: true, keepAliveMsecs: 1000, maxSockets: 256, maxFreeSockets: 256, scheduling: 'lifo', - proxy: `https://${proxy.address().address}:${proxy.address().port}` + proxy: `https://${PROXY_HOSTNAME}:${proxy.address().port}` }) }) From 5086d2edbe1fe5b539d5bc000f2359461858f091 Mon Sep 17 00:00:00 2001 From: Raghu Saxena Date: Mon, 2 May 2022 13:45:03 +0800 Subject: [PATCH 08/18] Fix node fetch --- test/node-fetch.test.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/test/node-fetch.test.js b/test/node-fetch.test.js index 60f157d..0e4f562 100644 --- a/test/node-fetch.test.js +++ b/test/node-fetch.test.js @@ -6,7 +6,9 @@ const { createServer, createSecureServer, createProxy, - createSecureProxy + createSecureProxy, + PROXY_HOSTNAME, + SERVER_HOSTNAME } = require('./utils') const { HttpProxyAgent, HttpsProxyAgent } = require('../') @@ -45,7 +47,7 @@ test('https to http', async t => { maxSockets: 256, maxFreeSockets: 256, scheduling: 'lifo', - proxy: `https://${proxy.address().address}:${proxy.address().port}` + proxy: `https://${PROXY_HOSTNAME}:${proxy.address().port}` }) }) @@ -61,7 +63,7 @@ test('http to https', async t => { const proxy = await createProxy() server.on('request', (req, res) => res.end('ok')) - const response = await fetch(`https://${server.address().address}:${server.address().port}`, { + const response = await fetch(`https://${SERVER_HOSTNAME}:${server.address().port}`, { agent: new HttpsProxyAgent({ keepAlive: true, keepAliveMsecs: 1000, @@ -84,14 +86,14 @@ test('https to https', async t => { const proxy = await createSecureProxy() server.on('request', (req, res) => res.end('ok')) - const response = await fetch(`https://${server.address().address}:${server.address().port}`, { + const response = await fetch(`https://${SERVER_HOSTNAME}:${server.address().port}`, { agent: new HttpsProxyAgent({ keepAlive: true, keepAliveMsecs: 1000, maxSockets: 256, maxFreeSockets: 256, scheduling: 'lifo', - proxy: `https://${proxy.address().address}:${proxy.address().port}` + proxy: `https://${PROXY_HOSTNAME}:${proxy.address().port}` }) }) From d1d2511bb9e593df40c5df38db1da48cb37f7189 Mon Sep 17 00:00:00 2001 From: Raghu Saxena Date: Mon, 2 May 2022 13:45:46 +0800 Subject: [PATCH 09/18] Fix simple get --- test/simple-get.test.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/test/simple-get.test.js b/test/simple-get.test.js index 9468aa6..8984dda 100644 --- a/test/simple-get.test.js +++ b/test/simple-get.test.js @@ -6,7 +6,9 @@ const { createServer, createSecureServer, createProxy, - createSecureProxy + createSecureProxy, + PROXY_HOSTNAME, + SERVER_HOSTNAME } = require('./utils') const { HttpProxyAgent, HttpsProxyAgent } = require('..') @@ -56,7 +58,7 @@ test('https to http', async t => { maxSockets: 256, maxFreeSockets: 256, scheduling: 'lifo', - proxy: `https://${proxy.address().address}:${proxy.address().port}` + proxy: `https://${PROXY_HOSTNAME}:${proxy.address().port}` }) }, function (err, response, data) { if (err) { @@ -81,7 +83,7 @@ test('http to https', async t => { const response = await new Promise((resolve, reject) => { sget.concat({ - url: `https://${server.address().address}:${server.address().port}`, + url: `https://${SERVER_HOSTNAME}:${server.address().port}`, agent: new HttpsProxyAgent({ keepAlive: true, keepAliveMsecs: 1000, @@ -113,14 +115,14 @@ test('https to https', async t => { const response = await new Promise((resolve, reject) => { sget.concat({ - url: `https://${server.address().address}:${server.address().port}`, + url: `https://${SERVER_HOSTNAME}:${server.address().port}`, agent: new HttpsProxyAgent({ keepAlive: true, keepAliveMsecs: 1000, maxSockets: 256, maxFreeSockets: 256, scheduling: 'lifo', - proxy: `https://${proxy.address().address}:${proxy.address().port}` + proxy: `https://${PROXY_HOSTNAME}:${proxy.address().port}` }) }, function (err, response, data) { if (err) { From 974606a384ab98277ebd0f767e7d19d11e463887 Mon Sep 17 00:00:00 2001 From: Raghu Saxena Date: Mon, 2 May 2022 13:46:07 +0800 Subject: [PATCH 10/18] Run lint / standard --- test/https-http.test.js | 4 +--- test/https-https.test.js | 2 +- test/utils.js | 26 +++++++++++++------------- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/test/https-http.test.js b/test/https-http.test.js index 7183724..4f5801c 100644 --- a/test/https-http.test.js +++ b/test/https-http.test.js @@ -18,8 +18,6 @@ test('Basic', async t => { const proxy = await createSecureProxy() server.on('request', (req, res) => res.end('ok')) - - const response = await request({ method: 'GET', hostname: server.address().address, @@ -32,7 +30,7 @@ test('Basic', async t => { maxFreeSockets: 256, scheduling: 'lifo', proxy: `https://${PROXY_HOSTNAME}:${proxy.address().port}` - }), + }) }) let body = '' diff --git a/test/https-https.test.js b/test/https-https.test.js index 69ba951..3ad8929 100644 --- a/test/https-https.test.js +++ b/test/https-https.test.js @@ -30,7 +30,7 @@ test('Basic', async t => { maxFreeSockets: 256, scheduling: 'lifo', proxy: `https://${PROXY_HOSTNAME}:${proxy.address().port}` - }), + }) }) let body = '' diff --git a/test/utils.js b/test/utils.js index c92a0bc..d6abab4 100644 --- a/test/utils.js +++ b/test/utils.js @@ -8,27 +8,27 @@ const { readFileSync } = require('fs') const { join } = require('path') const http = require('http') const https = require('https') -const dns = require('dns'); +const dns = require('dns') /** * We've manually created self signed certificates for the proxy * and for the server, with the following domains (Subject CN) * proxy.hpagent-unit-test.com * server.hpagent-unit-test.com - * + * * This will allow us to properly test the TLS-over-TLS proxy, * specifically that the first handshake provides the proxy SNI, not the server SNI. - * + * * These certs were generated using openssl: * openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout key_server.pem -out cert_server.pem * openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout key_proxy.pem -out cert_proxy.pem - * + * * The certs are concatenated to the can be passed to Node.JS as trusted certs: * $ cat cert_proxy.pem > certs_unit_test.pem * $ cat cert_server.pem >> certs_unit_test.pem - * + * * using `NODE_EXTRA_CA_CERTS` (https://nodejs.org/api/cli.html#node_extra_ca_certsfile) - * + * * This allows actual verification of the certs w/ hostname instead of ignoring all errors */ @@ -43,16 +43,16 @@ const sslServer = { } /** - * We override all DNS requests from the node process (for unit test) to resolve to + * We override all DNS requests from the node process (for unit test) to resolve to * 127.0.0.1. This allows us to use the self signed certs we made for the fake * domains to be verified, and then the connection made to localhost. */ - dns.lookup = (hostname, opts, cb) => { - if (typeof opts === 'function'){ - return opts(null, '127.0.0.1', 4); +dns.lookup = (hostname, opts, cb) => { + if (typeof opts === 'function') { + return opts(null, '127.0.0.1', 4) } - return cb(null, '127.0.0.1', 4); + return cb(null, '127.0.0.1', 4) } function createProxy () { @@ -91,8 +91,8 @@ function createSecureServer (handler, callback) { }) } -const PROXY_HOSTNAME = `proxy.hpagent-unit-test.com`; -const SERVER_HOSTNAME = `server.hpagent-unit-test.com`; +const PROXY_HOSTNAME = 'proxy.hpagent-unit-test.com' +const SERVER_HOSTNAME = 'server.hpagent-unit-test.com' module.exports = { createProxy, From e96f40bf511ab988af5a145ac9dafeea17e176ca Mon Sep 17 00:00:00 2001 From: Raghu Saxena Date: Mon, 2 May 2022 13:47:26 +0800 Subject: [PATCH 11/18] Update test command to provide extra certs --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 364aecb..2a4f375 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "./": "./" }, "scripts": { - "test": "standard && ava -v test/*.test.js && tsd" + "test": "standard && NODE_EXTRA_CA_CERTS=test/certs_unit_test.pem ava -v test/*.test.js && tsd" }, "repository": { "type": "git", From f3e2d36c13303f814a88784cd1bc555dc7e12308 Mon Sep 17 00:00:00 2001 From: Raghu Saxena Date: Mon, 2 May 2022 13:53:26 +0800 Subject: [PATCH 12/18] version bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2a4f375..a49cad5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hpagent", - "version": "0.1.2", + "version": "0.1.3", "description": "A ready to use http and https agent for working with proxies that keeps connections alive!", "main": "index.js", "types": "index.d.ts", From 669163aa64d7e63303798904c35001304206ce3c Mon Sep 17 00:00:00 2001 From: Raghu Saxena Date: Mon, 2 May 2022 14:12:10 +0800 Subject: [PATCH 13/18] Fix implementation for Node v10 --- index.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/index.js b/index.js index da97e6f..0922c99 100644 --- a/index.js +++ b/index.js @@ -29,6 +29,10 @@ class HttpProxyAgent extends http.Agent { requestOptions.headers['proxy-authorization'] = `Basic ${base64}` } + if (this.proxy.protocol === 'https:') { + requestOptions.servername = this.proxy.hostname + } + const request = (this.proxy.protocol === 'http:' ? http : https).request(requestOptions) request.once('connect', (response, socket, head) => { request.removeAllListeners() From c3d5181c357b75113a0c6f794841400a4892f16d Mon Sep 17 00:00:00 2001 From: Raghu Saxena Date: Mon, 2 May 2022 14:17:08 +0800 Subject: [PATCH 14/18] Try env var for windows --- .github/workflows/build.yml | 5 ++++- package.json | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 444d84f..3ee021e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -20,10 +20,13 @@ jobs: with: node-version: ${{ matrix.node-version }} + - name: Set env var + run: | + echo "NODE_EXTRA_CA_CERTS=test/certs_unit_test.pem" >> $GITHUB_ENV - name: Install run: | npm install - name: Test run: | - npm test + npm run test-ci diff --git a/package.json b/package.json index a49cad5..55e5e92 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,8 @@ "./": "./" }, "scripts": { - "test": "standard && NODE_EXTRA_CA_CERTS=test/certs_unit_test.pem ava -v test/*.test.js && tsd" + "test": "standard && NODE_EXTRA_CA_CERTS=test/certs_unit_test.pem ava -v test/*.test.js && tsd", + "test-ci": "standard && ava -v test/*.test.js && tsd" }, "repository": { "type": "git", From 909810bfa599bf9057155b9eef17b9f5f1a9206f Mon Sep 17 00:00:00 2001 From: Raghu Saxena Date: Mon, 2 May 2022 14:37:33 +0800 Subject: [PATCH 15/18] env directive --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3ee021e..dc46ca9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,6 +2,9 @@ name: build on: [push, pull_request] +env: + NODE_EXTRA_CA_CERTS: test/certs_unit_test.pem + jobs: test: name: Test @@ -20,9 +23,6 @@ jobs: with: node-version: ${{ matrix.node-version }} - - name: Set env var - run: | - echo "NODE_EXTRA_CA_CERTS=test/certs_unit_test.pem" >> $GITHUB_ENV - name: Install run: | npm install From e8b766625fc4995ba56ec8449834a98e92880f24 Mon Sep 17 00:00:00 2001 From: Raghu Saxena Date: Mon, 2 May 2022 14:51:56 +0800 Subject: [PATCH 16/18] remove irelevant comment --- test/utils.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/utils.js b/test/utils.js index d6abab4..ae4f5fb 100644 --- a/test/utils.js +++ b/test/utils.js @@ -1,8 +1,5 @@ 'use strict' -// We are using self-signed certificates -// process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0 - const proxy = require('proxy') const { readFileSync } = require('fs') const { join } = require('path') From 4f50ca7c9f615ff116fe1ac62a6fbf938de4fa76 Mon Sep 17 00:00:00 2001 From: Raghu Saxena Date: Mon, 2 May 2022 19:02:25 +0800 Subject: [PATCH 17/18] undo version bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 55e5e92..626cb10 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hpagent", - "version": "0.1.3", + "version": "0.1.2", "description": "A ready to use http and https agent for working with proxies that keeps connections alive!", "main": "index.js", "types": "index.d.ts", From 2c5263a58f70626d51aa89fe1b6b4ffc4cbced71 Mon Sep 17 00:00:00 2001 From: Raghu Saxena Date: Mon, 2 May 2022 23:03:45 +0800 Subject: [PATCH 18/18] Move SSL certs, keys to fixtures, ignored in npmignore --- .github/workflows/build.yml | 2 +- .npmignore | 109 ++++++++++++++++++++++++ package.json | 2 +- test/{ => fixtures}/cert_proxy.pem | 0 test/{ => fixtures}/cert_server.pem | 0 test/{ => fixtures}/certs_unit_test.pem | 0 test/{ => fixtures}/key_proxy.pem | 0 test/{ => fixtures}/key_server.pem | 0 test/utils.js | 8 +- 9 files changed, 115 insertions(+), 6 deletions(-) create mode 100644 .npmignore rename test/{ => fixtures}/cert_proxy.pem (100%) rename test/{ => fixtures}/cert_server.pem (100%) rename test/{ => fixtures}/certs_unit_test.pem (100%) rename test/{ => fixtures}/key_proxy.pem (100%) rename test/{ => fixtures}/key_server.pem (100%) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index dc46ca9..c92d385 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,7 +3,7 @@ name: build on: [push, pull_request] env: - NODE_EXTRA_CA_CERTS: test/certs_unit_test.pem + NODE_EXTRA_CA_CERTS: test/fixtures/certs_unit_test.pem jobs: test: diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..b06b67a --- /dev/null +++ b/.npmignore @@ -0,0 +1,109 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env +.env.test + +# parcel-bundler cache (https://parceljs.org/) +.cache + +# Next.js build output +.next + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and *not* Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +.DS_Store + +# Skip the self signed SSL certs / keys for testing +test/fixtures/ diff --git a/package.json b/package.json index 626cb10..922fd71 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "./": "./" }, "scripts": { - "test": "standard && NODE_EXTRA_CA_CERTS=test/certs_unit_test.pem ava -v test/*.test.js && tsd", + "test": "standard && NODE_EXTRA_CA_CERTS=test/fixtures/certs_unit_test.pem ava -v test/*.test.js && tsd", "test-ci": "standard && ava -v test/*.test.js && tsd" }, "repository": { diff --git a/test/cert_proxy.pem b/test/fixtures/cert_proxy.pem similarity index 100% rename from test/cert_proxy.pem rename to test/fixtures/cert_proxy.pem diff --git a/test/cert_server.pem b/test/fixtures/cert_server.pem similarity index 100% rename from test/cert_server.pem rename to test/fixtures/cert_server.pem diff --git a/test/certs_unit_test.pem b/test/fixtures/certs_unit_test.pem similarity index 100% rename from test/certs_unit_test.pem rename to test/fixtures/certs_unit_test.pem diff --git a/test/key_proxy.pem b/test/fixtures/key_proxy.pem similarity index 100% rename from test/key_proxy.pem rename to test/fixtures/key_proxy.pem diff --git a/test/key_server.pem b/test/fixtures/key_server.pem similarity index 100% rename from test/key_server.pem rename to test/fixtures/key_server.pem diff --git a/test/utils.js b/test/utils.js index ae4f5fb..c5738df 100644 --- a/test/utils.js +++ b/test/utils.js @@ -30,13 +30,13 @@ const dns = require('dns') */ const sslProxy = { - key: readFileSync(join(__dirname, 'key_proxy.pem')), - cert: readFileSync(join(__dirname, 'cert_proxy.pem')) + key: readFileSync(join(__dirname, 'fixtures/key_proxy.pem')), + cert: readFileSync(join(__dirname, 'fixtures/cert_proxy.pem')) } const sslServer = { - key: readFileSync(join(__dirname, 'key_server.pem')), - cert: readFileSync(join(__dirname, 'cert_server.pem')) + key: readFileSync(join(__dirname, 'fixtures/key_server.pem')), + cert: readFileSync(join(__dirname, 'fixtures/cert_server.pem')) } /**