#!/usr/bin/env node /** * Check Omada firewall rules for Blockscout access * Queries Omada Controller API to list firewall rules that might block Blockscout */ import { OmadaClient } from '../omada-api/src/client/OmadaClient.js'; import { FirewallService } from '../omada-api/src/services/FirewallService.js'; 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'; async function main() { console.log('════════════════════════════════════════'); console.log('Omada Firewall Rules Check for Blockscout'); console.log('════════════════════════════════════════'); console.log(''); console.log(`Blockscout IP: ${BLOCKSCOUT_IP}`); console.log(`Blockscout Port: ${BLOCKSCOUT_PORT}`); console.log(''); // Get Omada credentials from environment const controllerUrl = process.env.OMADA_CONTROLLER_URL || process.env.OMADA_CONTROLLER_BASE_URL; const apiKey = process.env.OMADA_API_KEY || process.env.OMADA_CLIENT_ID; const apiSecret = process.env.OMADA_API_SECRET || process.env.OMADA_CLIENT_SECRET; const siteId = process.env.OMADA_SITE_ID; if (!controllerUrl || !apiKey || !apiSecret) { console.error('❌ Missing Omada credentials in .env file'); console.error(''); console.error('Required environment variables:'); console.error(' OMADA_CONTROLLER_URL (or OMADA_CONTROLLER_BASE_URL)'); console.error(' OMADA_API_KEY (or OMADA_CLIENT_ID)'); console.error(' OMADA_API_SECRET (or OMADA_CLIENT_SECRET)'); console.error(' OMADA_SITE_ID (optional)'); process.exit(1); } console.log(`Controller URL: ${controllerUrl}`); console.log(`Site ID: ${siteId || 'auto-detect'}`); console.log(''); try { // Initialize Omada client const client = new OmadaClient({ baseUrl: controllerUrl, clientId: apiKey, clientSecret: apiSecret, siteId: siteId, verifySsl: process.env.OMADA_VERIFY_SSL !== 'false', }); const firewallService = new FirewallService(client); console.log('Fetching firewall rules...'); console.log(''); // List all firewall rules const rules = await firewallService.listFirewallRules(); console.log(`Found ${rules.length} firewall rules`); console.log(''); // Filter rules that might affect Blockscout const relevantRules = rules.filter((rule) => { // Check if rule affects Blockscout IP or port 80 const affectsBlockscoutIP = !rule.dstIp || rule.dstIp === BLOCKSCOUT_IP || rule.dstIp.includes(BLOCKSCOUT_IP.split('.').slice(0, 3).join('.')); const affectsPort80 = !rule.dstPort || rule.dstPort === BLOCKSCOUT_PORT || rule.dstPort.includes(BLOCKSCOUT_PORT) || rule.dstPort === 'all'; 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('ℹ️ No firewall rules found that specifically target Blockscout'); console.log(''); console.log('Checking for default deny policies...'); console.log(''); // Check for default deny rules 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 that might block traffic:`); console.log(''); denyRules.forEach((rule) => { console.log(` - ${rule.name} (Action: ${rule.action}, Priority: ${rule.priority})`); }); console.log(''); } // Check all rules for reference console.log('All firewall rules:'); console.log(''); rules.forEach((rule) => { const status = rule.enable ? '✓' : '✗'; console.log( ` ${status} ${rule.name} (Action: ${rule.action}, Direction: ${rule.direction}, Priority: ${rule.priority})` ); }); } else { console.log(`🔍 Found ${relevantRules.length} rule(s) that might affect Blockscout:`); console.log(''); relevantRules.forEach((rule) => { console.log(`Rule: ${rule.name}`); console.log(` ID: ${rule.id}`); console.log(` Enabled: ${rule.enable ? 'Yes' : 'No'}`); console.log(` Action: ${rule.action}`); console.log(` Direction: ${rule.direction}`); 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}`); console.log(''); if (rule.action === 'deny' || rule.action === 'reject') { console.log(' ⚠️ WARNING: This rule BLOCKS traffic!'); console.log(''); } }); } console.log('════════════════════════════════════════'); console.log('Recommendations'); console.log('════════════════════════════════════════'); console.log(''); // Check if there's an allow rule for Blockscout const allowRules = relevantRules.filter((rule) => rule.action === 'allow'); const denyRules = relevantRules.filter( (rule) => rule.action === 'deny' || rule.action === 'reject' ); if (denyRules.length > 0 && allowRules.length === 0) { console.log('❌ Issue Found:'); console.log(' Deny rules exist that might block Blockscout, but no allow rules found.'); console.log(''); console.log('✅ Recommended Action:'); console.log(' Create an allow rule with HIGH priority (above deny rules):'); 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 (above deny rules)'); console.log(''); } else if (allowRules.length > 0) { const highestAllowPriority = Math.max(...allowRules.map((r) => r.priority)); const lowestDenyPriority = denyRules.length > 0 ? Math.min(...denyRules.map((r) => r.priority)) : Infinity; if (highestAllowPriority < lowestDenyPriority) { console.log('✅ Configuration looks correct:'); console.log(' Allow rules have higher priority than deny rules.'); console.log(''); } else { console.log('⚠️ Potential Issue:'); console.log(' Some deny rules have higher priority than allow rules.'); console.log(' Ensure allow rules are above deny rules in priority.'); console.log(''); } } else { console.log('ℹ️ No specific rules found for Blockscout.'); console.log(' Traffic should be allowed by default (LAN → LAN on same subnet).'); console.log(' If issues persist, check for default deny policies.'); console.log(''); } console.log('════════════════════════════════════════'); } catch (error) { console.error('❌ Error querying Omada Controller:'); console.error(''); if (error.message) { console.error(` ${error.message}`); } else { console.error(' ', error); } console.error(''); console.error('Troubleshooting:'); console.error(' 1. Verify Omada Controller is accessible'); console.error(' 2. Check API credentials in .env file'); console.error(' 3. Verify network connectivity to controller'); process.exit(1); } } main().catch((error) => { console.error('Fatal error:', error); process.exit(1); });