mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-08-29 18:31:33 +00:00
fix: centralize outbound address validation (#1093)
This commit is contained in:
@@ -3,8 +3,9 @@ import express from "express";
|
|||||||
import https from "https";
|
import https from "https";
|
||||||
import http from "http";
|
import http from "http";
|
||||||
import { lookup } from "dns/promises";
|
import { lookup } from "dns/promises";
|
||||||
import { BlockList, isIP } from "net";
|
import { isIP } from "net";
|
||||||
import { homepageLogger } from "../../utils/logger.js";
|
import { homepageLogger } from "../../utils/logger.js";
|
||||||
|
import { isBlockedAddress } from "../../utils/safe-outbound-fetch.js";
|
||||||
|
|
||||||
export const homepageProxyRouter = express.Router();
|
export const homepageProxyRouter = express.Router();
|
||||||
|
|
||||||
@@ -17,40 +18,6 @@ const proxyCache = new Map<string, ProxyCacheEntry>();
|
|||||||
const CACHE_SIZE = 50;
|
const CACHE_SIZE = 50;
|
||||||
const FETCH_TIMEOUT_MS = 8000;
|
const FETCH_TIMEOUT_MS = 8000;
|
||||||
|
|
||||||
const blockedAddresses = new BlockList();
|
|
||||||
for (const [network, prefix] of [
|
|
||||||
["0.0.0.0", 8],
|
|
||||||
["10.0.0.0", 8],
|
|
||||||
["100.64.0.0", 10],
|
|
||||||
["127.0.0.0", 8],
|
|
||||||
["169.254.0.0", 16],
|
|
||||||
["172.16.0.0", 12],
|
|
||||||
["192.168.0.0", 16],
|
|
||||||
["198.18.0.0", 15],
|
|
||||||
["224.0.0.0", 4],
|
|
||||||
["240.0.0.0", 4],
|
|
||||||
] as const) {
|
|
||||||
blockedAddresses.addSubnet(network, prefix, "ipv4");
|
|
||||||
}
|
|
||||||
for (const [network, prefix] of [
|
|
||||||
["::", 128],
|
|
||||||
["::1", 128],
|
|
||||||
["::ffff:0:0", 96],
|
|
||||||
["fc00::", 7],
|
|
||||||
["fe80::", 10],
|
|
||||||
["ff00::", 8],
|
|
||||||
] as const) {
|
|
||||||
blockedAddresses.addSubnet(network, prefix, "ipv6");
|
|
||||||
}
|
|
||||||
|
|
||||||
function isBlockedAddress(address: string): boolean {
|
|
||||||
const family = isIP(address);
|
|
||||||
return (
|
|
||||||
family === 0 ||
|
|
||||||
blockedAddresses.check(address, family === 4 ? "ipv4" : "ipv6")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function resolvePublicUrl(rawUrl: string): Promise<{
|
async function resolvePublicUrl(rawUrl: string): Promise<{
|
||||||
url: URL;
|
url: URL;
|
||||||
address: string;
|
address: string;
|
||||||
|
|||||||
@@ -3,23 +3,9 @@ import type { SocksClientOptions } from "socks";
|
|||||||
import net from "net";
|
import net from "net";
|
||||||
import dns from "dns/promises";
|
import dns from "dns/promises";
|
||||||
import { sshLogger } from "./logger.js";
|
import { sshLogger } from "./logger.js";
|
||||||
|
import { isBlockedAddress } from "./safe-outbound-fetch.js";
|
||||||
import type { ProxyNode } from "../../types/index.js";
|
import type { ProxyNode } from "../../types/index.js";
|
||||||
|
|
||||||
function isBlockedAddress(ip: string): boolean {
|
|
||||||
if (ip === "0.0.0.0" || ip === "::1" || ip === "::") return true;
|
|
||||||
|
|
||||||
const parts = ip.split(".").map(Number);
|
|
||||||
if (parts.length !== 4) return false;
|
|
||||||
|
|
||||||
if (parts[0] === 127) return true;
|
|
||||||
if (parts[0] === 10) return true;
|
|
||||||
if (parts[0] === 172 && parts[1] >= 16 && parts[1] <= 31) return true;
|
|
||||||
if (parts[0] === 192 && parts[1] === 168) return true;
|
|
||||||
if (parts[0] === 169 && parts[1] === 254) return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function validateHost(host: string): Promise<void> {
|
async function validateHost(host: string): Promise<void> {
|
||||||
if (net.isIP(host)) {
|
if (net.isIP(host)) {
|
||||||
if (isBlockedAddress(host)) {
|
if (isBlockedAddress(host)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user