fix: 申请证书没有使用到系统设置的http代理的bug

pull/229/head
xiaojunnuo 2024-10-22 01:01:04 +08:00
parent 4a7018ac26
commit 3db216f515
10 changed files with 151 additions and 25 deletions

View File

@ -20,6 +20,7 @@
"asn1js": "^3.0.5", "asn1js": "^3.0.5",
"axios": "^1.7.2", "axios": "^1.7.2",
"debug": "^4.3.5", "debug": "^4.3.5",
"http-proxy-agent": "^7.0.2",
"https-proxy-agent": "^7.0.5", "https-proxy-agent": "^7.0.5",
"node-forge": "^1.3.1" "node-forge": "^1.3.1"
}, },

View File

@ -0,0 +1,101 @@
const nodeHttp = require('node:http');
const https = require('node:https');
const { HttpProxyAgent } = require('http-proxy-agent');
const { HttpsProxyAgent } = require('https-proxy-agent');
const { log } = require('./logger');
function createAgent(opts = {}) {
let httpAgent;
let
httpsAgent;
const httpProxy = process.env.HTTP_PROXY || process.env.http_proxy;
if (httpProxy) {
log(`acme use httpProxy:${httpProxy}`);
httpAgent = new HttpProxyAgent(httpProxy, opts);
}
else {
httpAgent = new nodeHttp.Agent(opts);
}
const httpsProxy = process.env.HTTPS_PROXY || process.env.https_proxy;
if (httpsProxy) {
log(`acme use httpsProxy:${httpsProxy}`);
httpsAgent = new HttpsProxyAgent(httpsProxy, opts);
}
else {
httpsAgent = new https.Agent(opts);
}
return {
httpAgent,
httpsAgent,
};
}
let defaultAgents = createAgent();
function getGlobalAgents() {
return defaultAgents;
}
function setGlobalProxy(opts) {
log('acme setGlobalProxy:', opts);
if (opts.httpProxy) {
process.env.HTTP_PROXY = opts.httpProxy;
}
if (opts.httpsProxy) {
process.env.HTTPS_PROXY = opts.httpsProxy;
}
defaultAgents = createAgent();
}
class HttpError extends Error {
constructor(error) {
super(error || error.message);
if (!error) {
return;
}
if (error.message.indexOf('ssl3_get_record:wrong version number') >= 0) {
this.message = 'http协议错误服务端要求http协议请检查是否使用了https请求';
}
this.name = error.name;
this.code = error.code;
this.cause = error.cause;
if (error.response) {
this.status = error.response.status;
this.statusText = error.response.statusText;
this.response = {
data: error.response.data,
};
}
let url = '';
if (error.config) {
this.request = {
baseURL: error.config.baseURL,
url: error.config.url,
method: error.config.method,
params: error.config.params,
data: error.config.data,
};
url = error.config.baseURL + error.config.url;
}
if (url) {
this.message = `${this.message}:${url}`;
}
delete error.response;
delete error.config;
delete error.request;
// logger.error(error);
}
}
module.exports = {
setGlobalProxy,
createAgent,
getGlobalAgents,
HttpError,
};

View File

@ -30,6 +30,7 @@ class AcmeApi {
} }
} }
} }
console.log(locationUrl, mapping);
return locationUrl; return locationUrl;
} }

View File

@ -1,11 +1,11 @@
/** /**
* Axios instance * Axios instance
*/ */
const axios = require('axios'); const axios = require('axios');
const { parseRetryAfterHeader } = require('./util'); const { parseRetryAfterHeader } = require('./util');
const { log } = require('./logger'); const { log } = require('./logger');
const pkg = require('./../package.json'); const pkg = require('./../package.json');
const Agents = require('./agents');
const { AxiosError } = axios; const { AxiosError } = axios;
@ -24,8 +24,8 @@ instance.defaults.acmeSettings = {
httpsChallengePort: 443, httpsChallengePort: 443,
tlsAlpnChallengePort: 443, tlsAlpnChallengePort: 443,
retryMaxAttempts: 5, retryMaxAttempts: 3,
retryDefaultDelay: 5, retryDefaultDelay: 3,
}; };
// instance.defaults.proxy = { // instance.defaults.proxy = {
// host: '192.168.34.139', // host: '192.168.34.139',
@ -56,19 +56,26 @@ function isRetryableError(error) {
/* https://github.com/axios/axios/blob/main/lib/core/settle.js */ /* https://github.com/axios/axios/blob/main/lib/core/settle.js */
function validateStatus(response) { function validateStatus(response) {
const validator = response.config.retryValidateStatus; if (!response) {
return new Error('Response is undefined');
}
let validator = null;
if (response.config) {
validator = response.config.retryValidateStatus;
}
if (!response.status || !validator || validator(response.status)) { if (!response.status || !validator || validator(response.status)) {
return response; return response;
} }
throw new AxiosError( const err = new AxiosError(
`Request failed with status code ${response.status}`, `Request failed with status code ${response.status}`,
(Math.floor(response.status / 100) === 4) ? AxiosError.ERR_BAD_REQUEST : AxiosError.ERR_BAD_RESPONSE, (Math.floor(response.status / 100) === 4) ? AxiosError.ERR_BAD_REQUEST : AxiosError.ERR_BAD_RESPONSE,
response.config, response.config,
response.request, response.request,
response, response,
); );
throw new Agents.HttpError(err);
} }
/* Pass all responses through the error interceptor */ /* Pass all responses through the error interceptor */
@ -76,8 +83,17 @@ instance.interceptors.request.use((config) => {
if (!('retryValidateStatus' in config)) { if (!('retryValidateStatus' in config)) {
config.retryValidateStatus = config.validateStatus; config.retryValidateStatus = config.validateStatus;
} }
config.validateStatus = () => false; config.validateStatus = () => false;
const agents = Agents.getGlobalAgents();
// if (config.skipSslVerify) {
// logger.info('跳过SSL验证');
// agents = createAgent({ rejectUnauthorized: false } as any);
// }
// delete config.skipSslVerify;
config.httpsAgent = agents.httpsAgent;
config.httpAgent = agents.httpAgent;
config.proxy = false; // 必须 否则还会走一层代理,
return config; return config;
}); });
@ -86,7 +102,7 @@ instance.interceptors.response.use(null, async (error) => {
const { config, response } = error; const { config, response } = error;
if (!config) { if (!config) {
return Promise.reject(error); return Promise.reject(new Agents.HttpError(error));
} }
/* Pick up errors we want to retry */ /* Pick up errors we want to retry */
@ -115,6 +131,9 @@ instance.interceptors.response.use(null, async (error) => {
} }
} }
if (!response) {
return Promise.reject(new Agents.HttpError(error));
}
/* Validate and return response */ /* Validate and return response */
return validateStatus(response); return validateStatus(response);
}); });

View File

@ -3,21 +3,9 @@
*/ */
const { createHmac, createSign, constants: { RSA_PKCS1_PADDING } } = require('crypto'); const { createHmac, createSign, constants: { RSA_PKCS1_PADDING } } = require('crypto');
const { HttpsProxyAgent } = require('https-proxy-agent');
const { getJwk } = require('./crypto'); const { getJwk } = require('./crypto');
const { log } = require('./logger'); const { log } = require('./logger');
const axios1 = require('./axios'); const axios = require('./axios');
const httpsProxy = process.env.HTTPS_PROXY || process.env.https_proxy;
let httpsAgent = null;
if (httpsProxy) {
httpsAgent = new HttpsProxyAgent(httpsProxy);
log(`use https_proxy:${httpsProxy}`);
}
const axios = axios1.create({
proxy: false,
httpsAgent,
});
/** /**
* ACME HTTP client * ACME HTTP client

View File

@ -39,6 +39,7 @@ exports.forge = require('./crypto/forge');
*/ */
exports.axios = require('./axios'); exports.axios = require('./axios');
exports.agents = require('./agents');
/** /**
* Logger * Logger

View File

@ -192,6 +192,7 @@ export const forge: CryptoLegacyInterface;
export const axios: AxiosInstance; export const axios: AxiosInstance;
export const agents: any;
/** /**
* Logger * Logger
*/ */

View File

@ -35,6 +35,14 @@ export class HttpError extends Error {
params: error.config?.params, params: error.config?.params,
data: error.config?.data, data: error.config?.data,
}; };
let url = error.config?.url;
if (error.config?.baseURL) {
url = error.config?.baseURL + url;
}
if (url) {
this.message = `${this.message} : ${url}`;
}
this.response = { this.response = {
data: error.response?.data, data: error.response?.data,
}; };
@ -62,6 +70,10 @@ export function setGlobalProxy(opts: { httpProxy?: string; httpsProxy?: string }
defaultAgents = createAgent(); defaultAgents = createAgent();
} }
export function getGlobalAgents() {
return defaultAgents;
}
/** /**
* @description * @description
*/ */

View File

@ -27,6 +27,7 @@
"license": "AGPL", "license": "AGPL",
"dependencies": { "dependencies": {
"@certd/basic": "^1.26.10", "@certd/basic": "^1.26.10",
"@certd/acme-client": "^1.26.10",
"@certd/pipeline": "^1.26.10", "@certd/pipeline": "^1.26.10",
"@midwayjs/cache": "~3.14.0", "@midwayjs/cache": "~3.14.0",
"@midwayjs/core": "~3.17.1", "@midwayjs/core": "~3.17.1",

View File

@ -7,7 +7,7 @@ import { BaseSettings, SysInstallInfo, SysPrivateSettings, SysPublicSettings, Sy
import * as _ from 'lodash-es'; import * as _ from 'lodash-es';
import { BaseService } from '../../../basic/index.js'; import { BaseService } from '../../../basic/index.js';
import { logger, setGlobalProxy } from '@certd/basic'; import { logger, setGlobalProxy } from '@certd/basic';
import { agents } from '@certd/acme-client';
/** /**
* *
*/ */
@ -23,7 +23,6 @@ export class SysSettingsService extends BaseService<SysSettingsEntity> {
getRepository() { getRepository() {
return this.repository; return this.repository;
} }
async getById(id: any): Promise<SysSettingsEntity | null> { async getById(id: any): Promise<SysSettingsEntity | null> {
const entity = await this.info(id); const entity = await this.info(id);
if (!entity) { if (!entity) {
@ -129,10 +128,12 @@ export class SysSettingsService extends BaseService<SysSettingsEntity> {
async reloadPrivateSettings() { async reloadPrivateSettings() {
const bean = await this.getPrivateSettings(); const bean = await this.getPrivateSettings();
if (bean.httpProxy || bean.httpsProxy) { if (bean.httpProxy || bean.httpsProxy) {
setGlobalProxy({ const opts = {
httpProxy: bean.httpProxy, httpProxy: bean.httpProxy,
httpsProxy: bean.httpsProxy, httpsProxy: bean.httpsProxy,
}); };
setGlobalProxy(opts);
agents.setGlobalProxy(opts);
} }
} }