mirror of
https://github.com/samsonjs/vibetunnel.git
synced 2026-04-27 15:17:38 +00:00
Add local bypass feature
This commit is contained in:
parent
85ac380095
commit
801438d867
2 changed files with 66 additions and 1 deletions
|
|
@ -11,14 +11,42 @@ interface AuthConfig {
|
|||
isHQMode: boolean;
|
||||
bearerToken?: string; // Token that HQ must use to authenticate with this remote
|
||||
authService?: AuthService; // Enhanced auth service for JWT tokens
|
||||
allowLocalBypass?: boolean; // Allow localhost connections to bypass auth
|
||||
localAuthToken?: string; // Token for localhost authentication
|
||||
}
|
||||
|
||||
interface AuthenticatedRequest extends Request {
|
||||
userId?: string;
|
||||
authMethod?: 'ssh-key' | 'password' | 'hq-bearer' | 'no-auth';
|
||||
authMethod?: 'ssh-key' | 'password' | 'hq-bearer' | 'no-auth' | 'local-bypass';
|
||||
isHQRequest?: boolean;
|
||||
}
|
||||
|
||||
// Helper function to check if request is from localhost
|
||||
function isLocalRequest(req: Request): boolean {
|
||||
// Get the real client IP
|
||||
const clientIp = req.ip || req.socket.remoteAddress || '';
|
||||
|
||||
// Check for localhost IPs
|
||||
const localIPs = ['127.0.0.1', '::1', '::ffff:127.0.0.1', 'localhost'];
|
||||
const ipIsLocal = localIPs.includes(clientIp);
|
||||
|
||||
// Additional security checks to prevent spoofing
|
||||
const noForwardedFor = !req.headers['x-forwarded-for'];
|
||||
const noRealIP = !req.headers['x-real-ip'];
|
||||
const noForwardedHost = !req.headers['x-forwarded-host'];
|
||||
|
||||
// Check hostname
|
||||
const hostIsLocal =
|
||||
req.hostname === 'localhost' || req.hostname === '127.0.0.1' || req.hostname === '[::1]';
|
||||
|
||||
logger.debug(
|
||||
`Local request check - IP: ${clientIp}, Host: ${req.hostname}, ` +
|
||||
`Forwarded headers: ${!noForwardedFor || !noRealIP || !noForwardedHost}`
|
||||
);
|
||||
|
||||
return ipIsLocal && noForwardedFor && noRealIP && noForwardedHost && hostIsLocal;
|
||||
}
|
||||
|
||||
export function createAuthMiddleware(config: AuthConfig) {
|
||||
return (req: AuthenticatedRequest, res: Response, next: NextFunction) => {
|
||||
// Skip auth for health check endpoint, auth endpoints, client logging, and push notifications
|
||||
|
|
@ -37,6 +65,28 @@ export function createAuthMiddleware(config: AuthConfig) {
|
|||
return next();
|
||||
}
|
||||
|
||||
// Check for local bypass if enabled
|
||||
if (config.allowLocalBypass && isLocalRequest(req)) {
|
||||
// If a local auth token is configured, check for it
|
||||
if (config.localAuthToken) {
|
||||
const providedToken = req.headers['x-vibetunnel-local'] as string;
|
||||
if (providedToken === config.localAuthToken) {
|
||||
logger.debug('Local request authenticated with token');
|
||||
req.authMethod = 'local-bypass';
|
||||
req.userId = 'local-user';
|
||||
return next();
|
||||
} else {
|
||||
logger.debug('Local request missing or invalid token');
|
||||
}
|
||||
} else {
|
||||
// No token required for local bypass
|
||||
logger.debug('Local request authenticated without token');
|
||||
req.authMethod = 'local-bypass';
|
||||
req.userId = 'local-user';
|
||||
return next();
|
||||
}
|
||||
}
|
||||
|
||||
// Only log auth requests that might be problematic (no header or failures)
|
||||
// Remove verbose logging for successful token auth to reduce spam
|
||||
|
||||
|
|
|
|||
|
|
@ -61,6 +61,9 @@ interface Config {
|
|||
vapidEmail: string | null;
|
||||
generateVapidKeys: boolean;
|
||||
bellNotificationsEnabled: boolean;
|
||||
// Local bypass configuration
|
||||
allowLocalBypass: boolean;
|
||||
localAuthToken: string | null;
|
||||
}
|
||||
|
||||
// Show help message
|
||||
|
|
@ -78,6 +81,8 @@ Options:
|
|||
--enable-ssh-keys Enable SSH key authentication UI and functionality
|
||||
--disallow-user-password Disable password auth, SSH keys only (auto-enables --enable-ssh-keys)
|
||||
--no-auth Disable authentication (auto-login as current user)
|
||||
--allow-local-bypass Allow localhost connections to bypass authentication
|
||||
--local-auth-token <token> Token for localhost authentication bypass
|
||||
--debug Enable debug logging
|
||||
|
||||
Push Notification Options:
|
||||
|
|
@ -141,6 +146,9 @@ function parseArgs(): Config {
|
|||
vapidEmail: null as string | null,
|
||||
generateVapidKeys: true, // Generate keys automatically
|
||||
bellNotificationsEnabled: true, // Enable bell notifications by default
|
||||
// Local bypass configuration
|
||||
allowLocalBypass: false,
|
||||
localAuthToken: null as string | null,
|
||||
};
|
||||
|
||||
// Check for help flag first
|
||||
|
|
@ -197,6 +205,11 @@ function parseArgs(): Config {
|
|||
i++; // Skip the email value in next iteration
|
||||
} else if (args[i] === '--generate-vapid-keys') {
|
||||
config.generateVapidKeys = true;
|
||||
} else if (args[i] === '--allow-local-bypass') {
|
||||
config.allowLocalBypass = true;
|
||||
} else if (args[i] === '--local-auth-token' && i + 1 < args.length) {
|
||||
config.localAuthToken = args[i + 1];
|
||||
i++; // Skip the token value in next iteration
|
||||
} else if (args[i].startsWith('--')) {
|
||||
// Unknown argument
|
||||
logger.error(`Unknown argument: ${args[i]}`);
|
||||
|
|
@ -428,6 +441,8 @@ export async function createApp(): Promise<AppInstance> {
|
|||
isHQMode: config.isHQMode,
|
||||
bearerToken: remoteBearerToken || undefined, // Token that HQ must use to auth with us
|
||||
authService, // Add enhanced auth service for JWT tokens
|
||||
allowLocalBypass: config.allowLocalBypass,
|
||||
localAuthToken: config.localAuthToken || undefined,
|
||||
});
|
||||
|
||||
// Serve static files with .html extension handling
|
||||
|
|
|
|||
Loading…
Reference in a new issue