You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
372 lines
12 KiB
372 lines
12 KiB
---
|
|
title: "Bastion Host On DigitalOcean"
|
|
date: 2021-09-14T21:17:12+06:00
|
|
image: "images/blog/blog-post-4.jpg"
|
|
author: "Edwin Lyon"
|
|
categories: ["cybersecurity","cloud"]
|
|
tags: ["ubuntu","harden","security","linux","digital ocean","bastion-host","cloud"]
|
|
description : "Hardening Your Ubuntu 20.0.4 LTS Cloud Server With A Bastion Host"
|
|
draft: false
|
|
type: "post"
|
|
---
|
|
|
|
## **What is a Bastion Host?**
|
|
|
|
A bastion host is a special-purpose computer on a network specifically designed and configured to withstand attacks. There are two common network configurations that include bastion hosts and their placement.
|
|
|
|
The first requires two firewalls, with bastion hosts sitting between the first "outside world" firewall, and an inside firewall, in a DMZ. Often, smaller networks do not have multiple firewalls, so if only one firewall exists in a network, bastion hosts are commonly placed outside the firewall.
|
|
|
|
### **Getting Started**
|
|
|
|
You can use the referral badge below to get started with a $100 credit from Digital Ocean or use this link to [DigitalOcean](https://m.do.co/c/42cf2120197b).
|
|
|
|
[](https://www.digitalocean.com/?refcode=42cf2120197b&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=badge)
|
|
|
|
### **DigitalOcean VPC**
|
|
|
|
On 7 April, 2020, the VPC service replaced the Private Networking service on DigitalOcean.
|
|
|
|
> A Virtual Private Cloud (VPC) is a private network interface for collections of DigitalOcean resources. VPC networks provide a more secure connection between resources because the network is inaccessible from the public internet and other VPC networks. Traffic within a VPC network doesn’t count against bandwidth usage.
|
|
|
|
VPC are available at no additional cost and are enabled by default. They serve the same function as VLANs do. You have two options, you can either manual create a VPC network or if you don't have a VPC network DigitalOcean will create it for you when you build a new VPS.
|
|
|
|
### **DigitalOcean Cloud Firewalls**
|
|
|
|
> Cloud Firewalls affect both public and VPC network traffic. Rules specific to either must specify the public or private IP range.
|
|
|
|
We will be creating two cloud firewall rules, one named public-network and the other named private-network. These will be used as Access Control Lists to help protect our VPC network.
|
|
|
|
Both the Public-Network and Private-Network cloud firewalls should be added to the bastion-host, while only the Private-Network cloud firewall should be added to all other members of your VPS.
|
|
|
|
**PUBLIC-NETWORK**
|
|
|
|
* INBOUND RULES :
|
|
|
|
**Type** | **Protocol** | **Port Range** | **Sources**
|
|
:--- | :--- | :--- | :---
|
|
ICMP | ICMP | None | All IPv4, All IPv6
|
|
SSH | TCP | 22 | All IPv4, All IPv6
|
|
HTTP | TCP | 80 | All IPv4, All IPv6
|
|
HTTPS | TCP | 443 | All IPv4, All IPv6
|
|
CUSTOM | UDP | 51820 | All IPv4, All IPv6
|
|
|
|
* OUTBOUND RULES :
|
|
|
|
**Type** | **Protocol** | **Port Range** | **Sources**
|
|
:--- | :--- | :--- | :---
|
|
ICMP | ICMP | None | All IPv4, All IPv6
|
|
All TCP | TCP | All Ports | All IPv4, All IPv6
|
|
All UDP | UDP | All Ports | All IPv4, All IPv6
|
|
|
|
**PRIVATE-NETWORK**
|
|
|
|
* INBOUND RULES :
|
|
|
|
**Type** | **Protocol** | **Port Range** | **Sources**
|
|
:--- | :--- | :--- | :---
|
|
ICMP | ICMP | None | 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16
|
|
All TCP | TCP | All Ports | 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16
|
|
All UDP | UDP | All Ports | 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16
|
|
|
|
* OUTBOUND RULES :
|
|
|
|
**Type** | **Protocol** | **Port Range** | **Sources**
|
|
:--- | :--- | :--- | :---
|
|
ICMP | ICMP | None | All IPv4
|
|
All TCP | TCP | All Ports | All IPv4
|
|
All UDP | UDP | All Ports | All IPv4
|
|
|
|
I also recommend creating new ssh keys to add to your bastion-host.
|
|
|
|
```bash
|
|
ssh-keygen -b 4096 -a 1000 -t rsa -f ~/.ssh/id_rsa
|
|
```
|
|
|
|
Let's lock down your ssh service.
|
|
|
|
```bash
|
|
$ sudo mv /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
|
|
|
|
# Harden SSH Settings
|
|
$ sudo cat <<-EOF > /etc/ssh/sshd_config
|
|
HostKey /etc/ssh/ssh_host_ed25519_key
|
|
HostKey /etc/ssh/ssh_host_rsa_key
|
|
HostKey /etc/ssh/ssh_host_ecdsa_key
|
|
AcceptEnv LANG LC_*
|
|
AllowGroups root sudo
|
|
Banner /etc/issue.net
|
|
ChallengeResponseAuthentication no
|
|
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes256-ctr
|
|
ClientAliveCountMax 0
|
|
ClientAliveInterval 300
|
|
Compression no
|
|
HostbasedAuthentication no
|
|
IgnoreUserKnownHosts yes
|
|
KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256
|
|
LoginGraceTime 20
|
|
LogLevel VERBOSE
|
|
Macs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512,hmac-sha2-256
|
|
MaxAuthTries 3
|
|
MaxSessions 3
|
|
MaxStartups 10:30:60
|
|
PermitEmptyPasswords no
|
|
PermitRootLogin no
|
|
PubkeyAuthentication yes
|
|
PasswordAuthentication no
|
|
PermitUserEnvironment no
|
|
PrintLastLog yes
|
|
PrintMotd no
|
|
StrictModes yes
|
|
Subsystem sftp internal-sftp
|
|
UseDNS no
|
|
UsePAM yes
|
|
X11Forwarding no
|
|
AllowTcpForwarding yes
|
|
EOF
|
|
```
|
|
|
|
Create a new set of ssh host keys.
|
|
|
|
```bash
|
|
## Update ssh_host keys
|
|
rm /etc/ssh/ssh_host_*
|
|
ssh-keygen -t ecdsa -b 521 -f /etc/ssh/ssh_host_ecdsa_key -N ""
|
|
ssh-keygen -t rsa -b 4096 -f /etc/ssh/ssh_host_rsa_key -N ""
|
|
ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N ""
|
|
|
|
awk '$5 >= 3071' /etc/ssh/moduli > /etc/ssh/moduli.safe
|
|
mv /etc/ssh/moduli.safe /etc/ssh/moduli
|
|
```
|
|
|
|
We need to edit the netplan for both the bastion-host and the webproxy so that the bastion-host handles all routing.
|
|
|
|
```bash
|
|
sudo nano /etc/netplan/50-cloud-init.yaml
|
|
```
|
|
|
|
You can read more details on editing your netplan on DigitalOcean.
|
|
|
|
```nano
|
|
network:
|
|
version: 2
|
|
ethernets:
|
|
eth0:
|
|
addresses:
|
|
- xxx.xxx.xxx.xxx/20
|
|
- 26xx:xxxx:x:xxx::xx:xxxx/64
|
|
gateway4: xxx.xxx.xxx.1
|
|
gateway6: 26xx:xxxx:x:xxx::1
|
|
match:
|
|
macaddress: ab:ab:ab:ab:ab:ab
|
|
nameservers:
|
|
addresses:
|
|
- 1.1.1.1
|
|
- 1.0.0.1
|
|
- 2606:4700:4700::1111
|
|
- 2606:4700:4700::1001
|
|
search: [technerdonline.com]
|
|
eth1:
|
|
addresses:
|
|
- 10.128.0.2/20
|
|
match:
|
|
macaddress: ba:ba:ba:ba:ba:ba
|
|
nameservers:
|
|
addresses:
|
|
- 10.128.0.2
|
|
search: [local]
|
|
routes:
|
|
- to: 10.128.0.0/20
|
|
via: 10.128.0.2
|
|
```
|
|
|
|
On the proxy server make the following netplan change.
|
|
|
|
```nano
|
|
network:
|
|
version: 2
|
|
ethernets:
|
|
eth0:
|
|
addresses:
|
|
- xxx.xxx.xxx.xxx/20
|
|
- 26xx:xxxx:x:xxx::xx:xxxx/64
|
|
#gateway4: xxx.xxx.xxx.1
|
|
#gateway6: 26xx:xxxx:x:xxx::1
|
|
match:
|
|
macaddress: ab:ab:ab:ab:ab:ab
|
|
nameservers:
|
|
addresses:
|
|
- 1.1.1.1
|
|
- 1.0.0.1
|
|
- 2606:4700:4700::1111
|
|
- 2606:4700:4700::1001
|
|
search: [technerdonline.com]
|
|
eth1:
|
|
addresses:
|
|
- 10.128.0.3/20
|
|
match:
|
|
macaddress: ba:ba:ba:ba:ba:ba
|
|
nameservers:
|
|
addresses:
|
|
- 10.128.0.2
|
|
search: [local]
|
|
routes:
|
|
- to: 0.0.0.0/0
|
|
via: 10.128.0.2
|
|
```
|
|
|
|
Apply the netplan changes.
|
|
|
|
```bash
|
|
sudo netplan apply
|
|
```
|
|
|
|
We will need to create a set of IPTABLES rules for both IPv4 and IPv6 but first we need to load some Kernel modules.
|
|
|
|
|
|
```bash
|
|
sudo nano /etc/modules-load.d/iptables.conf
|
|
```
|
|
```nano
|
|
overlay
|
|
br_netfilter
|
|
ip_vs
|
|
ip_vs_rr
|
|
ip_vs_wrr
|
|
ip_vs_sh
|
|
nf_conntrack
|
|
iptable_nat
|
|
iptable_filter
|
|
iptable_mangle
|
|
ip_nf_target_redirect
|
|
ip_set
|
|
ip_vs_nfct
|
|
ip_vs_proto_tcp
|
|
ip_vs_proto_udp
|
|
veth
|
|
bridge
|
|
bridge_netfilter
|
|
ip_nf_filter
|
|
ip_nf_target_masquerade
|
|
netfilter_xt_match_addrtype
|
|
netfilter_xt_match_conntrack
|
|
netfilter_xt_match_ipvs
|
|
nf_nat
|
|
```
|
|
|
|
Copy and paste the following content, replacing PUBLIC_IP with the public IP address of the bastion-host, WEBPROXY_PRIVATE_IP with the VPC IP address for the webproxy, and BASTION_PRIVATE_IP with the VPC IP address with the bastion host private IP.
|
|
|
|
```bash
|
|
nano ipv4.conf
|
|
```
|
|
|
|
```nano
|
|
*mangle
|
|
:PREROUTING ACCEPT [0:0]
|
|
:INPUT ACCEPT [0:0]
|
|
:FORWARD ACCEPT [0:0]
|
|
:OUTPUT ACCEPT [0:0]
|
|
:POSTROUTING ACCEPT [0:0]
|
|
COMMIT
|
|
|
|
*nat
|
|
:PREROUTING ACCEPT [0:0]
|
|
:INPUT ACCEPT [0:0]
|
|
:OUTPUT ACCEPT [0:0]
|
|
:POSTROUTING ACCEPT [0:0]
|
|
-A PREROUTING -i eth0 -d {PUBLIC_IP} -p tcp -m tcp --dport 80 -j DNAT --to-destination {WEBPROXY_PRIVATE_IP}:80
|
|
-A PREROUTING -i eth0 -d {PUBLIC_IP} -p tcp -m tcp --dport 443 -j DNAT --to-destination {WEBPROXY_PRIVATE_IP}:443
|
|
-A POSTROUTING -d {WEBPROXY_PRIVATE_IP} -o eth1 -p tcp -m tcp --dport 80 -j SNAT --to-source {BASTION_PRIVATE_IP}
|
|
-A POSTROUTING -d {WEBPROXY_PRIVATE_IP} -o eth1 -p tcp -m tcp --dport 443 -j SNAT --to-source {BASTION_PRIVATE_IP}
|
|
-A POSTROUTING -s {BASTION_PRIVATE_IP} -o eth0 -j SNAT --to-source {PUBLIC_IP}
|
|
-A POSTROUTING -s {PRIVATE_SUBNET} ! -d {PRIVATE_SUBNET} -j MASQUERADE
|
|
COMMIT
|
|
|
|
*filter
|
|
:INPUT DROP [0:0]
|
|
:FORWARD DROP [0:0]
|
|
:OUTPUT ACCEPT [0:0]
|
|
:FILTERS - [0:0]
|
|
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
|
|
-A INPUT -i lo -j ACCEPT
|
|
-A INPUT -m conntrack --ctstate INVALID -j DROP
|
|
-A INPUT -p icmp -m icmp --icmp-type 8 -m limit --limit 5/sec -j ACCEPT
|
|
-A INPUT -i eth1 -m conntrack --ctstate NEW -s {PRIVATE_SUBNET} -j ACCEPT
|
|
-A INPUT -j FILTERS
|
|
-A INPUT -j DROP
|
|
-A FORWARD -o eth1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
|
|
-A FORWARD -i eth1 -o eth1 -m conntrack --ctstate NEW -s {PRIVATE_SUBNET} -j ACCEPT
|
|
-A FORWARD -o eth0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
|
|
-A FORWARD -i eth1 -o eth0 -m conntrack --ctstate NEW -s {PRIVATE_SUBNET} -j ACCEPT
|
|
-A FORWARD -i eth0 -o eth1 -j FILTERS
|
|
-A OUTPUT -o lo -j ACCEPT
|
|
-A OUTPUT -o eth0 -j ACCEPT
|
|
-A OUTPUT -o eth1 -j ACCEPT
|
|
-A FILTERS -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
|
|
-A FILTERS -p tcp -m conntrack --ctstate NEW -m tcp --syn --dport 22 -j ACCEPT
|
|
-A FILTERS -p tcp -m conntrack --ctstate NEW -m tcp --syn --dport 80 -j ACCEPT
|
|
-A FILTERS -p tcp -m conntrack --ctstate NEW -m tcp --syn --dport 443 -j ACCEPT
|
|
-A FILTERS -p udp -m conntrack --ctstate NEW -m udp --dport 51820 -j ACCEPT
|
|
-A FILTERS -p udp -m conntrack --ctstate NEW -m udp --dport 51821 -j ACCEPT
|
|
-A FILTERS -m conntrack --ctstate INVALID -j DROP
|
|
-A FILTERS -j REJECT
|
|
COMMIT
|
|
```
|
|
|
|
Now create IPTABLES Rules for IPv6.
|
|
|
|
```bash
|
|
nano ipv6.conf
|
|
```
|
|
|
|
```nano
|
|
*nat
|
|
:PREROUTING ACCEPT [0:0]
|
|
:INPUT ACCEPT [0:0]
|
|
:OUTPUT ACCEPT [0:0]
|
|
:POSTROUTING ACCEPT [0:0]
|
|
COMMIT
|
|
|
|
*filter
|
|
:INPUT DROP [0:0]
|
|
:FORWARD DROP [0:0]
|
|
:OUTPUT ACCEPT [0:0]
|
|
:FILTERS - [0:0]
|
|
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
|
|
-A INPUT -i lo -j ACCEPT
|
|
-A INPUT -m conntrack --ctstate INVALID -j DROP
|
|
-A INPUT -i eth0 -p ipv6-icmp -m icmp6 --icmpv6-type 128 -m limit --limit 5/sec -j ACCEPT
|
|
-A INPUT -i eth0 -p ipv6-icmp -m icmp6 --icmpv6-type 133 -m limit --limit 5/sec -j ACCEPT
|
|
-A INPUT -i eth0 -p ipv6-icmp -m icmp6 --icmpv6-type 134 -m limit --limit 5/sec -j ACCEPT
|
|
-A INPUT -i eth0 -p ipv6-icmp -m icmp6 --icmpv6-type 135 -m limit --limit 5/sec -j ACCEPT
|
|
-A INPUT -j FILTERS
|
|
-A INPUT -j DROP
|
|
-A FILTERS -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
|
|
-A FILTERS -p tcp -m conntrack --ctstate NEW -m tcp --dport 80 --tcp-flags FIN,SYN,RST,ACK SYN -j ACCEPT
|
|
-A FILTERS -p tcp -m conntrack --ctstate NEW -m tcp --dport 443 --tcp-flags FIN,SYN,RST,ACK SYN -j ACCEPT
|
|
-A FILTERS -m conntrack --ctstate INVALID -j DROP
|
|
-A FILTERS -j REJECT
|
|
-A OUTPUT -o lo -j ACCEPT
|
|
-A OUTPUT -o eth0 -j ACCEPT
|
|
-A OUTPUT -o eth1 -j ACCEPT
|
|
-A FORWARD -o eth1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
|
|
-A FORWARD -i eth1 -o eth1 -j FILTERS
|
|
-A FORWARD -o eth0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
|
|
-A FORWARD -i eth1 -o eth0 -m conntrack --ctstate NEW -j ACCEPT
|
|
-A FORWARD -i eth0 -o eth1 -j FILTERS
|
|
-A FORWARD -j REJECT
|
|
COMMIT
|
|
```
|
|
|
|
Apply the iptables rules and install iptables-persistent.
|
|
|
|
```bash
|
|
sudo iptables-restore -n ipv4.conf
|
|
sudo ip6tables-restore -n ipv6.conf
|
|
|
|
sudo iptables-save
|
|
sudo ip6tables-save
|
|
|
|
sudo apt install iptables-persistent
|
|
```
|
|
|
|
Simply install your favorite web server on the proxy droplet (i.e. nginx, caddy, haproxy etc). I would also suggest installing wireguard on the bastion host, it is also pretty easy to get a secure wireguard mesh network setup if you have multiple VPC.
|
|
|