| name | vpn-security-check |
| description | Infrastructure security audit for VPN server. Use when user asks 'check security', 'is my VPN safe', 'audit security', 'security check'. Also use after deployment when user has security concerns. |
VPN Infrastructure Security Audit
Checks that the VPN server is properly hardened. All checks run via ssh_exec.py — no additional tools needed.
When to Use
- User asks about security: "check security", "is my VPN safe"
- After initial deployment (offer proactively)
- User has security concerns
- Periodic security checkup
The Iron Law
EVERY CHECK MUST RUN A COMMAND. NO ASSUMPTIONS.
"quick-rebuild.sh enables the firewall" is not evidence that the firewall is active. Run the check.
Security Checks
Run ALL checks in order. Report each as PASS/FAIL/WARN with evidence.
1. SSH Hardening
1a. SSH Port
Command: python ssh_exec.py exec "grep -E '^Port ' /etc/ssh/sshd_config"
| Result | Rating |
|---|
| Port != 22 (e.g., 49152) | PASS |
| Port 22 | FAIL — TSPU scans and blocks port 22 to foreign IPs. Change with: python ssh_exec.py exec "sed -i 's/^Port 22/Port 49152/' /etc/ssh/sshd_config && systemctl restart sshd" |
1b. Root Password Login
Command: python ssh_exec.py exec "grep -E '^PasswordAuthentication' /etc/ssh/sshd_config"
| Result | Rating |
|---|
| PasswordAuthentication no | PASS |
| PasswordAuthentication yes | WARN — Key-only auth is more secure. Note: some beginners use password auth intentionally. Inform, don't force change |
| Not set (commented out) | WARN — defaults to yes on most distros |
2. Firewall
2a. UFW Status
Command: python ssh_exec.py exec "ufw status verbose"
| Result | Rating |
|---|
| Status: active, rules for 443/8443/2053/SSH port | PASS |
| Status: inactive | FAIL — python ssh_exec.py exec "ufw --force enable" |
| Active but missing expected ports | WARN — check if needed ports are open |
2b. Open Ports (reality check)
Command: python ssh_exec.py exec "ss -tnlp | grep -E 'LISTEN' | awk '{print \$4, \$6}'"
Verify only expected services are listening:
- xray on 443, 8443, 2053 (VPN)
- x-ui panel (some high port)
- sshd on configured port
- nginx on 80 (camouflage)
Any unexpected service = WARN
3. Intrusion Prevention
3a. fail2ban
Command: python ssh_exec.py exec "systemctl is-active fail2ban && fail2ban-client status sshd 2>/dev/null | grep -E 'Currently|Total'"
| Result | Rating |
|---|
| active + shows ban stats | PASS |
| inactive or not installed | FAIL — python ssh_exec.py exec "apt install -y fail2ban && systemctl enable --now fail2ban" |
4. VPN Service Security
4a. 3X-UI Panel Access
Command: python ssh_exec.py exec "grep -E 'webPort|webBasePath' /etc/x-ui/x-ui.db 2>/dev/null || echo 'db not readable as text'"
Check:
- Panel is on non-standard port (not 80, 443, 8080, 2053)
- Panel base path is randomized (not
/ or /panel)
If DB not readable as text, try: python ssh_exec.py exec "x-ui settings show 2>/dev/null || echo 'cannot read settings'"
| Result | Rating |
|---|
| Non-standard port + randomized path | PASS |
| Default port or path = "/" | WARN — Panel is discoverable. Suggest changing via x-ui settings |
4b. Xray Running with Expected Config
Command: python ssh_exec.py exec "xray version 2>/dev/null || /usr/local/x-ui/bin/xray-linux-amd64 version 2>/dev/null"
| Result | Rating |
|---|
| Version >= 24.x | PASS |
| Old version | WARN — Update with python ssh_exec.py update-xray |
5. Camouflage
5a. Nginx Responding
Command: python ssh_exec.py exec "curl -s -o /dev/null -w '%{http_code}' http://localhost:80"
| Result | Rating |
|---|
| 200 | PASS — Camouflage page is active |
| Connection refused / other | WARN — Without nginx, port scanners see an unusual server profile |
6. Secrets Management
6a. .env Not in Git
Command (local): Check .gitignore includes .env AND git ls-files .env returns nothing
| Result | Rating |
|---|
| .env is gitignored and not tracked | PASS |
| .env is tracked in git | CRITICAL FAIL — git rm --cached .env immediately. Credentials are exposed! |
6b. Credentials File Permissions (on server)
Command: python ssh_exec.py exec "ls -la /root/vpn-credentials.txt 2>/dev/null || echo 'not found'"
| Result | Rating |
|---|
| Permissions -rw------- (600) or not found | PASS |
| World-readable (644, 755, etc.) | WARN — python ssh_exec.py exec "chmod 600 /root/vpn-credentials.txt" |
7. System Updates
Command: python ssh_exec.py exec "apt list --upgradable 2>/dev/null | tail -n +2 | wc -l"
| Result | Rating |
|---|
| 0 or <5 pending updates | PASS |
| 5+ pending security updates | WARN — python ssh_exec.py exec "apt update && apt upgrade -y" |
Report Format
Present as a security scorecard (in Russian):
Аудит безопасности VPN-сервера:
SSH:
1a. SSH-порт: [PASS/FAIL]
1b. Парольная авторизация: [PASS/WARN]
Firewall:
2a. UFW: [PASS/FAIL]
2b. Открытые порты: [PASS/WARN]
Защита от вторжений:
3a. fail2ban: [PASS/FAIL]
VPN-сервис:
4a. Панель 3X-UI: [PASS/WARN]
4b. Версия Xray: [PASS/WARN]
Камуфляж:
5a. Nginx: [PASS/WARN]
Секреты:
6a. .env в git: [PASS/CRITICAL]
6b. Файл credentials: [PASS/WARN]
Обновления:
7. Системные: [PASS/WARN]
Итого: X/10 проверок пройдено
For each FAIL/WARN: provide the specific fix command.
For CRITICAL: fix immediately before continuing.
Communication Rules
- Communicate in Russian
- Run every check — do not skip "because the deploy script handles it"
- If a check fails, provide the exact fix command
- Do not alarm the user unnecessarily — WARN is informational, FAIL needs action, CRITICAL needs immediate action
- Remind user this is an infrastructure audit, not a guarantee of anonymity (VPN protects from censorship, not from targeted surveillance)