Making node-fetch Work with a TLS Intercept Proxy
Making Node’s fetch() trust specific CA certificates when using a proxy is not straightforward. This is one way to hack up node-fetch to trust your favorite intercept proxy’s CA cert.
https://www.npmjs.com/package/https-proxy-agent says this about the HttpsProxyAgent contstructor:
new HttpsProxyAgent(Object options)
...
Any other options given are passed to the net.connect()/tls.connect() functions.
but simply adding your proxy’s CA to the options object doesn’t work.
Hacking Up node-fetch
in /node_modules/node-fetch/src/index.js, add your CA cert near the top:
const myCA = `-----BEGIN CERTIFICATE-----
MIID5zCCAs+gAwIBAgIUBk0FAGkiIkNfvaHWZKV3oRkc1r4wDQYJKoZIhvcNAQEL
BQAwgYIxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJPSDESMBAGA1UEBwwJQ2xldmVs
YW5kMQ8wDQYDVQQKDAZTdGV2ZTAxGTAXBgNVBAMMEHN0ZXZlIGRldnRlc3QgQ0Ex
JjAkBgkqhkiG9w0BCQEWF3N0ZXZlQGh1cnJpY2FuZWxhYnMuY29tMB4XDTIyMDIx
NzA4MjA0M1oXDTMyMDIxNTA4MjA0M1owgYIxCzAJBgNVBAYTAlVTMQswCQYDVQQI
DAJPSDESMBAGA1UEBwwJQ2xldmVsYW5kMQ8wDQYDVQQKDAZTdGV2ZTAxGTAXBgNV
BAMMEHN0ZXZlIGRldnRlc3QgQ0ExJjAkBgkqhkiG9w0BCQEWF3N0ZXZlQGh1cnJp
Y2FuZWxhYnMuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqck5
gDqD561J0afRxw0jU1ZEH2je+S8pHNdQuG3Duel5QT2egtKYxCjB9L1Md3WTdhHg
52j2C0WjHLx0fk2Xnz/bGSdInKw6VzqFSJ1wWaYfMrJHT19n/i/18mNDz5HeLDV3
0GzJWMNRjpdnQz0ScaRXjXoEnpSnlR7S988DTXsM+SJRy03QzHmjsg2JCqrb5vF9
LXWDjjK4SpIYkqqSG+Btq9N+fjkBT3gez2fXXw2y7sds+QN0UwKitetiVCZAIB2v
D2Yxtvpn9M71oH3JCF14lIknbCHU87iWKxztqISl+QPa45eX/BUZ4szvw9dLMe6Y
FcteEsLz3fsCzUIs0wIDAQABo1MwUTAdBgNVHQ4EFgQUplPBB2saUNSuqpvwmnmv
T8gEGnAwHwYDVR0jBBgwFoAUplPBB2saUNSuqpvwmnmvT8gEGnAwDwYDVR0TAQH/
BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAR/RNasLm8ArpihH09xasv/LazvbA
LAaSnrgFZEJVW9d3q+60DPmOpudpjptkn5LAu+LXZjJtMveq88CdO9DgReXQqSJn
Bg8tZbyvaJnueIQieou4C+0tMvYNXiwkEHEdL/eaYyyTHcxfn3f2TDWAoGVb5R0k
vmqsMO0jJqRoRVZ1+sMIGVX8jLCnqzjnDMJkXD76RLQNcPeMZGM/X+Uyfuq1yqcB
6I8Gv0yauEg9vagBE1qDtlqNmJfFXLd2hD1s4nodLVPDRhe3UM0n1S3pA0UlCRWh
9x1zFisK4Bl1E5k1ReWlmvE5JfCCUvJO3KGonZ3WHTgWBVfgu+cW9KFXGw==
-----END CERTIFICATE-----`;
find this, near line 92:
// Send request
const request_ = send(parsedURL.toString(), options);
prepend this:
// Copy options
if( options_.hasOwnProperty('agent') && options_.agent.hasOwnProperty('proxy') ) {
for( let copyProp of ['ca','cert'] ) {
if( options_.agent.proxy.hasOwnProperty(copyProp) )
options[copyProp] = options_.agent.proxy[copyProp];
}
}
Example
'use strict';
import fetch from 'node-fetch';
import HttpsProxyAgent from 'https-proxy-agent';
const myCA = `-----BEGIN CERTIFICATE-----
MIID5zCCAs+gAwIBAgIUBk0FAGkiIkNfvaHWZKV3oRkc1r4wDQYJKoZIhvcNAQEL
...
9x1zFisK4Bl1E5k1ReWlmvE5JfCCUvJO3KGonZ3WHTgWBVfgu+cW9KFXGw==
-----END CERTIFICATE-----`;
function main ()
{
const proxyAgent = new HttpsProxyAgent({
host: '172.25.105.161',
port: 8066,
ca: [myCA],
});
const fetchOpts = {
agent: proxyAgent,
};
fetch('https://www.google.com', fetchOpts).then( resp => {
console.log(`got a resp with status ${resp.status}`);
});
}
if( require.main === module )
main();