Saturday, January 25, 2014

Configure iptables to allow a dynamic IP

A client asked me to configure their servers' iptables and make them as secure as possible. The catch was that they wanted these servers accessible from their offices, which didn't have a static IP (of course).

Luckily enough, they did have an account with DynDNS. What I did was the following:

[root@server ~]# iptables -F INPUT  
[root@server ~]# iptables -A INPUT -i lo -j ACCEPT   
[root@server ~]# iptables -A INPUT -s server.IP -j ACCEPT   
[root@server ~]# iptables -A INPUT -s server.IP -j ACCEPT   
....  
more iptables rules follow  
....  
[root@server ~]# iptables -F FORWARD  
[root@server ~]# iptables -A FORWARD -j REJECT --reject-with icmp-host-prohibited   
[root@server ~]# iptables -A OUTPUT -j ACCEPT  
[root@server ~]# iptables-save > /etc/sysconfig/iptables  

So besides allowing everything coming from the loopback interface, which is always the first iptables rule, I entered a duplicate entry.

If you're wondering then let me tell you that there's a method to my madness. Now I'm going to write a script that resolves my client's IP address using their DynDNS hostname and replaces that duplicate line with that address. 

[root@server ~]# yum install bind-utils  
[root@server ~]# vi /root/nslookup.pl
#!/usr/bin/perl  
   
use strict;  
use warnings;  
   
my $result_raw=`dig www.example.com`;
my @result=split(/\n/, $result_raw);
my $IP='0.0.0.0';  
foreach my $line (@result)  
      {  
           if ($line =~ /.*www.example.com.*/)  
                {  
                     $IP = $line;       
                }  
      }   
chomp $IP;  
$IP=~ s/(.*\s+)(\d.*)/$2/;  
if ($IP =~ /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/ and $IP ne '0.0.0.0')  
      {  
           system("/sbin/iptables -D INPUT 3");  
           system("/sbin/iptables -I INPUT 3 -s $IP -j ACCEPT");  
      }  
[root@server ~]# crontab -e
*/5 * * * * /usr/bin/perl /root/nslookup.pl > /dev/null 2>&1

This process is for Red Hat based systems. For Debian-based systems the process is slightly different:

root@server ~# iptables -F INPUT   
root@server ~# iptables -A INPUT -i lo -j ACCEPT    
root@server ~# iptables -A INPUT -s server.IP -j ACCEPT    
root@server ~# iptables -A INPUT -s server.IP -j ACCEPT    
....   
more iptables rules follow   
....   
root@server ~# iptables -F FORWARD   
root@server ~# iptables -A FORWARD -j REJECT --reject-with icmp-host-prohibited    
root@server ~# iptables -A OUTPUT -j ACCEPT   
root@server:~# iptables-save > /etc/iptables.up.rules  
   
root@server:~# vi /etc/init.d/iptables_fw
#!/bin/sh  
### BEGIN INIT INFO  
# Provides:     iptables_init  
# Required-Start:  $local_fs $network  
# Required-Stop:  
# Default-Start:   2 3 4 5       
# Default-Stop:   0 1 6  
# Short-Description: Firewall script  
# Description:    Start iptables-based firewall  
### END INIT INFO  
#  
iptables-restore < /etc/iptables.up.rules  

root@server:~# chmod 755 /etc/init.d/iptables_fw  
root@server:~# service iptables_fw start  
root@server:~# update-rc.d iptables_fw defaults
root@server:~# vi /root/nslookup.pl
#!/usr/bin/perl  
  
use strict;  
use warnings;  
   
my $result_raw=`dig www.example.com`;
my @result=split(/\n/, $result_raw);
my $IP='0.0.0.0';  
foreach my $line (@result)  
      {  
           if ($line =~ /.*www.example.com.*/)  
                {  
                     $IP = $line;       
                }  
      }   
chomp $IP;  
$IP=~ s/(.*\s+)(\d.*)/$2/;  
if ($IP =~ /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/ and $IP ne '0.0.0.0')  
      {  
           system("/sbin/iptables -D INPUT 3");  
           system("/sbin/iptables -I INPUT 3 -s $IP -j ACCEPT");  
      }  
root@server:~# crontab -e
*/5 * * * * /usr/bin/perl /root/nslookup.pl > /dev/null 2>&1

No comments:

Post a Comment