I started a thread about some modules I use for
iptables and
Fidget wanted me to share how I configure my firewall using iptables. So here you go...
First off you need to make sure you have the ipt_state module loaded, if you don't then you'll get some errors and eUKHost will be able to add that to your
VPS Hosting for you. You can test with this safe command below.
Code:
iptables -A OUTPUT -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT
So for an example I'll use my
VPS Hosting, on whic the IP addresses on my
VPS Hosting are
- 91.186.1.130
- 91.186.1.131
- 91.186.1.162
The first has services for SSH, DNS, HTTP, HTTPS and Webmin connections, the second for DNS, HTTP and HTTPS and the last just for HTTP and HTTPS.
PHP Code:
#!/usr/bin/php
<?php
// set ips to allowed ports
$ips = array(
'91.186.1.130' => array( 22, 53, 80, 443, 10000 ), // ssh, dns, http, https, webmin
'91.186.1.131' => array( 53, 80, 443 ), // dns, http, https
'91.186.1.162' => array( 80, 443 ) // http, https
);
$iptables = '/sbin/iptables';
// do not edit below this line
$rules = array(
'-F', // clear
'-t nat -F', // clear
'-X', // clear
'-P INPUT DROP', //default rules
'-P OUTPUT DROP',
'-P FORWARD DROP',
'-A INPUT -i lo -j ACCEPT', // allow localhost
'-A OUTPUT -o lo -j ACCEPT',
'-A OUTPUT -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT', // allow new, related and established connections
'-N PACKET',
'-A PACKET -p tcp -m tcp --tcp-flags SYN,RST,ACK SYN -m limit --limit 1/sec -j ACCEPT',
'-A PACKET -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK RST -m limit --limit 1/sec -j ACCEPT',
'-A PACKET -p icmp -m icmp --icmp-type 8 -m limit --limit 1/sec -j ACCEPT', // limit ping to 1 per second,'
'-N STATE_TRACK',
'-A STATE_TRACK -m state --state RELATED,ESTABLISHED -j ACCEPT', // connection tracking
'-A STATE_TRACK -m state --state INVALID -j DROP',
'-N PORTSCAN',
'-A PORTSCAN -p tcp --tcp-flags ACK,FIN FIN -j DROP', // drop bad flags a portscanning
'-A PORTSCAN -p tcp --tcp-flags ACK,PSH PSH -j DROP',
'-A PORTSCAN -p tcp --tcp-flags ACK,URG URG -j DROP',
'-A PORTSCAN -p tcp --tcp-flags FIN,RST FIN,RST -j DROP',
'-A PORTSCAN -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP',
'-A PORTSCAN -p tcp --tcp-flags SYN,RST SYN,RST -j DROP',
'-A PORTSCAN -p tcp --tcp-flags ALL ALL -j DROP',
'-A PORTSCAN -p tcp --tcp-flags ALL NONE -j DROP',
'-A PORTSCAN -p tcp --tcp-flags ALL FIN,PSH,URG -j DROP',
'-A PORTSCAN -p tcp --tcp-flags ALL SYN,FIN,PSH,URG -j DROP',
'-A PORTSCAN -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP',
'-N COMMON',
'-A COMMON -j STATE_TRACK',
'-A COMMON -j PORTSCAN',
'-A INPUT -j COMMON',
'-A OUTPUT -j COMMON',
'-A FORWARD -j COMMON',
'-A FORWARD -j PACKET'
);
// add targets for each IP address
$keys = array_keys($ips);
for($i = 0; $i < count($keys); $i++) {
echo "Adding targets for {$keys[$i]}: ";
$target = 'IP' . ($i + 1);
$rules[] = '-N ' . $target;
$rules[] = '-A INPUT -d ' . $keys[$i] . ' -j ' . $target;
$rules[] = '-A OUTPUT -d ' . $keys[$i] . ' -j ' . $target;
$rules[] = '-A FORWARD -d ' . $keys[$i] . ' -j ' . $target;
$ips[$target] = $ips[$keys[$i]]; // replace IP with target
unset($ips[$keys[$i]]);
echo "Done\n";
}
foreach($ips as $target => $ports) {
foreach($ports as $port) {
switch($port) {
case 20: // ftp-data
case 21: // ftp-data
case 53: //domain
$rules[] = '-A ' . $target . ' -p tcp --dport ' . $port . ' -j ACCEPT';
$rules[] = '-A ' . $target . ' -p udp --dport ' . $port . ' -j ACCEPT';
break;
default :
$rules[] = '-A ' . $target . ' -p tcp --dport ' . $port . ' -j ACCEPT';
break;
}
}
}
echo "Applying iptables: ";
// execute the rules
foreach($rules as $rule) {
shell_exec("$iptables $rule");
}
echo "Done\n";
To use you need to copy this script to a file, ie. firewall.php and change it's permissions to executable:
Code:
$ chmod +x firewall.php
Now, before you go and run this script, when you are tinkering with iptables it's always a good idea to setup a cron (scheduled task) so that you don't go blocking yourself out. You could argue if my script works as it should then why bother, but this is my disclaimer here
Firstly make a copy of your current iptables rules and dump it to a file
Code:
$ mkdir -p /etc/iptables
$ /sbin/iptables-save > /etc/iptables/firewall_restore
Now add a crontab so that your rules are restored every five minutes
Add the following line:
Code:
*/5 * * * * /sbin/iptables-restore < /etc/iptables/firewall_restore
Now you are safe to run the firewall
If everything is fine and dandy, then you can remove the cron and leave well alone. If you want to go one step further, and you probably do, then you can save your firewall rules and then make it possible to create an init script.
Code:
$ /sbin/iptables-save > /etc/iptables/firewall_rules
Script:
Code:
#!/bin/bash
RETVAL=0
start() {
echo -n "Starting iptables: "
/sbin/iptables-restore < /etc/iptables/firewall_rules
echo "Done."
}
stop() {
echo -n "Stopping iptables: "
/sbin/iptables-restore < /etc/iptables/firewall_reset
echo "Done."
}
case $1 in
start )
start
;;
stop )
stop
;;
restart )
stop
start
;;
status )
/sbin/iptables -L
;;
* )
echo "Usage: $0 start|stop|restart"
RETVAL=1
;;
esac
exit
Save this script as /etc/init.d/firewall and change it's permissions to executable. I don't know how to get this to load on boot in Redhat/CentOS/Fedora, but for Debian or Ubuntu you just need to run:
Code:
$ update-rc.d firewall start 2 3 4 5 .
$ update-rc.d firewall stop 1 6 .
Enjoy
