94 lines
3.8 KiB
Python
94 lines
3.8 KiB
Python
import re
|
|
import os
|
|
from view_common import run, load_ddns, public_ip_info, live_dhcp_leases, fmt_timestamp, BLOCKLISTS_DIR
|
|
|
|
|
|
def get_dnsmasq_stats():
|
|
stats = {'queries': '-', 'hits': '-', 'hit_rate': '-', 'forwarded': '-', 'auth': '-', 'tcp_peak': '-'}
|
|
out = run('journalctl -u dnsmasq -n 200 --no-pager 2>/dev/null')
|
|
for line in reversed(out.splitlines()):
|
|
if 'queries forwarded' in line:
|
|
m = re.search(r'queries forwarded (\d+)', line)
|
|
if m:
|
|
stats['forwarded'] = m.group(1)
|
|
m = re.search(r'queries answered locally (\d+)', line)
|
|
if m:
|
|
stats['hits'] = m.group(1)
|
|
fwd = int(stats['forwarded']) if stats['forwarded'] != '-' else 0
|
|
hit = int(stats['hits']) if stats['hits'] != '-' else 0
|
|
total = fwd + hit
|
|
stats['queries'] = str(total) if total else '-'
|
|
if total > 0:
|
|
stats['hit_rate'] = f'{hit / total * 100:.0f}%'
|
|
break
|
|
if 'auth answered' in line:
|
|
m = re.search(r'auth answered (\d+)', line)
|
|
if m and stats['auth'] == '-':
|
|
stats['auth'] = m.group(1)
|
|
if 'max TCP connections' in line:
|
|
m = re.search(r'max TCP connections (\d+)', line)
|
|
if m and stats['tcp_peak'] == '-':
|
|
stats['tcp_peak'] = m.group(1)
|
|
return stats
|
|
|
|
|
|
def _count_blocked_today():
|
|
out = run("journalctl -u dnsmasq --since today --no-pager 2>/dev/null | grep -c 'is NXDOMAIN'")
|
|
return out or '0'
|
|
|
|
|
|
def _count_blocked_domains():
|
|
try:
|
|
total = sum(
|
|
int(run(f'wc -l < "{BLOCKLISTS_DIR}/{f}"') or 0)
|
|
for f in os.listdir(BLOCKLISTS_DIR) if f.endswith('.con')
|
|
)
|
|
return str(total)
|
|
except Exception:
|
|
return '-'
|
|
|
|
|
|
def _bl_last_update():
|
|
try:
|
|
mtime = max(
|
|
os.path.getmtime(f'{BLOCKLISTS_DIR}/{f}')
|
|
for f in os.listdir(BLOCKLISTS_DIR) if f.endswith('.con')
|
|
)
|
|
return fmt_timestamp(int(mtime))
|
|
except Exception:
|
|
return '-'
|
|
|
|
|
|
def collect_tokens(cfg):
|
|
vlans = cfg.get('vlans', [])
|
|
non_vpn_vlans = [v for v in vlans if not v.get('is_vpn')]
|
|
vlan_names = [v.get('name', '') for v in vlans]
|
|
net = cfg.get('network_interfaces', {})
|
|
dns = cfg.get('upstream_dns', {})
|
|
dns_stats = get_dnsmasq_stats()
|
|
ddns = load_ddns()
|
|
ip_str, domains_sub, last_obtained = public_ip_info(ddns)
|
|
|
|
return {
|
|
'GENERAL_WAN_INTERFACE': str(net.get('wan_interface', '-')),
|
|
'OVERVIEW_VLAN_NAMES': ', '.join(vlan_names) or '-',
|
|
'STAT_VLAN_COUNT': str(len(non_vpn_vlans)),
|
|
'STAT_LEASE_COUNT': str(len(live_dhcp_leases())),
|
|
'STAT_BANNED_IP_COUNT': str(sum(1 for b in cfg.get('banned_ips', []) if b.get('enabled', True))),
|
|
'STAT_BLOCKLIST_COUNT': str(len(cfg.get('dns_blocking', {}).get('blocklists', []))),
|
|
'STAT_BLOCKED_TODAY': _count_blocked_today(),
|
|
'STAT_BLOCKED_DOMAINS': _count_blocked_domains(),
|
|
'STAT_BL_LAST_UPDATE': _bl_last_update(),
|
|
'STAT_UPTIME': run('uptime -p') or '-',
|
|
'STAT_NFTABLES_STATUS': 'Active' if run('nft list tables 2>/dev/null').strip() else 'Inactive',
|
|
'STAT_PUBLIC_IP': ip_str,
|
|
'STAT_DDNS_HOSTNAME': domains_sub,
|
|
'DNS_CACHE_SIZE': str(dns.get('cache_size', '-')),
|
|
'OVERVIEW_UPSTREAM_SERVERS': ', '.join(dns.get('upstream_servers', [])) or '-',
|
|
'DNS_STAT_QUERIES': dns_stats['queries'],
|
|
'DNS_STAT_HITS': dns_stats['hits'],
|
|
'DNS_STAT_HIT_RATE': dns_stats['hit_rate'],
|
|
'DNS_STAT_FORWARDED': dns_stats['forwarded'],
|
|
'DNS_STAT_AUTH': dns_stats['auth'],
|
|
'DNS_STAT_TCP_PEAK': dns_stats['tcp_peak'],
|
|
}
|