Files
proxmox/scripts/query-omada-firewall-blockscout.js
defiQUG cb47cce074 Complete markdown files cleanup and organization
- Organized 252 files across project
- Root directory: 187 → 2 files (98.9% reduction)
- Moved configuration guides to docs/04-configuration/
- Moved troubleshooting guides to docs/09-troubleshooting/
- Moved quick start guides to docs/01-getting-started/
- Moved reports to reports/ directory
- Archived temporary files
- Generated comprehensive reports and documentation
- Created maintenance scripts and guides

All files organized according to established standards.
2026-01-06 01:46:25 -08:00

271 lines
9.7 KiB
JavaScript
Executable File
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env node
/**
* Query Omada Controller firewall rules for Blockscout access
* Uses direct API calls with admin credentials
*/
import dotenv from 'dotenv';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// Load environment variables
dotenv.config({ path: join(__dirname, '..', '.env') });
const BLOCKSCOUT_IP = '192.168.11.140';
const BLOCKSCOUT_PORT = '80';
// Get configuration from environment
const controllerUrl = process.env.OMADA_CONTROLLER_URL || process.env.OMADA_CONTROLLER_BASE_URL || 'https://192.168.11.8:8043';
const username = process.env.OMADA_ADMIN_USERNAME || process.env.OMADA_API_KEY || process.env.OMADA_CLIENT_ID;
const password = process.env.OMADA_ADMIN_PASSWORD || process.env.OMADA_API_SECRET || process.env.OMADA_CLIENT_SECRET;
const siteId = process.env.OMADA_SITE_ID || '090862bebcb1997bb263eea9364957fe';
const verifySSL = process.env.OMADA_VERIFY_SSL !== 'false';
// Disable SSL verification if needed
if (!verifySSL) {
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
}
async function login() {
const url = `${controllerUrl}/api/v2/login`;
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
username: username,
password: password,
}),
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`Login failed: ${response.status} ${response.statusText} - ${errorText}`);
}
const data = await response.json();
if (data.errorCode !== 0) {
throw new Error(`Login failed: ${data.msg || 'Unknown error'}`);
}
const token = data.result?.token || data.token;
if (!token) {
throw new Error('No token received from server');
}
return token;
}
async function requestWithToken(token, endpoint, method = 'GET', body = null) {
const url = `${controllerUrl}${endpoint}`;
const options = {
method,
headers: {
'Content-Type': 'application/json',
'Csrf-Token': token,
'Cookie': `TOKEN=${token}`,
},
};
if (body) {
options.body = JSON.stringify(body);
}
const response = await fetch(url, options);
if (!response.ok) {
const errorText = await response.text();
throw new Error(`API request failed: ${response.status} ${response.statusText} - ${errorText}`);
}
const data = await response.json();
if (data.errorCode !== 0) {
throw new Error(`API error: ${data.msg || 'Unknown error'}`);
}
return data.result || data;
}
async function main() {
console.log('════════════════════════════════════════');
console.log('Omada Firewall Rules Check for Blockscout');
console.log('════════════════════════════════════════');
console.log('');
console.log(`Controller: ${controllerUrl}`);
console.log(`Site ID: ${siteId}`);
console.log(`Blockscout IP: ${BLOCKSCOUT_IP}`);
console.log(`Blockscout Port: ${BLOCKSCOUT_PORT}`);
console.log('');
if (!username || !password) {
console.error('❌ Missing Omada credentials in .env file');
console.error('');
console.error('Required environment variables:');
console.error(' OMADA_ADMIN_USERNAME (or OMADA_API_KEY/OMADA_CLIENT_ID)');
console.error(' OMADA_ADMIN_PASSWORD (or OMADA_API_SECRET/OMADA_CLIENT_SECRET)');
console.error('');
console.error('Optional:');
console.error(' OMADA_CONTROLLER_URL (default: https://192.168.11.8:8043)');
console.error(' OMADA_SITE_ID (default: auto-detect)');
process.exit(1);
}
try {
console.log('Authenticating to Omada Controller...');
const token = await login();
console.log('✓ Authentication successful');
console.log('');
console.log('Fetching firewall rules...');
const rules = await requestWithToken(token, `/api/v2/sites/${siteId}/firewall/rules`);
console.log(`✓ Found ${rules.length} firewall rules`);
console.log('');
// Filter rules that might affect Blockscout
const relevantRules = rules.filter((rule) => {
const affectsBlockscoutIP =
!rule.dstIp ||
rule.dstIp === BLOCKSCOUT_IP ||
rule.dstIp.includes(BLOCKSCOUT_IP.split('.').slice(0, 3).join('.')) ||
rule.dstIp === '192.168.11.0/24' ||
rule.dstIp === '192.168.11.0/255.255.255.0';
const affectsPort80 =
!rule.dstPort ||
rule.dstPort === BLOCKSCOUT_PORT ||
rule.dstPort.includes(BLOCKSCOUT_PORT) ||
rule.dstPort === 'all' ||
rule.dstPort === '0-65535';
const isTCP =
!rule.protocol ||
rule.protocol === 'tcp' ||
rule.protocol === 'tcp/udp' ||
rule.protocol === 'all';
return rule.enable && (affectsBlockscoutIP || affectsPort80) && isTCP;
});
if (relevantRules.length > 0) {
console.log(`🔍 Found ${relevantRules.length} rule(s) that might affect Blockscout:`);
console.log('');
relevantRules.forEach((rule) => {
console.log(`Rule: ${rule.name || rule.id}`);
console.log(` ID: ${rule.id}`);
console.log(` Enabled: ${rule.enable ? 'Yes ✓' : 'No ✗'}`);
console.log(` Action: ${rule.action}`);
console.log(` Direction: ${rule.direction || 'N/A'}`);
console.log(` Protocol: ${rule.protocol || 'all'}`);
console.log(` Source IP: ${rule.srcIp || 'Any'}`);
console.log(` Source Port: ${rule.srcPort || 'Any'}`);
console.log(` Destination IP: ${rule.dstIp || 'Any'}`);
console.log(` Destination Port: ${rule.dstPort || 'Any'}`);
console.log(` Priority: ${rule.priority || 'N/A'}`);
console.log('');
if (rule.action === 'deny' || rule.action === 'reject') {
console.log(' ⚠️ WARNING: This rule BLOCKS traffic!');
console.log('');
}
});
// Separate allow and deny rules
const allowRules = relevantRules.filter((rule) => rule.action === 'allow');
const denyRules = relevantRules.filter((rule) => rule.action === 'deny' || rule.action === 'reject');
console.log('════════════════════════════════════════');
console.log('Analysis');
console.log('════════════════════════════════════════');
console.log('');
if (denyRules.length > 0 && allowRules.length === 0) {
console.log('❌ Issue Found:');
console.log(' Deny rules exist that block Blockscout, but no allow rules found.');
console.log(' This explains the "No route to host" error.');
console.log('');
} else if (allowRules.length > 0 && denyRules.length > 0) {
console.log('⚠️ Both allow and deny rules exist.');
console.log(' Check rule priority - allow rules must be above deny rules.');
console.log('');
} else if (allowRules.length > 0) {
console.log('✅ Allow rules exist for Blockscout.');
console.log(' If issues persist, check rule priority or default policies.');
console.log('');
}
} else {
console.log(' No firewall rules found that specifically target Blockscout.');
console.log('');
console.log('Checking all deny/reject rules...');
console.log('');
const denyRules = rules.filter(
(rule) => rule.enable && (rule.action === 'deny' || rule.action === 'reject')
);
if (denyRules.length > 0) {
console.log(`⚠️ Found ${denyRules.length} deny/reject rules:`);
console.log('');
denyRules.slice(0, 10).forEach((rule) => {
console.log(` - ${rule.name || rule.id} (Priority: ${rule.priority || 'N/A'})`);
if (rule.dstIp) console.log(` Dest: ${rule.dstIp}`);
if (rule.dstPort) console.log(` Port: ${rule.dstPort}`);
});
if (denyRules.length > 10) {
console.log(` ... and ${denyRules.length - 10} more`);
}
console.log('');
}
}
console.log('════════════════════════════════════════');
console.log('Recommendations');
console.log('════════════════════════════════════════');
console.log('');
if (relevantRules.length === 0 || relevantRules.filter(r => r.action === 'allow').length === 0) {
console.log('✅ Recommended Action:');
console.log(' Create an allow rule in Omada Controller:');
console.log('');
console.log(' Name: Allow Internal to Blockscout HTTP');
console.log(' Enable: Yes');
console.log(' Action: Allow');
console.log(' Direction: Forward');
console.log(' Protocol: TCP');
console.log(' Source IP: 192.168.11.0/24 (or leave blank for Any)');
console.log(' Destination IP: 192.168.11.140');
console.log(' Destination Port: 80');
console.log(' Priority: High (ensure it\'s above any deny rules)');
console.log('');
console.log(' Then apply the configuration.');
console.log('');
}
console.log('════════════════════════════════════════');
} catch (error) {
console.error('❌ Error:');
console.error('');
if (error.message) {
console.error(` ${error.message}`);
} else {
console.error(' ', error);
}
console.error('');
process.exit(1);
}
}
main().catch((error) => {
console.error('Fatal error:', error);
process.exit(1);
});