From bde38b925e8e1bd202d39bf8a69a14a5290957ea Mon Sep 17 00:00:00 2001 From: lucas_nz <606314+lucasnz@users.noreply.github.com> Date: Sat, 14 Oct 2023 23:33:18 +1300 Subject: [PATCH] Add IP version selection --- .../2023-10-14-2127-ip-family.js | 14 ++++++++ server/model/monitor.js | 17 ++++++++-- server/monitor-types/dns.js | 14 ++++++-- server/server.js | 2 ++ server/util-server.js | 31 +++++++++++++++++ src/pages/EditMonitor.vue | 33 +++++++++++++++++++ 6 files changed, 105 insertions(+), 6 deletions(-) create mode 100644 db/knex_migrations/2023-10-14-2127-ip-family.js diff --git a/db/knex_migrations/2023-10-14-2127-ip-family.js b/db/knex_migrations/2023-10-14-2127-ip-family.js new file mode 100644 index 000000000..f62971016 --- /dev/null +++ b/db/knex_migrations/2023-10-14-2127-ip-family.js @@ -0,0 +1,14 @@ +exports.up = function (knex) { + // Add new column monitor.ip_family + return knex.schema + .alterTable("monitor", function (table) { + table.integer("ip_family").defaultTo(0).notNullable(); + }); +}; + +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 3e595f92e..01e9e4ae4 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -6,7 +6,7 @@ const { log, UP, DOWN, PENDING, MAINTENANCE, flipStatus, MAX_INTERVAL_SECOND, MI SQL_DATETIME_FORMAT } = require("../../src/util"); const { tcping, ping, checkCertificate, checkStatusCode, getTotalClientInRoom, setting, mssqlQuery, postgresQuery, mysqlQuery, mqttAsync, setSetting, httpNtlm, radius, grpcQuery, - redisPingAsync, mongodbPing, kafkaProducerAsync, getOidcTokenClientCredentials, + redisPingAsync, mongodbPing, kafkaProducerAsync, getOidcTokenClientCredentials, lookup, } = require("../util-server"); const { R } = require("redbean-node"); const { BeanModel } = require("redbean-node/dist/bean-model"); @@ -102,6 +102,7 @@ class Monitor extends BeanModel { method: this.method, hostname: this.hostname, port: this.port, + ipFamily: this.ipFamily, maxretries: this.maxretries, weight: this.weight, active: await this.isActive(), @@ -347,6 +348,16 @@ class Monitor extends BeanModel { } try { + let hostname = this.hostname; + if (this.type === "ping" || this.type === "port" ) { + try { + hostname = await lookup(this.hostname, this.ipFamily); + } catch (err) { + log.debug("monitor", err); + hostname = null; + } + } + if (await Monitor.isUnderMaintenance(this.id)) { bean.msg = "Monitor under maintenance"; bean.status = MAINTENANCE; @@ -576,12 +587,12 @@ class Monitor extends BeanModel { } } else if (this.type === "port") { - bean.ping = await tcping(this.hostname, this.port); + bean.ping = await tcping(hostname, this.port); bean.msg = ""; bean.status = UP; } else if (this.type === "ping") { - bean.ping = await ping(this.hostname, this.packetSize); + bean.ping = await ping(hostname, this.packetSize); bean.msg = ""; bean.status = UP; } else if (this.type === "push") { // Type: Push diff --git a/server/monitor-types/dns.js b/server/monitor-types/dns.js index d4cd02ab5..99ebf2b5e 100644 --- a/server/monitor-types/dns.js +++ b/server/monitor-types/dns.js @@ -1,7 +1,7 @@ const { MonitorType } = require("./monitor-type"); -const { UP } = require("../../src/util"); +const { UP, log } = require("../../src/util"); const dayjs = require("dayjs"); -const { dnsResolve } = require("../util-server"); +const { dnsResolve, lookup } = require("../util-server"); const { R } = require("redbean-node"); class DnsMonitorType extends MonitorType { @@ -15,7 +15,15 @@ class DnsMonitorType extends MonitorType { let startTime = dayjs().valueOf(); let dnsMessage = ""; - let dnsRes = await dnsResolve(monitor.hostname, monitor.dns_resolve_server, monitor.port, monitor.dns_resolve_type); + let dnsResolveServer = monitor.dns_resolve_server; + try { + dnsResolveServer = await lookup(dnsResolveServer, monitor.ipFamily); + } catch (err) { + log.debug("monitor", err); + dnsResolveServer = null; + } + + let dnsRes = await dnsResolve(monitor.hostname, dnsResolveServer, monitor.port, monitor.dns_resolve_type); heartbeat.ping = dayjs().valueOf() - startTime; if (monitor.dns_resolve_type === "A" || monitor.dns_resolve_type === "AAAA" || monitor.dns_resolve_type === "TXT" || monitor.dns_resolve_type === "PTR") { diff --git a/server/server.js b/server/server.js index 03f1cff2a..9be8e2ad8 100644 --- a/server/server.js +++ b/server/server.js @@ -785,6 +785,7 @@ let needSetup = false; bean.port = null; } + bean.ipFamily = monitor.ipFamily; bean.keyword = monitor.keyword; bean.invertKeyword = monitor.invertKeyword; bean.ignoreTls = monitor.ignoreTls; @@ -1558,6 +1559,7 @@ let needSetup = false; dns_resolve_server: monitorListData[i].dns_resolve_server, notificationIDList: monitorListData[i].notificationIDList, proxy_id: monitorListData[i].proxy_id || null, + ipFamily: monitorListData[i].ipFamily, }; if (monitorListData[i].pushToken) { diff --git a/server/util-server.js b/server/util-server.js index 181073843..ea9dc4a68 100644 --- a/server/util-server.js +++ b/server/util-server.js @@ -22,6 +22,7 @@ const protojs = require("protobufjs"); const radiusClient = require("node-radius-client"); const redis = require("redis"); const oidc = require("openid-client"); +const dns = require("dns"); const { dictionaries: { @@ -1095,3 +1096,33 @@ if (process.env.TEST_BACKEND) { return module.exports.__test[functionName]; }; } + +/** + * lookup the hostname and return a single IP Address of the specified IP address family. + * @param {string} hostname hostname to lookup + * @param {int} ipFamily valid values are 4 or 6 - for IPv4 or IPv6 respectively + * @returns {string} the resolved address + */ +module.exports.lookup = async (hostname, ipFamily) => { + return new Promise((resolve, reject) => { + if (ipFamily === 4 || ipFamily === 6) { + const options = { + family: ipFamily, + all: false + }; + dns.lookup(hostname, options, (err, address, addrFamily) => { + log.debug("lookup", `hostname: ${hostname}, ipFamily: ${ipFamily}, address: ${address}, addrFamily: IPv${addrFamily}, err: ${err}`); + if (ipFamily !== addrFamily) { + reject("Error: Incorrect IP family."); + } + if (err) { + reject(err); + } else { + resolve(address); + } + }); + } else { + resolve(hostname); + } + }); +}; diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index cab85fe95..5a0a328cc 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -462,6 +462,23 @@ + + +