Cloudflare's Railgun - VPS Setup

Requirements

The first step to any deployment is to find out the requirements. As this deployment will focus around Cloudflare’s Railgun, it is wise to work with that as a base. Railgun’s requirements can be found here, but it can be boiled down to the following:

  • Dual core processor
  • 4GB RAM
  • 64-bit Architecture
  • Memcache >= 1.4 with at least 512MB of storage (>1GB recommended)

One of the following operating systems:

  • Debian 7, 8
  • Ubuntu Linux 12.04, 14.04, 15.10
  • FreeBSD 10 & 11
  • Red Hat Enterprise Linux 6, 7
  • CentOS 6, 7

You will also want port 2408 open to traffic from Cloudflare’s IPs.

Also, one of the requirements is that no content is served via IPv4. You will want to make sure you have a way to use IPv6.

Place website on Cloudflare

The process of migrating a domain to Cloudflare is a very simple process. I am using Route 53 for my DNS provider. Use the “+ Add Site” option on Cloudflare and follow the guided instructions.

As a note, if you have the IP of the system you want to point to, I would recommend pointing an AAAA DNS record like ssh.domain.com that is not routed through Cloudflare to help make it easier to connect to the origin.

Also make sure to use AAAA records for IPv6 addresses.

Scope

I beleive that harding a system should be one of the first steps to get it production ready. My goal is to go over the basic steps to harden a system and provide an easy to follow list of actions. The system hardening is by no means exhaustive, but it should be a good starting point.

  • Basic configurations in order to make sure that it has the latest patches.
  • Harden SSH so that root will not be able to log in directly and SSH keys are required.
  • Enable and install Fail2Ban.
  • Set firewalld to disable any ports (and traffic) I will not be using.
[root@thebrodeo ~]# yum update
[root@thebrodeo ~]# useradd colinm
[root@thebrodeo ~]# passwd colinm
Changing password for user colinm.
New password: 
Retype new password: 
passwd: all authentication tokens updated successfully.
[root@thebrodeo ~]# passwd root
Changing password for user root.
New password: 
Retype new password: 
passwd: all authentication tokens updated successfully.
[root@thebrodeo ~]# passwd colinm
Changing password for user colinm.
New password: 
Retype new password: 
passwd: all authentication tokens updated successfully.
[root@thebrodeo ~]# usermod -a -G wheel colinm

Now that user colinm is created and I have added them to the “wheel” group (which has root privilages), I test to ensure I can run elevated commands. I login as the user with su colinm and type the password I provided. At this point, I try to run a command like sudo vi and find that I am able to execute commands as root.

SSH

At this point, I place my public key I want to use in ~/.ssh/authorized_keys. I want to make sure it is owned by colinm:colinm, and that the directoy .ssh has permissions 700 and that the file authorized_keys has permissions 600. To test, I try to SSH in as the new user by running ssh colinm@ssh.thebrodeo.com on my client machine.

Now, I will disable root login for SSH. On the machine, I run sudo vi /etc/ssh/sshd_config and set PermitRootLogin no. After that, I will restart the SSH service with sudo systemctl restart sshd.

Fail2Ban

For Fail2Ban (and NGINX), I enable the epel repository. I do this by sudo yum install epel-release. I then run sudo yum update to update the cache. After the update, I run sudo yum install fail2ban fail2ban-systemd to install the program and the systemd service. I copy the default jail configuration by running sudo cp -pf /etc/fail2ban/jail.conf /etc/fail2ban/jail.local and then alter the desired jail with sudo vi /etc/fail2ban/jail.local I have created a basic jail which looks like this.

[sshd]
enabled = true
port = ssh
bantime = 3600
logpath = %(sshd_log)s
maxretry = 5

Installing NGINX

First, I will install NGINX and enable it during boot.

yum install nginx
sudo systemctl start nginx
sudo systemctl enable nginx

I will be editing the NGINX config during the SSL part of the install.

You can also check what ports NGINX are running on with the following command: netstat -nlp | grep nginx

Enabling Services

I run the following commands to enable the serivces iptables and Fail2Ban on boot.

sudo systemctl stop firewalld
sudo systemctl mask firewalld
sudo yum install iptables-services
sudo systemctl senable ip6tables
sudo systemctl start ip6tables
sudo systemctl enable iptables
sudo systemctl start iptables
sudo systemctl enable fail2ban
sudo systemctl start fail2ban 
sudo yum -y install yum-cron
sudo systemctl enable yum-cron.service

We will start to disable IPv4 traffic at this point. It is wise to make sure that you have a way to reach IPv6 traffic over the internet. As I don’t have a IPv6 addresses assigned to me, I have decided to keep it simple and spin up another VPS that has an address and use that as a jump box. This will eliminate some of the complexity of trying to configure a IPv6 transition mechanism.

sudo iptables -P INPUT DROP
sudo iptables -P FORWARD DROP
sudo iptables -P OUTPUT DROP

sudo /sbin/service iptables save to save your tables.

I also limited IPv6 traffic with the following IP rules. Obviously, this is not one size fits all.

sudo ip6tables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
sudo ip6tables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
sudo ip6tables -A INPUT -p ipv6-icmp -j ACCEPT
sudo ip6tables -A INPUT -i lo -j ACCEPT
sudo ip6tables -A INPUT -m state --state NEW -m udp -p udp --dport 546 -d fe80::/64 -j ACCEPT
sudo ip6tables -A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
sudo ip6tables -A INPUT -m state --state NEW -m tcp -p tcp --dport 443 -j ACCEPT
sudo ip6tables -A INPUT -p tcp -s 2400:cb00::/32 --dport 2408 -j ACCEPT
sudo ip6tables -A INPUT -p tcp -s 2405:8100::/32 --dport 2408 -j ACCEPT
sudo ip6tables -A INPUT -p tcp -s 2405:b500::/32 --dport 2408 -j ACCEPT
sudo ip6tables -A INPUT -p tcp -s 2606:4700::/32 --dport 2408 -j ACCEPT
sudo ip6tables -A INPUT -p tcp -s 2803:f800::/32 --dport 2408 -j ACCEPT
sudo ip6tables -A INPUT -p tcp -s 2c0f:f248::/32 --dport 2408 -j ACCEPT
sudo ip6tables -A INPUT -p tcp -s 2a06:98c0::/29 --dport 2408 -j ACCEPT
sudo ip6tables -A INPUT -j REJECT --reject-with icmp6-port-unreachable
sudo ip6tables -A FORWARD -j REJECT --reject-with icmp6-port-unreachable

Login as root and run ip6tables-save > /etc/sysconfig/ip6tables to make the rules persistent through boot.

Colin Murray avatar
About Colin Murray
I am a solutions engineer at Cloudflare. All opinions are my own.
comments powered by Disqus