What a VPN Does for Remote Access

A Virtual Private Network creates an encrypted tunnel between your device and a private network. When you connect to a VPN server, your internet traffic routes through that server before reaching its destination. To the services you access, it appears as if your connection originates from the VPN server's network rather than your actual location.

This setup is useful when you need to access internal business applications, file shares, development servers, or other resources that should not be exposed to the public internet. Rather than opening ports on your network and relying on passwords alone, a VPN keeps those resources isolated while still allowing authorised access from anywhere.

VPNs are not the same as proxies, and they do not automatically make you anonymous online. They encrypt traffic between your device and the VPN server, but traffic from the VPN server to its final destination is not protected by the VPN tunnel itself. For general privacy and anonymity, a privacy-focused commercial VPN service may be more appropriate. For remote access to your own infrastructure, setting up your own VPN server gives you direct control over the configuration and who can connect.

For a broader comparison of remote access methods, including when a VPN makes sense compared to alternatives like Remote Desktop Protocol, it is worth reviewing the practical differences between these approaches.

Choosing Between WireGuard, OpenVPN, and SSH Tunneling

Three technologies commonly used for VPN access are WireGuard, OpenVPN, and SSH-based tunnels. Each has distinct characteristics that make it more suitable for different situations.

WireGuard is the modern choice for most use cases. It uses modern cryptographic primitives, has a significantly smaller codebase than older VPN protocols, and generally establishes connections faster. The configuration format is straightforward, and the performance advantages over OpenVPN are noticeable, particularly on lower-powered hardware or mobile devices.

OpenVPN has been widely used for years and works reliably across different devices and operating systems. It can run over both UDP and TCP, which helps in environments where UDP traffic is restricted or filtered. The setup process is more involved than WireGuard, and the performance is lower, but the extensive track record and flexibility make it a practical option in certain network environments.

SSH tunneling creates a port forward from your local machine through an SSH server to a destination service. This is useful for quick, temporary access to specific resources without configuring a full VPN tunnel.

# SSH tunnel: forward local port 8080 to remote server's port 80 via SSH

ssh -L 8080:localhost:80 [email protected]

For most business needs involving regular remote access to internal resources, WireGuard is the recommended starting point. It delivers better performance and requires less ongoing maintenance than OpenVPN while providing equivalent security for most practical purposes.

Installing WireGuard on Ubuntu

WireGuard is available in the Ubuntu package repositories from Ubuntu 20.04 onwards. For Ubuntu 18.04, you will need to add the WireGuard repository before installation.

# For Ubuntu 20.04 and later
sudo apt update
sudo apt install wireguard

# For Ubuntu 18.04, add the WireGuard PPA first
sudo apt install software-properties-common
sudo add-apt-repository ppa:wireguard/wireguard
sudo apt update
sudo apt install wireguard

Once installed, generate a key pair on the server. The private key stays on the server, and the public key is shared with clients that need to connect.

# Generate server keys
wg genkey | sudo tee /etc/wireguard/server_private.key | wg pubkey | sudo tee /etc/wireguard/server_public.key

# Restrict permissions on the private key
sudo chmod 600 /etc/wireguard/server_private.key

Create the server configuration file using a text editor with root privileges.

sudo nano /etc/wireguard/wg0.conf

Add the following configuration, replacing the placeholder keys with your actual generated keys:

[Interface]
Address = 10.0.0.1/24
ListenPort = 51820
PrivateKey = <SERVER_PRIVATE_KEY>

PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

[Peer]
PublicKey = <CLIENT_PUBLIC_KEY>
AllowedIPs = 10.0.0.2/32

Enable IP forwarding on the server so it can route traffic between the VPN interface and your physical network interface.

echo "net.ipv4.ip_forward = 1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

Configure the firewall to allow WireGuard traffic on the specified port.

sudo ufw allow 51820/udp

Start the WireGuard interface and ensure it starts automatically on boot.

sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0

Configuring the Client Machine

On the client machine, generate a key pair in the same way you did on the server.

wg genkey | tee client_private.key | wg pubkey > client_public.key

Create the client configuration file. Save it with a recognisable name.

[Interface]
PrivateKey = <CLIENT_PRIVATE_KEY>
Address = 10.0.0.2/24
DNS = 1.1.1.1

[Peer]
PublicKey = <SERVER_PUBLIC_KEY>
Endpoint = your_server_ip:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25

The PersistentKeepalive setting helps maintain the connection through NAT devices and firewalls by sending a keepalive packet every 25 seconds.

On the server, add the client's public key to the wg0.conf file as an additional Peer entry.

[Peer]
PublicKey = <CLIENT_PUBLIC_KEY>
AllowedIPs = 10.0.0.2/32

Restart WireGuard on the server to load the updated configuration.

sudo systemctl restart wg-quick@wg0

You can now activate the VPN connection on the client using the configuration file you created.

