Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Small VPS: a family VPN with the management plane off the internet

Notes and templates from running a single small VPS as a family VPN endpoint, and from the security audit I did on it afterwards.

The point of this repository is one design decision, applied consistently:

Nothing that manages the server is reachable from the internet. The admin panel, the file sync service and everything else with a login page listen only on an internal WireGuard subnet. The only things the public internet can reach are the VPN entry points and a rate-limited SSH port.

Everything here uses placeholders. No addresses, ports, hostnames or keys from a real deployment appear in this repository — pick your own values as described in hardening-checklist.md.


Architecture

                    internet
                        |
        +---------------+----------------+
        |               |                |
   VPN inbounds     WireGuard        SSH (rate-limited,
   (xray/VLESS)     <WG_PORT>/udp     keys only, <SSH_PORT>)
        |               |
        |               v
        |        admin tunnel <ADMIN_SUBNET>
        |               |
        |     +---------+----------+
        |     |                    |
        |  admin panel        WebDAV / file sync
        |  <PANEL_PORT>       <HTTP_PORT>
        |     (tunnel only)   (tunnel only)
        v
   family devices

Two separate planes:

  • Data plane — the VPN itself (VLESS + Reality over xray). Public by necessity: family devices connect to it from arbitrary networks.
  • Management plane — the xray admin panel and the WebDAV endpoint used to sync notes between devices. Both bind to the host but are firewalled to the WireGuard subnet, so from the internet they do not exist.

WireGuard here is not a privacy tunnel. It is the administrative access path, and all clients run split tunnel (AllowedIPs = <ADMIN_SUBNET>) so only traffic to the server goes through it.

Stack

Component Choice Why
OS Ubuntu 22.04 LTS boring, long support window
VPN xray, VLESS + Reality survives protocol filtering better than plain TLS
Panel 3x-ui web management for xray — never exposed publicly
Admin access WireGuard small, fast, and trivial to firewall by subnet
File sync Apache WebDAV notes sync, content encrypted client-side before upload
Firewall ufw enough for a single host, easy to audit
Certificates acme.sh, Let's Encrypt, DNS-01 see below
Intrusion response fail2ban sshd and the WebDAV auth jail

Three things worth stealing

1. Firewall by subnet, not by obscurity

A management interface on a high port is still on the internet. ufw allow from <ADMIN_SUBNET> to any port <PANEL_PORT> is a different statement from ufw allow <PANEL_PORT>, and only the first one is a security control.

After this change an external scan sees the VPN ports and nothing else. The panel is not "hard to find" — it is unreachable.

2. DNS-01 instead of HTTP-01, so port 80 never opens

The obvious way to renew a certificate is HTTP-01 validation, which needs port 80 open to the world. The common workaround is worse: a cron job that opens the port, runs the renewal, and closes it again.

That job is a scheduled hole. If the renewal hangs, the port stays open, and nothing alerts you.

DNS-01 validation removes the problem instead of scheduling around it: acme.sh proves control of the domain through the DNS provider's API, and port 80 is never opened at all. Any DDNS or DNS provider with an acme.sh DNS plugin works.

3. Audit the rules you already have, not just the ones you add

The most useful part of the audit was deleting rules, not writing them. On my host the firewall carried allow rules for:

  • a DNS port, where the resolver was actually listening on loopback only
  • an internal xray port, also loopback only
  • a TLS port where nothing was listening at all

None of these were exploited. All of them were lies about the system's shape, and they made the real attack surface harder to see. ss -tulpn next to ufw status numbered, line by line, is a twenty-minute job that pays for itself.


Files

File What it is
hardening-checklist.md The audit, as a checklist you can run against your own host
ufw-example.sh Firewall policy with placeholders
wireguard-example.conf Server and client templates for the admin tunnel

Scope and honesty

This is a single host serving one family, not a production fleet. There is no configuration management, no monitoring stack, and no high availability. Backups of the server config are manual.

Automated hardening scanners will not give a host like this a high score, and chasing that number is not the goal — most of the remaining findings are about audit daemons and package tooling that make sense on a fleet and not on one VPS. The controls that matter here are the ones above: the management plane is not routable from the internet, SSH takes keys only, and certificate renewal does not open a port.

License

MIT — see LICENSE.

About

Running a family VPN on one small VPS with the management plane firewalled off the internet

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages