diff --git a/db/knex_migrations/2025-06-03-0000-add-ip-family.js b/db/knex_migrations/2025-06-03-0000-add-ip-family.js new file mode 100644 index 000000000..a3bcdc613 --- /dev/null +++ b/db/knex_migrations/2025-06-03-0000-add-ip-family.js @@ -0,0 +1,13 @@ +exports.up = function (knex) { + return knex.schema + .alterTable("monitor", function (table) { + table.boolean("ip_family").defaultTo(null); + }); +}; + +exports.down = function (knex) { + return knex.schema + .alterTable("monitor", function (table) { + table.dropColumn("ip_family"); + }); +}; diff --git a/server/model/monitor.js b/server/model/monitor.js index 741fb940e..c9844a55d 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -160,6 +160,7 @@ class Monitor extends BeanModel { smtpSecurity: this.smtpSecurity, rabbitmqNodes: JSON.parse(this.rabbitmqNodes), conditions: JSON.parse(this.conditions), + ipFamily: this.ipFamily, // ping advanced options ping_numeric: this.isPingNumeric(), @@ -426,10 +427,26 @@ class Monitor extends BeanModel { } } + let agentFamily = undefined; + if (this.ipFamily === "ipv4") { + agentFamily = 4; + } + if (this.ipFamily === "ipv6") { + agentFamily = 6; + } + const httpsAgentOptions = { maxCachedSessions: 0, // Use Custom agent to disable session reuse (https://github.com/nodejs/node/issues/3940) rejectUnauthorized: !this.getIgnoreTls(), secureOptions: crypto.constants.SSL_OP_LEGACY_SERVER_CONNECT, + autoSelectFamily: true, + ...(agentFamily ? { family: agentFamily } : {}) + }; + + const httpAgentOptions = { + maxCachedSessions: 0, + autoSelectFamily: true, + ...(agentFamily ? { family: agentFamily } : {}) }; log.debug("monitor", `[${this.name}] Prepare Options for axios`); @@ -491,6 +508,7 @@ class Monitor extends BeanModel { if (proxy && proxy.active) { const { httpAgent, httpsAgent } = Proxy.createAgents(proxy, { httpsAgentOptions: httpsAgentOptions, + httpAgentOptions: httpAgentOptions, }); options.proxy = false; @@ -499,6 +517,10 @@ class Monitor extends BeanModel { } } + if (!options.httpAgent) { + options.httpAgent = new http.Agent(httpAgentOptions); + } + if (!options.httpsAgent) { let jar = new CookieJar(); let httpsCookieAgentOptions = { diff --git a/server/server.js b/server/server.js index cba02174d..77ba695d1 100644 --- a/server/server.js +++ b/server/server.js @@ -792,6 +792,7 @@ let needSetup = false; bean.url = monitor.url; bean.method = monitor.method; bean.body = monitor.body; + bean.ipFamily = monitor.ipFamily; bean.headers = monitor.headers; bean.basic_auth_user = monitor.basic_auth_user; bean.basic_auth_pass = monitor.basic_auth_pass; diff --git a/src/lang/en.json b/src/lang/en.json index bedcd61c1..e11e9e81e 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -1116,6 +1116,9 @@ "Sender name": "Sender name", "smsplanetNeedToApproveName": "Needs to be approved in the client panel", "Disable URL in Notification": "Disable URL in Notification", + "Ip Family": "IP Family", + "ipFamilyDescriptionAutoSelect": "Uses the {happyEyeballs} for determining the IP family.", + "Happy Eyeballs algorithm": "Happy Eyeballs algorithm", "Add Another Tag": "Add Another Tag", "Staged Tags for Batch Add": "Staged Tags for Batch Add", "Clear Form": "Clear Form", diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index 95b29aa58..691414843 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -745,6 +745,20 @@ {{ $t("acceptedStatusCodesDescription") }} + +