0.3_Hardened_Jump_Hosts_OCI_AWS_DigitalOcean

Hardened Jump Hosts on OCI, AWS, and DigitalOcean

BLUF: If you need a "jump point" for legitimate administration, make it a hardened bastion host with narrowly scoped ingress, strong identity controls, centralized logging, and no direct trust beyond what is required.

Warning

This note covers defensive bastion/jump-host architecture for approved administrative access. It does not cover offensive redirectors, covert proxying, or C2 infrastructure.


1. Safe Architecture

graph TD
    Admin[Admin laptop
VPN or allowlisted IP] --> Bastion[Bastion / Jump Host] Bastion --> Private1[Private workload subnet] Bastion --> Private2[Internal admin endpoint] Bastion --> Logs[Central logs / SIEM] Bastion --> Patch[Patch + config management] FW[Cloud firewall / SG / NSG] --> Bastion

Core Pattern

  1. Put the bastion in its own subnet or isolate it with strict firewall policy.
  2. Allow inbound access only from your admin IP range or VPN.
  3. Use SSH keys only or a managed access service.
  4. Send auth, audit, and network logs to a central location.
  5. Treat the bastion as ephemeral infrastructure, not a snowflake box.

2. Best Option by Cloud

Cloud Preferred approach Good fallback
OCI OCI Bastion service for private SSH sessions Small hardened compute instance with NSG-restricted SSH
AWS SSM Session Manager with no inbound SSH if possible EC2 bastion with SG allowlisting and SSH keys only
DigitalOcean Hardened Droplet with Cloud Firewall and private networking Same, plus WireGuard/Tailscale if you want no public SSH from the internet

Rule: If the cloud gives you a managed access path, prefer that over a permanently exposed VM.


3. Shared Hardening Checklist

Minimal sshd_config Baseline

PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
PermitEmptyPasswords no
MaxAuthTries 3
X11Forwarding no
AllowTcpForwarding no
AllowAgentForwarding no
ClientAliveInterval 300
ClientAliveCountMax 2

Re-enable AllowTcpForwarding only if you explicitly need it for legitimate admin workflows.


4. GitHub Resources

These are useful as reference material for bastions, reverse proxies, and hardening patterns:

Resource Use
BastionBox Simple bastion host setup ideas for cloud labs
docker-bastion Minimal OpenSSH bastion container reference
jumpbox Multi-user SSH jumpbox reference
secured-bastion-host-terraform AWS sample for secured bastion infrastructure
reproxy Lightweight reverse-proxy reference
ansible-cis-nginx-hardening NGINX hardening examples

5. Step-by-Step Walkthrough

Step 1 — Decide whether you need a VM at all

Use this decision rule:

If you only need a short-lived admin path, avoid creating a permanent public bastion.


Step 2 — Build isolated network boundaries

Before you launch anything:

  1. Create or identify the target VPC/VCN/project network.
  2. Put the bastion in a separate subnet or isolate it with dedicated firewall rules.
  3. Allow inbound admin access only from:
    • your static office/home IP
    • a corporate VPN
    • a private overlay like WireGuard or Tailscale
  4. Allow outbound traffic only to:
    • package mirrors
    • logging destinations
    • the specific internal systems you administer

Do not allow 0.0.0.0/0 to SSH unless this is a temporary lab and you understand the risk.


Step 3 — Launch the smallest possible host

Preferred baseline:

After first boot:

sudo apt update && sudo apt -y upgrade
sudo apt -y install fail2ban unattended-upgrades auditd

Create a dedicated admin user:

sudo adduser adminops
sudo usermod -aG sudo adminops
sudo mkdir -p /home/adminops/.ssh
sudo cp /home/ubuntu/.ssh/authorized_keys /home/adminops/.ssh/authorized_keys
sudo chown -R adminops:adminops /home/adminops/.ssh
sudo chmod 700 /home/adminops/.ssh
sudo chmod 600 /home/adminops/.ssh/authorized_keys

Step 4 — Harden SSH immediately

Edit /etc/ssh/sshd_config and apply the baseline above.

Then restart SSH:

sudo systemctl restart ssh
sudo systemctl status ssh --no-pager

Enable Fail2ban:

sudo systemctl enable --now fail2ban
sudo fail2ban-client status

Keep one working session open while testing SSH changes so you do not lock yourself out.


Step 5 — Enable logging and updates

At minimum:

Also enable automatic updates:

sudo dpkg-reconfigure --priority=low unattended-upgrades

If you have a SIEM or log collector, ship logs off-host so compromise of the bastion does not erase the trail.


Step 6 — Test the path like an operator

Validate all of the following:

  1. You can log in from the approved admin source.
  2. You cannot log in from an unapproved source.
  3. Password auth is rejected.
  4. Root login is rejected.
  5. Logs arrive centrally.
  6. The bastion can reach only the internal systems it is supposed to manage.

Useful checks:

ssh -o PreferredAuthentications=password adminops@bastion.example
ssh adminops@bastion.example
sudo tail -n 50 /var/log/auth.log
sudo ufw status verbose

6. OCI Walkthrough

Preferred: OCI Bastion Service

  1. Create or identify a private subnet for the target host.
  2. In OCI, create a Bastion in the same VCN.
  3. Create a session scoped to the target private instance.
  4. Restrict session lifetime and allowed CIDR/source where possible.
  5. Use the generated SSH command to connect through the managed bastion path.

Why this is best: no permanently exposed public SSH service is required.

If you must use a bastion VM

  1. Launch a small compute instance in a subnet with a public IP.
  2. Create an NSG or Security List rule allowing TCP/22 only from your admin IP.
  3. Block all other inbound ports unless there is a documented need.
  4. Permit outbound traffic only to required private subnets and update/logging endpoints.
  5. Apply the shared hardening checklist.

OCI quick checks


7. AWS Walkthrough

Preferred: SSM Session Manager

  1. Launch EC2 in a private subnet if possible.
  2. Attach an IAM role with the minimum SSM permissions needed.
  3. Ensure the SSM Agent is installed and online.
  4. Create VPC endpoints or controlled outbound internet access so the instance can reach SSM.
  5. Connect with Session Manager instead of exposing inbound SSH.

Why this is best: no inbound port 22 required.

If you must use an EC2 bastion

  1. Place the EC2 bastion in a public subnet.
  2. Assign a Security Group that allows:
    • inbound TCP/22 from your admin IP only
    • no other inbound rules unless documented
  3. Use private Security Groups on internal workloads so only the bastion can reach them.
  4. Enable CloudTrail, VPC Flow Logs, and instance logs.
  5. Apply the shared SSH hardening baseline.

AWS quick checks


8. DigitalOcean Walkthrough

DigitalOcean usually means you will run a real bastion host, so be stricter with boundaries.

  1. Create a Droplet with a minimal Ubuntu image.
  2. Inject your SSH public key at creation time.
  3. Put the Droplet behind a Cloud Firewall:
    • inbound TCP/22 from your admin IP or VPN only
    • deny all other inbound by default
  4. Use VPC networking for private traffic to internal systems.
  5. Apply SSH hardening, Fail2ban, and automatic updates.
  6. If possible, place admin access behind WireGuard or Tailscale and remove broad public exposure.

DigitalOcean quick checks


9. Reverse Proxy Guidance

Only use a reverse proxy if you need controlled application-layer access, not just SSH administration.

Safe baseline:

If you do not need HTTP(S) application access, do not add a reverse proxy just because it seems flexible.


10. Operator Notes


11. Quick Build Checklist