diff --git a/server/model/monitor.js b/server/model/monitor.js index e106f7ab33..16fac903cb 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -7,7 +7,7 @@ dayjs.extend(timezone); const axios = require("axios"); const { Prometheus } = require("../prometheus"); const { log, UP, DOWN, PENDING, flipStatus, TimeLogger } = require("../../src/util"); -const { tcping, ping, dnsResolve, checkCertificate, checkStatusCode, getTotalClientInRoom, setting, errorLog, mqttAsync } = require("../util-server"); +const { tcping, ping, dnsResolve, checkCertificate, checkStatusCode, getTotalClientInRoom, setting, errorLog, mqttAsync, tlsAsync } = require("../util-server"); const { R } = require("redbean-node"); const { BeanModel } = require("redbean-node/dist/bean-model"); const { Notification } = require("../notification"); @@ -434,6 +434,12 @@ class Monitor extends BeanModel { interval: this.interval, }); bean.status = UP; + } else if (this.type === "tls") { + bean.msg = await tlsAsync(this.hostname, this.port, { + keyword: this.keyword, + interval: this.interval, + }); + bean.status = UP; } else { bean.msg = "Unknown Monitor Type"; bean.status = PENDING; diff --git a/server/util-server.js b/server/util-server.js index 39a2d90409..b3ea1dbae2 100644 --- a/server/util-server.js +++ b/server/util-server.js @@ -10,6 +10,7 @@ const chardet = require("chardet"); const fs = require("fs"); const nodeJsUtil = require("util"); const mqtt = require("mqtt"); +const tls = require("tls"); // From ping-lite exports.WIN = /^win/.test(process.platform); @@ -172,6 +173,61 @@ exports.mqttAsync = function (hostname, topic, okMessage, options = {}) { }); }; +exports.tlsAsync = function (hostname, port, options = {}) { + return new Promise((resolve, reject) => { + const { keyword, interval = 60 } = options; + + const timeoutID = setTimeout(() => { + log.debug("tls", "Timeout triggered"); + client.end(); + reject(new Error("Timeout")); + }, interval * 1000 * 0.8); + + log.debug("tls", "Connecting to " + hostname + ":" + port); + + let client = tls.connect(port, hostname, {}); + + client.on("secureConnect", () => { + const cipher = client.getCipher(); + log.debug("tls", "Connected: authorized: " + client.authorized + ", cipher: " + (cipher ? cipher.name : '')); + }); + + client.on("error", (error) => { + log.debug("tls", "Error: " + error); + client.destroy(); + clearTimeout(timeoutID); + reject(error); + }); + + client.on("data", (data) => { + const dataString = data.toString().replace(/^\s+|\s+$/g, ""); + log.debug("tls", "Data: '" + dataString + "', keyword: '" + (keyword || "") + "'"); + client.end(); + clearTimeout(timeoutID); + let success = false; + let message = undefined; + if (keyword) { + if (dataString.includes(keyword)) { + success = true; + message = "Data contains keyword"; + } else { + message = "Data does not contain keyword"; + } + } else { + message = "Data received"; + success = true; + } + if (success) { + log.debug("tls", "Success: " + message); + resolve(message); + } else { + log.debug("tls", "Failure: " + message); + reject(new Error(message)); + } + }); + }); +}; + /** * Resolves a given record using the specified DNS server * @param {string} hostname The hostname of the record to lookup diff --git a/src/pages/Details.vue b/src/pages/Details.vue index d40561fe0b..78727b8c2c 100644 --- a/src/pages/Details.vue +++ b/src/pages/Details.vue @@ -9,7 +9,7 @@ {{ monitor.url }} TCP Ping {{ monitor.hostname }}:{{ monitor.port }} Ping: {{ monitor.hostname }} - +
{{ $t("Keyword") }}: {{ monitor.keyword }}
diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index 43f3452731..91ee1a0243 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -35,6 +35,9 @@ + @@ -61,7 +64,7 @@ -
+
@@ -70,15 +73,15 @@
- -
+ +
- -
+ +