In the neon-bathed streets of the future city, the air crackles with digital ghosts, packets skittering through fibre-optic veins, surveillance drones circling like metallic vultures, every keystroke a pulse in the endless machine. You’re crouched in your cluttered room, screens flickering, the hum of servers resonating like electrostatic symphonies. You want to slip into the shadows, tunnel through the grid without the watchers knowing you’re there. You want WireGuard and OpenSSH, two lockdown tools, to build secret passageways across hostile networks. The rain in your cortex, reflection of LEDs in puddled puddles of ethernet, you taste freedom, and tension.
This post is for new cybersecurity enthusiasts, those drawn to electric rebel codes, the hum of cryptographic lockpicks, eager to learn the craft. We’ll dive into tunnelling with WireGuard and OpenSSH, peeling back layers of protocol, cipher, port, routing. You will see code snippets, powerful, sometimes dangerous if abused, and understand when you hold a scalpel, not a toy.
WireGuard: The Lightweight Blade in Your Cyber Deck
WireGuard is a VPN tunnelling protocol, sharp, efficient, built on modern cryptography. Its core features include:
- Use of Curve25519 for key exchange, ChaCha20 for stream encryption, Poly1305 for authentication, BLAKE2s for hashing. These primitives give you confidentiality, integrity, authenticity. (informationsecurityasia.com)
- A minimal code-base (≈4,000 lines), reducing attack surface. (techopedia.com)
- Running in the kernel (on Linux) for performance, lower latency, less overhead. (techradar.com)
Trade-offs to note:
- WireGuard by default uses UDP only; tunnelling TCP over TCP (or UDP) through mis-configured paths can lead to performance degradation. (techradar.com)
- Static IP assignment for peers unless extra logic or management infrastructure is built around it. (cloudwards.net)
- No built-in obfuscation; traffic is easily fingerprinted unless hidden by additional layers. (techradar.com)
OpenSSH Tunnelling: The Classic Cloak
OpenSSH, the Swiss-army blade of secure shells, gives you port forwarding, proxying, remote shells, reverse tunnels. Three common patterns:
- Local port forwarding (
ssh -L) to send traffic from your local machine via remote server to a destination. - Remote port forwarding (
ssh -R) to open a port on the remote server that routes back to your local machine or another target. - Dynamic port forwarding (
ssh -D) like a SOCKS proxy; your SSH client becomes a proxy for arbitrary outbound traffic.
From official docs:
bash
# Local forward example:
ssh -L 127.0.0.1:8080:internal.service.local:80 [email protected]
# Remote forward example:
ssh -R 9000:localhost:22 [email protected]
# Dynamic (SOCKS) forward:
ssh -D 1080 [email protected]
Actionable configurations in /etc/ssh/ssh_config or ~/.ssh/config let you bake these into your workflow. (docs.oracle.com)
Merging Powers: WireGuard Under SSH vs SSH Over WireGuard
You can combine WireGuard and OpenSSH in two principal ways: run WireGuard over an SSH-tunnel, or route SSH through a WireGuard-protected network.
Option A: WireGuard inside an SSH tunnel
You wrap the WireGuard UDP port inside an SSH-TCP tunnel. This is often used to bypass strict firewalls that only allow TCP or SSH. Be warned: using TCP as transport for a VPN that expects UDP can introduce performance issues (re-transmissions, head-of-line blocking). Use this only if you have no UDP path. Here’s a sketch:
bash
# On local machine
ssh -N -L 5555:127.0.0.1:51820 [email protected]
# WireGuard peer configuration (local side)
[Peer]
PublicKey = <remote_pubkey>
Endpoint = 127.0.0.1:5555
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
Above, WireGuard will believe it's sending UDP to 127.0.0.1:5555, SSH forwards that to remote, which in turn passes to the real WireGuard listener.
Option B: SSH tunnelling through WireGuard network
You set up a WireGuard VPN between you and a bastion or remote network; then you use OpenSSH inside that VPN to access internal resources securely. Advantage: all SSH traffic is encrypted twice, once by WireGuard, once by SSH; latency often low, performance high since WireGuard is fast. Configuration:
- Set up WireGuard peer-to-peer network (e.g. 10.0.0.1 for client, 10.0.0.2 for server).
- On client, create WireGuard interface:
ini
[Interface]
PrivateKey = <client_privkey>
Address = 10.0.0.1/24
[Peer]
PublicKey = <server_pubkey>
Endpoint = server.example.com:51820
AllowedIPs = 10.0.0.0/24
PersistentKeepalive = 25
- After WireGuard is up, SSH through the 10.0.0.2 address:
bash
ssh [email protected]
This shelters SSH within the VPN tunnel, hides endpoints, improves resistance to passive listening.
Code Snippets & Practical Setup
Here’s a shell script to set up a simple WireGuard peer, then run SSH over it. Use responsibly, only in networks you own or have permission to use. Misuse can be malicious.
bash
#!/bin/bash
# WARNING: may be misused for unauthorised access. Only in trusted contexts.
# Generate keys
wg genkey | tee client_priv | wg pubkey > client_pub
wg genkey | tee server_priv | wg pubkey > server_pub
# Server config at /etc/wireguard/wg0.conf
cat <<EOF > server_wg0.conf
[Interface]
PrivateKey = $(cat server_priv)
Address = 10.0.0.2/24
ListenPort = 51820
[Peer]
PublicKey = $(cat client_pub)
AllowedIPs = 10.0.0.1/32
EOF
# Client config at ~/client_wg0.conf
cat <<EOF > client_wg0.conf
[Interface]
PrivateKey = $(cat client_priv)
Address = 10.0.0.1/24
[Peer]
PublicKey = $(cat server_pub)
Endpoint = 203.0.113.5:51820 # replace with server IP
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
EOF
# Bring up interface (on both sides, with sudo)
# sudo wg-quick up server_wg0.conf
# sudo wg-quick up client_wg0.conf
# Once VPN is live, SSH through WireGuard
ssh [email protected]
Security Tips and Warnings
- Always protect your private keys. If a WireGuard private key or SSH key is compromised, you lose identity. Rotate keys periodically.
- Watch for permissions on key files:
chmod 600. - For SSH port forwarding, ensure your server’s
sshd_confighas judicious settings:AllowTcpForwarding,AllowStreamLocalForwardingas needed. Unrestricted forwarding becomes a pivot for attackers. (ssh.com) - Be cautious with reverse tunnels: ensure authentication and access controls are tight.
- Using WireGuard over TCP (via SSH) can kill performance. Only do it if UDP is blocked. Testing is essential.
Which One, When?
| Scenario | Best Tool / Hybrid |
|---|---|
| Strict firewall only allowing SSH/TCP | Tunnel WireGuard via SSH |
| Need a secure pipe between you and remote network | Use WireGuard, then SSH within it |
| Access internal services behind NAT or closed network | SSH remote forwarding or WireGuard mesh |
| Low-latency, high throughput required | Lean on WireGuard alone, avoid layering unless necessary |
Mastering Tunnelling with WireGuard and OpenSSH
Aim
To guide you through practical steps for creating secure tunnels using WireGuard and OpenSSH, enabling you to securely connect remote networks or individual machines, forward ports and securely route traffic.
Learning outcomes
By following this guide you will be able to:
- Install and configure WireGuard tunnels for point-to-point networking.
- Use OpenSSH for secure remote access and port forwarding.
- Combine WireGuard and OpenSSH to enhance security and flexibility.
- Troubleshoot common issues in tunnel setup and connectivity.
Prerequisites
- A machine running a Linux distribution (Ubuntu, Debian, CentOS, etc.).
- Two or more machines (or one local and one remote) with root or sudo privileges.
- Basic knowledge of Linux command-line usage, networking concepts such as IP addresses, ports, firewall rules.
- WireGuard and OpenSSH server and client packages available via package manager.
1 Step-by-step: Setting up a WireGuard tunnel
1.1 Install WireGuard
bash
sudo apt update
sudo apt install wireguard
1.2 Generate key pairs on each machine (“server”, “client”)
bash
wg genkey | tee privatekey | wg pubkey > publickey
1.3 Configure server side (e.g. /etc/wireguard/wg0.conf)
ini
[Interface]
PrivateKey = <server_private_key>
Address = 10.0.0.1/24
ListenPort = 51820
[Peer]
PublicKey = <client_public_key>
AllowedIPs = 10.0.0.2/32
1.4 Configure client side (e.g. /etc/wireguard/wg0.conf)
ini
[Interface]
PrivateKey = <client_private_key>
Address = 10.0.0.2/24
[Peer]
PublicKey = <server_public_key>
Endpoint = server.example.com:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
1.5 Enable and start WireGuard interface
bash
sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0
1.6 Verify status and connectivity
bash
sudo wg show
ping 10.0.0.1 # from client to server
ping 10.0.0.2 # from server to client
2 Step-by-step: SSH tunnelling with OpenSSH
2.1 Ensure OpenSSH is installed and server is running
bash
sudo apt update
sudo apt install openssh-server
sudo systemctl enable ssh
sudo systemctl start ssh
2.2 Basic SSH remote access
bash
ssh [email protected]
2.3 Local port forwarding
Forward a port from remote to local.
bash
ssh -L 8080:localhost:80 [email protected]
When you visit localhost:8080 on your machine you reach localhost:80 on server.
2.4 Remote port forwarding
Forward a port from local machine to remote.
bash
ssh -R 9090:localhost:3000 [email protected]
Remote server’s port 9090 now forwards traffic to local port 3000.
3 Combining WireGuard and OpenSSH
3.1 Route SSH traffic over WireGuard tunnel
After WireGuard is up, force SSH to use the tunnel rather than public network by specifying the WireGuard-assigned address or using the tunnel in SSH configuration.
E.g. in ~/.ssh/config:
ini
Host remote-via-wg
HostName 10.0.0.1
User username
Port 22
Then run:
bash
ssh remote-via-wg
3.2 Use SSH jump host over WireGuard
If you have a second machine accessible via WireGuard only, use it as a jump host:
bash
ssh -J [email protected] [email protected]
4 Troubleshooting common issues
| Issue | Possible cause | Solution |
|---|---|---|
| No connectivity in WireGuard | Firewall blocking UDP/51820 | Open firewall for UDP on specified port |
| AllowedIPs misconfigured | Overlapping or missing ranges | Check peer AllowedIPs include correct subnets |
| SSH over public rather than WireGuard | DNS resolves to public IP | Use WireGuard address in SSH config |
| Port forwarding not working | SSHD config disallowed GatewayPorts or remote forwarding disabled |
Enable GatewayPorts yes in /etc/ssh/sshd_config and restart sshd |
5 Best practices and security tips
- Use strong, unique keys for WireGuard and SSH key-based authentication.
- Limit
AllowedIPsin WireGuard to only those IPs necessary. - Use non-standard ports for SSH if publicly exposed.
- Regularly apply system and package updates.
- Monitor logs (
/var/log/auth.log, WireGuard status) for unauthorised or unexpected connections.
Following these instructions you will acquire hands-on skill using WireGuard for secure tunnelling, OpenSSH for flexible port forwarding, and combine both to build robust, secure connectivity between machines or networks.
You stand at your terminal, green text scrolling, neon code bleeding into your retinas. You have built tunnels, crafted routes, smuggled packets through gates they were not meant to pass. Let this be your toolkit, the keys, the locks, the shadows. And when the watch-dogs howl, you’ll be there, tucked in darkness, moving unseen.