fixes mixed ipv4-ipv6 handling in cidr module
This commit is contained in:
parent
7d517a4c5f
commit
6352df5d5a
|
@ -314,10 +314,10 @@ router.post("/maintenance", (req, res) => {
|
|||
const temps = users.filter((u) => u.type === "temporary");
|
||||
temps.forEach((user) => {
|
||||
user.expiresAt = Date.now();
|
||||
user.disabledReason = "Admin forced expiration."
|
||||
user.disabledReason = "Admin forced expiration.";
|
||||
userStore.upsertUser(user);
|
||||
});
|
||||
invalidatePowHmacKey()
|
||||
invalidatePowHmacKey();
|
||||
flash.type = "success";
|
||||
flash.message = `${temps.length} temporary users marked for expiration.`;
|
||||
break;
|
||||
|
@ -370,8 +370,8 @@ router.post("/maintenance", (req, res) => {
|
|||
ipv4RangeMap.set(subnet, userSet);
|
||||
} else if (parsed.kind() === "ipv6") {
|
||||
const subnet =
|
||||
parsed.toNormalizedString().split(":").slice(0, 3).join(":") +
|
||||
"::/56";
|
||||
parsed.toNormalizedString().split(":").slice(0, 4).join(":") +
|
||||
"::/48";
|
||||
const userSet = ipv6RangeMap.get(subnet) || new Set<string>();
|
||||
userSet.add(u.token);
|
||||
ipv6RangeMap.set(subnet, userSet);
|
||||
|
|
|
@ -158,7 +158,7 @@ function getSelfServiceLinks() {
|
|||
links.unshift(["Request a user token", "/user/captcha"]);
|
||||
}
|
||||
|
||||
return `<div class="self-service-links"">${links
|
||||
return `<div class="self-service-links">${links
|
||||
.map(([text, link]) => `<a target="_blank" href="${link}">${text}</a>`)
|
||||
.join(" | ")}</div>`;
|
||||
}
|
||||
|
|
|
@ -24,9 +24,9 @@ export function parseCidrs(cidrs: string[] | string): [IPv4 | IPv6, number][] {
|
|||
.map((input) => {
|
||||
try {
|
||||
if (input.includes("/")) {
|
||||
return ipaddr.parseCIDR(input);
|
||||
return ipaddr.parseCIDR(input.trim());
|
||||
} else {
|
||||
const ip = ipaddr.parse(input);
|
||||
const ip = ipaddr.parse(input.trim());
|
||||
return ipaddr.parseCIDR(
|
||||
`${input}/${ip.kind() === "ipv4" ? 32 : 128}`
|
||||
);
|
||||
|
@ -44,23 +44,25 @@ export function createWhitelistMiddleware(
|
|||
base: string[] | string
|
||||
) {
|
||||
let cidrs: string[] = [];
|
||||
let matchers: [IPv4 | IPv6, number][] = [];
|
||||
let ranges: Record<string, [IPv4 | IPv6, number][]> = {};
|
||||
|
||||
const middleware = (req: Request, res: Response, next: NextFunction) => {
|
||||
const middleware: IpCheckMiddleware = (req, res, next) => {
|
||||
const ip = ipaddr.process(req.ip);
|
||||
const allowed = matchers.some((cidr) => ip.match(cidr));
|
||||
if (allowed) {
|
||||
const match = ipaddr.subnetMatch(ip, ranges, "none");
|
||||
if (match === name) {
|
||||
return next();
|
||||
} else {
|
||||
req.log.warn({ ip: req.ip, list: name }, "Request denied by whitelist");
|
||||
res.status(403).json({ error: `Forbidden (by ${name})` });
|
||||
}
|
||||
req.log.warn({ ip: req.ip, list: name }, "Request denied by whitelist");
|
||||
res.status(403).json({ error: `Forbidden (by ${name})` });
|
||||
};
|
||||
middleware.ranges = [] as string[];
|
||||
middleware.updateRanges = (ranges: string[] | string) => {
|
||||
cidrs = Array.isArray(ranges) ? ranges.slice() : [ranges];
|
||||
matchers = parseCidrs(cidrs);
|
||||
log.info({ list: name, matchers }, "IP whitelist configured");
|
||||
middleware.ranges = cidrs;
|
||||
middleware.updateRanges = (r: string[] | string) => {
|
||||
cidrs = Array.isArray(r) ? r.slice() : [r];
|
||||
const parsed = parseCidrs(cidrs);
|
||||
ranges = { [name]: parsed };
|
||||
middleware.ranges = cidrs;
|
||||
log.info({ list: name, ranges }, "IP whitelist configured");
|
||||
};
|
||||
|
||||
middleware.updateRanges(base);
|
||||
|
@ -74,24 +76,27 @@ export function createBlacklistMiddleware(
|
|||
base: string[] | string
|
||||
) {
|
||||
let cidrs: string[] = [];
|
||||
let matchers: [IPv4 | IPv6, number][] = [];
|
||||
let ranges: Record<string, [IPv4 | IPv6, number][]> = {};
|
||||
|
||||
const middleware = (req: Request, res: Response, next: NextFunction) => {
|
||||
const middleware: IpCheckMiddleware = (req, res, next) => {
|
||||
const ip = ipaddr.process(req.ip);
|
||||
const denied = matchers.some((cidr) => ip.match(cidr));
|
||||
if (denied) {
|
||||
const match = ipaddr.subnetMatch(ip, ranges, "none");
|
||||
if (match === name) {
|
||||
req.log.warn({ ip: req.ip, list: name }, "Request denied by blacklist");
|
||||
return res.status(403).json({ error: `Forbidden (by ${name})` });
|
||||
} else {
|
||||
return next();
|
||||
}
|
||||
return next();
|
||||
};
|
||||
middleware.ranges = [] as string[];
|
||||
middleware.updateRanges = (ranges: string[] | string) => {
|
||||
cidrs = Array.isArray(ranges) ? ranges.slice() : [ranges];
|
||||
matchers = parseCidrs(cidrs);
|
||||
log.info({ list: name, matchers }, "IP blacklist configured");
|
||||
middleware.ranges = cidrs;
|
||||
middleware.updateRanges = (r: string[] | string) => {
|
||||
cidrs = Array.isArray(r) ? r.slice() : [r];
|
||||
const parsed = parseCidrs(cidrs);
|
||||
ranges = { [name]: parsed };
|
||||
middleware.ranges = cidrs;
|
||||
log.info({ list: name, ranges }, "IP blacklist configured");
|
||||
};
|
||||
|
||||
middleware.updateRanges(base);
|
||||
|
||||
blacklists.set(name, middleware);
|
||||
|
|
|
@ -100,5 +100,3 @@
|
|||
</head>
|
||||
<body>
|
||||
<%- include("partials/shared_flash", { flashData: flash }) %>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -335,7 +335,7 @@
|
|||
elapsedTime += (Date.now() - lastUpdateTime) / 1000;
|
||||
lastUpdateTime = Date.now();
|
||||
const hashRate = totalHashes / elapsedTime;
|
||||
const expectedTimeRemaining = (workFactor - totalHashes) / hashRate;
|
||||
const timeRemaining = (workFactor - totalHashes) / hashRate;
|
||||
const progress = 100 * (1 - Math.exp(-totalHashes / workFactor));
|
||||
|
||||
const formatTime = (time) => {
|
||||
|
@ -362,11 +362,11 @@
|
|||
|
||||
document.getElementById("captcha-progress").style.width = Math.min(progress, 100) + "%";
|
||||
document.getElementById("captcha-progress-text").value = `
|
||||
Average hashes needed: ${workFactor.toLocaleString()}
|
||||
Solution probability: 1 in ${workFactor.toLocaleString()} hashes
|
||||
Hashes computed: ${totalHashes.toLocaleString()}${note}
|
||||
Elapsed time: ${formatTime(elapsedTime)}
|
||||
Hash rate: ${hashRate.toFixed(2)} H/s
|
||||
Workers: ${workers.length}${isMobileWebkit ? " (iOS/iPadOS detected)" : ""}
|
||||
${active ? `Approx. time remaining: ${formatTime(expectedTimeRemaining)}` : "Verification task stopped"}`.trim();
|
||||
${active ? `Average time remaining: ${formatTime(timeRemaining)}` : "Verification task stopped"}`.trim();
|
||||
}
|
||||
</script>
|
||||
|
|
Loading…
Reference in New Issue