DEV Community

Cover image for Securing a Remote Linux Host with firewalld and OpenVPN
Iuri Covaliov
Iuri Covaliov

Posted on • Edited on

Securing a Remote Linux Host with firewalld and OpenVPN

For my experiments I'm renting a remote Linux server. As soon as it was
online, it became clear that the first real problem wasn't installing
software, but reducing how much of the server was exposed to the
internet by default. Services like SSH are continuously scanned and
probed, and a freshly provisioned host is immediately visible.

This lab documents how I secured that host step by step: first by
establishing a strict firewall baseline, then by introducing a private
administrative VPN, and finally by removing public SSH exposure
entirely.


Goal

The goal of this lab is to secure a rented Linux host that acts as the
entry point to a private network.

In this setup, the public host fronts several internal virtual machines.
External HTTP(S) traffic is terminated on the host and routed to
internal services via a reverse proxy, while internal systems are not
directly exposed to the internet.

Although built as a homelab, this mirrors real-world infrastructure
patterns where a single edge node provides controlled access to private
services.

This lab focuses on:

  • Reducing the exposed attack surface
  • Replacing unrestricted public SSH with controlled access
  • Establishing a reusable hardening pattern for future hosts

Constraints / Assumptions

  • The host is publicly reachable.
  • SSH is initially exposed.
  • Out-of-band recovery access is available from the provider.
  • A non-root admin user with sudo is used.
  • Temporary SSH disruption is acceptable during hardening.

High-Level Design

The host serves two roles:

  1. Public entry point (reverse proxy, VPN)
  2. Gateway to a private internal network

Traffic model:

  • Internet → Public host (only required ports open)
  • Public host → Private VMs
  • Administrative access via VPN only (Phase 2)

The final state minimizes public exposure and separates management
traffic from application traffic.


Phase 1 --- Make it work

The objective is to regain control.

Using firewalld with a deny-by-default policy, inbound traffic is
restricted to explicitly allowed services. SSH remains publicly
accessible temporarily to avoid lockout during baseline setup.

Phase 1 ensures:

  • Explicitly defined inbound access
  • Persistent firewall rules
  • Stable administrative connectivity

ICMP remains enabled for diagnostics.


Phase 2 --- Reduce trust / Harden access

With a stable firewall in place, administrative access is redesigned.

Introduce a Private Administrative Network

OpenVPN is deployed to create a private management plane. SSH is no
longer treated as a public service but as a capability granted to
authenticated VPN members.

Split-tunnel mode is intentionally used. Administrative traffic routes
through the VPN, while general internet traffic remains local.

Restrict SSH to VPN + Controlled IP

Once VPN access is validated:

  • Public SSH is removed.
  • SSH is allowed only from:
    • The VPN subnet
    • A specific home IP address (fallback)

This eliminates global SSH exposure.

Disable Root SSH Login

Root login is disabled. Administrative access occurs through a dedicated
non-root user with sudo.


Automating Client Profile Generation

Instead of manually assembling the .ovpn file, the repository includes
a helper script:

make-ovpn.sh
Enter fullscreen mode Exit fullscreen mode

The script:

  • Reads the server configuration
  • Embeds the correct CA and tls-crypt key
  • Extracts the correct certificate block
  • Generates a ready-to-import profile

Example:

./make-ovpn.sh client1
Enter fullscreen mode Exit fullscreen mode

This prevents formatting mistakes and ensures server/client consistency.


Final Validation Checklist

  • SSH not publicly reachable
  • SSH reachable via VPN
  • Root login disabled
  • VPN stable after reboot
  • Firewall rules persist

Lessons Learned

  • Firewall first, VPN second.
  • Separate access plane from data plane.
  • tls-crypt keys must match exactly.
  • Split-tunnel DNS requires careful handling.
  • Root access should be deliberate.

Where to Go Next

  • Replace OpenVPN with WireGuard
  • Mirror firewall rules at provider level
  • Convert the host into a bastion/jump host pattern
  • Automate via Ansible

Repository

The full and step‑by‑step documentation — is available here:

👉 https://github.com/ic-devops-lab/devops-labs/tree/main/ProtectRemoteHostWithFirewallAndVPN

This repository is intended to be read alongside the article: the article explains why each layer exists, while the repository shows how it is implemented.


Published Labs in This Series

Top comments (0)