Development
This commit is contained in:
parent
6d8be4845e
commit
bc623b14fc
5 changed files with 64 additions and 49 deletions
|
|
@ -33,8 +33,8 @@ def _parse_entry():
|
|||
protocol = sanitize.filtervalue(request.form.get('protocol', ''), validate.VALID_PROTOCOLS)
|
||||
src_raw = request.form.get('src_ip_or_subnet', '').strip()
|
||||
dst_raw = request.form.get('dst_ip_or_subnet', '').strip()
|
||||
dst_port_min_raw = request.form.get('dst_port_min', '').strip()
|
||||
dst_port_max_raw = request.form.get('dst_port_max', '').strip()
|
||||
dest_port_start_raw = request.form.get('dest_port_start', '').strip()
|
||||
dest_port_end_raw = request.form.get('dest_port_end', '').strip()
|
||||
|
||||
if not protocol:
|
||||
flash(f'The configuration has not been saved because the protocol is invalid. '
|
||||
|
|
@ -57,21 +57,21 @@ def _parse_entry():
|
|||
flash(f'The configuration has not been saved because "{dst_raw}" is not a valid IP address or subnet.', 'error')
|
||||
return None, True
|
||||
|
||||
dst_port_min = ''
|
||||
if dst_port_min_raw:
|
||||
dst_port_min = validate.port(dst_port_min_raw)
|
||||
if not dst_port_min:
|
||||
flash(f'The configuration has not been saved because "{dst_port_min_raw}" is not a valid port number (1-65535).', 'error')
|
||||
dest_port_start = ''
|
||||
if dest_port_start_raw:
|
||||
dest_port_start = validate.port(dest_port_start_raw)
|
||||
if not dest_port_start:
|
||||
flash(f'The configuration has not been saved because "{dest_port_start_raw}" is not a valid port number (1-65535).', 'error')
|
||||
return None, True
|
||||
|
||||
dst_port_max = ''
|
||||
if dst_port_max_raw:
|
||||
dst_port_max = validate.port(dst_port_max_raw)
|
||||
if not dst_port_max:
|
||||
flash(f'The configuration has not been saved because "{dst_port_max_raw}" is not a valid port number (1-65535).', 'error')
|
||||
dest_port_end = ''
|
||||
if dest_port_end_raw:
|
||||
dest_port_end = validate.port(dest_port_end_raw)
|
||||
if not dest_port_end:
|
||||
flash(f'The configuration has not been saved because "{dest_port_end_raw}" is not a valid port number (1-65535).', 'error')
|
||||
return None, True
|
||||
|
||||
if dst_port_min and dst_port_max and int(dst_port_min) > int(dst_port_max):
|
||||
if dest_port_start and dest_port_end and int(dest_port_start) > int(dest_port_end):
|
||||
flash('Port range min must not be greater than max.', 'error')
|
||||
return None, True
|
||||
|
||||
|
|
@ -80,8 +80,8 @@ def _parse_entry():
|
|||
'protocol': protocol,
|
||||
'src_ip_or_subnet': src,
|
||||
'dst_ip_or_subnet': dst,
|
||||
'dst_port_min': dst_port_min,
|
||||
'dst_port_max': dst_port_max,
|
||||
'dest_port_start': dest_port_start,
|
||||
'dest_port_end': dest_port_end,
|
||||
'enabled': True,
|
||||
}, None
|
||||
|
||||
|
|
|
|||
|
|
@ -39,13 +39,13 @@
|
|||
"class": "col-mono"
|
||||
},
|
||||
{
|
||||
"label": "Port Min",
|
||||
"field": "dst_port_min",
|
||||
"label": "Port Start",
|
||||
"field": "dest_port_start",
|
||||
"class": "col-mono col-narrow"
|
||||
},
|
||||
{
|
||||
"label": "Port Max",
|
||||
"field": "dst_port_max",
|
||||
"label": "Port End",
|
||||
"field": "dest_port_end",
|
||||
"class": "col-mono col-narrow"
|
||||
},
|
||||
{
|
||||
|
|
@ -80,11 +80,11 @@
|
|||
"input_type": "text"
|
||||
},
|
||||
{
|
||||
"col": "dst_port_min",
|
||||
"col": "dest_port_start",
|
||||
"input_type": "number"
|
||||
},
|
||||
{
|
||||
"col": "dst_port_max",
|
||||
"col": "dest_port_end",
|
||||
"input_type": "number"
|
||||
},
|
||||
{
|
||||
|
|
@ -159,7 +159,7 @@
|
|||
{
|
||||
"type": "field",
|
||||
"label": "Dest Port Range Start",
|
||||
"name": "dst_port_min",
|
||||
"name": "dest_port_start",
|
||||
"input_type": "number",
|
||||
"min": 1,
|
||||
"max": 65535
|
||||
|
|
@ -167,7 +167,7 @@
|
|||
{
|
||||
"type": "field",
|
||||
"label": "Dest Port Range End",
|
||||
"name": "dst_port_max",
|
||||
"name": "dest_port_end",
|
||||
"input_type": "number",
|
||||
"min": 1,
|
||||
"max": 65535
|
||||
|
|
|
|||
|
|
@ -75,7 +75,8 @@
|
|||
"protocol": "tcp",
|
||||
"src_ip_or_subnet": "192.168.10.3",
|
||||
"dst_ip_or_subnet": "192.168.1.20",
|
||||
"dst_port": 32400
|
||||
"dest_port_start": 32400,
|
||||
"dest_port_end": 32400
|
||||
},
|
||||
{
|
||||
"description": "IoT Streaming Box -> Plex",
|
||||
|
|
@ -83,7 +84,8 @@
|
|||
"protocol": "tcp",
|
||||
"src_ip_or_subnet": "192.168.10.4",
|
||||
"dst_ip_or_subnet": "192.168.1.20",
|
||||
"dst_port": 32400
|
||||
"dest_port_start": 32400,
|
||||
"dest_port_end": 32400
|
||||
},
|
||||
{
|
||||
"description": "Kids -> Plex",
|
||||
|
|
@ -91,7 +93,8 @@
|
|||
"protocol": "both",
|
||||
"src_ip_or_subnet": "192.168.30.0/24",
|
||||
"dst_ip_or_subnet": "192.168.1.20",
|
||||
"dst_port": 32400
|
||||
"dest_port_start": 32400,
|
||||
"dest_port_end": 32400
|
||||
},
|
||||
{
|
||||
"description": "Kids -> SMB",
|
||||
|
|
@ -99,7 +102,8 @@
|
|||
"protocol": "tcp",
|
||||
"src_ip_or_subnet": "192.168.30.0/24",
|
||||
"dst_ip_or_subnet": "192.168.1.20",
|
||||
"dst_port": 445
|
||||
"dest_port_start": 445,
|
||||
"dest_port_end": 445
|
||||
},
|
||||
{
|
||||
"description": "Kids -> Game Server",
|
||||
|
|
@ -107,7 +111,8 @@
|
|||
"protocol": "tcp",
|
||||
"src_ip_or_subnet": "192.168.30.0/24",
|
||||
"dst_ip_or_subnet": "192.168.1.20",
|
||||
"dst_port": 25565
|
||||
"dest_port_start": 25565,
|
||||
"dest_port_end": 25565
|
||||
},
|
||||
{
|
||||
"description": "Kids -> Web Server HTTP",
|
||||
|
|
@ -115,7 +120,8 @@
|
|||
"protocol": "tcp",
|
||||
"src_ip_or_subnet": "192.168.30.0/24",
|
||||
"dst_ip_or_subnet": "192.168.1.20",
|
||||
"dst_port": 80
|
||||
"dest_port_start": 80,
|
||||
"dest_port_end": 80
|
||||
},
|
||||
{
|
||||
"description": "Kids -> Web Server HTTPS",
|
||||
|
|
@ -123,7 +129,8 @@
|
|||
"protocol": "tcp",
|
||||
"src_ip_or_subnet": "192.168.30.0/24",
|
||||
"dst_ip_or_subnet": "192.168.1.20",
|
||||
"dst_port": 443
|
||||
"dest_port_start": 443,
|
||||
"dest_port_end": 443
|
||||
},
|
||||
{
|
||||
"description": "Trusted -> Printer (RAW)",
|
||||
|
|
@ -131,7 +138,8 @@
|
|||
"protocol": "tcp",
|
||||
"src_ip_or_subnet": "192.168.1.0/24",
|
||||
"dst_ip_or_subnet": "192.168.10.2",
|
||||
"dst_port": 9100
|
||||
"dest_port_start": 9100,
|
||||
"dest_port_end": 9100
|
||||
},
|
||||
{
|
||||
"description": "Trusted -> Printer (IPP)",
|
||||
|
|
@ -139,7 +147,8 @@
|
|||
"protocol": "tcp",
|
||||
"src_ip_or_subnet": "192.168.1.0/24",
|
||||
"dst_ip_or_subnet": "192.168.10.2",
|
||||
"dst_port": 631
|
||||
"dest_port_start": 631,
|
||||
"dest_port_end": 631
|
||||
},
|
||||
{
|
||||
"description": "Kids -> Printer (RAW)",
|
||||
|
|
@ -147,7 +156,8 @@
|
|||
"protocol": "tcp",
|
||||
"src_ip_or_subnet": "192.168.30.0/24",
|
||||
"dst_ip_or_subnet": "192.168.10.2",
|
||||
"dst_port": 9100
|
||||
"dest_port_start": 9100,
|
||||
"dest_port_end": 9100
|
||||
},
|
||||
{
|
||||
"description": "Kids -> Printer (IPP)",
|
||||
|
|
@ -155,7 +165,8 @@
|
|||
"protocol": "tcp",
|
||||
"src_ip_or_subnet": "192.168.30.0/24",
|
||||
"dst_ip_or_subnet": "192.168.10.2",
|
||||
"dst_port": 631
|
||||
"dest_port_start": 631,
|
||||
"dest_port_end": 631
|
||||
},
|
||||
{
|
||||
"description": "Guest -> Printer (RAW)",
|
||||
|
|
@ -163,7 +174,8 @@
|
|||
"protocol": "tcp",
|
||||
"src_ip_or_subnet": "192.168.20.0/24",
|
||||
"dst_ip_or_subnet": "192.168.10.2",
|
||||
"dst_port": 9100
|
||||
"dest_port_start": 9100,
|
||||
"dest_port_end": 9100
|
||||
},
|
||||
{
|
||||
"description": "Guest -> Printer (IPP)",
|
||||
|
|
@ -171,7 +183,8 @@
|
|||
"protocol": "tcp",
|
||||
"src_ip_or_subnet": "192.168.20.0/24",
|
||||
"dst_ip_or_subnet": "192.168.10.2",
|
||||
"dst_port": 631
|
||||
"dest_port_start": 631,
|
||||
"dest_port_end": 631
|
||||
},
|
||||
{
|
||||
"description": "VPN -> SSH + Rsync",
|
||||
|
|
@ -179,7 +192,8 @@
|
|||
"protocol": "tcp",
|
||||
"src_ip_or_subnet": "192.168.40.0/24",
|
||||
"dst_ip_or_subnet": "192.168.1.20",
|
||||
"dst_port": 22
|
||||
"dest_port_start": 22,
|
||||
"dest_port_end": 22
|
||||
},
|
||||
{
|
||||
"description": "VPN -> SMB",
|
||||
|
|
@ -187,7 +201,8 @@
|
|||
"protocol": "tcp",
|
||||
"src_ip_or_subnet": "192.168.40.0/24",
|
||||
"dst_ip_or_subnet": "192.168.1.20",
|
||||
"dst_port": 445
|
||||
"dest_port_start": 445,
|
||||
"dest_port_end": 445
|
||||
},
|
||||
{
|
||||
"description": "Trusted -> Kids (LAN Gaming)",
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ Validation:
|
|||
Generates DNAT rules only; no forward chain rules needed
|
||||
since redirect_to is always a local IP (INPUT handles it).
|
||||
inter_vlan_exceptions -- src_ip_or_subnet and dst_ip_or_subnet may be a single IPv4 address
|
||||
or a CIDR network. dst_port_min/dst_port_max are optional (1-65535).
|
||||
or a CIDR network. dest_port_start/dest_port_end are optional (1-65535).
|
||||
Protocol must be tcp, udp, or both.
|
||||
|
||||
Usage:
|
||||
|
|
@ -1560,8 +1560,8 @@ def build_nft_config(data, dry_run=False):
|
|||
for r in all_except:
|
||||
src = r["src_ip_or_subnet"]
|
||||
dst = r.get("dst_ip_or_subnet") or r.get("dst_ip", "")
|
||||
min_p = r.get("dst_port_min") or r.get("dst_port")
|
||||
max_p = r.get("dst_port_max")
|
||||
min_p = r.get("dest_port_start") or r.get("dst_port")
|
||||
max_p = r.get("dest_port_end")
|
||||
if min_p and max_p and str(min_p) != str(max_p):
|
||||
port_spec = f"{min_p}-{max_p}"
|
||||
elif min_p:
|
||||
|
|
@ -1739,8 +1739,8 @@ def apply_nftables(data, dry_run=False):
|
|||
for r in active_except:
|
||||
src = r["src_ip_or_subnet"]
|
||||
dst = r.get("dst_ip_or_subnet") or r.get("dst_ip", "")
|
||||
min_p = r.get("dst_port_min") or r.get("dst_port")
|
||||
max_p = r.get("dst_port_max")
|
||||
min_p = r.get("dest_port_start") or r.get("dst_port")
|
||||
max_p = r.get("dest_port_end")
|
||||
if min_p and max_p and str(min_p) != str(max_p):
|
||||
port_str = f":{min_p}-{max_p}"
|
||||
elif min_p:
|
||||
|
|
|
|||
|
|
@ -851,15 +851,15 @@ def validate_config(data):
|
|||
if not ipv4_or_cidr(dst):
|
||||
errors.append(f"{label}: dst_ip_or_subnet '{dst}' is not a valid "
|
||||
f"IPv4 address or network.")
|
||||
if r.get("dst_port_min"):
|
||||
nat_check_port(f"{label} dst_port_min", r.get("dst_port_min"))
|
||||
if r.get("dst_port_max"):
|
||||
nat_check_port(f"{label} dst_port_max", r.get("dst_port_max"))
|
||||
min_p, max_p = r.get("dst_port_min", ""), r.get("dst_port_max", "")
|
||||
if r.get("dest_port_start"):
|
||||
nat_check_port(f"{label} dest_port_start", r.get("dest_port_start"))
|
||||
if r.get("dest_port_end"):
|
||||
nat_check_port(f"{label} dest_port_end", r.get("dest_port_end"))
|
||||
min_p, max_p = r.get("dest_port_start", ""), r.get("dest_port_end", "")
|
||||
if min_p and max_p:
|
||||
try:
|
||||
if int(min_p) > int(max_p):
|
||||
errors.append(f"{label}: dst_port_min {min_p} is greater than dst_port_max {max_p}.")
|
||||
errors.append(f"{label}: dest_port_start {min_p} is greater than dest_port_end {max_p}.")
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue