network-modes: add DMZ mode and docs

This commit is contained in:
CyberMind-FR 2025-12-29 16:58:18 +01:00
parent baab096876
commit 33dcb35ddc
9 changed files with 536 additions and 2 deletions

View File

@ -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 2minute window to restore the previous configs automatically.
---
## Troubleshooting
| Issue | Fix |

View File

@ -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 |

View File

@ -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

View File

@ -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'
]
},

View File

@ -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' },

View File

@ -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');
});
}
});

View File

@ -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'

View File

@ -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'"
;;

View File

@ -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,