Watch on YouTube:


The 15-Minute Guide to Secure VPS Access (for the Paranoid)

Securing your VPS for the semi-paranoid

(this article is only half-baked at this point, the screencast is more complete)

  • The VPS provider should be secured with two-factor authentication
  • The server should run in an undisclosed region on an undisclosed service provider
  • The server should have key-only, passphrase-protected, non-root ssh access (with a separate sudo password)
  • The server's IP address sholud only be discoverable by first compromising another server with similar security in place (the most sensitive information - such as credit-card orders - should only be processed on the most secure server and the results be passed back).

Disallow SSH Keyring Caching

Most of the time you create an ssh key you don't bother adding a passphrase. But for an application like this, it's important that you have a specific key that uses a passphrase.

By default, most operating systems will only ask you to enter in your SSH passphrase once and then cache it securely in memory.

If someone gets physical access to your machine, however, they can just open up a terminal and log into any server that requires that passphrase without typing it in (if you've accessed that machine since the last time the cache was cleared), so we'll want to turn that off.

On OS X this is fairly straight forward:

# OS X
launchctl unload -w /System/Library/LaunchAgents/org.openbsd.ssh-agent.plist

On Ubuntu Desktops, surprisingly, you have to go into some GUI settings and or edit a few config files

Create secure SSH key

For a project where security is this important I think it's not only important that the ssh key be passphrase projected and key caching should be disabled, but also that the key should be its own distinct key (otherwise I would get lazy and turn caching back on).

In this case, I'll create a key and call it 'waffles':

> Enter file in which to save the key (/Users/homestar/.ssh/id_rsa): /Users/homestar/.ssh/waffles
> Enter passphrase (empty for no passphrase):
> Enter same passphrase again:
> Your identification has been saved in /Users/homestar/.ssh/waffles.
> Your public key has been saved in /Users/homestar/.ssh/
> The key fingerprint is:
> ff:9c:38:58:63:cc:f6:d4:fd:94:3e:68:7a:75:74:e0 homestar@lappy486.local
> The key's randomart image is:
> +--[ RSA 2048]----+
> |                 |
> |              .  |
> |             . . |
> |              E o|
> |        So   . oo|
> |         .B . .o+|
> |         =.+  +.o|
> |        . .+.= o.|
> |          .oB   .|
> +-----------------+

It's important that the passphrase should be long. You could use something like "Remember to take the trash out this Tuesday!"

If you don't want to forget it you could write it down and stick it in your wallet with your grocery list or use a catchphrase from a favorite book or TV show or something else creative that hides in plain sight.

What you don't want to do is ever put it in a file on your computer or write it on a sticky note on your monitor.

Secure the Server

After creating the server, update it and install fail2ban.

# on the remote server

sudo apt-get update
sudo apt-get install -y fail2ban

Next create a user, add the secure key, then remove remove root and password access.

# remote server

adduser strongbad
adduser strongbad sudo # or wheel if sudo doesn't exist
# local laptop
brew install ssh-copy-id                            # needed on OS X
ssh-copy-id -i ~/.ssh/waffles "strongbad@ -p 22" # this will prompt for the password

ssh strongbad@ -i ~/.ssh/waffles -p 22
> Enter passphrase for key '/Users/homestar/.ssh/waffles':
# remote server
sudo vim /etc/ssh/sshd_config
> Port 4242
> PermitRootLogin no
> PasswordAuthentication no
sudo service ssh restart
sudo apt-get update
sudo apt-get upgrade -y

You could also change Port to 4242 or something creative.

Okay, now the server is reasonably secure from the outside world. Now test that you can still log in and that no extraneous services are running.

# Local Laptop
vim ~/.ssh/config
> Host
> Port 4242
> User strongbad
> IdentityFile ~/.ssh/waffles


I don't find basic firewalls to be very practical for servers for the average Joe.

If you don't want a remote system to have access to a local service, don't expose the service. Simple. Done.

If you aren't a firewall guru then you'll probably do it wrong anyway.

# change the icmp (ping) rules

vim /etc/ufw/before.rules
# Only change ('y') the lines related no ICMP, not any of the others!!! ('n' for next).

So check to make sure that the only listening service running at this point is ssh:

# Remote Server
sudo netstat -peanut # an easy way to remember those 6 params

You should only see a few sshd instances listening on port 22 or 4242 or whatever. If you see anything else, you should probably use a different OS or VPS service that isn't setup by default with crap that you don't understand running on public ports.

Note: If you see a few port 80 connections in "Foreign Address" it's just hanging outbound connections from 'sudo apt-get update' downloading updates. Wait a minute and check again and you should see that it's empty.

Don't run WordPress or PHP

Don't run any additional services other than what you need. Especially, don't run WordPress or anything PHP-related. WordPress is the Internet Explorer of Servers. It just attracts malware and rootkits (because it's super popular and all of its 0-day exploits for every version ever released are included in any basic hacker tool, so it's super hard to know you have a secure version).

P.S. Remember that when you're making a screencast that a discerning user can tell whether you're using Qwerty or Dvorak just by the rhythm of the keys and a discerning computer can tell what your passwords are (by the sounds of each key).

By AJ ONeal

If you loved this and want more like it, sign up!

Did I make your day?
Buy me a coffeeBuy me a coffee  

(you can learn about the bigger picture I'm working towards on my patreon page )