Managing Multiple Devices and Peers

Each device that needs VPN access requires its own key pair and a corresponding Peer entry on the server. As the number of devices grows, keeping track of which public key belongs to which device becomes important.

A practical approach is to maintain a simple document that maps device names to their public keys and assigned IP addresses within the VPN range. Store this document securely alongside your server configuration backups.

Here is how a server configuration looks with multiple peers:

[Interface]
Address = 10.0.0.1/24
ListenPort = 51820
PrivateKey = <SERVER_PRIVATE_KEY>

# Laptop
[Peer]
PublicKey = <LAPTOP_PUBLIC_KEY>
AllowedIPs = 10.0.0.2/32

# Mobile phone
[Peer]
PublicKey = <PHONE_PUBLIC_KEY>
AllowedIPs = 10.0.0.3/32

# Tablet
[Peer]
PublicKey = <TABLET_PUBLIC_KEY>
AllowedIPs = 10.0.0.4/32

Assigning consistent internal IP addresses makes it easier to set up firewall rules based on IP if you need to restrict access to certain services for specific devices.

Full Tunnel Versus Split Tunnel

The AllowedIPs setting controls what traffic routes through the VPN. In the client configuration above, AllowedIPs = 0.0.0.0/0, ::/0 routes all IPv4 and IPv6 traffic through the VPN. This is a full tunnel configuration.

Full tunnel is useful when you are on an untrusted network, such as public WiFi, and want all your internet activity protected by the VPN. It also means your traffic appears to originate from your VPN server, which can help with accessing region-restricted services.

Split tunneling routes only specific traffic through the VPN while allowing other traffic to go directly to the internet.

# Split tunnel: only route traffic for a specific network range through VPN
AllowedIPs = 192.168.1.0/24

Split tunneling is more efficient when you only need access to your office network and do not want to route all your browsing, streaming, or other traffic through the VPN server. This can reduce latency for general web browsing and reduce bandwidth usage on your VPN server.

Accessing Internal Network Resources

Once connected to the VPN, you can reach resources on the private network using their internal IP addresses. If your office network uses the 192.168.1.0/24 range and your VPN network uses 10.0.0.0/24, a development server at 192.168.1.100 becomes accessible from your client machine at 10.0.0.2.

For services that use domain names internally, configure your VPN client's DNS to point to your internal DNS server. This allows internal hostnames like files.internal or dev.internal to resolve correctly while connected.

[Interface]
PrivateKey = <CLIENT_PRIVATE_KEY>
Address = 10.0.0.2/24
DNS = 192.168.1.1

If you do not have an internal DNS server, you can add entries to your local hosts file instead. However, using an internal DNS server scales better as the number of services grows.

Security Best Practices

WireGuard uses modern cryptography that is considered robust for most practical purposes. Security in a WireGuard setup depends more on how you manage keys and maintain the server than on the protocol itself.

  • Protect private keys: Store the server private key with restricted filesystem permissions (600). If a key is compromised, regenerate it and update all peer configurations with the new public key.
  • Remove unused peers: Delete peer entries from the server configuration when devices are lost, decommissioned, or no longer need access. This prevents former devices from connecting.
  • Keep software updated: Apply WireGuard updates through your package manager regularly to receive security patches and improvements.
  • Use strong key management: Generate keys using the wg genkey command rather than creating them manually. This ensures proper key generation using a secure random source.
  • Consider firewall rules: Limit which services on your internal network are reachable through the VPN. Not every internal service needs to be accessible via VPN.

For a more comprehensive review of common security risks affecting business web applications and infrastructure, the OWASP Top 10 provides useful context on what to protect beyond the VPN layer.

Monitoring Active Connections

You can check which peers are currently connected and see traffic statistics using the WireGuard command line tool.

sudo wg show

This displays which peers are connected, the time of their last handshake, and the amount of data transferred through each connection. Regular monitoring helps you spot unexpected connections or unusual traffic patterns.

If you need to keep a persistent eye on connections, consider logging the output of wg show at regular intervals or integrating it into a monitoring setup that alerts you to unexpected changes.

When to Consider a Different Setup

A basic WireGuard setup works well for small teams with straightforward remote access needs. However, there are situations where additional tools or approaches may be more appropriate.

If you need to manage VPN access for many users across different teams, a more structured approach to key distribution and peer management becomes necessary. Some administrators use configuration management tools or custom scripts to automate the process of adding and removing peers.

If your remote access needs include requiring users to authenticate with usernames and passwords rather than just cryptographic keys, a setup using OpenVPN with an authentication backend may be more suitable, even if the performance trade-off is accepted.

For teams that need remote access alongside other infrastructure management tasks, containerised VPN solutions running on managed infrastructure can simplify deployment and updates. Tools like Docker can help package VPN configurations for consistent deployment across multiple servers.