Securing Your Server the Sexy Way Using Snort, Snorby, IP Tables and Artillery
Ok, so a lot of the time you see servers running nothing but their OS. No logs are checked, no IDS is running, no iptables have been configures and no additional check/monitoring is performed.
In this post I’ll describe in a decent but short and hopefully clear way how you can secure your server using a couple of tools. I’ll be describing three way’s that will make a significant difference in the security of your server.
When securing a server the following things are important: 1. Block unwanted traffic 2. Take care of hosts that generate the unwanted traffic 3. Monitor for malicious traffic 4. Make sure your security services are running
Well to be fair this list probably is missing some points but right now I’m to lazy to write more about this subject than I’m already doing in this post….
With these 4 points you are taking care of most of the security issues you’re server has to deal with every single day. The tools I chose for this are Snort (IDS 126.96.36.199), IPTables (Firewall) , Artillery (Server hardening tool (0.4 alpha)).
Snort is a tool that does package analysis. It uses a set of rules to determine if a packet (or serie of) is malicious. IPtables come most of the time with the default installation of most *UNIX systems and functions as a firewall. It uses a chain containing rules that define what traffic is allowed (ACCEPT) or disallowed (DROP or REJECT). Artillery is a fairly new tool developed by David Kennedy (ReL1K) and uses a couple of techniques to determine if your server is running a save configurations. But, and this is in my opinion the fun feature: it runs a couple of “honeypot” ports. This means that Artillery sets up a socket listener on a couple of ports. The minute someone connects to this port Artillery sends a random data string to the user and adds a rule to your iptables to DROP all traffic from this host. This is a great way to block suspicious IP addresses.
Now that we know what tools we are going to use, here is how you do it:
To install snort just find the installation doc on the snort website. These docs are perfectly fine so I’m not going to write a lot about installing snort. – http://snort.org/docs
Now that snort is running you’ll need to install a decent interface that will give you a report on what alerts have been triggered by snort. A very nice project that is under active development is Snorby (http://snorby.org/). Snorby is an easy to use interface for snort. The installation of snorby is a bit tricky if you have no experience with ruby (like me). When installing Snorby make sure you download and compile all the dependencies (don’t use your repositories, I think Snorby uses some newer libs). Here is a snort description of what I did:
#Installing the needed dependencies sudo apt-get install gcc g++ build-essential libssl-dev libreadline5-dev zlib1g-dev linux-headers-generic libsqlite3-dev libxslt-dev libxml2-dev imagemagick libmysqlclient-dev libmagick9-dev git-core mysql-server wkhtmltopdf #Getting the latest ruby (when writing 1.9.2 was the latest release) and compile it sudo wget ftp://ftp.ruby-lang.org//pub/ruby/1.9/ruby-1.9.2-p0.tar.gz tar -xvzf ruby-1.9.2-p0.tar.gz cd ruby-1.9.2-p0/ sudo ./configure --prefix=/usr/local/ruby && sudo make && sudo make install #Adding ruby to your environment sudo nano /etc/environment PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/ruby/bin" source /etc/environment #Linking the binaries sudo ln -s /usr/local/ruby/bin/ruby /usr/bin/ruby sudo ln -s /usr/local/ruby/bin/gem /usr/bin/gem #Installing the neede ruby dependencies sudo gem install tzinfo builder memcache-client rack rack-test erubis mail text-format bundler thor i18n sqlite3-ruby sudo gem install rack-mount -v 0.4.0 sudo gem install rails -v 3.0.0 #Linking the binraries sudo ln -s /usr/local/ruby /bin/rails /usr/bin/rails sudo ln -s /usr/local/ruby /bin/rake /usr/bin/rake #Getting the snorby code git clone git://github.com/Snorby/snorby.git #Update your gemfile (and maybe also gemfile.lock) in the snorby dir. Because you probably run a different version of gem (just update the value to your current version) update gemfile (and gemfile.lock?) #Build snorby (the --deployment was very import for me otherwise bundle stated to build and require heaps of libs that I did not need) bundle install --deployment
After this you’re good. Running Snorby with passenger (run ruby on rails apps via Apache) is very useful and doesn’t require you to start the service every time (this is also recommended by Snorby).
Now you have Snort and Snorby running it is time to take care of some iptables. I will not talk about configuring Snort, first of all, I’m still trying to figure that out, and secondly, it depends on where you are running your IDS. Tuning of the rules for every individual system is important to reduce the amount of false-positives (alerts).
Next just install and configure Artillery. The good thing about artillery is that it is quick and brutal. Someone connects to a port that does not run anything? Artillery considers you a malicious user. I think this is very effective considering the fact that there is absolutely no reason for anyone to connect to that port. (unbanning is easy by the remove_ban.py script). I’m not going to explain how to configure Artillery because this is so dirty easy that any text as an addition to the current comments in the config file of Artillery are useless haha. Just do an svn checkout (https://www.secmaniac.com/download/) and just read the readme and config file comments. You’ll be fine ;)
IPtables are dirty easy. All you need to do is configure what you want to ACCEPT, DROP or REJECT – the difference between DROP and REJECT is that with REJECT you notify the client about the fact that the network traffic has been dropped. I build a short script that basically uses a white listing approach. I DROP all traffic by default, and then I whitelist all the traffic that I allow. Here is my script:
#!/bin/sh # Make sure to run this as root (sudo) # My system IP/set ip address of server SERVER_IP="<your-server-ip>" ARTILLERY="/<path-to>/artillery/restart_server.py" # Showing you some data so you can recover if something went wrong echo "*******START-CURRENT-IPTABLES*******" iptables -L -v -n iptables -L -v -n -t nat echo "*******END-CURRENT-IPTABLES*******" echo "" echo "*******BAKCUP*******" iptables-save echo "*****END-BACKUP*****" # Flushing all rules # We leave the artillery chain alone. Artillery will deal with this on its own when restared at the end of this file echo "Flushing INPUT, OUTPUT, FORWARD and the nat chain." iptables -F INPUT iptables -F OUTPUT iptables -F FORWARD iptables -F LOGGING iptables -t nat -F #Only if applicable iptables -t mangle -F #Only if applicable iptables -t mangle -X # Setting default filter policy. Basically, drop all unless said otherwise echo "Setting default policy (DROP)" iptables -P INPUT DROP iptables -P OUTPUT DROP iptables -P FORWARD DROP #Dropping all ipv6 traffic echo "I see no need for ipv6 support" ip6tables -P INPUT DROP ip6tables -P OUTPUT DROP ip6tables -P FORWARD DROP # Allow unlimited traffic on loopback echo "Allowing loopback (lo)" iptables -A INPUT -i lo -j ACCEPT iptables -A OUTPUT -o lo -j ACCEPT # Allow dns lookups echo "Allow all traffic to and from DNS servers" for dnsserverip in `grep nameserver /etc/resolv.conf | sed 's/.* //'` ; do iptables -A OUTPUT -d $dnsserverip -p udp -o eth0 --dport 53 --sport 1024:65535 -j ACCEPT iptables -A INPUT -s $dnsserverip -p udp -i eth0 --sport 53 --dport 1024:65535 -j ACCEPT done # Allow outgoing ping echo "Allowing outgoing ping packages" iptables -A OUTPUT -p icmp --icmp-type 8 -s $SERVER_IP -d 0/0 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT iptables -A INPUT -p icmp --icmp-type 0 -s 0/0 -d $SERVER_IP -m state --state ESTABLISHED,RELATED -j ACCEPT # Allow all outgoing http traffic echo "Allow all outgoing HTTP and HTTPS traffic" iptables -A OUTPUT -o eth0 -p tcp --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A INPUT -i eth0 -p tcp --sport 443 -m state --state ESTABLISHED -j ACCEPT iptables -A OUTPUT -o eth0 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A INPUT -i eth0 -p tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT # Allow incoming ssh only echo "Allowing ssh traffic on port [port]" iptables -A INPUT -i eth0 -p tcp --dport [port] -m state --state NEW,ESTABLISHED -j ACCEPT #Accepting incomming ssh traffic (new and established connection) iptables -A OUTPUT -o eth0 -p tcp --sport [port] -m state --state ESTABLISHED -j ACCEPT #Accept outgoing (established) connections # Allow NTP (time) client echo "Allowing NTP (time) client" iptables -A OUTPUT -p udp --dport 123 -j ACCEPT iptables -A INPUT -p udp --sport 123 -j ACCEPT #Reject packages we do not want to log #DHCP traffic iptables -A OUTPUT -o eth0 -p udp --dport 67 --sport 68 -j DROP iptables -A INPUT -i eth0 -p udp --dport 67 --sport 68 -j DROP #Broadcast traffic iptables -A OUTPUT -s 0/0 -d 255.255.255.255 -o eth0 -j DROP iptables -A INPUT -s 0/0 -d 255.255.255.255 -i eth0 -j DROP iptables -A OUTPUT -s 0/0 -d xx.xx.xx.255 -o eth0 -j DROP iptables -A INPUT -s 0/0 -d xx.xx.xx.255 -i eth0 -j DROP #Making sure artillery can still work, these are the configured ports in the artillery config file echo "Allowing traffic on the following ports: <your-artillery-honeypot-ports>. Now artillery can do its job" #Repeat the following two lines for every honeypot-port you have configured in artillery iptables -A INPUT -i eth0 -p tcp --dport 21 -j ACCEPT iptables -A OUTPUT -o eth0 -p tcp --sport 21 -j ACCEPT #Only use this if you run the script manually echo "Restarting artillery" python $ARTILLERY # Log droped packages echo "Enabling logging..." iptables -N LOGGING iptables -A INPUT -j LOGGING #To log potential attackers iptables -A OUTPUT -j LOGGING #Logging purposes in case we need to allow a service iptables -A LOGGING -m limit --limit 2/min -j LOG --log-prefix "IPTables Packet Dropped: " --log-level 4 echo "Firewall configuration done. Firewall is running"
If you want to set this script at startup just add it (in ubuntu) to the following directory: /etc/network/if-pre-up.d/ Artillery will initialize all the other rules on startup, so you don’t need to worry about that.
The last part you should do is configure logwatch to send you a daily log file. This should give you all the additional information on what is happening on your server.
Also simply adding a cron job that checks if snort and artillery are running (if not send you an email or something like that) would be a good idea.
So what did we accomplish with this? 1. We monitor all incoming and outgoing traffic for malicious traffic. 2. We have a good reporting system for these alerts. 3. We have a firewall running. 4. We have a couple of ports functioning as a kind of ‘trap’ to catch malicious IP addresses.
Ok, so that was a lot of info in a very short amount of time. Still, I hope this post was useful, any question just leave them in the comment section and I will get back to you as soon as possible.