secubox-openwrt/luci-app-network-modes/htdocs/luci-static/resources/view/network-modes/doublenat.js

198 lines
6.7 KiB
JavaScript
Raw 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.

'use strict';
'require view';
'require ui';
'require network-modes.api as api';
'require network-modes.helpers as helpers';
'require secubox-theme/theme as Theme';
var nmLang = (typeof L !== 'undefined' && L.env && L.env.lang) ||
(document.documentElement && document.documentElement.getAttribute('lang')) ||
(navigator.language ? navigator.language.split('-')[0] : 'en');
Theme.init({ language: nmLang });
return view.extend({
title: _('Double NAT Mode'),
load: function() {
return api.getDoubleNatConfig();
},
render: function(data) {
var cfg = data || {};
var wan = cfg.wan || {};
var lan = cfg.lan || {};
var container = E('div', { 'class': 'network-modes-dashboard doublenat-mode' }, [
E('link', { 'rel': 'stylesheet', 'href': L.resource('secubox-theme/secubox-theme.css') }),
E('link', { 'rel': 'stylesheet', 'href': L.resource('network-modes/common.css') }),
E('link', { 'rel': 'stylesheet', 'href': L.resource('network-modes/dashboard.css') }),
helpers.createNavigationTabs('doublenat'),
helpers.createHero({
icon: '🔁',
title: _('Double NAT'),
subtitle: _('Operate behind an ISP router with a second isolated LAN, guest network, and hardened perimeter.'),
actions: [
E('button', {
'class': 'nm-btn nm-btn-primary',
'data-action': 'doublenat-save',
'type': 'button'
}, '💾 ' + _('Save Settings')),
E('button', {
'class': 'nm-btn',
'type': 'button',
'click': ui.createHandlerFn(helpers, helpers.showGeneratedConfig, 'doublenat')
}, '📝 ' + _('Preview Config'))
]
}),
this.renderWanSection(wan),
this.renderLanSection(lan, cfg),
this.renderSecuritySection(cfg)
]);
container.querySelectorAll('.nm-toggle-switch').forEach(function(toggle) {
toggle.addEventListener('click', function() {
this.classList.toggle('active');
});
});
this.bindActions(container);
return container;
},
renderWanSection: function(wan) {
return helpers.createSection({
icon: '🌐',
title: _('Upstream (ISP box)'),
body: [
E('div', { 'class': 'nm-form-grid' }, [
E('div', { 'class': 'nm-form-group' }, [
E('label', { 'class': 'nm-form-label' }, _('WAN Interface')),
E('input', {
'class': 'nm-input',
'id': 'dn-wan-interface',
'value': wan.interface || 'eth1'
})
]),
E('div', { 'class': 'nm-form-group' }, [
E('label', { 'class': 'nm-form-label' }, _('Protocol')),
E('select', { 'class': 'nm-select', 'id': 'dn-wan-proto' }, [
E('option', { 'value': 'dhcp', 'selected': (wan.protocol || 'dhcp') === 'dhcp' }, _('DHCP Client')),
E('option', { 'value': 'static', 'selected': wan.protocol === 'static' }, _('Static IP')),
E('option', { 'value': 'pppoe', 'selected': wan.protocol === 'pppoe' }, _('PPPoE'))
])
])
]),
E('p', { 'class': 'nm-text-muted' }, _('Keep WAN as DHCP client to obtain an address from the ISP box. Use DMZ on the ISP router to point to SecuBox for best results.'))
]
});
},
renderLanSection: function(lan, cfg) {
return helpers.createSection({
icon: '🏠',
title: _('LAN & Guest Segments'),
body: [
E('div', { 'class': 'nm-form-grid' }, [
E('div', { 'class': 'nm-form-group' }, [
E('label', { 'class': 'nm-form-label' }, _('LAN Interface')),
E('input', {
'class': 'nm-input',
'id': 'dn-lan-interface',
'value': lan.interface || 'br-lan'
})
]),
E('div', { 'class': 'nm-form-group' }, [
E('label', { 'class': 'nm-form-label' }, _('LAN IP')),
E('input', {
'class': 'nm-input',
'id': 'dn-lan-ip',
'value': lan.ipaddr || '10.10.0.1'
})
]),
E('div', { 'class': 'nm-form-group' }, [
E('label', { 'class': 'nm-form-label' }, _('LAN Netmask')),
E('input', {
'class': 'nm-input',
'id': 'dn-lan-netmask',
'value': lan.netmask || '255.255.255.0'
})
]),
E('div', { 'class': 'nm-form-group' }, [
E('label', { 'class': 'nm-form-label' }, _('Guest bridge name')),
E('input', {
'class': 'nm-input',
'id': 'dn-guest-bridge',
'value': cfg.guest_network || 'br-guest'
})
])
])
]
});
},
renderSecuritySection: function(cfg) {
return helpers.createSection({
icon: '🛡',
title: _('Security Hardening'),
body: [
E('div', { 'class': 'nm-toggle-list' }, [
this.renderToggle(_('Disable UPnP on downstream LAN'), 'Prevents auto-forwarding from LAN devices', 'dn-upnp', cfg.upnp_enabled && cfg.upnp_enabled !== '0'),
this.renderToggle(_('Isolate guest bridge'), 'Block traffic between guest and LAN networks', 'dn-isolate-guest', cfg.isolate_guest === 1 || cfg.isolate_guest === '1')
]),
E('div', { 'class': 'nm-form-group', 'style': 'margin-top: 16px;' }, [
E('label', { 'class': 'nm-form-label' }, _('DMZ Host on ISP router')),
E('input', {
'class': 'nm-input',
'id': 'dn-dmz-host',
'value': cfg.dmz_host || '',
'placeholder': _('192.168.1.254 (optional)')
}),
E('p', { 'class': 'nm-text-muted' }, _('Configure the ISP router DMZ to forward everything to this LAN IP.'))
])
]
});
},
renderToggle: function(label, desc, id, active) {
return E('div', { 'class': 'nm-toggle' }, [
E('div', { 'class': 'nm-toggle-info' }, [
E('span', { 'class': 'nm-toggle-icon' }, ''),
E('div', {}, [
E('div', { 'class': 'nm-toggle-label' }, label),
E('div', { 'class': 'nm-toggle-desc' }, desc)
])
]),
E('div', {
'class': 'nm-toggle-switch' + (active ? ' active' : ''),
'id': id
})
]);
},
bindActions: function(container) {
var saveBtn = container.querySelector('[data-action="doublenat-save"]');
if (saveBtn)
saveBtn.addEventListener('click', ui.createHandlerFn(this, 'saveDoubleNatSettings', container));
},
saveDoubleNatSettings: function(container) {
var payload = {
wan_interface: (container.querySelector('#dn-wan-interface') || {}).value,
wan_protocol: (container.querySelector('#dn-wan-proto') || {}).value,
lan_interface: (container.querySelector('#dn-lan-interface') || {}).value,
lan_ip: (container.querySelector('#dn-lan-ip') || {}).value,
lan_netmask: (container.querySelector('#dn-lan-netmask') || {}).value,
guest_network: (container.querySelector('#dn-guest-bridge') || {}).value,
isolate_guest: helpers.isToggleActive(container.querySelector('#dn-isolate-guest')) ? 1 : 0,
upnp_enabled: helpers.isToggleActive(container.querySelector('#dn-upnp')) ? 1 : 0,
dmz_host: (container.querySelector('#dn-dmz-host') || {}).value
};
return helpers.persistSettings('doublenat', payload);
},
handleSaveApply: null,
handleSave: null,
handleReset: null
});