fix: WebSocket auth gate + SSRF private IP blocklist in posimai-dev

This commit is contained in:
posimai 2026-04-06 00:39:18 +09:00
parent c24c710f33
commit 9e90008575
1 changed files with 10 additions and 2 deletions

View File

@ -235,7 +235,7 @@ app.get('/api/vps-health', async (req, res) => {
// ── サービス死活チェックプロキシ (/api/check?url=...) ────────── // ── サービス死活チェックプロキシ (/api/check?url=...) ──────────
// ブラウザの mixed-content 制限を回避するためサーバー側から HTTP チェック // ブラウザの mixed-content 制限を回避するためサーバー側から HTTP チェック
// SSRF 対策: http/https のみ許可、クラウドメタデータ IP をブロック // SSRF 対策: http/https のみ許可、クラウドメタデータ IP をブロック
const BLOCKED_HOSTS = /^(169\.254\.|100\.100\.100\.100|metadata\.google\.internal)/; const BLOCKED_HOSTS = /^(127\.|localhost$|::1$|169\.254\.|10\.|172\.(1[6-9]|2[0-9]|3[01])\.|192\.168\.|100\.100\.100\.100|metadata\.google\.internal)/i;
function isCheckUrlAllowed(raw) { function isCheckUrlAllowed(raw) {
let parsed; let parsed;
try { parsed = new URL(raw); } catch { return false; } try { parsed = new URL(raw); } catch { return false; }
@ -277,7 +277,15 @@ const proto = tlsOpts ? 'https' : 'http';
const wss = new WebSocketServer({ server, path: '/terminal' }); const wss = new WebSocketServer({ server, path: '/terminal' });
wss.on('connection', (ws) => { wss.on('connection', (ws, req) => {
// Tailscale ネットワーク外からの接続を拒否
const ip = req.socket.remoteAddress || '';
const allowed = ip === '::1' || ip === '127.0.0.1' || ip.startsWith('100.');
if (!allowed) {
ws.close(1008, 'Forbidden');
return;
}
// セッションID・ログファイル作成 // セッションID・ログファイル作成
const sessionId = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19); const sessionId = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
const logPath = path.join(SESSIONS_DIR, `${sessionId}.log`); const logPath = path.join(SESSIONS_DIR, `${sessionId}.log`);