network-modes: add DMZ mode and docs
This commit is contained in:
parent
baab096876
commit
33dcb35ddc
@ -83,6 +83,19 @@ The LuCI backend writes to the same `/etc/config/vhosts` file, so changes from `
|
||||
|
||||
---
|
||||
|
||||
## DMZ Mode + VHost Workflow
|
||||
|
||||
When enabling the new **Router + DMZ** network mode (admin → SecuBox → Network → Modes → DMZ):
|
||||
|
||||
1. Assign `eth2` (or another physical port) as the DMZ interface and give it a subnet such as `192.168.50.1/24`.
|
||||
2. Apply the mode; the backend creates a dedicated firewall zone (`dmz`) that only forwards to WAN.
|
||||
3. Connect servers (e.g., Lyrion, Zigbee2MQTT UI) to the DMZ port so they can reach the internet but cannot reach the LAN.
|
||||
4. Use `scripts/vhostctl.sh add ... --upstream http://192.168.50.10:32400` to expose the DMZ service through nginx with TLS.
|
||||
|
||||
Rollback is one click away: use the Network Modes “Confirm / Rollback” dialog within the 2‑minute window to restore the previous configs automatically.
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Issue | Fix |
|
||||
|
||||
@ -83,6 +83,19 @@ The LuCI backend writes to the same `/etc/config/vhosts` file, so changes from `
|
||||
|
||||
---
|
||||
|
||||
## DMZ Mode + VHost Workflow
|
||||
|
||||
When enabling the new **Router + DMZ** network mode (admin → SecuBox → Network → Modes → DMZ):
|
||||
|
||||
1. Assign `eth2` (or another physical port) as the DMZ interface and give it a subnet such as `192.168.50.1/24`.
|
||||
2. Apply the mode; the backend creates a dedicated firewall zone (`dmz`) that only forwards to WAN.
|
||||
3. Connect servers (e.g., Lyrion, Zigbee2MQTT UI) to the DMZ port so they can reach the internet but cannot reach the LAN.
|
||||
4. Use `scripts/vhostctl.sh add ... --upstream http://192.168.50.10:32400` to expose the DMZ service through nginx with TLS.
|
||||
|
||||
If something goes wrong, simply click **Rollback** in the Network Modes UI—the previous `/etc/config/network`, `/etc/config/firewall`, and `/etc/config/dhcp` are restored automatically thanks to the built-in backups.
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Issue | Fix |
|
||||
|
||||
@ -173,6 +173,13 @@ Full router with WAN, proxy and HTTPS frontends.
|
||||
- **HTTPS Reverse Proxy**: Nginx, HAProxy, Caddy
|
||||
- **Multiple virtual hosts** with Let's Encrypt
|
||||
|
||||
### 🛡️ Router + DMZ Mode
|
||||
Create a dedicated DMZ segment for exposed servers while keeping LAN traffic segregated.
|
||||
- Separate DMZ interface with its own subnet/DHCP scope
|
||||
- Firewall zone isolation (DMZ → WAN forwarding, no DMZ → LAN unless toggled)
|
||||
- Fast rollback using the existing backup/confirm workflow
|
||||
- Designed for hosting apps (Zigbee2MQTT, Lyrion, etc.) when combined with the VHost manager
|
||||
|
||||
## ✨ Features
|
||||
|
||||
- 🎛️ One-click mode switching with backup
|
||||
|
||||
@ -95,6 +95,12 @@ var callRouterConfig = rpc.declare({
|
||||
expect: { }
|
||||
});
|
||||
|
||||
var callDmzConfig = rpc.declare({
|
||||
object: 'luci.network-modes',
|
||||
method: 'dmz_config',
|
||||
expect: { }
|
||||
});
|
||||
|
||||
var callTravelConfig = rpc.declare({
|
||||
object: 'luci.network-modes',
|
||||
method: 'travel_config',
|
||||
@ -172,6 +178,7 @@ return baseclass.extend({
|
||||
getAvailableModes: callGetAvailableModes,
|
||||
setMode: callSetMode,
|
||||
getInterfaces: callGetInterfaces,
|
||||
getDmzConfig: callDmzConfig,
|
||||
validateConfig: callValidateConfig,
|
||||
previewChanges: callPreviewChanges,
|
||||
confirmMode: callConfirmMode,
|
||||
@ -337,6 +344,7 @@ return baseclass.extend({
|
||||
features: []
|
||||
};
|
||||
},
|
||||
getDmzConfig: callDmzConfig,
|
||||
|
||||
// Format uptime seconds to human readable
|
||||
formatUptime: function(seconds) {
|
||||
@ -388,3 +396,15 @@ return baseclass.extend({
|
||||
return callEnableTcpBbr();
|
||||
}
|
||||
});
|
||||
dmz: {
|
||||
id: 'dmz',
|
||||
name: 'Router + DMZ',
|
||||
icon: '🛡️',
|
||||
description: 'Traditional router with an additional DMZ interface isolated from LAN but allowed to reach WAN.',
|
||||
features: [
|
||||
'Dedicated DMZ subnet',
|
||||
'Separate firewall zone',
|
||||
'Optional DHCP for DMZ clients',
|
||||
'Quick rollback timer'
|
||||
]
|
||||
},
|
||||
|
||||
@ -7,6 +7,7 @@ var NAV_BLUEPRINT = [
|
||||
{ id: 'overview', icon: '📊', labelKey: 'Overview' },
|
||||
{ id: 'wizard', icon: '🧭', labelKey: 'Wizard' },
|
||||
{ id: 'router', icon: '🌐', labelKey: 'Router' },
|
||||
{ id: 'dmz', icon: '🛡️', labelKey: 'DMZ' },
|
||||
{ id: 'multiwan', icon: '🔀', labelKey: 'Multi-WAN' },
|
||||
{ id: 'doublenat', icon: '🧱', labelKey: 'Double NAT' },
|
||||
{ id: 'accesspoint', icon: '📡', labelKey: 'Access Point' },
|
||||
|
||||
@ -0,0 +1,212 @@
|
||||
'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';
|
||||
|
||||
var lang = (typeof L !== 'undefined' && L.env && L.env.lang) ||
|
||||
(document.documentElement && document.documentElement.getAttribute('lang')) ||
|
||||
(navigator.language ? navigator.language.split('-')[0] : 'en');
|
||||
Theme.init({ language: lang });
|
||||
|
||||
function buildToggle(id, icon, title, desc, enabled) {
|
||||
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' + (enabled ? ' active' : ''),
|
||||
'id': id
|
||||
})
|
||||
]);
|
||||
}
|
||||
|
||||
return view.extend({
|
||||
title: _('DMZ Mode'),
|
||||
|
||||
load: function() {
|
||||
return Promise.all([
|
||||
api.getDmzConfig(),
|
||||
api.getStatus()
|
||||
]);
|
||||
},
|
||||
|
||||
render: function(payload) {
|
||||
var config = (payload && payload[0]) || {};
|
||||
var status = (payload && payload[1]) || {};
|
||||
var wan = config.wan || {};
|
||||
var lan = config.lan || {};
|
||||
var dmz = config.dmz || {};
|
||||
|
||||
var hero = helpers.createHero({
|
||||
icon: '🛡️',
|
||||
title: _('Router + DMZ Mode'),
|
||||
subtitle: _('Create an isolated DMZ network that only reaches the WAN while keeping your LAN protected. Perfect for exposing servers without risking the internal network.'),
|
||||
gradient: 'linear-gradient(135deg,#1e293b,#0ea5e9)',
|
||||
meta: [
|
||||
{ label: _('WAN Interface'), value: wan.interface || 'eth1' },
|
||||
{ label: _('LAN Gateway'), value: lan.ip_address || '192.168.1.1' },
|
||||
{ label: _('DMZ Gateway'), value: dmz.ip_address || '192.168.50.1' }
|
||||
],
|
||||
actions: [
|
||||
E('button', { 'class': 'nm-btn nm-btn-primary', 'type': 'button', 'data-action': 'dmz-save' }, ['💾 ', _('Save Template')]),
|
||||
E('button', { 'class': 'nm-btn', 'type': 'button', 'data-action': 'dmz-apply' }, ['🚀 ', _('Apply DMZ Mode')]),
|
||||
E('button', { 'class': 'nm-btn', 'type': 'button', 'data-action': 'dmz-preview' }, ['📝 ', _('Preview Config')])
|
||||
]
|
||||
});
|
||||
|
||||
var wanSection = helpers.createSection({
|
||||
title: _('WAN Settings'),
|
||||
icon: '🌍',
|
||||
badge: (wan.interface || 'eth1').toUpperCase(),
|
||||
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': 'dmz-wan-if', 'value': wan.interface || 'eth1' })
|
||||
]),
|
||||
E('div', { 'class': 'nm-form-group' }, [
|
||||
E('label', { 'class': 'nm-form-label' }, _('WAN Protocol')),
|
||||
E('select', { 'class': 'nm-select', 'id': 'dmz-wan-proto' },
|
||||
(wan.protocols || ['dhcp', 'static', 'pppoe']).map(function(proto) {
|
||||
return E('option', {
|
||||
'value': proto,
|
||||
'selected': (proto === wan.protocol)
|
||||
}, proto.toUpperCase());
|
||||
})
|
||||
)
|
||||
])
|
||||
])
|
||||
]
|
||||
});
|
||||
|
||||
var lanSection = helpers.createSection({
|
||||
title: _('LAN Network'),
|
||||
icon: '🏠',
|
||||
badge: lan.interface || 'br-lan',
|
||||
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': 'dmz-lan-if', 'value': lan.interface || 'br-lan' })
|
||||
]),
|
||||
E('div', { 'class': 'nm-form-group' }, [
|
||||
E('label', { 'class': 'nm-form-label' }, _('LAN IP Address')),
|
||||
E('input', { 'class': 'nm-input', 'id': 'dmz-lan-ip', 'value': lan.ip_address || '192.168.1.1' })
|
||||
]),
|
||||
E('div', { 'class': 'nm-form-group' }, [
|
||||
E('label', { 'class': 'nm-form-label' }, _('Netmask')),
|
||||
E('input', { 'class': 'nm-input', 'id': 'dmz-lan-mask', 'value': lan.netmask || '255.255.255.0' })
|
||||
])
|
||||
])
|
||||
]
|
||||
});
|
||||
|
||||
var dmzSection = helpers.createSection({
|
||||
title: _('DMZ Segment'),
|
||||
icon: '🧱',
|
||||
badge: dmz.interface || 'eth2',
|
||||
body: [
|
||||
E('div', { 'class': 'nm-form-grid' }, [
|
||||
E('div', { 'class': 'nm-form-group' }, [
|
||||
E('label', { 'class': 'nm-form-label' }, _('DMZ Interface')),
|
||||
E('input', { 'class': 'nm-input', 'id': 'dmz-if', 'value': dmz.interface || 'eth2' })
|
||||
]),
|
||||
E('div', { 'class': 'nm-form-group' }, [
|
||||
E('label', { 'class': 'nm-form-label' }, _('DMZ IP Address')),
|
||||
E('input', { 'class': 'nm-input', 'id': 'dmz-ip', 'value': dmz.ip_address || '192.168.50.1' })
|
||||
]),
|
||||
E('div', { 'class': 'nm-form-group' }, [
|
||||
E('label', { 'class': 'nm-form-label' }, _('Netmask')),
|
||||
E('input', { 'class': 'nm-input', 'id': 'dmz-mask', 'value': dmz.netmask || '255.255.255.0' })
|
||||
]),
|
||||
E('div', { 'class': 'nm-form-group' }, [
|
||||
E('label', { 'class': 'nm-form-label' }, _('DHCP Start')),
|
||||
E('input', { 'class': 'nm-input', 'type': 'number', 'id': 'dmz-dhcp-start', 'value': dmz.dhcp_start || 50 })
|
||||
]),
|
||||
E('div', { 'class': 'nm-form-group' }, [
|
||||
E('label', { 'class': 'nm-form-label' }, _('DHCP Pool Size')),
|
||||
E('input', { 'class': 'nm-input', 'type': 'number', 'id': 'dmz-dhcp-limit', 'value': dmz.dhcp_limit || 80 })
|
||||
])
|
||||
]),
|
||||
E('div', { 'style': 'margin-top:12px;' }, [
|
||||
buildToggle('dmz-isolated-toggle', '🚧', _('Isolate DMZ from LAN'), _('Block DMZ clients from reaching the LAN'), dmz.isolated !== false)
|
||||
]),
|
||||
E('p', { 'class': 'nm-alert nm-alert-info', 'style': 'margin-top:12px;' }, _('DMZ clients will reach the WAN by default. Toggle isolation to prevent DMZ → LAN access.'))
|
||||
]
|
||||
});
|
||||
|
||||
var container = E('div', { 'class': 'nm-container' }, [
|
||||
helpers.createNavigationTabs('dmz'),
|
||||
hero,
|
||||
wanSection,
|
||||
lanSection,
|
||||
dmzSection
|
||||
]);
|
||||
|
||||
container.querySelectorAll('.nm-toggle-switch').forEach(function(toggle) {
|
||||
toggle.addEventListener('click', function() {
|
||||
this.classList.toggle('active');
|
||||
});
|
||||
});
|
||||
|
||||
this.bindActions(container);
|
||||
return container;
|
||||
},
|
||||
|
||||
bindActions: function(container) {
|
||||
var saveBtn = container.querySelector('[data-action="dmz-save"]');
|
||||
var applyBtn = container.querySelector('[data-action="dmz-apply"]');
|
||||
var previewBtn = container.querySelector('[data-action="dmz-preview"]');
|
||||
|
||||
if (saveBtn)
|
||||
saveBtn.addEventListener('click', ui.createHandlerFn(this, 'saveSettings', container));
|
||||
if (applyBtn)
|
||||
applyBtn.addEventListener('click', ui.createHandlerFn(this, 'applyMode'));
|
||||
if (previewBtn)
|
||||
previewBtn.addEventListener('click', ui.createHandlerFn(helpers, helpers.showGeneratedConfig, 'dmz'));
|
||||
},
|
||||
|
||||
saveSettings: function(container) {
|
||||
var payload = {
|
||||
wan_interface: (container.querySelector('#dmz-wan-if') || {}).value || 'eth1',
|
||||
wan_protocol: (container.querySelector('#dmz-wan-proto') || {}).value || 'dhcp',
|
||||
lan_interface: (container.querySelector('#dmz-lan-if') || {}).value || 'br-lan',
|
||||
lan_ip: (container.querySelector('#dmz-lan-ip') || {}).value || '192.168.1.1',
|
||||
lan_netmask: (container.querySelector('#dmz-lan-mask') || {}).value || '255.255.255.0',
|
||||
dmz_interface: (container.querySelector('#dmz-if') || {}).value || 'eth2',
|
||||
dmz_ip: (container.querySelector('#dmz-ip') || {}).value || '192.168.50.1',
|
||||
dmz_netmask: (container.querySelector('#dmz-mask') || {}).value || '255.255.255.0',
|
||||
dmz_dhcp_start: (container.querySelector('#dmz-dhcp-start') || {}).value || '50',
|
||||
dmz_dhcp_limit: (container.querySelector('#dmz-dhcp-limit') || {}).value || '80',
|
||||
dmz_isolated: helpers.isToggleActive(container.querySelector('#dmz-isolated-toggle')) ? 1 : 0
|
||||
};
|
||||
|
||||
return helpers.persistSettings('dmz', payload);
|
||||
},
|
||||
|
||||
applyMode: function() {
|
||||
ui.showModal(_('Applying DMZ mode'), [
|
||||
E('p', { 'class': 'spinning' }, _('Backing up current config and switching to DMZ mode...'))
|
||||
]);
|
||||
|
||||
return api.applyMode('dmz').then(function(result) {
|
||||
ui.hideModal();
|
||||
if (result && result.success) {
|
||||
ui.addNotification(null, E('p', {}, _('DMZ mode applied. Confirm within rollback window.')), 'info');
|
||||
window.location.reload();
|
||||
} else {
|
||||
ui.addNotification(null, E('p', {}, (result && result.error) || _('Unable to apply DMZ mode')), 'error');
|
||||
}
|
||||
}).catch(function(err) {
|
||||
ui.hideModal();
|
||||
ui.addNotification(null, E('p', {}, err.message || err), 'error');
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -50,6 +50,22 @@ config mode 'router'
|
||||
option frontend_type 'nginx'
|
||||
list frontend_domains ''
|
||||
|
||||
config mode 'dmz'
|
||||
option name 'Router + DMZ'
|
||||
option description 'Router mode with isolated DMZ segment and firewall segmentation'
|
||||
option enabled '0'
|
||||
option wan_interface 'eth1'
|
||||
option wan_protocol 'dhcp'
|
||||
option lan_interface 'br-lan'
|
||||
option lan_ip '192.168.1.1'
|
||||
option lan_netmask '255.255.255.0'
|
||||
option dmz_interface 'eth2'
|
||||
option dmz_ip '192.168.50.1'
|
||||
option dmz_netmask '255.255.255.0'
|
||||
option dmz_dhcp_start '50'
|
||||
option dmz_dhcp_limit '80'
|
||||
option dmz_isolated '1'
|
||||
|
||||
config mode 'doublenat'
|
||||
option name 'Double NAT'
|
||||
option description 'Behind ISP box with isolated LAN'
|
||||
|
||||
@ -393,6 +393,59 @@ get_router_config() {
|
||||
json_dump
|
||||
}
|
||||
|
||||
get_dmz_config() {
|
||||
json_init
|
||||
|
||||
json_add_string "mode" "dmz"
|
||||
json_add_string "name" "Router + DMZ"
|
||||
json_add_string "description" "LAN avec NAT + segment DMZ isolé"
|
||||
|
||||
local wan_iface=$(uci -q get network-modes.dmz.wan_interface || echo "eth1")
|
||||
local wan_proto=$(uci -q get network-modes.dmz.wan_protocol || echo "dhcp")
|
||||
local lan_iface=$(uci -q get network-modes.dmz.lan_interface || echo "br-lan")
|
||||
local lan_ip=$(uci -q get network-modes.dmz.lan_ip || echo "192.168.1.1")
|
||||
local lan_netmask=$(uci -q get network-modes.dmz.lan_netmask || echo "255.255.255.0")
|
||||
local dmz_iface=$(uci -q get network-modes.dmz.dmz_interface || echo "eth2")
|
||||
local dmz_ip=$(uci -q get network-modes.dmz.dmz_ip || echo "192.168.50.1")
|
||||
local dmz_netmask=$(uci -q get network-modes.dmz.dmz_netmask || echo "255.255.255.0")
|
||||
local dmz_start=$(uci -q get network-modes.dmz.dmz_dhcp_start || echo "50")
|
||||
local dmz_limit=$(uci -q get network-modes.dmz.dmz_dhcp_limit || echo "80")
|
||||
local dmz_isolated=$(uci -q get network-modes.dmz.dmz_isolated || echo "1")
|
||||
|
||||
json_add_object "wan"
|
||||
json_add_string "interface" "$wan_iface"
|
||||
json_add_string "protocol" "$wan_proto"
|
||||
json_add_array "protocols"
|
||||
for proto in dhcp static pppoe; do
|
||||
json_add_string "" "$proto"
|
||||
done
|
||||
json_close_array
|
||||
json_close_object
|
||||
|
||||
json_add_object "lan"
|
||||
json_add_string "interface" "$lan_iface"
|
||||
json_add_string "ip_address" "$lan_ip"
|
||||
json_add_string "netmask" "$lan_netmask"
|
||||
json_close_object
|
||||
|
||||
json_add_object "dmz"
|
||||
json_add_string "interface" "$dmz_iface"
|
||||
json_add_string "ip_address" "$dmz_ip"
|
||||
json_add_string "netmask" "$dmz_netmask"
|
||||
json_add_int "dhcp_start" "$dmz_start"
|
||||
json_add_int "dhcp_limit" "$dmz_limit"
|
||||
json_add_boolean "isolated" "$([ "$dmz_isolated" = "1" ] && echo 1 || echo 0)"
|
||||
json_close_object
|
||||
|
||||
json_add_array "available_interfaces"
|
||||
for iface in $(ls /sys/class/net/ | grep -v "^lo$"); do
|
||||
json_add_string "" "$iface"
|
||||
done
|
||||
json_close_array
|
||||
|
||||
json_dump
|
||||
}
|
||||
|
||||
# Get travel router configuration
|
||||
get_travel_config() {
|
||||
json_init
|
||||
@ -599,6 +652,88 @@ apply_mode() {
|
||||
apply_transparent_proxy_rules
|
||||
deploy_nginx_vhosts
|
||||
;;
|
||||
dmz)
|
||||
local dmz_wan=$(uci -q get network-modes.dmz.wan_interface || echo "eth1")
|
||||
local dmz_wan_proto=$(uci -q get network-modes.dmz.wan_protocol || echo "dhcp")
|
||||
local dmz_lan_iface=$(uci -q get network-modes.dmz.lan_interface || echo "br-lan")
|
||||
local dmz_lan_ip=$(uci -q get network-modes.dmz.lan_ip || echo "192.168.1.1")
|
||||
local dmz_lan_netmask=$(uci -q get network-modes.dmz.lan_netmask || echo "255.255.255.0")
|
||||
local dmz_iface=$(uci -q get network-modes.dmz.dmz_interface || echo "eth2")
|
||||
local dmz_ip=$(uci -q get network-modes.dmz.dmz_ip || echo "192.168.50.1")
|
||||
local dmz_netmask=$(uci -q get network-modes.dmz.dmz_netmask || echo "255.255.255.0")
|
||||
local dmz_start=$(uci -q get network-modes.dmz.dmz_dhcp_start || echo "50")
|
||||
local dmz_limit=$(uci -q get network-modes.dmz.dmz_dhcp_limit || echo "80")
|
||||
local dmz_isolated_flag=$(uci -q get network-modes.dmz.dmz_isolated || echo "1")
|
||||
|
||||
uci delete network.wan 2>/dev/null
|
||||
uci set network.wan=interface
|
||||
uci set network.wan.device="$dmz_wan"
|
||||
uci set network.wan.proto="$dmz_wan_proto"
|
||||
|
||||
uci set network.lan=interface
|
||||
uci set network.lan.proto='static'
|
||||
uci set network.lan.device="$dmz_lan_iface"
|
||||
uci set network.lan.ipaddr="$dmz_lan_ip"
|
||||
uci set network.lan.netmask="$dmz_lan_netmask"
|
||||
|
||||
uci delete network.dmz 2>/dev/null
|
||||
uci set network.dmz=interface
|
||||
uci set network.dmz.proto='static'
|
||||
uci set network.dmz.device="$dmz_iface"
|
||||
uci set network.dmz.ipaddr="$dmz_ip"
|
||||
uci set network.dmz.netmask="$dmz_netmask"
|
||||
|
||||
uci set dhcp.lan=dhcp
|
||||
uci set dhcp.lan.interface='lan'
|
||||
uci set dhcp.lan.start='100'
|
||||
uci set dhcp.lan.limit='150'
|
||||
uci set dhcp.lan.leasetime='12h'
|
||||
|
||||
uci delete dhcp.dmz 2>/dev/null
|
||||
uci set dhcp.dmz=dhcp
|
||||
uci set dhcp.dmz.interface='dmz'
|
||||
uci set dhcp.dmz.start="$dmz_start"
|
||||
uci set dhcp.dmz.limit="$dmz_limit"
|
||||
uci set dhcp.dmz.leasetime='12h'
|
||||
|
||||
uci -q delete firewall.lan
|
||||
uci set firewall.lan=zone
|
||||
uci set firewall.lan.name='lan'
|
||||
uci set firewall.lan.network='lan'
|
||||
uci set firewall.lan.input='ACCEPT'
|
||||
uci set firewall.lan.output='ACCEPT'
|
||||
uci set firewall.lan.forward='ACCEPT'
|
||||
|
||||
uci -q delete firewall.wan
|
||||
uci set firewall.wan=zone
|
||||
uci set firewall.wan.name='wan'
|
||||
uci set firewall.wan.network='wan'
|
||||
uci set firewall.wan.input='REJECT'
|
||||
uci set firewall.wan.output='ACCEPT'
|
||||
uci set firewall.wan.forward='REJECT'
|
||||
uci set firewall.wan.masq='1'
|
||||
uci set firewall.wan.mtu_fix='1'
|
||||
|
||||
uci -q delete firewall.dmz
|
||||
uci set firewall.dmz=zone
|
||||
uci set firewall.dmz.name='dmz'
|
||||
uci set firewall.dmz.network='dmz'
|
||||
uci set firewall.dmz.input='REJECT'
|
||||
uci set firewall.dmz.output='ACCEPT'
|
||||
uci set firewall.dmz.forward='REJECT'
|
||||
|
||||
uci -q delete firewall.dmz_wan
|
||||
uci set firewall.dmz_wan=forwarding
|
||||
uci set firewall.dmz_wan.src='dmz'
|
||||
uci set firewall.dmz_wan.dest='wan'
|
||||
|
||||
uci -q delete firewall.dmz_lan 2>/dev/null
|
||||
if [ "$dmz_isolated_flag" != "1" ]; then
|
||||
uci set firewall.dmz_lan=forwarding
|
||||
uci set firewall.dmz_lan.src='dmz'
|
||||
uci set firewall.dmz_lan.dest='lan'
|
||||
fi
|
||||
;;
|
||||
travel)
|
||||
local client_iface=$(uci -q get network-modes.travel.client_interface || echo "wlan1")
|
||||
local client_radio=$(uci -q get network-modes.travel.client_radio || echo "radio1")
|
||||
@ -915,6 +1050,31 @@ update_settings() {
|
||||
[ -n "$dns_over_https" ] && uci set network-modes.router.dns_over_https="$dns_over_https"
|
||||
[ -n "$letsencrypt" ] && uci set network-modes.router.letsencrypt="$letsencrypt"
|
||||
;;
|
||||
dmz)
|
||||
json_get_var wan_interface wan_interface
|
||||
json_get_var wan_protocol wan_protocol
|
||||
json_get_var lan_interface lan_interface
|
||||
json_get_var lan_ip lan_ip
|
||||
json_get_var lan_netmask lan_netmask
|
||||
json_get_var dmz_interface dmz_interface
|
||||
json_get_var dmz_ip dmz_ip
|
||||
json_get_var dmz_netmask dmz_netmask
|
||||
json_get_var dmz_dhcp_start dmz_dhcp_start
|
||||
json_get_var dmz_dhcp_limit dmz_dhcp_limit
|
||||
json_get_var dmz_isolated dmz_isolated
|
||||
|
||||
[ -n "$wan_interface" ] && uci set network-modes.dmz.wan_interface="$wan_interface"
|
||||
[ -n "$wan_protocol" ] && uci set network-modes.dmz.wan_protocol="$wan_protocol"
|
||||
[ -n "$lan_interface" ] && uci set network-modes.dmz.lan_interface="$lan_interface"
|
||||
[ -n "$lan_ip" ] && uci set network-modes.dmz.lan_ip="$lan_ip"
|
||||
[ -n "$lan_netmask" ] && uci set network-modes.dmz.lan_netmask="$lan_netmask"
|
||||
[ -n "$dmz_interface" ] && uci set network-modes.dmz.dmz_interface="$dmz_interface"
|
||||
[ -n "$dmz_ip" ] && uci set network-modes.dmz.dmz_ip="$dmz_ip"
|
||||
[ -n "$dmz_netmask" ] && uci set network-modes.dmz.dmz_netmask="$dmz_netmask"
|
||||
[ -n "$dmz_dhcp_start" ] && uci set network-modes.dmz.dmz_dhcp_start="$dmz_dhcp_start"
|
||||
[ -n "$dmz_dhcp_limit" ] && uci set network-modes.dmz.dmz_dhcp_limit="$dmz_dhcp_limit"
|
||||
[ -n "$dmz_isolated" ] && uci set network-modes.dmz.dmz_isolated="$dmz_isolated"
|
||||
;;
|
||||
travel)
|
||||
json_get_var client_interface client_interface
|
||||
json_get_var client_radio client_radio
|
||||
@ -2016,6 +2176,9 @@ get_available_modes() {
|
||||
add_mode "router" "Router" "🌐" "Mode routeur complet avec NAT, DHCP et firewall" \
|
||||
"NAT activé" "Serveur DHCP" "Firewall (zones WAN/LAN)" "Proxy optionnel"
|
||||
|
||||
add_mode "dmz" "Router + DMZ" "🛡️" "Mode routeur avec réseau DMZ isolé et firewall segmenté" \
|
||||
"Réseau DMZ séparé" "DHCP optionnel pour DMZ" "Isolation LAN/DMZ" "Forwarding WAN contrôlé"
|
||||
|
||||
add_mode "doublenat" "Double NAT" "🔁" "Derrière box opérateur avec réseau isolé" \
|
||||
"WAN DHCP client" "Deuxième LAN privé" "Isolation invitée" "UPnP désactivé"
|
||||
|
||||
@ -2051,7 +2214,7 @@ set_mode() {
|
||||
|
||||
# Validate mode
|
||||
case "$target_mode" in
|
||||
router|multiwan|doublenat|accesspoint|relay|vpnrelay|bridge|sniffer|travel)
|
||||
router|dmz|multiwan|doublenat|accesspoint|relay|vpnrelay|bridge|sniffer|travel)
|
||||
;;
|
||||
*)
|
||||
json_add_boolean "success" 0
|
||||
@ -2104,6 +2267,9 @@ preview_changes() {
|
||||
# Changes array
|
||||
json_add_array "changes"
|
||||
|
||||
local dmz_ip_preview
|
||||
dmz_ip_preview=$(uci -q get network-modes.dmz.dmz_ip || echo "192.168.50.1")
|
||||
|
||||
case "$pending_mode" in
|
||||
router)
|
||||
json_add_object
|
||||
@ -2119,6 +2285,24 @@ preview_changes() {
|
||||
json_add_string "change" "Zones: WAN, LAN, forwarding rules"
|
||||
json_close_object
|
||||
;;
|
||||
dmz)
|
||||
json_add_object
|
||||
json_add_string "file" "/etc/config/network"
|
||||
json_add_string "change" "WAN interface + LAN bridge reconfiguré"
|
||||
json_close_object
|
||||
json_add_object
|
||||
json_add_string "file" "/etc/config/network"
|
||||
json_add_string "change" "Nouveau segment DMZ (${dmz_ip_preview}/24)"
|
||||
json_close_object
|
||||
json_add_object
|
||||
json_add_string "file" "/etc/config/dhcp"
|
||||
json_add_string "change" "Serveur DHCP dédié pour DMZ"
|
||||
json_close_object
|
||||
json_add_object
|
||||
json_add_string "file" "/etc/config/firewall"
|
||||
json_add_string "change" "Zone DMZ isolée (forwarding uniquement vers WAN)"
|
||||
json_close_object
|
||||
;;
|
||||
accesspoint)
|
||||
json_add_object
|
||||
json_add_string "file" "/etc/config/network"
|
||||
@ -2376,7 +2560,7 @@ rollback() {
|
||||
# Main dispatcher
|
||||
case "$1" in
|
||||
list)
|
||||
echo '{"status":{},"modes":{},"get_current_mode":{},"get_available_modes":{},"set_mode":{"mode":"str"},"preview_changes":{},"apply_mode":{},"confirm_mode":{},"rollback":{},"sniffer_config":{},"ap_config":{},"relay_config":{},"router_config":{},"travel_config":{},"doublenat_config":{},"multiwan_config":{},"vpnrelay_config":{},"travel_scan_networks":{},"update_settings":{"mode":"str"},"generate_wireguard_keys":{},"apply_wireguard_config":{},"apply_mtu_clamping":{},"enable_tcp_bbr":{},"add_vhost":{"domain":"str","backend":"str","port":"int","ssl":"bool"},"generate_config":{"mode":"str"},"validate_pcap_filter":{"filter":"str"},"cleanup_old_pcaps":{}}'
|
||||
echo '{"status":{},"modes":{},"get_current_mode":{},"get_available_modes":{},"set_mode":{"mode":"str"},"preview_changes":{},"apply_mode":{},"confirm_mode":{},"rollback":{},"sniffer_config":{},"ap_config":{},"relay_config":{},"router_config":{},"dmz_config":{},"travel_config":{},"doublenat_config":{},"multiwan_config":{},"vpnrelay_config":{},"travel_scan_networks":{},"update_settings":{"mode":"str"},"generate_wireguard_keys":{},"apply_wireguard_config":{},"apply_mtu_clamping":{},"enable_tcp_bbr":{},"add_vhost":{"domain":"str","backend":"str","port":"int","ssl":"bool"},"generate_config":{"mode":"str"},"validate_pcap_filter":{"filter":"str"},"cleanup_old_pcaps":{}}'
|
||||
;;
|
||||
call)
|
||||
case "$2" in
|
||||
@ -2419,6 +2603,9 @@ case "$1" in
|
||||
router_config)
|
||||
get_router_config
|
||||
;;
|
||||
dmz_config)
|
||||
get_dmz_config
|
||||
;;
|
||||
travel_config)
|
||||
get_travel_config
|
||||
;;
|
||||
@ -2479,3 +2666,63 @@ case "$1" in
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
dmz)
|
||||
local wan_if=$(uci -q get network-modes.dmz.wan_interface || echo "eth1")
|
||||
local wan_proto=$(uci -q get network-modes.dmz.wan_protocol || echo "dhcp")
|
||||
local lan_iface=$(uci -q get network-modes.dmz.lan_interface || echo "br-lan")
|
||||
local lan_ip=$(uci -q get network-modes.dmz.lan_ip || echo "192.168.1.1")
|
||||
local lan_mask=$(uci -q get network-modes.dmz.lan_netmask || echo "255.255.255.0")
|
||||
local dmz_iface=$(uci -q get network-modes.dmz.dmz_interface || echo "eth2")
|
||||
local dmz_ip=$(uci -q get network-modes.dmz.dmz_ip || echo "192.168.50.1")
|
||||
local dmz_mask=$(uci -q get network-modes.dmz.dmz_netmask || echo "255.255.255.0")
|
||||
config="# DMZ Mode Configuration
|
||||
# /etc/config/network
|
||||
|
||||
config interface 'wan'
|
||||
option device '$wan_if'
|
||||
option proto '$wan_proto'
|
||||
|
||||
config interface 'lan'
|
||||
option device '$lan_iface'
|
||||
option proto 'static'
|
||||
option ipaddr '$lan_ip'
|
||||
option netmask '$lan_mask'
|
||||
|
||||
config interface 'dmz'
|
||||
option device '$dmz_iface'
|
||||
option proto 'static'
|
||||
option ipaddr '$dmz_ip'
|
||||
option netmask '$dmz_mask'
|
||||
|
||||
# /etc/config/firewall
|
||||
config zone
|
||||
option name 'lan'
|
||||
option input 'ACCEPT'
|
||||
option output 'ACCEPT'
|
||||
option forward 'ACCEPT'
|
||||
list network 'lan'
|
||||
|
||||
config zone
|
||||
option name 'dmz'
|
||||
option input 'REJECT'
|
||||
option output 'ACCEPT'
|
||||
option forward 'REJECT'
|
||||
list network 'dmz'
|
||||
|
||||
config zone
|
||||
option name 'wan'
|
||||
option input 'REJECT'
|
||||
option output 'ACCEPT'
|
||||
option forward 'REJECT'
|
||||
option masq '1'
|
||||
option mtu_fix '1'
|
||||
list network 'wan'
|
||||
|
||||
config forwarding
|
||||
option src 'lan'
|
||||
option dest 'wan'
|
||||
|
||||
config forwarding
|
||||
option src 'dmz'
|
||||
option dest 'wan'"
|
||||
;;
|
||||
|
||||
@ -20,6 +20,11 @@
|
||||
"order": 30,
|
||||
"action": {"type": "view", "path": "network-modes/router"}
|
||||
},
|
||||
"admin/secubox/network/modes/dmz": {
|
||||
"title": "DMZ Mode",
|
||||
"order": 33,
|
||||
"action": {"type": "view", "path": "network-modes/dmz"}
|
||||
},
|
||||
"admin/secubox/network/modes/multiwan": {
|
||||
"title": "Multi-WAN Mode",
|
||||
"order": 35,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user