Dec 2, 2009

Networking : network isolation with iptables and brctl


This is one of the first problems I had to solve in my career : the goal is to isolate a part of an existing network for any reason. Let's say your network is configured 192.168.0.0/16 and you cannot isolate with the use of VLANs (either you don't have compliant equipment, either you cannot do it on your architecture, ...).

The solution is to use a Linux bridge and filter packets with iptables.

Have a look at the graphic at the beginning of this post : this is what I'll implement with the following scripts. So let's suppose you want to isolate a group of client machines with their own servers (UNIX and Windows servers).
Considering this, there are three things to do :

  • Give access to the servers and client machines from admin machines
  • Give access to internet, e-mailing, FTP, etc to isolated machines
  • Give access to some services (license, Samba,...) from machines outside the isolated network

In order to do that, prepare a machine with 2 Ethernet cards, install any distro you want on it (i like CentOS but any Debian-like or Suse or any Linux is fine too). Once your this installed, verify that your 2 Ethernet controllers are recognized :

lsmod
lspci
ifconfig -a

The ifconfig -a command should have 2 ethernet interfaces (eth0 and eth1 usually), if not get the good linux module for your network card !

Now, install bridge utilities :
apt-get install bridge-utils #on Debians
yum install bridge-utils #on RHEL / CentOS / Fedora

Let's configure the brigde now. Here is the script that you'll have to put in /etc/init.d and link to /etc/rc5.d/ according to your distro (see /etc/runlevel for current runlevel and your distro doc for running a script at startup).
#!/bin/sh
#
# Start and stop Network bridge
#
case "$1" in
start)
ifconfig eth0 0.0.0.0 promisc
ifconfig eth1 0.0.0.0 promisc

brctl addbr pont
brctl addif pont eth0
brctl addif pont eth1

ifconfig pont 192.168.231.50 netmask 255.255.255.0
route add default gw 192.168.231.254
;;
stop)
brctl delif pont eth0
brctl delif pont eth1
brctl delbr pont
;;
stat)
brctl showstp
;;
*)
echo "Usage : /etc/init.d/brigde start | stop | stat"
;;
esac

We configure the bridge with the 192.168.231.50 IP address, and add to it our 2 ethernet cards.

Now the bridge is up and running let's focus on the packet filtering. As I said, iptables will help up do that, as long as we know source IP, dest IP, proto (tcp, udp,..) and port. Here is the firewalling script, to be put in /etc/init.d :

#!/bin/sh
#
# Start and stop Firewall
#
case "$1" in
start)
PATH="/usr/sbin:$PATH"

#We flush tables
iptables -F
#We erase all user tables
iptables -X

#Default rules : Deny all access
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP

#Let's log what goes through our firewall
iptables -t filter -A INPUT -j LOG --log-level notice
iptables -t filter -A OUTPUT -j LOG --log-level notice
iptables -t filter -A FORWARD -j LOG --log-level notice

#Admin machines, access the firewall, and UNIX and Windows servers
awk '{print $1}' /etc/machines_admin | while read ligne
do
#We accept connnection from admin machines to our firewall
iptables -A INPUT --source $ligne -p tcp --dport ssh -j ACCEPT
iptables -A OUTPUT --destination $ligne -p tcp --sport ssh -j ACCEPT
#Connections from admin machines to UNIX server : ping and SSH
iptables -A FORWARD --source $ligne --destination 192.168.100.102 -p icmp -j ACCEPT
iptables -A FORWARD --source 192.168.100.102 --destination $ligne -p icmp -j ACCEPT
iptables -A FORWARD --source $ligne --destination 192.168.100.102 -p tcp --dport ssh -j ACCEPT
iptables -A FORWARD --source 192.168.100.102 --destination $ligne -p tcp --sport ssh -j ACCEPT
#Connections from admns to Windows server : ping and Dameware remote control
iptables -A FORWARD --source $ligne --destination 192.168.100.100 -p icmp -j ACCEPT
iptables -A FORWARD --source 192.168.100.100 --destination $ligne -p icmp -j ACCEPT
iptables -A FORWARD --source $ligne --destination 192.168.100.100 -p tcp --dport 6129 -j ACCEPT
iptables -A FORWARD --source 192.168.100.100 --destination $ligne -p tcp --sport 6129 -j ACCEPT
#Add here any rule you need for admin machines
done

#Machines behind the firewall should accees mail server, internet, and an accees to a FTP server
awk '{print $1}' /etc/machines_client | while read ligne
do
#Client machines ger accees to mail server (smtp and imap), proxy (tcp 8080), and LDAP on the mail server (tcp/389)
iptables -A FORWARD --source $ligne --destination 192.168.110.97 -p tcp --dport 8080 -j ACCEPT
iptables -A FORWARD --source 192.168.110.97 --destination $ligne -p tcp --sport 8080 -j ACCEPT
iptables -A FORWARD --source $ligne --destination 192.168.110.112 -p tcp --dport 143 -j ACCEPT
iptables -A FORWARD --source 192.168.110.112 --destination $ligne -p tcp --sport 143 -j ACCEPT
iptables -A FORWARD --source $ligne --destination 192.168.110.112 -p tcp --dport 25 -j ACCEPT
iptables -A FORWARD --source 192.168.110.112 --destination $ligne -p tcp --sport 25 -j ACCEPT
iptables -A FORWARD --source $ligne --destination 192.168.110.112 -p tcp --dport 389 -j ACCEPT
iptables -A FORWARD --source 192.168.110.112 --destination $ligne -p tcp --sport 389 -j ACCEPT
#We authorize client machines to acceess a FTP server
iptables -A FORWARD --source $ligne --destination 10.243.0.225 -p tcp --dport 21 -j ACCEPT
iptables -A FORWARD --source 10.243.0.225 --destination $ligne -p tcp --sport 21 -j ACCEPT
iptables -A FORWARD --source $ligne --destination 10.243.0.225 -p tcp --dport 20 -j ACCEPT
iptables -A FORWARD --source 10.243.0.225 --destination $ligne -p tcp --sport 20 -j ACCEPT
#From admin machines to client machines, we let authorize ping and Dameware remote control
awk '{print $1}' /etc/machines_admin | while read admin
do
iptables -A FORWARD --source $admin --destination $ligne -p tcp --dport 6129 -j ACCEPT
iptables -A FORWARD --source $ligne --destination $admin -p tcp --sport 6129 -j ACCEPT
iptables -A FORWARD --source $admin --destination $ligne -p icmp -j ACCEPT
iptables -A FORWARD --source $ligne --destination $admin -p icmp -j ACCEPT
done
#Add here any rules you need for client machines
done

;;
stop)
iptables -F
iptables -X
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
;;
stat)
iptables -L
;;
*)
echo "Usage : /etc/init.d/firewall start | stop | status"
;;
esac

Note that we use 2 files for declaring admin and client machines. These 2 files should be same format as /etc/hosts, meaning for ex for /etc/machines_admin:
192.168.100.45 PC329
192.168.100.222 PC771

Same thing for /etc/machines_client.

Now you have a working, logging firewall/bridge :)

Have fun !

3 comments:

552 said...
This comment has been removed by a blog administrator.
Anonymous said...
This comment has been removed by a blog administrator.
Anonymous said...

耐斯的部落格值得推蔫!............................................................