mirror of
https://github.com/louislam/uptime-kuma.git
synced 2025-03-04 08:25:57 +00:00
Add IP version selection
This commit is contained in:
parent
03e43ab364
commit
bde38b925e
6 changed files with 105 additions and 6 deletions
14
db/knex_migrations/2023-10-14-2127-ip-family.js
Normal file
14
db/knex_migrations/2023-10-14-2127-ip-family.js
Normal 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");
|
||||||
|
});
|
||||||
|
};
|
|
@ -6,7 +6,7 @@ const { log, UP, DOWN, PENDING, MAINTENANCE, flipStatus, MAX_INTERVAL_SECOND, MI
|
||||||
SQL_DATETIME_FORMAT
|
SQL_DATETIME_FORMAT
|
||||||
} = require("../../src/util");
|
} = require("../../src/util");
|
||||||
const { tcping, ping, checkCertificate, checkStatusCode, getTotalClientInRoom, setting, mssqlQuery, postgresQuery, mysqlQuery, mqttAsync, setSetting, httpNtlm, radius, grpcQuery,
|
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");
|
} = require("../util-server");
|
||||||
const { R } = require("redbean-node");
|
const { R } = require("redbean-node");
|
||||||
const { BeanModel } = require("redbean-node/dist/bean-model");
|
const { BeanModel } = require("redbean-node/dist/bean-model");
|
||||||
|
@ -102,6 +102,7 @@ class Monitor extends BeanModel {
|
||||||
method: this.method,
|
method: this.method,
|
||||||
hostname: this.hostname,
|
hostname: this.hostname,
|
||||||
port: this.port,
|
port: this.port,
|
||||||
|
ipFamily: this.ipFamily,
|
||||||
maxretries: this.maxretries,
|
maxretries: this.maxretries,
|
||||||
weight: this.weight,
|
weight: this.weight,
|
||||||
active: await this.isActive(),
|
active: await this.isActive(),
|
||||||
|
@ -347,6 +348,16 @@ class Monitor extends BeanModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
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)) {
|
if (await Monitor.isUnderMaintenance(this.id)) {
|
||||||
bean.msg = "Monitor under maintenance";
|
bean.msg = "Monitor under maintenance";
|
||||||
bean.status = MAINTENANCE;
|
bean.status = MAINTENANCE;
|
||||||
|
@ -576,12 +587,12 @@ class Monitor extends BeanModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (this.type === "port") {
|
} else if (this.type === "port") {
|
||||||
bean.ping = await tcping(this.hostname, this.port);
|
bean.ping = await tcping(hostname, this.port);
|
||||||
bean.msg = "";
|
bean.msg = "";
|
||||||
bean.status = UP;
|
bean.status = UP;
|
||||||
|
|
||||||
} else if (this.type === "ping") {
|
} else if (this.type === "ping") {
|
||||||
bean.ping = await ping(this.hostname, this.packetSize);
|
bean.ping = await ping(hostname, this.packetSize);
|
||||||
bean.msg = "";
|
bean.msg = "";
|
||||||
bean.status = UP;
|
bean.status = UP;
|
||||||
} else if (this.type === "push") { // Type: Push
|
} else if (this.type === "push") { // Type: Push
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
const { MonitorType } = require("./monitor-type");
|
const { MonitorType } = require("./monitor-type");
|
||||||
const { UP } = require("../../src/util");
|
const { UP, log } = require("../../src/util");
|
||||||
const dayjs = require("dayjs");
|
const dayjs = require("dayjs");
|
||||||
const { dnsResolve } = require("../util-server");
|
const { dnsResolve, lookup } = require("../util-server");
|
||||||
const { R } = require("redbean-node");
|
const { R } = require("redbean-node");
|
||||||
|
|
||||||
class DnsMonitorType extends MonitorType {
|
class DnsMonitorType extends MonitorType {
|
||||||
|
@ -15,7 +15,15 @@ class DnsMonitorType extends MonitorType {
|
||||||
let startTime = dayjs().valueOf();
|
let startTime = dayjs().valueOf();
|
||||||
let dnsMessage = "";
|
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;
|
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") {
|
if (monitor.dns_resolve_type === "A" || monitor.dns_resolve_type === "AAAA" || monitor.dns_resolve_type === "TXT" || monitor.dns_resolve_type === "PTR") {
|
||||||
|
|
|
@ -785,6 +785,7 @@ let needSetup = false;
|
||||||
bean.port = null;
|
bean.port = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bean.ipFamily = monitor.ipFamily;
|
||||||
bean.keyword = monitor.keyword;
|
bean.keyword = monitor.keyword;
|
||||||
bean.invertKeyword = monitor.invertKeyword;
|
bean.invertKeyword = monitor.invertKeyword;
|
||||||
bean.ignoreTls = monitor.ignoreTls;
|
bean.ignoreTls = monitor.ignoreTls;
|
||||||
|
@ -1558,6 +1559,7 @@ let needSetup = false;
|
||||||
dns_resolve_server: monitorListData[i].dns_resolve_server,
|
dns_resolve_server: monitorListData[i].dns_resolve_server,
|
||||||
notificationIDList: monitorListData[i].notificationIDList,
|
notificationIDList: monitorListData[i].notificationIDList,
|
||||||
proxy_id: monitorListData[i].proxy_id || null,
|
proxy_id: monitorListData[i].proxy_id || null,
|
||||||
|
ipFamily: monitorListData[i].ipFamily,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (monitorListData[i].pushToken) {
|
if (monitorListData[i].pushToken) {
|
||||||
|
|
|
@ -22,6 +22,7 @@ const protojs = require("protobufjs");
|
||||||
const radiusClient = require("node-radius-client");
|
const radiusClient = require("node-radius-client");
|
||||||
const redis = require("redis");
|
const redis = require("redis");
|
||||||
const oidc = require("openid-client");
|
const oidc = require("openid-client");
|
||||||
|
const dns = require("dns");
|
||||||
|
|
||||||
const {
|
const {
|
||||||
dictionaries: {
|
dictionaries: {
|
||||||
|
@ -1095,3 +1096,33 @@ if (process.env.TEST_BACKEND) {
|
||||||
return module.exports.__test[functionName];
|
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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
|
@ -462,6 +462,23 @@
|
||||||
<input id="packet-size" v-model="monitor.packetSize" type="number" class="form-control" required min="1" max="65500" step="1">
|
<input id="packet-size" v-model="monitor.packetSize" type="number" class="form-control" required min="1" max="65500" step="1">
|
||||||
</div>
|
</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 -->
|
<!-- HTTP / Keyword only -->
|
||||||
<template v-if="monitor.type === 'http' || monitor.type === 'keyword' || monitor.type === 'json-query' || monitor.type === 'grpc-keyword' ">
|
<template v-if="monitor.type === 'http' || monitor.type === 'keyword' || monitor.type === 'json-query' || monitor.type === 'grpc-keyword' ">
|
||||||
<div class="my-3">
|
<div class="my-3">
|
||||||
|
@ -1236,6 +1253,21 @@ message HealthCheckResponse {
|
||||||
"aws",
|
"aws",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
let ipFamilyOptions = [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
name: "auto-detect",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
name: "IPv4",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 6,
|
||||||
|
name: "IPv6",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
for (let i = 100; i <= 999; i++) {
|
for (let i = 100; i <= 999; i++) {
|
||||||
acceptedStatusCodeOptions.push(i.toString());
|
acceptedStatusCodeOptions.push(i.toString());
|
||||||
}
|
}
|
||||||
|
@ -1243,6 +1275,7 @@ message HealthCheckResponse {
|
||||||
this.acceptedStatusCodeOptions = acceptedStatusCodeOptions;
|
this.acceptedStatusCodeOptions = acceptedStatusCodeOptions;
|
||||||
this.dnsresolvetypeOptions = dnsresolvetypeOptions;
|
this.dnsresolvetypeOptions = dnsresolvetypeOptions;
|
||||||
this.kafkaSaslMechanismOptions = kafkaSaslMechanismOptions;
|
this.kafkaSaslMechanismOptions = kafkaSaslMechanismOptions;
|
||||||
|
this.ipFamilyOptions = ipFamilyOptions;
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Reference in a new issue