Major Enhancements: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Network Modes Module: - Added 3 new network modes: * Double NAT mode (doublenat.js) - Cascaded router configuration * Multi-WAN mode (multiwan.js) - Load balancing and failover * VPN Relay mode (vpnrelay.js) - VPN gateway configuration - Enhanced existing modes: * Access Point improvements * Travel mode refinements * Router mode enhancements * Relay mode updates * Sniffer mode optimizations - Updated wizard with new mode options - Enhanced API with new mode support - Improved dashboard CSS styling - Updated helpers for new modes - Extended RPCD backend functionality - Updated menu structure for new modes - Enhanced UCI configuration System Hub Module: - Added dedicated logs.css stylesheet - Enhanced logs.js view with better styling - Improved overview.css responsive design - Enhanced services.css for better UX - Updated overview.js with theme integration - Improved services.js layout SecuBox Dashboard: - Enhanced dashboard.css with theme variables - Improved dashboard.js responsiveness - Better integration with global theme Files Changed: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Network Modes (17 files): Modified: api.js, dashboard.css, helpers.js, menu, config, RPCD backend Modified Views: accesspoint, overview, relay, router, sniffer, travel, wizard New Views: doublenat, multiwan, vpnrelay System Hub (6 files): New: logs.css Modified: overview.css, services.css, logs.js, overview.js, services.js SecuBox (2 files): Modified: dashboard.css, dashboard.js Total: 25 files changed (21 modified, 4 new) Technical Improvements: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Global theme CSS variable usage - Responsive design enhancements - Improved error handling - Better mode validation - Enhanced user feedback - Optimized CSS performance - Improved accessibility Network Mode Capabilities: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1. Router Mode - Standard routing 2. Access Point Mode - WiFi AP with bridge 3. Relay Mode - WiFi repeater/extender 4. Travel Mode - Portable router configuration 5. Sniffer Mode - Network monitoring 6. Double NAT Mode - Cascaded NAT for network isolation (NEW) 7. Multi-WAN Mode - Multiple uplinks with load balancing (NEW) 8. VPN Relay Mode - VPN gateway and tunnel endpoint (NEW) Breaking Changes: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ None - All changes are backward compatible 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
134 lines
4.9 KiB
JavaScript
134 lines
4.9 KiB
JavaScript
'use strict';
|
|
'require view';
|
|
'require dom';
|
|
'require ui';
|
|
'require network-modes.api as api';
|
|
'require network-modes.helpers as helpers';
|
|
'require secubox-theme/theme as Theme';
|
|
|
|
Theme.init({ theme: 'dark', language: 'en' });
|
|
|
|
function buildToggle(id, icon, title, desc, active) {
|
|
return E('div', { 'class': 'nm-toggle' }, [
|
|
E('div', { 'class': 'nm-toggle-info' }, [
|
|
E('span', { 'class': 'nm-toggle-icon' }, icon),
|
|
E('div', {}, [
|
|
E('div', { 'class': 'nm-toggle-label' }, title),
|
|
E('div', { 'class': 'nm-toggle-desc' }, desc)
|
|
])
|
|
]),
|
|
E('div', {
|
|
'class': 'nm-toggle-switch' + (active ? ' active' : ''),
|
|
'id': id
|
|
})
|
|
]);
|
|
}
|
|
|
|
return view.extend({
|
|
title: _('Sniffer Mode'),
|
|
|
|
load: function() {
|
|
return api.getSnifferConfig();
|
|
},
|
|
|
|
render: function(data) {
|
|
var config = data || {};
|
|
|
|
var hero = helpers.createHero({
|
|
icon: '🔍',
|
|
title: _('Sniffer / TAP Mode'),
|
|
subtitle: _('Transparent monitoring bridge feeding Netifyd + pcaps. Ideal for SOC taps, troubleshooting, or security labs.'),
|
|
gradient: 'linear-gradient(135deg,#8b5cf6,#a855f7)',
|
|
actions: [
|
|
E('button', { 'class': 'nm-btn nm-btn-primary', 'type': 'button', 'data-action': 'sniffer-save' }, ['💾 ', _('Save Settings')]),
|
|
E('button', { 'class': 'nm-btn', 'type': 'button', 'data-action': 'sniffer-config' }, ['📝 ', _('Preview Config')])
|
|
]
|
|
});
|
|
|
|
var stats = E('div', { 'style': 'display:flex;flex-wrap:wrap;gap:12px;margin-bottom:24px;' }, [
|
|
helpers.createStatBadge({ label: _('Bridge'), value: (config.bridge_interface || 'br-snoop').toUpperCase() }),
|
|
helpers.createStatBadge({ label: _('Netifyd'), value: config.netifyd_running ? _('Running') : _('Stopped') }),
|
|
helpers.createStatBadge({ label: _('Promiscuous'), value: config.promiscuous ? _('Enabled') : _('Disabled') })
|
|
]);
|
|
|
|
var bridgeSection = helpers.createSection({
|
|
title: _('Bridge Configuration'),
|
|
icon: '🌉',
|
|
body: [
|
|
E('div', { 'class': 'nm-form-group' }, [
|
|
E('label', { 'class': 'nm-form-label' }, _('Monitor Interface')),
|
|
E('select', { 'class': 'nm-select', 'id': 'bridge-interface' },
|
|
(config.available_interfaces || ['eth0', 'eth1']).map(function(iface) {
|
|
return E('option', { 'value': iface, 'selected': iface === config.bridge_interface }, iface);
|
|
})
|
|
),
|
|
E('div', { 'class': 'nm-form-hint' }, _('Use mirror/SPAN or inline tap'))
|
|
]),
|
|
buildToggle('toggle-promisc', '📡', _('Promiscuous Mode'), _('Capture all frames, not only bridged ones'), config.promiscuous)
|
|
]
|
|
});
|
|
|
|
var netifySection = helpers.createSection({
|
|
title: _('Netifyd & PCAP'),
|
|
icon: '📊',
|
|
badge: config.netifyd_running ? _('Running') : _('Stopped'),
|
|
body: [
|
|
buildToggle('toggle-netifyd', '🔬', _('Netifyd DPI'), _('Enable Deep Packet Inspection export'), config.netifyd_enabled),
|
|
helpers.createList([
|
|
{ title: _('pcap capture'), description: _('Optional tcpdump writes to /var/captures'), suffix: E('span', { 'class': 'nm-badge' }, _('pcap')) },
|
|
{ title: _('Rotation & retention'), description: _('Configure rotation with network-modes settings tab'), suffix: E('span', { 'class': 'nm-badge' }, _('Storage')) }
|
|
]),
|
|
config.netifyd_running ?
|
|
E('p', { 'style': 'margin-top:12px;color:#a5b4fc;' }, _('Netifyd analytics available in the Netifyd Dashboard.')) :
|
|
E('p', { 'style': 'margin-top:12px;color:#94a3b8;' }, _('Start Netifyd to feed DPI data.'))
|
|
]
|
|
});
|
|
|
|
var previewSection = helpers.createSection({
|
|
title: _('Configuration Preview'),
|
|
icon: '📝',
|
|
body: [
|
|
E('pre', { 'class': 'nm-config-preview' }, config.config_preview || '# No configuration preview available')
|
|
]
|
|
});
|
|
|
|
var container = E('div', { 'class': 'network-modes-dashboard sniffer-mode' }, [
|
|
E('link', { 'rel': 'stylesheet', 'href': L.resource('network-modes/dashboard.css') }),
|
|
hero,
|
|
stats,
|
|
bridgeSection,
|
|
netifySection,
|
|
previewSection
|
|
]);
|
|
|
|
container.querySelectorAll('.nm-toggle-switch').forEach(function(toggle) {
|
|
toggle.addEventListener('click', function() {
|
|
this.classList.toggle('active');
|
|
});
|
|
});
|
|
|
|
this.bindSnifferActions(container);
|
|
return container;
|
|
},
|
|
|
|
bindSnifferActions: function(container) {
|
|
var saveBtn = container.querySelector('[data-action="sniffer-save"]');
|
|
var applyBtn = container.querySelector('[data-action="sniffer-config"]');
|
|
|
|
if (saveBtn)
|
|
saveBtn.addEventListener('click', ui.createHandlerFn(this, 'saveSnifferSettings', container));
|
|
if (applyBtn)
|
|
applyBtn.addEventListener('click', ui.createHandlerFn(helpers, helpers.showGeneratedConfig, 'sniffer'));
|
|
},
|
|
|
|
saveSnifferSettings: function(container) {
|
|
var payload = {
|
|
bridge_interface: container.querySelector('#bridge-interface') ? container.querySelector('#bridge-interface').value : '',
|
|
netifyd_enabled: helpers.isToggleActive(container.querySelector('#toggle-netifyd')) ? 1 : 0,
|
|
promiscuous: helpers.isToggleActive(container.querySelector('#toggle-promisc')) ? 1 : 0
|
|
};
|
|
|
|
return helpers.persistSettings('sniffer', payload);
|
|
}
|
|
});
|