This commit is contained in:
lucas_nz 2024-07-31 15:58:26 +00:00 committed by GitHub
commit 760bf3603f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 103 additions and 6 deletions

View file

@ -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");
});
};

View file

@ -5,7 +5,7 @@ const { log, UP, DOWN, PENDING, MAINTENANCE, flipStatus, MAX_INTERVAL_SECOND, MI
SQL_DATETIME_FORMAT, evaluateJsonQuery
} = require("../../src/util");
const { tcping, ping, checkCertificate, checkStatusCode, getTotalClientInRoom, setting, mssqlQuery, postgresQuery, mysqlQuery, setSetting, httpNtlm, radius, grpcQuery,
redisPingAsync, kafkaProducerAsync, getOidcTokenClientCredentials, rootCertificatesFingerprints, axiosAbortSignal
redisPingAsync, kafkaProducerAsync, getOidcTokenClientCredentials, rootCertificatesFingerprints, axiosAbortSignal, lookup,
} = require("../util-server");
const { R } = require("redbean-node");
const { BeanModel } = require("redbean-node/dist/bean-model");
@ -110,6 +110,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(),
@ -385,6 +386,16 @@ class Monitor extends BeanModel {
}
try {
let HostnameOrIp = this.hostname;
if (this.type === "ping" || this.type === "port" ) {
try {
HostnameOrIp = await lookup(this.hostname, this.ipFamily);
} catch (err) {
log.debug("monitor", `Error resolving ${this.hostname}. Error: ${err}`);
throw new Error(`Error resolving ${this.hostname}. Error: ${err}`);
}
}
if (await Monitor.isUnderMaintenance(this.id)) {
bean.msg = "Monitor under maintenance";
bean.status = MAINTENANCE;
@ -612,12 +623,12 @@ class Monitor extends BeanModel {
}
} else if (this.type === "port") {
bean.ping = await tcping(this.hostname, this.port);
bean.ping = await tcping(HostnameOrIp, this.port);
bean.msg = "";
bean.status = UP;
} else if (this.type === "ping") {
bean.ping = await ping(this.hostname, this.packetSize);
bean.ping = await ping(HostnameOrIp, this.packetSize);
bean.msg = "";
bean.status = UP;
} else if (this.type === "push") { // Type: Push

View file

@ -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 {
@ -14,7 +14,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", `Error resolving ${monitor.dns_resolve_server}. Error: ${err}`);
throw new Error(`Error resolving ${monitor.dns_resolve_server}. Error: ${err}`);
}
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") {

View file

@ -782,6 +782,7 @@ let needSetup = false;
bean.port = null;
}
bean.ipFamily = monitor.ipFamily;
bean.keyword = monitor.keyword;
bean.invertKeyword = monitor.invertKeyword;
bean.ignoreTls = monitor.ignoreTls;

View file

@ -18,6 +18,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 tls = require("tls");
const {
@ -1037,6 +1038,35 @@ if (process.env.TEST_BACKEND) {
};
}
/**
* 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);
}
});
/**
* Generates an abort signal with the specified timeout.
* @param {number} timeoutMs - The timeout in milliseconds.

View file

@ -590,6 +590,23 @@
<input id="packet-size" v-model="monitor.packetSize" type="number" class="form-control" required min="1" max="65500" step="1">
</div>
<!-- Resolve Family -->
<!-- TCP Port / Ping / DNS -->
<div v-if="monitor.type === 'port' || monitor.type === 'ping' || monitor.type === 'dns' " class="my-3">
<label for="ip-family" class="form-label">{{ $t("IP Address Family") }}</label>
<VueMultiselect
id="ip-family"
v-model="monitor.ipFamily"
:options="ipFamilyOptions.map(i => i.id)"
:custom-label="opt => ipFamilyOptions.find(e => e.id === opt).name"
:multiple="false"
:preselect-first="true"
:max-height="500"
:allow-empty="false"
:taggable="false"
></VueMultiselect>
</div>
<!-- HTTP / Keyword only -->
<template v-if="monitor.type === 'http' || monitor.type === 'keyword' || monitor.type === 'json-query' || monitor.type === 'grpc-keyword' ">
<div class="my-3">
@ -1436,6 +1453,21 @@ message HealthCheckResponse {
"aws",
];
let ipFamilyOptions = [
{
id: 0,
name: "auto-detect",
},
{
id: 4,
name: "IPv4",
},
{
id: 6,
name: "IPv6",
},
];
for (let i = 100; i <= 999; i++) {
acceptedStatusCodeOptions.push(i.toString());
}
@ -1443,6 +1475,7 @@ message HealthCheckResponse {
this.acceptedStatusCodeOptions = acceptedStatusCodeOptions;
this.dnsresolvetypeOptions = dnsresolvetypeOptions;
this.kafkaSaslMechanismOptions = kafkaSaslMechanismOptions;
this.ipFamilyOptions = ipFamilyOptions;
},
methods: {
/**