Locking Down Access to Your VPS

There are a number of ways you can restrict access to your VPS. Passwords (specifically, good passwords) is the most basic method. Restricting access to ssh keys only is better. You can use Google Authenticator to require a short-lived number as a second factor of authentication. You could also setup a VPN so that only connections from that network are allowed.
One alternative method I’ve sometimes used is to allow connections only from a specific IP or set of IPs. There are a couple different ways to achieve this.
Restricting in sshd_config
In the sshd_config file, you can add rules to match users and match addresses. Consider the following directives
PermitRootLogin no
PermitEmptyPasswords no
PasswordAuthentication no
PubkeyAuthentication no
Match Address 1.2.3.4/32
PermitRootLogin prohibit-password
PubkeyAuthentication yes
The first four lines turn off all forms of authentication and restrict root logins. Then from the IP address 1.2.3.4, we permit root login (by SSH key only) and allow sshd key authentication for other users. This combination of “default deny, then permit from a specific IP” effectively limits connections from one IP.
sshd_config supports a number of “Match” rules, including “Match User” and “Match Host”. Most of the major configuration options can be overridden using Match directives. Consult the sshd_config man page for full details.
Restricting via Firewall
If you are connecting to things besides ssh, you can restrict the entire box’s access to an IP via a firewall. One wrinkle is if you want to limit access to your home IP, but you have a DHCP’d IP from your ISP.
One way around this is to sign up with a Dynamic DNS provider. For example, you can sign up with afraid.org and they will grant you (for free) a DNS name in one of their domains you pick. So if you pick example.com (not a real afraid.org domain, just an example), you then choose what subdomain you have. In this tutorial, we’ll assume I’ve chosen lowend.example.com.
If your router (Netgear, etc.) has a Dynamic DNS client for afraid.org, just configure it in the router’s panel and you’re done. If not, you can use this little script to update afraid.org:
#!/bin/bash
#FreeDNS updater script

UPDATEURL="http://freedns.afraid.org/dynamic/update.php?YOUR-AFRAID-ORG-KEY-HERE"
DOMAIN="lowend.example.com"

registered=$(nslookup $DOMAIN|tail -n2|grep A|sed s/[^0-9.]//g)
current=$(wget -q -O - http://checkip.dyndns.org|sed s/[^0-9.]//g)
if [ "$current" != "$registered" ] ; then
wget -q -O /dev/null $UPDATEURL
MSG="FYI, DNS updated for ${DOMAIN}, now $current"
echo "${MSG}" | mailx -s "${MSG}" someone@example.com
fi
Put that in any user’s crontab on a home Linux box to run (perhaps every 12 hours, or more frequently if you need constant access). Every time it runs, it checks what the IP address is at afraid.org, then checks what the Internet IP is for your home. If they’re different, it updates afraid.org.
Now, on the server you want to lock down, all you need is a script to query afraid.org and update your iptables rules. Here is an example:
#!/bin/bash

# fix the PATH since we run from cron
PATH=/usr/bin:/sbin:/bin:usr/sbin:/usr/local/bin
export PATH

# CONFIG

ssh_port=5555
dns="lowend.example.com"
LOG="/root/iptables_update.log"

# MAIN

nslookup $dns > /tmp/nslookup.out 2>&1
home_ip=$(grep Address: /tmp/nslookup.out | tail -1 | awk -F: '{ print $2 }' | sed 's/ //')

echo "----------------------------------------------------------" > ${LOG}
echo "`date` updating iptables using home IP ${home_ip}" >> ${LOG}

# make sure we can stay connected
iptables -P INPUT ACCEPT >> $LOG 2>&1

# flush existing rules
iptables -F >> $LOG 2>&1

# anything on loopback is OK
iptables -A INPUT -i lo -j ACCEPT >> $LOG 2>&1

# anything for established/related connections is OK
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT >> $LOG 2>&1

# open SSH
iptables -A INPUT -s ${home_ip} -p tcp --dport ${ssh_port} -j ACCEPT >> $LOG 2>&1

# open web
iptables -A INPUT -s ${home_ip} -p tcp --dport 80 -j ACCEPT >> $LOG 2>&1
iptables -A INPUT -s ${home_ip} -p tcp --dport 443 -j ACCEPT >> $LOG 2>&1

# otherwise drop
iptables -P INPUT DROP >> $LOG 2>&1

# drop all forwards - we're not a router
iptables -P FORWARD DROP >> $LOG 2>&1

# anything outgoing is OK
iptables -P OUTPUT ACCEPT >> $LOG 2>&1

# list at end
iptables -L -v >> $LOG 2>&1
What this script does is:


looks the current address of your afraid.org dynamic DNS
flushes all iptables rules
allows everything on loopback, and anything established
opens ssh, and web (ports 80 and 443) to the dynamic DNS IP only
drops everything else and disable routing
logs all actions to /root/iptables_update.log.

If you put this in cron to run at the same time as your dynamic dns updater script (perhaps offset by a couple minutes), your server will always have your home IP address in its iptables rules.
Of course, if you don’t use dynamic DNS, you can just hardwire an IP for the home_ip variable.
As a bit of bonus advice, whenever I’m developing an iptables ruleset, I usually create a script like this called “flush_iptables.sh” and have it called out of cron every couple minutes.
#!/bin/bash

PATH=/usr/bin:/sbin:/bin:usr/sbin:/usr/local/bin
export PATH

iptables -P INPUT ACCEPT
iptables -F
echo "warning! firewall disabled on $(hostname)" |mailx -s "firewall disabled on $(hostname)!" someone@example.com
Update your email address, and make sure you have mailx installed (it’s in the mailutils package on Debian).
This way, if I screw something and am locked out, the lockout will reverse itself after a couple minutes and I don’t have to go through the hassle of finding the provider’s console. It also emails me (every couple minutes) to warn me that it’s in place so I don’t forget to disable it once my rules are set.
The post Locking Down Access to Your VPS appeared first on LowEndBox .

Top News