A computer engineer poking at your cerebral cortex.

Tackling iptables in linux

iptables is one of the most powerful tools on any linux machine. After using linux for years I always though they were too complicated. (UFW) uncomplicated firewall that ubuntu makes is basically just on top of iptables. I use UFW for simple things but many times find myself needing iptables directly.

The first task I needed to tackle is routing issues with being on a VPN. I would connect to this companies VPN and immediately all my internet traffic would be routed to the company. I thought this was very strange since I haven't scene this before on my other VPN connections. I then started with google to try and find a solution. Everywhere people said I could edit the properties of the VPN and select “Ignore automatically obtained routes.”

I was like perfect this is exactly what I was looking for. Checkbox select and done right? Of course not. As soon as I did this all resources on the remote VPN were not working but at least the internet stopped routing over the VPN. So I loaded back up the configuration of the VPN and checked again. There is another checkbox: “Use this connection only for resources on its network.” Perfect this is what I needed. Checked that checkbox and of course it didn't work. None of the network resources through the VPN were accessible. This is when I was like why am I fighting using iptables? I know I can create a simple route to do this and still have all my internet traffic route over my normal internet. Some users have reported issues with ubuntu VPN networking as well and I don't get why this isn't work. After banging my head I just used iptables.

So first step is to find out what virtual interface is running the VPN. A quick ifconfig told me that ppp0 was my interface over the VPN. In my case the remote network is 192.168.255.x. Then I figured out this command to forward my local traffic for its paticular network (192.168.255.x) over ppp0.

sudo route add -net 192.168.255.0 netmask 255.255.255.0 dev ppp0
Just like that all traffic going to the 192.168.255.x network goes over ppp0 while everything else continues to flow over your normal network.

The next problem I ran into using iptables is a little more complicated. I run an lxc container with some pre configured invoice software on my laptop. This way I can easily shutdown the lxc container, zip it up, and send it to dropbox. This way everything is backed up. EVERYONE SHOULD BE TESTING DISASTER RECOVERY! So I decided to do that today. How fast could I get the lxc container on another system and have it loaded on another laptop browser? So if you have ever used lxc containers they create a virtual network usually called lxcbr0. When I start the lxc container on my local laptop I can just hit the private IP address of the lxc container and the site loads. The problem though is now the lxc container is on another box behind another private network: usually 192.168.1.x. Many people would say use a reverse proxy for this (apache, nginx, etc) but I'm the only one using this software. iptables fixes all this. Since I running KVM networks on this same box my primary virtual interface is br0 and not the typical eth0. If you are using eth0 just swap br0 for eth0 in the below command.

The below commands says take br0 192.168.1.10 port 8080 and forward all traffic to the lxc container backend IP address 10.0.3.168 and send it to the apache2 web server on port 80. As you run the below commands and the lxc container is started you can get to the web site from anywhere on the network by using http://192.168.1.10:8080/ in your browser. This way you don't even need a reverse proxy for single web sites like this.

sudo echo 1 > /proc/sys/net/ipv4/ip_forward
sudo iptables -t nat -A PREROUTING -p tcp -i br0 -d 192.168.1.10 --dport 8080 -j DNAT --to 10.0.3.168:80

The next problem I run into again is the damn internet goes out at my place of business or home. When you work in IT you need the internet 24/7 so this can't be an option. This is how I keep the entire network on the internet with iptables. iptables supports turning any wired + wireless devices into a router. Cell phones and portable wifi hotspots are pretty much a thing things days. This is the latest one I have from verzion and has great battery life.

This device providers a wireless network for devices to connect to. This is great for laptops/tablets and other devices with wireless but what about an entire network of computers that need to use the internet. This could even be implimtend and scripted for thousands of machines to redirect internet traffic through your custom iptables router.

First thing we want to do is connect any laptop to the wired + wireless devices. In my example wlan0 is the wireless device and eth0 is the wired device. This is usually the typical connection names when connected to wireless and wired on linux. This script will configure your machine as a router. This will also DELETE ALL existing routes. So if you are already using iptables adjust accordingly.

#!/bin/bash                                                                     
                                                                                
iptables -F                                                                     
iptables -t nat -F                                                              
                                                                                
iptables -P INPUT ACCEPT                                                        
iptables -P OUTPUT ACCEPT                                                       
iptables -P FORWARD DROP                                                        
                                                                                
export LAN=eth0                                                                 
export WAN=wlan0                                                                
                                                                                
 iptables -I INPUT 1 -i ${LAN} -j ACCEPT                                        
 iptables -I INPUT 1 -i lo -j ACCEPT                                            
 iptables -A INPUT -p UDP --dport bootps ! -i ${LAN} -j REJECT                  
 iptables -A INPUT -p UDP --dport domain ! -i ${LAN} -j REJECT                  
                                                                                
#(Optional) Allow access to our ssh server from the WAN                         
# iptables -A INPUT -p TCP --dport ssh -i ${WAN} -j ACCEPT                      
                                                                                
#Drop TCP / UDP packets to privileged ports                                     
# iptables -A INPUT -p TCP ! -i ${LAN} -d 0/0 --dport 0:1023 -j DROP            
# iptables -A INPUT -p UDP ! -i ${LAN} -d 0/0 --dport 0:1023 -j DROP            
                                                                                
#Finally we add the rules for NAT                                               
iptables -I FORWARD -i ${LAN} -d 192.168.0.0/255.255.0.0 -j DROP                
iptables -A FORWARD -i ${LAN} -s 192.168.0.0/255.255.0.0 -j ACCEPT              
iptables -A FORWARD -i ${WAN} -d 192.168.0.0/255.255.0.0 -j ACCEPT              
iptables -t nat -A POSTROUTING -o ${WAN} -j MASQUERADE                          
                                                                                
#Tell the kernel that ip forwarding is OK                                       
echo 1 > /proc/sys/net/ipv4/ip_forward                                          
# for f in /proc/sys/net/ipv4/conf/*/rp_filter ; do echo 1 > $f ; done
Now if you screw up iptables or have routing issues don't worry. This script will get rid off all iptables rules:

#!/bin/bash
iptables -F                                                                     
iptables -t nat -F                                                              
                                                                                
iptables -P INPUT ACCEPT                                                        
iptables -P OUTPUT ACCEPT                                                       
iptables -P FORWARD DROP
Now you just have one last step. Pointing your servers/desktops/wired devices to the new gatway which is eth0 on your laptop. This can be done through the DHCP renewal process or this is how I do it on linux.

sudo route del default gw 192.168.1.x #your old gateway
sudo route add default gw 192.168.1.x #eth0 of your laptop
ping -c 3 google.com #test the network
iptables is super powerful and can be found on all linux machines. Eventually if you need to do advance routing you will need iptables. Don't be afraid and jump in now.