mirror of
https://github.com/fosrl/pangolin.git
synced 2025-08-24 11:15:31 +02:00
Smoothing over initial connection issues
This commit is contained in:
parent
d771317e3f
commit
609435328e
5 changed files with 80 additions and 74 deletions
|
@ -1 +1,2 @@
|
||||||
export * from "./exitNodes";
|
export * from "./exitNodes";
|
||||||
|
export * from "./shared";
|
30
server/lib/exitNodes/shared.ts
Normal file
30
server/lib/exitNodes/shared.ts
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import { db, exitNodes } from "@server/db";
|
||||||
|
import config from "@server/lib/config";
|
||||||
|
import { findNextAvailableCidr } from "@server/lib/ip";
|
||||||
|
|
||||||
|
export async function getNextAvailableSubnet(): Promise<string> {
|
||||||
|
// Get all existing subnets from routes table
|
||||||
|
const existingAddresses = await db
|
||||||
|
.select({
|
||||||
|
address: exitNodes.address
|
||||||
|
})
|
||||||
|
.from(exitNodes);
|
||||||
|
|
||||||
|
const addresses = existingAddresses.map((a) => a.address);
|
||||||
|
let subnet = findNextAvailableCidr(
|
||||||
|
addresses,
|
||||||
|
config.getRawConfig().gerbil.block_size,
|
||||||
|
config.getRawConfig().gerbil.subnet_group
|
||||||
|
);
|
||||||
|
if (!subnet) {
|
||||||
|
throw new Error("No available subnets remaining in space");
|
||||||
|
}
|
||||||
|
|
||||||
|
// replace the last octet with 1
|
||||||
|
subnet =
|
||||||
|
subnet.split(".").slice(0, 3).join(".") +
|
||||||
|
".1" +
|
||||||
|
"/" +
|
||||||
|
subnet.split("/")[1];
|
||||||
|
return subnet;
|
||||||
|
}
|
|
@ -155,14 +155,11 @@ export class TraefikConfigManager {
|
||||||
method: error.config?.method
|
method: error.config?.method
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
logger.error(
|
logger.error("Error updating local SNI:", error);
|
||||||
"Error updating local SNI:",
|
|
||||||
error
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.error("No exit node found");
|
logger.error("No exit node found. Has gerbil registered yet?");
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error("Failed to post domains to SNI proxy:", err);
|
logger.error("Failed to post domains to SNI proxy:", err);
|
||||||
|
@ -213,18 +210,25 @@ export class TraefikConfigManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// logger.debug(
|
||||||
|
// `Successfully retrieved traefik config: ${JSON.stringify(traefikConfig)}`
|
||||||
|
// );
|
||||||
|
|
||||||
const badgerMiddlewareName = "badger";
|
const badgerMiddlewareName = "badger";
|
||||||
|
if (traefikConfig?.http?.middlewares) {
|
||||||
traefikConfig.http.middlewares[badgerMiddlewareName] = {
|
traefikConfig.http.middlewares[badgerMiddlewareName] = {
|
||||||
plugin: {
|
plugin: {
|
||||||
[badgerMiddlewareName]: {
|
[badgerMiddlewareName]: {
|
||||||
apiBaseUrl: new URL(
|
apiBaseUrl: new URL(
|
||||||
"/api/v1",
|
"/api/v1",
|
||||||
`http://${
|
`http://${
|
||||||
config.getRawConfig().server.internal_hostname
|
config.getRawConfig().server
|
||||||
|
.internal_hostname
|
||||||
}:${config.getRawConfig().server.internal_port}`
|
}:${config.getRawConfig().server.internal_port}`
|
||||||
).href,
|
).href,
|
||||||
userSessionCookieName:
|
userSessionCookieName:
|
||||||
config.getRawConfig().server.session_cookie_name,
|
config.getRawConfig().server
|
||||||
|
.session_cookie_name,
|
||||||
|
|
||||||
// deprecated
|
// deprecated
|
||||||
accessTokenQueryParam:
|
accessTokenQueryParam:
|
||||||
|
@ -237,10 +241,7 @@ export class TraefikConfigManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
}
|
||||||
// logger.debug(
|
|
||||||
// `Successfully retrieved traefik config: ${JSON.stringify(traefikConfig)}`
|
|
||||||
// );
|
|
||||||
|
|
||||||
return { domains, traefikConfig };
|
return { domains, traefikConfig };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
|
@ -150,25 +150,20 @@ export class TokenManager {
|
||||||
this.token = response.data.data.token;
|
this.token = response.data.data.token;
|
||||||
logger.debug("Token refreshed successfully");
|
logger.debug("Token refreshed successfully");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error("Failed to refresh token:", error);
|
|
||||||
|
|
||||||
if (axios.isAxiosError(error)) {
|
if (axios.isAxiosError(error)) {
|
||||||
if (error.response) {
|
logger.error("Error updating proxy mapping:", {
|
||||||
throw new Error(
|
message: error.message,
|
||||||
`Failed to get token with status code: ${error.response.status}`
|
code: error.code,
|
||||||
);
|
status: error.response?.status,
|
||||||
} else if (error.request) {
|
statusText: error.response?.statusText,
|
||||||
throw new Error(
|
url: error.config?.url,
|
||||||
"Failed to request new token: No response received"
|
method: error.config?.method
|
||||||
);
|
});
|
||||||
} else {
|
} else {
|
||||||
throw new Error(
|
logger.error("Error updating proxy mapping:", error);
|
||||||
`Failed to request new token: ${error.message}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new Error(`Failed to get token: ${error}`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
throw new Error("Failed to refresh token");
|
||||||
} finally {
|
} finally {
|
||||||
this.isRefreshing = false;
|
this.isRefreshing = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import { findNextAvailableCidr } from "@server/lib/ip";
|
||||||
import { fromError } from "zod-validation-error";
|
import { fromError } from "zod-validation-error";
|
||||||
import { getAllowedIps } from "../target/helpers";
|
import { getAllowedIps } from "../target/helpers";
|
||||||
import { proxyToRemote } from "@server/lib/remoteProxy";
|
import { proxyToRemote } from "@server/lib/remoteProxy";
|
||||||
|
import { getNextAvailableSubnet } from "@server/lib/exitNodes";
|
||||||
// Define Zod schema for request validation
|
// Define Zod schema for request validation
|
||||||
const getConfigSchema = z.object({
|
const getConfigSchema = z.object({
|
||||||
publicKey: z.string(),
|
publicKey: z.string(),
|
||||||
|
@ -104,6 +105,11 @@ export async function getConfig(
|
||||||
|
|
||||||
// STOP HERE IN HYBRID MODE
|
// STOP HERE IN HYBRID MODE
|
||||||
if (config.isHybridMode()) {
|
if (config.isHybridMode()) {
|
||||||
|
req.body = {
|
||||||
|
...req.body,
|
||||||
|
endpoint: exitNode[0].endpoint,
|
||||||
|
listenPort: exitNode[0].listenPort
|
||||||
|
}
|
||||||
return proxyToRemote(req, res, next, "hybrid/gerbil/get-config");
|
return proxyToRemote(req, res, next, "hybrid/gerbil/get-config");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,33 +170,6 @@ export async function generateGerbilConfig(exitNode: ExitNode) {
|
||||||
return configResponse;
|
return configResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getNextAvailableSubnet(): Promise<string> {
|
|
||||||
// Get all existing subnets from routes table
|
|
||||||
const existingAddresses = await db
|
|
||||||
.select({
|
|
||||||
address: exitNodes.address
|
|
||||||
})
|
|
||||||
.from(exitNodes);
|
|
||||||
|
|
||||||
const addresses = existingAddresses.map((a) => a.address);
|
|
||||||
let subnet = findNextAvailableCidr(
|
|
||||||
addresses,
|
|
||||||
config.getRawConfig().gerbil.block_size,
|
|
||||||
config.getRawConfig().gerbil.subnet_group
|
|
||||||
);
|
|
||||||
if (!subnet) {
|
|
||||||
throw new Error("No available subnets remaining in space");
|
|
||||||
}
|
|
||||||
|
|
||||||
// replace the last octet with 1
|
|
||||||
subnet =
|
|
||||||
subnet.split(".").slice(0, 3).join(".") +
|
|
||||||
".1" +
|
|
||||||
"/" +
|
|
||||||
subnet.split("/")[1];
|
|
||||||
return subnet;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getNextAvailablePort(): Promise<number> {
|
async function getNextAvailablePort(): Promise<number> {
|
||||||
// Get all existing ports from exitNodes table
|
// Get all existing ports from exitNodes table
|
||||||
const existingPorts = await db
|
const existingPorts = await db
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue