NodeJS使用代理报错:无法连接代理,证书域名与目标主机不匹配
错误原因
- 根本原因是通过HTTPS代理发起HTTPS请求时,建立CONNECT隧道阶段的证书域名校验逻辑不匹配:
request库默认使用**目标请求地址的域名(即ipv4.icanhazip.com)**校验代理返回的SSL证书,而代理返回的证书属于packetstream.io域名,两者不匹配就抛出该错误。 - 代码中设置的
rejectUnauthorized: false没有生效,是因为这个参数默认只控制和目标服务器建立连接时的证书校验,不会作用于和代理建立隧道阶段的校验。
解决方法
方法1:修改代理协议前缀(最推荐)
包括PacketStream在内的绝大多数商用HTTP代理本身是HTTP类型代理,仅需要用HTTP协议和代理建立连接,再通过CONNECT隧道转发HTTPS请求,不需要和代理本身建立HTTPS连接。仅需把代理地址的前缀从https://改成http://即可解决问题,修改后的代码示例:
const request = require('request'); // 仅修改代理前缀为http://,其余内容保持不变 const proxy = "http://USERNAME:PASSWORD@proxy.packetstream.io:PORT"; const url = "https://ipv4.icanhazip.com" const proxiedRequest = request.defaults({ 'proxy': proxy, rejectUnauthorized: false }); proxiedRequest.get(url, function(err, resp, body) { if (err) return console.log(err) console.log(body) });
该方法不需要关闭任何安全校验,不会产生额外安全风险。
方法2:关闭代理隧道阶段的证书校验
如果确实需要使用HTTPS协议连接代理,可以新增strictSSL: false参数,关闭代理隧道阶段的证书校验即可:
const proxiedRequest = request.defaults({ 'proxy': proxy, rejectUnauthorized: false, strictSSL: false // 新增该行关闭代理侧证书校验 });
注意:该方法会降低请求安全性,仅建议在测试环境使用。
方法3:自定义校验逻辑保留证书校验
如果要保留证书校验同时解决域名不匹配问题,可以自定义checkServerIdentity函数,仅校验代理证书的有效性,不强制匹配目标域名:
const proxiedRequest = request.defaults({ 'proxy': proxy, rejectUnauthorized: false, agentOptions: { checkServerIdentity: (host, cert) => { // 仅当证书属于packetstream.io域名时放行 const validDomains = ['*.packetstream.io', 'packetstream.io'] const certAltNames = cert.subjectaltname?.split(', ').map(item => item.replace('DNS:', '')) || [] const isProxyCertValid = certAltNames.some(name => validDomains.includes(name)) if (!isProxyCertValid) { return new Error(`Proxy certificate is not valid for ${host}`) } } } });
内容的提问来源于stack exchange,提问作者Lizzo
相关产品推荐
相关产品推荐

