Skillfade Logo

Tunneling with Wireguard and OpenSSH

⏳ 9 min read

Table of Contents

    Cybersecurity Illustration

    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:

    1. Set up WireGuard peer-to-peer network (e.g. 10.0.0.1 for client, 10.0.0.2 for server).
    2. 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
    
    1. 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_config has judicious settings: AllowTcpForwarding, AllowStreamLocalForwarding as 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 AllowedIPs in 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.