mirror of
https://github.com/louislam/uptime-kuma.git
synced 2024-11-30 10:14:03 +00:00
Merge branch '1.23.X' into version-merge
# Conflicts: # package-lock.json # package.json # server/server.js # server/uptime-kuma-server.js
This commit is contained in:
commit
1a47563eb8
5 changed files with 69 additions and 36 deletions
|
@ -99,7 +99,6 @@ function disconnectAllSocketClients(username, password) {
|
||||||
|
|
||||||
// Disconnect all socket connections
|
// Disconnect all socket connections
|
||||||
const socket = io(localWebSocketURL, {
|
const socket = io(localWebSocketURL, {
|
||||||
transports: [ "websocket" ],
|
|
||||||
reconnection: false,
|
reconnection: false,
|
||||||
timeout: 5000,
|
timeout: 5000,
|
||||||
});
|
});
|
||||||
|
|
|
@ -46,7 +46,7 @@
|
||||||
"build-docker-nightly-local": "npm run build && docker build -f docker/dockerfile -t louislam/uptime-kuma:nightly2 --target nightly .",
|
"build-docker-nightly-local": "npm run build && docker build -f docker/dockerfile -t louislam/uptime-kuma:nightly2 --target nightly .",
|
||||||
"build-docker-pr-test": "docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64 -t louislam/uptime-kuma:pr-test2 --target pr-test2 . --push",
|
"build-docker-pr-test": "docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64 -t louislam/uptime-kuma:pr-test2 --target pr-test2 . --push",
|
||||||
"upload-artifacts": "docker buildx build -f docker/dockerfile --platform linux/amd64 -t louislam/uptime-kuma:upload-artifact --build-arg VERSION --build-arg GITHUB_TOKEN --target upload-artifact . --progress plain",
|
"upload-artifacts": "docker buildx build -f docker/dockerfile --platform linux/amd64 -t louislam/uptime-kuma:upload-artifact --build-arg VERSION --build-arg GITHUB_TOKEN --target upload-artifact . --progress plain",
|
||||||
"setup": "git checkout 1.23.9 && npm ci --production && npm run download-dist",
|
"setup": "git checkout 1.23.10 && npm ci --production && npm run download-dist",
|
||||||
"download-dist": "node extra/download-dist.js",
|
"download-dist": "node extra/download-dist.js",
|
||||||
"mark-as-nightly": "node extra/mark-as-nightly.js",
|
"mark-as-nightly": "node extra/mark-as-nightly.js",
|
||||||
"reset-password": "node extra/reset-password.js",
|
"reset-password": "node extra/reset-password.js",
|
||||||
|
|
|
@ -53,7 +53,10 @@ if (!process.env.UPTIME_KUMA_WS_ORIGIN_CHECK) {
|
||||||
|
|
||||||
log.info("server", "Env: " + process.env.NODE_ENV);
|
log.info("server", "Env: " + process.env.NODE_ENV);
|
||||||
log.debug("server", "Inside Container: " + (process.env.UPTIME_KUMA_IS_CONTAINER === "1"));
|
log.debug("server", "Inside Container: " + (process.env.UPTIME_KUMA_IS_CONTAINER === "1"));
|
||||||
log.info("server", "WebSocket Origin Check: " + process.env.UPTIME_KUMA_WS_ORIGIN_CHECK);
|
|
||||||
|
if (process.env.UPTIME_KUMA_WS_ORIGIN_CHECK === "bypass") {
|
||||||
|
log.warn("server", "WebSocket Origin Check: " + process.env.UPTIME_KUMA_WS_ORIGIN_CHECK);
|
||||||
|
}
|
||||||
|
|
||||||
const checkVersion = require("./check-version");
|
const checkVersion = require("./check-version");
|
||||||
log.info("server", "Uptime Kuma Version: " + checkVersion.version);
|
log.info("server", "Uptime Kuma Version: " + checkVersion.version);
|
||||||
|
|
|
@ -114,39 +114,64 @@ class UptimeKumaServer {
|
||||||
UptimeKumaServer.monitorTypeList["dns"] = new DnsMonitorType();
|
UptimeKumaServer.monitorTypeList["dns"] = new DnsMonitorType();
|
||||||
UptimeKumaServer.monitorTypeList["mqtt"] = new MqttMonitorType();
|
UptimeKumaServer.monitorTypeList["mqtt"] = new MqttMonitorType();
|
||||||
|
|
||||||
|
// Allow all CORS origins (polling) in development
|
||||||
|
let cors = undefined;
|
||||||
|
if (isDev) {
|
||||||
|
cors = {
|
||||||
|
origin: "*",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
this.io = new Server(this.httpServer, {
|
this.io = new Server(this.httpServer, {
|
||||||
allowRequest: (req, callback) => {
|
cors,
|
||||||
let isOriginValid = true;
|
allowRequest: async (req, callback) => {
|
||||||
const bypass = isDev || process.env.UPTIME_KUMA_WS_ORIGIN_CHECK === "bypass";
|
let transport;
|
||||||
|
// It should be always true, but just in case, because this property is not documented
|
||||||
|
if (req._query) {
|
||||||
|
transport = req._query.transport;
|
||||||
|
} else {
|
||||||
|
log.error("socket", "Ops!!! Cannot get transport type, assume that it is polling");
|
||||||
|
transport = "polling";
|
||||||
|
}
|
||||||
|
|
||||||
if (!bypass) {
|
const clientIP = await this.getClientIPwithProxy(req.connection.remoteAddress, req.headers);
|
||||||
|
log.info("socket", `New ${transport} connection, IP = ${clientIP}`);
|
||||||
|
|
||||||
|
// The following check is only for websocket connections, polling connections are already protected by CORS
|
||||||
|
if (transport === "polling") {
|
||||||
|
callback(null, true);
|
||||||
|
} else if (transport === "websocket") {
|
||||||
|
const bypass = process.env.UPTIME_KUMA_WS_ORIGIN_CHECK === "bypass";
|
||||||
|
if (bypass) {
|
||||||
|
log.info("auth", "WebSocket origin check is bypassed");
|
||||||
|
callback(null, true);
|
||||||
|
} else if (!req.headers.origin) {
|
||||||
|
log.info("auth", "WebSocket with no origin is allowed");
|
||||||
|
callback(null, true);
|
||||||
|
} else {
|
||||||
let host = req.headers.host;
|
let host = req.headers.host;
|
||||||
|
|
||||||
// If this is set, it means the request is from the browser
|
|
||||||
let origin = req.headers.origin;
|
let origin = req.headers.origin;
|
||||||
|
|
||||||
// If this is from the browser, check if the origin is allowed
|
|
||||||
if (origin) {
|
|
||||||
try {
|
try {
|
||||||
let originURL = new URL(origin);
|
let originURL = new URL(origin);
|
||||||
|
let xForwardedFor;
|
||||||
|
if (await Settings.get("trustProxy")) {
|
||||||
|
xForwardedFor = req.headers["x-forwarded-for"];
|
||||||
|
}
|
||||||
|
|
||||||
if (host !== originURL.host) {
|
if (host !== originURL.host && xForwardedFor !== originURL.host) {
|
||||||
isOriginValid = false;
|
callback(null, false);
|
||||||
log.error("auth", `Origin (${origin}) does not match host (${host}), IP: ${req.socket.remoteAddress}`);
|
log.error("auth", `Origin (${origin}) does not match host (${host}), IP: ${clientIP}`);
|
||||||
|
} else {
|
||||||
|
callback(null, true);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Invalid origin url, probably not from browser
|
// Invalid origin url, probably not from browser
|
||||||
isOriginValid = false;
|
callback(null, false);
|
||||||
log.error("auth", `Invalid origin url (${origin}), IP: ${req.socket.remoteAddress}`);
|
log.error("auth", `Invalid origin url (${origin}), IP: ${clientIP}`);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
log.info("auth", `Origin is not set, IP: ${req.socket.remoteAddress}`);
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
log.debug("auth", "Origin check is bypassed");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(null, isOriginValid);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -290,20 +315,27 @@ class UptimeKumaServer {
|
||||||
/**
|
/**
|
||||||
* Get the IP of the client connected to the socket
|
* Get the IP of the client connected to the socket
|
||||||
* @param {Socket} socket Socket to query
|
* @param {Socket} socket Socket to query
|
||||||
* @returns {string} IP of client
|
* @returns {Promise<string>} IP of client
|
||||||
*/
|
*/
|
||||||
async getClientIP(socket) {
|
getClientIP(socket) {
|
||||||
let clientIP = socket.client.conn.remoteAddress;
|
return this.getClientIPwithProxy(socket.client.conn.remoteAddress, socket.client.conn.request.headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} clientIP Raw client IP
|
||||||
|
* @param {IncomingHttpHeaders} headers HTTP headers
|
||||||
|
* @returns {Promise<string>} Client IP with proxy (if trusted)
|
||||||
|
*/
|
||||||
|
async getClientIPwithProxy(clientIP, headers) {
|
||||||
if (clientIP === undefined) {
|
if (clientIP === undefined) {
|
||||||
clientIP = "";
|
clientIP = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (await Settings.get("trustProxy")) {
|
if (await Settings.get("trustProxy")) {
|
||||||
const forwardedFor = socket.client.conn.request.headers["x-forwarded-for"];
|
const forwardedFor = headers["x-forwarded-for"];
|
||||||
|
|
||||||
return (typeof forwardedFor === "string" ? forwardedFor.split(",")[0].trim() : null)
|
return (typeof forwardedFor === "string" ? forwardedFor.split(",")[0].trim() : null)
|
||||||
|| socket.client.conn.request.headers["x-real-ip"]
|
|| headers["x-real-ip"]
|
||||||
|| clientIP.replace(/^::ffff:/, "");
|
|| clientIP.replace(/^::ffff:/, "");
|
||||||
} else {
|
} else {
|
||||||
return clientIP.replace(/^::ffff:/, "");
|
return clientIP.replace(/^::ffff:/, "");
|
||||||
|
|
|
@ -99,21 +99,20 @@ export default {
|
||||||
|
|
||||||
this.socket.initedSocketIO = true;
|
this.socket.initedSocketIO = true;
|
||||||
|
|
||||||
let protocol = (location.protocol === "https:") ? "wss://" : "ws://";
|
let protocol = location.protocol + "//";
|
||||||
|
|
||||||
let wsHost;
|
let url;
|
||||||
const env = process.env.NODE_ENV || "production";
|
const env = process.env.NODE_ENV || "production";
|
||||||
if (env === "development" && isDevContainer()) {
|
if (env === "development" && isDevContainer()) {
|
||||||
wsHost = protocol + getDevContainerServerHostname();
|
url = protocol + getDevContainerServerHostname();
|
||||||
} else if (env === "development" || localStorage.dev === "dev") {
|
} else if (env === "development" || localStorage.dev === "dev") {
|
||||||
wsHost = protocol + location.hostname + ":3001";
|
url = protocol + location.hostname + ":3001";
|
||||||
} else {
|
} else {
|
||||||
wsHost = protocol + location.host;
|
// Connect to the current url
|
||||||
|
url = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
socket = io(wsHost, {
|
socket = io(url);
|
||||||
transports: [ "websocket" ],
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on("info", (info) => {
|
socket.on("info", (info) => {
|
||||||
this.info = info;
|
this.info = info;
|
||||||
|
|
Loading…
Reference in a new issue