mirror of
https://github.com/louislam/uptime-kuma.git
synced 2025-05-23 23:32:34 +02:00
feat: add TCP tls
monitor (new proposition)
This commit is contained in:
parent
484ec5345f
commit
601a6ae580
4 changed files with 43 additions and 85 deletions
|
@ -24,6 +24,7 @@ const { CookieJar } = require("tough-cookie");
|
||||||
const { HttpsCookieAgent } = require("http-cookie-agent/http");
|
const { HttpsCookieAgent } = require("http-cookie-agent/http");
|
||||||
const https = require("https");
|
const https = require("https");
|
||||||
const http = require("http");
|
const http = require("http");
|
||||||
|
const tls = require("tls");
|
||||||
|
|
||||||
const rootCertificates = rootCertificatesFingerprints();
|
const rootCertificates = rootCertificatesFingerprints();
|
||||||
|
|
||||||
|
@ -580,6 +581,45 @@ 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(this.hostname, this.port);
|
||||||
|
if (this.isEnabledExpiryNotification()) {
|
||||||
|
const host = this.hostname;
|
||||||
|
const port = this.port || 443;
|
||||||
|
try {
|
||||||
|
const options = {
|
||||||
|
host,
|
||||||
|
port,
|
||||||
|
servername: host,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Convert TLS connect to a Promise and await it
|
||||||
|
const tlsInfoObject = await new Promise((resolve, reject) => {
|
||||||
|
const socket = tls.connect(options);
|
||||||
|
|
||||||
|
socket.on("secureConnect", () => {
|
||||||
|
try {
|
||||||
|
const info = checkCertificate(socket);
|
||||||
|
socket.end();
|
||||||
|
resolve(info);
|
||||||
|
} catch (error) {
|
||||||
|
socket.end();
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on("error", (error) => {
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.setTimeout(10000, () => {
|
||||||
|
socket.end();
|
||||||
|
reject(new Error("Connection timed out"));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
await this.handleTlsInfo(tlsInfoObject);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("Retrieve certificate failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
bean.msg = "";
|
bean.msg = "";
|
||||||
bean.status = UP;
|
bean.status = UP;
|
||||||
|
|
||||||
|
|
|
@ -1,77 +0,0 @@
|
||||||
const { MonitorType } = require("./monitor-type");
|
|
||||||
const { UP, DOWN } = require("../../src/util");
|
|
||||||
const { checkCertificate, setting, setSetting } = require("../util-server");
|
|
||||||
const tls = require("tls");
|
|
||||||
|
|
||||||
class TlsCertificateMonitorType extends MonitorType {
|
|
||||||
name = "tlsCheck";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
async check(monitor, heartbeat, server) {
|
|
||||||
const host = monitor.hostname;
|
|
||||||
const port = monitor.port || 443;
|
|
||||||
let notifyDays = await setting("tlsExpiryNotifyDays");
|
|
||||||
if (notifyDays == null || !Array.isArray(notifyDays)) {
|
|
||||||
// Reset Default
|
|
||||||
await setSetting("tlsExpiryNotifyDays", [ 7, 14, 21 ], "general");
|
|
||||||
notifyDays = [ 7, 14, 21 ];
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const options = {
|
|
||||||
host,
|
|
||||||
port,
|
|
||||||
servername: host,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Convert TLS connect to a Promise and await it
|
|
||||||
const tlsInfoObject = await new Promise((resolve, reject) => {
|
|
||||||
const socket = tls.connect(options);
|
|
||||||
|
|
||||||
socket.on("secureConnect", () => {
|
|
||||||
try {
|
|
||||||
const info = checkCertificate(socket);
|
|
||||||
socket.end();
|
|
||||||
resolve(info);
|
|
||||||
} catch (error) {
|
|
||||||
socket.end();
|
|
||||||
reject(error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on("error", (error) => {
|
|
||||||
reject(error);
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.setTimeout(10000, () => {
|
|
||||||
socket.end();
|
|
||||||
reject(new Error("Connection timed out"));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const certInfo = tlsInfoObject.certInfo;
|
|
||||||
|
|
||||||
await monitor.updateTlsInfo(tlsInfoObject);
|
|
||||||
const alertDays = notifyDays.filter(targetDays => targetDays >= certInfo.daysRemaining);
|
|
||||||
|
|
||||||
if (alertDays.length === 0) {
|
|
||||||
heartbeat.status = UP;
|
|
||||||
heartbeat.msg = "";
|
|
||||||
} else {
|
|
||||||
const alertDay = Math.min(...alertDays);
|
|
||||||
heartbeat.status = DOWN;
|
|
||||||
heartbeat.msg = `Certificate expires in less thant ${alertDay} days`;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
heartbeat.status = DOWN;
|
|
||||||
heartbeat.msg = `Error checking SSL certificate: ${error.message}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
TlsCertificateMonitorType,
|
|
||||||
};
|
|
||||||
|
|
|
@ -117,7 +117,6 @@ class UptimeKumaServer {
|
||||||
UptimeKumaServer.monitorTypeList["snmp"] = new SNMPMonitorType();
|
UptimeKumaServer.monitorTypeList["snmp"] = new SNMPMonitorType();
|
||||||
UptimeKumaServer.monitorTypeList["mongodb"] = new MongodbMonitorType();
|
UptimeKumaServer.monitorTypeList["mongodb"] = new MongodbMonitorType();
|
||||||
UptimeKumaServer.monitorTypeList["rabbitmq"] = new RabbitMqMonitorType();
|
UptimeKumaServer.monitorTypeList["rabbitmq"] = new RabbitMqMonitorType();
|
||||||
UptimeKumaServer.monitorTypeList["tls"] = new TlsCertificateMonitorType();
|
|
||||||
|
|
||||||
// Allow all CORS origins (polling) in development
|
// Allow all CORS origins (polling) in development
|
||||||
let cors = undefined;
|
let cors = undefined;
|
||||||
|
@ -557,5 +556,4 @@ const { GroupMonitorType } = require("./monitor-types/group");
|
||||||
const { SNMPMonitorType } = require("./monitor-types/snmp");
|
const { SNMPMonitorType } = require("./monitor-types/snmp");
|
||||||
const { MongodbMonitorType } = require("./monitor-types/mongodb");
|
const { MongodbMonitorType } = require("./monitor-types/mongodb");
|
||||||
const { RabbitMqMonitorType } = require("./monitor-types/rabbitmq");
|
const { RabbitMqMonitorType } = require("./monitor-types/rabbitmq");
|
||||||
const { TlsCertificateMonitorType } = require("./monitor-types/tls");
|
|
||||||
const Monitor = require("./model/monitor");
|
const Monitor = require("./model/monitor");
|
||||||
|
|
|
@ -21,9 +21,6 @@
|
||||||
<option value="port">
|
<option value="port">
|
||||||
TCP Port
|
TCP Port
|
||||||
</option>
|
</option>
|
||||||
<option value="tls">
|
|
||||||
TCP Port (tls check)
|
|
||||||
</option>
|
|
||||||
<option value="ping">
|
<option value="ping">
|
||||||
Ping
|
Ping
|
||||||
</option>
|
</option>
|
||||||
|
@ -285,7 +282,7 @@
|
||||||
|
|
||||||
<!-- Hostname -->
|
<!-- Hostname -->
|
||||||
<!-- TCP Port / Ping / DNS / Steam / MQTT / Radius / Tailscale Ping / SNMP only -->
|
<!-- TCP Port / Ping / DNS / Steam / MQTT / Radius / Tailscale Ping / SNMP only -->
|
||||||
<div v-if="monitor.type === 'port' || monitor.type === 'ping' || monitor.type === 'dns' || monitor.type === 'steam' || monitor.type === 'gamedig' || monitor.type === 'mqtt' || monitor.type === 'radius' || monitor.type === 'tailscale-ping' || monitor.type === 'snmp' || monitor.type === 'tls'" class="my-3">
|
<div v-if="monitor.type === 'port' || monitor.type === 'ping' || monitor.type === 'dns' || monitor.type === 'steam' || monitor.type === 'gamedig' || monitor.type === 'mqtt' || monitor.type === 'radius' || monitor.type === 'tailscale-ping' || monitor.type === 'snmp'" class="my-3">
|
||||||
<label for="hostname" class="form-label">{{ $t("Hostname") }}</label>
|
<label for="hostname" class="form-label">{{ $t("Hostname") }}</label>
|
||||||
<input
|
<input
|
||||||
id="hostname"
|
id="hostname"
|
||||||
|
@ -300,7 +297,7 @@
|
||||||
|
|
||||||
<!-- Port -->
|
<!-- Port -->
|
||||||
<!-- For TCP Port / Steam / MQTT / Radius Type / SNMP -->
|
<!-- For TCP Port / Steam / MQTT / Radius Type / SNMP -->
|
||||||
<div v-if="monitor.type === 'port' || monitor.type === 'steam' || monitor.type === 'gamedig' || monitor.type === 'mqtt' || monitor.type === 'radius' || monitor.type === 'snmp' || monitor.type === 'tls'" class="my-3">
|
<div v-if="monitor.type === 'port' || monitor.type === 'steam' || monitor.type === 'gamedig' || monitor.type === 'mqtt' || monitor.type === 'radius' || monitor.type === 'snmp'" class="my-3">
|
||||||
<label for="port" class="form-label">{{ $t("Port") }}</label>
|
<label for="port" class="form-label">{{ $t("Port") }}</label>
|
||||||
<input id="port" v-model="monitor.port" type="number" class="form-control" required min="0" max="65535" step="1">
|
<input id="port" v-model="monitor.port" type="number" class="form-control" required min="0" max="65535" step="1">
|
||||||
</div>
|
</div>
|
||||||
|
@ -615,7 +612,7 @@
|
||||||
|
|
||||||
<h2 v-if="monitor.type !== 'push'" class="mt-5 mb-2">{{ $t("Advanced") }}</h2>
|
<h2 v-if="monitor.type !== 'push'" class="mt-5 mb-2">{{ $t("Advanced") }}</h2>
|
||||||
|
|
||||||
<div v-if="monitor.type === 'http' || monitor.type === 'keyword' || monitor.type === 'json-query' || monitor.type === 'tls' " class="my-3 form-check" :title="monitor.ignoreTls ? $t('ignoredTLSError') : ''">
|
<div v-if="monitor.type === 'http' || monitor.type === 'keyword' || monitor.type === 'json-query' || monitor.type === 'port' " class="my-3 form-check" :title="monitor.ignoreTls ? $t('ignoredTLSError') : ''">
|
||||||
<input id="expiry-notification" v-model="monitor.expiryNotification" class="form-check-input" type="checkbox" :disabled="monitor.ignoreTls">
|
<input id="expiry-notification" v-model="monitor.expiryNotification" class="form-check-input" type="checkbox" :disabled="monitor.ignoreTls">
|
||||||
<label class="form-check-label" for="expiry-notification">
|
<label class="form-check-label" for="expiry-notification">
|
||||||
{{ $t("Certificate Expiry Notification") }}
|
{{ $t("Certificate Expiry Notification") }}
|
||||||
|
|
Loading…
Add table
Reference in a new issue