fix(gui): correct wg dump indexes, status, traffic, UX improvements
- Fix off-by-one bug in wg_dump(): handshake was read from parts[5] (rx_bytes), now correctly reads from parts[4]; rx/tx shifted accordingly - Run wg show via sudo to work under unprivileged wgadmin user - Remove NoNewPrivileges from systemd service (needed for sudo) - Merge Handshake column into Status badge (shows "online · 2м назад") - Add humanize_ago() for human-readable handshake time - Add next_free_ip() to suggest next available IP in new peer form - Add device type quick-select buttons (Phone/Laptop/PC/Router/Server/Tablet) - Placeholder in AllowedIPs now shows the real next free IP - Traffic column shows ↓ rx / ↑ tx separately Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -9,34 +9,44 @@
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
||||
|
||||
<div class="form-group">
|
||||
<label>Имя клиента</label>
|
||||
<input type="text" name="name" placeholder="например: phone-ruslan" autofocus required />
|
||||
<label>Имя устройства</label>
|
||||
<input type="text" name="name" id="name-input" placeholder="например: iphone-ruslan" autofocus required />
|
||||
<div class="name-hints">
|
||||
<span class="hint-label">Быстрый выбор:</span>
|
||||
<button type="button" class="hint-btn" onclick="setPrefix('phone')">Phone</button>
|
||||
<button type="button" class="hint-btn" onclick="setPrefix('laptop')">Laptop</button>
|
||||
<button type="button" class="hint-btn" onclick="setPrefix('pc')">PC</button>
|
||||
<button type="button" class="hint-btn" onclick="setPrefix('router')">Router</button>
|
||||
<button type="button" class="hint-btn" onclick="setPrefix('server')">Server</button>
|
||||
<button type="button" class="hint-btn" onclick="setPrefix('tablet')">Tablet</button>
|
||||
</div>
|
||||
<small>Рекомендуем формат <code>тип-место</code>: <code>laptop-home</code>, <code>router-office</code>, <code>phone-moscow</code></small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Режим</label>
|
||||
<label>Режим туннеля</label>
|
||||
<div class="radio-group">
|
||||
<label class="radio-label">
|
||||
<input type="radio" name="mode" value="full" checked onchange="toggleRoutes(this)">
|
||||
<span>Полный туннель (0.0.0.0/0)</span>
|
||||
<span>Полный туннель — весь трафик через VPN (<code>0.0.0.0/0</code>)</span>
|
||||
</label>
|
||||
<label class="radio-label">
|
||||
<input type="radio" name="mode" value="split" onchange="toggleRoutes(this)">
|
||||
<span>Split-tunnel (только нужные сети)</span>
|
||||
<span>Split-tunnel — только указанные сети</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" id="allowed-ips-group" style="display:none">
|
||||
<label>AllowedIPs для клиента</label>
|
||||
<input type="text" name="allowed_ips" placeholder="{{ meta.get('WG_NETWORK','10.66.66.0/24') }}" />
|
||||
<small>Через запятую. Оставьте пустым — подставится сеть WG.</small>
|
||||
<input type="text" name="allowed_ips" placeholder="{{ next_ip or meta.get('WG_NETWORK','10.66.66.0/24') }}" />
|
||||
<small>Следующий свободный IP: <code>{{ next_ip or 'не определён' }}</code>. Оставьте пустым — подставится автоматически.</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Дополнительные роуты (advertised)</label>
|
||||
<label>Дополнительные роуты <span class="optional">необязательно</span></label>
|
||||
<input type="text" name="routes" placeholder="192.168.1.0/24, 10.0.0.0/8" />
|
||||
<small>Сети, которые клиент анонсирует другим участникам. Необязательно.</small>
|
||||
<small>Локальные сети за клиентом, доступные другим участникам VPN.</small>
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
@@ -51,5 +61,14 @@ function toggleRoutes(el) {
|
||||
document.getElementById('allowed-ips-group').style.display =
|
||||
el.value === 'split' ? 'block' : 'none';
|
||||
}
|
||||
function setPrefix(type) {
|
||||
const inp = document.getElementById('name-input');
|
||||
const cur = inp.value;
|
||||
const m = cur.match(/^[a-z]+-?(.*)$/i);
|
||||
const suffix = (m && m[1]) ? m[1] : '';
|
||||
inp.value = suffix ? type + '-' + suffix : type + '-';
|
||||
inp.focus();
|
||||
inp.setSelectionRange(inp.value.length, inp.value.length);
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user