Development
This commit is contained in:
parent
27eaea3d73
commit
c6d2ded525
8 changed files with 188 additions and 171 deletions
|
|
@ -30,8 +30,9 @@ def add_vlan():
|
|||
is_vpn = 'is_vpn' in request.form
|
||||
subnet = sanitize.ip(request.form.get('subnet', ''))
|
||||
subnet_mask = sanitize.subnet_mask(request.form.get('subnet_mask', ''))
|
||||
radius_default = 'radius_default' in request.form
|
||||
mdns_reflection = 'mdns_reflection' in request.form
|
||||
radius_default = 'radius_default' in request.form
|
||||
mdns_reflection = 'mdns_reflection' in request.form
|
||||
dnsmasq_log_queries = 'dnsmasq_log_queries' in request.form
|
||||
use_blocklists = sanitize.filterlist(request.form.getlist('use_blocklists'),
|
||||
{b.get('name') for b in load_core().get('dns_blocking', {}).get('blocklists', [])})
|
||||
|
||||
|
|
@ -67,13 +68,14 @@ def add_vlan():
|
|||
return redirect(VIEW)
|
||||
|
||||
entry = {
|
||||
'name': name,
|
||||
'is_vpn': is_vpn,
|
||||
'subnet': subnet,
|
||||
'subnet_mask': subnet_mask,
|
||||
'use_blocklists': use_blocklists,
|
||||
'radius_default': radius_default,
|
||||
'mdns_reflection': mdns_reflection,
|
||||
'name': name,
|
||||
'is_vpn': is_vpn,
|
||||
'subnet': subnet,
|
||||
'subnet_mask': subnet_mask,
|
||||
'dnsmasq_log_queries': dnsmasq_log_queries,
|
||||
'use_blocklists': use_blocklists,
|
||||
'radius_default': radius_default,
|
||||
'mdns_reflection': mdns_reflection,
|
||||
}
|
||||
if is_vpn:
|
||||
entry['peers'] = []
|
||||
|
|
@ -101,8 +103,9 @@ def edit_vlan():
|
|||
|
||||
name = sanitize.name(request.form.get('name', ''))
|
||||
subnet = sanitize.ip(request.form.get('subnet', ''))
|
||||
radius_default = 'radius_default' in request.form
|
||||
mdns_reflection = 'mdns_reflection' in request.form
|
||||
radius_default = 'radius_default' in request.form
|
||||
mdns_reflection = 'mdns_reflection' in request.form
|
||||
dnsmasq_log_queries = 'dnsmasq_log_queries' in request.form
|
||||
use_blocklists = sanitize.filterlist(request.form.getlist('use_blocklists'),
|
||||
{b.get('name') for b in load_core().get('dns_blocking', {}).get('blocklists', [])})
|
||||
|
||||
|
|
@ -162,13 +165,14 @@ def edit_vlan():
|
|||
return redirect(VIEW)
|
||||
|
||||
existing.update({
|
||||
'name': name,
|
||||
'is_vpn': is_vpn,
|
||||
'subnet': subnet,
|
||||
'subnet_mask': final_mask,
|
||||
'radius_default': radius_default,
|
||||
'mdns_reflection': mdns_reflection,
|
||||
'use_blocklists': use_blocklists,
|
||||
'name': name,
|
||||
'is_vpn': is_vpn,
|
||||
'subnet': subnet,
|
||||
'subnet_mask': final_mask,
|
||||
'dnsmasq_log_queries': dnsmasq_log_queries,
|
||||
'radius_default': radius_default,
|
||||
'mdns_reflection': mdns_reflection,
|
||||
'use_blocklists': use_blocklists,
|
||||
})
|
||||
errors = validate.validate_config(core)
|
||||
if errors:
|
||||
|
|
|
|||
|
|
@ -184,9 +184,8 @@ def dnsblocking_cardblocklistrefresh_refreshnow():
|
|||
@bp.route('/action/dnsblocking_cardlogging_save', methods=['POST'])
|
||||
@require_level('administrator')
|
||||
def dnsblocking_cardlogging_save():
|
||||
log_max_kb_raw = request.form.get('log_max_kb', '').strip()
|
||||
log_errors_only = 'log_errors_only' in request.form
|
||||
dnsmasq_log_queries = 'dnsmasq_log_queries' in request.form
|
||||
log_max_kb_raw = request.form.get('log_max_kb', '').strip()
|
||||
log_errors_only = 'log_errors_only' in request.form
|
||||
|
||||
log_max_kb = validate.int_range(log_max_kb_raw, 64, None)
|
||||
if log_max_kb is None:
|
||||
|
|
@ -202,7 +201,6 @@ def dnsblocking_cardlogging_save():
|
|||
'log_max_kb': log_max_kb,
|
||||
'log_errors_only': log_errors_only,
|
||||
})
|
||||
core.setdefault('network_interfaces', {})['dnsmasq_log_queries'] = dnsmasq_log_queries
|
||||
errors = validate.validate_config(core)
|
||||
if errors:
|
||||
for msg in errors:
|
||||
|
|
|
|||
|
|
@ -12,9 +12,8 @@ _VIEW = '/view/view_upstream_dns'
|
|||
@bp.route('/action/upstreamdns_cardupstreamdns_save', methods=['POST'])
|
||||
@require_level('administrator')
|
||||
def upstreamdns_cardupstreamdns_save():
|
||||
strict_order = 'strict_order' in request.form
|
||||
cache_size_raw = request.form.get('cache_size', '').strip()
|
||||
submitted = request.form.getlist('upstream_servers')
|
||||
strict_order = 'strict_order' in request.form
|
||||
submitted = request.form.getlist('upstream_servers')
|
||||
|
||||
for s in submitted:
|
||||
if not s.strip():
|
||||
|
|
@ -29,26 +28,19 @@ def upstreamdns_cardupstreamdns_save():
|
|||
return redirect(_VIEW)
|
||||
upstream_servers.append(clean)
|
||||
|
||||
cache_size = validate.int_range(cache_size_raw, 0, None)
|
||||
if cache_size is None:
|
||||
flash('Cache Size must be a non-negative integer.', 'error')
|
||||
return redirect(_VIEW)
|
||||
|
||||
if not verify_core_hash(request.form.get('config_hash', '')):
|
||||
flash('Configuration was modified by another session. Please refresh and try again.', 'error')
|
||||
return redirect(_VIEW)
|
||||
|
||||
core = load_core()
|
||||
current = core.get('upstream_dns', {})
|
||||
if (strict_order == bool(current.get('strict_order', False)) and
|
||||
cache_size == int(current.get('cache_size', 0)) and
|
||||
if (strict_order == bool(current.get('strict_order', False)) and
|
||||
upstream_servers == current.get('upstream_servers', [])):
|
||||
flash('No changes detected.', 'info')
|
||||
return redirect(_VIEW)
|
||||
|
||||
core.setdefault('upstream_dns', {}).update({
|
||||
'strict_order': strict_order,
|
||||
'cache_size': cache_size,
|
||||
'upstream_servers': upstream_servers,
|
||||
})
|
||||
errors = validate.validate_config(core)
|
||||
|
|
@ -59,3 +51,32 @@ def upstreamdns_cardupstreamdns_save():
|
|||
save_core(core)
|
||||
flash(queued_msg('core apply'), 'success')
|
||||
return redirect(_VIEW)
|
||||
|
||||
|
||||
@bp.route('/action/upstreamdns_cardforwardingdnsservice_save', methods=['POST'])
|
||||
@require_level('administrator')
|
||||
def upstreamdns_cardforwardingdnsservice_save():
|
||||
cache_size = validate.int_range(request.form.get('cache_size', '').strip(), 0, None)
|
||||
if cache_size is None:
|
||||
flash('Cache Size must be a non-negative integer.', 'error')
|
||||
return redirect(_VIEW)
|
||||
|
||||
if not verify_core_hash(request.form.get('config_hash', '')):
|
||||
flash('Configuration was modified by another session. Please refresh and try again.', 'error')
|
||||
return redirect(_VIEW)
|
||||
|
||||
core = load_core()
|
||||
current = core.get('upstream_dns', {})
|
||||
if cache_size == int(current.get('cache_size', 0)):
|
||||
flash('No changes detected.', 'info')
|
||||
return redirect(_VIEW)
|
||||
|
||||
core.setdefault('upstream_dns', {})['cache_size'] = cache_size
|
||||
errors = validate.validate_config(core)
|
||||
if errors:
|
||||
for msg in errors:
|
||||
flash(msg, 'error')
|
||||
return redirect(_VIEW)
|
||||
save_core(core)
|
||||
flash(queued_msg('core apply'), 'success')
|
||||
return redirect(_VIEW)
|
||||
|
|
|
|||
|
|
@ -291,7 +291,7 @@ def _config_datasource(name):
|
|||
bl_desc = {b['name']: b.get('description', b['name']) for b in core.get('dns_blocking', {}).get('blocklists', []) if 'name' in b}
|
||||
rows = []
|
||||
for v in sorted(vlans, key=lambda x: validate.derive_vlan_id(x.get('subnet', ''), x.get('subnet_mask', 24)) or 0):
|
||||
row = {k: v.get(k) for k in ('name', 'subnet', 'subnet_mask', 'radius_default', 'mdns_reflection', 'is_vpn')}
|
||||
row = {k: v.get(k) for k in ('name', 'subnet', 'subnet_mask', 'radius_default', 'mdns_reflection', 'is_vpn', 'dnsmasq_log_queries')}
|
||||
row['vlan_id'] = validate.derive_vlan_id(v.get('subnet', ''), v.get('subnet_mask', 24))
|
||||
row['interface'] = _resolve_iface(v, core)
|
||||
row['use_blocklists'] = json.dumps([
|
||||
|
|
@ -587,9 +587,8 @@ def collect_tokens():
|
|||
)
|
||||
tokens['NETWORK_INTERFACE_STATS_SPEED_PAD'] = str(max(max_speed_len, len('Speed')))
|
||||
|
||||
tokens['GENERAL_LOG_ERRORS_ONLY'] = 'true' if dns_blk_gen.get('log_errors_only') else 'false'
|
||||
tokens['GENERAL_DNSMASQ_LOG_QUERIES'] = 'true' if net.get('dnsmasq_log_queries') else 'false'
|
||||
tokens['GENERAL_DAILY_EXECUTE_TIME'] = str(dns_blk_gen.get('daily_execute_time_24hr_local', '-'))
|
||||
tokens['GENERAL_LOG_ERRORS_ONLY'] = 'true' if dns_blk_gen.get('log_errors_only') else 'false'
|
||||
tokens['GENERAL_DAILY_EXECUTE_TIME'] = str(dns_blk_gen.get('daily_execute_time_24hr_local', '-'))
|
||||
tokens['GENERAL_APPLY_ON_SAVE'] = 'true' if net.get('apply_on_save', True) else 'false'
|
||||
|
||||
pending_items = get_dashboard_pending()
|
||||
|
|
@ -1431,6 +1430,13 @@ def _render_table_cell(value, render_fn, col_class='', field='', row_idx=None,
|
|||
inner = '<span class="badge badge-disabled">Disabled</span>'
|
||||
return f'{td_open}{inner}</td>'
|
||||
|
||||
if render_fn == 'badge_recording_on_off':
|
||||
if str(value).lower() in ('true', '1', 'yes'):
|
||||
inner = '<span class="badge badge-enabled">Recording On</span>'
|
||||
else:
|
||||
inner = '<span class="badge badge-disabled">Recording Off</span>'
|
||||
return f'{td_open}{inner}</td>'
|
||||
|
||||
if render_fn == 'badge_toggle':
|
||||
if str(value).lower() in ('true', '1', 'yes', 'enabled'):
|
||||
label = 'Enabled'; badge_cls = 'badge-enabled'
|
||||
|
|
|
|||
|
|
@ -13,14 +13,14 @@
|
|||
"items": [
|
||||
{ "type": "nav_item", "label": "General", "map_to": "view_general", "client_requirement": "client_is_administrator+" },
|
||||
{ "type": "nav_item", "label": "Network Interfaces", "map_to": "view_network_interfaces", "client_requirement": "client_is_administrator+" },
|
||||
{ "type": "nav_item", "label": "Upstream DNS", "map_to": "view_upstream_dns", "client_requirement": "client_is_administrator+" },
|
||||
{ "type": "nav_item", "label": "DNS", "map_to": "view_upstream_dns", "client_requirement": "client_is_administrator+" },
|
||||
{ "type": "nav_item", "label": "DNS Blocking", "map_to": "view_dns_blocking", "client_requirement": "client_is_administrator+" },
|
||||
{ "type": "nav_item", "label": "DDNS", "map_to": "view_ddns" },
|
||||
{ "type": "nav_item", "label": "VLANs", "map_to": "view_vlans", "client_requirement": "client_is_administrator+" },
|
||||
{ "type": "nav_item", "label": "Inter-VLAN Exceptions", "map_to": "view_inter_vlan", "client_requirement": "client_is_administrator+" },
|
||||
{ "type": "nav_item", "label": "Port Forwarding", "map_to": "view_port_forwarding", "client_requirement": "client_is_administrator+" },
|
||||
{ "type": "nav_item", "label": "DHCP", "map_to": "view_dhcp" },
|
||||
{ "type": "nav_item", "label": "Host Overrides", "map_to": "view_host_overrides", "client_requirement": "client_is_administrator+" },
|
||||
{ "type": "nav_item", "label": "DDNS", "map_to": "view_ddns" },
|
||||
{ "type": "nav_item", "label": "VPN", "map_to": "view_vpn" },
|
||||
{ "type": "nav_item", "label": "Banned IPs", "map_to": "view_banned_ips", "client_requirement": "client_is_administrator+" }
|
||||
]
|
||||
|
|
|
|||
|
|
@ -819,11 +819,11 @@
|
|||
"items": [
|
||||
{
|
||||
"type": "h1",
|
||||
"text": "Upstream DNS"
|
||||
"text": "DNS"
|
||||
},
|
||||
{
|
||||
"type": "p",
|
||||
"text": "Upstream resolvers and caching behaviour for dnsmasq."
|
||||
"text": "Upstream resolvers and forwarding DNS service settings."
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -845,15 +845,6 @@
|
|||
"value": "%DNS_STRICT_ORDER%",
|
||||
"hint": "Query DNS providers in list order rather than in parallel."
|
||||
},
|
||||
{
|
||||
"type": "field",
|
||||
"label": "Cache Size",
|
||||
"name": "cache_size",
|
||||
"input_type": "number",
|
||||
"value": "%DNS_CACHE_SIZE%",
|
||||
"min": 0,
|
||||
"hint": "Max DNS responses to cache per instance. Set to 0 to disable caching."
|
||||
},
|
||||
{
|
||||
"type": "editable_list",
|
||||
"label": "DNS Providers",
|
||||
|
|
@ -882,6 +873,44 @@
|
|||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
"label": "Forwarding DNS Service",
|
||||
"client_requirement": "client_is_administrator+",
|
||||
"items": [
|
||||
{
|
||||
"type": "form",
|
||||
"action": "/action/upstreamdns_cardforwardingdnsservice_save",
|
||||
"method": "post",
|
||||
"items": [
|
||||
{
|
||||
"type": "field",
|
||||
"label": "Cache Size",
|
||||
"name": "cache_size",
|
||||
"input_type": "number",
|
||||
"value": "%DNS_CACHE_SIZE%",
|
||||
"min": 0,
|
||||
"hint": "Max DNS responses to cache per instance. Set to 0 to disable caching."
|
||||
},
|
||||
{
|
||||
"type": "button_row",
|
||||
"items": [
|
||||
{
|
||||
"type": "button_primary",
|
||||
"action": "/action/upstreamdns_cardforwardingdnsservice_save",
|
||||
"method": "post",
|
||||
"text": "Save"
|
||||
},
|
||||
{
|
||||
"type": "button_cancel",
|
||||
"text": "Cancel"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -1156,60 +1185,6 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
"label": "Logging",
|
||||
"client_requirement": "client_is_administrator+",
|
||||
"items": [
|
||||
{
|
||||
"type": "form",
|
||||
"action": "/action/dnsblocking_cardlogging_save",
|
||||
"method": "post",
|
||||
"items": [
|
||||
{
|
||||
"type": "field",
|
||||
"label": "Max Log Size (KB)",
|
||||
"name": "log_max_kb",
|
||||
"input_type": "number",
|
||||
"value": "%GENERAL_LOG_MAX_KB%",
|
||||
"min": 64,
|
||||
"hint": "Log is cleared and restarted when it exceeds this size."
|
||||
},
|
||||
{
|
||||
"type": "field",
|
||||
"label": "Errors Only",
|
||||
"name": "log_errors_only",
|
||||
"input_type": "checkbox",
|
||||
"value": "%GENERAL_LOG_ERRORS_ONLY%",
|
||||
"hint": "Only write error-level messages to the log."
|
||||
},
|
||||
{
|
||||
"type": "field",
|
||||
"label": "Log DNS Queries",
|
||||
"name": "dnsmasq_log_queries",
|
||||
"input_type": "checkbox",
|
||||
"value": "%GENERAL_DNSMASQ_LOG_QUERIES%",
|
||||
"hint": "Log every DNS query. High volume \u2014 enable for debugging only."
|
||||
},
|
||||
{
|
||||
"type": "button_row",
|
||||
"items": [
|
||||
{
|
||||
"type": "button_primary",
|
||||
"action": "/action/dnsblocking_cardlogging_save",
|
||||
"method": "post",
|
||||
"text": "Save"
|
||||
},
|
||||
{
|
||||
"type": "button_cancel",
|
||||
"text": "Cancel"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "table",
|
||||
"datasource": "config:blocklists",
|
||||
|
|
@ -1393,6 +1368,52 @@
|
|||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
"label": "Logging",
|
||||
"client_requirement": "client_is_administrator+",
|
||||
"items": [
|
||||
{
|
||||
"type": "form",
|
||||
"action": "/action/dnsblocking_cardlogging_save",
|
||||
"method": "post",
|
||||
"items": [
|
||||
{
|
||||
"type": "field",
|
||||
"label": "Max Log Size (KB)",
|
||||
"name": "log_max_kb",
|
||||
"input_type": "number",
|
||||
"value": "%GENERAL_LOG_MAX_KB%",
|
||||
"min": 64,
|
||||
"hint": "Log is cleared and restarted when it exceeds this size."
|
||||
},
|
||||
{
|
||||
"type": "field",
|
||||
"label": "Errors Only",
|
||||
"name": "log_errors_only",
|
||||
"input_type": "checkbox",
|
||||
"value": "%GENERAL_LOG_ERRORS_ONLY%",
|
||||
"hint": "Only write error-level messages to the log."
|
||||
},
|
||||
{
|
||||
"type": "button_row",
|
||||
"items": [
|
||||
{
|
||||
"type": "button_primary",
|
||||
"action": "/action/dnsblocking_cardlogging_save",
|
||||
"method": "post",
|
||||
"text": "Save"
|
||||
},
|
||||
{
|
||||
"type": "button_cancel",
|
||||
"text": "Cancel"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -1465,6 +1486,12 @@
|
|||
"field": "mdns_reflection",
|
||||
"class": "col-narrow",
|
||||
"render": "badge_enabled_disabled"
|
||||
},
|
||||
{
|
||||
"label": "DNS Queries",
|
||||
"field": "dnsmasq_log_queries",
|
||||
"class": "col-narrow",
|
||||
"render": "badge_recording_on_off"
|
||||
}
|
||||
],
|
||||
"row_actions": [
|
||||
|
|
@ -1498,6 +1525,10 @@
|
|||
"col": "mdns_reflection",
|
||||
"input_type": "checkbox"
|
||||
},
|
||||
{
|
||||
"col": "dnsmasq_log_queries",
|
||||
"input_type": "checkbox"
|
||||
},
|
||||
{
|
||||
"col": "use_blocklists",
|
||||
"input_type": "checkbox_multi",
|
||||
|
|
@ -1610,6 +1641,13 @@
|
|||
"input_type": "checkbox",
|
||||
"hint": "Reflect mDNS traffic to/from this VLAN via avahi-daemon. Not supported on WireGuard interfaces."
|
||||
},
|
||||
{
|
||||
"type": "field",
|
||||
"label": "Record DNS Queries",
|
||||
"name": "dnsmasq_log_queries",
|
||||
"input_type": "checkbox",
|
||||
"hint": "Log every DNS query. High volume — enable for debugging only."
|
||||
},
|
||||
{
|
||||
"type": "button_row",
|
||||
"items": [
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
{
|
||||
"network_interfaces": {
|
||||
"wan_interface": "eno2",
|
||||
"lan_interface": "enp6s0",
|
||||
"dnsmasq_log_queries": false
|
||||
"lan_interface": "enp6s0"
|
||||
},
|
||||
"upstream_dns": {
|
||||
"strict_order": false,
|
||||
|
|
@ -264,10 +263,11 @@
|
|||
],
|
||||
"vlans": [
|
||||
{
|
||||
"vlan_id": 1,
|
||||
"name": "trusted",
|
||||
"subnet": "192.168.1.0",
|
||||
"subnet_mask": 24,
|
||||
"is_vpn": false,
|
||||
"dnsmasq_log_queries": false,
|
||||
"radius_default": false,
|
||||
"mdns_reflection": false,
|
||||
"use_blocklists": [
|
||||
|
|
@ -364,14 +364,14 @@
|
|||
"dest_port": 123,
|
||||
"redirect_to": "192.168.1.1"
|
||||
}
|
||||
],
|
||||
"is_vpn": false
|
||||
]
|
||||
},
|
||||
{
|
||||
"vlan_id": 10,
|
||||
"name": "iot",
|
||||
"subnet": "192.168.10.0",
|
||||
"subnet_mask": 24,
|
||||
"is_vpn": false,
|
||||
"dnsmasq_log_queries": false,
|
||||
"radius_default": false,
|
||||
"mdns_reflection": true,
|
||||
"use_blocklists": [
|
||||
|
|
@ -468,14 +468,14 @@
|
|||
"dest_port": 123,
|
||||
"redirect_to": "192.168.10.1"
|
||||
}
|
||||
],
|
||||
"is_vpn": false
|
||||
]
|
||||
},
|
||||
{
|
||||
"vlan_id": 20,
|
||||
"name": "guest",
|
||||
"subnet": "192.168.20.0",
|
||||
"subnet_mask": 24,
|
||||
"is_vpn": false,
|
||||
"dnsmasq_log_queries": false,
|
||||
"radius_default": true,
|
||||
"mdns_reflection": true,
|
||||
"use_blocklists": [
|
||||
|
|
@ -530,14 +530,14 @@
|
|||
"dest_port": 123,
|
||||
"redirect_to": "192.168.20.1"
|
||||
}
|
||||
],
|
||||
"is_vpn": false
|
||||
]
|
||||
},
|
||||
{
|
||||
"vlan_id": 30,
|
||||
"name": "kids",
|
||||
"subnet": "192.168.30.0",
|
||||
"subnet_mask": 24,
|
||||
"is_vpn": false,
|
||||
"dnsmasq_log_queries": false,
|
||||
"radius_default": false,
|
||||
"mdns_reflection": true,
|
||||
"use_blocklists": [
|
||||
|
|
@ -607,14 +607,14 @@
|
|||
"dest_port": 123,
|
||||
"redirect_to": "192.168.30.1"
|
||||
}
|
||||
],
|
||||
"is_vpn": false
|
||||
]
|
||||
},
|
||||
{
|
||||
"vlan_id": 40,
|
||||
"name": "vpn",
|
||||
"subnet": "192.168.40.0",
|
||||
"subnet_mask": 24,
|
||||
"is_vpn": true,
|
||||
"dnsmasq_log_queries": false,
|
||||
"radius_default": false,
|
||||
"mdns_reflection": false,
|
||||
"use_blocklists": [
|
||||
|
|
@ -653,8 +653,7 @@
|
|||
"dest_port": 123,
|
||||
"redirect_to": "192.168.40.1"
|
||||
}
|
||||
],
|
||||
"is_vpn": true
|
||||
]
|
||||
}
|
||||
],
|
||||
"ddns": {
|
||||
|
|
|
|||
|
|
@ -87,7 +87,6 @@ Usage:
|
|||
import hashlib
|
||||
import ipaddress
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
|
|
@ -108,7 +107,6 @@ PRODUCT_NAME = "routlin"
|
|||
SCRIPT_DIR = Path(__file__).parent
|
||||
CONFIG_FILE = SCRIPT_DIR / "core.json"
|
||||
BLOCKLIST_DIR = SCRIPT_DIR / "blocklists"
|
||||
LOG_FILE = SCRIPT_DIR / "core.log"
|
||||
METRICS_FILE = SCRIPT_DIR / ".dns-metrics"
|
||||
DNSMASQ_CONF_DIR = Path(f"/etc/dnsmasq-{PRODUCT_NAME}")
|
||||
LEASES_DIR = Path("/var/lib/misc")
|
||||
|
|
@ -140,48 +138,6 @@ NAT_SERVICE_FILE = SYSTEMD_DIR / f"{NAT_SERVICE_NAME}.service"
|
|||
WG_DIR = Path("/etc/wireguard")
|
||||
WG_KEEPALIVE = 25
|
||||
|
||||
log = None
|
||||
|
||||
# ===================================================================
|
||||
# Logging
|
||||
# ===================================================================
|
||||
|
||||
def chown_to_script_dir_owner(path):
|
||||
"""Chown a file to the owner of the script directory.
|
||||
This works correctly whether invoked via sudo, directly as root (e.g. systemd timer),
|
||||
or as a normal user - the script directory owner is always the right target.
|
||||
"""
|
||||
try:
|
||||
stat = SCRIPT_DIR.stat()
|
||||
os.chown(path, stat.st_uid, stat.st_gid)
|
||||
except OSError:
|
||||
pass # non-fatal
|
||||
|
||||
def setup_logging(max_kb, errors_only):
|
||||
global log
|
||||
try:
|
||||
if LOG_FILE.exists() and LOG_FILE.stat().st_size > max_kb * 1024:
|
||||
LOG_FILE.write_text("")
|
||||
if not LOG_FILE.exists():
|
||||
LOG_FILE.touch()
|
||||
chown_to_script_dir_owner(LOG_FILE)
|
||||
file_handler = logging.FileHandler(LOG_FILE)
|
||||
except PermissionError:
|
||||
print(f"WARNING: Cannot write to {LOG_FILE} (permission denied). "
|
||||
f"Run with sudo or fix ownership: sudo chown $USER {LOG_FILE}")
|
||||
file_handler = None
|
||||
level = logging.ERROR if errors_only else logging.INFO
|
||||
handlers = [logging.StreamHandler(sys.stdout)]
|
||||
if file_handler:
|
||||
handlers.insert(0, file_handler)
|
||||
logging.basicConfig(
|
||||
level=level,
|
||||
format="%(asctime)s %(levelname)-8s %(message)s",
|
||||
datefmt="%Y-%m-%d %H:%M:%S",
|
||||
handlers=handlers,
|
||||
)
|
||||
log = logging.getLogger("dns-dhcp")
|
||||
|
||||
# ===================================================================
|
||||
# Helpers
|
||||
# ===================================================================
|
||||
|
|
@ -592,7 +548,7 @@ def build_vlan_dnsmasq_conf(vlan, data, iface):
|
|||
continue # skip IPv6 upstream -- WAN has no IPv6 address
|
||||
line(f"server={srv}")
|
||||
line(f"cache-size={dns_cfg.get('cache_size', 1000)}")
|
||||
if general.get("dnsmasq_log_queries", False):
|
||||
if vlan.get("dnsmasq_log_queries", False):
|
||||
line("log-queries")
|
||||
line()
|
||||
|
||||
|
|
@ -3132,11 +3088,6 @@ def main():
|
|||
print(f" - {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
general = data.get("dns_blocking", {}).get("general", {})
|
||||
setup_logging(
|
||||
general.get("log_max_kb", 1024),
|
||||
general.get("log_errors_only", False)
|
||||
)
|
||||
|
||||
if args.status:
|
||||
show_status(data)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue