Securing your VPS for the semi-paranoidPublished 2014-12-29
Watch on YouTube: youtu.be/YZzhIIJmlE0
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
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':
ssh-keygen > 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/waffles.pub. > The key fingerprint is: > ff:9c:38:58:63:cc:f6:d4:fd:94:3e:68:7a:75:74:e0 email@example.com > 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
# 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 exit
# local laptop brew install ssh-copy-id # needed on OS X ssh-copy-id -i ~/.ssh/waffles "firstname.lastname@example.org -p 22" # this will prompt for the password ssh email@example.com -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 exit
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 22.214.171.124 > Port 4242 > User strongbad > IdentityFile ~/.ssh/waffles ssh 126.96.36.199
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 # IMPORTANT # DANGER # WARNING # Only change ('y') the lines related no ICMP, not any of the others!!! ('n' for next). :%s/ACCEPT/DROP/gc
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
Did I make your day?
Buy me a coffee